diff options
author | Uwe Klotz <uklotz@mixxx.org> | 2018-03-04 08:44:28 +0100 |
---|---|---|
committer | Uwe Klotz <uklotz@mixxx.org> | 2018-03-11 13:24:10 +0100 |
commit | 73001bf863b411df3645029d0f09c9980db598fc (patch) | |
tree | 04eaf26311cfd86921abc145f7e8d52b3a9e6f48 /lib | |
parent | 7ab6f3fa6f1367c0f3a70df4563257616ee751d8 (diff) |
Upgrade libebur128 to version 1.2.4
Diffstat (limited to 'lib')
-rw-r--r-- | lib/libebur128-1.2.3/test/tests.c | 241 | ||||
-rw-r--r-- | lib/libebur128/.gitignore (renamed from lib/libebur128-1.2.3/.gitignore) | 0 | ||||
-rw-r--r-- | lib/libebur128/CMakeLists.txt (renamed from lib/libebur128-1.2.3/CMakeLists.txt) | 6 | ||||
-rw-r--r-- | lib/libebur128/COPYING (renamed from lib/libebur128-1.2.3/COPYING) | 0 | ||||
-rw-r--r-- | lib/libebur128/README.md (renamed from lib/libebur128-1.2.3/README.md) | 9 | ||||
-rw-r--r-- | lib/libebur128/cmake/utils.cmake (renamed from lib/libebur128-1.2.3/cmake/utils.cmake) | 0 | ||||
-rw-r--r-- | lib/libebur128/doc/license/R128Scan.txt (renamed from lib/libebur128-1.2.3/doc/license/R128Scan.txt) | 0 | ||||
-rw-r--r-- | lib/libebur128/doc/license/queue.txt (renamed from lib/libebur128-1.2.3/doc/license/queue.txt) | 0 | ||||
-rw-r--r-- | lib/libebur128/ebur128/CMakeLists.txt (renamed from lib/libebur128-1.2.3/ebur128/CMakeLists.txt) | 11 | ||||
-rw-r--r-- | lib/libebur128/ebur128/ebur128.c (renamed from lib/libebur128-1.2.3/ebur128/ebur128.c) | 21 | ||||
-rw-r--r-- | lib/libebur128/ebur128/ebur128.def (renamed from lib/libebur128-1.2.3/ebur128/ebur128.def) | 0 | ||||
-rw-r--r-- | lib/libebur128/ebur128/ebur128.h (renamed from lib/libebur128-1.2.3/ebur128/ebur128.h) | 2 | ||||
-rw-r--r-- | lib/libebur128/ebur128/libebur128.pc.cmake (renamed from lib/libebur128-1.2.3/ebur128/libebur128.pc.cmake) | 0 | ||||
-rw-r--r-- | lib/libebur128/ebur128/queue/sys/queue.h (renamed from lib/libebur128-1.2.3/ebur128/queue/sys/queue.h) | 0 | ||||
-rw-r--r-- | lib/libebur128/test/CMakeLists.txt (renamed from lib/libebur128-1.2.3/test/CMakeLists.txt) | 0 | ||||
-rw-r--r-- | lib/libebur128/test/minimal-example.c (renamed from lib/libebur128-1.2.3/test/minimal-example.c) | 0 | ||||
-rw-r--r-- | lib/libebur128/test/tests.c | 426 |
17 files changed, 456 insertions, 260 deletions
diff --git a/lib/libebur128-1.2.3/test/tests.c b/lib/libebur128-1.2.3/test/tests.c deleted file mode 100644 index ace7228db8..0000000000 --- a/lib/libebur128-1.2.3/test/tests.c +++ /dev/null @@ -1,241 +0,0 @@ -/* See COPYING file for copyright and license details. */ - -#include <math.h> -#include <sndfile.h> -#include <string.h> -#include <stdlib.h> - -#include "ebur128.h" - -double test_global_loudness(const char* filename) { - SF_INFO file_info; - SNDFILE* file; - sf_count_t nr_frames_read; - - ebur128_state* st = NULL; - double gated_loudness; - double* buffer; - - memset(&file_info, '\0', sizeof(file_info)); - file = sf_open(filename, SFM_READ, &file_info); - if (!file) { - fprintf(stderr, "Could not open file %s!\n", filename); - return 0.0; - } - st = ebur128_init((unsigned) file_info.channels, - (unsigned) file_info.samplerate, - EBUR128_MODE_I); - if (file_info.channels == 5) { - ebur128_set_channel(st, 0, EBUR128_LEFT); - ebur128_set_channel(st, 1, EBUR128_RIGHT); - ebur128_set_channel(st, 2, EBUR128_CENTER); - ebur128_set_channel(st, 3, EBUR128_LEFT_SURROUND); - ebur128_set_channel(st, 4, EBUR128_RIGHT_SURROUND); - } - buffer = (double*) malloc(st->samplerate * st->channels * sizeof(double)); - while ((nr_frames_read = sf_readf_double(file, buffer, - (sf_count_t) st->samplerate))) { - ebur128_add_frames_double(st, buffer, (size_t) nr_frames_read); - } - - ebur128_loudness_global(st, &gated_loudness); - - /* clean up */ - ebur128_destroy(&st); - - free(buffer); - buffer = NULL; - if (sf_close(file)) { - fprintf(stderr, "Could not close input file!\n"); - } - return gated_loudness; -} - -double test_loudness_range(const char* filename) { - SF_INFO file_info; - SNDFILE* file; - sf_count_t nr_frames_read; - - ebur128_state* st = NULL; - double loudness_range; - double* buffer; - - memset(&file_info, '\0', sizeof(file_info)); - file = sf_open(filename, SFM_READ, &file_info); - if (!file) { - fprintf(stderr, "Could not open file %s!\n", filename); - return 0.0; - } - st = ebur128_init((unsigned) file_info.channels, - (unsigned) file_info.samplerate, - EBUR128_MODE_LRA); - if (file_info.channels == 5) { - ebur128_set_channel(st, 0, EBUR128_LEFT); - ebur128_set_channel(st, 1, EBUR128_RIGHT); - ebur128_set_channel(st, 2, EBUR128_CENTER); - ebur128_set_channel(st, 3, EBUR128_LEFT_SURROUND); - ebur128_set_channel(st, 4, EBUR128_RIGHT_SURROUND); - } - buffer = (double*) malloc(st->samplerate * st->channels * sizeof(double)); - while ((nr_frames_read = sf_readf_double(file, buffer, - (sf_count_t) st->samplerate))) { - ebur128_add_frames_double(st, buffer, (size_t) nr_frames_read); - } - - ebur128_loudness_range(st, &loudness_range); - - /* clean up */ - ebur128_destroy(&st); - - free(buffer); - buffer = NULL; - if (sf_close(file)) { - fprintf(stderr, "Could not close input file!\n"); - } - return loudness_range; -} - -double test_true_peak(const char* filename) { - SF_INFO file_info; - SNDFILE* file; - sf_count_t nr_frames_read; - int i; - - ebur128_state* st = NULL; - double true_peak; - double max_true_peak = -HUGE_VAL; - double* buffer; - - memset(&file_info, '\0', sizeof(file_info)); - file = sf_open(filename, SFM_READ, &file_info); - if (!file) { - fprintf(stderr, "Could not open file %s!\n", filename); - return 0.0; - } - st = ebur128_init((unsigned) file_info.channels, - (unsigned) file_info.samplerate, - EBUR128_MODE_TRUE_PEAK); - if (file_info.channels == 5) { - ebur128_set_channel(st, 0, EBUR128_LEFT); - ebur128_set_channel(st, 1, EBUR128_RIGHT); - ebur128_set_channel(st, 2, EBUR128_CENTER); - ebur128_set_channel(st, 3, EBUR128_LEFT_SURROUND); - ebur128_set_channel(st, 4, EBUR128_RIGHT_SURROUND); - } - buffer = (double*) malloc(st->samplerate * st->channels * sizeof(double)); - while ((nr_frames_read = sf_readf_double(file, buffer, - (sf_count_t) st->samplerate))) { - ebur128_add_frames_double(st, buffer, (size_t) nr_frames_read); - } - - for (i = 0; i < file_info.channels; i++) { - ebur128_true_peak(st, (unsigned)i, &true_peak); - if (true_peak > max_true_peak) - max_true_peak = true_peak; - } - /* clean up */ - ebur128_destroy(&st); - - free(buffer); - buffer = NULL; - if (sf_close(file)) { - fprintf(stderr, "Could not close input file!\n"); - } - return 20 * log10(max_true_peak); -} - -double gr[] = {-23.0, - -33.0, - -23.0, - -23.0, - -23.0, - -23.0, - -23.0, - -23.0, - -23.0}; -double gre[] = {-2.2953556442089987e+01, - -3.2959860397340044e+01, - -2.2995899818255047e+01, - -2.3035918615414182e+01, - -2.2949997446096436e+01, - -2.3017157781104373e+01, - -2.3017157781104373e+01, - -2.2980242495081757e+01, - -2.3009077718930545e+01}; -double lra[] = {10.0, - 5.0, - 20.0, - 15.0, - 5.0, - 15.0}; -double lrae[] = {1.0001105488329134e+01, - 4.9993734051522178e+00, - 1.9995064067783115e+01, - 1.4999273937723455e+01, - 4.9747585878473721e+00, - 1.4993650849123316e+01}; - - -int main() { - double result; - - fprintf(stderr, "Note: the tests do not have to pass with EXACT_PASSED.\n" - "Passing these tests does not mean that the library is " - "100%% EBU R 128 compliant!\n\n"); - -#define TEST_GLOBAL_LOUDNESS(filename, i) \ - result = test_global_loudness(filename); \ - if (result == result) { \ - printf("%s, %s - %s: %1.16e\n", \ - (result <= gr[i] + 0.1 && result >= gr[i] - 0.1) ? "PASSED" : "FAILED", \ - (result == gre[i]) ? "EXACT_PASSED" : "EXACT_FAILED", \ - filename, result); \ - } - - TEST_GLOBAL_LOUDNESS("seq-3341-1-16bit.wav", 0) - TEST_GLOBAL_LOUDNESS("seq-3341-2-16bit.wav", 1) - TEST_GLOBAL_LOUDNESS("seq-3341-3-16bit-v02.wav", 2) - TEST_GLOBAL_LOUDNESS("seq-3341-4-16bit-v02.wav", 3) - TEST_GLOBAL_LOUDNESS("seq-3341-5-16bit-v02.wav", 4) - TEST_GLOBAL_LOUDNESS("seq-3341-6-5channels-16bit.wav", 5) - TEST_GLOBAL_LOUDNESS("seq-3341-6-6channels-WAVEEX-16bit.wav", 6) - TEST_GLOBAL_LOUDNESS("seq-3341-7_seq-3342-5-24bit.wav", 7) - TEST_GLOBAL_LOUDNESS("seq-3341-2011-8_seq-3342-6-24bit-v02.wav", 8) - - -#define TEST_LRA(filename, i) \ - result = test_loudness_range(filename); \ - if (result == result) { \ - printf("%s, %s - %s: %1.16e\n", \ - (result <= lra[i] + 1 && result >= lra[i] - 1) ? "PASSED" : "FAILED", \ - (result == lrae[i]) ? "EXACT_PASSED" : "EXACT_FAILED", \ - filename, result); \ - } - - TEST_LRA("seq-3342-1-16bit.wav", 0) - TEST_LRA("seq-3342-2-16bit.wav", 1) - TEST_LRA("seq-3342-3-16bit.wav", 2) - TEST_LRA("seq-3342-4-16bit.wav", 3) - TEST_LRA("seq-3341-7_seq-3342-5-24bit.wav", 4) - TEST_LRA("seq-3341-2011-8_seq-3342-6-24bit-v02.wav", 5) - -#define TEST_MAX_TRUE_PEAK(filename, expected) \ - result = test_true_peak(filename); \ - if (result == result) { \ - printf("%s - %s: %1.16e\n", \ - (result <= expected + 0.2 && result >= expected - 0.4) ? "PASSED" : "FAILED", \ - filename, result); \ - } - - TEST_MAX_TRUE_PEAK("seq-3341-15-24bit.wav.wav", -6.0) - TEST_MAX_TRUE_PEAK("seq-3341-16-24bit.wav.wav", -6.0) - TEST_MAX_TRUE_PEAK("seq-3341-17-24bit.wav.wav", -6.0) - TEST_MAX_TRUE_PEAK("seq-3341-18-24bit.wav.wav", -6.0) - TEST_MAX_TRUE_PEAK("seq-3341-19-24bit.wav.wav", 3.0) - TEST_MAX_TRUE_PEAK("seq-3341-20-24bit.wav.wav", 0.0) - TEST_MAX_TRUE_PEAK("seq-3341-21-24bit.wav.wav", 0.0) - TEST_MAX_TRUE_PEAK("seq-3341-22-24bit.wav.wav", 0.0) - TEST_MAX_TRUE_PEAK("seq-3341-23-24bit.wav.wav", 0.0) - - return 0; -} diff --git a/lib/libebur128-1.2.3/.gitignore b/lib/libebur128/.gitignore index 567609b123..567609b123 100644 --- a/lib/libebur128-1.2.3/.gitignore +++ b/lib/libebur128/.gitignore diff --git a/lib/libebur128-1.2.3/CMakeLists.txt b/lib/libebur128/CMakeLists.txt index ff352ebfcb..f741317f50 100644 --- a/lib/libebur128-1.2.3/CMakeLists.txt +++ b/lib/libebur128/CMakeLists.txt @@ -1,9 +1,9 @@ cmake_minimum_required(VERSION 2.8.12 FATAL_ERROR) project(libebur128 C) -list(APPEND CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/cmake) -set(EXECUTABLE_OUTPUT_PATH ${CMAKE_BINARY_DIR}) -set(LIBRARY_OUTPUT_PATH ${CMAKE_BINARY_DIR}) +list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake) +set(EXECUTABLE_OUTPUT_PATH ${CMAKE_CURRENT_BINARY_DIR}) +set(LIBRARY_OUTPUT_PATH ${CMAKE_CURRENT_BINARY_DIR}) include(utils) include(GNUInstallDirs) diff --git a/lib/libebur128-1.2.3/COPYING b/lib/libebur128/COPYING index e3cebca683..e3cebca683 100644 --- a/lib/libebur128-1.2.3/COPYING +++ b/lib/libebur128/COPYING diff --git a/lib/libebur128-1.2.3/README.md b/lib/libebur128/README.md index f44adcb7ab..42e958192e 100644 --- a/lib/libebur128-1.2.3/README.md +++ b/lib/libebur128/README.md @@ -12,6 +12,15 @@ See also [loudness-scanner tool](https://github.com/jiixyj/loudness-scanner). News ---- +v1.2.4 released: + * Fix broken `ebur128_loudness_global_multiple()` function. Since v1.1.0 it + calculated the relative threshold just from the last state given to it, + resulting in wrong values. + * More tests + * Fix some minor build issues + * Fix uninitialized memory in `ebur128_init()`, possibly resulting in wrong + values + v1.2.3 released: * Fix uninitialized memory access during true peak scanning (bug #72) diff --git a/lib/libebur128-1.2.3/cmake/utils.cmake b/lib/libebur128/cmake/utils.cmake index b27c57bd51..b27c57bd51 100644 --- a/lib/libebur128-1.2.3/cmake/utils.cmake +++ b/lib/libebur128/cmake/utils.cmake diff --git a/lib/libebur128-1.2.3/doc/license/R128Scan.txt b/lib/libebur128/doc/license/R128Scan.txt index 305b5e1d85..305b5e1d85 100644 --- a/lib/libebur128-1.2.3/doc/license/R128Scan.txt +++ b/lib/libebur128/doc/license/R128Scan.txt diff --git a/lib/libebur128-1.2.3/doc/license/queue.txt b/lib/libebur128/doc/license/queue.txt index 87fb4d13ba..87fb4d13ba 100644 --- a/lib/libebur128-1.2.3/doc/license/queue.txt +++ b/lib/libebur128/doc/license/queue.txt diff --git a/lib/libebur128-1.2.3/ebur128/CMakeLists.txt b/lib/libebur128/ebur128/CMakeLists.txt index 2876aabef4..d77385e23f 100644 --- a/lib/libebur128-1.2.3/ebur128/CMakeLists.txt +++ b/lib/libebur128/ebur128/CMakeLists.txt @@ -23,12 +23,14 @@ endif() set(EBUR128_VERSION_MAJOR 1) -set(EBUR128_VERSION 1.2.3) +set(EBUR128_VERSION 1.2.4) #### static if(BUILD_STATIC_LIBS) add_library(ebur128_static STATIC ebur128.c) - set_property(TARGET ebur128_static PROPERTY OUTPUT_NAME ebur128) + if(NOT MSVC) + set_property(TARGET ebur128_static PROPERTY OUTPUT_NAME ebur128) + endif() endif() if(WITH_STATIC_PIC) @@ -47,8 +49,9 @@ set_target_properties(ebur128 PROPERTIES SOVERSION ${EBUR128_VERSION_MAJOR} VERSION ${EBUR128_VERSION}) -if(UNIX) - target_link_libraries(ebur128 m) +find_library(MATH_LIBRARY m) +if(MATH_LIBRARY) + target_link_libraries(ebur128 ${MATH_LIBRARY}) endif() set(EBUR128_INCLUDE_DIR ${CMAKE_CURRENT_SOURCE_DIR} CACHE INTERNAL "") diff --git a/lib/libebur128-1.2.3/ebur128/ebur128.c b/lib/libebur128/ebur128/ebur128.c index aa20db35df..2e987102cb 100644 --- a/lib/libebur128-1.2.3/ebur128/ebur128.c +++ b/lib/libebur128/ebur128/ebur128.c @@ -404,7 +404,7 @@ ebur128_state* ebur128_init(unsigned int channels, sizeof(double)); CHECK_ERROR(!st->d->audio_data, 0, free_true_peak) for (j = 0; j < st->d->audio_data_frames * st->channels; ++j) { - st->d->audio_data[i] = 0.0; + st->d->audio_data[j] = 0.0; } ebur128_init_filter(st); @@ -528,7 +528,7 @@ static void ebur128_check_true_peak(ebur128_state* st, size_t frames) { } } -#if defined(__SSE2_MATH__) || defined(__SSE2__) +#ifdef __SSE2_MATH__ #include <xmmintrin.h> #define TURN_ON_FTZ \ unsigned int mxcsr = _mm_getcsr(); \ @@ -955,8 +955,6 @@ static int ebur128_calc_relative_threshold(ebur128_state* st, double* relative_threshold) { struct ebur128_dq_entry* it; size_t i; - *relative_threshold = 0.0; - *above_thresh_counter = 0; if (st->d->use_histogram) { for (i = 0; i < 1000; ++i) { @@ -971,11 +969,6 @@ static int ebur128_calc_relative_threshold(ebur128_state* st, } } - if (*above_thresh_counter != 0) { - *relative_threshold /= (double) *above_thresh_counter; - *relative_threshold *= relative_gate_factor; - } - return EBUR128_SUCCESS; } @@ -1004,6 +997,9 @@ static int ebur128_gated_loudness(ebur128_state** sts, size_t size, return EBUR128_SUCCESS; } + relative_threshold /= (double)above_thresh_counter; + relative_threshold *= relative_gate_factor; + above_thresh_counter = 0; if (relative_threshold < histogram_energy_boundaries[0]) { start_index = 0; @@ -1042,8 +1038,8 @@ static int ebur128_gated_loudness(ebur128_state** sts, size_t size, } int ebur128_relative_threshold(ebur128_state* st, double* out) { - double relative_threshold; - size_t above_thresh_counter; + double relative_threshold = 0.0; + size_t above_thresh_counter = 0; if ((st->mode & EBUR128_MODE_I) != EBUR128_MODE_I) { return EBUR128_ERROR_INVALID_MODE; @@ -1056,6 +1052,9 @@ int ebur128_relative_threshold(ebur128_state* st, double* out) { return EBUR128_SUCCESS; } + relative_threshold /= (double)above_thresh_counter; + relative_threshold *= relative_gate_factor; + *out = ebur128_energy_to_loudness(relative_threshold); return EBUR128_SUCCESS; } diff --git a/lib/libebur128-1.2.3/ebur128/ebur128.def b/lib/libebur128/ebur128/ebur128.def index 81602f74a2..81602f74a2 100644 --- a/lib/libebur128-1.2.3/ebur128/ebur128.def +++ b/lib/libebur128/ebur128/ebur128.def diff --git a/lib/libebur128-1.2.3/ebur128/ebur128.h b/lib/libebur128/ebur128/ebur128.h index 5b95682caf..6a673c7123 100644 --- a/lib/libebur128-1.2.3/ebur128/ebur128.h +++ b/lib/libebur128/ebur128/ebur128.h @@ -14,7 +14,7 @@ extern "C" { #define EBUR128_VERSION_MAJOR 1 #define EBUR128_VERSION_MINOR 2 -#define EBUR128_VERSION_PATCH 3 +#define EBUR128_VERSION_PATCH 4 #include <stddef.h> /* for size_t */ diff --git a/lib/libebur128-1.2.3/ebur128/libebur128.pc.cmake b/lib/libebur128/ebur128/libebur128.pc.cmake index 017fdebaf3..017fdebaf3 100644 --- a/lib/libebur128-1.2.3/ebur128/libebur128.pc.cmake +++ b/lib/libebur128/ebur128/libebur128.pc.cmake diff --git a/lib/libebur128-1.2.3/ebur128/queue/sys/queue.h b/lib/libebur128/ebur128/queue/sys/queue.h index daf4553d33..daf4553d33 100644 --- a/lib/libebur128-1.2.3/ebur128/queue/sys/queue.h +++ b/lib/libebur128/ebur128/queue/sys/queue.h diff --git a/lib/libebur128-1.2.3/test/CMakeLists.txt b/lib/libebur128/test/CMakeLists.txt index c988bcb189..c988bcb189 100644 --- a/lib/libebur128-1.2.3/test/CMakeLists.txt +++ b/lib/libebur128/test/CMakeLists.txt diff --git a/lib/libebur128-1.2.3/test/minimal-example.c b/lib/libebur128/test/minimal-example.c index 499fe09a95..499fe09a95 100644 --- a/lib/libebur128-1.2.3/test/minimal-example.c +++ b/lib/libebur128/test/minimal-example.c diff --git a/lib/libebur128/test/tests.c b/lib/libebur128/test/tests.c new file mode 100644 index 0000000000..d2bef6f0ea --- /dev/null +++ b/lib/libebur128/test/tests.c @@ -0,0 +1,426 @@ +/* See COPYING file for copyright and license details. */ + +#include <math.h> +#include <sndfile.h> +#include <string.h> +#include <stdlib.h> + +#include "ebur128.h" + +double test_global_loudness(const char* filename, ebur128_state** out_state) { + SF_INFO file_info; + SNDFILE* file; + sf_count_t nr_frames_read; + + ebur128_state* st = NULL; + double gated_loudness; + double* buffer; + + memset(&file_info, '\0', sizeof(file_info)); + file = sf_open(filename, SFM_READ, &file_info); + if (!file) { + fprintf(stderr, "Could not open file %s!\n", filename); + return 0.0; + } + st = ebur128_init((unsigned) file_info.channels, + (unsigned) file_info.samplerate, + EBUR128_MODE_I); + if (file_info.channels == 5) { + ebur128_set_channel(st, 0, EBUR128_LEFT); + ebur128_set_channel(st, 1, EBUR128_RIGHT); + ebur128_set_channel(st, 2, EBUR128_CENTER); + ebur128_set_channel(st, 3, EBUR128_LEFT_SURROUND); + ebur128_set_channel(st, 4, EBUR128_RIGHT_SURROUND); + } + buffer = (double*) malloc(st->samplerate * st->channels * sizeof(double)); + while ((nr_frames_read = sf_readf_double(file, buffer, + (sf_count_t) st->samplerate))) { + ebur128_add_frames_double(st, buffer, (size_t) nr_frames_read); + } + + ebur128_loudness_global(st, &gated_loudness); + + *out_state = st; + + free(buffer); + buffer = NULL; + if (sf_close(file)) { + fprintf(stderr, "Could not close input file!\n"); + } + return gated_loudness; +} + +double test_loudness_range(const char* filename) { + SF_INFO file_info; + SNDFILE* file; + sf_count_t nr_frames_read; + + ebur128_state* st = NULL; + double loudness_range; + double* buffer; + + memset(&file_info, '\0', sizeof(file_info)); + file = sf_open(filename, SFM_READ, &file_info); + if (!file) { + fprintf(stderr, "Could not open file %s!\n", filename); + return 0.0; + } + st = ebur128_init((unsigned) file_info.channels, + (unsigned) file_info.samplerate, + EBUR128_MODE_LRA); + if (file_info.channels == 5) { + ebur128_set_channel(st, 0, EBUR128_LEFT); + ebur128_set_channel(st, 1, EBUR128_RIGHT); + ebur128_set_channel(st, 2, EBUR128_CENTER); + ebur128_set_channel(st, 3, EBUR128_LEFT_SURROUND); + ebur128_set_channel(st, 4, EBUR128_RIGHT_SURROUND); + } + buffer = (double*) malloc(st->samplerate * st->channels * sizeof(double)); + while ((nr_frames_read = sf_readf_double(file, buffer, + (sf_count_t) st->samplerate))) { + ebur128_add_frames_double(st, buffer, (size_t) nr_frames_read); + } + + ebur128_loudness_range(st, &loudness_range); + + /* clean up */ + ebur128_destroy(&st); + + free(buffer); + buffer = NULL; + if (sf_close(file)) { + fprintf(stderr, "Could not close input file!\n"); + } + return loudness_range; +} + +double test_true_peak(const char* filename) { + SF_INFO file_info; + SNDFILE* file; + sf_count_t nr_frames_read; + int i; + + ebur128_state* st = NULL; + double true_peak; + double max_true_peak = -HUGE_VAL; + double* buffer; + + memset(&file_info, '\0', sizeof(file_info)); + file = sf_open(filename, SFM_READ, &file_info); + if (!file) { + fprintf(stderr, "Could not open file %s!\n", filename); + return 0.0; + } + st = ebur128_init((unsigned) file_info.channels, + (unsigned) file_info.samplerate, + EBUR128_MODE_TRUE_PEAK); + if (file_info.channels == 5) { + ebur128_set_channel(st, 0, EBUR128_LEFT); + ebur128_set_channel(st, 1, EBUR128_RIGHT); + ebur128_set_channel(st, 2, EBUR128_CENTER); + ebur128_set_channel(st, 3, EBUR128_LEFT_SURROUND); + ebur128_set_channel(st, 4, EBUR128_RIGHT_SURROUND); + } + buffer = (double*) malloc(st->samplerate * st->channels * sizeof(double)); + while ((nr_frames_read = sf_readf_double(file, buffer, + (sf_count_t) st->samplerate))) { + ebur128_add_frames_double(st, buffer, (size_t) nr_frames_read); + } + + for (i = 0; i < file_info.channels; i++) { + ebur128_true_peak(st, (unsigned)i, &true_peak); + if (true_peak > max_true_peak) + max_true_peak = true_peak; + } + /* clean up */ + ebur128_destroy(&st); + + free(buffer); + buffer = NULL; + if (sf_close(file)) { + fprintf(stderr, "Could not close input file!\n"); + } + return 20 * log10(max_true_peak); +} + +double test_max_momentary(const char* filename) { + SF_INFO file_info; + SNDFILE* file; + sf_count_t nr_frames_read; + sf_count_t total_frames_read; + ebur128_state* st = NULL; + double momentary; + double max_momentary = -HUGE_VAL; + double* buffer; + + memset(&file_info, '\0', sizeof(file_info)); + file = sf_open(filename, SFM_READ, &file_info); + if (!file) { + fprintf(stderr, "Could not open file %s!\n", filename); + return 0.0; + } + st = ebur128_init((unsigned) file_info.channels, + (unsigned) file_info.samplerate, + EBUR128_MODE_M); + if (file_info.channels == 5) { + ebur128_set_channel(st, 0, EBUR128_LEFT); + ebur128_set_channel(st, 1, EBUR128_RIGHT); + ebur128_set_channel(st, 2, EBUR128_CENTER); + ebur128_set_channel(st, 3, EBUR128_LEFT_SURROUND); + ebur128_set_channel(st, 4, EBUR128_RIGHT_SURROUND); + } + /* 10 ms buffer/ 100 Hz refresh rate as 10 Hz refresh rate fails on several tests */ + buffer = (double*) malloc(st->samplerate / 100 * st->channels * sizeof(double)); + while ((nr_frames_read = sf_readf_double(file, buffer, + (sf_count_t) st->samplerate / 100))) { + ebur128_add_frames_double(st, buffer, (size_t) nr_frames_read); + total_frames_read += nr_frames_read; + /* invalid results before the first 400 ms */ + if (total_frames_read >= 4 * st->samplerate / 10) { + ebur128_loudness_momentary(st, &momentary); + if (momentary > max_momentary) + max_momentary = momentary; + } + } + + /* clean up */ + ebur128_destroy(&st); + + free(buffer); + buffer = NULL; + if (sf_close(file)) { + fprintf(stderr, "Could not close input file!\n"); + } + return max_momentary; +} + +double test_max_shortterm(const char* filename) { + SF_INFO file_info; + SNDFILE* file; + sf_count_t nr_frames_read; + sf_count_t total_frames_read; + ebur128_state* st = NULL; + double shortterm; + double max_shortterm = -HUGE_VAL; + double* buffer; + + memset(&file_info, '\0', sizeof(file_info)); + file = sf_open(filename, SFM_READ, &file_info); + if (!file) { + fprintf(stderr, "Could not open file %s!\n", filename); + return 0.0; + } + st = ebur128_init((unsigned) file_info.channels, + (unsigned) file_info.samplerate, + EBUR128_MODE_S); + if (file_info.channels == 5) { + ebur128_set_channel(st, 0, EBUR128_LEFT); + ebur128_set_channel(st, 1, EBUR128_RIGHT); + ebur128_set_channel(st, 2, EBUR128_CENTER); + ebur128_set_channel(st, 3, EBUR128_LEFT_SURROUND); + ebur128_set_channel(st, 4, EBUR128_RIGHT_SURROUND); + } + /* 100 ms buffer / 10 Hz refresh rate */ + buffer = (double*) malloc(st->samplerate / 10 * st->channels * sizeof(double)); + while ((nr_frames_read = sf_readf_double(file, buffer, + (sf_count_t) st->samplerate / 10))) { + ebur128_add_frames_double(st, buffer, (size_t) nr_frames_read); + total_frames_read += nr_frames_read; + /* invalid results before the first 3 s */ + if (total_frames_read >= 3 * st->samplerate) { + ebur128_loudness_shortterm(st, &shortterm); + if (shortterm > max_shortterm) + max_shortterm = shortterm; + } + } + + /* clean up */ + ebur128_destroy(&st); + + free(buffer); + buffer = NULL; + if (sf_close(file)) { + fprintf(stderr, "Could not close input file!\n"); + } + return max_shortterm; +} + +double gr[] = {-23.0, + -33.0, + -23.0, + -23.0, + -23.0, + -23.0, + -23.0, + -23.0, + -23.0}; +double gre[] = {-2.2953556442089987e+01, + -3.2959860397340044e+01, + -2.2995899818255047e+01, + -2.3035918615414182e+01, + -2.2949997446096436e+01, + -2.3017157781104373e+01, + -2.3017157781104373e+01, + -2.2980242495081757e+01, + -2.3009077718930545e+01}; +double lra[] = {10.0, + 5.0, + 20.0, + 15.0, + 5.0, + 15.0}; +double lrae[] = {1.0001105488329134e+01, + 4.9993734051522178e+00, + 1.9995064067783115e+01, + 1.4999273937723455e+01, + 4.9747585878473721e+00, + 1.4993650849123316e+01}; + + +int main() { + double result; + ebur128_state* states[9] = {0}; + int i; + + fprintf(stderr, "Note: the tests do not have to pass with EXACT_PASSED.\n" + "Passing these tests does not mean that the library is " + "100%% EBU R 128 compliant!\n\n"); + +#define TEST_GLOBAL_LOUDNESS(filename, i, state_array) \ + result = test_global_loudness(filename, &state_array[i]); \ + if (result == result) { \ + printf("%s, %s - %s: %1.16e\n", \ + (result <= gr[i] + 0.1 && result >= gr[i] - 0.1) ? "PASSED" : "FAILED", \ + (result == gre[i]) ? "EXACT_PASSED" : "EXACT_FAILED", \ + filename, result); \ + } + + TEST_GLOBAL_LOUDNESS("seq-3341-1-16bit.wav", 0, states) + TEST_GLOBAL_LOUDNESS("seq-3341-2-16bit.wav", 1, states) + TEST_GLOBAL_LOUDNESS("seq-3341-3-16bit-v02.wav", 2, states) + TEST_GLOBAL_LOUDNESS("seq-3341-4-16bit-v02.wav", 3, states) + TEST_GLOBAL_LOUDNESS("seq-3341-5-16bit-v02.wav", 4, states) + TEST_GLOBAL_LOUDNESS("seq-3341-6-5channels-16bit.wav", 5, states) + TEST_GLOBAL_LOUDNESS("seq-3341-6-6channels-WAVEEX-16bit.wav", 6, states) + TEST_GLOBAL_LOUDNESS("seq-3341-7_seq-3342-5-24bit.wav", 7, states) + TEST_GLOBAL_LOUDNESS("seq-3341-2011-8_seq-3342-6-24bit-v02.wav", 8, states) + + /* Move some states around, to make the bug where + * ebur128_loudness_global_multiple() calculated the relative threshold just + * from the last state easier to reproduce. Don't care for leaks, etc. */ + states[5] = states[0]; + states[0] = states[8]; + + for (i = 0; i < 6; ++i) { + if (states[i] == NULL) { + printf("FAILED, ebur128_loudness_global_multiple needs all states of seq-3341-1 until seq-3341-5 (inclusive) and seq-3341-2011-8_seq-3342-6-24bit\n"); + goto after_multiple_test; + } + } + + result = 0; + ebur128_loudness_global_multiple(states, 6, &result); + fprintf(stderr, "multiple output: %f\n", result); + if (result >= -23.18758 - 0.05 && result <= -23.18758 + 0.05) { + printf("PASSED, ebur128_loudness_global_multiple\n"); + } else { + printf("FAILED, ebur128_loudness_global_multiple\n"); + } + +after_multiple_test: + ; + +#define TEST_LRA(filename, i) \ + result = test_loudness_range(filename); \ + if (result == result) { \ + printf("%s, %s - %s: %1.16e\n", \ + (result <= lra[i] + 1 && result >= lra[i] - 1) ? "PASSED" : "FAILED", \ + (result == lrae[i]) ? "EXACT_PASSED" : "EXACT_FAILED", \ + filename, result); \ + } + + TEST_LRA("seq-3342-1-16bit.wav", 0) + TEST_LRA("seq-3342-2-16bit.wav", 1) + TEST_LRA("seq-3342-3-16bit.wav", 2) + TEST_LRA("seq-3342-4-16bit.wav", 3) + TEST_LRA("seq-3341-7_seq-3342-5-24bit.wav", 4) + TEST_LRA("seq-3341-2011-8_seq-3342-6-24bit-v02.wav", 5) + +#define TEST_MAX_TRUE_PEAK(filename, expected) \ + result = test_true_peak(filename); \ + if (result == result) { \ + printf("%s - %s: %1.16e\n", \ + (result <= expected + 0.2 && result >= expected - 0.4) ? "PASSED" : "FAILED", \ + filename, result); \ + } + + TEST_MAX_TRUE_PEAK("seq-3341-15-24bit.wav.wav", -6.0) + TEST_MAX_TRUE_PEAK("seq-3341-16-24bit.wav.wav", -6.0) + TEST_MAX_TRUE_PEAK("seq-3341-17-24bit.wav.wav", -6.0) + TEST_MAX_TRUE_PEAK("seq-3341-18-24bit.wav.wav", -6.0) + TEST_MAX_TRUE_PEAK("seq-3341-19-24bit.wav.wav", 3.0) + TEST_MAX_TRUE_PEAK("seq-3341-20-24bit.wav.wav", 0.0) + TEST_MAX_TRUE_PEAK("seq-3341-21-24bit.wav.wav", 0.0) + TEST_MAX_TRUE_PEAK("seq-3341-22-24bit.wav.wav", 0.0) + TEST_MAX_TRUE_PEAK("seq-3341-23-24bit.wav.wav", 0.0) + +#define TEST_MAX_MOMENTARY(filename, expected) \ + result = test_max_momentary(filename); \ + if (result == result) { \ + printf("%s - %s: %1.16e\n", \ + (result <= expected + 0.1 && result >= expected - 0.1) ? "PASSED" : "FAILED", \ + filename, result); \ |