2 * filter_audiolevel.c -- get the audio level of each channel
3 * Copyright (C) 2002 Steve Harris
4 * Copyright (C) 2010 Marco Gittler <g.marco@freenet.de>
5 * Copyright (C) 2012 Dan Dennedy <dan@dennedy.org>
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software Foundation,
19 * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
22 #include <framework/mlt_filter.h>
23 #include <framework/mlt_frame.h>
24 #include <framework/mlt_log.h>
29 #define AMPTODBFS(n) (log10(n) * 20.0)
31 //----------------------------------------------------------------------------
32 // IEC standard dB scaling -- as borrowed from meterbridge (c) Steve Harris
34 static inline double IEC_Scale(double dB)
40 else if (dB < -60.0f) // 0.0 .. 2.5
41 fScale = (dB + 70.0f) * 0.0025f;
42 else if (dB < -50.0f) // 2.5 .. 7.5
43 fScale = (dB + 60.0f) * 0.005f + 0.025f;
44 else if (dB < -40.0) // 7.5 .. 15.0
45 fScale = (dB + 50.0f) * 0.0075f + 0.075f;
46 else if (dB < -30.0f) // 15.0 .. 30.0
47 fScale = (dB + 40.0f) * 0.015f + 0.15f;
48 else if (dB < -20.0f) // 30.0 .. 50.0
49 fScale = (dB + 30.0f) * 0.02f + 0.3f;
50 else if (dB < -0.001f || dB > 0.001f) // 50.0 .. 100.0
51 fScale = (dB + 20.0f) * 0.025f + 0.5f;
56 static int filter_get_audio( mlt_frame frame, void **buffer, mlt_audio_format *format, int *frequency, int *channels, int *samples )
58 mlt_filter filter = mlt_frame_pop_audio( frame );
59 int iec_scale = mlt_properties_get_int( MLT_FILTER_PROPERTIES(filter), "iec_scale" );
60 *format = mlt_audio_s16;
61 int error = mlt_frame_get_audio( frame, buffer, format, frequency, channels, samples );
62 if ( error || !buffer ) return error;
64 int num_channels = *channels;
65 int num_samples = *samples > 200 ? 200 : *samples;
66 int num_oversample = 0;
69 int16_t *pcm = (int16_t*) *buffer;
71 for ( c = 0; c < *channels; c++ )
76 for ( s = 0; s < num_samples; s++ )
78 int sample = abs( pcm[c + s * num_channels] / 128 );
84 // 10 samples @max => show max signal
85 if ( num_oversample > 10 )
90 // if 3 samples over max => 1 peak over 0 db (0 dB = 40.0)
91 if ( num_oversample > 3 )
94 // max amplitude = 40/42, 3to10 oversamples=41, more then 10 oversamples=42
95 if ( level == 0.0 && num_samples > 0 )
96 level = val / num_samples * 40.0/42.0 / 127.0;
98 level = IEC_Scale( AMPTODBFS( level ) );
99 sprintf( key, "meta.media.audio_level.%d", c );
100 mlt_properties_set_double( MLT_FRAME_PROPERTIES( frame ), key, level );
101 sprintf( key, "_audio_level.%d", c );
102 mlt_properties_set_double( MLT_FILTER_PROPERTIES( filter ), key, level );
103 mlt_log_debug( MLT_FILTER_SERVICE( filter ), "channel %d level %f\n", c, level );
109 /** Filter processing.
112 static mlt_frame filter_process( mlt_filter filter, mlt_frame frame )
114 mlt_frame_push_audio( frame, filter );
115 mlt_frame_push_audio( frame, filter_get_audio );
119 /** Constructor for the filter.
122 mlt_filter filter_audiolevel_init( mlt_profile profile, mlt_service_type type, const char *id, char *arg )
124 mlt_filter filter = mlt_filter_new();
127 filter->process = filter_process;
128 mlt_properties_set_int( MLT_FILTER_PROPERTIES(filter), "iec_scale", 1 );