]> icculus.org git repositories - icculus/iodoom3.git/blob - neo/sound/OggVorbis/vorbissrc/mapping0.c
Various Mac OS X tweaks to get this to build. Probably breaking things.
[icculus/iodoom3.git] / neo / sound / OggVorbis / vorbissrc / 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-2002             *
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.60 2003/09/01 23:05:49 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 "window.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 static void mapping0_free_info(vorbis_info_mapping *i){
41   vorbis_info_mapping0 *info=(vorbis_info_mapping0 *)i;
42   if(info){
43     memset(info,0,sizeof(*info));
44     _ogg_free(info);
45   }
46 }
47
48 static int ilog(unsigned int v){
49   int ret=0;
50   if(v)--v;
51   while(v){
52     ret++;
53     v>>=1;
54   }
55   return(ret);
56 }
57
58 static void mapping0_pack(vorbis_info *vi,vorbis_info_mapping *vm,
59                           oggpack_buffer *opb){
60   int i;
61   vorbis_info_mapping0 *info=(vorbis_info_mapping0 *)vm;
62
63   /* another 'we meant to do it this way' hack...  up to beta 4, we
64      packed 4 binary zeros here to signify one submapping in use.  We
65      now redefine that to mean four bitflags that indicate use of
66      deeper features; bit0:submappings, bit1:coupling,
67      bit2,3:reserved. This is backward compatable with all actual uses
68      of the beta code. */
69
70   if(info->submaps>1){
71     oggpack_write(opb,1,1);
72     oggpack_write(opb,info->submaps-1,4);
73   }else
74     oggpack_write(opb,0,1);
75
76   if(info->coupling_steps>0){
77     oggpack_write(opb,1,1);
78     oggpack_write(opb,info->coupling_steps-1,8);
79     
80     for(i=0;i<info->coupling_steps;i++){
81       oggpack_write(opb,info->coupling_mag[i],ilog(vi->channels));
82       oggpack_write(opb,info->coupling_ang[i],ilog(vi->channels));
83     }
84   }else
85     oggpack_write(opb,0,1);
86   
87   oggpack_write(opb,0,2); /* 2,3:reserved */
88
89   /* we don't write the channel submappings if we only have one... */
90   if(info->submaps>1){
91     for(i=0;i<vi->channels;i++)
92       oggpack_write(opb,info->chmuxlist[i],4);
93   }
94   for(i=0;i<info->submaps;i++){
95     oggpack_write(opb,0,8); /* time submap unused */
96     oggpack_write(opb,info->floorsubmap[i],8);
97     oggpack_write(opb,info->residuesubmap[i],8);
98   }
99 }
100
101 /* also responsible for range checking */
102 static vorbis_info_mapping *mapping0_unpack(vorbis_info *vi,oggpack_buffer *opb){
103   int i;
104   vorbis_info_mapping0 *info=_ogg_calloc(1,sizeof(*info));
105   codec_setup_info     *ci=vi->codec_setup;
106   memset(info,0,sizeof(*info));
107
108   if(oggpack_read(opb,1))
109     info->submaps=oggpack_read(opb,4)+1;
110   else
111     info->submaps=1;
112
113   if(oggpack_read(opb,1)){
114     info->coupling_steps=oggpack_read(opb,8)+1;
115
116     for(i=0;i<info->coupling_steps;i++){
117       int testM=info->coupling_mag[i]=oggpack_read(opb,ilog(vi->channels));
118       int testA=info->coupling_ang[i]=oggpack_read(opb,ilog(vi->channels));
119
120       if(testM<0 || 
121          testA<0 || 
122          testM==testA || 
123          testM>=vi->channels ||
124          testA>=vi->channels) goto err_out;
125     }
126
127   }
128
129   if(oggpack_read(opb,2)>0)goto err_out; /* 2,3:reserved */
130     
131   if(info->submaps>1){
132     for(i=0;i<vi->channels;i++){
133       info->chmuxlist[i]=oggpack_read(opb,4);
134       if(info->chmuxlist[i]>=info->submaps)goto err_out;
135     }
136   }
137   for(i=0;i<info->submaps;i++){
138     oggpack_read(opb,8); /* time submap unused */
139     info->floorsubmap[i]=oggpack_read(opb,8);
140     if(info->floorsubmap[i]>=ci->floors)goto err_out;
141     info->residuesubmap[i]=oggpack_read(opb,8);
142     if(info->residuesubmap[i]>=ci->residues)goto err_out;
143   }
144
145   return info;
146
147  err_out:
148   mapping0_free_info(info);
149   return(NULL);
150 }
151
152 #include "os.h"
153 #include "lpc.h"
154 #include "lsp.h"
155 #include "envelope.h"
156 #include "mdct.h"
157 #include "psy.h"
158 #include "scales.h"
159
160 #if 0
161 static long seq=0;
162 static ogg_int64_t total=0;
163 static float FLOOR1_fromdB_LOOKUP[256]={
164   1.0649863e-07F, 1.1341951e-07F, 1.2079015e-07F, 1.2863978e-07F, 
165   1.3699951e-07F, 1.4590251e-07F, 1.5538408e-07F, 1.6548181e-07F, 
166   1.7623575e-07F, 1.8768855e-07F, 1.9988561e-07F, 2.128753e-07F, 
167   2.2670913e-07F, 2.4144197e-07F, 2.5713223e-07F, 2.7384213e-07F, 
168   2.9163793e-07F, 3.1059021e-07F, 3.3077411e-07F, 3.5226968e-07F, 
169   3.7516214e-07F, 3.9954229e-07F, 4.2550680e-07F, 4.5315863e-07F, 
170   4.8260743e-07F, 5.1396998e-07F, 5.4737065e-07F, 5.8294187e-07F, 
171   6.2082472e-07F, 6.6116941e-07F, 7.0413592e-07F, 7.4989464e-07F, 
172   7.9862701e-07F, 8.5052630e-07F, 9.0579828e-07F, 9.6466216e-07F, 
173   1.0273513e-06F, 1.0941144e-06F, 1.1652161e-06F, 1.2409384e-06F, 
174   1.3215816e-06F, 1.4074654e-06F, 1.4989305e-06F, 1.5963394e-06F, 
175   1.7000785e-06F, 1.8105592e-06F, 1.9282195e-06F, 2.0535261e-06F, 
176   2.1869758e-06F, 2.3290978e-06F, 2.4804557e-06F, 2.6416497e-06F, 
177   2.8133190e-06F, 2.9961443e-06F, 3.1908506e-06F, 3.3982101e-06F, 
178   3.6190449e-06F, 3.8542308e-06F, 4.1047004e-06F, 4.3714470e-06F, 
179   4.6555282e-06F, 4.9580707e-06F, 5.2802740e-06F, 5.6234160e-06F, 
180   5.9888572e-06F, 6.3780469e-06F, 6.7925283e-06F, 7.2339451e-06F, 
181   7.7040476e-06F, 8.2047000e-06F, 8.7378876e-06F, 9.3057248e-06F, 
182   9.9104632e-06F, 1.0554501e-05F, 1.1240392e-05F, 1.1970856e-05F, 
183   1.2748789e-05F, 1.3577278e-05F, 1.4459606e-05F, 1.5399272e-05F, 
184   1.6400004e-05F, 1.7465768e-05F, 1.8600792e-05F, 1.9809576e-05F, 
185   2.1096914e-05F, 2.2467911e-05F, 2.3928002e-05F, 2.5482978e-05F, 
186   2.7139006e-05F, 2.8902651e-05F, 3.0780908e-05F, 3.2781225e-05F, 
187   3.4911534e-05F, 3.7180282e-05F, 3.9596466e-05F, 4.2169667e-05F, 
188   4.4910090e-05F, 4.7828601e-05F, 5.0936773e-05F, 5.4246931e-05F, 
189   5.7772202e-05F, 6.1526565e-05F, 6.5524908e-05F, 6.9783085e-05F, 
190   7.4317983e-05F, 7.9147585e-05F, 8.4291040e-05F, 8.9768747e-05F, 
191   9.5602426e-05F, 0.00010181521F, 0.00010843174F, 0.00011547824F, 
192   0.00012298267F, 0.00013097477F, 0.00013948625F, 0.00014855085F, 
193   0.00015820453F, 0.00016848555F, 0.00017943469F, 0.00019109536F, 
194   0.00020351382F, 0.00021673929F, 0.00023082423F, 0.00024582449F, 
195   0.00026179955F, 0.00027881276F, 0.00029693158F, 0.00031622787F, 
196   0.00033677814F, 0.00035866388F, 0.00038197188F, 0.00040679456F, 
197   0.00043323036F, 0.00046138411F, 0.00049136745F, 0.00052329927F, 
198   0.00055730621F, 0.00059352311F, 0.00063209358F, 0.00067317058F, 
199   0.00071691700F, 0.00076350630F, 0.00081312324F, 0.00086596457F, 
200   0.00092223983F, 0.00098217216F, 0.0010459992F, 0.0011139742F, 
201   0.0011863665F, 0.0012634633F, 0.0013455702F, 0.0014330129F, 
202   0.0015261382F, 0.0016253153F, 0.0017309374F, 0.0018434235F, 
203   0.0019632195F, 0.0020908006F, 0.0022266726F, 0.0023713743F, 
204   0.0025254795F, 0.0026895994F, 0.0028643847F, 0.0030505286F, 
205   0.0032487691F, 0.0034598925F, 0.0036847358F, 0.0039241906F, 
206   0.0041792066F, 0.0044507950F, 0.0047400328F, 0.0050480668F, 
207   0.0053761186F, 0.0057254891F, 0.0060975636F, 0.0064938176F, 
208   0.0069158225F, 0.0073652516F, 0.0078438871F, 0.0083536271F, 
209   0.0088964928F, 0.009474637F, 0.010090352F, 0.010746080F, 
210   0.011444421F, 0.012188144F, 0.012980198F, 0.013823725F, 
211   0.014722068F, 0.015678791F, 0.016697687F, 0.017782797F, 
212   0.018938423F, 0.020169149F, 0.021479854F, 0.022875735F, 
213   0.024362330F, 0.025945531F, 0.027631618F, 0.029427276F, 
214   0.031339626F, 0.033376252F, 0.035545228F, 0.037855157F, 
215   0.040315199F, 0.042935108F, 0.045725273F, 0.048696758F, 
216   0.051861348F, 0.055231591F, 0.058820850F, 0.062643361F, 
217   0.066714279F, 0.071049749F, 0.075666962F, 0.080584227F, 
218   0.085821044F, 0.091398179F, 0.097337747F, 0.10366330F, 
219   0.11039993F, 0.11757434F, 0.12521498F, 0.13335215F, 
220   0.14201813F, 0.15124727F, 0.16107617F, 0.17154380F, 
221   0.18269168F, 0.19456402F, 0.20720788F, 0.22067342F, 
222   0.23501402F, 0.25028656F, 0.26655159F, 0.28387361F, 
223   0.30232132F, 0.32196786F, 0.34289114F, 0.36517414F, 
224   0.38890521F, 0.41417847F, 0.44109412F, 0.46975890F, 
225   0.50028648F, 0.53279791F, 0.56742212F, 0.60429640F, 
226   0.64356699F, 0.68538959F, 0.72993007F, 0.77736504F, 
227   0.82788260F, 0.88168307F, 0.9389798F, 1.F, 
228 };
229
230 #endif 
231
232 extern int *floor1_fit(vorbis_block *vb,vorbis_look_floor *look,
233                        const float *logmdct,   /* in */
234                        const float *logmask);
235 extern int *floor1_interpolate_fit(vorbis_block *vb,vorbis_look_floor *look,
236                                    int *A,int *B,
237                                    int del);
238 extern int floor1_encode(vorbis_block *vb,vorbis_look_floor *look,
239                          int *post,int *ilogmask);
240
241
242 static int mapping0_forward(vorbis_block *vb){
243   vorbis_dsp_state      *vd=vb->vd;
244   vorbis_info           *vi=vd->vi;
245   codec_setup_info      *ci=vi->codec_setup;
246   private_state         *b=vb->vd->backend_state;
247   vorbis_block_internal *vbi=(vorbis_block_internal *)vb->internal;
248   int                    n=vb->pcmend;
249   int i,j,k;
250
251   int    *nonzero    = alloca(sizeof(*nonzero)*vi->channels);
252   float  **gmdct     = _vorbis_block_alloc(vb,vi->channels*sizeof(*gmdct));
253   int    **ilogmaskch= _vorbis_block_alloc(vb,vi->channels*sizeof(*ilogmaskch));
254   int ***floor_posts = _vorbis_block_alloc(vb,vi->channels*sizeof(*floor_posts));
255   
256   float global_ampmax=vbi->ampmax;
257   float *local_ampmax=alloca(sizeof(*local_ampmax)*vi->channels);
258   int blocktype=vbi->blocktype;
259
260   int modenumber=vb->W;
261   vorbis_info_mapping0 *info=ci->map_param[modenumber];
262   vorbis_look_psy *psy_look=
263     b->psy+blocktype+(vb->W?2:0);
264
265   vb->mode=modenumber;
266
267   for(i=0;i<vi->channels;i++){
268     float scale=4.f/n;
269     float scale_dB;
270
271     float *pcm     =vb->pcm[i]; 
272     float *logfft  =pcm;
273
274     gmdct[i]=_vorbis_block_alloc(vb,n/2*sizeof(**gmdct));
275
276     scale_dB=todB(&scale);
277
278 #if 0
279     if(vi->channels==2)
280       if(i==0)
281         _analysis_output("pcmL",seq,pcm,n,0,0,total-n/2);
282       else
283         _analysis_output("pcmR",seq,pcm,n,0,0,total-n/2);
284 #endif
285   
286     /* window the PCM data */
287     _vorbis_apply_window(pcm,b->window,ci->blocksizes,vb->lW,vb->W,vb->nW);
288
289 #if 0
290     if(vi->channels==2)
291       if(i==0)
292         _analysis_output("windowedL",seq,pcm,n,0,0,total-n/2);
293       else
294         _analysis_output("windowedR",seq,pcm,n,0,0,total-n/2);
295 #endif
296
297     /* transform the PCM data */
298     /* only MDCT right now.... */
299     mdct_forward(b->transform[vb->W][0],pcm,gmdct[i]);
300     
301     /* FFT yields more accurate tonal estimation (not phase sensitive) */
302     drft_forward(&b->fft_look[vb->W],pcm);
303     logfft[0]=scale_dB+todB(pcm);
304     local_ampmax[i]=logfft[0];
305     for(j=1;j<n-1;j+=2){
306       float temp=pcm[j]*pcm[j]+pcm[j+1]*pcm[j+1];
307       temp=logfft[(j+1)>>1]=scale_dB+.5f*todB(&temp);
308       if(temp>local_ampmax[i])local_ampmax[i]=temp;
309     }
310
311     if(local_ampmax[i]>0.f)local_ampmax[i]=0.f;
312     if(local_ampmax[i]>global_ampmax)global_ampmax=local_ampmax[i];
313
314 #if 0
315     if(vi->channels==2)
316       if(i==0)
317         _analysis_output("fftL",seq,logfft,n/2,1,0,0);
318       else
319         _analysis_output("fftR",seq,logfft,n/2,1,0,0);
320 #endif
321
322   }
323   
324   {
325     float   *noise        = _vorbis_block_alloc(vb,n/2*sizeof(*noise));
326     float   *tone         = _vorbis_block_alloc(vb,n/2*sizeof(*tone));
327     
328     for(i=0;i<vi->channels;i++){
329       /* the encoder setup assumes that all the modes used by any
330          specific bitrate tweaking use the same floor */
331       
332       int submap=info->chmuxlist[i];
333       
334       /* the following makes things clearer to *me* anyway */
335       float *mdct    =gmdct[i];
336       float *logfft  =vb->pcm[i];
337       
338       float *logmdct =logfft+n/2;
339       float *logmask =logfft;
340
341       vb->mode=modenumber;
342
343       floor_posts[i]=_vorbis_block_alloc(vb,PACKETBLOBS*sizeof(**floor_posts));
344       memset(floor_posts[i],0,sizeof(**floor_posts)*PACKETBLOBS);
345       
346       for(j=0;j<n/2;j++)
347         logmdct[j]=todB(mdct+j);
348
349 #if 0
350       if(vi->channels==2){
351         if(i==0)
352           _analysis_output("mdctL",seq,logmdct,n/2,1,0,0);
353         else
354           _analysis_output("mdctR",seq,logmdct,n/2,1,0,0);
355       }else{
356         _analysis_output("mdct",seq,logmdct,n/2,1,0,0);
357       }
358 #endif 
359       
360       /* first step; noise masking.  Not only does 'noise masking'
361          give us curves from which we can decide how much resolution
362          to give noise parts of the spectrum, it also implicitly hands
363          us a tonality estimate (the larger the value in the
364          'noise_depth' vector, the more tonal that area is) */
365
366       _vp_noisemask(psy_look,
367                     logmdct,
368                     noise); /* noise does not have by-frequency offset
369                                bias applied yet */
370 #if 0
371       if(vi->channels==2){
372         if(i==0)
373           _analysis_output("noiseL",seq,noise,n/2,1,0,0);
374         else
375           _analysis_output("noiseR",seq,noise,n/2,1,0,0);
376       }
377 #endif
378
379       /* second step: 'all the other crap'; all the stuff that isn't
380          computed/fit for bitrate management goes in the second psy
381          vector.  This includes tone masking, peak limiting and ATH */
382
383       _vp_tonemask(psy_look,
384                    logfft,
385                    tone,
386                    global_ampmax,
387                    local_ampmax[i]);
388
389 #if 0
390       if(vi->channels==2){
391         if(i==0)
392           _analysis_output("toneL",seq,tone,n/2,1,0,0);
393         else
394           _analysis_output("toneR",seq,tone,n/2,1,0,0);
395       }
396 #endif
397
398       /* third step; we offset the noise vectors, overlay tone
399          masking.  We then do a floor1-specific line fit.  If we're
400          performing bitrate management, the line fit is performed
401          multiple times for up/down tweakage on demand. */
402       
403       _vp_offset_and_mix(psy_look,
404                          noise,
405                          tone,
406                          1,
407                          logmask);
408
409 #if 0
410       if(vi->channels==2){
411         if(i==0)
412           _analysis_output("mask1L",seq,logmask,n/2,1,0,0);
413         else
414           _analysis_output("mask1R",seq,logmask,n/2,1,0,0);
415       }
416 #endif
417
418       /* this algorithm is hardwired to floor 1 for now; abort out if
419          we're *not* floor1.  This won't happen unless someone has
420          broken the encode setup lib.  Guard it anyway. */
421       if(ci->floor_type[info->floorsubmap[submap]]!=1)return(-1);
422
423       floor_posts[i][PACKETBLOBS/2]=
424         floor1_fit(vb,b->flr[info->floorsubmap[submap]],
425                    logmdct,
426                    logmask);
427       
428       /* are we managing bitrate?  If so, perform two more fits for
429          later rate tweaking (fits represent hi/lo) */
430       if(vorbis_bitrate_managed(vb) && floor_posts[i][PACKETBLOBS/2]){
431         /* higher rate by way of lower noise curve */
432
433         _vp_offset_and_mix(psy_look,
434                            noise,
435                            tone,
436                            2,
437                            logmask);
438
439 #if 0
440         if(vi->channels==2){
441           if(i==0)
442             _analysis_output("mask2L",seq,logmask,n/2,1,0,0);
443           else
444             _analysis_output("mask2R",seq,logmask,n/2,1,0,0);
445         }
446 #endif
447         
448         floor_posts[i][PACKETBLOBS-1]=
449           floor1_fit(vb,b->flr[info->floorsubmap[submap]],
450                      logmdct,
451                      logmask);
452       
453         /* lower rate by way of higher noise curve */
454         _vp_offset_and_mix(psy_look,
455                            noise,
456                            tone,
457                            0,
458                            logmask);
459
460 #if 0
461         if(vi->channels==2)
462           if(i==0)
463             _analysis_output("mask0L",seq,logmask,n/2,1,0,0);
464           else
465             _analysis_output("mask0R",seq,logmask,n/2,1,0,0);
466 #endif
467
468         floor_posts[i][0]=
469           floor1_fit(vb,b->flr[info->floorsubmap[submap]],
470                      logmdct,
471                      logmask);
472         
473         /* we also interpolate a range of intermediate curves for
474            intermediate rates */
475         for(k=1;k<PACKETBLOBS/2;k++)
476           floor_posts[i][k]=
477             floor1_interpolate_fit(vb,b->flr[info->floorsubmap[submap]],
478                                    floor_posts[i][0],
479                                    floor_posts[i][PACKETBLOBS/2],
480                                    k*65536/(PACKETBLOBS/2));
481         for(k=PACKETBLOBS/2+1;k<PACKETBLOBS-1;k++)
482           floor_posts[i][k]=
483             floor1_interpolate_fit(vb,b->flr[info->floorsubmap[submap]],
484                                    floor_posts[i][PACKETBLOBS/2],
485                                    floor_posts[i][PACKETBLOBS-1],
486                                    (k-PACKETBLOBS/2)*65536/(PACKETBLOBS/2));
487       }
488     }
489   }
490   vbi->ampmax=global_ampmax;
491
492   /*
493     the next phases are performed once for vbr-only and PACKETBLOB
494     times for bitrate managed modes.
495     
496     1) encode actual mode being used
497     2) encode the floor for each channel, compute coded mask curve/res
498     3) normalize and couple.
499     4) encode residue
500     5) save packet bytes to the packetblob vector
501     
502   */
503
504   /* iterate over the many masking curve fits we've created */
505
506   {
507     float **res_bundle=alloca(sizeof(*res_bundle)*vi->channels);
508     float **couple_bundle=alloca(sizeof(*couple_bundle)*vi->channels);
509     int *zerobundle=alloca(sizeof(*zerobundle)*vi->channels);
510     int **sortindex=alloca(sizeof(*sortindex)*vi->channels);
511     float **mag_memo;
512     int **mag_sort;
513
514     if(info->coupling_steps){
515       mag_memo=_vp_quantize_couple_memo(vb,
516                                         &ci->psy_g_param,
517                                         psy_look,
518                                         info,
519                                         gmdct);    
520       
521       mag_sort=_vp_quantize_couple_sort(vb,
522                                         psy_look,
523                                         info,
524                                         mag_memo);    
525     }
526
527     memset(sortindex,0,sizeof(*sortindex)*vi->channels);
528     if(psy_look->vi->normal_channel_p){
529       for(i=0;i<vi->channels;i++){
530         float *mdct    =gmdct[i];
531         sortindex[i]=alloca(sizeof(**sortindex)*n/2);
532         _vp_noise_normalize_sort(psy_look,mdct,sortindex[i]);
533       }
534     }
535
536     for(k=(vorbis_bitrate_managed(vb)?0:PACKETBLOBS/2);
537         k<=(vorbis_bitrate_managed(vb)?PACKETBLOBS-1:PACKETBLOBS/2);
538         k++){
539
540       /* start out our new packet blob with packet type and mode */
541       /* Encode the packet type */
542       oggpack_write(&vb->opb,0,1);
543       /* Encode the modenumber */
544       /* Encode frame mode, pre,post windowsize, then dispatch */
545       oggpack_write(&vb->opb,modenumber,b->modebits);
546       if(vb->W){
547         oggpack_write(&vb->opb,vb->lW,1);
548         oggpack_write(&vb->opb,vb->nW,1);
549       }
550
551       /* encode floor, compute masking curve, sep out residue */
552       for(i=0;i<vi->channels;i++){
553         int submap=info->chmuxlist[i];
554         float *mdct    =gmdct[i];
555         float *res     =vb->pcm[i];
556         int   *ilogmask=ilogmaskch[i]=
557           _vorbis_block_alloc(vb,n/2*sizeof(**gmdct));
558       
559         nonzero[i]=floor1_encode(vb,b->flr[info->floorsubmap[submap]],
560                                  floor_posts[i][k],
561                                  ilogmask);
562 #if 0
563         {
564           char buf[80];
565           sprintf(buf,"maskI%c%d",i?'R':'L',k);
566           float work[n/2];
567           for(j=0;j<n/2;j++)
568             work[j]=FLOOR1_fromdB_LOOKUP[ilogmask[j]];
569           _analysis_output(buf,seq,work,n/2,1,1,0);
570         }
571 #endif
572         _vp_remove_floor(psy_look,
573                          mdct,
574                          ilogmask,
575                          res,
576                          ci->psy_g_param.sliding_lowpass[vb->W][k]);
577
578         _vp_noise_normalize(psy_look,res,res+n/2,sortindex[i]);
579
580         
581 #if 0
582         {
583           char buf[80];
584           float work[n/2];
585           for(j=0;j<n/2;j++)
586             work[j]=FLOOR1_fromdB_LOOKUP[ilogmask[j]]*(res+n/2)[j];
587           sprintf(buf,"resI%c%d",i?'R':'L',k);
588           _analysis_output(buf,seq,work,n/2,1,1,0);
589
590         }
591 #endif
592       }
593       
594       /* our iteration is now based on masking curve, not prequant and
595          coupling.  Only one prequant/coupling step */
596       
597       /* quantize/couple */
598       /* incomplete implementation that assumes the tree is all depth
599          one, or no tree at all */
600       if(info->coupling_steps){
601         _vp_couple(k,
602                    &ci->psy_g_param,
603                    psy_look,
604                    info,
605                    vb->pcm,
606                    mag_memo,
607                    mag_sort,
608                    ilogmaskch,
609                    nonzero,
610                    ci->psy_g_param.sliding_lowpass[vb->W][k]);
611       }
612       
613       /* classify and encode by submap */
614       for(i=0;i<info->submaps;i++){
615         int ch_in_bundle=0;
616         long **classifications;
617         int resnum=info->residuesubmap[i];
618
619         for(j=0;j<vi->channels;j++){
620           if(info->chmuxlist[j]==i){
621             zerobundle[ch_in_bundle]=0;
622             if(nonzero[j])zerobundle[ch_in_bundle]=1;
623             res_bundle[ch_in_bundle]=vb->pcm[j];
624             couple_bundle[ch_in_bundle++]=vb->pcm[j]+n/2;
625           }
626         }
627         
628         classifications=_residue_P[ci->residue_type[resnum]]->
629           class(vb,b->residue[resnum],couple_bundle,zerobundle,ch_in_bundle);
630         
631         _residue_P[ci->residue_type[resnum]]->
632           forward(vb,b->residue[resnum],
633                   couple_bundle,NULL,zerobundle,ch_in_bundle,classifications);
634       }
635       
636       /* ok, done encoding.  Mark this protopacket and prepare next. */
637       oggpack_writealign(&vb->opb);
638       vbi->packetblob_markers[k]=oggpack_bytes(&vb->opb);
639       
640     }
641     
642   }
643
644 #if 0
645   seq++;
646   total+=ci->blocksizes[vb->W]/4+ci->blocksizes[vb->nW]/4;
647 #endif
648   return(0);
649 }
650
651 static int mapping0_inverse(vorbis_block *vb,vorbis_info_mapping *l){
652   vorbis_dsp_state     *vd=vb->vd;
653   vorbis_info          *vi=vd->vi;
654   codec_setup_info     *ci=vi->codec_setup;
655   private_state        *b=vd->backend_state;
656   vorbis_info_mapping0 *info=(vorbis_info_mapping0 *)l;
657   int hs=ci->halfrate_flag; 
658
659   int                   i,j;
660   long                  n=vb->pcmend=ci->blocksizes[vb->W];
661
662   float **pcmbundle=alloca(sizeof(*pcmbundle)*vi->channels);
663   int    *zerobundle=alloca(sizeof(*zerobundle)*vi->channels);
664
665   int   *nonzero  =alloca(sizeof(*nonzero)*vi->channels);
666   void **floormemo=alloca(sizeof(*floormemo)*vi->channels);
667   
668   /* recover the spectral envelope; store it in the PCM vector for now */
669   for(i=0;i<vi->channels;i++){
670     int submap=info->chmuxlist[i];
671     floormemo[i]=_floor_P[ci->floor_type[info->floorsubmap[submap]]]->
672       inverse1(vb,b->flr[info->floorsubmap[submap]]);
673     if(floormemo[i])
674       nonzero[i]=1;
675     else
676       nonzero[i]=0;      
677     memset(vb->pcm[i],0,sizeof(*vb->pcm[i])*n/2);
678   }
679
680   /* channel coupling can 'dirty' the nonzero listing */
681   for(i=0;i<info->coupling_steps;i++){
682     if(nonzero[info->coupling_mag[i]] ||
683        nonzero[info->coupling_ang[i]]){
684       nonzero[info->coupling_mag[i]]=1; 
685       nonzero[info->coupling_ang[i]]=1; 
686     }
687   }
688
689   /* recover the residue into our working vectors */
690   for(i=0;i<info->submaps;i++){
691     int ch_in_bundle=0;
692     for(j=0;j<vi->channels;j++){
693       if(info->chmuxlist[j]==i){
694         if(nonzero[j])
695           zerobundle[ch_in_bundle]=1;
696         else
697           zerobundle[ch_in_bundle]=0;
698         pcmbundle[ch_in_bundle++]=vb->pcm[j];
699       }
700     }
701
702     _residue_P[ci->residue_type[info->residuesubmap[i]]]->
703       inverse(vb,b->residue[info->residuesubmap[i]],
704               pcmbundle,zerobundle,ch_in_bundle);
705   }
706
707   /* channel coupling */
708   for(i=info->coupling_steps-1;i>=0;i--){
709     float *pcmM=vb->pcm[info->coupling_mag[i]];
710     float *pcmA=vb->pcm[info->coupling_ang[i]];
711
712     for(j=0;j<n/2;j++){
713       float mag=pcmM[j];
714       float ang=pcmA[j];
715
716       if(mag>0)
717         if(ang>0){
718           pcmM[j]=mag;
719           pcmA[j]=mag-ang;
720         }else{
721           pcmA[j]=mag;
722           pcmM[j]=mag+ang;
723         }
724       else
725         if(ang>0){
726           pcmM[j]=mag;
727           pcmA[j]=mag+ang;
728         }else{
729           pcmA[j]=mag;
730           pcmM[j]=mag-ang;
731         }
732     }
733   }
734
735   /* compute and apply spectral envelope */
736   for(i=0;i<vi->channels;i++){
737     float *pcm=vb->pcm[i];
738     int submap=info->chmuxlist[i];
739     _floor_P[ci->floor_type[info->floorsubmap[submap]]]->
740       inverse2(vb,b->flr[info->floorsubmap[submap]],
741                floormemo[i],pcm);
742   }
743
744   /* transform the PCM data; takes PCM vector, vb; modifies PCM vector */
745   /* only MDCT right now.... */
746   for(i=0;i<vi->channels;i++){
747     float *pcm=vb->pcm[i];
748     mdct_backward(b->transform[vb->W][0],pcm,pcm);
749   }
750
751   /* all done! */
752   return(0);
753 }
754
755 /* export hooks */
756 vorbis_func_mapping mapping0_exportbundle={
757   &mapping0_pack,
758   &mapping0_unpack,
759   &mapping0_free_info,
760   &mapping0_forward,
761   &mapping0_inverse
762 };
763