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