00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
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
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091 #ifdef HAVE_CONFIG_H
00092 #include <config.h>
00093 #endif
00094
00095 #include <stdio.h>
00096 #include <stdlib.h>
00097 #include <string.h>
00098
00099 #include "lame.h"
00100 #include "machine.h"
00101 #include "gain_analysis.h"
00102
00103
00104
00105
00106 #ifdef WIN32
00107 #pragma warning ( disable : 4305 )
00108 #endif
00109
00110
00111 static const Float_t ABYule[9][2 * YULE_ORDER + 1] = {
00112 {0.03857599435200, -3.84664617118067, -0.02160367184185, 7.81501653005538, -0.00123395316851,
00113 -11.34170355132042, -0.00009291677959, 13.05504219327545, -0.01655260341619,
00114 -12.28759895145294, 0.02161526843274, 9.48293806319790, -0.02074045215285, -5.87257861775999,
00115 0.00594298065125, 2.75465861874613, 0.00306428023191, -0.86984376593551, 0.00012025322027,
00116 0.13919314567432, 0.00288463683916},
00117 {0.05418656406430, -3.47845948550071, -0.02911007808948, 6.36317777566148, -0.00848709379851,
00118 -8.54751527471874, -0.00851165645469, 9.47693607801280, -0.00834990904936, -8.81498681370155,
00119 0.02245293253339, 6.85401540936998, -0.02596338512915, -4.39470996079559, 0.01624864962975,
00120 2.19611684890774, -0.00240879051584, -0.75104302451432, 0.00674613682247, 0.13149317958808,
00121 -0.00187763777362},
00122 {0.15457299681924, -2.37898834973084, -0.09331049056315, 2.84868151156327, -0.06247880153653,
00123 -2.64577170229825, 0.02163541888798, 2.23697657451713, -0.05588393329856, -1.67148153367602,
00124 0.04781476674921, 1.00595954808547, 0.00222312597743, -0.45953458054983, 0.03174092540049,
00125 0.16378164858596, -0.01390589421898, -0.05032077717131, 0.00651420667831, 0.02347897407020,
00126 -0.00881362733839},
00127 {0.30296907319327, -1.61273165137247, -0.22613988682123, 1.07977492259970, -0.08587323730772,
00128 -0.25656257754070, 0.03282930172664, -0.16276719120440, -0.00915702933434, -0.22638893773906,
00129 -0.02364141202522, 0.39120800788284, -0.00584456039913, -0.22138138954925, 0.06276101321749,
00130 0.04500235387352, -0.00000828086748, 0.02005851806501, 0.00205861885564, 0.00302439095741,
00131 -0.02950134983287},
00132 {0.33642304856132, -1.49858979367799, -0.25572241425570, 0.87350271418188, -0.11828570177555,
00133 0.12205022308084, 0.11921148675203, -0.80774944671438, -0.07834489609479, 0.47854794562326,
00134 -0.00469977914380, -0.12453458140019, -0.00589500224440, -0.04067510197014, 0.05724228140351,
00135 0.08333755284107, 0.00832043980773, -0.04237348025746, -0.01635381384540, 0.02977207319925,
00136 -0.01760176568150},
00137 {0.44915256608450, -0.62820619233671, -0.14351757464547, 0.29661783706366, -0.22784394429749,
00138 -0.37256372942400, -0.01419140100551, 0.00213767857124, 0.04078262797139, -0.42029820170918,
00139 -0.12398163381748, 0.22199650564824, 0.04097565135648, 0.00613424350682, 0.10478503600251,
00140 0.06747620744683, -0.01863887810927, 0.05784820375801, -0.03193428438915, 0.03222754072173,
00141 0.00541907748707},
00142 {0.56619470757641, -1.04800335126349, -0.75464456939302, 0.29156311971249, 0.16242137742230,
00143 -0.26806001042947, 0.16744243493672, 0.00819999645858, -0.18901604199609, 0.45054734505008,
00144 0.30931782841830, -0.33032403314006, -0.27562961986224, 0.06739368333110, 0.00647310677246,
00145 -0.04784254229033, 0.08647503780351, 0.01639907836189, -0.03788984554840, 0.01807364323573,
00146 -0.00588215443421},
00147 {0.58100494960553, -0.51035327095184, -0.53174909058578, -0.31863563325245, -0.14289799034253,
00148 -0.20256413484477, 0.17520704835522, 0.14728154134330, 0.02377945217615, 0.38952639978999,
00149 0.15558449135573, -0.23313271880868, -0.25344790059353, -0.05246019024463, 0.01628462406333,
00150 -0.02505961724053, 0.06920467763959, 0.02442357316099, -0.03721611395801, 0.01818801111503,
00151 -0.00749618797172},
00152 {0.53648789255105, -0.25049871956020, -0.42163034350696, -0.43193942311114, -0.00275953611929,
00153 -0.03424681017675, 0.04267842219415, -0.04678328784242, -0.10214864179676, 0.26408300200955,
00154 0.14590772289388, 0.15113130533216, -0.02459864859345, -0.17556493366449, -0.11202315195388,
00155 -0.18823009262115, -0.04060034127000, 0.05477720428674, 0.04788665548180, 0.04704409688120,
00156 -0.02217936801134}
00157 };
00158
00159 static const Float_t ABButter[9][2 * BUTTER_ORDER + 1] = {
00160 {0.98621192462708, -1.97223372919527, -1.97242384925416, 0.97261396931306, 0.98621192462708},
00161 {0.98500175787242, -1.96977855582618, -1.97000351574484, 0.97022847566350, 0.98500175787242},
00162 {0.97938932735214, -1.95835380975398, -1.95877865470428, 0.95920349965459, 0.97938932735214},
00163 {0.97531843204928, -1.95002759149878, -1.95063686409857, 0.95124613669835, 0.97531843204928},
00164 {0.97316523498161, -1.94561023566527, -1.94633046996323, 0.94705070426118, 0.97316523498161},
00165 {0.96454515552826, -1.92783286977036, -1.92909031105652, 0.93034775234268, 0.96454515552826},
00166 {0.96009142950541, -1.91858953033784, -1.92018285901082, 0.92177618768381, 0.96009142950541},
00167 {0.95856916599601, -1.91542108074780, -1.91713833199203, 0.91885558323625, 0.95856916599601},
00168 {0.94597685600279, -1.88903307939452, -1.89195371200558, 0.89487434461664, 0.94597685600279}
00169 };
00170
00171
00172
00173 #ifdef WIN32
00174 #pragma warning ( default : 4305 )
00175 #endif
00176
00177
00178
00179 static void
00180 filterYule(const Float_t * input, Float_t * output, size_t nSamples, const Float_t * const kernel)
00181 {
00182
00183
00184 while (nSamples--) {
00185 *output = 1e-10
00186 + input[0] * kernel[0]
00187 - output[-1] * kernel[1]
00188 + input[-1] * kernel[2]
00189 - output[-2] * kernel[3]
00190 + input[-2] * kernel[4]
00191 - output[-3] * kernel[5]
00192 + input[-3] * kernel[6]
00193 - output[-4] * kernel[7]
00194 + input[-4] * kernel[8]
00195 - output[-5] * kernel[9]
00196 + input[-5] * kernel[10]
00197 - output[-6] * kernel[11]
00198 + input[-6] * kernel[12]
00199 - output[-7] * kernel[13]
00200 + input[-7] * kernel[14]
00201 - output[-8] * kernel[15]
00202 + input[-8] * kernel[16]
00203 - output[-9] * kernel[17]
00204 + input[-9] * kernel[18]
00205 - output[-10] * kernel[19]
00206 + input[-10] * kernel[20];
00207 ++output;
00208 ++input;
00209
00210 }
00211 }
00212
00213 static void
00214 filterButter(const Float_t * input, Float_t * output, size_t nSamples, const Float_t * const kernel)
00215 {
00216
00217 while (nSamples--) {
00218 *output = input[0] * kernel[0]
00219 - output[-1] * kernel[1]
00220 + input[-1] * kernel[2]
00221 - output[-2] * kernel[3]
00222 + input[-2] * kernel[4];
00223 ++output;
00224 ++input;
00225
00226 }
00227 }
00228
00229
00230
00231
00232 int
00233 ResetSampleFrequency(replaygain_t * rgData, long samplefreq)
00234 {
00235 int i;
00236
00237
00238 for (i = 0; i < MAX_ORDER; i++)
00239 rgData->linprebuf[i] = rgData->lstepbuf[i]
00240 = rgData->loutbuf[i]
00241 = rgData->rinprebuf[i]
00242 = rgData->rstepbuf[i]
00243 = rgData->routbuf[i] = 0.;
00244
00245 switch ((int) (samplefreq)) {
00246 case 48000:
00247 rgData->freqindex = 0;
00248 break;
00249 case 44100:
00250 rgData->freqindex = 1;
00251 break;
00252 case 32000:
00253 rgData->freqindex = 2;
00254 break;
00255 case 24000:
00256 rgData->freqindex = 3;
00257 break;
00258 case 22050:
00259 rgData->freqindex = 4;
00260 break;
00261 case 16000:
00262 rgData->freqindex = 5;
00263 break;
00264 case 12000:
00265 rgData->freqindex = 6;
00266 break;
00267 case 11025:
00268 rgData->freqindex = 7;
00269 break;
00270 case 8000:
00271 rgData->freqindex = 8;
00272 break;
00273 default:
00274 return INIT_GAIN_ANALYSIS_ERROR;
00275 }
00276
00277 rgData->sampleWindow =
00278 (samplefreq * RMS_WINDOW_TIME_NUMERATOR + RMS_WINDOW_TIME_DENOMINATOR -
00279 1) / RMS_WINDOW_TIME_DENOMINATOR;
00280
00281 rgData->lsum = 0.;
00282 rgData->rsum = 0.;
00283 rgData->totsamp = 0;
00284
00285 memset(rgData->A, 0, sizeof(rgData->A));
00286
00287 return INIT_GAIN_ANALYSIS_OK;
00288 }
00289
00290 int
00291 InitGainAnalysis(replaygain_t * rgData, long samplefreq)
00292 {
00293 if (ResetSampleFrequency(rgData, samplefreq) != INIT_GAIN_ANALYSIS_OK) {
00294 return INIT_GAIN_ANALYSIS_ERROR;
00295 }
00296
00297 rgData->linpre = rgData->linprebuf + MAX_ORDER;
00298 rgData->rinpre = rgData->rinprebuf + MAX_ORDER;
00299 rgData->lstep = rgData->lstepbuf + MAX_ORDER;
00300 rgData->rstep = rgData->rstepbuf + MAX_ORDER;
00301 rgData->lout = rgData->loutbuf + MAX_ORDER;
00302 rgData->rout = rgData->routbuf + MAX_ORDER;
00303
00304 memset(rgData->B, 0, sizeof(rgData->B));
00305
00306 return INIT_GAIN_ANALYSIS_OK;
00307 }
00308
00309
00310
00311 static inline double
00312 fsqr(const double d)
00313 {
00314 return d * d;
00315 }
00316
00317 int
00318 AnalyzeSamples(replaygain_t * rgData, const Float_t * left_samples, const Float_t * right_samples,
00319 size_t num_samples, int num_channels)
00320 {
00321 const Float_t *curleft;
00322 const Float_t *curright;
00323 long batchsamples;
00324 long cursamples;
00325 long cursamplepos;
00326 int i;
00327
00328 if (num_samples == 0)
00329 return GAIN_ANALYSIS_OK;
00330
00331 cursamplepos = 0;
00332 batchsamples = (long)num_samples;
00333
00334 switch (num_channels) {
00335 case 1:
00336 right_samples = left_samples;
00337 case 2:
00338 break;
00339 default:
00340 return GAIN_ANALYSIS_ERROR;
00341 }
00342
00343 if (num_samples < MAX_ORDER) {
00344 memcpy(rgData->linprebuf + MAX_ORDER, left_samples, num_samples * sizeof(Float_t));
00345 memcpy(rgData->rinprebuf + MAX_ORDER, right_samples, num_samples * sizeof(Float_t));
00346 }
00347 else {
00348 memcpy(rgData->linprebuf + MAX_ORDER, left_samples, MAX_ORDER * sizeof(Float_t));
00349 memcpy(rgData->rinprebuf + MAX_ORDER, right_samples, MAX_ORDER * sizeof(Float_t));
00350 }
00351
00352 while (batchsamples > 0) {
00353 cursamples = batchsamples > rgData->sampleWindow - rgData->totsamp ?
00354 rgData->sampleWindow - rgData->totsamp : batchsamples;
00355 if (cursamplepos < MAX_ORDER) {
00356 curleft = rgData->linpre + cursamplepos;
00357 curright = rgData->rinpre + cursamplepos;
00358 if (cursamples > MAX_ORDER - cursamplepos)
00359 cursamples = MAX_ORDER - cursamplepos;
00360 }
00361 else {
00362 curleft = left_samples + cursamplepos;
00363 curright = right_samples + cursamplepos;
00364 }
00365
00366 YULE_FILTER(curleft, rgData->lstep + rgData->totsamp, cursamples,
00367 ABYule[rgData->freqindex]);
00368 YULE_FILTER(curright, rgData->rstep + rgData->totsamp, cursamples,
00369 ABYule[rgData->freqindex]);
00370
00371 BUTTER_FILTER(rgData->lstep + rgData->totsamp, rgData->lout + rgData->totsamp, cursamples,
00372 ABButter[rgData->freqindex]);
00373 BUTTER_FILTER(rgData->rstep + rgData->totsamp, rgData->rout + rgData->totsamp, cursamples,
00374 ABButter[rgData->freqindex]);
00375
00376 curleft = rgData->lout + rgData->totsamp;
00377 curright = rgData->rout + rgData->totsamp;
00378
00379 i = cursamples % 8;
00380 while (i--) {
00381 rgData->lsum += fsqr(*curleft++);
00382 rgData->rsum += fsqr(*curright++);
00383 }
00384 i = cursamples / 8;
00385 while (i--) {
00386 rgData->lsum += fsqr(curleft[0])
00387 + fsqr(curleft[1])
00388 + fsqr(curleft[2])
00389 + fsqr(curleft[3])
00390 + fsqr(curleft[4])
00391 + fsqr(curleft[5])
00392 + fsqr(curleft[6])
00393 + fsqr(curleft[7]);
00394 curleft += 8;
00395 rgData->rsum += fsqr(curright[0])
00396 + fsqr(curright[1])
00397 + fsqr(curright[2])
00398 + fsqr(curright[3])
00399 + fsqr(curright[4])
00400 + fsqr(curright[5])
00401 + fsqr(curright[6])
00402 + fsqr(curright[7]);
00403 curright += 8;
00404 }
00405
00406 batchsamples -= cursamples;
00407 cursamplepos += cursamples;
00408 rgData->totsamp += cursamples;
00409 if (rgData->totsamp == rgData->sampleWindow) {
00410 double const val =
00411 STEPS_per_dB * 10. * log10((rgData->lsum + rgData->rsum) / rgData->totsamp * 0.5 +
00412 1.e-37);
00413 int ival = (int) val;
00414 if (ival < 0)
00415 ival = 0;
00416 if (ival >= sizeof(rgData->A) / sizeof(*(rgData->A)))
00417 ival = sizeof(rgData->A) / sizeof(*(rgData->A)) - 1;
00418 rgData->A[ival]++;
00419 rgData->lsum = rgData->rsum = 0.;
00420 memmove(rgData->loutbuf, rgData->loutbuf + rgData->totsamp,
00421 MAX_ORDER * sizeof(Float_t));
00422 memmove(rgData->routbuf, rgData->routbuf + rgData->totsamp,
00423 MAX_ORDER * sizeof(Float_t));
00424 memmove(rgData->lstepbuf, rgData->lstepbuf + rgData->totsamp,
00425 MAX_ORDER * sizeof(Float_t));
00426 memmove(rgData->rstepbuf, rgData->rstepbuf + rgData->totsamp,
00427 MAX_ORDER * sizeof(Float_t));
00428 rgData->totsamp = 0;
00429 }
00430 if (rgData->totsamp > rgData->sampleWindow)
00431 return GAIN_ANALYSIS_ERROR;
00432 }
00433 if (num_samples < MAX_ORDER) {
00434 memmove(rgData->linprebuf, rgData->linprebuf + num_samples,
00435 (MAX_ORDER - num_samples) * sizeof(Float_t));
00436 memmove(rgData->rinprebuf, rgData->rinprebuf + num_samples,
00437 (MAX_ORDER - num_samples) * sizeof(Float_t));
00438 memcpy(rgData->linprebuf + MAX_ORDER - num_samples, left_samples,
00439 num_samples * sizeof(Float_t));
00440 memcpy(rgData->rinprebuf + MAX_ORDER - num_samples, right_samples,
00441 num_samples * sizeof(Float_t));
00442 }
00443 else {
00444 memcpy(rgData->linprebuf, left_samples + num_samples - MAX_ORDER,
00445 MAX_ORDER * sizeof(Float_t));
00446 memcpy(rgData->rinprebuf, right_samples + num_samples - MAX_ORDER,
00447 MAX_ORDER * sizeof(Float_t));
00448 }
00449
00450 return GAIN_ANALYSIS_OK;
00451 }
00452
00453
00454 static Float_t
00455 analyzeResult(uint32_t const *Array, size_t len)
00456 {
00457 uint32_t elems;
00458 int32_t upper;
00459 size_t i;
00460
00461 elems = 0;
00462 for (i = 0; i < len; i++)
00463 elems += Array[i];
00464 if (elems == 0)
00465 return GAIN_NOT_ENOUGH_SAMPLES;
00466
00467 upper = (int32_t) ceil(elems * (1. - RMS_PERCENTILE));
00468 for (i = len; i-- > 0;) {
00469 if ((upper -= Array[i]) <= 0)
00470 break;
00471 }
00472
00473 return (Float_t) ((Float_t) PINK_REF - (Float_t) i / (Float_t) STEPS_per_dB);
00474 }
00475
00476
00477 Float_t
00478 GetTitleGain(replaygain_t * rgData)
00479 {
00480 Float_t retval;
00481 unsigned int i;
00482
00483 retval = analyzeResult(rgData->A, sizeof(rgData->A) / sizeof(*(rgData->A)));
00484
00485 for (i = 0; i < sizeof(rgData->A) / sizeof(*(rgData->A)); i++) {
00486 rgData->B[i] += rgData->A[i];
00487 rgData->A[i] = 0;
00488 }
00489
00490 for (i = 0; i < MAX_ORDER; i++)
00491 rgData->linprebuf[i] = rgData->lstepbuf[i]
00492 = rgData->loutbuf[i]
00493 = rgData->rinprebuf[i]
00494 = rgData->rstepbuf[i]
00495 = rgData->routbuf[i] = 0.f;
00496
00497 rgData->totsamp = 0;
00498 rgData->lsum = rgData->rsum = 0.;
00499 return retval;
00500 }
00501
00502
00503 Float_t
00504 GetAlbumGain(replaygain_t * rgData)
00505 {
00506 return analyzeResult(rgData->B, sizeof(rgData->B) / sizeof(*(rgData->B)));
00507 }
00508
00509