MODULES_LIST: add missing entries
[vlc.git] / modules / audio_filter / audiobargraph_a.c
blobbdccf32f38b5a67c5fb88eb671ed4e0783633dfc
1 /*****************************************************************************
2 * audiobargraph_a.c : audiobargraph audio plugin for vlc
3 *****************************************************************************
4 * Copyright (C) 2002-2014 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 ) // FIXME: this is a bool
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 ) // FIXME: this is a bool
81 add_integer( CFG_PREFIX "time_window", 5000, TIME_WINDOW_TEXT, TIME_WINDOW_LONGTEXT, false )
82 add_float( CFG_PREFIX "alarm_threshold", 0.02, 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 bool bargraph;
98 int bargraph_repetition;
99 bool silence;
100 int64_t time_window;
101 float alarm_threshold;
102 int64_t repetition_time;
103 int counter;
104 ValueDate_t* first;
105 ValueDate_t* last;
106 int started;
107 mtime_t lastAlarm;
110 /*****************************************************************************
111 * Open: open the visualizer
112 *****************************************************************************/
113 static int Open( vlc_object_t *p_this )
115 filter_t *p_filter = (filter_t *)p_this;
116 filter_sys_t *p_sys = p_filter->p_sys = malloc(sizeof(*p_sys));
117 if (!p_sys)
118 return VLC_ENOMEM;
120 static const char *const options[] = {
121 "bargraph", "bargraph_repetition", "silence", "time_window",
122 "alarm_threshold", "repetition_time", NULL
124 config_ChainParse(p_filter, CFG_PREFIX, options, p_filter->p_cfg);
126 p_sys->bargraph = !!var_CreateGetInteger(p_filter, CFG_PREFIX "bargraph");
127 p_sys->bargraph_repetition = var_CreateGetInteger(p_filter, CFG_PREFIX "bargraph_repetition");
128 p_sys->silence = !!var_CreateGetInteger(p_filter, CFG_PREFIX "silence");
129 p_sys->time_window = var_CreateGetInteger(p_filter, CFG_PREFIX "time_window") * 1000;
130 p_sys->alarm_threshold = var_CreateGetFloat(p_filter, CFG_PREFIX "alarm_threshold");
131 p_sys->repetition_time = var_CreateGetInteger(p_filter, CFG_PREFIX "repetition_time") * 1000;
132 p_sys->counter = 0;
133 p_sys->first = NULL;
134 p_sys->last = NULL;
135 p_sys->started = 0;
136 p_sys->lastAlarm = 0;
138 p_filter->fmt_in.audio.i_format = VLC_CODEC_FL32;
139 aout_FormatPrepare(&p_filter->fmt_in.audio);
140 p_filter->fmt_out.audio = p_filter->fmt_in.audio;
141 p_filter->pf_audio_filter = DoWork;
143 var_Create(p_filter->obj.libvlc, "audiobargraph_v-alarm", VLC_VAR_BOOL);
144 var_Create(p_filter->obj.libvlc, "audiobargraph_v-i_values", VLC_VAR_STRING);
146 return VLC_SUCCESS;
149 static void SendValues(filter_t *p_filter, float *value, int nbChannels)
151 char msg[256];
152 size_t len = 0;
154 for (int i = 0; i < nbChannels; i++) {
155 if (len >= sizeof (msg))
156 break;
157 len += snprintf(msg + len, sizeof (msg) - len, "%f:", value[i]);
160 //msg_Dbg(p_filter, "values: %s", msg);
161 var_SetString(p_filter->obj.libvlc, "audiobargraph_v-i_values", msg);
164 /*****************************************************************************
165 * DoWork: treat an audio buffer
166 ****************************************************************************/
167 static block_t *DoWork( filter_t *p_filter, block_t *p_in_buf )
169 filter_sys_t *p_sys = p_filter->p_sys;
170 float *p_sample = (float *)p_in_buf->p_buffer;
171 float i_value[AOUT_CHAN_MAX];
173 int nbChannels = aout_FormatNbChannels(&p_filter->fmt_in.audio);
175 for (int i = 0; i < nbChannels; i++)
176 i_value[i] = 0.;
178 /* 1 - Compute the peak values */
179 for (size_t i = 0; i < p_in_buf->i_nb_samples; i++)
180 for (int j = 0; j<nbChannels; j++) {
181 float ch = *p_sample++;
182 if (ch > i_value[j])
183 i_value[j] = ch;
186 if (p_sys->silence) {
187 /* 2 - store the new value */
188 ValueDate_t *new = xmalloc(sizeof(*new));
189 new->value = 0.0;
190 for (int j = 0; j<nbChannels; j++) {
191 float ch = i_value[j];
192 if (ch > new->value)
193 new->value = ch;
195 new->value *= new->value;
196 new->date = p_in_buf->i_pts;
197 new->next = NULL;
198 if (p_sys->last != NULL)
199 p_sys->last->next = new;
200 p_sys->last = new;
201 if (p_sys->first == NULL)
202 p_sys->first = new;
204 /* 3 - delete too old values */
205 while (p_sys->first->date < new->date - p_sys->time_window) {
206 p_sys->started = 1; // we have enough values to compute a valid total
207 ValueDate_t *current = p_sys->first;
208 p_sys->first = p_sys->first->next;
209 free(current);
212 /* If last message was sent enough time ago */
213 if (p_sys->started && p_in_buf->i_pts > p_sys->lastAlarm + p_sys->repetition_time) {
215 /* 4 - compute the RMS */
216 ValueDate_t *current = p_sys->first;
217 float sum = 0.0;
218 int count = 0;
219 while (current != NULL) {
220 sum += current->value;
221 count++;
222 current = current->next;
224 sum /= count;
225 sum = sqrtf(sum);
227 /* 5 - compare it to the threshold */
228 var_SetBool(p_filter->obj.libvlc, "audiobargraph_v-alarm",
229 sum < p_sys->alarm_threshold);
231 p_sys->lastAlarm = p_in_buf->i_pts;
235 if (p_sys->bargraph && nbChannels > 0 && p_sys->counter++ > p_sys->bargraph_repetition) {
236 SendValues(p_filter, i_value, nbChannels);
237 p_sys->counter = 0;
240 return p_in_buf;
243 /*****************************************************************************
244 * Close: close the plugin
245 *****************************************************************************/
246 static void Close( vlc_object_t *p_this )
248 filter_t * p_filter = (filter_t *)p_this;
249 filter_sys_t *p_sys = p_filter->p_sys;
251 var_Destroy(p_filter->obj.libvlc, "audiobargraph_v-i_values");
252 var_Destroy(p_filter->obj.libvlc, "audiobargraph_v-alarm");
254 while (p_sys->first != NULL) {
255 ValueDate_t *current = p_sys->first;
256 p_sys->first = p_sys->first->next;
257 free(current);
259 free(p_sys);