vx32

Local 9vx git repository for patches.
git clone git://r-36.net/vx32
Log | Files | Refs

mapping0.c (23521B)


      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 1919 2005-07-24 14:18:04Z baford $
     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