misc/libtremor/tremor/mapping0.c
changeset 7697 767d3c4153a1
parent 6045 9a7cc0f29430
child 7849 a12155461b34
equal deleted inserted replaced
7696:78a00bc68913 7697:767d3c4153a1
     4  *                                                                  *
     4  *                                                                  *
     5  * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS     *
     5  * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS     *
     6  * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE *
     6  * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE *
     7  * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING.       *
     7  * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING.       *
     8  *                                                                  *
     8  *                                                                  *
     9  * THE OggVorbis 'TREMOR' SOURCE CODE IS (C) COPYRIGHT 1994-2002    *
     9  * THE OggVorbis 'TREMOR' SOURCE CODE IS (C) COPYRIGHT 1994-2003    *
    10  * BY THE Xiph.Org FOUNDATION http://www.xiph.org/                  *
    10  * BY THE Xiph.Org FOUNDATION http://www.xiph.org/                  *
    11  *                                                                  *
    11  *                                                                  *
    12  ********************************************************************
    12  ********************************************************************
    13 
    13 
    14  function: channel mapping 0 implementation
    14  function: channel mapping 0 implementation
    22 #include "ogg.h"
    22 #include "ogg.h"
    23 #include "ivorbiscodec.h"
    23 #include "ivorbiscodec.h"
    24 #include "mdct.h"
    24 #include "mdct.h"
    25 #include "codec_internal.h"
    25 #include "codec_internal.h"
    26 #include "codebook.h"
    26 #include "codebook.h"
    27 #include "window.h"
       
    28 #include "registry.h"
       
    29 #include "misc.h"
    27 #include "misc.h"
    30 
    28 
    31 /* simplistic, wasteful way of doing this (unique lookup for each
    29 void mapping_clear_info(vorbis_info_mapping *info){
    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){
    30   if(info){
       
    31     if(info->chmuxlist)_ogg_free(info->chmuxlist);
       
    32     if(info->submaplist)_ogg_free(info->submaplist);
       
    33     if(info->coupling)_ogg_free(info->coupling);
    59     memset(info,0,sizeof(*info));
    34     memset(info,0,sizeof(*info));
    60     _ogg_free(info);
    35   }
    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 }
    36 }
   116 
    37 
   117 static int ilog(unsigned int v){
    38 static int ilog(unsigned int v){
   118   int ret=0;
    39   int ret=0;
   119   if(v)--v;
    40   if(v)--v;
   123   }
    44   }
   124   return(ret);
    45   return(ret);
   125 }
    46 }
   126 
    47 
   127 /* also responsible for range checking */
    48 /* also responsible for range checking */
   128 static vorbis_info_mapping *mapping0_unpack(vorbis_info *vi,oggpack_buffer *opb){
    49 int mapping_info_unpack(vorbis_info_mapping *info,vorbis_info *vi,
       
    50 			oggpack_buffer *opb){
   129   int i;
    51   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;
    52   codec_setup_info     *ci=(codec_setup_info *)vi->codec_setup;
   132   memset(info,0,sizeof(*info));
    53   memset(info,0,sizeof(*info));
   133 
    54 
   134   if(oggpack_read(opb,1))
    55   if(oggpack_read(opb,1))
   135     info->submaps=oggpack_read(opb,4)+1;
    56     info->submaps=oggpack_read(opb,4)+1;
   136   else
    57   else
   137     info->submaps=1;
    58     info->submaps=1;
   138 
    59 
   139   if(oggpack_read(opb,1)){
    60   if(oggpack_read(opb,1)){
   140     info->coupling_steps=oggpack_read(opb,8)+1;
    61     info->coupling_steps=oggpack_read(opb,8)+1;
   141 
    62     info->coupling=
       
    63       _ogg_malloc(info->coupling_steps*sizeof(*info->coupling));
       
    64     
   142     for(i=0;i<info->coupling_steps;i++){
    65     for(i=0;i<info->coupling_steps;i++){
   143       int testM=info->coupling_mag[i]=oggpack_read(opb,ilog(vi->channels));
    66       int testM=info->coupling[i].mag=oggpack_read(opb,ilog(vi->channels));
   144       int testA=info->coupling_ang[i]=oggpack_read(opb,ilog(vi->channels));
    67       int testA=info->coupling[i].ang=oggpack_read(opb,ilog(vi->channels));
   145 
    68 
   146       if(testM<0 || 
    69       if(testM<0 || 
   147 	 testA<0 || 
    70 	 testA<0 || 
   148 	 testM==testA || 
    71 	 testM==testA || 
   149 	 testM>=vi->channels ||
    72 	 testM>=vi->channels ||
   153   }
    76   }
   154 
    77 
   155   if(oggpack_read(opb,2)>0)goto err_out; /* 2,3:reserved */
    78   if(oggpack_read(opb,2)>0)goto err_out; /* 2,3:reserved */
   156     
    79     
   157   if(info->submaps>1){
    80   if(info->submaps>1){
       
    81     info->chmuxlist=_ogg_malloc(sizeof(*info->chmuxlist)*vi->channels);
   158     for(i=0;i<vi->channels;i++){
    82     for(i=0;i<vi->channels;i++){
   159       info->chmuxlist[i]=oggpack_read(opb,4);
    83       info->chmuxlist[i]=oggpack_read(opb,4);
   160       if(info->chmuxlist[i]>=info->submaps)goto err_out;
    84       if(info->chmuxlist[i]>=info->submaps)goto err_out;
   161     }
    85     }
   162   }
    86   }
       
    87 
       
    88   info->submaplist=_ogg_malloc(sizeof(*info->submaplist)*info->submaps);
   163   for(i=0;i<info->submaps;i++){
    89   for(i=0;i<info->submaps;i++){
   164     int temp=oggpack_read(opb,8);
    90     int temp=oggpack_read(opb,8);
   165     if(temp>=ci->times)goto err_out;
    91     info->submaplist[i].floor=oggpack_read(opb,8);
   166     info->floorsubmap[i]=oggpack_read(opb,8);
    92     if(info->submaplist[i].floor>=ci->floors)goto err_out;
   167     if(info->floorsubmap[i]>=ci->floors)goto err_out;
    93     info->submaplist[i].residue=oggpack_read(opb,8);
   168     info->residuesubmap[i]=oggpack_read(opb,8);
    94     if(info->submaplist[i].residue>=ci->residues)goto err_out;
   169     if(info->residuesubmap[i]>=ci->residues)goto err_out;
    95   }
   170   }
    96 
   171 
    97   return 0;
   172   return info;
       
   173 
    98 
   174  err_out:
    99  err_out:
   175   mapping0_free_info(info);
   100   mapping_clear_info(info);
   176   return(NULL);
   101   return -1;
   177 }
   102 }
   178 
   103 
   179 static int seq=0;
   104 int mapping_inverse(vorbis_dsp_state *vd,vorbis_info_mapping *info){
   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;
   105   vorbis_info          *vi=vd->vi;
   183   codec_setup_info     *ci=(codec_setup_info *)vi->codec_setup;
   106   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 
   107 
   188   int                   i,j;
   108   int                   i,j;
   189   long                  n=vb->pcmend=ci->blocksizes[vb->W];
   109   long                  n=ci->blocksizes[vd->W];
   190 
   110 
   191   ogg_int32_t **pcmbundle=(ogg_int32_t **)alloca(sizeof(*pcmbundle)*vi->channels);
   111   ogg_int32_t **pcmbundle=
   192   int    *zerobundle=(int *)alloca(sizeof(*zerobundle)*vi->channels);
   112     (ogg_int32_t **)alloca(sizeof(*pcmbundle)*vi->channels);
       
   113   int          *zerobundle=
       
   114     (int *)alloca(sizeof(*zerobundle)*vi->channels);
       
   115   int          *nonzero=
       
   116     (int *)alloca(sizeof(*nonzero)*vi->channels);
       
   117   ogg_int32_t **floormemo=
       
   118     (void **)alloca(sizeof(*floormemo)*vi->channels);
   193   
   119   
   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 */
   120   /* recover the spectral envelope; store it in the PCM vector for now */
   203   for(i=0;i<vi->channels;i++){
   121   for(i=0;i<vi->channels;i++){
   204     int submap=info->chmuxlist[i];
   122     int submap=0;
   205     floormemo[i]=look->floor_func[submap]->
   123     int floorno;
   206       inverse1(vb,look->floor_look[submap]);
   124     
       
   125     if(info->submaps>1)
       
   126       submap=info->chmuxlist[i];
       
   127     floorno=info->submaplist[submap].floor;
       
   128     
       
   129     if(ci->floor_type[floorno]){
       
   130       /* floor 1 */
       
   131       floormemo[i]=alloca(sizeof(*floormemo[i])*
       
   132 			  floor1_memosize(ci->floor_param[floorno]));
       
   133       floormemo[i]=floor1_inverse1(vd,ci->floor_param[floorno],floormemo[i]);
       
   134     }else{
       
   135       /* floor 0 */
       
   136       floormemo[i]=alloca(sizeof(*floormemo[i])*
       
   137 			  floor0_memosize(ci->floor_param[floorno]));
       
   138       floormemo[i]=floor0_inverse1(vd,ci->floor_param[floorno],floormemo[i]);
       
   139     }
       
   140     
   207     if(floormemo[i])
   141     if(floormemo[i])
   208       nonzero[i]=1;
   142       nonzero[i]=1;
   209     else
   143     else
   210       nonzero[i]=0;      
   144       nonzero[i]=0;      
   211     memset(vb->pcm[i],0,sizeof(*vb->pcm[i])*n/2);
   145     memset(vd->work[i],0,sizeof(*vd->work[i])*n/2);
   212   }
   146   }
   213 
   147 
   214   /* channel coupling can 'dirty' the nonzero listing */
   148   /* channel coupling can 'dirty' the nonzero listing */
   215   for(i=0;i<info->coupling_steps;i++){
   149   for(i=0;i<info->coupling_steps;i++){
   216     if(nonzero[info->coupling_mag[i]] ||
   150     if(nonzero[info->coupling[i].mag] ||
   217        nonzero[info->coupling_ang[i]]){
   151        nonzero[info->coupling[i].ang]){
   218       nonzero[info->coupling_mag[i]]=1; 
   152       nonzero[info->coupling[i].mag]=1; 
   219       nonzero[info->coupling_ang[i]]=1; 
   153       nonzero[info->coupling[i].ang]=1; 
   220     }
   154     }
   221   }
   155   }
   222 
   156 
   223   /* recover the residue into our working vectors */
   157   /* recover the residue into our working vectors */
   224   for(i=0;i<info->submaps;i++){
   158   for(i=0;i<info->submaps;i++){
   225     int ch_in_bundle=0;
   159     int ch_in_bundle=0;
   226     for(j=0;j<vi->channels;j++){
   160     for(j=0;j<vi->channels;j++){
   227       if(info->chmuxlist[j]==i){
   161       if(!info->chmuxlist || info->chmuxlist[j]==i){
   228 	if(nonzero[j])
   162 	if(nonzero[j])
   229 	  zerobundle[ch_in_bundle]=1;
   163 	  zerobundle[ch_in_bundle]=1;
   230 	else
   164 	else
   231 	  zerobundle[ch_in_bundle]=0;
   165 	  zerobundle[ch_in_bundle]=0;
   232 	pcmbundle[ch_in_bundle++]=vb->pcm[j];
   166 	pcmbundle[ch_in_bundle++]=vd->work[j];
   233       }
   167       }
   234     }
   168     }
   235     
   169     
   236     look->residue_func[i]->inverse(vb,look->residue_look[i],
   170     res_inverse(vd,ci->residue_param+info->submaplist[i].residue,
   237 				   pcmbundle,zerobundle,ch_in_bundle);
   171 		pcmbundle,zerobundle,ch_in_bundle);
   238   }
   172   }
   239 
   173 
   240   //for(j=0;j<vi->channels;j++)
   174   //for(j=0;j<vi->channels;j++)
   241   //_analysis_output("coupled",seq+j,vb->pcm[j],-8,n/2,0,0);
   175   //_analysis_output("coupled",seq+j,vb->pcm[j],-8,n/2,0,0);
   242 
       
   243 
   176 
   244   /* channel coupling */
   177   /* channel coupling */
   245   for(i=info->coupling_steps-1;i>=0;i--){
   178   for(i=info->coupling_steps-1;i>=0;i--){
   246     ogg_int32_t *pcmM=vb->pcm[info->coupling_mag[i]];
   179     ogg_int32_t *pcmM=vd->work[info->coupling[i].mag];
   247     ogg_int32_t *pcmA=vb->pcm[info->coupling_ang[i]];
   180     ogg_int32_t *pcmA=vd->work[info->coupling[i].ang];
   248     
   181     
   249     for(j=0;j<n/2;j++){
   182     for(j=0;j<n/2;j++){
   250       ogg_int32_t mag=pcmM[j];
   183       ogg_int32_t mag=pcmM[j];
   251       ogg_int32_t ang=pcmA[j];
   184       ogg_int32_t ang=pcmA[j];
   252       
   185       
   272   //for(j=0;j<vi->channels;j++)
   205   //for(j=0;j<vi->channels;j++)
   273   //_analysis_output("residue",seq+j,vb->pcm[j],-8,n/2,0,0);
   206   //_analysis_output("residue",seq+j,vb->pcm[j],-8,n/2,0,0);
   274 
   207 
   275   /* compute and apply spectral envelope */
   208   /* compute and apply spectral envelope */
   276   for(i=0;i<vi->channels;i++){
   209   for(i=0;i<vi->channels;i++){
   277     ogg_int32_t *pcm=vb->pcm[i];
   210     ogg_int32_t *pcm=vd->work[i];
   278     int submap=info->chmuxlist[i];
   211     int submap=0;
   279     look->floor_func[submap]->
   212     int floorno;
   280       inverse2(vb,look->floor_look[submap],floormemo[i],pcm);
   213 
       
   214     if(info->submaps>1)
       
   215       submap=info->chmuxlist[i];
       
   216     floorno=info->submaplist[submap].floor;
       
   217 
       
   218     if(ci->floor_type[floorno]){
       
   219       /* floor 1 */
       
   220       floor1_inverse2(vd,ci->floor_param[floorno],floormemo[i],pcm);
       
   221     }else{
       
   222       /* floor 0 */
       
   223       floor0_inverse2(vd,ci->floor_param[floorno],floormemo[i],pcm);
       
   224     }
   281   }
   225   }
   282 
   226 
   283   //for(j=0;j<vi->channels;j++)
   227   //for(j=0;j<vi->channels;j++)
   284   //_analysis_output("mdct",seq+j,vb->pcm[j],-24,n/2,0,1);
   228   //_analysis_output("mdct",seq+j,vb->pcm[j],-24,n/2,0,1);
   285 
   229 
   286   /* transform the PCM data; takes PCM vector, vb; modifies PCM vector */
   230   /* transform the PCM data; takes PCM vector, vb; modifies PCM vector */
   287   /* only MDCT right now.... */
   231   /* only MDCT right now.... */
   288   for(i=0;i<vi->channels;i++){
   232   for(i=0;i<vi->channels;i++)
   289     ogg_int32_t *pcm=vb->pcm[i];
   233     mdct_backward(n,vd->work[i]);
   290     mdct_backward(n,pcm,pcm);
       
   291   }
       
   292 
   234 
   293   //for(j=0;j<vi->channels;j++)
   235   //for(j=0;j<vi->channels;j++)
   294   //_analysis_output("imdct",seq+j,vb->pcm[j],-24,n,0,0);
   236   //_analysis_output("imdct",seq+j,vb->pcm[j],-24,n,0,0);
   295 
   237 
   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! */
   238   /* all done! */
   312   return(0);
   239   return(0);
   313 }
   240 }
   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 };