Finished patch to deal with channel coupling and some-zero, some-nonzero channels
[platform/upstream/libvorbis.git] / lib / mapping0.c
1 /********************************************************************
2  *                                                                  *
3  * THIS FILE IS PART OF THE OggVorbis SOFTWARE CODEC SOURCE CODE.   *
4  * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS     *
5  * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE *
6  * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING.       *
7  *                                                                  *
8  * THE OggVorbis SOURCE CODE IS (C) COPYRIGHT 1994-2001             *
9  * by the XIPHOPHORUS Company http://www.xiph.org/                  *
10  *                                                                  *
11  ********************************************************************
12
13  function: channel mapping 0 implementation
14  last mod: $Id: mapping0.c,v 1.32 2001/06/15 23:59:47 xiphmont Exp $
15
16  ********************************************************************/
17
18 #include <stdlib.h>
19 #include <stdio.h>
20 #include <string.h>
21 #include <math.h>
22 #include <ogg/ogg.h>
23 #include "vorbis/codec.h"
24 #include "codec_internal.h"
25 #include "codebook.h"
26 #include "bitbuffer.h"
27 #include "registry.h"
28 #include "psy.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   drft_lookup fft_look;
42   vorbis_info_mode *mode;
43   vorbis_info_mapping0 *map;
44
45   vorbis_look_time **time_look;
46   vorbis_look_floor **floor_look;
47
48   vorbis_look_residue **residue_look;
49   vorbis_look_psy *psy_look;
50
51   vorbis_func_time **time_func;
52   vorbis_func_floor **floor_func;
53   vorbis_func_residue **residue_func;
54
55   int ch;
56   long lastframe; /* if a different mode is called, we need to 
57                      invalidate decay */
58 } vorbis_look_mapping0;
59
60 static vorbis_info_mapping *mapping0_copy_info(vorbis_info_mapping *vm){
61   vorbis_info_mapping0 *info=(vorbis_info_mapping0 *)vm;
62   vorbis_info_mapping0 *ret=_ogg_malloc(sizeof(vorbis_info_mapping0));
63   memcpy(ret,info,sizeof(vorbis_info_mapping0));
64   return(ret);
65 }
66
67 static void mapping0_free_info(vorbis_info_mapping *i){
68   if(i){
69     memset(i,0,sizeof(vorbis_info_mapping0));
70     _ogg_free(i);
71   }
72 }
73
74 static void mapping0_free_look(vorbis_look_mapping *look){
75   int i;
76   vorbis_look_mapping0 *l=(vorbis_look_mapping0 *)look;
77   if(l){
78     drft_clear(&l->fft_look);
79
80     for(i=0;i<l->map->submaps;i++){
81       l->time_func[i]->free_look(l->time_look[i]);
82       l->floor_func[i]->free_look(l->floor_look[i]);
83       l->residue_func[i]->free_look(l->residue_look[i]);
84       if(l->psy_look)_vp_psy_clear(l->psy_look+i);
85     }
86
87     _ogg_free(l->time_func);
88     _ogg_free(l->floor_func);
89     _ogg_free(l->residue_func);
90     _ogg_free(l->time_look);
91     _ogg_free(l->floor_look);
92     _ogg_free(l->residue_look);
93     if(l->psy_look)_ogg_free(l->psy_look);
94     memset(l,0,sizeof(vorbis_look_mapping0));
95     _ogg_free(l);
96   }
97 }
98
99 static vorbis_look_mapping *mapping0_look(vorbis_dsp_state *vd,vorbis_info_mode *vm,
100                           vorbis_info_mapping *m){
101   int i;
102   vorbis_info          *vi=vd->vi;
103   codec_setup_info     *ci=vi->codec_setup;
104   vorbis_look_mapping0 *look=_ogg_calloc(1,sizeof(vorbis_look_mapping0));
105   vorbis_info_mapping0 *info=look->map=(vorbis_info_mapping0 *)m;
106   look->mode=vm;
107   
108   look->time_look=_ogg_calloc(info->submaps,sizeof(vorbis_look_time *));
109   look->floor_look=_ogg_calloc(info->submaps,sizeof(vorbis_look_floor *));
110
111   look->residue_look=_ogg_calloc(info->submaps,sizeof(vorbis_look_residue *));
112   if(ci->psys)look->psy_look=_ogg_calloc(info->submaps,sizeof(vorbis_look_psy));
113
114   look->time_func=_ogg_calloc(info->submaps,sizeof(vorbis_func_time *));
115   look->floor_func=_ogg_calloc(info->submaps,sizeof(vorbis_func_floor *));
116   look->residue_func=_ogg_calloc(info->submaps,sizeof(vorbis_func_residue *));
117   
118   for(i=0;i<info->submaps;i++){
119     int timenum=info->timesubmap[i];
120     int floornum=info->floorsubmap[i];
121     int resnum=info->residuesubmap[i];
122
123     look->time_func[i]=_time_P[ci->time_type[timenum]];
124     look->time_look[i]=look->time_func[i]->
125       look(vd,vm,ci->time_param[timenum]);
126     look->floor_func[i]=_floor_P[ci->floor_type[floornum]];
127     look->floor_look[i]=look->floor_func[i]->
128       look(vd,vm,ci->floor_param[floornum]);
129     look->residue_func[i]=_residue_P[ci->residue_type[resnum]];
130     look->residue_look[i]=look->residue_func[i]->
131       look(vd,vm,ci->residue_param[resnum]);
132     
133     if(ci->psys && vd->analysisp){
134       int psynum=info->psysubmap[i];
135       _vp_psy_init(look->psy_look+i,ci->psy_param[psynum],
136                    ci->blocksizes[vm->blockflag]/2,vi->rate);
137     }
138   }
139
140   look->ch=vi->channels;
141
142   if(vd->analysisp)drft_init(&look->fft_look,ci->blocksizes[vm->blockflag]);
143   return(look);
144 }
145
146 static int ilog2(unsigned int v){
147   int ret=0;
148   while(v>1){
149     ret++;
150     v>>=1;
151   }
152   return(ret);
153 }
154
155 static void mapping0_pack(vorbis_info *vi,vorbis_info_mapping *vm,oggpack_buffer *opb){
156   int i;
157   vorbis_info_mapping0 *info=(vorbis_info_mapping0 *)vm;
158
159   /* another 'we meant to do it this way' hack...  up to beta 4, we
160      packed 4 binary zeros here to signify one submapping in use.  We
161      now redefine that to mean four bitflags that indicate use of
162      deeper features; bit0:submappings, bit1:coupling,
163      bit2,3:reserved. This is backward compatable with all actual uses
164      of the beta code. */
165
166   if(info->submaps>1){
167     oggpack_write(opb,1,1);
168     oggpack_write(opb,info->submaps-1,4);
169   }else
170     oggpack_write(opb,0,1);
171
172   if(info->coupling_steps>0){
173     oggpack_write(opb,1,1);
174     oggpack_write(opb,info->coupling_steps-1,8);
175     
176     for(i=0;i<info->coupling_steps;i++){
177       oggpack_write(opb,info->coupling_mag[i],ilog2(vi->channels));
178       oggpack_write(opb,info->coupling_ang[i],ilog2(vi->channels));
179     }
180   }else
181     oggpack_write(opb,0,1);
182   
183   oggpack_write(opb,0,2); /* 2,3:reserved */
184
185   /* we don't write the channel submappings if we only have one... */
186   if(info->submaps>1){
187     for(i=0;i<vi->channels;i++)
188       oggpack_write(opb,info->chmuxlist[i],4);
189   }
190   for(i=0;i<info->submaps;i++){
191     oggpack_write(opb,info->timesubmap[i],8);
192     oggpack_write(opb,info->floorsubmap[i],8);
193     oggpack_write(opb,info->residuesubmap[i],8);
194   }
195 }
196
197 /* also responsible for range checking */
198 static vorbis_info_mapping *mapping0_unpack(vorbis_info *vi,oggpack_buffer *opb){
199   int i;
200   vorbis_info_mapping0 *info=_ogg_calloc(1,sizeof(vorbis_info_mapping0));
201   codec_setup_info     *ci=vi->codec_setup;
202   memset(info,0,sizeof(vorbis_info_mapping0));
203
204   if(oggpack_read(opb,1))
205     info->submaps=oggpack_read(opb,4)+1;
206   else
207     info->submaps=1;
208
209   if(oggpack_read(opb,1)){
210     info->coupling_steps=oggpack_read(opb,8)+1;
211
212     for(i=0;i<info->coupling_steps;i++){
213       int testM=info->coupling_mag[i]=oggpack_read(opb,ilog2(vi->channels));
214       int testA=info->coupling_ang[i]=oggpack_read(opb,ilog2(vi->channels));
215
216       if(testM<0 || 
217          testA<0 || 
218          testM==testA || 
219          testM>=vi->channels ||
220          testA>=vi->channels) goto err_out;
221     }
222
223   }
224
225   if(oggpack_read(opb,2)>0)goto err_out; /* 2,3:reserved */
226     
227   if(info->submaps>1){
228     for(i=0;i<vi->channels;i++){
229       info->chmuxlist[i]=oggpack_read(opb,4);
230       if(info->chmuxlist[i]>=info->submaps)goto err_out;
231     }
232   }
233   for(i=0;i<info->submaps;i++){
234     info->timesubmap[i]=oggpack_read(opb,8);
235     if(info->timesubmap[i]>=ci->times)goto err_out;
236     info->floorsubmap[i]=oggpack_read(opb,8);
237     if(info->floorsubmap[i]>=ci->floors)goto err_out;
238     info->residuesubmap[i]=oggpack_read(opb,8);
239     if(info->residuesubmap[i]>=ci->residues)goto err_out;
240   }
241
242   return info;
243
244  err_out:
245   mapping0_free_info(info);
246   return(NULL);
247 }
248
249 #include "os.h"
250 #include "lpc.h"
251 #include "lsp.h"
252 #include "envelope.h"
253 #include "mdct.h"
254 #include "psy.h"
255 #define VORBIS_IEEE_FLOAT32
256 #include "scales.h"
257
258 /* no time mapping implementation for now */
259 static long seq=0;
260 static int mapping0_forward(vorbis_block *vb,vorbis_look_mapping *l){
261   vorbis_dsp_state      *vd=vb->vd;
262   vorbis_info           *vi=vd->vi;
263   backend_lookup_state  *b=vb->vd->backend_state;
264   vorbis_look_mapping0  *look=(vorbis_look_mapping0 *)l;
265   vorbis_info_mapping0  *info=look->map;
266   vorbis_info_mode      *mode=look->mode;
267   vorbis_block_internal *vbi=(vorbis_block_internal *)vb->internal;
268   int                    n=vb->pcmend;
269   int i,j;
270   float *window=b->window[vb->W][vb->lW][vb->nW][mode->windowtype];
271
272   float **pcmbundle=alloca(sizeof(float *)*vi->channels);
273   int    *zerobundle=alloca(sizeof(int)*vi->channels);
274
275   int    *nonzero=alloca(sizeof(int)*vi->channels);
276
277   float *work=_vorbis_block_alloc(vb,n*sizeof(float));
278   float newmax=vbi->ampmax;
279
280   for(i=0;i<vi->channels;i++){
281     float scale=4.f/n;
282     int submap=info->chmuxlist[i];
283     float ret;
284
285     /* the following makes things clearer to *me* anyway */
286     float *pcm     =vb->pcm[i]; 
287     float *mdct    =pcm;
288     float *logmdct =pcm+n/2;
289     float *res     =pcm;
290     float *codedflr=pcm+n/2;
291     float *fft     =work;
292     float *logfft  =work;
293     float *logmax  =work;
294     float *logmask =work+n/2;
295
296     /* window the PCM data */
297     for(j=0;j<n;j++)
298       fft[j]=pcm[j]*=window[j];
299     
300     /* transform the PCM data */
301     /* only MDCT right now.... */
302     mdct_forward(b->transform[vb->W][0],pcm,pcm);
303     for(j=0;j<n/2;j++)
304       logmdct[j]=todB(mdct+j);
305     
306     /* FFT yields more accurate tonal estimation (not phase sensitive) */
307     drft_forward(&look->fft_look,fft);
308     fft[0]*=scale;
309     fft[0]=todB(fft);
310     for(j=1;j<n-1;j+=2){
311       float temp=scale*FAST_HYPOT(fft[j],fft[j+1]);
312       logfft[(j+1)>>1]=todB(&temp);
313     }
314
315     _analysis_output("fft",seq,logfft,n/2,0,0);
316     _analysis_output("mdct",seq,logmdct,n/2,0,0);
317
318     /* perform psychoacoustics; do masking */
319     ret=_vp_compute_mask(look->psy_look+submap,
320                          logfft, /* -> logmax */
321                          logmdct,
322                          logmask,
323                          vbi->ampmax);
324     if(ret>newmax)newmax=ret;
325
326     _analysis_output("mask",seq,logmask,n/2,0,0);
327     
328     /* perform floor encoding */
329     nonzero[i]=look->floor_func[submap]->
330       forward(vb,look->floor_look[submap],
331               mdct,
332               logmdct,
333               logmask,
334               logmax,
335               res,
336               codedflr);
337
338     for(j=0;j<n/2;j++)
339       if(fabs(vb->pcm[i][j]>1000))
340         fprintf(stderr,"%ld ",seq);
341     
342     _analysis_output("res",seq-vi->channels+j,vb->pcm[i],n,0,0);
343     _analysis_output("codedflr",seq++,codedflr,n/2,0,1);
344       
345   }
346
347   vbi->ampmax=newmax;
348
349   /* channel coupling */
350   for(i=0;i<info->coupling_steps;i++){
351     if(nonzero[info->coupling_mag[i]] ||
352        nonzero[info->coupling_ang[i]]){
353       
354       float *pcmM=vb->pcm[info->coupling_mag[i]];
355       float *pcmA=vb->pcm[info->coupling_ang[i]];
356       
357     /*     +- 
358             B
359             |       A-B
360      -4 -3 -2 -1  0                    
361             |
362       3     |     1
363             |
364   -+  2-----+-----2----A ++  
365             |
366       1     |     3
367             |
368       0 -1 -2 -3 -4
369   B-A       |
370            --
371
372     */
373
374       nonzero[info->coupling_mag[i]]=1; 
375       nonzero[info->coupling_ang[i]]=1; 
376
377       for(j=n/2-1;j>=0;j--){
378         float A=rint(pcmM[j]);
379         float B=rint(pcmA[j]);
380         float mag;
381         float ang;
382         
383         if(fabs(A)>fabs(B)){
384           mag=A;
385           if(A>0)
386             ang=A-B;
387           else
388             ang=B-A;
389         }else{
390           mag=B;
391         if(B>0)
392           ang=A-B;
393         else
394           ang=B-A;
395         }
396         
397         /*if(fabs(mag)<3.5f)
398           ang=rint(ang/(mag*2.f))*mag*2.f;*/
399         
400         if(fabs(mag)<1.5)
401         ang=0;
402       
403         if(j>(n*3/16))
404           ang=0;
405         
406         if(ang>=fabs(mag*2))ang=-fabs(mag*2);
407         
408         pcmM[j]=mag;
409         pcmA[j]=ang;
410       }
411     }
412   }
413   
414   /* perform residue encoding with residue mapping; this is
415      multiplexed.  All the channels belonging to one submap are
416      encoded (values interleaved), then the next submap, etc */
417   
418   for(i=0;i<info->submaps;i++){
419     int ch_in_bundle=0;
420     for(j=0;j<vi->channels;j++){
421       if(info->chmuxlist[j]==i){
422         if(nonzero[j])
423           zerobundle[ch_in_bundle]=1;
424         else
425           zerobundle[ch_in_bundle]=0;
426         pcmbundle[ch_in_bundle++]=vb->pcm[j];
427       }
428     }
429     
430     look->residue_func[i]->forward(vb,look->residue_look[i],
431                                    pcmbundle,zerobundle,ch_in_bundle);
432   }
433   
434   look->lastframe=vb->sequence;
435   return(0);
436 }
437
438 static int mapping0_inverse(vorbis_block *vb,vorbis_look_mapping *l){
439   vorbis_dsp_state     *vd=vb->vd;
440   vorbis_info          *vi=vd->vi;
441   codec_setup_info     *ci=vi->codec_setup;
442   backend_lookup_state *b=vd->backend_state;
443   vorbis_look_mapping0 *look=(vorbis_look_mapping0 *)l;
444   vorbis_info_mapping0 *info=look->map;
445   vorbis_info_mode     *mode=look->mode;
446   int                   i,j;
447   long                  n=vb->pcmend=ci->blocksizes[vb->W];
448
449   float *window=b->window[vb->W][vb->lW][vb->nW][mode->windowtype];
450   float **pcmbundle=alloca(sizeof(float *)*vi->channels);
451   int    *zerobundle=alloca(sizeof(int)*vi->channels);
452
453   int   *nonzero  =alloca(sizeof(int)*vi->channels);
454   void **floormemo=alloca(sizeof(void *)*vi->channels);
455   
456   /* time domain information decode (note that applying the
457      information would have to happen later; we'll probably add a
458      function entry to the harness for that later */
459   /* NOT IMPLEMENTED */
460
461   /* recover the spectral envelope; store it in the PCM vector for now */
462   for(i=0;i<vi->channels;i++){
463     int submap=info->chmuxlist[i];
464     floormemo[i]=look->floor_func[submap]->
465       inverse1(vb,look->floor_look[submap]);
466     if(floormemo[i])
467       nonzero[i]=1;
468     else
469       nonzero[i]=0;      
470     memset(vb->pcm[i],0,sizeof(float)*n/2);
471   }
472
473   /* channel coupling can 'dirty' the nonzero listing */
474   for(i=0;i<info->coupling_steps;i++){
475     if(nonzero[info->coupling_mag[i]] ||
476        nonzero[info->coupling_ang[i]]){
477       nonzero[info->coupling_mag[i]]=1; 
478       nonzero[info->coupling_ang[i]]=1; 
479     }
480   }
481
482   /* recover the residue into our working vectors */
483   for(i=0;i<info->submaps;i++){
484     int ch_in_bundle=0;
485     for(j=0;j<vi->channels;j++){
486       if(info->chmuxlist[j]==i){
487         if(nonzero[j])
488           zerobundle[ch_in_bundle]=1;
489         else
490           zerobundle[ch_in_bundle]=0;
491         pcmbundle[ch_in_bundle++]=vb->pcm[j];
492       }
493     }
494     
495     look->residue_func[i]->inverse(vb,look->residue_look[i],
496                                    pcmbundle,zerobundle,ch_in_bundle);
497   }
498
499   /* channel coupling */
500   for(i=info->coupling_steps-1;i>=0;i--){
501     float *pcmM=vb->pcm[info->coupling_mag[i]];
502     float *pcmA=vb->pcm[info->coupling_ang[i]];
503
504     for(j=0;j<n/2;j++){
505       float mag=pcmM[j];
506       float ang=pcmA[j];
507
508       if(mag>0)
509         if(ang>0){
510           pcmM[j]=mag;
511           pcmA[j]=mag-ang;
512         }else{
513           pcmA[j]=mag;
514           pcmM[j]=mag+ang;
515         }
516       else
517         if(ang>0){
518           pcmM[j]=mag;
519           pcmA[j]=mag+ang;
520         }else{
521           pcmA[j]=mag;
522           pcmM[j]=mag-ang;
523         }
524     }
525   }
526
527   /* compute and apply spectral envelope */
528   for(i=0;i<vi->channels;i++){
529     float *pcm=vb->pcm[i];
530     int submap=info->chmuxlist[i];
531     look->floor_func[submap]->
532       inverse2(vb,look->floor_look[submap],floormemo[i],pcm);
533   }
534
535   /* transform the PCM data; takes PCM vector, vb; modifies PCM vector */
536   /* only MDCT right now.... */
537   for(i=0;i<vi->channels;i++){
538     float *pcm=vb->pcm[i];
539     _analysis_output("out",seq+i,pcm,n/2,0,1);
540     mdct_backward(b->transform[vb->W][0],pcm,pcm);
541   }
542
543   /* window the data */
544   for(i=0;i<vi->channels;i++){
545     float *pcm=vb->pcm[i];
546     if(nonzero[i])
547       for(j=0;j<n;j++)
548         pcm[j]*=window[j];
549     else
550       for(j=0;j<n;j++)
551         pcm[j]=0.f;
552     _analysis_output("final",seq++,pcm,n,0,0);
553   }
554             
555   /* now apply the decoded post-window time information */
556   /* NOT IMPLEMENTED */
557
558   /* all done! */
559   return(0);
560 }
561
562 /* export hooks */
563 vorbis_func_mapping mapping0_exportbundle={
564   &mapping0_pack,&mapping0_unpack,&mapping0_look,&mapping0_copy_info,
565   &mapping0_free_info,&mapping0_free_look,&mapping0_forward,&mapping0_inverse
566 };