/** @internal @This handles input. * * @param upipe description structure of the pipe * @param uref uref structure * @param upump_p reference to upump structure */ static void upipe_filter_ebur128_input(struct upipe *upipe, struct uref *uref, struct upump **upump_p) { struct upipe_filter_ebur128 *upipe_filter_ebur128 = upipe_filter_ebur128_from_upipe(upipe); double loud = 0, lra = 0, global = 0; size_t samples; if (unlikely(!ubase_check(uref_sound_size(uref, &samples, NULL)))) { upipe_warn(upipe, "invalid sound buffer"); uref_free(uref); return; } const char *channel = NULL; const int16_t *buf = NULL; if (ubase_check(uref_sound_plane_iterate(uref, &channel)) && channel) { if (unlikely(!ubase_check(uref_sound_plane_read_int16_t(uref, channel, 0, -1, &buf)))) { upipe_warn(upipe, "error mapping sound buffer"); uref_free(uref); return; } if (unlikely((uintptr_t)buf & 1)) { upipe_warn(upipe, "unaligned buffer"); } ebur128_add_frames_short(upipe_filter_ebur128->st, buf, samples); uref_sound_plane_unmap(uref, channel, 0, -1); } ebur128_loudness_momentary(upipe_filter_ebur128->st, &loud); ebur128_loudness_range(upipe_filter_ebur128->st, &lra); ebur128_loudness_global(upipe_filter_ebur128->st, &global); uref_ebur128_set_momentary(uref, loud); uref_ebur128_set_lra(uref, lra); uref_ebur128_set_global(uref, global); upipe_verbose_va(upipe, "loud %f lra %f global %f", loud, lra, global); upipe_filter_ebur128_output(upipe, uref, upump_p); }
static void analyze_audio( mlt_filter filter, void* buffer, int samples ) { mlt_properties properties = MLT_FILTER_PROPERTIES( filter ); private_data* pdata = (private_data*)filter->child; int result = -1; double loudness = 0.0; ebur128_add_frames_float( pdata->r128, buffer, samples ); if( mlt_properties_get_int( MLT_FILTER_PROPERTIES(filter), "calc_program" ) ) { result = ebur128_loudness_global( pdata->r128, &loudness ); if( result == EBUR128_SUCCESS && loudness != HUGE_VAL && loudness != -HUGE_VAL ) { mlt_properties_set_double( properties, "program", loudness ); } } if( mlt_properties_get_int( MLT_FILTER_PROPERTIES(filter), "calc_shortterm" ) ) { result = ebur128_loudness_shortterm( pdata->r128, &loudness ); if( result == EBUR128_SUCCESS && loudness != HUGE_VAL && loudness != -HUGE_VAL ) { mlt_properties_set_double( properties, "shortterm", loudness ); } } if( mlt_properties_get_int( MLT_FILTER_PROPERTIES(filter), "calc_momentary" ) ) { result = ebur128_loudness_momentary( pdata->r128, &loudness ); if( result == EBUR128_SUCCESS && loudness != HUGE_VAL && loudness != -HUGE_VAL ) { mlt_properties_set_double( properties, "momentary", loudness ); } } if( mlt_properties_get_int( MLT_FILTER_PROPERTIES(filter), "calc_range" ) ) { double range = 0; result = ebur128_loudness_range( pdata->r128, &range ); if( result == EBUR128_SUCCESS && range != HUGE_VAL && range != -HUGE_VAL ) { mlt_properties_set_double( properties, "range", range ); } } if( mlt_properties_get_int( MLT_FILTER_PROPERTIES(filter), "calc_peak" ) ) { double prev_peak = 0.0; double max_peak = 0.0; int c = 0; for( c = 0; c < pdata->r128->channels; c++ ) { double peak; result = ebur128_sample_peak( pdata->r128, c, &peak ); if( result == EBUR128_SUCCESS && peak != HUGE_VAL && peak > max_peak ) { max_peak = peak; } result = ebur128_prev_sample_peak( pdata->r128, c, &peak ); if( result == EBUR128_SUCCESS && peak != HUGE_VAL && peak > prev_peak ) { prev_peak = peak; } } mlt_properties_set_double( properties, "max_peak", 20 * log10(max_peak) ); mlt_properties_set_double( properties, "peak", 20 * log10(prev_peak) ); } if( mlt_properties_get_int( MLT_FILTER_PROPERTIES(filter), "calc_true_peak" ) ) { double prev_peak = 0.0; double max_peak = 0.0; int c = 0; for( c = 0; c < pdata->r128->channels; c++ ) { double peak; result = ebur128_true_peak( pdata->r128, c, &peak ); if( result == EBUR128_SUCCESS && peak != HUGE_VAL && peak > max_peak ) { max_peak = peak; } result = ebur128_prev_true_peak( pdata->r128, c, &peak ); if( result == EBUR128_SUCCESS && peak != HUGE_VAL && peak > prev_peak ) { prev_peak = peak; } } mlt_properties_set_double( properties, "max_true_peak", 20 * log10(max_peak) ); mlt_properties_set_double( properties, "true_peak", 20 * log10(prev_peak) ); } mlt_properties_set_position( properties, "frames_processed", mlt_properties_get_position( properties, "frames_processed" ) + 1 ); }
/** @internal @This handles input. * * @param upipe description structure of the pipe * @param uref uref structure * @param upump_p reference to upump structure */ static void upipe_filter_ebur128_input(struct upipe *upipe, struct uref *uref, struct upump **upump_p) { struct upipe_filter_ebur128 *upipe_filter_ebur128 = upipe_filter_ebur128_from_upipe(upipe); double loud = 0, lra = 0, global = 0; if (unlikely(upipe_filter_ebur128->output_flow == NULL)) { upipe_err_va(upipe, "invalid input"); uref_free(uref); return; } size_t samples; uint8_t sample_size; if (unlikely(!ubase_check(uref_sound_size(uref, &samples, &sample_size)))) { upipe_warn(upipe, "invalid sound buffer"); uref_free(uref); return; } void *buf = NULL; const char *channel = NULL; if (upipe_filter_ebur128->planes == 1) { if (ubase_check(uref_sound_plane_iterate(uref, &channel)) && channel) { if (unlikely(!ubase_check(uref_sound_plane_read_void(uref, channel, 0, -1, (const void **)&buf)))) { upipe_warn(upipe, "error mapping sound buffer"); uref_free(uref); return; } } } else { buf = malloc(sample_size * upipe_filter_ebur128->channels * samples); if (buf == NULL) { upipe_throw_fatal(upipe, UBASE_ERR_ALLOC); uref_free(uref); return; } if (!ubase_check(uref_sound_interleave(uref, (uint8_t *)buf, 0, samples, sample_size, upipe_filter_ebur128->planes))) { upipe_warn(upipe, "error mapping sound buffer"); uref_free(uref); return; } } if (unlikely((uintptr_t)buf & 1)) upipe_warn(upipe, "unaligned buffer"); switch (upipe_filter_ebur128->fmt) { case UPIPE_FILTER_EBUR128_SHORT: ebur128_add_frames_short(upipe_filter_ebur128->st, (short *)buf, samples); break; case UPIPE_FILTER_EBUR128_INT: ebur128_add_frames_int(upipe_filter_ebur128->st, (int *)buf, samples); break; case UPIPE_FILTER_EBUR128_FLOAT: ebur128_add_frames_float(upipe_filter_ebur128->st, (float *)buf, samples); break; case UPIPE_FILTER_EBUR128_DOUBLE: ebur128_add_frames_double(upipe_filter_ebur128->st, (double *)buf, samples); break; default: upipe_warn_va(upipe, "unknown sample format %d", upipe_filter_ebur128->fmt); break; } if (upipe_filter_ebur128->planes == 1) uref_sound_plane_unmap(uref, channel, 0, -1); else free(buf); ebur128_loudness_momentary(upipe_filter_ebur128->st, &loud); ebur128_loudness_range(upipe_filter_ebur128->st, &lra); ebur128_loudness_global(upipe_filter_ebur128->st, &global); uref_ebur128_set_momentary(uref, loud); uref_ebur128_set_lra(uref, lra); uref_ebur128_set_global(uref, global); upipe_verbose_va(upipe, "loud %f lra %f global %f", loud, lra, global); upipe_filter_ebur128_output(upipe, uref, upump_p); }