misc/libtremor/tremor/mapping0.c
branchhedgeroid
changeset 6045 9a7cc0f29430
parent 6043 9bd2d6b1ba52
child 7697 767d3c4153a1
equal deleted inserted replaced
6043:9bd2d6b1ba52 6045:9a7cc0f29430
       
     1 /********************************************************************
       
     2  *                                                                  *
       
     3  * THIS FILE IS PART OF THE OggVorbis 'TREMOR' CODEC SOURCE CODE.   *
       
     4  *                                                                  *
       
     5  * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS     *
       
     6  * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE *
       
     7  * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING.       *
       
     8  *                                                                  *
       
     9  * THE OggVorbis 'TREMOR' SOURCE CODE IS (C) COPYRIGHT 1994-2002    *
       
    10  * BY THE Xiph.Org FOUNDATION http://www.xiph.org/                  *
       
    11  *                                                                  *
       
    12  ********************************************************************
       
    13 
       
    14  function: channel mapping 0 implementation
       
    15 
       
    16  ********************************************************************/
       
    17 
       
    18 #include <stdlib.h>
       
    19 #include <stdio.h>
       
    20 #include <string.h>
       
    21 #include <math.h>
       
    22 #include "ogg.h"
       
    23 #include "ivorbiscodec.h"
       
    24 #include "mdct.h"
       
    25 #include "codec_internal.h"
       
    26 #include "codebook.h"
       
    27 #include "window.h"
       
    28 #include "registry.h"
       
    29 #include "misc.h"
       
    30 
       
    31 /* simplistic, wasteful way of doing this (unique lookup for each
       
    32    mode/submapping); there should be a central repository for
       
    33    identical lookups.  That will require minor work, so I'm putting it
       
    34    off as low priority.
       
    35 
       
    36    Why a lookup for each backend in a given mode?  Because the
       
    37    blocksize is set by the mode, and low backend lookups may require
       
    38    parameters from other areas of the mode/mapping */
       
    39 
       
    40 typedef struct {
       
    41   vorbis_info_mode *mode;
       
    42   vorbis_info_mapping0 *map;
       
    43 
       
    44   vorbis_look_floor **floor_look;
       
    45 
       
    46   vorbis_look_residue **residue_look;
       
    47 
       
    48   vorbis_func_floor **floor_func;
       
    49   vorbis_func_residue **residue_func;
       
    50 
       
    51   int ch;
       
    52   long lastframe; /* if a different mode is called, we need to 
       
    53 		     invalidate decay */
       
    54 } vorbis_look_mapping0;
       
    55 
       
    56 static void mapping0_free_info(vorbis_info_mapping *i){
       
    57   vorbis_info_mapping0 *info=(vorbis_info_mapping0 *)i;
       
    58   if(info){
       
    59     memset(info,0,sizeof(*info));
       
    60     _ogg_free(info);
       
    61   }
       
    62 }
       
    63 
       
    64 static void mapping0_free_look(vorbis_look_mapping *look){
       
    65   int i;
       
    66   vorbis_look_mapping0 *l=(vorbis_look_mapping0 *)look;
       
    67   if(l){
       
    68 
       
    69     for(i=0;i<l->map->submaps;i++){
       
    70       l->floor_func[i]->free_look(l->floor_look[i]);
       
    71       l->residue_func[i]->free_look(l->residue_look[i]);
       
    72     }
       
    73 
       
    74     _ogg_free(l->floor_func);
       
    75     _ogg_free(l->residue_func);
       
    76     _ogg_free(l->floor_look);
       
    77     _ogg_free(l->residue_look);
       
    78     memset(l,0,sizeof(*l));
       
    79     _ogg_free(l);
       
    80   }
       
    81 }
       
    82 
       
    83 static vorbis_look_mapping *mapping0_look(vorbis_dsp_state *vd,vorbis_info_mode *vm,
       
    84 			  vorbis_info_mapping *m){
       
    85   int i;
       
    86   vorbis_info          *vi=vd->vi;
       
    87   codec_setup_info     *ci=(codec_setup_info *)vi->codec_setup;
       
    88   vorbis_look_mapping0 *look=(vorbis_look_mapping0 *)_ogg_calloc(1,sizeof(*look));
       
    89   vorbis_info_mapping0 *info=look->map=(vorbis_info_mapping0 *)m;
       
    90   look->mode=vm;
       
    91   
       
    92   look->floor_look=(vorbis_look_floor **)_ogg_calloc(info->submaps,sizeof(*look->floor_look));
       
    93 
       
    94   look->residue_look=(vorbis_look_residue **)_ogg_calloc(info->submaps,sizeof(*look->residue_look));
       
    95 
       
    96   look->floor_func=(vorbis_func_floor **)_ogg_calloc(info->submaps,sizeof(*look->floor_func));
       
    97   look->residue_func=(vorbis_func_residue **)_ogg_calloc(info->submaps,sizeof(*look->residue_func));
       
    98   
       
    99   for(i=0;i<info->submaps;i++){
       
   100     int floornum=info->floorsubmap[i];
       
   101     int resnum=info->residuesubmap[i];
       
   102 
       
   103     look->floor_func[i]=_floor_P[ci->floor_type[floornum]];
       
   104     look->floor_look[i]=look->floor_func[i]->
       
   105       look(vd,vm,ci->floor_param[floornum]);
       
   106     look->residue_func[i]=_residue_P[ci->residue_type[resnum]];
       
   107     look->residue_look[i]=look->residue_func[i]->
       
   108       look(vd,vm,ci->residue_param[resnum]);
       
   109     
       
   110   }
       
   111 
       
   112   look->ch=vi->channels;
       
   113 
       
   114   return(look);
       
   115 }
       
   116 
       
   117 static int ilog(unsigned int v){
       
   118   int ret=0;
       
   119   if(v)--v;
       
   120   while(v){
       
   121     ret++;
       
   122     v>>=1;
       
   123   }
       
   124   return(ret);
       
   125 }
       
   126 
       
   127 /* also responsible for range checking */
       
   128 static vorbis_info_mapping *mapping0_unpack(vorbis_info *vi,oggpack_buffer *opb){
       
   129   int i;
       
   130   vorbis_info_mapping0 *info=(vorbis_info_mapping0 *)_ogg_calloc(1,sizeof(*info));
       
   131   codec_setup_info     *ci=(codec_setup_info *)vi->codec_setup;
       
   132   memset(info,0,sizeof(*info));
       
   133 
       
   134   if(oggpack_read(opb,1))
       
   135     info->submaps=oggpack_read(opb,4)+1;
       
   136   else
       
   137     info->submaps=1;
       
   138 
       
   139   if(oggpack_read(opb,1)){
       
   140     info->coupling_steps=oggpack_read(opb,8)+1;
       
   141 
       
   142     for(i=0;i<info->coupling_steps;i++){
       
   143       int testM=info->coupling_mag[i]=oggpack_read(opb,ilog(vi->channels));
       
   144       int testA=info->coupling_ang[i]=oggpack_read(opb,ilog(vi->channels));
       
   145 
       
   146       if(testM<0 || 
       
   147 	 testA<0 || 
       
   148 	 testM==testA || 
       
   149 	 testM>=vi->channels ||
       
   150 	 testA>=vi->channels) goto err_out;
       
   151     }
       
   152 
       
   153   }
       
   154 
       
   155   if(oggpack_read(opb,2)>0)goto err_out; /* 2,3:reserved */
       
   156     
       
   157   if(info->submaps>1){
       
   158     for(i=0;i<vi->channels;i++){
       
   159       info->chmuxlist[i]=oggpack_read(opb,4);
       
   160       if(info->chmuxlist[i]>=info->submaps)goto err_out;
       
   161     }
       
   162   }
       
   163   for(i=0;i<info->submaps;i++){
       
   164     int temp=oggpack_read(opb,8);
       
   165     if(temp>=ci->times)goto err_out;
       
   166     info->floorsubmap[i]=oggpack_read(opb,8);
       
   167     if(info->floorsubmap[i]>=ci->floors)goto err_out;
       
   168     info->residuesubmap[i]=oggpack_read(opb,8);
       
   169     if(info->residuesubmap[i]>=ci->residues)goto err_out;
       
   170   }
       
   171 
       
   172   return info;
       
   173 
       
   174  err_out:
       
   175   mapping0_free_info(info);
       
   176   return(NULL);
       
   177 }
       
   178 
       
   179 static int seq=0;
       
   180 static int mapping0_inverse(vorbis_block *vb,vorbis_look_mapping *l){
       
   181   vorbis_dsp_state     *vd=vb->vd;
       
   182   vorbis_info          *vi=vd->vi;
       
   183   codec_setup_info     *ci=(codec_setup_info *)vi->codec_setup;
       
   184   private_state        *b=(private_state *)vd->backend_state;
       
   185   vorbis_look_mapping0 *look=(vorbis_look_mapping0 *)l;
       
   186   vorbis_info_mapping0 *info=look->map;
       
   187 
       
   188   int                   i,j;
       
   189   long                  n=vb->pcmend=ci->blocksizes[vb->W];
       
   190 
       
   191   ogg_int32_t **pcmbundle=(ogg_int32_t **)alloca(sizeof(*pcmbundle)*vi->channels);
       
   192   int    *zerobundle=(int *)alloca(sizeof(*zerobundle)*vi->channels);
       
   193   
       
   194   int   *nonzero  =(int *)alloca(sizeof(*nonzero)*vi->channels);
       
   195   void **floormemo=(void **)alloca(sizeof(*floormemo)*vi->channels);
       
   196   
       
   197   /* time domain information decode (note that applying the
       
   198      information would have to happen later; we'll probably add a
       
   199      function entry to the harness for that later */
       
   200   /* NOT IMPLEMENTED */
       
   201 
       
   202   /* recover the spectral envelope; store it in the PCM vector for now */
       
   203   for(i=0;i<vi->channels;i++){
       
   204     int submap=info->chmuxlist[i];
       
   205     floormemo[i]=look->floor_func[submap]->
       
   206       inverse1(vb,look->floor_look[submap]);
       
   207     if(floormemo[i])
       
   208       nonzero[i]=1;
       
   209     else
       
   210       nonzero[i]=0;      
       
   211     memset(vb->pcm[i],0,sizeof(*vb->pcm[i])*n/2);
       
   212   }
       
   213 
       
   214   /* channel coupling can 'dirty' the nonzero listing */
       
   215   for(i=0;i<info->coupling_steps;i++){
       
   216     if(nonzero[info->coupling_mag[i]] ||
       
   217        nonzero[info->coupling_ang[i]]){
       
   218       nonzero[info->coupling_mag[i]]=1; 
       
   219       nonzero[info->coupling_ang[i]]=1; 
       
   220     }
       
   221   }
       
   222 
       
   223   /* recover the residue into our working vectors */
       
   224   for(i=0;i<info->submaps;i++){
       
   225     int ch_in_bundle=0;
       
   226     for(j=0;j<vi->channels;j++){
       
   227       if(info->chmuxlist[j]==i){
       
   228 	if(nonzero[j])
       
   229 	  zerobundle[ch_in_bundle]=1;
       
   230 	else
       
   231 	  zerobundle[ch_in_bundle]=0;
       
   232 	pcmbundle[ch_in_bundle++]=vb->pcm[j];
       
   233       }
       
   234     }
       
   235     
       
   236     look->residue_func[i]->inverse(vb,look->residue_look[i],
       
   237 				   pcmbundle,zerobundle,ch_in_bundle);
       
   238   }
       
   239 
       
   240   //for(j=0;j<vi->channels;j++)
       
   241   //_analysis_output("coupled",seq+j,vb->pcm[j],-8,n/2,0,0);
       
   242 
       
   243 
       
   244   /* channel coupling */
       
   245   for(i=info->coupling_steps-1;i>=0;i--){
       
   246     ogg_int32_t *pcmM=vb->pcm[info->coupling_mag[i]];
       
   247     ogg_int32_t *pcmA=vb->pcm[info->coupling_ang[i]];
       
   248     
       
   249     for(j=0;j<n/2;j++){
       
   250       ogg_int32_t mag=pcmM[j];
       
   251       ogg_int32_t ang=pcmA[j];
       
   252       
       
   253       if(mag>0)
       
   254 	if(ang>0){
       
   255 	  pcmM[j]=mag;
       
   256 	  pcmA[j]=mag-ang;
       
   257 	}else{
       
   258 	  pcmA[j]=mag;
       
   259 	  pcmM[j]=mag+ang;
       
   260 	}
       
   261       else
       
   262 	if(ang>0){
       
   263 	  pcmM[j]=mag;
       
   264 	  pcmA[j]=mag+ang;
       
   265 	}else{
       
   266 	  pcmA[j]=mag;
       
   267 	  pcmM[j]=mag-ang;
       
   268 	}
       
   269     }
       
   270   }
       
   271 
       
   272   //for(j=0;j<vi->channels;j++)
       
   273   //_analysis_output("residue",seq+j,vb->pcm[j],-8,n/2,0,0);
       
   274 
       
   275   /* compute and apply spectral envelope */
       
   276   for(i=0;i<vi->channels;i++){
       
   277     ogg_int32_t *pcm=vb->pcm[i];
       
   278     int submap=info->chmuxlist[i];
       
   279     look->floor_func[submap]->
       
   280       inverse2(vb,look->floor_look[submap],floormemo[i],pcm);
       
   281   }
       
   282 
       
   283   //for(j=0;j<vi->channels;j++)
       
   284   //_analysis_output("mdct",seq+j,vb->pcm[j],-24,n/2,0,1);
       
   285 
       
   286   /* transform the PCM data; takes PCM vector, vb; modifies PCM vector */
       
   287   /* only MDCT right now.... */
       
   288   for(i=0;i<vi->channels;i++){
       
   289     ogg_int32_t *pcm=vb->pcm[i];
       
   290     mdct_backward(n,pcm,pcm);
       
   291   }
       
   292 
       
   293   //for(j=0;j<vi->channels;j++)
       
   294   //_analysis_output("imdct",seq+j,vb->pcm[j],-24,n,0,0);
       
   295 
       
   296   /* window the data */
       
   297   for(i=0;i<vi->channels;i++){
       
   298     ogg_int32_t *pcm=vb->pcm[i];
       
   299     if(nonzero[i])
       
   300       _vorbis_apply_window(pcm,b->window,ci->blocksizes,vb->lW,vb->W,vb->nW);
       
   301     else
       
   302       for(j=0;j<n;j++)
       
   303 	pcm[j]=0;
       
   304     
       
   305   }
       
   306 
       
   307   //for(j=0;j<vi->channels;j++)
       
   308   //_analysis_output("window",seq+j,vb->pcm[j],-24,n,0,0);
       
   309 
       
   310   seq+=vi->channels;
       
   311   /* all done! */
       
   312   return(0);
       
   313 }
       
   314 
       
   315 /* export hooks */
       
   316 vorbis_func_mapping mapping0_exportbundle={
       
   317   &mapping0_unpack,
       
   318   &mapping0_look,
       
   319   &mapping0_free_info,
       
   320   &mapping0_free_look,
       
   321   &mapping0_inverse
       
   322 };