00001 #include <stdio.h>
00002 #include <stdlib.h>
00003 #include <math.h>
00004 #include <string.h>
00005 #include "common.h"
00006 #include "options.h"
00007 #include "encoder.h"
00008 #include "mem.h"
00009 #include "fft.h"
00010 #include "ath.h"
00011 #include "psycho_4.h"
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044 static int new = 0, old = 1, oldest = 0;
00045 static int init = 0;
00046
00047
00048 static double NMT = 5.5;
00049
00050
00051
00052 static FLOAT minval[27] = {
00053 0.0,
00054 20.0,
00055 20.0,
00056 20.0,
00057 20.0,
00058 20.0,
00059 17.0,
00060 15.0,
00061 10.0,
00062 7.0,
00063 4.4,
00064 4.5, 4.5, 4.5,4.5, 4.5, 4.5, 4.5, 4.5, 4.5, 4.5, 4.5, 4.5, 4.5, 4.5, 4.5,
00065 3.5
00066 };
00067
00068
00069 static FLOAT *grouped_c, *grouped_e, *nb, *cb, *tb, *ecb, *bc;
00070 static FLOAT *wsamp_r, *phi, *energy;
00071 static FLOAT *c, *bark, *thr;
00072 static F32 *snrtmp;
00073
00074 static int *numlines;
00075 static int *partition;
00076 static FLOAT *cbval, *rnorm;
00077 static FLOAT *window;
00078 static FLOAT *ath;
00079 static double *tmn;
00080 static FCB *s;
00081 static FHBLK *lthr;
00082 static F2HBLK *r, *phi_sav;
00083
00084 #define TRIGTABLESIZE 3142
00085 #define TRIGTABLESCALE 1000.0
00086 static FLOAT cos_table[TRIGTABLESIZE];
00087 static FLOAT sin_table[TRIGTABLESIZE];
00088 void psycho_4_trigtable_init(void) {
00089
00090 int i;
00091 for (i=0;i<TRIGTABLESIZE;i++) {
00092 cos_table[i] = cos((double)i/TRIGTABLESCALE);
00093 sin_table[i] = sin((double)i/TRIGTABLESCALE);
00094 }
00095 }
00096
00097 INLINE FLOAT psycho_4_cos(FLOAT phi) {
00098 int index;
00099 int sign=1;
00100
00101 index = (int)(fabs(phi) * TRIGTABLESCALE);
00102 while (index>=TRIGTABLESIZE) {
00103 index -= TRIGTABLESIZE;
00104 sign*=-1;
00105 }
00106 return(sign * cos_table[index]);
00107 }
00108
00109 INLINE FLOAT psycho_4_sin(FLOAT phi) {
00110 int index;
00111 int sign=1;
00112
00113 index = (int)(fabs(phi) * TRIGTABLESCALE);
00114 while (index>=TRIGTABLESIZE) {
00115 index -= TRIGTABLESIZE;
00116 sign*=-1;
00117 }
00118 if (phi<0)
00119 return(-1 * sign * sin_table[index]);
00120 return(sign * sin_table[index]);
00121 }
00122
00123
00124 void psycho_4 (short int *buffer, short int savebuf[1056], int chn,
00125 double *smr, double sfreq, options *glopts)
00126
00127 {
00128 unsigned int run, i, j, k;
00129 FLOAT r_prime, phi_prime;
00130 FLOAT npart, epart;
00131
00132 if (init == 0) {
00133 psycho_4_init (sfreq, glopts);
00134 init++;
00135 }
00136
00137 for (run = 0; run < 2; run++) {
00138
00139
00140
00141
00142
00143
00144
00145
00146
00147 for (j = 0; j < 480; j++) {
00148 savebuf[j] = savebuf[j + 576];
00149 wsamp_r[j] = window[j] * ((FLOAT) savebuf[j]);
00150 }
00151 for (; j < 1024; j++) {
00152 savebuf[j] = *buffer++;
00153 wsamp_r[j] = window[j] * ((FLOAT) savebuf[j]);
00154 }
00155 for (; j < 1056; j++)
00156 savebuf[j] = *buffer++;
00157
00158
00159
00160 psycho_2_fft (wsamp_r, energy, phi);
00161
00162
00163
00164 {
00165 if (new == 0) {
00166 new = 1;
00167 oldest = 1;
00168 } else {
00169 new = 0;
00170 oldest = 0;
00171 }
00172 if (old == 0)
00173 old = 1;
00174 else
00175 old = 0;
00176 }
00177
00178 for (j = 0; j < HBLKSIZE; j++) {
00179 #ifdef NEWATAN
00180 double temp1, temp2, temp3;
00181 r_prime = 2.0 * r[chn][old][j] - r[chn][oldest][j];
00182 phi_prime = 2.0 * phi_sav[chn][old][j] - phi_sav[chn][oldest][j];
00183
00184 r[chn][new][j] = sqrt ((double) energy[j]);
00185 phi_sav[chn][new][j] = phi[j];
00186
00187 {
00188 temp1 =
00189 r[chn][new][j] * psycho_4_cos(phi[j]) -
00190 r_prime * psycho_4_cos(phi_prime);
00191 temp2 =
00192 r[chn][new][j] * psycho_4_sin(phi[j]) -
00193 r_prime * psycho_4_sin(phi_prime);
00194
00195
00196 }
00197
00198
00199 temp3 = r[chn][new][j] + fabs ((double) r_prime);
00200 if (temp3 != 0)
00201 c[j] = sqrt (temp1 * temp1 + temp2 * temp2) / temp3;
00202 else
00203 c[j] = 0;
00204 #else
00205 double temp1, temp2, temp3;
00206 r_prime = 2.0 * r[chn][old][j] - r[chn][oldest][j];
00207 phi_prime = 2.0 * phi_sav[chn][old][j] - phi_sav[chn][oldest][j];
00208
00209 r[chn][new][j] = sqrt ((double) energy[j]);
00210 phi_sav[chn][new][j] = phi[j];
00211
00212
00213 temp1 =
00214 r[chn][new][j] * cos ((double) phi[j]) -
00215 r_prime * cos ((double) phi_prime);
00216 temp2 =
00217 r[chn][new][j] * sin ((double) phi[j]) -
00218 r_prime * sin ((double) phi_prime);
00219
00220 temp3 = r[chn][new][j] + fabs ((double) r_prime);
00221 if (temp3 != 0)
00222 c[j] = sqrt (temp1 * temp1 + temp2 * temp2) / temp3;
00223 else
00224 c[j] = 0;
00225 #endif
00226 }
00227
00228
00229
00230
00231 for (j = 1; j < CBANDS; j++) {
00232 grouped_e[j] = 0;
00233 grouped_c[j] = 0;
00234 }
00235 grouped_e[0] = energy[0];
00236 grouped_c[0] = energy[0] * c[0];
00237 for (j = 1; j < HBLKSIZE; j++) {
00238 grouped_e[partition[j]] += energy[j];
00239 grouped_c[partition[j]] += energy[j] * c[j];
00240 }
00241
00242
00243
00244
00245 for (j = 0; j < CBANDS; j++) {
00246 ecb[j] = 0;
00247 cb[j] = 0;
00248 for (k = 0; k < CBANDS; k++) {
00249 if (s[j][k] != 0.0) {
00250 ecb[j] += s[j][k] * grouped_e[k];
00251 cb[j] += s[j][k] * grouped_c[k];
00252 }
00253 }
00254 if (ecb[j] != 0)
00255 cb[j] = cb[j] / ecb[j];
00256 else
00257 cb[j] = 0;
00258 }
00259
00260
00261
00262 for (i=0;i<CBANDS;i++) {
00263 if (cb[i] < 0.05)
00264 cb[i] = 0.05;
00265 else if (cb[i] > 0.5)
00266 cb[i] = 0.5;
00267 tb[i] = -0.301029996 - 0.434294482 * log((double) cb[i]);
00268 }
00269
00270
00271
00272
00273 for (j = 0; j < CBANDS; j++) {
00274 FLOAT SNR, SNRtemp;
00275 SNRtemp = tmn[j] * tb[j] + NMT * (1.0 - tb[j]);
00276 SNR = MAX(SNRtemp, minval[(int)cbval[j]]);
00277 bc[j] = exp ((double) -SNR * LN_TO_LOG10);
00278 }
00279
00280
00281
00282
00283
00284 for (j = 0; j < CBANDS; j++) {
00285 if (rnorm[j] && numlines[j])
00286 nb[j] = ecb[j] * bc[j] / (rnorm[j] * numlines[j]);
00287 else
00288 nb[j] = 0;
00289 }
00290
00291
00292 for (j = 0; j < HBLKSIZE; j++)
00293 thr[j] = MAX(nb[partition[j]], ath[j]);
00294
00295
00296
00297 for (j = 0; j < 193; j += 16) {
00298
00299 npart = 60802371420160.0;
00300 epart = 0.0;
00301 for (k = 0; k < 17; k++) {
00302 if (thr[j + k] < npart)
00303 npart = thr[j + k];
00304
00305 epart += energy[j + k];
00306 }
00307 snrtmp[run][j / 16] = 4.342944819 * log((double)(epart/(npart*17.0)));
00308 }
00309 for (j = 208; j < (HBLKSIZE - 1); j += 16) {
00310
00311 npart = 0.0;
00312 epart = 0.0;
00313 for (k = 0; k < 17; k++) {
00314 npart += thr[j + k];
00315 epart += energy[j + k];
00316 }
00317 snrtmp[run][j / 16] = 4.342944819 * log ((double) (epart/npart));
00318 }
00319 }
00320
00321
00322 for (i = 0; i < 32; i++)
00323 smr[i] = MAX(snrtmp[0][i], snrtmp[1][i]);
00324
00325 }
00326
00327
00328
00329
00330 void psycho_4_init (double sfreq, options *glopts)
00331 {
00332 int i, j;
00333
00334
00335 psycho_4_allocmem();
00336
00337
00338 psycho_4_trigtable_init();
00339
00340
00341 for (i = 0; i < BLKSIZE; i++)
00342 window[i] = 0.5 * (1 - cos (2.0 * PI * (i - 0.5) / BLKSIZE));
00343
00344
00345
00346
00347
00348
00349
00350
00351
00352
00353 for (i=0; i<HBLKSIZE; i++) {
00354 FLOAT freq = i * sfreq/BLKSIZE;
00355 bark[i] = toolame_freq2bark(freq);
00356
00357
00358
00359 ath[i] = ATH_energy(freq,glopts->athlevel);
00360
00361 }
00362
00363
00364
00365
00366
00367
00368 int partition_count = 0;
00369 int cbase = 0;
00370 for (i=0;i<HBLKSIZE;i++) {
00371 if ((bark[i] - bark[cbase]) > 0.33) {
00372
00373
00374
00375
00376 cbase = i;
00377 partition_count++;
00378 }
00379
00380 partition[i] = partition_count;
00381
00382 numlines[partition_count]++;
00383 }
00384
00385
00386
00387 for (i=0;i<HBLKSIZE;i++)
00388 cbval[partition[i]] += bark[i];
00389 for (i=0;i<CBANDS;i++) {
00390 if (numlines[i] != 0)
00391 cbval[i] /= numlines[i];
00392 else {
00393 cbval[i]=0;
00394 }
00395 }
00396
00397
00398
00399 for (i=0;i<CBANDS;i++) {
00400 for (j=0;j<CBANDS;j++) {
00401 s[i][j] = psycho_4_spreading_function( 1.05 * (cbval[i] - cbval[j]) );
00402 rnorm[i] += s[i][j];
00403
00404 }
00405 }
00406
00407
00408 for (j = 0; j < CBANDS; j++)
00409 tmn[j] = MAX(15.5+cbval[j], 24.5);
00410
00411
00412 if (glopts->verbosity > 10) {
00413
00414 int wlow, whigh=0;
00415 int ntot=0;
00416 fprintf(stdout,"psy model 4 init\n");
00417 fprintf(stdout,"index \tnlines \twlow \twhigh \tbval \tminval \ttmn\n");
00418 for (i=0;i<CBANDS;i++)
00419 if (numlines[i] != 0) {
00420 wlow = whigh+1;
00421 whigh = wlow + numlines[i] - 1;
00422 fprintf(stdout,"%i \t%i \t%i \t%i \t%5.2f \t%4.2f \t%4.2f\n",i+1, numlines[i],wlow, whigh, cbval[i],minval[(int)cbval[i]],tmn[i]);
00423 ntot += numlines[i];
00424 }
00425 fprintf(stdout,"total lines %i\n",ntot);
00426 exit(0);
00427 }
00428 }
00429
00430
00431
00432
00433
00434 FLOAT8 psycho_4_spreading_function(FLOAT8 bark) {
00435
00436 FLOAT8 tempx,x,tempy,temp;
00437 tempx = bark;
00438 #ifdef LAME
00439
00440 if (tempx>=0) tempx *= 3;
00441 else tempx *=1.5;
00442 #endif
00443
00444 if(tempx>=0.5 && tempx<=2.5)
00445 {
00446 temp = tempx - 0.5;
00447 x = 8.0 * (temp*temp - 2.0 * temp);
00448 }
00449 else x = 0.0;
00450 tempx += 0.474;
00451 tempy = 15.811389 + 7.5*tempx - 17.5*sqrt(1.0+tempx*tempx);
00452
00453 if (tempy <= -60.0) return 0.0;
00454
00455 tempx = exp( (x + tempy)*LN_TO_LOG10 );
00456
00457 #ifdef LAME
00458
00459
00460
00461
00462
00463
00464
00465
00466
00467
00468 tempx /= .6609193;
00469 #endif
00470 return tempx;
00471
00472 }
00473
00474 void psycho_4_allocmem() {
00475 grouped_c = (FLOAT *) mem_alloc (sizeof (FCB), "grouped_c");
00476 grouped_e = (FLOAT *) mem_alloc (sizeof (FCB), "grouped_e");
00477 nb = (FLOAT *) mem_alloc (sizeof (FCB), "nb");
00478 cb = (FLOAT *) mem_alloc (sizeof (FCB), "cb");
00479 tb = (FLOAT *) mem_alloc (sizeof (FCB), "tb");
00480 ecb = (FLOAT *) mem_alloc (sizeof (FCB), "ecb");
00481 bc = (FLOAT *) mem_alloc (sizeof (FCB), "bc");
00482 wsamp_r = (FLOAT *) mem_alloc (sizeof (FBLK), "wsamp_r");
00483 phi = (FLOAT *) mem_alloc (sizeof (FBLK), "phi");
00484 energy = (FLOAT *) mem_alloc (sizeof (FBLK), "energy");
00485 c = (FLOAT *) mem_alloc (sizeof (FHBLK), "c");
00486 bark = (FLOAT *) mem_alloc (sizeof (FHBLK), "bark");
00487 thr = (FLOAT *) mem_alloc (sizeof (FHBLK), "thr");
00488 snrtmp = (F32 *) mem_alloc (sizeof (F2_32), "snrtmp");
00489
00490 numlines = (int *) mem_alloc (sizeof (ICB), "numlines");
00491 partition = (int *) mem_alloc (sizeof (IHBLK), "partition");
00492 cbval = (FLOAT *) mem_alloc (sizeof (FCB), "cbval");
00493 rnorm = (FLOAT *) mem_alloc (sizeof (FCB), "rnorm");
00494 window = (FLOAT *) mem_alloc (sizeof (FBLK), "window");
00495 ath = (FLOAT *) mem_alloc (sizeof (FHBLK), "ath");
00496 tmn = (double *) mem_alloc (sizeof (DCB), "tmn");
00497 s = (FCB *) mem_alloc (sizeof (FCBCB), "s");
00498 lthr = (FHBLK *) mem_alloc (sizeof (F2HBLK), "lthr");
00499 r = (F2HBLK *) mem_alloc (sizeof (F22HBLK), "r");
00500 phi_sav = (F2HBLK *) mem_alloc (sizeof (F22HBLK), "phi_sav");
00501
00502 }
00503
00504
00505
00506
00507