audiobargraph_a: simplify Close
[vlc/gmpfix.git] / modules / audio_filter / audiobargraph_a.c
blob53cba3e04dec29a5e5716940d50ea33554079cdb
1 /*****************************************************************************
2 * audiobargraph_a.c : audiobargraph audio plugin for vlc
3 *****************************************************************************
4 * Copyright (C) 2002-2009 VLC authors and VideoLAN
5 * $Id$
7 * Authors: Clement CHESNIN <clement.chesnin@gmail.com>
8 * Philippe COENT <philippe.coent@tdf.fr>
10 * This program is free software; you can redistribute it and/or modify it
11 * under the terms of the GNU Lesser General Public License as published by
12 * the Free Software Foundation; either version 2.1 of the License, or
13 * (at your option) any later version.
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU Lesser General Public License for more details.
20 * You should have received a copy of the GNU Lesser General Public License
21 * along with this program; if not, write to the Free Software Foundation,
22 * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
23 *****************************************************************************/
25 /*****************************************************************************
26 * Preamble
27 *****************************************************************************/
28 #ifdef HAVE_CONFIG_H
29 # include "config.h"
30 #endif
32 #include <vlc_common.h>
33 #include <vlc_plugin.h>
34 #include <vlc_aout.h>
35 #include <vlc_filter.h>
37 #include <math.h>
39 #define BARGRAPH_TEXT N_("Defines if BarGraph information should be sent")
40 #define BARGRAPH_LONGTEXT N_("Defines if BarGraph information should be sent. "\
41 "1 if the information should be sent, 0 otherwise (default 1)." )
42 #define BARGRAPH_REPETITION_TEXT N_("Sends the barGraph information every n audio packets")
43 #define BARGRAPH_REPETITION_LONGTEXT N_("Defines how often the barGraph information should be sent. "\
44 "Sends the barGraph information every n audio packets (default 4)." )
45 #define SILENCE_TEXT N_("Defines if silence alarm information should be sent")
46 #define SILENCE_LONGTEXT N_("Defines if silence alarm information should be sent. "\
47 "1 if the information should be sent, 0 otherwise (default 1)." )
48 #define TIME_WINDOW_TEXT N_("Time window to use in ms")
49 #define TIME_WINDOW_LONGTEXT N_("Time Window during when the audio level is measured in ms for silence detection. "\
50 "If the audio level is under the threshold during this time, "\
51 "an alarm is sent (default 5000)." )
52 #define ALARM_THRESHOLD_TEXT N_("Minimum Audio level to raise the alarm")
53 #define ALARM_THRESHOLD_LONGTEXT N_("Threshold to be attained to raise an alarm. "\
54 "If the audio level is under the threshold during this time, "\
55 "an alarm is sent (default 0.1)." )
56 #define REPETITION_TIME_TEXT N_("Time between two alarm messages in ms" )
57 #define REPETITION_TIME_LONGTEXT N_("Time between two alarm messages in ms. "\
58 "This value is used to avoid alarm saturation (default 2000)." )
60 #define CFG_PREFIX "audiobargraph_a-"
62 /*****************************************************************************
63 * Module descriptor
64 *****************************************************************************/
65 static int Open( vlc_object_t * );
66 static void Close( vlc_object_t * );
67 static block_t *DoWork( filter_t *, block_t * );
69 vlc_module_begin ()
70 set_description( N_("Audio part of the BarGraph function") )
71 set_shortname( N_("Audiobar Graph") )
72 set_capability( "audio filter", 0 )
73 set_category( CAT_AUDIO )
74 set_subcategory( SUBCAT_AUDIO_AFILTER )
76 add_obsolete_string( CFG_PREFIX "address" )
77 add_obsolete_integer( CFG_PREFIX "port" )
78 add_integer( CFG_PREFIX "bargraph", 1, BARGRAPH_TEXT, BARGRAPH_LONGTEXT, false )
79 add_integer( CFG_PREFIX "bargraph_repetition", 4, BARGRAPH_REPETITION_TEXT, BARGRAPH_REPETITION_LONGTEXT, false )
80 add_integer( CFG_PREFIX "silence", 1, SILENCE_TEXT, SILENCE_LONGTEXT, false )
81 add_integer( CFG_PREFIX "time_window", 5000, TIME_WINDOW_TEXT, TIME_WINDOW_LONGTEXT, false )
82 add_float( CFG_PREFIX "alarm_threshold", 0.1, ALARM_THRESHOLD_TEXT, ALARM_THRESHOLD_LONGTEXT, false )
83 add_integer( CFG_PREFIX "repetition_time", 2000, REPETITION_TIME_TEXT, REPETITION_TIME_LONGTEXT, false )
84 add_obsolete_integer( CFG_PREFIX "connection_reset" )
86 set_callbacks( Open, Close )
87 vlc_module_end ()
89 typedef struct ValueDate_t {
90 float value;
91 mtime_t date;
92 struct ValueDate_t* next;
93 } ValueDate_t;
95 struct filter_sys_t
97 int bargraph;
98 int bargraph_repetition;
99 int silence;
100 int time_window;
101 float alarm_threshold;
102 int repetition_time;
103 int counter;
104 int nbChannels;
105 ValueDate_t* first;
106 ValueDate_t* last;
107 int started;
108 mtime_t lastAlarm;
111 /*****************************************************************************
112 * Open: open the visualizer
113 *****************************************************************************/
114 static int Open( vlc_object_t *p_this )
116 filter_t *p_filter = (filter_t *)p_this;
117 filter_sys_t *p_sys = p_filter->p_sys = malloc( sizeof( *p_sys ) );
118 if( !p_sys )
119 return VLC_ENOMEM;
121 p_sys->bargraph = var_CreateGetIntegerCommand( p_filter, "audiobargraph_a-bargraph" );
122 p_sys->bargraph_repetition = var_CreateGetIntegerCommand( p_filter, "audiobargraph_a-bargraph_repetition" );
123 p_sys->silence = var_CreateGetIntegerCommand( p_filter, "audiobargraph_a-silence" );
124 p_sys->time_window = var_CreateGetIntegerCommand( p_filter, "audiobargraph_a-time_window" );
125 p_sys->alarm_threshold = var_CreateGetFloatCommand( p_filter, "audiobargraph_a-alarm_threshold" );
126 p_sys->repetition_time = var_CreateGetIntegerCommand( p_filter, "audiobargraph_a-repetition_time" );
127 p_sys->counter = 0;
128 p_sys->nbChannels = 0;
129 p_sys->first = NULL;
130 p_sys->last = NULL;
131 p_sys->started = 0;
132 p_sys->lastAlarm = 0;
134 p_filter->fmt_in.audio.i_format = VLC_CODEC_FL32;
135 p_filter->fmt_out.audio = p_filter->fmt_in.audio;
136 p_filter->pf_audio_filter = DoWork;
138 var_Create( p_filter->p_libvlc, "audiobargraph_v-alarm", VLC_VAR_BOOL );
139 var_Create( p_filter->p_libvlc, "audiobargraph_v-i_values", VLC_VAR_STRING );
141 return VLC_SUCCESS;
144 /*****************************************************************************
145 * DoWork: treat an audio buffer
146 ****************************************************************************/
147 static block_t *DoWork( filter_t *p_filter, block_t *p_in_buf )
149 filter_sys_t *p_sys = p_filter->p_sys;
150 int i;
151 float *p_sample = (float *)p_in_buf->p_buffer;
152 float i_value[AOUT_CHAN_MAX];
153 float ch;
154 float max = 0.0;
155 int nbChannels = 0;
156 ValueDate_t* current = NULL;
157 float sum;
158 int count = 0;
160 nbChannels = aout_FormatNbChannels( &p_filter->fmt_in.audio );
161 p_sys->nbChannels = nbChannels;
163 for (i=0; i<nbChannels; i++) {
164 i_value[i] = 0.;
167 /* 1 - Compute the peack values */
168 for ( i = 0 ; i < (int)(p_in_buf->i_nb_samples); i++ )
170 for (int j = 0; j<nbChannels; j++) {
171 ch = (*p_sample++);
172 if (ch > i_value[j])
173 i_value[j] = ch;
174 if (ch > max)
175 max = ch;
178 max = powf( max, 2 );
180 if (p_sys->silence) {
181 /* 2 - store the new value */
182 ValueDate_t *new = xmalloc(sizeof(*new));
183 new->value = max;
184 new->date = p_in_buf->i_pts;
185 new->next = NULL;
186 if (p_sys->last != NULL) {
187 p_sys->last->next = new;
189 p_sys->last = new;
190 if (p_sys->first == NULL) {
191 p_sys->first = new;
194 /* 3 - delete too old values */
195 while (p_sys->first->date < (new->date - (p_sys->time_window*1000))) {
196 p_sys->started = 1; // we have enough values to compute a valid total
197 current = p_sys->first;
198 p_sys->first = p_sys->first->next;
199 free(current);
202 /* If last message was sent enough time ago */
203 if ((p_sys->started) && (p_in_buf->i_pts > p_sys->lastAlarm + (p_sys->repetition_time*1000))) {
205 /* 4 - compute the RMS */
206 current = p_sys->first;
207 sum = 0.0;
208 while (current != NULL) {
209 sum += current->value;
210 count ++;
211 current = current->next;
213 sum /= count;
214 sum = sqrtf(sum);
216 /* 5 - compare it to the threshold */
217 var_SetBool(p_filter->p_libvlc, "audiobargraph_v-alarm",
218 sum < p_sys->alarm_threshold);
220 p_sys->lastAlarm = p_in_buf->i_pts;
224 /*for (i=0; i<nbChannels; i++) {
225 value[i] = abs(i_value[i]*100);
226 if ( value[i] > p_sys->value[i] - 6 )
227 p_sys->value[i] = value[i];
228 else
229 p_sys->value[i] = p_sys->value[i] - 6;
232 if (p_sys->bargraph) {
233 /* 6 - sent the message with the values for the BarGraph */
234 if ((nbChannels > 0) && (p_sys->counter%(p_sys->bargraph_repetition) == 0)) {
235 char message[256];
236 size_t j = 0;
238 for (i = 0; i < nbChannels; i++) {
239 if (j >= sizeof (message))
240 break;
241 j += snprintf(message + j, sizeof (message),"%f:", i_value[i]);
244 message[--j] = '\0';
245 msg_Dbg( p_filter, "values: %s", message );
247 var_SetString(p_filter->p_libvlc, "audiobargraph_v-i_values",
248 message);
252 if (p_sys->counter > p_sys->bargraph_repetition*100)
253 p_sys->counter = 0;
255 p_sys->counter++;
257 return p_in_buf;
260 /*****************************************************************************
261 * Close: close the plugin
262 *****************************************************************************/
263 static void Close( vlc_object_t *p_this )
265 filter_t * p_filter = (filter_t *)p_this;
266 filter_sys_t *p_sys = p_filter->p_sys;
268 var_Destroy( p_filter->p_libvlc, "audiobargraph_v-i_values" );
269 var_Destroy( p_filter->p_libvlc, "audiobargraph_v-alarm" );
271 while (p_sys->first != NULL) {
272 ValueDate_t *current = p_sys->first;
273 p_sys->first = p_sys->first->next;
274 free(current);
276 free( p_sys );