summaryrefslogtreecommitdiffstats
path: root/lib/libebur128/ebur128/ebur128.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/libebur128/ebur128/ebur128.c')
-rw-r--r--lib/libebur128/ebur128/ebur128.c1333
1 files changed, 0 insertions, 1333 deletions
diff --git a/lib/libebur128/ebur128/ebur128.c b/lib/libebur128/ebur128/ebur128.c
deleted file mode 100644
index e05165b096..0000000000
--- a/lib/libebur128/ebur128/ebur128.c
+++ /dev/null
@@ -1,1333 +0,0 @@
-/* See COPYING file for copyright and license details. */
-
-#include "ebur128.h"
-
-#include <float.h>
-#include <limits.h>
-#include <math.h> /* You may have to define _USE_MATH_DEFINES if you use MSVC */
-#include <stdio.h>
-#include <stdlib.h>
-
-/* This can be replaced by any BSD-like queue implementation. */
-#include <sys/queue.h>
-
-#define CHECK_ERROR(condition, errorcode, goto_point) \
- if ((condition)) { \
- errcode = (errorcode); \
- goto goto_point; \
- }
-
-STAILQ_HEAD(ebur128_double_queue, ebur128_dq_entry);
-struct ebur128_dq_entry {
- double z;
- STAILQ_ENTRY(ebur128_dq_entry) entries;
-};
-
-#define ALMOST_ZERO 0.000001
-
-typedef struct { /* Data structure for polyphase FIR interpolator */
- unsigned int factor; /* Interpolation factor of the interpolator */
- unsigned int taps; /* Taps (prefer odd to increase zero coeffs) */
- unsigned int channels; /* Number of channels */
- unsigned int delay; /* Size of delay buffer */
- struct {
- unsigned int count; /* Number of coefficients in this subfilter */
- unsigned int* index; /* Delay index of corresponding filter coeff */
- double* coeff; /* List of subfilter coefficients */
- }* filter; /* List of subfilters (one for each factor) */
- float** z; /* List of delay buffers (one for each channel) */
- unsigned int zi; /* Current delay buffer index */
-} interpolator;
-
-struct ebur128_state_internal {
- /** Filtered audio data (used as ring buffer). */
- double* audio_data;
- /** Size of audio_data array. */
- size_t audio_data_frames;
- /** Current index for audio_data. */
- size_t audio_data_index;
- /** How many frames are needed for a gating block. Will correspond to 400ms
- * of audio at initialization, and 100ms after the first block (75% overlap
- * as specified in the 2011 revision of BS1770). */
- unsigned long needed_frames;
- /** The channel map. Has as many elements as there are channels. */
- int* channel_map;
- /** How many samples fit in 100ms (rounded). */
- unsigned long samples_in_100ms;
- /** BS.1770 filter coefficients (nominator). */
- double b[5];
- /** BS.1770 filter coefficients (denominator). */
- double a[5];
- /** BS.1770 filter state. */
- double v[5][5];
- /** Linked list of block energies. */
- struct ebur128_double_queue block_list;
- unsigned long block_list_max;
- unsigned long block_list_size;
- /** Linked list of 3s-block energies, used to calculate LRA. */
- struct ebur128_double_queue short_term_block_list;
- unsigned long st_block_list_max;
- unsigned long st_block_list_size;
- int use_histogram;
- unsigned long *block_energy_histogram;
- unsigned long *short_term_block_energy_histogram;
- /** Keeps track of when a new short term block is needed. */
- size_t short_term_frame_counter;
- /** Maximum sample peak, one per channel */
- double* sample_peak;
- double* prev_sample_peak;
- /** Maximum true peak, one per channel */
- double* true_peak;
- double* prev_true_peak;
- interpolator* interp;
- float* resampler_buffer_input;
- size_t resampler_buffer_input_frames;
- float* resampler_buffer_output;
- size_t resampler_buffer_output_frames;
- /** The maximum window duration in ms. */
- unsigned long window;
- unsigned long history;
-};
-
-static double relative_gate = -10.0;
-
-/* Those will be calculated when initializing the library */
-static double relative_gate_factor;
-static double minus_twenty_decibels;
-static double histogram_energies[1000];
-static double histogram_energy_boundaries[1001];
-
-static interpolator* interp_create(unsigned int taps, unsigned int factor, unsigned int channels) {
- interpolator* interp = calloc(1, sizeof(interpolator));
- unsigned int j = 0;
-
- interp->taps = taps;
- interp->factor = factor;
- interp->channels = channels;
- interp->delay = (interp->taps + interp->factor - 1) / interp->factor;
-
- /* Initialize the filter memory
- * One subfilter per interpolation factor. */
- interp->filter = calloc(interp->factor, sizeof(*interp->filter));
- for (j = 0; j < interp->factor; j++) {
- interp->filter[j].index = calloc(interp->delay, sizeof(unsigned int));
- interp->filter[j].coeff = calloc(interp->delay, sizeof(double));
- }
- /* One delay buffer per channel. */
- interp->z = calloc(interp->channels, sizeof(float*));
- for (j = 0; j < interp->channels; j++) {
- interp->z[j] = calloc( interp->delay, sizeof(float) );
- }
-
- /* Calculate the filter coefficients */
- for (j = 0; j < interp->taps; j++) {
- /* Calculate sinc */
- double m = (double)j - (double)(interp->taps - 1) / 2.0;
- double c = 1.0;
- if (fabs(m) > ALMOST_ZERO) {
- c = sin(m * M_PI / interp->factor) / (m * M_PI / interp->factor);
- }
- /* Apply Hanning window */
- c *= 0.5 * (1 - cos(2 * M_PI * j / (interp->taps - 1)));
-
- if (fabs(c) > ALMOST_ZERO) { /* Ignore any zero coeffs. */
- /* Put the coefficient into the correct subfilter */
- unsigned int f = j % interp->factor;
- unsigned int t = interp->filter[f].count++;
- interp->filter[f].coeff[t] = c;
- interp->filter[f].index[t] = j / interp->factor;
- }
- }
- return interp;
-}
-
-static void interp_destroy(interpolator* interp) {
- unsigned int j = 0;
- if (!interp) {
- return;
- }
- for (j = 0; j < interp->factor; j++) {
- free(interp->filter[j].index);
- free(interp->filter[j].coeff);
- }
- free(interp->filter);
- for (j = 0; j < interp->channels; j++) {
- free(interp->z[j]);
- }
- free(interp->z);
- free(interp);
-}
-
-static size_t interp_process(interpolator* interp, size_t frames, float* in, float* out) {
- size_t frame = 0;
- unsigned int chan = 0;
- unsigned int f = 0;
- unsigned int t = 0;
- unsigned int out_stride = interp->channels * interp->factor;
- float* outp = 0;
- double acc = 0;
- double c = 0;
-
- for (frame = 0; frame < frames; frame++) {
- for (chan = 0; chan < interp->channels; chan++) {
- /* Add sample to delay buffer */
- interp->z[chan][interp->zi] = *in++;
- /* Apply coefficients */
- outp = out + chan;
- for (f = 0; f < interp->factor; f++) {
- acc = 0.0;
- for (t = 0; t < interp->filter[f].count; t++) {
- int i = (int)interp->zi - (int)interp->filter[f].index[t];
- if (i < 0) {
- i += interp->delay;
- }
- c = interp->filter[f].coeff[t];
- acc += interp->z[chan][i] * c;
- }
- *outp = (float)acc;
- outp += interp->channels;
- }
- }
- out += out_stride;
- interp->zi++;
- if (interp->zi == interp->delay) {
- interp->zi = 0;
- }
- }
-
- return frames * interp->factor;
-}
-
-static void ebur128_init_filter(ebur128_state* st) {
- int i, j;
-
- double f0 = 1681.974450955533;
- double G = 3.999843853973347;
- double Q = 0.7071752369554196;
-
- double K = tan(M_PI * f0 / (double) st->samplerate);
- double Vh = pow(10.0, G / 20.0);
- double Vb = pow(Vh, 0.4996667741545416);
-
- double pb[3] = {0.0, 0.0, 0.0};
- double pa[3] = {1.0, 0.0, 0.0};
- double rb[3] = {1.0, -2.0, 1.0};
- double ra[3] = {1.0, 0.0, 0.0};
-
- double a0 = 1.0 + K / Q + K * K ;
- pb[0] = (Vh + Vb * K / Q + K * K) / a0;
- pb[1] = 2.0 * (K * K - Vh) / a0;
- pb[2] = (Vh - Vb * K / Q + K * K) / a0;
- pa[1] = 2.0 * (K * K - 1.0) / a0;
- pa[2] = (1.0 - K / Q + K * K) / a0;
-
- /* fprintf(stderr, "%.14f %.14f %.14f %.14f %.14f\n",
- b1[0], b1[1], b1[2], a1[1], a1[2]); */
-
- f0 = 38.13547087602444;
- Q = 0.5003270373238773;
- K = tan(M_PI * f0 / (double) st->samplerate);
-
- ra[1] = 2.0 * (K * K - 1.0) / (1.0 + K / Q + K * K);
- ra[2] = (1.0 - K / Q + K * K) / (1.0 + K / Q + K * K);
-
- /* fprintf(stderr, "%.14f %.14f\n", a2[1], a2[2]); */
-
- st->d->b[0] = pb[0] * rb[0];
- st->d->b[1] = pb[0] * rb[1] + pb[1] * rb[0];
- st->d->b[2] = pb[0] * rb[2] + pb[1] * rb[1] + pb[2] * rb[0];
- st->d->b[3] = pb[1] * rb[2] + pb[2] * rb[1];
- st->d->b[4] = pb[2] * rb[2];
-
- st->d->a[0] = pa[0] * ra[0];
- st->d->a[1] = pa[0] * ra[1] + pa[1] * ra[0];
- st->d->a[2] = pa[0] * ra[2] + pa[1] * ra[1] + pa[2] * ra[0];
- st->d->a[3] = pa[1] * ra[2] + pa[2] * ra[1];
- st->d->a[4] = pa[2] * ra[2];
-
- for (i = 0; i < 5; ++i) {
- for (j = 0; j < 5; ++j) {
- st->d->v[i][j] = 0.0;
- }
- }
-}
-
-static int ebur128_init_channel_map(ebur128_state* st) {
- size_t i;
- st->d->channel_map = (int*) malloc(st->channels * sizeof(int));
- if (!st->d->channel_map) {
- return EBUR128_ERROR_NOMEM;
- }
- if (st->channels == 4) {
- st->d->channel_map[0] = EBUR128_LEFT;
- st->d->channel_map[1] = EBUR128_RIGHT;
- st->d->channel_map[2] = EBUR128_LEFT_SURROUND;
- st->d->channel_map[3] = EBUR128_RIGHT_SURROUND;
- } else if (st->channels == 5) {
- st->d->channel_map[0] = EBUR128_LEFT;
- st->d->channel_map[1] = EBUR128_RIGHT;
- st->d->channel_map[2] = EBUR128_CENTER;
- st->d->channel_map[3] = EBUR128_LEFT_SURROUND;
- st->d->channel_map[4] = EBUR128_RIGHT_SURROUND;
- } else {
- for (i = 0; i < st->channels; ++i) {
- switch (i) {
- case 0: st->d->channel_map[i] = EBUR128_LEFT; break;
- case 1: st->d->channel_map[i] = EBUR128_RIGHT; break;
- case 2: st->d->channel_map[i] = EBUR128_CENTER; break;
- case 3: st->d->channel_map[i] = EBUR128_UNUSED; break;
- case 4: st->d->channel_map[i] = EBUR128_LEFT_SURROUND; break;
- case 5: st->d->channel_map[i] = EBUR128_RIGHT_SURROUND; break;
- default: st->d->channel_map[i] = EBUR128_UNUSED; break;
- }
- }
- }
- return EBUR128_SUCCESS;
-}
-
-static int ebur128_init_resampler(ebur128_state* st) {
- int errcode = EBUR128_SUCCESS;
-
- if (st->samplerate < 96000) {
- st->d->interp = interp_create(49, 4, st->channels);
- CHECK_ERROR(!st->d->interp, EBUR128_ERROR_NOMEM, exit)
- } else if (st->samplerate < 192000) {
- st->d->interp = interp_create(49, 2, st->channels);
- CHECK_ERROR(!st->d->interp, EBUR128_ERROR_NOMEM, exit)
- } else {
- st->d->resampler_buffer_input = NULL;
- st->d->resampler_buffer_output = NULL;
- st->d->interp = NULL;
- goto exit;
- }
-
- st->d->resampler_buffer_input_frames = st->d->samples_in_100ms * 4;
- st->d->resampler_buffer_input = malloc(st->d->resampler_buffer_input_frames *
- st->channels *
- sizeof(float));
- CHECK_ERROR(!st->d->resampler_buffer_input, EBUR128_ERROR_NOMEM, free_interp)
-
- st->d->resampler_buffer_output_frames =
- st->d->resampler_buffer_input_frames *
- st->d->interp->factor;
- st->d->resampler_buffer_output = malloc
- (st->d->resampler_buffer_output_frames *
- st->channels *
- sizeof(float));
- CHECK_ERROR(!st->d->resampler_buffer_output, EBUR128_ERROR_NOMEM, free_input)
-
- return errcode;
-
-free_interp:
- interp_destroy(st->d->interp);
- st->d->interp = NULL;
-free_input:
- free(st->d->resampler_buffer_input);
- st->d->resampler_buffer_input = NULL;
-exit:
- return errcode;
-}
-
-static void ebur128_destroy_resampler(ebur128_state* st) {
- free(st->d->resampler_buffer_input);
- st->d->resampler_buffer_input = NULL;
- free(st->d->resampler_buffer_output);
- st->d->resampler_buffer_output = NULL;
- interp_destroy(st->d->interp);
- st->d->interp = NULL;
-}
-
-void ebur128_get_version(int* major, int* minor, int* patch) {
- *major = EBUR128_VERSION_MAJOR;
- *minor = EBUR128_VERSION_MINOR;
- *patch = EBUR128_VERSION_PATCH;
-}
-
-ebur128_state* ebur128_init(unsigned int channels,
- unsigned long samplerate,
- int mode) {
- int result;
- int errcode;
- ebur128_state* st;
- unsigned int i;
- size_t j;
-
- if (channels == 0 || samplerate < 5) {
- return NULL;
- }
-
- st = (ebur128_state*) malloc(sizeof(ebur128_state));
- CHECK_ERROR(!st, 0, exit)
- st->d = (struct ebur128_state_internal*)
- malloc(sizeof(struct ebur128_state_internal));
- CHECK_ERROR(!st->d, 0, free_state)
- st->channels = channels;
- errcode = ebur128_init_channel_map(st);
- CHECK_ERROR(errcode, 0, free_internal)
-
- st->d->sample_peak = (double*) malloc(channels * sizeof(double));
- CHECK_ERROR(!st->d->sample_peak, 0, free_channel_map)
- st->d->prev_sample_peak = (double*) malloc(channels * sizeof(double));
- CHECK_ERROR(!st->d->prev_sample_peak, 0, free_sample_peak)
- st->d->true_peak = (double*) malloc(channels * sizeof(double));
- CHECK_ERROR(!st->d->true_peak, 0, free_prev_sample_peak)
- st->d->prev_true_peak = (double*) malloc(channels * sizeof(double));
- CHECK_ERROR(!st->d->prev_true_peak, 0, free_true_peak)
- for (i = 0; i < channels; ++i) {
- st->d->sample_peak[i] = 0.0;
- st->d->prev_sample_peak[i] = 0.0;
- st->d->true_peak[i] = 0.0;
- st->d->prev_true_peak[i] = 0.0;
- }
-
- st->d->use_histogram = mode & EBUR128_MODE_HISTOGRAM ? 1 : 0;
- st->d->history = ULONG_MAX;
- st->samplerate = samplerate;
- st->d->samples_in_100ms = (st->samplerate + 5) / 10;
- st->mode = mode;
- if ((mode & EBUR128_MODE_S) == EBUR128_MODE_S) {
- st->d->window = 3000;
- } else if ((mode & EBUR128_MODE_M) == EBUR128_MODE_M) {
- st->d->window = 400;
- } else {
- goto free_prev_true_peak;
- }
- st->d->audio_data_frames = st->samplerate * st->d->window / 1000;
- if (st->d->audio_data_frames % st->d->samples_in_100ms) {
- /* round up to multiple of samples_in_100ms */
- st->d->audio_data_frames = st->d->audio_data_frames
- + st->d->samples_in_100ms
- - (st->d->audio_data_frames % st->d->samples_in_100ms);
- }
- st->d->audio_data = (double*) malloc(st->d->audio_data_frames *
- st->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[j] = 0.0;
- }
-
- ebur128_init_filter(st);
-
- if (st->d->use_histogram) {
- st->d->block_energy_histogram = malloc(1000 * sizeof(unsigned long));
- CHECK_ERROR(!st->d->block_energy_histogram, 0, free_audio_data)
- for (i = 0; i < 1000; ++i) {
- st->d->block_energy_histogram[i] = 0;
- }
- } else {
- st->d->block_energy_histogram = NULL;
- }
- if (st->d->use_histogram) {
- st->d->short_term_block_energy_histogram = malloc(1000 * sizeof(unsigned long));
- CHECK_ERROR(!st->d->short_term_block_energy_histogram, 0, free_block_energy_histogram)
- for (i = 0; i < 1000; ++i) {
- st->d->short_term_block_energy_histogram[i] = 0;
- }
- } else {
- st->d->short_term_block_energy_histogram = NULL;
- }
- STAILQ_INIT(&st->d->block_list);
- st->d->block_list_size = 0;
- st->d->block_list_max = st->d->history / 100;
- STAILQ_INIT(&st->d->short_term_block_list);
- st->d->st_block_list_size = 0;
- st->d->st_block_list_max = st->d->history / 3000;
- st->d->short_term_frame_counter = 0;
-
- result = ebur128_init_resampler(st);
- CHECK_ERROR(result, 0, free_short_term_block_energy_histogram)
-
- /* the first block needs 400ms of audio data */
- st->d->needed_frames = st->d->samples_in_100ms * 4;
- /* start at the beginning of the buffer */
- st->d->audio_data_index = 0;
-
- /* initialize static constants */
- relative_gate_factor = pow(10.0, relative_gate / 10.0);
- minus_twenty_decibels = pow(10.0, -20.0 / 10.0);
- histogram_energy_boundaries[0] = pow(10.0, (-70.0 + 0.691) / 10.0);
- if (st->d->use_histogram) {
- for (i = 0; i < 1000; ++i) {
- histogram_energies[i] = pow(10.0, ((double) i / 10.0 - 69.95 + 0.691) / 10.0);
- }
- for (i = 1; i < 1001; ++i) {
- histogram_energy_boundaries[i] = pow(10.0, ((double) i / 10.0 - 70.0 + 0.691) / 10.0);
- }
- }
-
- return st;
-
-free_short_term_block_energy_histogram:
- free(st->d->short_term_block_energy_histogram);
-free_block_energy_histogram:
- free(st->d->block_energy_histogram);
-free_audio_data:
- free(st->d->audio_data);
-free_prev_true_peak:
- free(st->d->prev_true_peak);
-free_true_peak:
- free(st->d->true_peak);
-free_prev_sample_peak:
- free(st->d->prev_sample_peak);
-free_sample_peak:
- free(st->d->sample_peak);
-free_channel_map:
- free(st->d->channel_map);
-free_internal:
- free(st->d);
-free_state:
- free(st);
-exit:
- return NULL;
-}
-
-void ebur128_destroy(ebur128_state** st) {
- struct ebur128_dq_entry* entry;
- free((*st)->d->block_energy_histogram);
- free((*st)->d->short_term_block_energy_histogram);
- free((*st)->d->audio_data);
- free((*st)->d->channel_map);
- free((*st)->d->sample_peak);
- free((*st)->d->prev_sample_peak);
- free((*st)->d->true_peak);
- free((*st)->d->prev_true_peak);
- while (!STAILQ_EMPTY(&(*st)->d->block_list)) {
- entry = STAILQ_FIRST(&(*st)->d->block_list);
- STAILQ_REMOVE_HEAD(&(*st)->d->block_list, entries);
- free(entry);
- }
- while (!STAILQ_EMPTY(&(*st)->d->short_term_block_list)) {
- entry = STAILQ_FIRST(&(*st)->d->short_term_block_list);
- STAILQ_REMOVE_HEAD(&(*st)->d->short_term_block_list, entries);
- free(entry);
- }
- ebur128_destroy_resampler(*st);
- free((*st)->d);
- free(*st);
- *st = NULL;
-}
-
-static void ebur128_check_true_peak(ebur128_state* st, size_t frames) {
- size_t c, i, frames_out;
-
- frames_out = interp_process(st->d->interp, frames,
- st->d->resampler_buffer_input,
- st->d->resampler_buffer_output);
-
- for (i = 0; i < frames_out; ++i) {
- for (c = 0; c < st->channels; ++c) {
- float val = st->d->resampler_buffer_output[i * st->channels + c];
-
- if (val > st->d->prev_true_peak[c]) {
- st->d->prev_true_peak[c] = val;
- } else if (-val > st->d->prev_true_peak[c]) {
- st->d->prev_true_peak[c] = -val;
- }
- }
- }
-}
-
-#if defined(__SSE2_MATH__) || defined(_M_X64) || _M_IX86_FP >= 2
-#include <xmmintrin.h>
-#define TURN_ON_FTZ \
- unsigned int mxcsr = _mm_getcsr(); \
- _mm_setcsr(mxcsr | _MM_FLUSH_ZERO_ON);
-#define TURN_OFF_FTZ _mm_setcsr(mxcsr);
-#define FLUSH_MANUALLY
-#else
-#warning "manual FTZ is being used, please enable SSE2 (-msse2 -mfpmath=sse)"
-#define TURN_ON_FTZ
-#define TURN_OFF_FTZ
-#define FLUSH_MANUALLY \
- st->d->v[ci][4] = fabs(st->d->v[ci][4]) < DBL_MIN ? 0.0 : st->d->v[ci][4]; \
- st->d->v[ci][3] = fabs(st->d->v[ci][3]) < DBL_MIN ? 0.0 : st->d->v[ci][3]; \
- st->d->v[ci][2] = fabs(st->d->v[ci][2]) < DBL_MIN ? 0.0 : st->d->v[ci][2]; \
- st->d->v[ci][1] = fabs(st->d->v[ci][1]) < DBL_MIN ? 0.0 : st->d->v[ci][1];
-#endif
-
-#define EBUR128_FILTER(type, min_scale, max_scale) \
-static void ebur128_filter_##type(ebur128_state* st, const type* src, \
- size_t frames) { \
- static double scaling_factor = \
- -((double) (min_scale)) > (double) (max_scale) ? \
- -((double) (min_scale)) : (double) (max_scale); \
- double* audio_data = st->d->audio_data + st->d->audio_data_index; \
- size_t i, c; \
- \
- TURN_ON_FTZ \
- \
- if ((st->mode & EBUR128_MODE_SAMPLE_PEAK) == EBUR128_MODE_SAMPLE_PEAK) { \
- for (c = 0; c < st->channels; ++c) { \
- double max = 0.0; \
- for (i = 0; i < frames; ++i) { \
- if (src[i * st->channels + c] > max) { \
- max = src[i * st->channels + c]; \
- } else if (-src[i * st->channels + c] > max) { \
- max = -1.0 * src[i * st->channels + c]; \
- } \
- } \
- max /= scaling_factor; \
- if (max > st->d->prev_sample_peak[c]) st->d->prev_sample_peak[c] = max; \
- } \
- } \
- if ((st->mode & EBUR128_MODE_TRUE_PEAK) == EBUR128_MODE_TRUE_PEAK && \
- st->d->interp) { \
- for (c = 0; c < st->channels; ++c) { \
- for (i = 0; i < frames; ++i) { \
- st->d->resampler_buffer_input[i * st->channels + c] = \
- (float) (src[i * st->channels + c] / scaling_factor); \
- } \
- } \
- ebur128_check_true_peak(st, frames); \
- } \
- for (c = 0; c < st->channels; ++c) { \
- int ci = st->d->channel_map[c] - 1; \
- if (ci < 0) continue; \
- else if (ci == EBUR128_DUAL_MONO - 1) ci = 0; /*dual mono */ \
- for (i = 0; i < frames; ++i) { \
- st->d->v[ci][0] = (double) (src[i * st->channels + c] / scaling_factor) \
- - st->d->a[1] * st->d->v[ci][1] \
- - st->d->a[2] * st->d->v[ci][2] \
- - st->d->a[3] * st->d->v[ci][3] \
- - st->d->a[4] * st->d->v[ci][4]; \
- audio_data[i * st->channels + c] = \
- st->d->b[0] * st->d->v[ci][0] \
- + st->d->b[1] * st->d->v[ci][1] \
- + st->d->b[2] * st->d->v[ci][2] \
- + st->d->b[3] * st->d->v[ci][3] \
- + st->d->b[4] * st->d->v[ci][4]; \
- st->d->v[ci][4] = st->d->v[ci][3]; \
- st->d->v[ci][3] = st->d->v[ci][2]; \
- st->d->v[ci][2] = st->d->v[ci][1]; \
- st->d->v[ci][1] = st->d->v[ci][0]; \
- } \
- FLUSH_MANUALLY \
- } \
- TURN_OFF_FTZ \
-}
-EBUR128_FILTER(short, SHRT_MIN, SHRT_MAX)
-EBUR128_FILTER(int, INT_MIN, INT_MAX)
-EBUR128_FILTER(float, -1.0f, 1.0f)
-EBUR128_FILTER(double, -1.0, 1.0)
-
-static double ebur128_energy_to_loudness(double energy) {
- return 10 * (log(energy) / log(10.0)) - 0.691;
-}
-
-static size_t find_histogram_index(double energy) {
- size_t index_min = 0;
- size_t index_max = 1000;
- size_t index_mid;
-
- do {
- index_mid = (index_min + index_max) / 2;
- if (energy >= histogram_energy_boundaries[index_mid]) {
- index_min = index_mid;
- } else {
- index_max = index_mid;
- }
- } while (index_max - index_min != 1);
-
- return index_min;
-}
-
-static int ebur128_calc_gating_block(ebur128_state* st, size_t frames_per_block,
- double* optional_output) {
- size_t i, c;
- double sum = 0.0;
- double channel_sum;
- for (c = 0; c < st->channels; ++c) {
- if (st->d->channel_map[c] == EBUR128_UNUSED) {
- continue;
- }
- channel_sum = 0.0;
- if (st->d->audio_data_index < frames_per_block * st->channels) {
- for (i = 0; i < st->d->audio_data_index / st->channels; ++i) {
- channel_sum += st->d->audio_data[i * st->channels + c] *
- st->d->audio_data[i * st->channels + c];
- }
- for (i = st->d->audio_data_frames -
- (frames_per_block -
- st->d->audio_data_index / st->channels);
- i < st->d->audio_data_frames; ++i) {
- channel_sum += st->d->audio_data[i * st->channels + c] *
- st->d->audio_data[i * st->channels + c];
- }
- } else {
- for (i = st->d->audio_data_index / st->channels - frames_per_block;
- i < st->d->audio_data_index / st->channels;
- ++i) {
- channel_sum += st->d->audio_data[i * st->channels + c] *
- st->d->audio_data[i * st->channels + c];
- }
- }
- if (st->d->channel_map[c] == EBUR128_Mp110 ||
- st->d->channel_map[c] == EBUR128_Mm110 ||
- st->d->channel_map[c] == EBUR128_Mp060 ||
- st->d->channel_map[c] == EBUR128_Mm060 ||
- st->d->channel_map[c] == EBUR128_Mp090 ||
- st->d->channel_map[c] == EBUR128_Mm090) {
- channel_sum *= 1.41;
- } else if (st->d->channel_map[c] == EBUR128_DUAL_MONO) {
- channel_sum *= 2.0;
- }
- sum += channel_sum;
- }
- sum /= (double) frames_per_block;
- if (optional_output) {
- *optional_output = sum;
- return EBUR128_SUCCESS;
- } else if (sum >= histogram_energy_boundaries[0]) {
- if (st->d->use_histogram) {
- ++st->d->block_energy_histogram[find_histogram_index(sum)];
- } else {
- struct ebur128_dq_entry* block;
- if (st->d->block_list_size == st->d->block_list_max) {
- block = STAILQ_FIRST(&st->d->block_list);
- STAILQ_REMOVE_HEAD(&st->d->block_list, entries);
- } else {
- block = (struct ebur128_dq_entry*) malloc(sizeof(struct ebur128_dq_entry));
- if (!block) {
- return EBUR128_ERROR_NOMEM;
- }
- st->d->block_list_size++;
- }
- block->z = sum;
- STAILQ_INSERT_TAIL(&st->d->block_list, block, entries);
- }
- return EBUR128_SUCCESS;
- } else {
- return EBUR128_SUCCESS;
- }
-}
-
-int ebur128_set_channel(ebur128_state* st,
- unsigned int channel_number,
- int value) {
- if (channel_number >= st->channels) {
- return 1;
- }
- if (value == EBUR128_DUAL_MONO &&
- (st->channels != 1 || channel_number != 0)) {
- fprintf(stderr, "EBUR128_DUAL_MONO only works with mono files!\n");
- return 1;
- }
- st->d->channel_map[channel_number] = value;
- return 0;
-}
-
-int ebur128_change_parameters(ebur128_state* st,
- unsigned int channels,
- unsigned long samplerate) {
- int errcode = EBUR128_SUCCESS;
- size_t j;
-
- if (channels == 0 || samplerate < 5) {
- return EBUR128_ERROR_NOMEM;
- }
-
- if (channels == st->channels &&
- samplerate == st->samplerate) {
- return EBUR128_ERROR_NO_CHANGE;
- }
-
- free(st->d->audio_data);
- st->d->audio_data = NULL;
-
- if (channels != st->channels) {
- unsigned int i;
-
- free(st->d->channel_map); st->d->channel_map = NULL;
- free(st->d->sample_peak); st->d->sample_peak = NULL;
- free(st->d->prev_sample_peak); st->d->prev_sample_peak = NULL;
- free(st->d->true_peak); st->d->true_peak = NULL;
- free(st->d->prev_true_peak); st->d->prev_true_peak = NULL;
- st->channels = channels;
-
- errcode = ebur128_init_channel_map(st);
- CHECK_ERROR(errcode, EBUR128_ERROR_NOMEM, exit)
-
- st->d->sample_peak = (double*) malloc(channels * sizeof(double));
- CHECK_ERROR(!st->d->sample_peak, EBUR128_ERROR_NOMEM, exit)
- st->d->prev_sample_peak = (double*) malloc(channels * sizeof(double));
- CHECK_ERROR(!st->d->prev_sample_peak, EBUR128_ERROR_NOMEM, exit)
- st->d->true_peak = (double*) malloc(channels * sizeof(double));
- CHECK_ERROR(!st->d->true_peak, EBUR128_ERROR_NOMEM, exit)
- st->d->prev_true_peak = (double*) malloc(channels * sizeof(double));
- CHECK_ERROR(!st->d->prev_true_peak, EBUR128_ERROR_NOMEM, exit)
- for (i = 0; i < channels; ++i) {
- st->d->sample_peak[i] = 0.0;
- st->d->prev_sample_peak[i] = 0.0;
- st->d->true_peak[i] = 0.0;
- st->d->prev_true_peak[i] = 0.0;
- }
- }
- if (samplerate != st->samplerate) {
- st->samplerate = samplerate;
- st->d->samples_in_100ms = (st->samplerate + 5) / 10;
- ebur128_init_filter(st);
- }
- st->d->audio_data_frames = st->samplerate * st->d->window / 1000;
- if (st->d->audio_data_frames % st->d->samples_in_100ms) {
- /* round up to multiple of samples_in_100ms */
- st->d->audio_data_frames = st->d->audio_data_frames
- + st->d->samples_in_100ms
- - (st->d->audio_data_frames % st->d->samples_in_100ms);
- }
- st->d->audio_data = (double*) malloc(st->d->audio_data_frames *
- st->channels *
- sizeof(double));
- CHECK_ERROR(!st->d->audio_data, EBUR128_ERROR_NOMEM, exit)
- for (j = 0; j < st->d->audio_data_frames * st->channels; ++j) {
- st->d->audio_data[j] = 0.0;
- }
-
- ebur128_destroy_resampler(st);
- errcode = ebur128_init_resampler(st);
- CHECK_ERROR(errcode, EBUR128_ERROR_NOMEM, exit)
-
- /* the first block needs 400ms of audio data */
- st->d->needed_frames = st->d->samples_in_100ms * 4;
- /* start at the beginning of the buffer */
- st->d->audio_data_index = 0;
- /* reset short term frame counter */
- st->d->short_term_frame_counter = 0;
-
-exit:
- return errcode;
-}
-
-int ebur128_set_max_window(ebur128_state* st, unsigned long window)
-{
- int errcode = EBUR128_SUCCESS;
- size_t j;
-
- if ((st->mode & EBUR128_MODE_S) == EBUR128_MODE_S && window < 3000) {
- window = 3000;
- } else if ((st->mode & EBUR128_MODE_M) == EBUR128_MODE_M && window < 400) {
- window = 400;
- }
- if (window == st->d->window) {
- return EBUR128_ERROR_NO_CHANGE;
- }
-
- st->d->window = window;
- free(st->d->audio_data);
- st->d->audio_data = NULL;
- st->d->audio_data_frames = st->samplerate * st->d->window / 1000;
- if (st->d->audio_data_frames % st->d->samples_in_100ms) {
- /* round up to multiple of samples_in_100ms */
- st->d->audio_data_frames = st->d->audio_data_frames
- + st->d->samples_in_100ms
- - (st->d->audio_data_frames % st->d->samples_in_100ms);
- }
- st->d->audio_data = (double*) malloc(st->d->audio_data_frames *
- st->channels *
- sizeof(double));
- CHECK_ERROR(!st->d->audio_data, EBUR128_ERROR_NOMEM, exit)
- for (j = 0; j < st->d->audio_data_frames * st->channels; ++j) {
- st->d->audio_data[j] = 0.0;
- }
-
- /* the first block needs 400ms of audio data */
- st->d->needed_frames = st->d->samples_in_100ms * 4;
- /* start at the beginning of the buffer */
- st->d->audio_data_index = 0;
- /* reset short term frame counter */
- st->d->short_term_frame_counter = 0;
-
-exit:
- return errcode;
-}
-
-int ebur128_set_max_history(ebur128_state* st, unsigned long history)
-{
- if ((st->mode & EBUR128_MODE_LRA) == EBUR128_MODE_LRA && history < 3000) {
- history = 3000;
- } else if ((st->mode & EBUR128_MODE_M) == EBUR128_MODE_M && history < 400) {
- history = 400;
- }
- if (history == st->d->history) {
- return EBUR128_ERROR_NO_CHANGE;
- }
- st->d->history = history;
- st->d->block_list_max = st->d->history / 100;
- st->d->st_block_list_max = st->d->history / 3000;
- while (st->d->block_list_size > st->d->block_list_max) {
- struct ebur128_dq_entry* block = STAILQ_FIRST(&st->d->block_list);
- STAILQ_REMOVE_HEAD(&st->d->block_list, entries);
- free(block);
- st->d->block_list_size--;
- }
- while (st->d->st_block_list_size > st->d->st_block_list_max) {
- struct ebur128_dq_entry* block = STAILQ_FIRST(&st->d->short_term_block_list);
- STAILQ_REMOVE_HEAD(&st->d->short_term_block_list, entries);
- free(block);
- st->d->st_block_list_size--;
- }
- return EBUR128_SUCCESS;
-}
-
-static int ebur128_energy_shortterm(ebur128_state* st, double* out);
-#define EBUR128_ADD_FRAMES(type) \
-int ebur128_add_frames_##type(ebur128_state* st, \
- const type* src, size_t frames) { \
- size_t src_index = 0; \
- unsigned int c = 0; \
- for (c = 0; c < st->channels; c++) { \
- st->d->prev_sample_peak[c] = 0.0; \
- st->d->prev_true_peak[c] = 0.0; \
- } \
- while (frames > 0) { \
- if (frames >= st->d->needed_frames) { \
- ebur128_filter_##type(st, src + src_index, st->d->needed_frames); \
- src_index += st->d->needed_frames * st->channels; \
- frames -= st->d->needed_frames; \
- st->d->audio_data_index += st->d->needed_frames * st->channels; \
- /* calculate the new gating block */ \
- if ((st->mode & EBUR128_MODE_I) == EBUR128_MODE_I) { \
- if (ebur128_calc_gating_block(st, st->d->samples_in_100ms * 4, NULL)) {\
- return EBUR128_ERROR_NOMEM; \
- } \
- } \
- if ((st->mode & EBUR128_MODE_LRA) == EBUR128_MODE_LRA) { \
- st->d->short_term_frame_counter += st->d->needed_frames; \
- if (st->d->short_term_frame_counter == st->d->samples_in_100ms * 30) { \
- struct ebur128_dq_entry* block; \
- double st_energy; \
- if (ebur128_energy_shortterm(st, &st_energy) == EBUR128_SUCCESS && \
- st_energy >= histogram_energy_boundaries[0]) { \
- if (st->d->use_histogram) { \
- ++st->d->short_term_block_energy_histogram[ \
- find_histogram_index(st_energy)];\
- } else { \
- if (st->d->st_block_list_size == st->d->st_block_list_max) { \
- block = STAILQ_FIRST(&st->d->short_term_block_list); \
- STAILQ_REMOVE_HEAD(&st->d->short_term_block_list, entries); \
- } else {