1 #include <Python.h>
2 #include "mod_defs.h"
3 #include "pcm.h"
4 #include "pcmconv.h"
5 #include "bitstream.h"
6 #include "array.h"
7 #include "dither.c"
8 #include "replaygain.h"
9
10 /*
11 * ReplayGainAnalysis - analyzes input samples and give the recommended dB change
12 * Copyright (C) 2001 David Robinson and Glen Sawyer
13 * Modified 2010 by Brian Langenberger for use in Python Audio Tools
14 *
15 * This library is free software; you can redistribute it and/or
16 * modify it under the terms of the GNU Lesser General Public
17 * License as published by the Free Software Foundation; either
18 * version 2.1 of the License, or (at your option) any later version.
19 *
20 * This library is distributed in the hope that it will be useful,
21 * but WITHOUT ANY WARRANTY; without even the implied warranty of
22 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
23 * Lesser General Public License for more details.
24 *
25 * You should have received a copy of the GNU Lesser General Public
26 * License along with this library; if not, write to the Free Software
27 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
28 *
29 * concept and filter values by David Robinson (David@Robinson.org)
30 * -- blame him if you think the idea is flawed
31 * coding by Glen Sawyer (mp3gain@hotmail.com) 735 W 255 N, Orem, UT 84057-4505 USA
32 * -- blame him if you think this runs too slowly, or the coding is otherwise flawed
33 *
34 * For an explanation of the concepts and the basic algorithms involved, go to:
35 * http://www.replaygain.org/
36 */
37
38 #ifndef MIN
39 #define MIN(x, y) ((x) < (y) ? (x) : (y))
40 #endif
41 #ifndef MAX
42 #define MAX(x, y) ((x) > (y) ? (x) : (y))
43 #endif
44
45 PyMethodDef module_methods[] = {
46 {NULL}
47 };
48
49 PyGetSetDef ReplayGain_getseters[] = {
50 {"sample_rate",
51 (getter)ReplayGain_sample_rate, NULL, "sample rate", NULL},
52 {NULL}
53 };
54
55 PyMethodDef ReplayGain_methods[] = {
56 {"update", (PyCFunction)ReplayGain_update,
57 METH_VARARGS, "update(FrameList) -> None"},
58 {"title_gain", (PyCFunction)ReplayGain_title_gain,
59 METH_NOARGS, "title_gain() -> title gain float"},
60 {"title_peak", (PyCFunction)ReplayGain_title_peak,
61 METH_NOARGS, "title_peak() -> title peak float"},
62 {"album_gain", (PyCFunction)ReplayGain_album_gain,
63 METH_NOARGS, "album_gain() -> album gain float"},
64 {"album_peak", (PyCFunction)ReplayGain_album_peak,
65 METH_NOARGS, "album_peak() -> album peak float"},
66 {"next_title", (PyCFunction)ReplayGain_next_title,
67 METH_NOARGS, "call after each title is completed"},
68 {NULL}
69 };
70
71 PyTypeObject replaygain_ReplayGainType = {
72 PyVarObject_HEAD_INIT(NULL, 0)
73 "replaygain.ReplayGain", /*tp_name*/
74 sizeof(replaygain_ReplayGain), /*tp_basicsize*/
75 0, /*tp_itemsize*/
76 (destructor)ReplayGain_dealloc, /*tp_dealloc*/
77 0, /*tp_print*/
78 0, /*tp_getattr*/
79 0, /*tp_setattr*/
80 0, /*tp_compare*/
81 0, /*tp_repr*/
82 0, /*tp_as_number*/
83 0, /*tp_as_sequence*/
84 0, /*tp_as_mapping*/
85 0, /*tp_hash */
86 0, /*tp_call*/
87 0, /*tp_str*/
88 0, /*tp_getattro*/
89 0, /*tp_setattro*/
90 0, /*tp_as_buffer*/
91 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/
92 "ReplayGain objects", /* tp_doc */
93 0, /* tp_traverse */
94 0, /* tp_clear */
95 0, /* tp_richcompare */
96 0, /* tp_weaklistoffset */
97 0, /* tp_iter */
98 0, /* tp_iternext */
99 ReplayGain_methods, /* tp_methods */
100 0, /* tp_members */
101 ReplayGain_getseters, /* tp_getset */
102 0, /* tp_base */
103 0, /* tp_dict */
104 0, /* tp_descr_get */
105 0, /* tp_descr_set */
106 0, /* tp_dictoffset */
107 (initproc)ReplayGain_init, /* tp_init */
108 0, /* tp_alloc */
109 ReplayGain_new, /* tp_new */
110 };
111
112 void
ReplayGain_dealloc(replaygain_ReplayGain * self)113 ReplayGain_dealloc(replaygain_ReplayGain* self)
114 {
115 Py_XDECREF(self->framelist_type);
116 Py_TYPE(self)->tp_free((PyObject*)self);
117 }
118
119 PyObject*
ReplayGain_new(PyTypeObject * type,PyObject * args,PyObject * kwds)120 ReplayGain_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
121 {
122 replaygain_ReplayGain *self;
123
124 self = (replaygain_ReplayGain *)type->tp_alloc(type, 0);
125
126 return (PyObject *)self;
127 }
128
129 int
ReplayGain_init(replaygain_ReplayGain * self,PyObject * args,PyObject * kwds)130 ReplayGain_init(replaygain_ReplayGain *self, PyObject *args, PyObject *kwds)
131 {
132 long sample_rate;
133 PyObject *audiotools_pcm;
134 int i;
135
136 self->framelist_type = NULL;
137 self->sample_rate = 0;
138 self->title_peak = 0.0;
139 self->album_peak = 0.0;
140
141 if (!PyArg_ParseTuple(args, "l", &sample_rate))
142 return -1;
143
144 /*store FrameList type for later comparison*/
145 if ((audiotools_pcm = PyImport_ImportModule("audiotools.pcm")) != NULL) {
146 self->framelist_type = PyObject_GetAttrString(audiotools_pcm,
147 "FrameList");
148 Py_DECREF(audiotools_pcm);
149 } else {
150 return -1;
151 }
152
153 self->sample_rate = (unsigned)sample_rate;
154
155 /* zero out initial values*/
156 for (i = 0; i < MAX_ORDER; i++ )
157 self->linprebuf[i] =
158 self->lstepbuf[i] =
159 self->loutbuf[i] =
160 self->rinprebuf[i] =
161 self->rstepbuf[i] =
162 self->routbuf[i] = 0.;
163
164 switch (sample_rate) {
165 case 48000: self->freqindex = 0; break;
166 case 44100: self->freqindex = 1; break;
167 case 32000: self->freqindex = 2; break;
168 case 24000: self->freqindex = 3; break;
169 case 22050: self->freqindex = 4; break;
170 case 16000: self->freqindex = 5; break;
171 case 12000: self->freqindex = 6; break;
172 case 11025: self->freqindex = 7; break;
173 case 8000: self->freqindex = 8; break;
174 case 18900: self->freqindex = 9; break;
175 case 37800: self->freqindex = 10; break;
176 case 56000: self->freqindex = 11; break;
177 case 64000: self->freqindex = 12; break;
178 case 88200: self->freqindex = 13; break;
179 case 96000: self->freqindex = 14; break;
180 case 112000: self->freqindex = 15; break;
181 case 128000: self->freqindex = 16; break;
182 case 144000: self->freqindex = 17; break;
183 case 176400: self->freqindex = 18; break;
184 case 192000: self->freqindex = 19; break;
185 default:
186 PyErr_SetString(PyExc_ValueError,"unsupported sample rate");
187 return -1;
188 }
189
190 self->sampleWindow = (int)ceil(sample_rate * RMS_WINDOW_TIME);
191
192 self->lsum = 0.;
193 self->rsum = 0.;
194 self->totsamp = 0;
195
196 memset (self->A, 0, sizeof(self->A));
197
198 self->linpre = self->linprebuf + MAX_ORDER;
199 self->rinpre = self->rinprebuf + MAX_ORDER;
200 self->lstep = self->lstepbuf + MAX_ORDER;
201 self->rstep = self->rstepbuf + MAX_ORDER;
202 self->lout = self->loutbuf + MAX_ORDER;
203 self->rout = self->routbuf + MAX_ORDER;
204
205 memset (self->B, 0, sizeof(self->B));
206
207
208 return 0;
209 }
210
211 PyObject*
ReplayGain_sample_rate(replaygain_ReplayGain * self,void * closure)212 ReplayGain_sample_rate(replaygain_ReplayGain *self, void *closure)
213 {
214 return Py_BuildValue("I", self->sample_rate);
215 }
216
217 PyObject*
ReplayGain_next_title(replaygain_ReplayGain * self)218 ReplayGain_next_title(replaygain_ReplayGain *self)
219 {
220 /*reset initial values for next title*/
221 int i;
222
223 for ( i = 0; i < (int)(sizeof(self->A)/sizeof(*(self->A))); i++ ) {
224 self->B[i] += self->A[i];
225 self->A[i] = 0;
226 }
227
228 for ( i = 0; i < MAX_ORDER; i++ )
229 self->linprebuf[i] =
230 self->lstepbuf[i] =
231 self->loutbuf[i] =
232 self->rinprebuf[i] =
233 self->rstepbuf[i] =
234 self->routbuf[i] = 0.f;
235
236 self->totsamp = 0;
237 self->lsum = self->rsum = 0.;
238
239 self->title_peak = 0.0;
240
241 Py_INCREF(Py_None);
242 return Py_None;
243 }
244
245 PyObject*
ReplayGain_update(replaygain_ReplayGain * self,PyObject * args)246 ReplayGain_update(replaygain_ReplayGain *self, PyObject *args)
247 {
248 pcm_FrameList* framelist;
249 aa_int* channels;
250 aa_double* channels_f;
251 unsigned channel;
252 int32_t peak_shift;
253
254 if (!PyArg_ParseTuple(args, "O!", self->framelist_type, &framelist))
255 return NULL;
256
257 /*if FrameList contains no samples, do nothing*/
258 if (framelist->samples_length == 0) {
259 Py_INCREF(Py_None);
260 return Py_None;
261 }
262
263 channels = aa_int_new();
264
265 /*split FrameList's packed ints into a set of channels
266 to a maximum of 2 channels*/
267 for (channel = 0; channel < MIN(framelist->channels, 2); channel++) {
268 a_int* channel_a = channels->append(channels);
269 unsigned frame;
270 channel_a->resize(channel_a, framelist->frames);
271 for (frame = 0; frame < framelist->frames; frame++) {
272 a_append(channel_a,
273 framelist->samples[(frame * framelist->channels) +
274 channel]);
275 }
276 }
277
278 /*if 1 channel, duplicate to other channel*/
279 if (framelist->channels == 1) {
280 channels->_[0]->copy(channels->_[0], channels->append(channels));
281 }
282
283 /*calculate peak values*/
284 peak_shift = 1 << (framelist->bits_per_sample - 1);
285 for (channel = 0; channel < 2; channel++) {
286 a_int* channel_i = channels->_[channel];
287 int i;
288
289 for (i = 0; i < channel_i->len; i++) {
290 const double peak = ((double)(abs(channel_i->_[i])) / peak_shift);
291 self->title_peak = MAX(self->title_peak, peak);
292 self->album_peak = MAX(self->album_peak, peak);
293 }
294 }
295
296 /*convert left and right channels to 16-bit doubles*/
297 channels_f = aa_double_new();
298 for (channel = 0; channel < 2; channel++) {
299 a_int* channel_i = channels->_[channel];
300 a_double* channel_f = channels_f->append(channels_f);
301 int i;
302
303 channel_f->resize(channel_f, channel_i->len);
304
305 switch (framelist->bits_per_sample) {
306 case 8:
307 for (i = 0; i < channel_i->len; i++) {
308 a_append(channel_f, (double)(channel_i->_[i] << 8));
309 }
310 break;
311 case 16:
312 for (i = 0; i < channel_i->len; i++) {
313 a_append(channel_f, (double)(channel_i->_[i]));
314 }
315 break;
316 case 24:
317 for (i = 0; i < channel_i->len; i++) {
318 a_append(channel_f, (double)(channel_i->_[i] >> 8));
319 }
320 break;
321 default:
322 PyErr_SetString(PyExc_ValueError,
323 "unsupported bits per sample");
324 channels->del(channels);
325 channels_f->del(channels_f);
326 return NULL;
327 }
328 }
329
330 /*perform gain analysis on channels*/
331 if (ReplayGain_analyze_samples(self,
332 channels_f->_[0]->_,
333 channels_f->_[1]->_,
334 channels_f->_[0]->len,
335 2) == GAIN_ANALYSIS_ERROR) {
336 PyErr_SetString(PyExc_ValueError, "ReplayGain calculation error");
337 channels->del(channels);
338 channels_f->del(channels_f);
339 return NULL;
340 }
341
342 /*remove temporary arrays and return None*/
343 channels->del(channels);
344 channels_f->del(channels_f);
345
346 Py_INCREF(Py_None);
347 return Py_None;
348 }
349
350 PyObject*
ReplayGain_title_gain(replaygain_ReplayGain * self)351 ReplayGain_title_gain(replaygain_ReplayGain *self)
352 {
353 const double gain_value = ReplayGain_get_title_gain(self);
354 if (gain_value != GAIN_NOT_ENOUGH_SAMPLES) {
355 return Py_BuildValue("d", gain_value);
356 } else {
357 PyErr_SetString(PyExc_ValueError,
358 "Not enough samples to perform calculation");
359 return NULL;
360 }
361 }
362
363 PyObject*
ReplayGain_title_peak(replaygain_ReplayGain * self)364 ReplayGain_title_peak(replaygain_ReplayGain *self)
365 {
366 return Py_BuildValue("d", self->title_peak);
367 }
368
369 PyObject*
ReplayGain_album_gain(replaygain_ReplayGain * self)370 ReplayGain_album_gain(replaygain_ReplayGain *self)
371 {
372 const double gain_value = ReplayGain_get_album_gain(self);
373 if (gain_value != GAIN_NOT_ENOUGH_SAMPLES) {
374 return Py_BuildValue("d", gain_value);
375 } else {
376 PyErr_SetString(PyExc_ValueError,
377 "Not enough samples to perform calculation");
378 return NULL;
379 }
380 }
381
382 PyObject*
ReplayGain_album_peak(replaygain_ReplayGain * self)383 ReplayGain_album_peak(replaygain_ReplayGain *self)
384 {
385 return Py_BuildValue("d", self->album_peak);
386 }
387
388 PyGetSetDef ReplayGainReader_getseters[] = {
389 {"sample_rate",
390 (getter)ReplayGainReader_sample_rate, NULL, "sample rate", NULL},
391 {"bits_per_sample",
392 (getter)ReplayGainReader_bits_per_sample, NULL, "bits per sample", NULL},
393 {"channels",
394 (getter)ReplayGainReader_channels, NULL, "channels", NULL},
395 {"channel_mask",
396 (getter)ReplayGainReader_channel_mask, NULL, "channel_mask", NULL},
397 {NULL}
398 };
399
400 PyMethodDef ReplayGainReader_methods[] = {
401 {"read", (PyCFunction)ReplayGainReader_read,
402 METH_VARARGS,
403 "Reads a pcm.FrameList with ReplayGain applied"},
404 {"close", (PyCFunction)ReplayGainReader_close,
405 METH_NOARGS, "Closes the substream"},
406 {NULL}
407 };
408
409 PyTypeObject replaygain_ReplayGainReaderType = {
410 PyVarObject_HEAD_INIT(NULL, 0)
411 "replaygain.ReplayGainReader", /*tp_name*/
412 sizeof(replaygain_ReplayGainReader), /*tp_basicsize*/
413 0, /*tp_itemsize*/
414 (destructor)ReplayGainReader_dealloc, /*tp_dealloc*/
415 0, /*tp_print*/
416 0, /*tp_getattr*/
417 0, /*tp_setattr*/
418 0, /*tp_compare*/
419 0, /*tp_repr*/
420 0, /*tp_as_number*/
421 0, /*tp_as_sequence*/
422 0, /*tp_as_mapping*/
423 0, /*tp_hash */
424 0, /*tp_call*/
425 0, /*tp_str*/
426 0, /*tp_getattro*/
427 0, /*tp_setattro*/
428 0, /*tp_as_buffer*/
429 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/
430 "ReplayGainReader objects",/* tp_doc */
431 0, /* tp_traverse */
432 0, /* tp_clear */
433 0, /* tp_richcompare */
434 0, /* tp_weaklistoffset */
435 0, /* tp_iter */
436 0, /* tp_iternext */
437 ReplayGainReader_methods, /* tp_methods */
438 0, /* tp_members */
439 ReplayGainReader_getseters,/* tp_getset */
440 0, /* tp_base */
441 0, /* tp_dict */
442 0, /* tp_descr_get */
443 0, /* tp_descr_set */
444 0, /* tp_dictoffset */
445 (initproc)ReplayGainReader_init, /* tp_init */
446 0, /* tp_alloc */
447 ReplayGainReader_new, /* tp_new */
448 };
449
450
451
MOD_INIT(replaygain)452 MOD_INIT(replaygain)
453 {
454 PyObject* m;
455
456 MOD_DEF(m, "replaygain",
457 "a ReplayGain calculation and synthesis module",
458 module_methods)
459
460 replaygain_ReplayGainType.tp_new = PyType_GenericNew;
461 if (PyType_Ready(&replaygain_ReplayGainType) < 0)
462 return MOD_ERROR_VAL;
463
464 replaygain_ReplayGainReaderType.tp_new = PyType_GenericNew;
465 if (PyType_Ready(&replaygain_ReplayGainReaderType) < 0)
466 return MOD_ERROR_VAL;
467
468 Py_INCREF(&replaygain_ReplayGainType);
469 PyModule_AddObject(m, "ReplayGain",
470 (PyObject *)&replaygain_ReplayGainType);
471
472 Py_INCREF(&replaygain_ReplayGainReaderType);
473 PyModule_AddObject(m, "ReplayGainReader",
474 (PyObject *)&replaygain_ReplayGainReaderType);
475
476 return MOD_SUCCESS_VAL(m);
477 }
478
479
480
481
482 /* for each filter: */
483 /* [0] 48 kHz, [1] 44.1 kHz, [2] 32 kHz, [3] 24 kHz, [4] 22050 Hz, [5] 16 kHz, [6] 12 kHz, [7] is 11025 Hz, [8] 8 kHz */
484
485 static const double ABYule[20][2*YULE_ORDER + 1] = {
486 /*48000Hz*/
487 {0.03857599435200, -3.84664617118067, -0.02160367184185, 7.81501653005538, -0.00123395316851,-11.34170355132042, -0.00009291677959, 13.05504219327545, -0.01655260341619,-12.28759895145294, 0.02161526843274, 9.48293806319790, -0.02074045215285, -5.87257861775999, 0.00594298065125, 2.75465861874613, 0.00306428023191, -0.86984376593551, 0.00012025322027, 0.13919314567432, 0.00288463683916 },
488
489 /*44100Hz*/
490 {0.05418656406430, -3.47845948550071, -0.02911007808948, 6.36317777566148, -0.00848709379851, -8.54751527471874, -0.00851165645469, 9.47693607801280, -0.00834990904936, -8.81498681370155, 0.02245293253339, 6.85401540936998, -0.02596338512915, -4.39470996079559, 0.01624864962975, 2.19611684890774, -0.00240879051584, -0.75104302451432, 0.00674613682247, 0.13149317958808, -0.00187763777362 },
491
492 /*32000Hz*/
493 {0.15457299681924, -2.37898834973084, -0.09331049056315, 2.84868151156327, -0.06247880153653, -2.64577170229825, 0.02163541888798, 2.23697657451713, -0.05588393329856, -1.67148153367602, 0.04781476674921, 1.00595954808547, 0.00222312597743, -0.45953458054983, 0.03174092540049, 0.16378164858596, -0.01390589421898, -0.05032077717131, 0.00651420667831, 0.02347897407020, -0.00881362733839 },
494
495 /*24000Hz*/
496 {0.30296907319327, -1.61273165137247, -0.22613988682123, 1.07977492259970, -0.08587323730772, -0.25656257754070, 0.03282930172664, -0.16276719120440, -0.00915702933434, -0.22638893773906, -0.02364141202522, 0.39120800788284, -0.00584456039913, -0.22138138954925, 0.06276101321749, 0.04500235387352, -0.00000828086748, 0.02005851806501, 0.00205861885564, 0.00302439095741, -0.02950134983287 },
497
498 /*22050Hz*/
499 {0.33642304856132, -1.49858979367799, -0.25572241425570, 0.87350271418188, -0.11828570177555, 0.12205022308084, 0.11921148675203, -0.80774944671438, -0.07834489609479, 0.47854794562326, -0.00469977914380, -0.12453458140019, -0.00589500224440, -0.04067510197014, 0.05724228140351, 0.08333755284107, 0.00832043980773, -0.04237348025746, -0.01635381384540, 0.02977207319925, -0.01760176568150 },
500
501 /*16000Hz*/
502 {0.44915256608450, -0.62820619233671, -0.14351757464547, 0.29661783706366, -0.22784394429749, -0.37256372942400, -0.01419140100551, 0.00213767857124, 0.04078262797139, -0.42029820170918, -0.12398163381748, 0.22199650564824, 0.04097565135648, 0.00613424350682, 0.10478503600251, 0.06747620744683, -0.01863887810927, 0.05784820375801, -0.03193428438915, 0.03222754072173, 0.00541907748707 },
503
504 /*12000Hz*/
505 {0.56619470757641, -1.04800335126349, -0.75464456939302, 0.29156311971249, 0.16242137742230, -0.26806001042947, 0.16744243493672, 0.00819999645858, -0.18901604199609, 0.45054734505008, 0.30931782841830, -0.33032403314006, -0.27562961986224, 0.06739368333110, 0.00647310677246, -0.04784254229033, 0.08647503780351, 0.01639907836189, -0.03788984554840, 0.01807364323573, -0.00588215443421 },
506
507 /*11025Hz*/
508 {0.58100494960553, -0.51035327095184, -0.53174909058578, -0.31863563325245, -0.14289799034253, -0.20256413484477, 0.17520704835522, 0.14728154134330, 0.02377945217615, 0.38952639978999, 0.15558449135573, -0.23313271880868, -0.25344790059353, -0.05246019024463, 0.01628462406333, -0.02505961724053, 0.06920467763959, 0.02442357316099, -0.03721611395801, 0.01818801111503, -0.00749618797172 },
509
510 /*8000Hz*/
511 {0.53648789255105, -0.25049871956020, -0.42163034350696, -0.43193942311114, -0.00275953611929, -0.03424681017675, 0.04267842219415, -0.04678328784242, -0.10214864179676, 0.26408300200955, 0.14590772289388, 0.15113130533216, -0.02459864859345, -0.17556493366449, -0.11202315195388, -0.18823009262115, -0.04060034127000, 0.05477720428674, 0.04788665548180, 0.04704409688120, -0.02217936801134 },
512
513
514 /*18900Hz*/
515 {0.38524531015142, -1.29708918404534, -0.27682212062067, 0.90399339674203, -0.09980181488805, -0.29613799017877, 0.09951486755646, -0.42326645916207, -0.08934020156622, 0.37934887402200, -0.00322369330199, -0.37919795944938, -0.00110329090689, 0.23410283284785, 0.03784509844682, -0.03892971758879, 0.01683906213303, 0.00403009552351, -0.01147039862572, 0.03640166626278, -0.01941767987192 },
516
517 /*37800Hz*/
518 {0.08717879977844, -2.62816311472146, -0.01000374016172, 3.53734535817992, -0.06265852122368, -3.81003448678921, -0.01119328800950, 3.91291636730132, -0.00114279372960, -3.53518605896288, 0.02081333954769, 2.71356866157873, -0.01603261863207, -1.86723311846592, 0.01936763028546, 1.12075382367659, 0.00760044736442, -0.48574086886890, -0.00303979112271, 0.11330544663849, -0.00075088605788 },
519
520 /*56000Hz*/
521 {0.03144914734085, -4.87377313090032, -0.06151729206963, 12.03922160140209, 0.08066788708145, -20.10151118381395, -0.09737939921516, 25.10388534415171, 0.08943210803999, -24.29065560815903, -0.06989984672010, 18.27158469090663, 0.04926972841044, -10.45249552560593, -0.03161257848451, 4.30319491872003, 0.01456837493506, -1.13716992070185, -0.00316015108496, 0.14510733527035, 0.00132807215875 },
522
523 /*64000Hz*/
524 {0.02613056568174, -5.73625477092119, -0.08128786488109, 16.15249794355035, 0.14937282347325, -29.68654912464508, -0.21695711675126, 39.55706155674083, 0.25010286673402, -39.82524556246253, -0.23162283619278, 30.50605345013009, 0.17424041833052, -17.43051772821245, -0.10299599216680, 7.05154573908017, 0.04258696481981, -1.80783839720514, -0.00977952936493, 0.22127840210813, 0.00105325558889 },
525
526 /*88200Hz*/
527 {0.02667482047416, -6.31836451657302, -0.11377479336097, 18.31351310801799, 0.23063167910965, -31.88210014815921, -0.30726477945593, 36.53792146976740, 0.33188520686529, -28.23393036467559, -0.33862680249063, 14.24725258227189, 0.31807161531340, -4.04670980012854, -0.23730796929880, 0.18865757280515, 0.12273894790371, 0.25420333563908, -0.03840017967282, -0.06012333531065, 0.00549673387936 },
528
529 /*96000Hz*/
530 {0.00588138296683, -5.97808823642008, -0.01613559730421, 16.21362507964068, 0.02184798954216, -25.72923730652599, -0.01742490405317, 25.40470663139513, 0.00464635643780, -14.66166287771134, 0.01117772513205, 2.81597484359752, -0.02123865824368, 2.51447125969733, 0.01959354413350, -2.23575306985286, -0.01079720643523, 0.75788151036791, 0.00352183686289, -0.10078025199029, -0.00063124341421 },
531
532 /*112000Hz*/
533 {0.00528778718259, -6.24932108456288, -0.01893240907245, 17.42344320538476, 0.03185982561867, -27.86819709054896, -0.02926260297838, 26.79087344681326, 0.00715743034072, -13.43711081485123, 0.01985743355827, -0.66023612948173, -0.03222614850941, 6.03658091814935, 0.02565681978192, -4.24926577030310, -0.01210662313473, 1.40829268709186, 0.00325436284541, -0.19480852628112, -0.00044173593001 },
534
535 /*128000Hz*/
536 {0.00553120584305, -6.14581710839925, -0.02112620545016, 16.04785903675838, 0.03549076243117, -22.19089131407749, -0.03362498312306, 15.24756471580286, 0.01425867248183, -0.52001440400238, 0.01344686928787, -8.00488641699940, -0.03392770787836, 6.60916094768855, 0.03464136459530, -2.37856022810923, -0.02039116051549, 0.33106947986101, 0.00667420794705, 0.00459820832036, -0.00093763762995 },
537
538 /*144000Hz*/
539 {0.00639682359450, -6.14814623523425, -0.02556437970955, 15.80002457141566, 0.04230854400938, -20.78487587686937, -0.03722462201267, 11.98848552310315, 0.01718514827295, 3.36462015062606, 0.00610592243009, -10.22419868359470, -0.03065965747365, 6.65599702146473, 0.04345745003539, -1.67141861110485, -0.03298592681309, -0.05417956536718, 0.01320937236809, 0.07374767867406, -0.00220304127757 },
540
541 /*176400Hz*/
542 {0.00268568524529, -5.57512782763045, -0.00852379426080, 12.44291056065794, 0.00852704191347, -12.87462799681221, 0.00146116310295, 3.08554846961576, -0.00950855828762, 6.62493459880692, 0.00625449515499, -7.07662766313248, 0.00116183868722, 2.51175542736441, -0.00362461417136, 0.06731510802735, 0.00203961000134, -0.24567753819213, -0.00050664587933, 0.03961404162376, 0.00004327455427 },
543
544 /*192000Hz*/
545 {0.01184742123123, -5.24727318348167, -0.04631092400086, 10.60821585192244, 0.06584226961238, -8.74127665810413, -0.02165588522478, -1.33906071371683, -0.05656260778952, 8.07972882096606, 0.08607493592760, -5.46179918950847, -0.03375544339786, 0.54318070652536, -0.04216579932754, 0.87450969224280, 0.06416711490648, -0.34656083539754, -0.03444708260844, 0.03034796843589, 0.00697275872241 },
546 };
547
548 static const double ABButter[20][2*BUTTER_ORDER + 1] = {
549 /*48000Hz*/
550 {0.98621192462708, -1.97223372919527, -1.97242384925416, 0.97261396931306, 0.98621192462708 },
551
552 /*44100Hz*/
553 {0.98500175787242, -1.96977855582618, -1.97000351574484, 0.97022847566350, 0.98500175787242 },
554
555 /*32000Hz*/
556 {0.97938932735214, -1.95835380975398, -1.95877865470428, 0.95920349965459, 0.97938932735214 },
557
558 /*24000Hz*/
559 {0.97531843204928, -1.95002759149878, -1.95063686409857, 0.95124613669835, 0.97531843204928 },
560
561 /*22050Hz*/
562 {0.97316523498161, -1.94561023566527, -1.94633046996323, 0.94705070426118, 0.97316523498161 },
563
564 /*16000Hz*/
565 {0.96454515552826, -1.92783286977036, -1.92909031105652, 0.93034775234268, 0.96454515552826 },
566
567 /*12000Hz*/
568 {0.96009142950541, -1.91858953033784, -1.92018285901082, 0.92177618768381, 0.96009142950541 },
569
570 /*11025Hz*/
571 {0.95856916599601, -1.91542108074780, -1.91713833199203, 0.91885558323625, 0.95856916599601 },
572
573 /*8000Hz*/
574 {0.94597685600279, -1.88903307939452, -1.89195371200558, 0.89487434461664, 0.94597685600279 },
575
576 /*18900Hz*/
577 {0.96535326815829, -1.92950577983524, -1.93070653631658, 0.93190729279793, 0.96535326815829 },
578
579 /*37800Hz*/
580 {0.98252400815195, -1.96474258269041, -1.96504801630391, 0.96535344991740, 0.98252400815195 },
581
582 /*56000Hz*/
583 {0.98816995007392, -1.97619994516973, -1.97633990014784, 0.97647985512594, 0.98816995007392 },
584
585 /*64000Hz*/
586 {0.98964101933472, -1.97917472731009, -1.97928203866944, 0.97938935002880, 0.98964101933472 },
587
588 /*88200Hz*/
589 {0.99247255046129, -1.98488843762335, -1.98494510092259, 0.98500176422183, 0.99247255046129 },
590
591 /*96000Hz*/
592 {0.99308203517541, -1.98611621154089, -1.98616407035082, 0.98621192916075, 0.99308203517541 },
593
594 /*112000Hz*/
595 {0.99406737810867, -1.98809955990514, -1.98813475621734, 0.98816995252954, 0.99406737810867 },
596
597 /*128000Hz*/
598 {0.99480702681278, -1.98958708647324, -1.98961405362557, 0.98964102077790, 0.99480702681278 },
599
600 /*144000Hz*/
601 {0.99538268958706, -1.99074405950505, -1.99076537917413, 0.99078669884321, 0.99538268958706 },
602
603 /*176400Hz*/
604 {0.99622916581118, -1.99244411238133, -1.99245833162236, 0.99247255086339, 0.99622916581118 },
605
606 /*192000Hz*/
607 {0.99653501465135, -1.99305802314321, -1.99307002930271, 0.99308203546221, 0.99653501465135 }
608 };
609
610
611 /* When calling these filter procedures, make sure that ip[-order] and op[-order] point to real data! */
612
613 /* If your compiler complains that "'operation on 'output' may be undefined", you can */
614 /* either ignore the warnings or uncomment the three "y" lines (and comment out the indicated line) */
615
616 static void
filterYule(const double * input,double * output,size_t nSamples,const double * kernel)617 filterYule (const double* input, double* output, size_t nSamples,
618 const double* kernel)
619 {
620 while (nSamples--) {
621 *output = 1e-10 /* 1e-10 is a hack to avoid slowdown because of denormals */
622 + input [0] * kernel[0]
623 - output[-1] * kernel[1]
624 + input [-1] * kernel[2]
625 - output[-2] * kernel[3]
626 + input [-2] * kernel[4]
627 - output[-3] * kernel[5]
628 + input [-3] * kernel[6]
629 - output[-4] * kernel[7]
630 + input [-4] * kernel[8]
631 - output[-5] * kernel[9]
632 + input [-5] * kernel[10]
633 - output[-6] * kernel[11]
634 + input [-6] * kernel[12]
635 - output[-7] * kernel[13]
636 + input [-7] * kernel[14]
637 - output[-8] * kernel[15]
638 + input [-8] * kernel[16]
639 - output[-9] * kernel[17]
640 + input [-9] * kernel[18]
641 - output[-10]* kernel[19]
642 + input [-10]* kernel[20];
643 ++output;
644 ++input;
645 }
646 }
647
648 static void
filterButter(const double * input,double * output,size_t nSamples,const double * kernel)649 filterButter (const double* input, double* output, size_t nSamples, const double* kernel)
650 {
651 while (nSamples--) {
652 *output =
653 input [0] * kernel[0]
654 - output[-1] * kernel[1]
655 + input [-1] * kernel[2]
656 - output[-2] * kernel[3]
657 + input [-2] * kernel[4];
658 ++output;
659 ++input;
660 }
661 }
662
663 static inline double
fsqr(const double d)664 fsqr(const double d)
665 {
666 return d * d;
667 }
668
669 /* returns GAIN_ANALYSIS_OK if successful, GAIN_ANALYSIS_ERROR if not */
670 gain_calc_status
ReplayGain_analyze_samples(replaygain_ReplayGain * self,const double * left_samples,const double * right_samples,size_t num_samples,int num_channels)671 ReplayGain_analyze_samples(replaygain_ReplayGain* self,
672 const double* left_samples,
673 const double* right_samples,
674 size_t num_samples,
675 int num_channels)
676 {
677 const double* curleft;
678 const double* curright;
679 long batchsamples;
680 long cursamples;
681 long cursamplepos;
682 long i;
683
684 if ( num_samples == 0 )
685 return GAIN_ANALYSIS_OK;
686
687 cursamplepos = 0;
688 batchsamples = num_samples;
689
690 switch ( num_channels) {
691 case 1: right_samples = left_samples;
692 case 2: break;
693 default: return GAIN_ANALYSIS_ERROR;
694 }
695
696 if ( num_samples < MAX_ORDER ) {
697 memcpy (self->linprebuf + MAX_ORDER, left_samples , num_samples * sizeof(double) );
698 memcpy ( self->rinprebuf + MAX_ORDER, right_samples, num_samples * sizeof(double) );
699 }
700 else {
701 memcpy ( self->linprebuf + MAX_ORDER, left_samples, MAX_ORDER * sizeof(double) );
702 memcpy ( self->rinprebuf + MAX_ORDER, right_samples, MAX_ORDER * sizeof(double) );
703 }
704
705 while ( batchsamples > 0 ) {
706 cursamples = batchsamples > self->sampleWindow - self->totsamp ? self->sampleWindow - self->totsamp : batchsamples;
707 if ( cursamplepos < MAX_ORDER ) {
708 curleft = self->linpre + cursamplepos;
709 curright = self->rinpre + cursamplepos;
710 if (cursamples > MAX_ORDER - cursamplepos )
711 cursamples = MAX_ORDER - cursamplepos;
712 }
713 else {
714 curleft = left_samples + cursamplepos;
715 curright = right_samples + cursamplepos;
716 }
717
718 YULE_FILTER ( curleft , self->lstep + self->totsamp, cursamples, ABYule[self->freqindex]);
719 YULE_FILTER ( curright, self->rstep + self->totsamp, cursamples, ABYule[self->freqindex]);
720
721 BUTTER_FILTER ( self->lstep + self->totsamp, self->lout + self->totsamp, cursamples, ABButter[self->freqindex]);
722 BUTTER_FILTER ( self->rstep + self->totsamp, self->rout + self->totsamp, cursamples, ABButter[self->freqindex]);
723
724 curleft = self->lout + self->totsamp; /* Get the squared values */
725 curright = self->rout + self->totsamp;
726
727 i = cursamples % 16;
728 while (i--)
729 { self->lsum += fsqr(*curleft++);
730 self->rsum += fsqr(*curright++);
731 }
732 i = cursamples / 16;
733 while (i--)
734 { self->lsum += fsqr(curleft[0])
735 + fsqr(curleft[1])
736 + fsqr(curleft[2])
737 + fsqr(curleft[3])
738 + fsqr(curleft[4])
739 + fsqr(curleft[5])
740 + fsqr(curleft[6])
741 + fsqr(curleft[7])
742 + fsqr(curleft[8])
743 + fsqr(curleft[9])
744 + fsqr(curleft[10])
745 + fsqr(curleft[11])
746 + fsqr(curleft[12])
747 + fsqr(curleft[13])
748 + fsqr(curleft[14])
749 + fsqr(curleft[15]);
750 curleft += 16;
751 self->rsum += fsqr(curright[0])
752 + fsqr(curright[1])
753 + fsqr(curright[2])
754 + fsqr(curright[3])
755 + fsqr(curright[4])
756 + fsqr(curright[5])
757 + fsqr(curright[6])
758 + fsqr(curright[7])
759 + fsqr(curright[8])
760 + fsqr(curright[9])
761 + fsqr(curright[10])
762 + fsqr(curright[11])
763 + fsqr(curright[12])
764 + fsqr(curright[13])
765 + fsqr(curright[14])
766 + fsqr(curright[15]);
767 curright += 16;
768 }
769
770 batchsamples -= cursamples;
771 cursamplepos += cursamples;
772 self->totsamp += cursamples;
773 if ( self->totsamp == self->sampleWindow ) { /* Get the Root Mean Square (RMS) for this set of samples */
774 double val = STEPS_per_dB * 10. * log10 ( (self->lsum + self->rsum) / self->totsamp * 0.5 + 1.e-37 );
775 int ival = (int) val;
776 if ( ival < 0 ) ival = 0;
777 if ( ival >= (int)(sizeof(self->A)/sizeof(*(self->A))) ) ival = sizeof(self->A)/sizeof(*(self->A)) - 1;
778 self->A [ival]++;
779 self->lsum = self->rsum = 0.;
780 memmove ( self->loutbuf , self->loutbuf + self->totsamp, MAX_ORDER * sizeof(double) );
781 memmove ( self->routbuf , self->routbuf + self->totsamp, MAX_ORDER * sizeof(double) );
782 memmove ( self->lstepbuf, self->lstepbuf + self->totsamp, MAX_ORDER * sizeof(double) );
783 memmove ( self->rstepbuf, self->rstepbuf + self->totsamp, MAX_ORDER * sizeof(double) );
784 self->totsamp = 0;
785 }
786 if ( self->totsamp > self->sampleWindow ) /* somehow I really screwed up: Error in programming! Contact author about self->totsamp > self->sampleWindow */
787 return GAIN_ANALYSIS_ERROR;
788 }
789 if ( num_samples < MAX_ORDER ) {
790 memmove ( self->linprebuf, self->linprebuf + num_samples, (MAX_ORDER-num_samples) * sizeof(double) );
791 memmove ( self->rinprebuf, self->rinprebuf + num_samples, (MAX_ORDER-num_samples) * sizeof(double) );
792 memcpy ( self->linprebuf + MAX_ORDER - num_samples, left_samples, num_samples * sizeof(double) );
793 memcpy ( self->rinprebuf + MAX_ORDER - num_samples, right_samples, num_samples * sizeof(double) );
794 }
795 else {
796 memcpy ( self->linprebuf, left_samples + num_samples - MAX_ORDER, MAX_ORDER * sizeof(double) );
797 memcpy ( self->rinprebuf, right_samples + num_samples - MAX_ORDER, MAX_ORDER * sizeof(double) );
798 }
799
800 return GAIN_ANALYSIS_OK;
801 }
802
803
804 static double
analyzeResult(uint32_t * Array,size_t len)805 analyzeResult(uint32_t* Array, size_t len)
806 {
807 uint32_t elems;
808 int32_t upper;
809 size_t i;
810
811 elems = 0;
812 for ( i = 0; i < len; i++ )
813 elems += Array[i];
814 if ( elems == 0 )
815 return GAIN_NOT_ENOUGH_SAMPLES;
816
817 upper = (int32_t)ceil (elems * (1. - RMS_PERCENTILE));
818 for ( i = len; i-- > 0; ) {
819 if ( (upper -= Array[i]) <= 0 )
820 break;
821 }
822
823 return (double) ((double)PINK_REF - (double)i / (double)STEPS_per_dB);
824 }
825
826
827 double
ReplayGain_get_title_gain(replaygain_ReplayGain * self)828 ReplayGain_get_title_gain(replaygain_ReplayGain *self)
829 {
830 return analyzeResult(self->A, sizeof(self->A)/sizeof(*(self->A)) );
831 }
832
833
834 double
ReplayGain_get_album_gain(replaygain_ReplayGain * self)835 ReplayGain_get_album_gain(replaygain_ReplayGain *self)
836 {
837 return analyzeResult(self->B, sizeof(self->B)/sizeof(*(self->B)) );
838 }
839
840
841 PyObject*
ReplayGainReader_new(PyTypeObject * type,PyObject * args,PyObject * kwds)842 ReplayGainReader_new(PyTypeObject *type, PyObject *args, PyObject *kwds) {
843 replaygain_ReplayGainReader *self;
844
845 self = (replaygain_ReplayGainReader *)type->tp_alloc(type, 0);
846
847 return (PyObject *)self;
848 }
849
850 int
ReplayGainReader_init(replaygain_ReplayGainReader * self,PyObject * args,PyObject * kwds)851 ReplayGainReader_init(replaygain_ReplayGainReader *self,
852 PyObject *args, PyObject *kwds) {
853 self->pcmreader = NULL;
854 self->channels = aa_int_new();
855 self->white_noise = NULL;
856 self->audiotools_pcm = NULL;
857
858 double replaygain;
859 double peak;
860
861 if (!PyArg_ParseTuple(args, "O&dd",
862 pcmreader_converter, &(self->pcmreader),
863 &(replaygain),
864 &(peak)))
865 return -1;
866
867 if ((self->white_noise = open_dither()) == NULL)
868 return -1;
869
870 if ((self->audiotools_pcm = open_audiotools_pcm()) == NULL)
871 return -1;
872
873 self->multiplier = powl(10.0l, replaygain / 20.0l);
874 if (self->multiplier > 1.0l)
875 self->multiplier = 1.0l / peak;
876
877 return 0;
878 }
879
880 void
ReplayGainReader_dealloc(replaygain_ReplayGainReader * self)881 ReplayGainReader_dealloc(replaygain_ReplayGainReader* self) {
882 if (self->pcmreader != NULL)
883 self->pcmreader->del(self->pcmreader);
884 self->channels = aa_int_new();
885 if (self->white_noise != NULL)
886 self->white_noise->close(self->white_noise);
887 Py_XDECREF(self->audiotools_pcm);
888
889 Py_TYPE(self)->tp_free((PyObject*)self);
890 }
891
892 static PyObject*
ReplayGainReader_sample_rate(replaygain_ReplayGainReader * self,void * closure)893 ReplayGainReader_sample_rate(replaygain_ReplayGainReader *self,
894 void *closure) {
895 return Py_BuildValue("i", self->pcmreader->sample_rate);
896 }
897
898 static PyObject*
ReplayGainReader_bits_per_sample(replaygain_ReplayGainReader * self,void * closure)899 ReplayGainReader_bits_per_sample(replaygain_ReplayGainReader *self,
900 void *closure) {
901 return Py_BuildValue("i", self->pcmreader->bits_per_sample);
902 }
903
904 static PyObject*
ReplayGainReader_channels(replaygain_ReplayGainReader * self,void * closure)905 ReplayGainReader_channels(replaygain_ReplayGainReader *self,
906 void *closure) {
907 return Py_BuildValue("i", self->pcmreader->channels);
908 }
909
910 static PyObject*
ReplayGainReader_channel_mask(replaygain_ReplayGainReader * self,void * closure)911 ReplayGainReader_channel_mask(replaygain_ReplayGainReader *self,
912 void *closure) {
913 return Py_BuildValue("i", self->pcmreader->channel_mask);
914 }
915
916 static PyObject*
ReplayGainReader_read(replaygain_ReplayGainReader * self,PyObject * args)917 ReplayGainReader_read(replaygain_ReplayGainReader* self, PyObject *args) {
918 int pcm_frames = 0;
919 aa_int* channels = self->channels;
920 unsigned c;
921
922 const int max_value = (1 << (self->pcmreader->bits_per_sample - 1)) - 1;
923 const int min_value = -(1 << (self->pcmreader->bits_per_sample - 1));
924 const double multiplier = self->multiplier;
925
926 if (!PyArg_ParseTuple(args, "i", &pcm_frames))
927 return NULL;
928
929 if (pcm_frames <= 0) {
930 PyErr_SetString(PyExc_ValueError, "pcm_frames must be positive");
931 return NULL;
932 }
933
934 /*read FrameList object from internal PCMReader*/
935 if (self->pcmreader->read(self->pcmreader,
936 (unsigned)pcm_frames,
937 channels))
938 return NULL;
939
940 /*apply our multiplier to framelist's integer samples
941 and apply dithering*/
942 for (c = 0; c < channels->len; c++) {
943 a_int* channel = channels->_[c];
944 unsigned i;
945 for (i = 0; i < channel->len; i++) {
946 channel->_[i] = (int)lround(channel->_[i] * multiplier);
947 channel->_[i] = (MIN(MAX(channel->_[i], min_value), max_value) ^
948 self->white_noise->read(self->white_noise, 1));
949 }
950 }
951
952 /*return integer samples as a new FrameList object*/
953 return aa_int_to_FrameList(self->audiotools_pcm,
954 channels,
955 self->pcmreader->bits_per_sample);
956 }
957
958 static PyObject*
ReplayGainReader_close(replaygain_ReplayGainReader * self,PyObject * args)959 ReplayGainReader_close(replaygain_ReplayGainReader* self, PyObject *args) {
960 self->pcmreader->close(self->pcmreader);
961 Py_INCREF(Py_None);
962 return Py_None;
963 }
964