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