annotate src/libvorbis-1.3.3/lib/mapping0.c @ 83:ae30d91d2ffe

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