Updated MediaInfo binaries to v19.07 (2019-07-16), compiled with ICL 19.0 and MSVC...
[LameXP.git] / etc / Patches / SoX-v14.4.2-DynamicAudioNormalizer.V1.diff
blob67870f4edd66ab6dfbd6206f20ff5c1bd8524ba2
1 src/DynamicAudioNormalizerSoX.c | 479 ++++++++++++++++++++++++++++++++++++++++
2 src/effects.h | 1 +
3 2 files changed, 480 insertions(+)
5 diff --git a/src/DynamicAudioNormalizerSoX.c b/src/DynamicAudioNormalizerSoX.c
6 new file mode 100644
7 index 0000000..e901f94
8 --- /dev/null
9 +++ b/src/DynamicAudioNormalizerSoX.c
10 @@ -0,0 +1,479 @@
11 +/* ================================================================================== */
12 +/* Dynamic Audio Normalizer - SoX Effect Wrapper */
13 +/* Copyright (c) 2014 LoRd_MuldeR <mulder2@gmx.de>. Some rights reserved. */
14 +/* */
15 +/* Permission is hereby granted, free of charge, to any person obtaining a copy */
16 +/* of this software and associated documentation files (the "Software"), to deal */
17 +/* in the Software without restriction, including without limitation the rights */
18 +/* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell */
19 +/* copies of the Software, and to permit persons to whom the Software is */
20 +/* furnished to do so, subject to the following conditions: */
21 +/* */
22 +/* The above copyright notice and this permission notice shall be included in */
23 +/* all copies or substantial portions of the Software. */
24 +/* */
25 +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR */
26 +/* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, */
27 +/* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE */
28 +/* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER */
29 +/* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, */
30 +/* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN */
31 +/* THE SOFTWARE. */
32 +/* */
33 +/* http://opensource.org/licenses/MIT */
34 +/* ================================================================================== */
36 +/*Shut up warnings*/
37 +#define _CRT_SECURE_NO_WARNINGS
39 +/*printf() macros*/
40 +#ifndef __STDC_FORMAT_MACROS
41 +#define __STDC_FORMAT_MACROS 1
42 +#endif
44 +/*SoX internal stuff*/
45 +#include "sox_i.h"
47 +/*Win32 Unicode support*/
48 +#ifdef _WIN32
49 +#include "unicode_support.h"
50 +#else
51 +#define lsx_fopen(X,Y) fopen((X),(Y))
52 +#endif /*_WIN32*/
54 +/*StdLib*/
55 +#include <string.h>
56 +#include <stdarg.h>
57 +#include <ctype.h>
58 +#include <inttypes.h>
60 +/*Linkage*/
61 +#if defined(_MSC_VER) && defined(_MT)
62 +#define MDYNAMICAUDIONORMALIZER_STATIC
63 +static const char *LINKAGE = "Static";
64 +#else
65 +static const char *LINKAGE = "Shared";
66 +#endif
68 +/*Dynamic Audio Normalizer*/
69 +#include <DynamicAudioNormalizer.h>
71 +/* ================================================================================== */
72 +/* Private Data */
73 +/* ================================================================================== */
75 +typedef struct
77 + uint32_t frameLenMsec;
78 + uint32_t filterSize;
79 + double peakValue;
80 + double maxAmplification;
81 + double targetRms;
82 + double compressFactor;
83 + int channelsCoupled;
84 + int enableDCCorrection;
85 + int altBoundaryMode;
86 + FILE *logFile;
88 +settings_t;
90 +typedef struct
92 + settings_t settings;
93 + MDynamicAudioNormalizer_Handle *instance;
94 + double **temp;
95 + size_t tempSize;
97 +priv_t;
99 +/* ================================================================================== */
100 +/* Internal Functions */
101 +/* ================================================================================== */
103 +static int parseArgInt(const char *const str, uint32_t *parameter, const uint32_t min_val, const uint32_t max_val)
105 + uint32_t temp;
106 + if(sscanf(str, "%u", &temp) == 1)
108 + *parameter = max(min_val, min(max_val, temp));
109 + return 1;
111 + lsx_fail("Failed to parse integral value `%s'", str);
112 + return 0;
115 +static int parseArgDbl(const char *const str, double *parameter, const double min_val, const double max_val)
117 + double temp;
118 + if(sscanf(str, "%lf", &temp) == 1)
120 + *parameter = max(min_val, min(max_val, temp));
121 + return 1;
123 + lsx_fail("Failed to parse floating point value `%s'", str);
124 + return 0;
127 +#define TRY_PARSE(TYPE, PARAM, MIN, MAX) do \
128 +{ \
129 + if(!parseArg##TYPE(optstate.arg, &(PARAM), (MIN), (MAX))) \
130 + { \
131 + return 0; \
132 + } \
133 +} \
134 +while(0)
136 +static void dynaudnorm_defaults(settings_t *settings)
138 + memset(settings, 0, sizeof(settings_t));
140 + settings->frameLenMsec = 500;
141 + settings->filterSize = 31;
142 + settings->peakValue = 0.95;
143 + settings->maxAmplification = 10.0;
144 + settings->targetRms = 0.0;
145 + settings->compressFactor = 0.0;
146 + settings->channelsCoupled = 1;
147 + settings->enableDCCorrection = 0;
148 + settings->altBoundaryMode = 0;
151 +static int dynaudnorm_parse_args(settings_t *settings, int argc, char **argv)
153 + static const char *const opts = "+f:g:p:m:r:ncbs:l:";
154 + lsx_getopt_t optstate; char c;
155 + lsx_getopt_init(argc, argv, opts, NULL, lsx_getopt_flag_opterr, 1, &optstate);
157 + while((c = lsx_getopt(&optstate)) != -1)
159 + switch(tolower(c))
161 + case 'f':
162 + TRY_PARSE(Int, settings->frameLenMsec, 10, 8000);
163 + break;
164 + case 'g':
165 + TRY_PARSE(Int, settings->filterSize, 3, 301);
166 + settings->filterSize += ((settings->filterSize + 1) % 2);
167 + break;
168 + case 'p':
169 + TRY_PARSE(Dbl, settings->peakValue, 0.0, 1.0);
170 + break;
171 + case 'm':
172 + TRY_PARSE(Dbl, settings->maxAmplification, 1.0, 100.0);
173 + break;
174 + case 'r':
175 + TRY_PARSE(Dbl, settings->targetRms, 0.0, 1.0);
176 + break;
177 + case 'n':
178 + settings->channelsCoupled = 0;
179 + break;
180 + case 'c':
181 + settings->enableDCCorrection = 1;
182 + break;
183 + case 'b':
184 + settings->altBoundaryMode = 1;
185 + break;
186 + case 's':
187 + TRY_PARSE(Dbl, settings->compressFactor, 0.0, 30.0);
188 + break;
189 + case 'l':
190 + if(!settings->logFile)
192 + settings->logFile = lsx_fopen(optstate.arg, "w");
193 + if(!settings->logFile)
195 + lsx_warn("Failed to open logfile `%s'", optstate.arg);
198 + break;
199 + default:
200 + return 0;
204 + return 1;
207 +static void dynaudnorm_deinterleave(double **temp, const sox_sample_t *const in, const size_t samples_per_channel, const unsigned channels)
209 + size_t i, c, in_pos = 0;
211 + for(i = 0; i < samples_per_channel; i++)
213 + for(c = 0; c < channels; c++)
215 + temp[c][i] = ((double)in[in_pos++]) / ((double)SOX_INT32_MAX);
220 +static void dynaudnorm_interleave(sox_sample_t *const out, const double *const *const temp, const size_t samples_per_channel, const unsigned channels)
222 + size_t i, c, out_pos = 0;
224 + for(i = 0; i < samples_per_channel; i++)
226 + for(c = 0; c < channels; c++)
228 + out[out_pos++] = (sox_sample_t) round(min(1.0, max(-1.0, temp[c][i])) * ((double)SOX_INT32_MAX));
233 +static void dynaudnorm_print(sox_effect_t *effp, const char *const fmt, ...)
235 + if(effp->global_info->global_info->output_message_handler)
237 + va_list arg_list;
238 + va_start(arg_list, fmt);
239 + vfprintf(stderr, fmt, arg_list);
240 + va_end(arg_list);
244 +static void dynaudnorm_log(const int logLevel, const char *const message)
246 + switch(logLevel)
248 + case 0:
249 + lsx_report("%s", message);
250 + break;
251 + case 1:
252 + lsx_warn("%s", message);
253 + break;
254 + case 2:
255 + lsx_fail("%s", message);
256 + break;
260 +static void dynaudnorm_update_buffsize(const sox_effect_t *const effp, priv_t *const p, const size_t input_samples)
262 + size_t c;
263 + if(input_samples > p->tempSize)
265 + lsx_warn("Increasing buffer size: %" PRIu64 " -> %" PRIu64, (uint64_t)p->tempSize, (uint64_t)input_samples);
266 + for(c = 0; c < effp->in_signal.channels; c++)
268 + p->temp[c] = lsx_realloc(p->temp[c], input_samples * sizeof(double));
270 + p->tempSize = input_samples;
274 +/* ================================================================================== */
275 +/* SoX Callback Functions */
276 +/* ================================================================================== */
278 +static int dynaudnorm_kill(sox_effect_t *effp)
280 + lsx_report("dynaudnorm_kill()");
281 + lsx_report("flows=%" PRIu64 ", flow=%" PRIu64 , (uint64_t)effp->flows, (uint64_t)effp->flow);
282 + return SOX_SUCCESS;
285 +static int dynaudnorm_create(sox_effect_t *effp, int argc, char **argv)
287 + priv_t *const p = (priv_t *)effp->priv;
289 + lsx_report("dynaudnorm_create()");
290 + lsx_report("flows=%" PRIu64 ", flow=%" PRIu64 , (uint64_t)effp->flows, (uint64_t)effp->flow);
292 + memset(effp->priv, 0, sizeof(priv_t));
293 + dynaudnorm_defaults(&p->settings);
295 + if(!dynaudnorm_parse_args(&p->settings, argc, argv))
297 + return lsx_usage(effp);
300 + return SOX_SUCCESS;
303 +static int dynaudnorm_stop(sox_effect_t *effp)
305 + priv_t *const p = (priv_t *)effp->priv;
306 + size_t c;
308 + lsx_report("dynaudnorm_stop()");
310 + if(p->instance)
312 + MDYNAMICAUDIONORMALIZER_FUNCTION(destroyInstance)(&p->instance);
313 + p->instance = NULL;
316 + if(p->settings.logFile)
318 + fclose(p->settings.logFile);
319 + p->settings.logFile = NULL;
322 + if(p->temp)
324 + for(c = 0; c < effp->in_signal.channels; c++)
326 + free(p->temp[c]);
327 + p->temp[c] = NULL;
329 + free(p->temp);
330 + p->temp = NULL;
333 + return SOX_SUCCESS;
336 +static int dynaudnorm_start(sox_effect_t *effp)
338 + priv_t *const p = (priv_t *)effp->priv;
340 + lsx_report("dynaudnorm_start()");
341 + lsx_report("flows=%" PRIu64 ", flow=%" PRIu64 ", in_signal.rate=%.2f, in_signal.channels=%" PRIu64, (uint64_t)effp->flows, (uint64_t)effp->flow, effp->in_signal.rate, (uint64_t)effp->in_signal.channels);
343 + if((effp->flow == 0) && (effp->global_info->global_info->verbosity > 1))
345 + uint32_t versionMajor, versionMinor, versionPatch;
346 + const char *buildDate, *buildTime, *buildCompiler, *buildArch; int buildDebug;
348 + MDYNAMICAUDIONORMALIZER_FUNCTION(getVersionInfo)(&versionMajor, &versionMinor, &versionPatch);
349 + MDYNAMICAUDIONORMALIZER_FUNCTION(getBuildInfo)(&buildDate, &buildTime, &buildCompiler, &buildArch, &buildDebug);
351 + dynaudnorm_print(effp, "\n---------------------------------------------------------------------------\n");
352 + dynaudnorm_print(effp, "Dynamic Audio Normalizer (SoX Wrapper), Version %u.%02u-%u, %s\n", versionMajor, versionMinor, versionPatch, LINKAGE);
353 + dynaudnorm_print(effp, "Copyright (c) 2014 LoRd_MuldeR <mulder2@gmx.de>. Some rights reserved.\n");
354 + dynaudnorm_print(effp, "Built on %s at %s with %s for %s.\n\n", buildDate, buildTime, buildCompiler, buildArch);
355 + dynaudnorm_print(effp, "This program is free software: you can redistribute it and/or modify\n");
356 + dynaudnorm_print(effp, "it under the terms of the GNU General Public License <http://www.gnu.org/>.\n");
357 + dynaudnorm_print(effp, "Note that this program is distributed with ABSOLUTELY NO WARRANTY.\n");
358 + dynaudnorm_print(effp, "---------------------------------------------------------------------------\n\n");
361 + p->tempSize = (size_t) max(ceil(effp->in_signal.rate), 8192.0); /*initial buffer size is one second*/
363 + p->instance = MDYNAMICAUDIONORMALIZER_FUNCTION(createInstance)
365 + effp->in_signal.channels,
366 + (uint32_t) round(effp->in_signal.rate),
367 + p->settings.frameLenMsec,
368 + p->settings.filterSize,
369 + p->settings.peakValue,
370 + p->settings.maxAmplification,
371 + p->settings.targetRms,
372 + p->settings.compressFactor,
373 + p->settings.channelsCoupled,
374 + p->settings.enableDCCorrection,
375 + p->settings.altBoundaryMode,
376 + p->settings.logFile
377 + );
379 + if(p->instance)
381 + size_t c;
382 + p->temp = (double**) lsx_calloc(effp->in_signal.channels, sizeof(double*));
383 + for(c = 0; c < effp->in_signal.channels; c++)
385 + p->temp[c] = (double*) lsx_calloc(p->tempSize, sizeof(double));
389 + return (p->instance) ? SOX_SUCCESS : SOX_EINVAL;
392 +static int dynaudnorm_flow(sox_effect_t *effp, const sox_sample_t *ibuf, sox_sample_t *obuf, size_t *isamp, size_t *osamp)
394 + priv_t *const p = (priv_t *)effp->priv;
395 + const size_t input_samples = min((*isamp), (*osamp)) / effp->in_signal.channels; /*this is per channel!*/
396 + int64_t output_samples = 0;
398 + lsx_debug("dynaudnorm_flow()");
399 + dynaudnorm_update_buffsize(effp, p, input_samples);
401 + if(input_samples > 0)
403 + dynaudnorm_deinterleave(p->temp, ibuf, input_samples, effp->in_signal.channels);
404 + if(!MDYNAMICAUDIONORMALIZER_FUNCTION(processInplace)(p->instance, p->temp, ((int64_t) input_samples), &output_samples))
406 + return SOX_EOF;
408 + if(output_samples > 0)
410 + dynaudnorm_interleave(obuf, ((const double**) p->temp), ((size_t) output_samples), effp->in_signal.channels);
415 + *isamp = (size_t)(input_samples * effp->in_signal.channels);
416 + *osamp = (size_t)(output_samples * effp->in_signal.channels);
418 + return SOX_SUCCESS;
421 +static int dynaudnorm_drain(sox_effect_t * effp, sox_sample_t * obuf, size_t * osamp)
423 + priv_t *const p = (priv_t *)effp->priv;
424 + const size_t input_samples = (*osamp) / effp->in_signal.channels; /*this is per channel!*/
425 + int64_t output_samples = 0;
427 + lsx_debug("dynaudnorm_drain()");
428 + dynaudnorm_update_buffsize(effp, p, input_samples);
430 + if(input_samples > 0)
432 + if(!MDYNAMICAUDIONORMALIZER_FUNCTION(flushBuffer)(p->instance, p->temp, ((int64_t) input_samples), &output_samples))
434 + return SOX_EOF;
436 + if(output_samples > 0)
438 + dynaudnorm_interleave(obuf, ((const double**) p->temp), ((size_t) output_samples), effp->in_signal.channels);
441 + else
443 + lsx_warn("drain() was called with zero-size output buffer!");
446 + *osamp = (size_t)(output_samples * effp->in_signal.channels);
447 + return SOX_SUCCESS;
450 +/* ================================================================================== */
451 +/* SoX Public API */
452 +/* ================================================================================== */
454 +sox_effect_handler_t const * lsx_dynaudnorm_effect_fn(void)
456 + static sox_effect_handler_t handler =
458 + "dynaudnorm", NULL, SOX_EFF_MCHAN,
459 + dynaudnorm_create, dynaudnorm_start, dynaudnorm_flow, dynaudnorm_drain, dynaudnorm_stop, dynaudnorm_kill, sizeof(priv_t)
460 + };
462 + static char const * lines[] =
464 + "[options]",
465 + "",
466 + "Algorithm Tweaks:",
467 + " -f <value> Frame length, in milliseconds",
468 + " -g <value> Gauss filter size, in frames",
469 + " -p <value> Target peak magnitude, 0.1-1.0",
470 + " -m <value> Maximum gain factor",
471 + " -r <value> Target RMS value",
472 + " -n Disable channel coupling",
473 + " -c Enable the DC bias correction",
474 + " -b Use alternative boundary mode",
475 + " -s <value> Compress the input data",
476 + "",
477 + "Diagnostics:",
478 + " -l <file> Create a log file",
479 + "",
480 + "",
481 + "Please refer to the manual for a detailed explanation!"
482 + };
484 + static char *usage;
485 + handler.usage = lsx_usage_lines(&usage, lines, array_length(lines));
487 + MDYNAMICAUDIONORMALIZER_FUNCTION(setLogFunction)(dynaudnorm_log);
488 + return &handler;
490 diff --git a/src/effects.h b/src/effects.h
491 index 450a5c2..78fdabf 100644
492 --- a/src/effects.h
493 +++ b/src/effects.h
494 @@ -88,3 +88,4 @@
495 EFFECT(upsample)
496 EFFECT(vad)
497 EFFECT(vol)
498 + EFFECT(dynaudnorm)