annotate src/libvorbis-1.3.3/lib/psy.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: psychoacoustics not including preecho
Chris@1 14 last mod: $Id: psy.c 18077 2011-09-02 02:49:00Z giles $
Chris@1 15
Chris@1 16 ********************************************************************/
Chris@1 17
Chris@1 18 #include <stdlib.h>
Chris@1 19 #include <math.h>
Chris@1 20 #include <string.h>
Chris@1 21 #include "vorbis/codec.h"
Chris@1 22 #include "codec_internal.h"
Chris@1 23
Chris@1 24 #include "masking.h"
Chris@1 25 #include "psy.h"
Chris@1 26 #include "os.h"
Chris@1 27 #include "lpc.h"
Chris@1 28 #include "smallft.h"
Chris@1 29 #include "scales.h"
Chris@1 30 #include "misc.h"
Chris@1 31
Chris@1 32 #define NEGINF -9999.f
Chris@1 33 static const double stereo_threshholds[]={0.0, .5, 1.0, 1.5, 2.5, 4.5, 8.5, 16.5, 9e10};
Chris@1 34 static const double stereo_threshholds_limited[]={0.0, .5, 1.0, 1.5, 2.0, 2.5, 4.5, 8.5, 9e10};
Chris@1 35
Chris@1 36 vorbis_look_psy_global *_vp_global_look(vorbis_info *vi){
Chris@1 37 codec_setup_info *ci=vi->codec_setup;
Chris@1 38 vorbis_info_psy_global *gi=&ci->psy_g_param;
Chris@1 39 vorbis_look_psy_global *look=_ogg_calloc(1,sizeof(*look));
Chris@1 40
Chris@1 41 look->channels=vi->channels;
Chris@1 42
Chris@1 43 look->ampmax=-9999.;
Chris@1 44 look->gi=gi;
Chris@1 45 return(look);
Chris@1 46 }
Chris@1 47
Chris@1 48 void _vp_global_free(vorbis_look_psy_global *look){
Chris@1 49 if(look){
Chris@1 50 memset(look,0,sizeof(*look));
Chris@1 51 _ogg_free(look);
Chris@1 52 }
Chris@1 53 }
Chris@1 54
Chris@1 55 void _vi_gpsy_free(vorbis_info_psy_global *i){
Chris@1 56 if(i){
Chris@1 57 memset(i,0,sizeof(*i));
Chris@1 58 _ogg_free(i);
Chris@1 59 }
Chris@1 60 }
Chris@1 61
Chris@1 62 void _vi_psy_free(vorbis_info_psy *i){
Chris@1 63 if(i){
Chris@1 64 memset(i,0,sizeof(*i));
Chris@1 65 _ogg_free(i);
Chris@1 66 }
Chris@1 67 }
Chris@1 68
Chris@1 69 static void min_curve(float *c,
Chris@1 70 float *c2){
Chris@1 71 int i;
Chris@1 72 for(i=0;i<EHMER_MAX;i++)if(c2[i]<c[i])c[i]=c2[i];
Chris@1 73 }
Chris@1 74 static void max_curve(float *c,
Chris@1 75 float *c2){
Chris@1 76 int i;
Chris@1 77 for(i=0;i<EHMER_MAX;i++)if(c2[i]>c[i])c[i]=c2[i];
Chris@1 78 }
Chris@1 79
Chris@1 80 static void attenuate_curve(float *c,float att){
Chris@1 81 int i;
Chris@1 82 for(i=0;i<EHMER_MAX;i++)
Chris@1 83 c[i]+=att;
Chris@1 84 }
Chris@1 85
Chris@1 86 static float ***setup_tone_curves(float curveatt_dB[P_BANDS],float binHz,int n,
Chris@1 87 float center_boost, float center_decay_rate){
Chris@1 88 int i,j,k,m;
Chris@1 89 float ath[EHMER_MAX];
Chris@1 90 float workc[P_BANDS][P_LEVELS][EHMER_MAX];
Chris@1 91 float athc[P_LEVELS][EHMER_MAX];
Chris@1 92 float *brute_buffer=alloca(n*sizeof(*brute_buffer));
Chris@1 93
Chris@1 94 float ***ret=_ogg_malloc(sizeof(*ret)*P_BANDS);
Chris@1 95
Chris@1 96 memset(workc,0,sizeof(workc));
Chris@1 97
Chris@1 98 for(i=0;i<P_BANDS;i++){
Chris@1 99 /* we add back in the ATH to avoid low level curves falling off to
Chris@1 100 -infinity and unnecessarily cutting off high level curves in the
Chris@1 101 curve limiting (last step). */
Chris@1 102
Chris@1 103 /* A half-band's settings must be valid over the whole band, and
Chris@1 104 it's better to mask too little than too much */
Chris@1 105 int ath_offset=i*4;
Chris@1 106 for(j=0;j<EHMER_MAX;j++){
Chris@1 107 float min=999.;
Chris@1 108 for(k=0;k<4;k++)
Chris@1 109 if(j+k+ath_offset<MAX_ATH){
Chris@1 110 if(min>ATH[j+k+ath_offset])min=ATH[j+k+ath_offset];
Chris@1 111 }else{
Chris@1 112 if(min>ATH[MAX_ATH-1])min=ATH[MAX_ATH-1];
Chris@1 113 }
Chris@1 114 ath[j]=min;
Chris@1 115 }
Chris@1 116
Chris@1 117 /* copy curves into working space, replicate the 50dB curve to 30
Chris@1 118 and 40, replicate the 100dB curve to 110 */
Chris@1 119 for(j=0;j<6;j++)
Chris@1 120 memcpy(workc[i][j+2],tonemasks[i][j],EHMER_MAX*sizeof(*tonemasks[i][j]));
Chris@1 121 memcpy(workc[i][0],tonemasks[i][0],EHMER_MAX*sizeof(*tonemasks[i][0]));
Chris@1 122 memcpy(workc[i][1],tonemasks[i][0],EHMER_MAX*sizeof(*tonemasks[i][0]));
Chris@1 123
Chris@1 124 /* apply centered curve boost/decay */
Chris@1 125 for(j=0;j<P_LEVELS;j++){
Chris@1 126 for(k=0;k<EHMER_MAX;k++){
Chris@1 127 float adj=center_boost+abs(EHMER_OFFSET-k)*center_decay_rate;
Chris@1 128 if(adj<0. && center_boost>0)adj=0.;
Chris@1 129 if(adj>0. && center_boost<0)adj=0.;
Chris@1 130 workc[i][j][k]+=adj;
Chris@1 131 }
Chris@1 132 }
Chris@1 133
Chris@1 134 /* normalize curves so the driving amplitude is 0dB */
Chris@1 135 /* make temp curves with the ATH overlayed */
Chris@1 136 for(j=0;j<P_LEVELS;j++){
Chris@1 137 attenuate_curve(workc[i][j],curveatt_dB[i]+100.-(j<2?2:j)*10.-P_LEVEL_0);
Chris@1 138 memcpy(athc[j],ath,EHMER_MAX*sizeof(**athc));
Chris@1 139 attenuate_curve(athc[j],+100.-j*10.f-P_LEVEL_0);
Chris@1 140 max_curve(athc[j],workc[i][j]);
Chris@1 141 }
Chris@1 142
Chris@1 143 /* Now limit the louder curves.
Chris@1 144
Chris@1 145 the idea is this: We don't know what the playback attenuation
Chris@1 146 will be; 0dB SL moves every time the user twiddles the volume
Chris@1 147 knob. So that means we have to use a single 'most pessimal' curve
Chris@1 148 for all masking amplitudes, right? Wrong. The *loudest* sound
Chris@1 149 can be in (we assume) a range of ...+100dB] SL. However, sounds
Chris@1 150 20dB down will be in a range ...+80], 40dB down is from ...+60],
Chris@1 151 etc... */
Chris@1 152
Chris@1 153 for(j=1;j<P_LEVELS;j++){
Chris@1 154 min_curve(athc[j],athc[j-1]);
Chris@1 155 min_curve(workc[i][j],athc[j]);
Chris@1 156 }
Chris@1 157 }
Chris@1 158
Chris@1 159 for(i=0;i<P_BANDS;i++){
Chris@1 160 int hi_curve,lo_curve,bin;
Chris@1 161 ret[i]=_ogg_malloc(sizeof(**ret)*P_LEVELS);
Chris@1 162
Chris@1 163 /* low frequency curves are measured with greater resolution than
Chris@1 164 the MDCT/FFT will actually give us; we want the curve applied
Chris@1 165 to the tone data to be pessimistic and thus apply the minimum
Chris@1 166 masking possible for a given bin. That means that a single bin
Chris@1 167 could span more than one octave and that the curve will be a
Chris@1 168 composite of multiple octaves. It also may mean that a single
Chris@1 169 bin may span > an eighth of an octave and that the eighth
Chris@1 170 octave values may also be composited. */
Chris@1 171
Chris@1 172 /* which octave curves will we be compositing? */
Chris@1 173 bin=floor(fromOC(i*.5)/binHz);
Chris@1 174 lo_curve= ceil(toOC(bin*binHz+1)*2);
Chris@1 175 hi_curve= floor(toOC((bin+1)*binHz)*2);
Chris@1 176 if(lo_curve>i)lo_curve=i;
Chris@1 177 if(lo_curve<0)lo_curve=0;
Chris@1 178 if(hi_curve>=P_BANDS)hi_curve=P_BANDS-1;
Chris@1 179
Chris@1 180 for(m=0;m<P_LEVELS;m++){
Chris@1 181 ret[i][m]=_ogg_malloc(sizeof(***ret)*(EHMER_MAX+2));
Chris@1 182
Chris@1 183 for(j=0;j<n;j++)brute_buffer[j]=999.;
Chris@1 184
Chris@1 185 /* render the curve into bins, then pull values back into curve.
Chris@1 186 The point is that any inherent subsampling aliasing results in
Chris@1 187 a safe minimum */
Chris@1 188 for(k=lo_curve;k<=hi_curve;k++){
Chris@1 189 int l=0;
Chris@1 190
Chris@1 191 for(j=0;j<EHMER_MAX;j++){
Chris@1 192 int lo_bin= fromOC(j*.125+k*.5-2.0625)/binHz;
Chris@1 193 int hi_bin= fromOC(j*.125+k*.5-1.9375)/binHz+1;
Chris@1 194
Chris@1 195 if(lo_bin<0)lo_bin=0;
Chris@1 196 if(lo_bin>n)lo_bin=n;
Chris@1 197 if(lo_bin<l)l=lo_bin;
Chris@1 198 if(hi_bin<0)hi_bin=0;
Chris@1 199 if(hi_bin>n)hi_bin=n;
Chris@1 200
Chris@1 201 for(;l<hi_bin && l<n;l++)
Chris@1 202 if(brute_buffer[l]>workc[k][m][j])
Chris@1 203 brute_buffer[l]=workc[k][m][j];
Chris@1 204 }
Chris@1 205
Chris@1 206 for(;l<n;l++)
Chris@1 207 if(brute_buffer[l]>workc[k][m][EHMER_MAX-1])
Chris@1 208 brute_buffer[l]=workc[k][m][EHMER_MAX-1];
Chris@1 209
Chris@1 210 }
Chris@1 211
Chris@1 212 /* be equally paranoid about being valid up to next half ocatve */
Chris@1 213 if(i+1<P_BANDS){
Chris@1 214 int l=0;
Chris@1 215 k=i+1;
Chris@1 216 for(j=0;j<EHMER_MAX;j++){
Chris@1 217 int lo_bin= fromOC(j*.125+i*.5-2.0625)/binHz;
Chris@1 218 int hi_bin= fromOC(j*.125+i*.5-1.9375)/binHz+1;
Chris@1 219
Chris@1 220 if(lo_bin<0)lo_bin=0;
Chris@1 221 if(lo_bin>n)lo_bin=n;
Chris@1 222 if(lo_bin<l)l=lo_bin;
Chris@1 223 if(hi_bin<0)hi_bin=0;
Chris@1 224 if(hi_bin>n)hi_bin=n;
Chris@1 225
Chris@1 226 for(;l<hi_bin && l<n;l++)
Chris@1 227 if(brute_buffer[l]>workc[k][m][j])
Chris@1 228 brute_buffer[l]=workc[k][m][j];
Chris@1 229 }
Chris@1 230
Chris@1 231 for(;l<n;l++)
Chris@1 232 if(brute_buffer[l]>workc[k][m][EHMER_MAX-1])
Chris@1 233 brute_buffer[l]=workc[k][m][EHMER_MAX-1];
Chris@1 234
Chris@1 235 }
Chris@1 236
Chris@1 237
Chris@1 238 for(j=0;j<EHMER_MAX;j++){
Chris@1 239 int bin=fromOC(j*.125+i*.5-2.)/binHz;
Chris@1 240 if(bin<0){
Chris@1 241 ret[i][m][j+2]=-999.;
Chris@1 242 }else{
Chris@1 243 if(bin>=n){
Chris@1 244 ret[i][m][j+2]=-999.;
Chris@1 245 }else{
Chris@1 246 ret[i][m][j+2]=brute_buffer[bin];
Chris@1 247 }
Chris@1 248 }
Chris@1 249 }
Chris@1 250
Chris@1 251 /* add fenceposts */
Chris@1 252 for(j=0;j<EHMER_OFFSET;j++)
Chris@1 253 if(ret[i][m][j+2]>-200.f)break;
Chris@1 254 ret[i][m][0]=j;
Chris@1 255
Chris@1 256 for(j=EHMER_MAX-1;j>EHMER_OFFSET+1;j--)
Chris@1 257 if(ret[i][m][j+2]>-200.f)
Chris@1 258 break;
Chris@1 259 ret[i][m][1]=j;
Chris@1 260
Chris@1 261 }
Chris@1 262 }
Chris@1 263
Chris@1 264 return(ret);
Chris@1 265 }
Chris@1 266
Chris@1 267 void _vp_psy_init(vorbis_look_psy *p,vorbis_info_psy *vi,
Chris@1 268 vorbis_info_psy_global *gi,int n,long rate){
Chris@1 269 long i,j,lo=-99,hi=1;
Chris@1 270 long maxoc;
Chris@1 271 memset(p,0,sizeof(*p));
Chris@1 272
Chris@1 273 p->eighth_octave_lines=gi->eighth_octave_lines;
Chris@1 274 p->shiftoc=rint(log(gi->eighth_octave_lines*8.f)/log(2.f))-1;
Chris@1 275
Chris@1 276 p->firstoc=toOC(.25f*rate*.5/n)*(1<<(p->shiftoc+1))-gi->eighth_octave_lines;
Chris@1 277 maxoc=toOC((n+.25f)*rate*.5/n)*(1<<(p->shiftoc+1))+.5f;
Chris@1 278 p->total_octave_lines=maxoc-p->firstoc+1;
Chris@1 279 p->ath=_ogg_malloc(n*sizeof(*p->ath));
Chris@1 280
Chris@1 281 p->octave=_ogg_malloc(n*sizeof(*p->octave));
Chris@1 282 p->bark=_ogg_malloc(n*sizeof(*p->bark));
Chris@1 283 p->vi=vi;
Chris@1 284 p->n=n;
Chris@1 285 p->rate=rate;
Chris@1 286
Chris@1 287 /* AoTuV HF weighting */
Chris@1 288 p->m_val = 1.;
Chris@1 289 if(rate < 26000) p->m_val = 0;
Chris@1 290 else if(rate < 38000) p->m_val = .94; /* 32kHz */
Chris@1 291 else if(rate > 46000) p->m_val = 1.275; /* 48kHz */
Chris@1 292
Chris@1 293 /* set up the lookups for a given blocksize and sample rate */
Chris@1 294
Chris@1 295 for(i=0,j=0;i<MAX_ATH-1;i++){
Chris@1 296 int endpos=rint(fromOC((i+1)*.125-2.)*2*n/rate);
Chris@1 297 float base=ATH[i];
Chris@1 298 if(j<endpos){
Chris@1 299 float delta=(ATH[i+1]-base)/(endpos-j);
Chris@1 300 for(;j<endpos && j<n;j++){
Chris@1 301 p->ath[j]=base+100.;
Chris@1 302 base+=delta;
Chris@1 303 }
Chris@1 304 }
Chris@1 305 }
Chris@1 306
Chris@1 307 for(;j<n;j++){
Chris@1 308 p->ath[j]=p->ath[j-1];
Chris@1 309 }
Chris@1 310
Chris@1 311 for(i=0;i<n;i++){
Chris@1 312 float bark=toBARK(rate/(2*n)*i);
Chris@1 313
Chris@1 314 for(;lo+vi->noisewindowlomin<i &&
Chris@1 315 toBARK(rate/(2*n)*lo)<(bark-vi->noisewindowlo);lo++);
Chris@1 316
Chris@1 317 for(;hi<=n && (hi<i+vi->noisewindowhimin ||
Chris@1 318 toBARK(rate/(2*n)*hi)<(bark+vi->noisewindowhi));hi++);
Chris@1 319
Chris@1 320 p->bark[i]=((lo-1)<<16)+(hi-1);
Chris@1 321
Chris@1 322 }
Chris@1 323
Chris@1 324 for(i=0;i<n;i++)
Chris@1 325 p->octave[i]=toOC((i+.25f)*.5*rate/n)*(1<<(p->shiftoc+1))+.5f;
Chris@1 326
Chris@1 327 p->tonecurves=setup_tone_curves(vi->toneatt,rate*.5/n,n,
Chris@1 328 vi->tone_centerboost,vi->tone_decay);
Chris@1 329
Chris@1 330 /* set up rolling noise median */
Chris@1 331 p->noiseoffset=_ogg_malloc(P_NOISECURVES*sizeof(*p->noiseoffset));
Chris@1 332 for(i=0;i<P_NOISECURVES;i++)
Chris@1 333 p->noiseoffset[i]=_ogg_malloc(n*sizeof(**p->noiseoffset));
Chris@1 334
Chris@1 335 for(i=0;i<n;i++){
Chris@1 336 float halfoc=toOC((i+.5)*rate/(2.*n))*2.;
Chris@1 337 int inthalfoc;
Chris@1 338 float del;
Chris@1 339
Chris@1 340 if(halfoc<0)halfoc=0;
Chris@1 341 if(halfoc>=P_BANDS-1)halfoc=P_BANDS-1;
Chris@1 342 inthalfoc=(int)halfoc;
Chris@1 343 del=halfoc-inthalfoc;
Chris@1 344
Chris@1 345 for(j=0;j<P_NOISECURVES;j++)
Chris@1 346 p->noiseoffset[j][i]=
Chris@1 347 p->vi->noiseoff[j][inthalfoc]*(1.-del) +
Chris@1 348 p->vi->noiseoff[j][inthalfoc+1]*del;
Chris@1 349
Chris@1 350 }
Chris@1 351 #if 0
Chris@1 352 {
Chris@1 353 static int ls=0;
Chris@1 354 _analysis_output_always("noiseoff0",ls,p->noiseoffset[0],n,1,0,0);
Chris@1 355 _analysis_output_always("noiseoff1",ls,p->noiseoffset[1],n,1,0,0);
Chris@1 356 _analysis_output_always("noiseoff2",ls++,p->noiseoffset[2],n,1,0,0);
Chris@1 357 }
Chris@1 358 #endif
Chris@1 359 }
Chris@1 360
Chris@1 361 void _vp_psy_clear(vorbis_look_psy *p){
Chris@1 362 int i,j;
Chris@1 363 if(p){
Chris@1 364 if(p->ath)_ogg_free(p->ath);
Chris@1 365 if(p->octave)_ogg_free(p->octave);
Chris@1 366 if(p->bark)_ogg_free(p->bark);
Chris@1 367 if(p->tonecurves){
Chris@1 368 for(i=0;i<P_BANDS;i++){
Chris@1 369 for(j=0;j<P_LEVELS;j++){
Chris@1 370 _ogg_free(p->tonecurves[i][j]);
Chris@1 371 }
Chris@1 372 _ogg_free(p->tonecurves[i]);
Chris@1 373 }
Chris@1 374 _ogg_free(p->tonecurves);
Chris@1 375 }
Chris@1 376 if(p->noiseoffset){
Chris@1 377 for(i=0;i<P_NOISECURVES;i++){
Chris@1 378 _ogg_free(p->noiseoffset[i]);
Chris@1 379 }
Chris@1 380 _ogg_free(p->noiseoffset);
Chris@1 381 }
Chris@1 382 memset(p,0,sizeof(*p));
Chris@1 383 }
Chris@1 384 }
Chris@1 385
Chris@1 386 /* octave/(8*eighth_octave_lines) x scale and dB y scale */
Chris@1 387 static void seed_curve(float *seed,
Chris@1 388 const float **curves,
Chris@1 389 float amp,
Chris@1 390 int oc, int n,
Chris@1 391 int linesper,float dBoffset){
Chris@1 392 int i,post1;
Chris@1 393 int seedptr;
Chris@1 394 const float *posts,*curve;
Chris@1 395
Chris@1 396 int choice=(int)((amp+dBoffset-P_LEVEL_0)*.1f);
Chris@1 397 choice=max(choice,0);
Chris@1 398 choice=min(choice,P_LEVELS-1);
Chris@1 399 posts=curves[choice];
Chris@1 400 curve=posts+2;
Chris@1 401 post1=(int)posts[1];
Chris@1 402 seedptr=oc+(posts[0]-EHMER_OFFSET)*linesper-(linesper>>1);
Chris@1 403
Chris@1 404 for(i=posts[0];i<post1;i++){
Chris@1 405 if(seedptr>0){
Chris@1 406 float lin=amp+curve[i];
Chris@1 407 if(seed[seedptr]<lin)seed[seedptr]=lin;
Chris@1 408 }
Chris@1 409 seedptr+=linesper;
Chris@1 410 if(seedptr>=n)break;
Chris@1 411 }
Chris@1 412 }
Chris@1 413
Chris@1 414 static void seed_loop(vorbis_look_psy *p,
Chris@1 415 const float ***curves,
Chris@1 416 const float *f,
Chris@1 417 const float *flr,
Chris@1 418 float *seed,
Chris@1 419 float specmax){
Chris@1 420 vorbis_info_psy *vi=p->vi;
Chris@1 421 long n=p->n,i;
Chris@1 422 float dBoffset=vi->max_curve_dB-specmax;
Chris@1 423
Chris@1 424 /* prime the working vector with peak values */
Chris@1 425
Chris@1 426 for(i=0;i<n;i++){
Chris@1 427 float max=f[i];
Chris@1 428 long oc=p->octave[i];
Chris@1 429 while(i+1<n && p->octave[i+1]==oc){
Chris@1 430 i++;
Chris@1 431 if(f[i]>max)max=f[i];
Chris@1 432 }
Chris@1 433
Chris@1 434 if(max+6.f>flr[i]){
Chris@1 435 oc=oc>>p->shiftoc;
Chris@1 436
Chris@1 437 if(oc>=P_BANDS)oc=P_BANDS-1;
Chris@1 438 if(oc<0)oc=0;
Chris@1 439
Chris@1 440 seed_curve(seed,
Chris@1 441 curves[oc],
Chris@1 442 max,
Chris@1 443 p->octave[i]-p->firstoc,
Chris@1 444 p->total_octave_lines,
Chris@1 445 p->eighth_octave_lines,
Chris@1 446 dBoffset);
Chris@1 447 }
Chris@1 448 }
Chris@1 449 }
Chris@1 450
Chris@1 451 static void seed_chase(float *seeds, int linesper, long n){
Chris@1 452 long *posstack=alloca(n*sizeof(*posstack));
Chris@1 453 float *ampstack=alloca(n*sizeof(*ampstack));
Chris@1 454 long stack=0;
Chris@1 455 long pos=0;
Chris@1 456 long i;
Chris@1 457
Chris@1 458 for(i=0;i<n;i++){
Chris@1 459 if(stack<2){
Chris@1 460 posstack[stack]=i;
Chris@1 461 ampstack[stack++]=seeds[i];
Chris@1 462 }else{
Chris@1 463 while(1){
Chris@1 464 if(seeds[i]<ampstack[stack-1]){
Chris@1 465 posstack[stack]=i;
Chris@1 466 ampstack[stack++]=seeds[i];
Chris@1 467 break;
Chris@1 468 }else{
Chris@1 469 if(i<posstack[stack-1]+linesper){
Chris@1 470 if(stack>1 && ampstack[stack-1]<=ampstack[stack-2] &&
Chris@1 471 i<posstack[stack-2]+linesper){
Chris@1 472 /* we completely overlap, making stack-1 irrelevant. pop it */
Chris@1 473 stack--;
Chris@1 474 continue;
Chris@1 475 }
Chris@1 476 }
Chris@1 477 posstack[stack]=i;
Chris@1 478 ampstack[stack++]=seeds[i];
Chris@1 479 break;
Chris@1 480
Chris@1 481 }
Chris@1 482 }
Chris@1 483 }
Chris@1 484 }
Chris@1 485
Chris@1 486 /* the stack now contains only the positions that are relevant. Scan
Chris@1 487 'em straight through */
Chris@1 488
Chris@1 489 for(i=0;i<stack;i++){
Chris@1 490 long endpos;
Chris@1 491 if(i<stack-1 && ampstack[i+1]>ampstack[i]){
Chris@1 492 endpos=posstack[i+1];
Chris@1 493 }else{
Chris@1 494 endpos=posstack[i]+linesper+1; /* +1 is important, else bin 0 is
Chris@1 495 discarded in short frames */
Chris@1 496 }
Chris@1 497 if(endpos>n)endpos=n;
Chris@1 498 for(;pos<endpos;pos++)
Chris@1 499 seeds[pos]=ampstack[i];
Chris@1 500 }
Chris@1 501
Chris@1 502 /* there. Linear time. I now remember this was on a problem set I
Chris@1 503 had in Grad Skool... I didn't solve it at the time ;-) */
Chris@1 504
Chris@1 505 }
Chris@1 506
Chris@1 507 /* bleaugh, this is more complicated than it needs to be */
Chris@1 508 #include<stdio.h>
Chris@1 509 static void max_seeds(vorbis_look_psy *p,
Chris@1 510 float *seed,
Chris@1 511 float *flr){
Chris@1 512 long n=p->total_octave_lines;
Chris@1 513 int linesper=p->eighth_octave_lines;
Chris@1 514 long linpos=0;
Chris@1 515 long pos;
Chris@1 516
Chris@1 517 seed_chase(seed,linesper,n); /* for masking */
Chris@1 518
Chris@1 519 pos=p->octave[0]-p->firstoc-(linesper>>1);
Chris@1 520
Chris@1 521 while(linpos+1<p->n){
Chris@1 522 float minV=seed[pos];
Chris@1 523 long end=((p->octave[linpos]+p->octave[linpos+1])>>1)-p->firstoc;
Chris@1 524 if(minV>p->vi->tone_abs_limit)minV=p->vi->tone_abs_limit;
Chris@1 525 while(pos+1<=end){
Chris@1 526 pos++;
Chris@1 527 if((seed[pos]>NEGINF && seed[pos]<minV) || minV==NEGINF)
Chris@1 528 minV=seed[pos];
Chris@1 529 }
Chris@1 530
Chris@1 531 end=pos+p->firstoc;
Chris@1 532 for(;linpos<p->n && p->octave[linpos]<=end;linpos++)
Chris@1 533 if(flr[linpos]<minV)flr[linpos]=minV;
Chris@1 534 }
Chris@1 535
Chris@1 536 {
Chris@1 537 float minV=seed[p->total_octave_lines-1];
Chris@1 538 for(;linpos<p->n;linpos++)
Chris@1 539 if(flr[linpos]<minV)flr[linpos]=minV;
Chris@1 540 }
Chris@1 541
Chris@1 542 }
Chris@1 543
Chris@1 544 static void bark_noise_hybridmp(int n,const long *b,
Chris@1 545 const float *f,
Chris@1 546 float *noise,
Chris@1 547 const float offset,
Chris@1 548 const int fixed){
Chris@1 549
Chris@1 550 float *N=alloca(n*sizeof(*N));
Chris@1 551 float *X=alloca(n*sizeof(*N));
Chris@1 552 float *XX=alloca(n*sizeof(*N));
Chris@1 553 float *Y=alloca(n*sizeof(*N));
Chris@1 554 float *XY=alloca(n*sizeof(*N));
Chris@1 555
Chris@1 556 float tN, tX, tXX, tY, tXY;
Chris@1 557 int i;
Chris@1 558
Chris@1 559 int lo, hi;
Chris@1 560 float R=0.f;
Chris@1 561 float A=0.f;
Chris@1 562 float B=0.f;
Chris@1 563 float D=1.f;
Chris@1 564 float w, x, y;
Chris@1 565
Chris@1 566 tN = tX = tXX = tY = tXY = 0.f;
Chris@1 567
Chris@1 568 y = f[0] + offset;
Chris@1 569 if (y < 1.f) y = 1.f;
Chris@1 570
Chris@1 571 w = y * y * .5;
Chris@1 572
Chris@1 573 tN += w;
Chris@1 574 tX += w;
Chris@1 575 tY += w * y;
Chris@1 576
Chris@1 577 N[0] = tN;
Chris@1 578 X[0] = tX;
Chris@1 579 XX[0] = tXX;
Chris@1 580 Y[0] = tY;
Chris@1 581 XY[0] = tXY;
Chris@1 582
Chris@1 583 for (i = 1, x = 1.f; i < n; i++, x += 1.f) {
Chris@1 584
Chris@1 585 y = f[i] + offset;
Chris@1 586 if (y < 1.f) y = 1.f;
Chris@1 587
Chris@1 588 w = y * y;
Chris@1 589
Chris@1 590 tN += w;
Chris@1 591 tX += w * x;
Chris@1 592 tXX += w * x * x;
Chris@1 593 tY += w * y;
Chris@1 594 tXY += w * x * y;
Chris@1 595
Chris@1 596 N[i] = tN;
Chris@1 597 X[i] = tX;
Chris@1 598 XX[i] = tXX;
Chris@1 599 Y[i] = tY;
Chris@1 600 XY[i] = tXY;
Chris@1 601 }
Chris@1 602
Chris@1 603 for (i = 0, x = 0.f;; i++, x += 1.f) {
Chris@1 604
Chris@1 605 lo = b[i] >> 16;
Chris@1 606 if( lo>=0 ) break;
Chris@1 607 hi = b[i] & 0xffff;
Chris@1 608
Chris@1 609 tN = N[hi] + N[-lo];
Chris@1 610 tX = X[hi] - X[-lo];
Chris@1 611 tXX = XX[hi] + XX[-lo];
Chris@1 612 tY = Y[hi] + Y[-lo];
Chris@1 613 tXY = XY[hi] - XY[-lo];
Chris@1 614
Chris@1 615 A = tY * tXX - tX * tXY;
Chris@1 616 B = tN * tXY - tX * tY;
Chris@1 617 D = tN * tXX - tX * tX;
Chris@1 618 R = (A + x * B) / D;
Chris@1 619 if (R < 0.f)
Chris@1 620 R = 0.f;
Chris@1 621
Chris@1 622 noise[i] = R - offset;
Chris@1 623 }
Chris@1 624
Chris@1 625 for ( ;; i++, x += 1.f) {
Chris@1 626
Chris@1 627 lo = b[i] >> 16;
Chris@1 628 hi = b[i] & 0xffff;
Chris@1 629 if(hi>=n)break;
Chris@1 630
Chris@1 631 tN = N[hi] - N[lo];
Chris@1 632 tX = X[hi] - X[lo];
Chris@1 633 tXX = XX[hi] - XX[lo];
Chris@1 634 tY = Y[hi] - Y[lo];
Chris@1 635 tXY = XY[hi] - XY[lo];
Chris@1 636
Chris@1 637 A = tY * tXX - tX * tXY;
Chris@1 638 B = tN * tXY - tX * tY;
Chris@1 639 D = tN * tXX - tX * tX;
Chris@1 640 R = (A + x * B) / D;
Chris@1 641 if (R < 0.f) R = 0.f;
Chris@1 642
Chris@1 643 noise[i] = R - offset;
Chris@1 644 }
Chris@1 645 for ( ; i < n; i++, x += 1.f) {
Chris@1 646
Chris@1 647 R = (A + x * B) / D;
Chris@1 648 if (R < 0.f) R = 0.f;
Chris@1 649
Chris@1 650 noise[i] = R - offset;
Chris@1 651 }
Chris@1 652
Chris@1 653 if (fixed <= 0) return;
Chris@1 654
Chris@1 655 for (i = 0, x = 0.f;; i++, x += 1.f) {
Chris@1 656 hi = i + fixed / 2;
Chris@1 657 lo = hi - fixed;
Chris@1 658 if(lo>=0)break;
Chris@1 659
Chris@1 660 tN = N[hi] + N[-lo];
Chris@1 661 tX = X[hi] - X[-lo];
Chris@1 662 tXX = XX[hi] + XX[-lo];
Chris@1 663 tY = Y[hi] + Y[-lo];
Chris@1 664 tXY = XY[hi] - XY[-lo];
Chris@1 665
Chris@1 666
Chris@1 667 A = tY * tXX - tX * tXY;
Chris@1 668 B = tN * tXY - tX * tY;
Chris@1 669 D = tN * tXX - tX * tX;
Chris@1 670 R = (A + x * B) / D;
Chris@1 671
Chris@1 672 if (R - offset < noise[i]) noise[i] = R - offset;
Chris@1 673 }
Chris@1 674 for ( ;; i++, x += 1.f) {
Chris@1 675
Chris@1 676 hi = i + fixed / 2;
Chris@1 677 lo = hi - fixed;
Chris@1 678 if(hi>=n)break;
Chris@1 679
Chris@1 680 tN = N[hi] - N[lo];
Chris@1 681 tX = X[hi] - X[lo];
Chris@1 682 tXX = XX[hi] - XX[lo];
Chris@1 683 tY = Y[hi] - Y[lo];
Chris@1 684 tXY = XY[hi] - XY[lo];
Chris@1 685
Chris@1 686 A = tY * tXX - tX * tXY;
Chris@1 687 B = tN * tXY - tX * tY;
Chris@1 688 D = tN * tXX - tX * tX;
Chris@1 689 R = (A + x * B) / D;
Chris@1 690
Chris@1 691 if (R - offset < noise[i]) noise[i] = R - offset;
Chris@1 692 }
Chris@1 693 for ( ; i < n; i++, x += 1.f) {
Chris@1 694 R = (A + x * B) / D;
Chris@1 695 if (R - offset < noise[i]) noise[i] = R - offset;
Chris@1 696 }
Chris@1 697 }
Chris@1 698
Chris@1 699 void _vp_noisemask(vorbis_look_psy *p,
Chris@1 700 float *logmdct,
Chris@1 701 float *logmask){
Chris@1 702
Chris@1 703 int i,n=p->n;
Chris@1 704 float *work=alloca(n*sizeof(*work));
Chris@1 705
Chris@1 706 bark_noise_hybridmp(n,p->bark,logmdct,logmask,
Chris@1 707 140.,-1);
Chris@1 708
Chris@1 709 for(i=0;i<n;i++)work[i]=logmdct[i]-logmask[i];
Chris@1 710
Chris@1 711 bark_noise_hybridmp(n,p->bark,work,logmask,0.,
Chris@1 712 p->vi->noisewindowfixed);
Chris@1 713
Chris@1 714 for(i=0;i<n;i++)work[i]=logmdct[i]-work[i];
Chris@1 715
Chris@1 716 #if 0
Chris@1 717 {
Chris@1 718 static int seq=0;
Chris@1 719
Chris@1 720 float work2[n];
Chris@1 721 for(i=0;i<n;i++){
Chris@1 722 work2[i]=logmask[i]+work[i];
Chris@1 723 }
Chris@1 724
Chris@1 725 if(seq&1)
Chris@1 726 _analysis_output("median2R",seq/2,work,n,1,0,0);
Chris@1 727 else
Chris@1 728 _analysis_output("median2L",seq/2,work,n,1,0,0);
Chris@1 729
Chris@1 730 if(seq&1)
Chris@1 731 _analysis_output("envelope2R",seq/2,work2,n,1,0,0);
Chris@1 732 else
Chris@1 733 _analysis_output("envelope2L",seq/2,work2,n,1,0,0);
Chris@1 734 seq++;
Chris@1 735 }
Chris@1 736 #endif
Chris@1 737
Chris@1 738 for(i=0;i<n;i++){
Chris@1 739 int dB=logmask[i]+.5;
Chris@1 740 if(dB>=NOISE_COMPAND_LEVELS)dB=NOISE_COMPAND_LEVELS-1;
Chris@1 741 if(dB<0)dB=0;
Chris@1 742 logmask[i]= work[i]+p->vi->noisecompand[dB];
Chris@1 743 }
Chris@1 744
Chris@1 745 }
Chris@1 746
Chris@1 747 void _vp_tonemask(vorbis_look_psy *p,
Chris@1 748 float *logfft,
Chris@1 749 float *logmask,
Chris@1 750 float global_specmax,
Chris@1 751 float local_specmax){
Chris@1 752
Chris@1 753 int i,n=p->n;
Chris@1 754
Chris@1 755 float *seed=alloca(sizeof(*seed)*p->total_octave_lines);
Chris@1 756 float att=local_specmax+p->vi->ath_adjatt;
Chris@1 757 for(i=0;i<p->total_octave_lines;i++)seed[i]=NEGINF;
Chris@1 758
Chris@1 759 /* set the ATH (floating below localmax, not global max by a
Chris@1 760 specified att) */
Chris@1 761 if(att<p->vi->ath_maxatt)att=p->vi->ath_maxatt;
Chris@1 762
Chris@1 763 for(i=0;i<n;i++)
Chris@1 764 logmask[i]=p->ath[i]+att;
Chris@1 765
Chris@1 766 /* tone masking */
Chris@1 767 seed_loop(p,(const float ***)p->tonecurves,logfft,logmask,seed,global_specmax);
Chris@1 768 max_seeds(p,seed,logmask);
Chris@1 769
Chris@1 770 }
Chris@1 771
Chris@1 772 void _vp_offset_and_mix(vorbis_look_psy *p,
Chris@1 773 float *noise,
Chris@1 774 float *tone,
Chris@1 775 int offset_select,
Chris@1 776 float *logmask,
Chris@1 777 float *mdct,
Chris@1 778 float *logmdct){
Chris@1 779 int i,n=p->n;
Chris@1 780 float de, coeffi, cx;/* AoTuV */
Chris@1 781 float toneatt=p->vi->tone_masteratt[offset_select];
Chris@1 782
Chris@1 783 cx = p->m_val;
Chris@1 784
Chris@1 785 for(i=0;i<n;i++){
Chris@1 786 float val= noise[i]+p->noiseoffset[offset_select][i];
Chris@1 787 if(val>p->vi->noisemaxsupp)val=p->vi->noisemaxsupp;
Chris@1 788 logmask[i]=max(val,tone[i]+toneatt);
Chris@1 789
Chris@1 790
Chris@1 791 /* AoTuV */
Chris@1 792 /** @ M1 **
Chris@1 793 The following codes improve a noise problem.
Chris@1 794 A fundamental idea uses the value of masking and carries out
Chris@1 795 the relative compensation of the MDCT.
Chris@1 796 However, this code is not perfect and all noise problems cannot be solved.
Chris@1 797 by Aoyumi @ 2004/04/18
Chris@1 798 */
Chris@1 799
Chris@1 800 if(offset_select == 1) {
Chris@1 801 coeffi = -17.2; /* coeffi is a -17.2dB threshold */
Chris@1 802 val = val - logmdct[i]; /* val == mdct line value relative to floor in dB */
Chris@1 803
Chris@1 804 if(val > coeffi){
Chris@1 805 /* mdct value is > -17.2 dB below floor */
Chris@1 806
Chris@1 807 de = 1.0-((val-coeffi)*0.005*cx);
Chris@1 808 /* pro-rated attenuation:
Chris@1 809 -0.00 dB boost if mdct value is -17.2dB (relative to floor)
Chris@1 810 -0.77 dB boost if mdct value is 0dB (relative to floor)
Chris@1 811 -1.64 dB boost if mdct value is +17.2dB (relative to floor)
Chris@1 812 etc... */
Chris@1 813
Chris@1 814 if(de < 0) de = 0.0001;
Chris@1 815 }else
Chris@1 816 /* mdct value is <= -17.2 dB below floor */
Chris@1 817
Chris@1 818 de = 1.0-((val-coeffi)*0.0003*cx);
Chris@1 819 /* pro-rated attenuation:
Chris@1 820 +0.00 dB atten if mdct value is -17.2dB (relative to floor)
Chris@1 821 +0.45 dB atten if mdct value is -34.4dB (relative to floor)
Chris@1 822 etc... */
Chris@1 823
Chris@1 824 mdct[i] *= de;
Chris@1 825
Chris@1 826 }
Chris@1 827 }
Chris@1 828 }
Chris@1 829
Chris@1 830 float _vp_ampmax_decay(float amp,vorbis_dsp_state *vd){
Chris@1 831 vorbis_info *vi=vd->vi;
Chris@1 832 codec_setup_info *ci=vi->codec_setup;
Chris@1 833 vorbis_info_psy_global *gi=&ci->psy_g_param;
Chris@1 834
Chris@1 835 int n=ci->blocksizes[vd->W]/2;
Chris@1 836 float secs=(float)n/vi->rate;
Chris@1 837
Chris@1 838 amp+=secs*gi->ampmax_att_per_sec;
Chris@1 839 if(amp<-9999)amp=-9999;
Chris@1 840 return(amp);
Chris@1 841 }
Chris@1 842
Chris@1 843 static float FLOOR1_fromdB_LOOKUP[256]={
Chris@1 844 1.0649863e-07F, 1.1341951e-07F, 1.2079015e-07F, 1.2863978e-07F,
Chris@1 845 1.3699951e-07F, 1.4590251e-07F, 1.5538408e-07F, 1.6548181e-07F,
Chris@1 846 1.7623575e-07F, 1.8768855e-07F, 1.9988561e-07F, 2.128753e-07F,
Chris@1 847 2.2670913e-07F, 2.4144197e-07F, 2.5713223e-07F, 2.7384213e-07F,
Chris@1 848 2.9163793e-07F, 3.1059021e-07F, 3.3077411e-07F, 3.5226968e-07F,
Chris@1 849 3.7516214e-07F, 3.9954229e-07F, 4.2550680e-07F, 4.5315863e-07F,
Chris@1 850 4.8260743e-07F, 5.1396998e-07F, 5.4737065e-07F, 5.8294187e-07F,
Chris@1 851 6.2082472e-07F, 6.6116941e-07F, 7.0413592e-07F, 7.4989464e-07F,
Chris@1 852 7.9862701e-07F, 8.5052630e-07F, 9.0579828e-07F, 9.6466216e-07F,
Chris@1 853 1.0273513e-06F, 1.0941144e-06F, 1.1652161e-06F, 1.2409384e-06F,
Chris@1 854 1.3215816e-06F, 1.4074654e-06F, 1.4989305e-06F, 1.5963394e-06F,
Chris@1 855 1.7000785e-06F, 1.8105592e-06F, 1.9282195e-06F, 2.0535261e-06F,
Chris@1 856 2.1869758e-06F, 2.3290978e-06F, 2.4804557e-06F, 2.6416497e-06F,
Chris@1 857 2.8133190e-06F, 2.9961443e-06F, 3.1908506e-06F, 3.3982101e-06F,
Chris@1 858 3.6190449e-06F, 3.8542308e-06F, 4.1047004e-06F, 4.3714470e-06F,
Chris@1 859 4.6555282e-06F, 4.9580707e-06F, 5.2802740e-06F, 5.6234160e-06F,
Chris@1 860 5.9888572e-06F, 6.3780469e-06F, 6.7925283e-06F, 7.2339451e-06F,
Chris@1 861 7.7040476e-06F, 8.2047000e-06F, 8.7378876e-06F, 9.3057248e-06F,
Chris@1 862 9.9104632e-06F, 1.0554501e-05F, 1.1240392e-05F, 1.1970856e-05F,
Chris@1 863 1.2748789e-05F, 1.3577278e-05F, 1.4459606e-05F, 1.5399272e-05F,
Chris@1 864 1.6400004e-05F, 1.7465768e-05F, 1.8600792e-05F, 1.9809576e-05F,
Chris@1 865 2.1096914e-05F, 2.2467911e-05F, 2.3928002e-05F, 2.5482978e-05F,
Chris@1 866 2.7139006e-05F, 2.8902651e-05F, 3.0780908e-05F, 3.2781225e-05F,
Chris@1 867 3.4911534e-05F, 3.7180282e-05F, 3.9596466e-05F, 4.2169667e-05F,
Chris@1 868 4.4910090e-05F, 4.7828601e-05F, 5.0936773e-05F, 5.4246931e-05F,
Chris@1 869 5.7772202e-05F, 6.1526565e-05F, 6.5524908e-05F, 6.9783085e-05F,
Chris@1 870 7.4317983e-05F, 7.9147585e-05F, 8.4291040e-05F, 8.9768747e-05F,
Chris@1 871 9.5602426e-05F, 0.00010181521F, 0.00010843174F, 0.00011547824F,
Chris@1 872 0.00012298267F, 0.00013097477F, 0.00013948625F, 0.00014855085F,
Chris@1 873 0.00015820453F, 0.00016848555F, 0.00017943469F, 0.00019109536F,
Chris@1 874 0.00020351382F, 0.00021673929F, 0.00023082423F, 0.00024582449F,
Chris@1 875 0.00026179955F, 0.00027881276F, 0.00029693158F, 0.00031622787F,
Chris@1 876 0.00033677814F, 0.00035866388F, 0.00038197188F, 0.00040679456F,
Chris@1 877 0.00043323036F, 0.00046138411F, 0.00049136745F, 0.00052329927F,
Chris@1 878 0.00055730621F, 0.00059352311F, 0.00063209358F, 0.00067317058F,
Chris@1 879 0.00071691700F, 0.00076350630F, 0.00081312324F, 0.00086596457F,
Chris@1 880 0.00092223983F, 0.00098217216F, 0.0010459992F, 0.0011139742F,
Chris@1 881 0.0011863665F, 0.0012634633F, 0.0013455702F, 0.0014330129F,
Chris@1 882 0.0015261382F, 0.0016253153F, 0.0017309374F, 0.0018434235F,
Chris@1 883 0.0019632195F, 0.0020908006F, 0.0022266726F, 0.0023713743F,
Chris@1 884 0.0025254795F, 0.0026895994F, 0.0028643847F, 0.0030505286F,
Chris@1 885 0.0032487691F, 0.0034598925F, 0.0036847358F, 0.0039241906F,
Chris@1 886 0.0041792066F, 0.0044507950F, 0.0047400328F, 0.0050480668F,
Chris@1 887 0.0053761186F, 0.0057254891F, 0.0060975636F, 0.0064938176F,
Chris@1 888 0.0069158225F, 0.0073652516F, 0.0078438871F, 0.0083536271F,
Chris@1 889 0.0088964928F, 0.009474637F, 0.010090352F, 0.010746080F,
Chris@1 890 0.011444421F, 0.012188144F, 0.012980198F, 0.013823725F,
Chris@1 891 0.014722068F, 0.015678791F, 0.016697687F, 0.017782797F,
Chris@1 892 0.018938423F, 0.020169149F, 0.021479854F, 0.022875735F,
Chris@1 893 0.024362330F, 0.025945531F, 0.027631618F, 0.029427276F,
Chris@1 894 0.031339626F, 0.033376252F, 0.035545228F, 0.037855157F,
Chris@1 895 0.040315199F, 0.042935108F, 0.045725273F, 0.048696758F,
Chris@1 896 0.051861348F, 0.055231591F, 0.058820850F, 0.062643361F,
Chris@1 897 0.066714279F, 0.071049749F, 0.075666962F, 0.080584227F,
Chris@1 898 0.085821044F, 0.091398179F, 0.097337747F, 0.10366330F,
Chris@1 899 0.11039993F, 0.11757434F, 0.12521498F, 0.13335215F,
Chris@1 900 0.14201813F, 0.15124727F, 0.16107617F, 0.17154380F,
Chris@1 901 0.18269168F, 0.19456402F, 0.20720788F, 0.22067342F,
Chris@1 902 0.23501402F, 0.25028656F, 0.26655159F, 0.28387361F,
Chris@1 903 0.30232132F, 0.32196786F, 0.34289114F, 0.36517414F,
Chris@1 904 0.38890521F, 0.41417847F, 0.44109412F, 0.46975890F,
Chris@1 905 0.50028648F, 0.53279791F, 0.56742212F, 0.60429640F,
Chris@1 906 0.64356699F, 0.68538959F, 0.72993007F, 0.77736504F,
Chris@1 907 0.82788260F, 0.88168307F, 0.9389798F, 1.F,
Chris@1 908 };
Chris@1 909
Chris@1 910 /* this is for per-channel noise normalization */
Chris@1 911 static int apsort(const void *a, const void *b){
Chris@1 912 float f1=**(float**)a;
Chris@1 913 float f2=**(float**)b;
Chris@1 914 return (f1<f2)-(f1>f2);
Chris@1 915 }
Chris@1 916
Chris@1 917 static void flag_lossless(int limit, float prepoint, float postpoint, float *mdct,
Chris@1 918 float *floor, int *flag, int i, int jn){
Chris@1 919 int j;
Chris@1 920 for(j=0;j<jn;j++){
Chris@1 921 float point = j>=limit-i ? postpoint : prepoint;
Chris@1 922 float r = fabs(mdct[j])/floor[j];
Chris@1 923 if(r<point)
Chris@1 924 flag[j]=0;
Chris@1 925 else
Chris@1 926 flag[j]=1;
Chris@1 927 }
Chris@1 928 }
Chris@1 929
Chris@1 930 /* Overload/Side effect: On input, the *q vector holds either the
Chris@1 931 quantized energy (for elements with the flag set) or the absolute
Chris@1 932 values of the *r vector (for elements with flag unset). On output,
Chris@1 933 *q holds the quantized energy for all elements */
Chris@1 934 static float noise_normalize(vorbis_look_psy *p, int limit, float *r, float *q, float *f, int *flags, float acc, int i, int n, int *out){
Chris@1 935
Chris@1 936 vorbis_info_psy *vi=p->vi;
Chris@1 937 float **sort = alloca(n*sizeof(*sort));
Chris@1 938 int j,count=0;
Chris@1 939 int start = (vi->normal_p ? vi->normal_start-i : n);
Chris@1 940 if(start>n)start=n;
Chris@1 941
Chris@1 942 /* force classic behavior where only energy in the current band is considered */
Chris@1 943 acc=0.f;
Chris@1 944
Chris@1 945 /* still responsible for populating *out where noise norm not in
Chris@1 946 effect. There's no need to [re]populate *q in these areas */
Chris@1 947 for(j=0;j<start;j++){
Chris@1 948 if(!flags || !flags[j]){ /* lossless coupling already quantized.
Chris@1 949 Don't touch; requantizing based on
Chris@1 950 energy would be incorrect. */
Chris@1 951 float ve = q[j]/f[j];
Chris@1 952 if(r[j]<0)
Chris@1 953 out[j] = -rint(sqrt(ve));
Chris@1 954 else
Chris@1 955 out[j] = rint(sqrt(ve));
Chris@1 956 }
Chris@1 957 }
Chris@1 958
Chris@1 959 /* sort magnitudes for noise norm portion of partition */
Chris@1 960 for(;j<n;j++){
Chris@1 961 if(!flags || !flags[j]){ /* can't noise norm elements that have
Chris@1 962 already been loslessly coupled; we can
Chris@1 963 only account for their energy error */
Chris@1 964 float ve = q[j]/f[j];
Chris@1 965 /* Despite all the new, more capable coupling code, for now we
Chris@1 966 implement noise norm as it has been up to this point. Only
Chris@1 967 consider promotions to unit magnitude from 0. In addition
Chris@1 968 the only energy error counted is quantizations to zero. */
Chris@1 969 /* also-- the original point code only applied noise norm at > pointlimit */
Chris@1 970 if(ve<.25f && (!flags || j>=limit-i)){
Chris@1 971 acc += ve;
Chris@1 972 sort[count++]=q+j; /* q is fabs(r) for unflagged element */
Chris@1 973 }else{
Chris@1 974 /* For now: no acc adjustment for nonzero quantization. populate *out and q as this value is final. */
Chris@1 975 if(r[j]<0)
Chris@1 976 out[j] = -rint(sqrt(ve));
Chris@1 977 else
Chris@1 978 out[j] = rint(sqrt(ve));
Chris@1 979 q[j] = out[j]*out[j]*f[j];
Chris@1 980 }
Chris@1 981 }/* else{
Chris@1 982 again, no energy adjustment for error in nonzero quant-- for now
Chris@1 983 }*/
Chris@1 984 }
Chris@1 985
Chris@1 986 if(count){
Chris@1 987 /* noise norm to do */
Chris@1 988 qsort(sort,count,sizeof(*sort),apsort);
Chris@1 989 for(j=0;j<count;j++){
Chris@1 990 int k=sort[j]-q;
Chris@1 991 if(acc>=vi->normal_thresh){
Chris@1 992 out[k]=unitnorm(r[k]);
Chris@1 993 acc-=1.f;
Chris@1 994 q[k]=f[k];
Chris@1 995 }else{
Chris@1 996 out[k]=0;
Chris@1 997 q[k]=0.f;
Chris@1 998 }
Chris@1 999 }
Chris@1 1000 }
Chris@1 1001
Chris@1 1002 return acc;
Chris@1 1003 }
Chris@1 1004
Chris@1 1005 /* Noise normalization, quantization and coupling are not wholly
Chris@1 1006 seperable processes in depth>1 coupling. */
Chris@1 1007 void _vp_couple_quantize_normalize(int blobno,
Chris@1 1008 vorbis_info_psy_global *g,
Chris@1 1009 vorbis_look_psy *p,
Chris@1 1010 vorbis_info_mapping0 *vi,
Chris@1 1011 float **mdct,
Chris@1 1012 int **iwork,
Chris@1 1013 int *nonzero,
Chris@1 1014 int sliding_lowpass,
Chris@1 1015 int ch){
Chris@1 1016
Chris@1 1017 int i;
Chris@1 1018 int n = p->n;
Chris@1 1019 int partition=(p->vi->normal_p ? p->vi->normal_partition : 16);
Chris@1 1020 int limit = g->coupling_pointlimit[p->vi->blockflag][blobno];
Chris@1 1021 float prepoint=stereo_threshholds[g->coupling_prepointamp[blobno]];
Chris@1 1022 float postpoint=stereo_threshholds[g->coupling_postpointamp[blobno]];
Chris@1 1023 #if 0
Chris@1 1024 float de=0.1*p->m_val; /* a blend of the AoTuV M2 and M3 code here and below */
Chris@1 1025 #endif
Chris@1 1026
Chris@1 1027 /* mdct is our raw mdct output, floor not removed. */
Chris@1 1028 /* inout passes in the ifloor, passes back quantized result */
Chris@1 1029
Chris@1 1030 /* unquantized energy (negative indicates amplitude has negative sign) */
Chris@1 1031 float **raw = alloca(ch*sizeof(*raw));
Chris@1 1032
Chris@1 1033 /* dual pupose; quantized energy (if flag set), othersize fabs(raw) */
Chris@1 1034 float **quant = alloca(ch*sizeof(*quant));
Chris@1 1035
Chris@1 1036 /* floor energy */
Chris@1 1037 float **floor = alloca(ch*sizeof(*floor));
Chris@1 1038
Chris@1 1039 /* flags indicating raw/quantized status of elements in raw vector */
Chris@1 1040 int **flag = alloca(ch*sizeof(*flag));
Chris@1 1041
Chris@1 1042 /* non-zero flag working vector */
Chris@1 1043 int *nz = alloca(ch*sizeof(*nz));
Chris@1 1044
Chris@1 1045 /* energy surplus/defecit tracking */
Chris@1 1046 float *acc = alloca((ch+vi->coupling_steps)*sizeof(*acc));
Chris@1 1047
Chris@1 1048 /* The threshold of a stereo is changed with the size of n */
Chris@1 1049 if(n > 1000)
Chris@1 1050 postpoint=stereo_threshholds_limited[g->coupling_postpointamp[blobno]];
Chris@1 1051
Chris@1 1052 raw[0] = alloca(ch*partition*sizeof(**raw));
Chris@1 1053 quant[0] = alloca(ch*partition*sizeof(**quant));
Chris@1 1054 floor[0] = alloca(ch*partition*sizeof(**floor));
Chris@1 1055 flag[0] = alloca(ch*partition*sizeof(**flag));
Chris@1 1056
Chris@1 1057 for(i=1;i<ch;i++){
Chris@1 1058 raw[i] = &raw[0][partition*i];
Chris@1 1059 quant[i] = &quant[0][partition*i];
Chris@1 1060 floor[i] = &floor[0][partition*i];
Chris@1 1061 flag[i] = &flag[0][partition*i];
Chris@1 1062 }
Chris@1 1063 for(i=0;i<ch+vi->coupling_steps;i++)
Chris@1 1064 acc[i]=0.f;
Chris@1 1065
Chris@1 1066 for(i=0;i<n;i+=partition){
Chris@1 1067 int k,j,jn = partition > n-i ? n-i : partition;
Chris@1 1068 int step,track = 0;
Chris@1 1069
Chris@1 1070 memcpy(nz,nonzero,sizeof(*nz)*ch);
Chris@1 1071
Chris@1 1072 /* prefill */
Chris@1 1073 memset(flag[0],0,ch*partition*sizeof(**flag));
Chris@1 1074 for(k=0;k<ch;k++){
Chris@1 1075 int *iout = &iwork[k][i];
Chris@1 1076 if(nz[k]){
Chris@1 1077
Chris@1 1078 for(j=0;j<jn;j++)
Chris@1 1079 floor[k][j] = FLOOR1_fromdB_LOOKUP[iout[j]];
Chris@1 1080
Chris@1 1081 flag_lossless(limit,prepoint,postpoint,&mdct[k][i],floor[k],flag[k],i,jn);
Chris@1 1082
Chris@1 1083 for(j=0;j<jn;j++){
Chris@1 1084 quant[k][j] = raw[k][j] = mdct[k][i+j]*mdct[k][i+j];
Chris@1 1085 if(mdct[k][i+j]<0.f) raw[k][j]*=-1.f;
Chris@1 1086 floor[k][j]*=floor[k][j];
Chris@1 1087 }
Chris@1 1088
Chris@1 1089 acc[track]=noise_normalize(p,limit,raw[k],quant[k],floor[k],NULL,acc[track],i,jn,iout);
Chris@1 1090
Chris@1 1091 }else{
Chris@1 1092 for(j=0;j<jn;j++){
Chris@1 1093 floor[k][j] = 1e-10f;
Chris@1 1094 raw[k][j] = 0.f;
Chris@1 1095 quant[k][j] = 0.f;
Chris@1 1096 flag[k][j] = 0;
Chris@1 1097 iout[j]=0;
Chris@1 1098 }
Chris@1 1099 acc[track]=0.f;
Chris@1 1100 }
Chris@1 1101 track++;
Chris@1 1102 }
Chris@1 1103
Chris@1 1104 /* coupling */
Chris@1 1105 for(step=0;step<vi->coupling_steps;step++){
Chris@1 1106 int Mi = vi->coupling_mag[step];
Chris@1 1107 int Ai = vi->coupling_ang[step];
Chris@1 1108 int *iM = &iwork[Mi][i];
Chris@1 1109 int *iA = &iwork[Ai][i];
Chris@1 1110 float *reM = raw[Mi];
Chris@1 1111 float *reA = raw[Ai];
Chris@1 1112 float *qeM = quant[Mi];
Chris@1 1113 float *qeA = quant[Ai];
Chris@1 1114 float *floorM = floor[Mi];
Chris@1 1115 float *floorA = floor[Ai];
Chris@1 1116 int *fM = flag[Mi];
Chris@1 1117 int *fA = flag[Ai];
Chris@1 1118
Chris@1 1119 if(nz[Mi] || nz[Ai]){
Chris@1 1120 nz[Mi] = nz[Ai] = 1;
Chris@1 1121
Chris@1 1122 for(j=0;j<jn;j++){
Chris@1 1123
Chris@1 1124 if(j<sliding_lowpass-i){
Chris@1 1125 if(fM[j] || fA[j]){
Chris@1 1126 /* lossless coupling */
Chris@1 1127
Chris@1 1128 reM[j] = fabs(reM[j])+fabs(reA[j]);
Chris@1 1129 qeM[j] = qeM[j]+qeA[j];
Chris@1 1130 fM[j]=fA[j]=1;
Chris@1 1131
Chris@1 1132 /* couple iM/iA */
Chris@1 1133 {
Chris@1 1134 int A = iM[j];
Chris@1 1135 int B = iA[j];
Chris@1 1136
Chris@1 1137 if(abs(A)>abs(B)){
Chris@1 1138 iA[j]=(A>0?A-B:B-A);
Chris@1 1139 }else{
Chris@1 1140 iA[j]=(B>0?A-B:B-A);
Chris@1 1141 iM[j]=B;
Chris@1 1142 }
Chris@1 1143
Chris@1 1144 /* collapse two equivalent tuples to one */
Chris@1 1145 if(iA[j]>=abs(iM[j])*2){
Chris@1 1146 iA[j]= -iA[j];
Chris@1 1147 iM[j]= -iM[j];
Chris@1 1148 }
Chris@1 1149
Chris@1 1150 }
Chris@1 1151
Chris@1 1152 }else{
Chris@1 1153 /* lossy (point) coupling */
Chris@1 1154 if(j<limit-i){
Chris@1 1155 /* dipole */
Chris@1 1156 reM[j] += reA[j];
Chris@1 1157 qeM[j] = fabs(reM[j]);
Chris@1 1158 }else{
Chris@1 1159 #if 0
Chris@1 1160 /* AoTuV */
Chris@1 1161 /** @ M2 **
Chris@1 1162 The boost problem by the combination of noise normalization and point stereo is eased.
Chris@1 1163 However, this is a temporary patch.
Chris@1 1164 by Aoyumi @ 2004/04/18
Chris@1 1165 */
Chris@1 1166 float derate = (1.0 - de*((float)(j-limit+i) / (float)(n-limit)));
Chris@1 1167 /* elliptical */
Chris@1 1168 if(reM[j]+reA[j]<0){
Chris@1 1169 reM[j] = - (qeM[j] = (fabs(reM[j])+fabs(reA[j]))*derate*derate);
Chris@1 1170 }else{
Chris@1 1171 reM[j] = (qeM[j] = (fabs(reM[j])+fabs(reA[j]))*derate*derate);
Chris@1 1172 }
Chris@1 1173 #else
Chris@1 1174 /* elliptical */
Chris@1 1175 if(reM[j]+reA[j]<0){
Chris@1 1176 reM[j] = - (qeM[j] = fabs(reM[j])+fabs(reA[j]));
Chris@1 1177 }else{
Chris@1 1178 reM[j] = (qeM[j] = fabs(reM[j])+fabs(reA[j]));
Chris@1 1179 }
Chris@1 1180 #endif
Chris@1 1181
Chris@1 1182 }
Chris@1 1183 reA[j]=qeA[j]=0.f;
Chris@1 1184 fA[j]=1;
Chris@1 1185 iA[j]=0;
Chris@1 1186 }
Chris@1 1187 }
Chris@1 1188 floorM[j]=floorA[j]=floorM[j]+floorA[j];
Chris@1 1189 }
Chris@1 1190 /* normalize the resulting mag vector */
Chris@1 1191 acc[track]=noise_normalize(p,limit,raw[Mi],quant[Mi],floor[Mi],flag[Mi],acc[track],i,jn,iM);
Chris@1 1192 track++;
Chris@1 1193 }
Chris@1 1194 }
Chris@1 1195 }
Chris@1 1196
Chris@1 1197 for(i=0;i<vi->coupling_steps;i++){
Chris@1 1198 /* make sure coupling a zero and a nonzero channel results in two
Chris@1 1199 nonzero channels. */
Chris@1 1200 if(nonzero[vi->coupling_mag[i]] ||
Chris@1 1201 nonzero[vi->coupling_ang[i]]){
Chris@1 1202 nonzero[vi->coupling_mag[i]]=1;
Chris@1 1203 nonzero[vi->coupling_ang[i]]=1;
Chris@1 1204 }
Chris@1 1205 }
Chris@1 1206 }