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