Blame lib/mapping0.c

Packit 06404a
/********************************************************************
Packit 06404a
 *                                                                  *
Packit 06404a
 * THIS FILE IS PART OF THE OggVorbis SOFTWARE CODEC SOURCE CODE.   *
Packit 06404a
 * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS     *
Packit 06404a
 * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE *
Packit 06404a
 * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING.       *
Packit 06404a
 *                                                                  *
Packit 06404a
 * THE OggVorbis SOURCE CODE IS (C) COPYRIGHT 1994-2010             *
Packit 06404a
 * by the Xiph.Org Foundation http://www.xiph.org/                  *
Packit 06404a
 *                                                                  *
Packit 06404a
 ********************************************************************
Packit 06404a
Packit 06404a
 function: channel mapping 0 implementation
Packit 06404a
 last mod: $Id: mapping0.c 19441 2015-01-21 01:17:41Z xiphmont $
Packit 06404a
Packit 06404a
 ********************************************************************/
Packit 06404a
Packit 06404a
#include <stdlib.h>
Packit 06404a
#include <stdio.h>
Packit 06404a
#include <string.h>
Packit 06404a
#include <math.h>
Packit 06404a
#include <ogg/ogg.h>
Packit 06404a
#include "vorbis/codec.h"
Packit 06404a
#include "codec_internal.h"
Packit 06404a
#include "codebook.h"
Packit 06404a
#include "window.h"
Packit 06404a
#include "registry.h"
Packit 06404a
#include "psy.h"
Packit 06404a
#include "misc.h"
Packit 06404a
Packit 06404a
/* simplistic, wasteful way of doing this (unique lookup for each
Packit 06404a
   mode/submapping); there should be a central repository for
Packit 06404a
   identical lookups.  That will require minor work, so I'm putting it
Packit 06404a
   off as low priority.
Packit 06404a
Packit 06404a
   Why a lookup for each backend in a given mode?  Because the
Packit 06404a
   blocksize is set by the mode, and low backend lookups may require
Packit 06404a
   parameters from other areas of the mode/mapping */
Packit 06404a
Packit 06404a
static void mapping0_free_info(vorbis_info_mapping *i){
Packit 06404a
  vorbis_info_mapping0 *info=(vorbis_info_mapping0 *)i;
Packit 06404a
  if(info){
Packit 06404a
    memset(info,0,sizeof(*info));
Packit 06404a
    _ogg_free(info);
Packit 06404a
  }
Packit 06404a
}
Packit 06404a
Packit 06404a
static void mapping0_pack(vorbis_info *vi,vorbis_info_mapping *vm,
Packit 06404a
                          oggpack_buffer *opb){
Packit 06404a
  int i;
Packit 06404a
  vorbis_info_mapping0 *info=(vorbis_info_mapping0 *)vm;
Packit 06404a
Packit 06404a
  /* another 'we meant to do it this way' hack...  up to beta 4, we
Packit 06404a
     packed 4 binary zeros here to signify one submapping in use.  We
Packit 06404a
     now redefine that to mean four bitflags that indicate use of
Packit 06404a
     deeper features; bit0:submappings, bit1:coupling,
Packit 06404a
     bit2,3:reserved. This is backward compatable with all actual uses
Packit 06404a
     of the beta code. */
Packit 06404a
Packit 06404a
  if(info->submaps>1){
Packit 06404a
    oggpack_write(opb,1,1);
Packit 06404a
    oggpack_write(opb,info->submaps-1,4);
Packit 06404a
  }else
Packit 06404a
    oggpack_write(opb,0,1);
Packit 06404a
Packit 06404a
  if(info->coupling_steps>0){
Packit 06404a
    oggpack_write(opb,1,1);
Packit 06404a
    oggpack_write(opb,info->coupling_steps-1,8);
Packit 06404a
Packit 06404a
    for(i=0;i<info->coupling_steps;i++){
Packit 06404a
      oggpack_write(opb,info->coupling_mag[i],ov_ilog(vi->channels-1));
Packit 06404a
      oggpack_write(opb,info->coupling_ang[i],ov_ilog(vi->channels-1));
Packit 06404a
    }
Packit 06404a
  }else
Packit 06404a
    oggpack_write(opb,0,1);
Packit 06404a
Packit 06404a
  oggpack_write(opb,0,2); /* 2,3:reserved */
Packit 06404a
Packit 06404a
  /* we don't write the channel submappings if we only have one... */
Packit 06404a
  if(info->submaps>1){
Packit 06404a
    for(i=0;i<vi->channels;i++)
Packit 06404a
      oggpack_write(opb,info->chmuxlist[i],4);
Packit 06404a
  }
Packit 06404a
  for(i=0;i<info->submaps;i++){
Packit 06404a
    oggpack_write(opb,0,8); /* time submap unused */
Packit 06404a
    oggpack_write(opb,info->floorsubmap[i],8);
Packit 06404a
    oggpack_write(opb,info->residuesubmap[i],8);
Packit 06404a
  }
Packit 06404a
}
Packit 06404a
Packit 06404a
/* also responsible for range checking */
Packit 06404a
static vorbis_info_mapping *mapping0_unpack(vorbis_info *vi,oggpack_buffer *opb){
Packit 06404a
  int i,b;
Packit 06404a
  vorbis_info_mapping0 *info=_ogg_calloc(1,sizeof(*info));
Packit 06404a
  codec_setup_info     *ci=vi->codec_setup;
Packit 06404a
  memset(info,0,sizeof(*info));
Packit 06404a
  if(vi->channels<=0)goto err_out;
Packit 06404a
Packit 06404a
  b=oggpack_read(opb,1);
Packit 06404a
  if(b<0)goto err_out;
Packit 06404a
  if(b){
Packit 06404a
    info->submaps=oggpack_read(opb,4)+1;
Packit 06404a
    if(info->submaps<=0)goto err_out;
Packit 06404a
  }else
Packit 06404a
    info->submaps=1;
Packit 06404a
Packit 06404a
  b=oggpack_read(opb,1);
Packit 06404a
  if(b<0)goto err_out;
Packit 06404a
  if(b){
Packit 06404a
    info->coupling_steps=oggpack_read(opb,8)+1;
Packit 06404a
    if(info->coupling_steps<=0)goto err_out;
Packit 06404a
    for(i=0;i<info->coupling_steps;i++){
Packit 06404a
      /* vi->channels > 0 is enforced in the caller */
Packit 06404a
      int testM=info->coupling_mag[i]=
Packit 06404a
        oggpack_read(opb,ov_ilog(vi->channels-1));
Packit 06404a
      int testA=info->coupling_ang[i]=
Packit 06404a
        oggpack_read(opb,ov_ilog(vi->channels-1));
Packit 06404a
Packit 06404a
      if(testM<0 ||
Packit 06404a
         testA<0 ||
Packit 06404a
         testM==testA ||
Packit 06404a
         testM>=vi->channels ||
Packit 06404a
         testA>=vi->channels) goto err_out;
Packit 06404a
    }
Packit 06404a
Packit 06404a
  }
Packit 06404a
Packit 06404a
  if(oggpack_read(opb,2)!=0)goto err_out; /* 2,3:reserved */
Packit 06404a
Packit 06404a
  if(info->submaps>1){
Packit 06404a
    for(i=0;i<vi->channels;i++){
Packit 06404a
      info->chmuxlist[i]=oggpack_read(opb,4);
Packit 06404a
      if(info->chmuxlist[i]>=info->submaps || info->chmuxlist[i]<0)goto err_out;
Packit 06404a
    }
Packit 06404a
  }
Packit 06404a
  for(i=0;i<info->submaps;i++){
Packit 06404a
    oggpack_read(opb,8); /* time submap unused */
Packit 06404a
    info->floorsubmap[i]=oggpack_read(opb,8);
Packit 06404a
    if(info->floorsubmap[i]>=ci->floors || info->floorsubmap[i]<0)goto err_out;
Packit 06404a
    info->residuesubmap[i]=oggpack_read(opb,8);
Packit 06404a
    if(info->residuesubmap[i]>=ci->residues || info->residuesubmap[i]<0)goto err_out;
Packit 06404a
  }
Packit 06404a
Packit 06404a
  return info;
Packit 06404a
Packit 06404a
 err_out:
Packit 06404a
  mapping0_free_info(info);
Packit 06404a
  return(NULL);
Packit 06404a
}
Packit 06404a
Packit 06404a
#include "os.h"
Packit 06404a
#include "lpc.h"
Packit 06404a
#include "lsp.h"
Packit 06404a
#include "envelope.h"
Packit 06404a
#include "mdct.h"
Packit 06404a
#include "psy.h"
Packit 06404a
#include "scales.h"
Packit 06404a
Packit 06404a
#if 0
Packit 06404a
static long seq=0;
Packit 06404a
static ogg_int64_t total=0;
Packit 06404a
static float FLOOR1_fromdB_LOOKUP[256]={
Packit 06404a
  1.0649863e-07F, 1.1341951e-07F, 1.2079015e-07F, 1.2863978e-07F,
Packit 06404a
  1.3699951e-07F, 1.4590251e-07F, 1.5538408e-07F, 1.6548181e-07F,
Packit 06404a
  1.7623575e-07F, 1.8768855e-07F, 1.9988561e-07F, 2.128753e-07F,
Packit 06404a
  2.2670913e-07F, 2.4144197e-07F, 2.5713223e-07F, 2.7384213e-07F,
Packit 06404a
  2.9163793e-07F, 3.1059021e-07F, 3.3077411e-07F, 3.5226968e-07F,
Packit 06404a
  3.7516214e-07F, 3.9954229e-07F, 4.2550680e-07F, 4.5315863e-07F,
Packit 06404a
  4.8260743e-07F, 5.1396998e-07F, 5.4737065e-07F, 5.8294187e-07F,
Packit 06404a
  6.2082472e-07F, 6.6116941e-07F, 7.0413592e-07F, 7.4989464e-07F,
Packit 06404a
  7.9862701e-07F, 8.5052630e-07F, 9.0579828e-07F, 9.6466216e-07F,
Packit 06404a
  1.0273513e-06F, 1.0941144e-06F, 1.1652161e-06F, 1.2409384e-06F,
Packit 06404a
  1.3215816e-06F, 1.4074654e-06F, 1.4989305e-06F, 1.5963394e-06F,
Packit 06404a
  1.7000785e-06F, 1.8105592e-06F, 1.9282195e-06F, 2.0535261e-06F,
Packit 06404a
  2.1869758e-06F, 2.3290978e-06F, 2.4804557e-06F, 2.6416497e-06F,
Packit 06404a
  2.8133190e-06F, 2.9961443e-06F, 3.1908506e-06F, 3.3982101e-06F,
Packit 06404a
  3.6190449e-06F, 3.8542308e-06F, 4.1047004e-06F, 4.3714470e-06F,
Packit 06404a
  4.6555282e-06F, 4.9580707e-06F, 5.2802740e-06F, 5.6234160e-06F,
Packit 06404a
  5.9888572e-06F, 6.3780469e-06F, 6.7925283e-06F, 7.2339451e-06F,
Packit 06404a
  7.7040476e-06F, 8.2047000e-06F, 8.7378876e-06F, 9.3057248e-06F,
Packit 06404a
  9.9104632e-06F, 1.0554501e-05F, 1.1240392e-05F, 1.1970856e-05F,
Packit 06404a
  1.2748789e-05F, 1.3577278e-05F, 1.4459606e-05F, 1.5399272e-05F,
Packit 06404a
  1.6400004e-05F, 1.7465768e-05F, 1.8600792e-05F, 1.9809576e-05F,
Packit 06404a
  2.1096914e-05F, 2.2467911e-05F, 2.3928002e-05F, 2.5482978e-05F,
Packit 06404a
  2.7139006e-05F, 2.8902651e-05F, 3.0780908e-05F, 3.2781225e-05F,
Packit 06404a
  3.4911534e-05F, 3.7180282e-05F, 3.9596466e-05F, 4.2169667e-05F,
Packit 06404a
  4.4910090e-05F, 4.7828601e-05F, 5.0936773e-05F, 5.4246931e-05F,
Packit 06404a
  5.7772202e-05F, 6.1526565e-05F, 6.5524908e-05F, 6.9783085e-05F,
Packit 06404a
  7.4317983e-05F, 7.9147585e-05F, 8.4291040e-05F, 8.9768747e-05F,
Packit 06404a
  9.5602426e-05F, 0.00010181521F, 0.00010843174F, 0.00011547824F,
Packit 06404a
  0.00012298267F, 0.00013097477F, 0.00013948625F, 0.00014855085F,
Packit 06404a
  0.00015820453F, 0.00016848555F, 0.00017943469F, 0.00019109536F,
Packit 06404a
  0.00020351382F, 0.00021673929F, 0.00023082423F, 0.00024582449F,
Packit 06404a
  0.00026179955F, 0.00027881276F, 0.00029693158F, 0.00031622787F,
Packit 06404a
  0.00033677814F, 0.00035866388F, 0.00038197188F, 0.00040679456F,
Packit 06404a
  0.00043323036F, 0.00046138411F, 0.00049136745F, 0.00052329927F,
Packit 06404a
  0.00055730621F, 0.00059352311F, 0.00063209358F, 0.00067317058F,
Packit 06404a
  0.00071691700F, 0.00076350630F, 0.00081312324F, 0.00086596457F,
Packit 06404a
  0.00092223983F, 0.00098217216F, 0.0010459992F, 0.0011139742F,
Packit 06404a
  0.0011863665F, 0.0012634633F, 0.0013455702F, 0.0014330129F,
Packit 06404a
  0.0015261382F, 0.0016253153F, 0.0017309374F, 0.0018434235F,
Packit 06404a
  0.0019632195F, 0.0020908006F, 0.0022266726F, 0.0023713743F,
Packit 06404a
  0.0025254795F, 0.0026895994F, 0.0028643847F, 0.0030505286F,
Packit 06404a
  0.0032487691F, 0.0034598925F, 0.0036847358F, 0.0039241906F,
Packit 06404a
  0.0041792066F, 0.0044507950F, 0.0047400328F, 0.0050480668F,
Packit 06404a
  0.0053761186F, 0.0057254891F, 0.0060975636F, 0.0064938176F,
Packit 06404a
  0.0069158225F, 0.0073652516F, 0.0078438871F, 0.0083536271F,
Packit 06404a
  0.0088964928F, 0.009474637F, 0.010090352F, 0.010746080F,
Packit 06404a
  0.011444421F, 0.012188144F, 0.012980198F, 0.013823725F,
Packit 06404a
  0.014722068F, 0.015678791F, 0.016697687F, 0.017782797F,
Packit 06404a
  0.018938423F, 0.020169149F, 0.021479854F, 0.022875735F,
Packit 06404a
  0.024362330F, 0.025945531F, 0.027631618F, 0.029427276F,
Packit 06404a
  0.031339626F, 0.033376252F, 0.035545228F, 0.037855157F,
Packit 06404a
  0.040315199F, 0.042935108F, 0.045725273F, 0.048696758F,
Packit 06404a
  0.051861348F, 0.055231591F, 0.058820850F, 0.062643361F,
Packit 06404a
  0.066714279F, 0.071049749F, 0.075666962F, 0.080584227F,
Packit 06404a
  0.085821044F, 0.091398179F, 0.097337747F, 0.10366330F,
Packit 06404a
  0.11039993F, 0.11757434F, 0.12521498F, 0.13335215F,
Packit 06404a
  0.14201813F, 0.15124727F, 0.16107617F, 0.17154380F,
Packit 06404a
  0.18269168F, 0.19456402F, 0.20720788F, 0.22067342F,
Packit 06404a
  0.23501402F, 0.25028656F, 0.26655159F, 0.28387361F,
Packit 06404a
  0.30232132F, 0.32196786F, 0.34289114F, 0.36517414F,
Packit 06404a
  0.38890521F, 0.41417847F, 0.44109412F, 0.46975890F,
Packit 06404a
  0.50028648F, 0.53279791F, 0.56742212F, 0.60429640F,
Packit 06404a
  0.64356699F, 0.68538959F, 0.72993007F, 0.77736504F,
Packit 06404a
  0.82788260F, 0.88168307F, 0.9389798F, 1.F,
Packit 06404a
};
Packit 06404a
Packit 06404a
#endif
Packit 06404a
Packit 06404a
Packit 06404a
static int mapping0_forward(vorbis_block *vb){
Packit 06404a
  vorbis_dsp_state      *vd=vb->vd;
Packit 06404a
  vorbis_info           *vi=vd->vi;
Packit 06404a
  codec_setup_info      *ci=vi->codec_setup;
Packit 06404a
  private_state         *b=vb->vd->backend_state;
Packit 06404a
  vorbis_block_internal *vbi=(vorbis_block_internal *)vb->internal;
Packit 06404a
  int                    n=vb->pcmend;
Packit 06404a
  int i,j,k;
Packit 06404a
Packit 06404a
  int    *nonzero    = alloca(sizeof(*nonzero)*vi->channels);
Packit 06404a
  float  **gmdct     = _vorbis_block_alloc(vb,vi->channels*sizeof(*gmdct));
Packit 06404a
  int    **iwork      = _vorbis_block_alloc(vb,vi->channels*sizeof(*iwork));
Packit 06404a
  int ***floor_posts = _vorbis_block_alloc(vb,vi->channels*sizeof(*floor_posts));
Packit 06404a
Packit 06404a
  float global_ampmax=vbi->ampmax;
Packit 06404a
  float *local_ampmax=alloca(sizeof(*local_ampmax)*vi->channels);
Packit 06404a
  int blocktype=vbi->blocktype;
Packit 06404a
Packit 06404a
  int modenumber=vb->W;
Packit 06404a
  vorbis_info_mapping0 *info=ci->map_param[modenumber];
Packit 06404a
  vorbis_look_psy *psy_look=b->psy+blocktype+(vb->W?2:0);
Packit 06404a
Packit 06404a
  vb->mode=modenumber;
Packit 06404a
Packit 06404a
  for(i=0;i<vi->channels;i++){
Packit 06404a
    float scale=4.f/n;
Packit 06404a
    float scale_dB;
Packit 06404a
Packit 06404a
    float *pcm     =vb->pcm[i];
Packit 06404a
    float *logfft  =pcm;
Packit 06404a
Packit 06404a
    iwork[i]=_vorbis_block_alloc(vb,n/2*sizeof(**iwork));
Packit 06404a
    gmdct[i]=_vorbis_block_alloc(vb,n/2*sizeof(**gmdct));
Packit 06404a
Packit 06404a
    scale_dB=todB(&scale) + .345; /* + .345 is a hack; the original
Packit 06404a
                                     todB estimation used on IEEE 754
Packit 06404a
                                     compliant machines had a bug that
Packit 06404a
                                     returned dB values about a third
Packit 06404a
                                     of a decibel too high.  The bug
Packit 06404a
                                     was harmless because tunings
Packit 06404a
                                     implicitly took that into
Packit 06404a
                                     account.  However, fixing the bug
Packit 06404a
                                     in the estimator requires
Packit 06404a
                                     changing all the tunings as well.
Packit 06404a
                                     For now, it's easier to sync
Packit 06404a
                                     things back up here, and
Packit 06404a
                                     recalibrate the tunings in the
Packit 06404a
                                     next major model upgrade. */
Packit 06404a
Packit 06404a
#if 0
Packit 06404a
    if(vi->channels==2){
Packit 06404a
      if(i==0)
Packit 06404a
        _analysis_output("pcmL",seq,pcm,n,0,0,total-n/2);
Packit 06404a
      else
Packit 06404a
        _analysis_output("pcmR",seq,pcm,n,0,0,total-n/2);
Packit 06404a
    }else{
Packit 06404a
      _analysis_output("pcm",seq,pcm,n,0,0,total-n/2);
Packit 06404a
    }
Packit 06404a
#endif
Packit 06404a
Packit 06404a
    /* window the PCM data */
Packit 06404a
    _vorbis_apply_window(pcm,b->window,ci->blocksizes,vb->lW,vb->W,vb->nW);
Packit 06404a
Packit 06404a
#if 0
Packit 06404a
    if(vi->channels==2){
Packit 06404a
      if(i==0)
Packit 06404a
        _analysis_output("windowedL",seq,pcm,n,0,0,total-n/2);
Packit 06404a
      else
Packit 06404a
        _analysis_output("windowedR",seq,pcm,n,0,0,total-n/2);
Packit 06404a
    }else{
Packit 06404a
      _analysis_output("windowed",seq,pcm,n,0,0,total-n/2);
Packit 06404a
    }
Packit 06404a
#endif
Packit 06404a
Packit 06404a
    /* transform the PCM data */
Packit 06404a
    /* only MDCT right now.... */
Packit 06404a
    mdct_forward(b->transform[vb->W][0],pcm,gmdct[i]);
Packit 06404a
Packit 06404a
    /* FFT yields more accurate tonal estimation (not phase sensitive) */
Packit 06404a
    drft_forward(&b->fft_look[vb->W],pcm);
Packit 06404a
    logfft[0]=scale_dB+todB(pcm)  + .345; /* + .345 is a hack; the
Packit 06404a
                                     original todB estimation used on
Packit 06404a
                                     IEEE 754 compliant machines had a
Packit 06404a
                                     bug that returned dB values about
Packit 06404a
                                     a third of a decibel too high.
Packit 06404a
                                     The bug was harmless because
Packit 06404a
                                     tunings implicitly took that into
Packit 06404a
                                     account.  However, fixing the bug
Packit 06404a
                                     in the estimator requires
Packit 06404a
                                     changing all the tunings as well.
Packit 06404a
                                     For now, it's easier to sync
Packit 06404a
                                     things back up here, and
Packit 06404a
                                     recalibrate the tunings in the
Packit 06404a
                                     next major model upgrade. */
Packit 06404a
    local_ampmax[i]=logfft[0];
Packit 06404a
    for(j=1;j
Packit 06404a
      float temp=pcm[j]*pcm[j]+pcm[j+1]*pcm[j+1];
Packit 06404a
      temp=logfft[(j+1)>>1]=scale_dB+.5f*todB(&temp)  + .345; /* +
Packit 06404a
                                     .345 is a hack; the original todB
Packit 06404a
                                     estimation used on IEEE 754
Packit 06404a
                                     compliant machines had a bug that
Packit 06404a
                                     returned dB values about a third
Packit 06404a
                                     of a decibel too high.  The bug
Packit 06404a
                                     was harmless because tunings
Packit 06404a
                                     implicitly took that into
Packit 06404a
                                     account.  However, fixing the bug
Packit 06404a
                                     in the estimator requires
Packit 06404a
                                     changing all the tunings as well.
Packit 06404a
                                     For now, it's easier to sync
Packit 06404a
                                     things back up here, and
Packit 06404a
                                     recalibrate the tunings in the
Packit 06404a
                                     next major model upgrade. */
Packit 06404a
      if(temp>local_ampmax[i])local_ampmax[i]=temp;
Packit 06404a
    }
Packit 06404a
Packit 06404a
    if(local_ampmax[i]>0.f)local_ampmax[i]=0.f;
Packit 06404a
    if(local_ampmax[i]>global_ampmax)global_ampmax=local_ampmax[i];
Packit 06404a
Packit 06404a
#if 0
Packit 06404a
    if(vi->channels==2){
Packit 06404a
      if(i==0){
Packit 06404a
        _analysis_output("fftL",seq,logfft,n/2,1,0,0);
Packit 06404a
      }else{
Packit 06404a
        _analysis_output("fftR",seq,logfft,n/2,1,0,0);
Packit 06404a
      }
Packit 06404a
    }else{
Packit 06404a
      _analysis_output("fft",seq,logfft,n/2,1,0,0);
Packit 06404a
    }
Packit 06404a
#endif
Packit 06404a
Packit 06404a
  }
Packit 06404a
Packit 06404a
  {
Packit 06404a
    float   *noise        = _vorbis_block_alloc(vb,n/2*sizeof(*noise));
Packit 06404a
    float   *tone         = _vorbis_block_alloc(vb,n/2*sizeof(*tone));
Packit 06404a
Packit 06404a
    for(i=0;i<vi->channels;i++){
Packit 06404a
      /* the encoder setup assumes that all the modes used by any
Packit 06404a
         specific bitrate tweaking use the same floor */
Packit 06404a
Packit 06404a
      int submap=info->chmuxlist[i];
Packit 06404a
Packit 06404a
      /* the following makes things clearer to *me* anyway */
Packit 06404a
      float *mdct    =gmdct[i];
Packit 06404a
      float *logfft  =vb->pcm[i];
Packit 06404a
Packit 06404a
      float *logmdct =logfft+n/2;
Packit 06404a
      float *logmask =logfft;
Packit 06404a
Packit 06404a
      vb->mode=modenumber;
Packit 06404a
Packit 06404a
      floor_posts[i]=_vorbis_block_alloc(vb,PACKETBLOBS*sizeof(**floor_posts));
Packit 06404a
      memset(floor_posts[i],0,sizeof(**floor_posts)*PACKETBLOBS);
Packit 06404a
Packit 06404a
      for(j=0;j
Packit 06404a
        logmdct[j]=todB(mdct+j)  + .345; /* + .345 is a hack; the original
Packit 06404a
                                     todB estimation used on IEEE 754
Packit 06404a
                                     compliant machines had a bug that
Packit 06404a
                                     returned dB values about a third
Packit 06404a
                                     of a decibel too high.  The bug
Packit 06404a
                                     was harmless because tunings
Packit 06404a
                                     implicitly took that into
Packit 06404a
                                     account.  However, fixing the bug
Packit 06404a
                                     in the estimator requires
Packit 06404a
                                     changing all the tunings as well.
Packit 06404a
                                     For now, it's easier to sync
Packit 06404a
                                     things back up here, and
Packit 06404a
                                     recalibrate the tunings in the
Packit 06404a
                                     next major model upgrade. */
Packit 06404a
Packit 06404a
#if 0
Packit 06404a
      if(vi->channels==2){
Packit 06404a
        if(i==0)
Packit 06404a
          _analysis_output("mdctL",seq,logmdct,n/2,1,0,0);
Packit 06404a
        else
Packit 06404a
          _analysis_output("mdctR",seq,logmdct,n/2,1,0,0);
Packit 06404a
      }else{
Packit 06404a
        _analysis_output("mdct",seq,logmdct,n/2,1,0,0);
Packit 06404a
      }
Packit 06404a
#endif
Packit 06404a
Packit 06404a
      /* first step; noise masking.  Not only does 'noise masking'
Packit 06404a
         give us curves from which we can decide how much resolution
Packit 06404a
         to give noise parts of the spectrum, it also implicitly hands
Packit 06404a
         us a tonality estimate (the larger the value in the
Packit 06404a
         'noise_depth' vector, the more tonal that area is) */
Packit 06404a
Packit 06404a
      _vp_noisemask(psy_look,
Packit 06404a
                    logmdct,
Packit 06404a
                    noise); /* noise does not have by-frequency offset
Packit 06404a
                               bias applied yet */
Packit 06404a
#if 0
Packit 06404a
      if(vi->channels==2){
Packit 06404a
        if(i==0)
Packit 06404a
          _analysis_output("noiseL",seq,noise,n/2,1,0,0);
Packit 06404a
        else
Packit 06404a
          _analysis_output("noiseR",seq,noise,n/2,1,0,0);
Packit 06404a
      }else{
Packit 06404a
        _analysis_output("noise",seq,noise,n/2,1,0,0);
Packit 06404a
      }
Packit 06404a
#endif
Packit 06404a
Packit 06404a
      /* second step: 'all the other crap'; all the stuff that isn't
Packit 06404a
         computed/fit for bitrate management goes in the second psy
Packit 06404a
         vector.  This includes tone masking, peak limiting and ATH */
Packit 06404a
Packit 06404a
      _vp_tonemask(psy_look,
Packit 06404a
                   logfft,
Packit 06404a
                   tone,
Packit 06404a
                   global_ampmax,
Packit 06404a
                   local_ampmax[i]);
Packit 06404a
Packit 06404a
#if 0
Packit 06404a
      if(vi->channels==2){
Packit 06404a
        if(i==0)
Packit 06404a
          _analysis_output("toneL",seq,tone,n/2,1,0,0);
Packit 06404a
        else
Packit 06404a
          _analysis_output("toneR",seq,tone,n/2,1,0,0);
Packit 06404a
      }else{
Packit 06404a
        _analysis_output("tone",seq,tone,n/2,1,0,0);
Packit 06404a
      }
Packit 06404a
#endif
Packit 06404a
Packit 06404a
      /* third step; we offset the noise vectors, overlay tone
Packit 06404a
         masking.  We then do a floor1-specific line fit.  If we're
Packit 06404a
         performing bitrate management, the line fit is performed
Packit 06404a
         multiple times for up/down tweakage on demand. */
Packit 06404a
Packit 06404a
#if 0
Packit 06404a
      {
Packit 06404a
      float aotuv[psy_look->n];
Packit 06404a
#endif
Packit 06404a
Packit 06404a
        _vp_offset_and_mix(psy_look,
Packit 06404a
                           noise,
Packit 06404a
                           tone,
Packit 06404a
                           1,
Packit 06404a
                           logmask,
Packit 06404a
                           mdct,
Packit 06404a
                           logmdct);
Packit 06404a
Packit 06404a
#if 0
Packit 06404a
        if(vi->channels==2){
Packit 06404a
          if(i==0)
Packit 06404a
            _analysis_output("aotuvM1_L",seq,aotuv,psy_look->n,1,1,0);
Packit 06404a
          else
Packit 06404a
            _analysis_output("aotuvM1_R",seq,aotuv,psy_look->n,1,1,0);
Packit 06404a
        }else{
Packit 06404a
          _analysis_output("aotuvM1",seq,aotuv,psy_look->n,1,1,0);
Packit 06404a
        }
Packit 06404a
      }
Packit 06404a
#endif
Packit 06404a
Packit 06404a
Packit 06404a
#if 0
Packit 06404a
      if(vi->channels==2){
Packit 06404a
        if(i==0)
Packit 06404a
          _analysis_output("mask1L",seq,logmask,n/2,1,0,0);
Packit 06404a
        else
Packit 06404a
          _analysis_output("mask1R",seq,logmask,n/2,1,0,0);
Packit 06404a
      }else{
Packit 06404a
        _analysis_output("mask1",seq,logmask,n/2,1,0,0);
Packit 06404a
      }
Packit 06404a
#endif
Packit 06404a
Packit 06404a
      /* this algorithm is hardwired to floor 1 for now; abort out if
Packit 06404a
         we're *not* floor1.  This won't happen unless someone has
Packit 06404a
         broken the encode setup lib.  Guard it anyway. */
Packit 06404a
      if(ci->floor_type[info->floorsubmap[submap]]!=1)return(-1);
Packit 06404a
Packit 06404a
      floor_posts[i][PACKETBLOBS/2]=
Packit 06404a
        floor1_fit(vb,b->flr[info->floorsubmap[submap]],
Packit 06404a
                   logmdct,
Packit 06404a
                   logmask);
Packit 06404a
Packit 06404a
      /* are we managing bitrate?  If so, perform two more fits for
Packit 06404a
         later rate tweaking (fits represent hi/lo) */
Packit 06404a
      if(vorbis_bitrate_managed(vb) && floor_posts[i][PACKETBLOBS/2]){
Packit 06404a
        /* higher rate by way of lower noise curve */
Packit 06404a
Packit 06404a
        _vp_offset_and_mix(psy_look,
Packit 06404a
                           noise,
Packit 06404a
                           tone,
Packit 06404a
                           2,
Packit 06404a
                           logmask,
Packit 06404a
                           mdct,
Packit 06404a
                           logmdct);
Packit 06404a
Packit 06404a
#if 0
Packit 06404a
        if(vi->channels==2){
Packit 06404a
          if(i==0)
Packit 06404a
            _analysis_output("mask2L",seq,logmask,n/2,1,0,0);
Packit 06404a
          else
Packit 06404a
            _analysis_output("mask2R",seq,logmask,n/2,1,0,0);
Packit 06404a
        }else{
Packit 06404a
          _analysis_output("mask2",seq,logmask,n/2,1,0,0);
Packit 06404a
        }
Packit 06404a
#endif
Packit 06404a
Packit 06404a
        floor_posts[i][PACKETBLOBS-1]=
Packit 06404a
          floor1_fit(vb,b->flr[info->floorsubmap[submap]],
Packit 06404a
                     logmdct,
Packit 06404a
                     logmask);
Packit 06404a
Packit 06404a
        /* lower rate by way of higher noise curve */
Packit 06404a
        _vp_offset_and_mix(psy_look,
Packit 06404a
                           noise,
Packit 06404a
                           tone,
Packit 06404a
                           0,
Packit 06404a
                           logmask,
Packit 06404a
                           mdct,
Packit 06404a
                           logmdct);
Packit 06404a
Packit 06404a
#if 0
Packit 06404a
        if(vi->channels==2){
Packit 06404a
          if(i==0)
Packit 06404a
            _analysis_output("mask0L",seq,logmask,n/2,1,0,0);
Packit 06404a
          else
Packit 06404a
            _analysis_output("mask0R",seq,logmask,n/2,1,0,0);
Packit 06404a
        }else{
Packit 06404a
          _analysis_output("mask0",seq,logmask,n/2,1,0,0);
Packit 06404a
        }
Packit 06404a
#endif
Packit 06404a
Packit 06404a
        floor_posts[i][0]=
Packit 06404a
          floor1_fit(vb,b->flr[info->floorsubmap[submap]],
Packit 06404a
                     logmdct,
Packit 06404a
                     logmask);
Packit 06404a
Packit 06404a
        /* we also interpolate a range of intermediate curves for
Packit 06404a
           intermediate rates */
Packit 06404a
        for(k=1;k
Packit 06404a
          floor_posts[i][k]=
Packit 06404a
            floor1_interpolate_fit(vb,b->flr[info->floorsubmap[submap]],
Packit 06404a
                                   floor_posts[i][0],
Packit 06404a
                                   floor_posts[i][PACKETBLOBS/2],
Packit 06404a
                                   k*65536/(PACKETBLOBS/2));
Packit 06404a
        for(k=PACKETBLOBS/2+1;k
Packit 06404a
          floor_posts[i][k]=
Packit 06404a
            floor1_interpolate_fit(vb,b->flr[info->floorsubmap[submap]],
Packit 06404a
                                   floor_posts[i][PACKETBLOBS/2],
Packit 06404a
                                   floor_posts[i][PACKETBLOBS-1],
Packit 06404a
                                   (k-PACKETBLOBS/2)*65536/(PACKETBLOBS/2));
Packit 06404a
      }
Packit 06404a
    }
Packit 06404a
  }
Packit 06404a
  vbi->ampmax=global_ampmax;
Packit 06404a
Packit 06404a
  /*
Packit 06404a
    the next phases are performed once for vbr-only and PACKETBLOB
Packit 06404a
    times for bitrate managed modes.
Packit 06404a
Packit 06404a
    1) encode actual mode being used
Packit 06404a
    2) encode the floor for each channel, compute coded mask curve/res
Packit 06404a
    3) normalize and couple.
Packit 06404a
    4) encode residue
Packit 06404a
    5) save packet bytes to the packetblob vector
Packit 06404a
Packit 06404a
  */
Packit 06404a
Packit 06404a
  /* iterate over the many masking curve fits we've created */
Packit 06404a
Packit 06404a
  {
Packit 06404a
    int **couple_bundle=alloca(sizeof(*couple_bundle)*vi->channels);
Packit 06404a
    int *zerobundle=alloca(sizeof(*zerobundle)*vi->channels);
Packit 06404a
Packit 06404a
    for(k=(vorbis_bitrate_managed(vb)?0:PACKETBLOBS/2);
Packit 06404a
        k<=(vorbis_bitrate_managed(vb)?PACKETBLOBS-1:PACKETBLOBS/2);
Packit 06404a
        k++){
Packit 06404a
      oggpack_buffer *opb=vbi->packetblob[k];
Packit 06404a
Packit 06404a
      /* start out our new packet blob with packet type and mode */
Packit 06404a
      /* Encode the packet type */
Packit 06404a
      oggpack_write(opb,0,1);
Packit 06404a
      /* Encode the modenumber */
Packit 06404a
      /* Encode frame mode, pre,post windowsize, then dispatch */
Packit 06404a
      oggpack_write(opb,modenumber,b->modebits);
Packit 06404a
      if(vb->W){
Packit 06404a
        oggpack_write(opb,vb->lW,1);
Packit 06404a
        oggpack_write(opb,vb->nW,1);
Packit 06404a
      }
Packit 06404a
Packit 06404a
      /* encode floor, compute masking curve, sep out residue */
Packit 06404a
      for(i=0;i<vi->channels;i++){
Packit 06404a
        int submap=info->chmuxlist[i];
Packit 06404a
        int *ilogmask=iwork[i];
Packit 06404a
Packit 06404a
        nonzero[i]=floor1_encode(opb,vb,b->flr[info->floorsubmap[submap]],
Packit 06404a
                                 floor_posts[i][k],
Packit 06404a
                                 ilogmask);
Packit 06404a
#if 0
Packit 06404a
        {
Packit 06404a
          char buf[80];
Packit 06404a
          sprintf(buf,"maskI%c%d",i?'R':'L',k);
Packit 06404a
          float work[n/2];
Packit 06404a
          for(j=0;j
Packit 06404a
            work[j]=FLOOR1_fromdB_LOOKUP[iwork[i][j]];
Packit 06404a
          _analysis_output(buf,seq,work,n/2,1,1,0);
Packit 06404a
        }
Packit 06404a
#endif
Packit 06404a
      }
Packit 06404a
Packit 06404a
      /* our iteration is now based on masking curve, not prequant and
Packit 06404a
         coupling.  Only one prequant/coupling step */
Packit 06404a
Packit 06404a
      /* quantize/couple */
Packit 06404a
      /* incomplete implementation that assumes the tree is all depth
Packit 06404a
         one, or no tree at all */
Packit 06404a
      _vp_couple_quantize_normalize(k,
Packit 06404a
                                    &ci->psy_g_param,
Packit 06404a
                                    psy_look,
Packit 06404a
                                    info,
Packit 06404a
                                    gmdct,
Packit 06404a
                                    iwork,
Packit 06404a
                                    nonzero,
Packit 06404a
                                    ci->psy_g_param.sliding_lowpass[vb->W][k],
Packit 06404a
                                    vi->channels);
Packit 06404a
Packit 06404a
#if 0
Packit 06404a
      for(i=0;i<vi->channels;i++){
Packit 06404a
        char buf[80];
Packit 06404a
        sprintf(buf,"res%c%d",i?'R':'L',k);
Packit 06404a
        float work[n/2];
Packit 06404a
        for(j=0;j
Packit 06404a
          work[j]=iwork[i][j];
Packit 06404a
        _analysis_output(buf,seq,work,n/2,1,0,0);
Packit 06404a
      }
Packit 06404a
#endif
Packit 06404a
Packit 06404a
      /* classify and encode by submap */
Packit 06404a
      for(i=0;i<info->submaps;i++){
Packit 06404a
        int ch_in_bundle=0;
Packit 06404a
        long **classifications;
Packit 06404a
        int resnum=info->residuesubmap[i];
Packit 06404a
Packit 06404a
        for(j=0;j<vi->channels;j++){
Packit 06404a
          if(info->chmuxlist[j]==i){
Packit 06404a
            zerobundle[ch_in_bundle]=0;
Packit 06404a
            if(nonzero[j])zerobundle[ch_in_bundle]=1;
Packit 06404a
            couple_bundle[ch_in_bundle++]=iwork[j];
Packit 06404a
          }
Packit 06404a
        }
Packit 06404a
Packit 06404a
        classifications=_residue_P[ci->residue_type[resnum]]->
Packit 06404a
          class(vb,b->residue[resnum],couple_bundle,zerobundle,ch_in_bundle);
Packit 06404a
Packit 06404a
        ch_in_bundle=0;
Packit 06404a
        for(j=0;j<vi->channels;j++)
Packit 06404a
          if(info->chmuxlist[j]==i)
Packit 06404a
            couple_bundle[ch_in_bundle++]=iwork[j];
Packit 06404a
Packit 06404a
        _residue_P[ci->residue_type[resnum]]->
Packit 06404a
          forward(opb,vb,b->residue[resnum],
Packit 06404a
                  couple_bundle,zerobundle,ch_in_bundle,classifications,i);
Packit 06404a
      }
Packit 06404a
Packit 06404a
      /* ok, done encoding.  Next protopacket. */
Packit 06404a
    }
Packit 06404a
Packit 06404a
  }
Packit 06404a
Packit 06404a
#if 0
Packit 06404a
  seq++;
Packit 06404a
  total+=ci->blocksizes[vb->W]/4+ci->blocksizes[vb->nW]/4;
Packit 06404a
#endif
Packit 06404a
  return(0);
Packit 06404a
}
Packit 06404a
Packit 06404a
static int mapping0_inverse(vorbis_block *vb,vorbis_info_mapping *l){
Packit 06404a
  vorbis_dsp_state     *vd=vb->vd;
Packit 06404a
  vorbis_info          *vi=vd->vi;
Packit 06404a
  codec_setup_info     *ci=vi->codec_setup;
Packit 06404a
  private_state        *b=vd->backend_state;
Packit 06404a
  vorbis_info_mapping0 *info=(vorbis_info_mapping0 *)l;
Packit 06404a
Packit 06404a
  int                   i,j;
Packit 06404a
  long                  n=vb->pcmend=ci->blocksizes[vb->W];
Packit 06404a
Packit 06404a
  float **pcmbundle=alloca(sizeof(*pcmbundle)*vi->channels);
Packit 06404a
  int    *zerobundle=alloca(sizeof(*zerobundle)*vi->channels);
Packit 06404a
Packit 06404a
  int   *nonzero  =alloca(sizeof(*nonzero)*vi->channels);
Packit 06404a
  void **floormemo=alloca(sizeof(*floormemo)*vi->channels);
Packit 06404a
Packit 06404a
  /* recover the spectral envelope; store it in the PCM vector for now */
Packit 06404a
  for(i=0;i<vi->channels;i++){
Packit 06404a
    int submap=info->chmuxlist[i];
Packit 06404a
    floormemo[i]=_floor_P[ci->floor_type[info->floorsubmap[submap]]]->
Packit 06404a
      inverse1(vb,b->flr[info->floorsubmap[submap]]);
Packit 06404a
    if(floormemo[i])
Packit 06404a
      nonzero[i]=1;
Packit 06404a
    else
Packit 06404a
      nonzero[i]=0;
Packit 06404a
    memset(vb->pcm[i],0,sizeof(*vb->pcm[i])*n/2);
Packit 06404a
  }
Packit 06404a
Packit 06404a
  /* channel coupling can 'dirty' the nonzero listing */
Packit 06404a
  for(i=0;i<info->coupling_steps;i++){
Packit 06404a
    if(nonzero[info->coupling_mag[i]] ||
Packit 06404a
       nonzero[info->coupling_ang[i]]){
Packit 06404a
      nonzero[info->coupling_mag[i]]=1;
Packit 06404a
      nonzero[info->coupling_ang[i]]=1;
Packit 06404a
    }
Packit 06404a
  }
Packit 06404a
Packit 06404a
  /* recover the residue into our working vectors */
Packit 06404a
  for(i=0;i<info->submaps;i++){
Packit 06404a
    int ch_in_bundle=0;
Packit 06404a
    for(j=0;j<vi->channels;j++){
Packit 06404a
      if(info->chmuxlist[j]==i){
Packit 06404a
        if(nonzero[j])
Packit 06404a
          zerobundle[ch_in_bundle]=1;
Packit 06404a
        else
Packit 06404a
          zerobundle[ch_in_bundle]=0;
Packit 06404a
        pcmbundle[ch_in_bundle++]=vb->pcm[j];
Packit 06404a
      }
Packit 06404a
    }
Packit 06404a
Packit 06404a
    _residue_P[ci->residue_type[info->residuesubmap[i]]]->
Packit 06404a
      inverse(vb,b->residue[info->residuesubmap[i]],
Packit 06404a
              pcmbundle,zerobundle,ch_in_bundle);
Packit 06404a
  }
Packit 06404a
Packit 06404a
  /* channel coupling */
Packit 06404a
  for(i=info->coupling_steps-1;i>=0;i--){
Packit 06404a
    float *pcmM=vb->pcm[info->coupling_mag[i]];
Packit 06404a
    float *pcmA=vb->pcm[info->coupling_ang[i]];
Packit 06404a
Packit 06404a
    for(j=0;j
Packit 06404a
      float mag=pcmM[j];
Packit 06404a
      float ang=pcmA[j];
Packit 06404a
Packit 06404a
      if(mag>0)
Packit 06404a
        if(ang>0){
Packit 06404a
          pcmM[j]=mag;
Packit 06404a
          pcmA[j]=mag-ang;
Packit 06404a
        }else{
Packit 06404a
          pcmA[j]=mag;
Packit 06404a
          pcmM[j]=mag+ang;
Packit 06404a
        }
Packit 06404a
      else
Packit 06404a
        if(ang>0){
Packit 06404a
          pcmM[j]=mag;
Packit 06404a
          pcmA[j]=mag+ang;
Packit 06404a
        }else{
Packit 06404a
          pcmA[j]=mag;
Packit 06404a
          pcmM[j]=mag-ang;
Packit 06404a
        }
Packit 06404a
    }
Packit 06404a
  }
Packit 06404a
Packit 06404a
  /* compute and apply spectral envelope */
Packit 06404a
  for(i=0;i<vi->channels;i++){
Packit 06404a
    float *pcm=vb->pcm[i];
Packit 06404a
    int submap=info->chmuxlist[i];
Packit 06404a
    _floor_P[ci->floor_type[info->floorsubmap[submap]]]->
Packit 06404a
      inverse2(vb,b->flr[info->floorsubmap[submap]],
Packit 06404a
               floormemo[i],pcm);
Packit 06404a
  }
Packit 06404a
Packit 06404a
  /* transform the PCM data; takes PCM vector, vb; modifies PCM vector */
Packit 06404a
  /* only MDCT right now.... */
Packit 06404a
  for(i=0;i<vi->channels;i++){
Packit 06404a
    float *pcm=vb->pcm[i];
Packit 06404a
    mdct_backward(b->transform[vb->W][0],pcm,pcm);
Packit 06404a
  }
Packit 06404a
Packit 06404a
  /* all done! */
Packit 06404a
  return(0);
Packit 06404a
}
Packit 06404a
Packit 06404a
/* export hooks */
Packit 06404a
const vorbis_func_mapping mapping0_exportbundle={
Packit 06404a
  &mapping0_pack,
Packit 06404a
  &mapping0_unpack,
Packit 06404a
  &mapping0_free_info,
Packit 06404a
  &mapping0_forward,
Packit 06404a
  &mapping0_inverse
Packit 06404a
};