qt: playlist: use item title if available
[vlc.git] / modules / audio_filter / audiobargraph_a.c
blob763ea2be20cfdd991195977a184d9eefe94abcc6
1 /*****************************************************************************
2 * audiobargraph_a.c : audiobargraph audio plugin for vlc
3 *****************************************************************************
4 * Copyright (C) 2002-2014 VLC authors and VideoLAN
6 * Authors: Clement CHESNIN <clement.chesnin@gmail.com>
7 * Philippe COENT <philippe.coent@tdf.fr>
9 * This program is free software; you can redistribute it and/or modify it
10 * under the terms of the GNU Lesser General Public License as published by
11 * the Free Software Foundation; either version 2.1 of the License, or
12 * (at your option) any later version.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU Lesser General Public License for more details.
19 * You should have received a copy of the GNU Lesser General Public License
20 * along with this program; if not, write to the Free Software Foundation,
21 * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
22 *****************************************************************************/
24 /*****************************************************************************
25 * Preamble
26 *****************************************************************************/
27 #ifdef HAVE_CONFIG_H
28 # include "config.h"
29 #endif
31 #include <vlc_common.h>
32 #include <vlc_plugin.h>
33 #include <vlc_aout.h>
34 #include <vlc_filter.h>
36 #include <math.h>
38 #define BARGRAPH_TEXT N_("Defines if BarGraph information should be sent")
39 #define BARGRAPH_LONGTEXT N_("Defines if BarGraph information should be sent. "\
40 "1 if the information should be sent, 0 otherwise (default 1)." )
41 #define BARGRAPH_REPETITION_TEXT N_("Sends the barGraph information every n audio packets")
42 #define BARGRAPH_REPETITION_LONGTEXT N_("Defines how often the barGraph information should be sent. "\
43 "Sends the barGraph information every n audio packets (default 4)." )
44 #define SILENCE_TEXT N_("Defines if silence alarm information should be sent")
45 #define SILENCE_LONGTEXT N_("Defines if silence alarm information should be sent. "\
46 "1 if the information should be sent, 0 otherwise (default 1)." )
47 #define TIME_WINDOW_TEXT N_("Time window to use in ms")
48 #define TIME_WINDOW_LONGTEXT N_("Time Window during when the audio level is measured in ms for silence detection. "\
49 "If the audio level is under the threshold during this time, "\
50 "an alarm is sent (default 5000)." )
51 #define ALARM_THRESHOLD_TEXT N_("Minimum Audio level to raise the alarm")
52 #define ALARM_THRESHOLD_LONGTEXT N_("Threshold to be attained to raise an alarm. "\
53 "If the audio level is under the threshold during this time, "\
54 "an alarm is sent (default 0.1)." )
55 #define REPETITION_TIME_TEXT N_("Time between two alarm messages in ms" )
56 #define REPETITION_TIME_LONGTEXT N_("Time between two alarm messages in ms. "\
57 "This value is used to avoid alarm saturation (default 2000)." )
59 #define CFG_PREFIX "audiobargraph_a-"
61 /*****************************************************************************
62 * Module descriptor
63 *****************************************************************************/
64 static int Open( vlc_object_t * );
65 static void Close( filter_t * );
66 static block_t *DoWork( filter_t *, block_t * );
68 vlc_module_begin ()
69 set_description( N_("Audio part of the BarGraph function") )
70 set_shortname( N_("Audiobar Graph") )
71 set_capability( "audio filter", 0 )
72 set_category( CAT_AUDIO )
73 set_subcategory( SUBCAT_AUDIO_AFILTER )
75 add_obsolete_string( CFG_PREFIX "address" )
76 add_obsolete_integer( CFG_PREFIX "port" )
77 add_integer( CFG_PREFIX "bargraph", 1, BARGRAPH_TEXT, BARGRAPH_LONGTEXT, false ) // FIXME: this is a bool
78 add_integer( CFG_PREFIX "bargraph_repetition", 4, BARGRAPH_REPETITION_TEXT, BARGRAPH_REPETITION_LONGTEXT, false )
79 add_integer( CFG_PREFIX "silence", 1, SILENCE_TEXT, SILENCE_LONGTEXT, false ) // FIXME: this is a bool
80 add_integer( CFG_PREFIX "time_window", 5000, TIME_WINDOW_TEXT, TIME_WINDOW_LONGTEXT, false )
81 add_float( CFG_PREFIX "alarm_threshold", 0.02, ALARM_THRESHOLD_TEXT, ALARM_THRESHOLD_LONGTEXT, false )
82 add_integer( CFG_PREFIX "repetition_time", 2000, REPETITION_TIME_TEXT, REPETITION_TIME_LONGTEXT, false )
83 add_obsolete_integer( CFG_PREFIX "connection_reset" )
85 set_callback( Open )
86 vlc_module_end ()
88 typedef struct ValueDate_t {
89 float value;
90 vlc_tick_t date;
91 struct ValueDate_t* next;
92 } ValueDate_t;
94 typedef struct
96 bool bargraph;
97 int bargraph_repetition;
98 bool silence;
99 vlc_tick_t time_window;
100 float alarm_threshold;
101 vlc_tick_t repetition_time;
102 int counter;
103 ValueDate_t* first;
104 ValueDate_t* last;
105 int started;
106 vlc_tick_t lastAlarm;
107 } filter_sys_t;
109 /*****************************************************************************
110 * Open: open the visualizer
111 *****************************************************************************/
112 static int Open( vlc_object_t *p_this )
114 filter_t *p_filter = (filter_t *)p_this;
115 filter_sys_t *p_sys = p_filter->p_sys = malloc(sizeof(*p_sys));
116 if (!p_sys)
117 return VLC_ENOMEM;
119 static const char *const options[] = {
120 "bargraph", "bargraph_repetition", "silence", "time_window",
121 "alarm_threshold", "repetition_time", NULL
123 config_ChainParse(p_filter, CFG_PREFIX, options, p_filter->p_cfg);
125 p_sys->bargraph = !!var_CreateGetInteger(p_filter, CFG_PREFIX "bargraph");
126 p_sys->bargraph_repetition = var_CreateGetInteger(p_filter, CFG_PREFIX "bargraph_repetition");
127 p_sys->silence = !!var_CreateGetInteger(p_filter, CFG_PREFIX "silence");
128 p_sys->time_window = VLC_TICK_FROM_MS( var_CreateGetInteger(p_filter, CFG_PREFIX "time_window") );
129 p_sys->alarm_threshold = var_CreateGetFloat(p_filter, CFG_PREFIX "alarm_threshold");
130 p_sys->repetition_time = VLC_TICK_FROM_MS( var_CreateGetInteger(p_filter, CFG_PREFIX "repetition_time") );
131 p_sys->counter = 0;
132 p_sys->first = NULL;
133 p_sys->last = NULL;
134 p_sys->started = 0;
135 p_sys->lastAlarm = 0;
137 p_filter->fmt_in.audio.i_format = VLC_CODEC_FL32;
138 aout_FormatPrepare(&p_filter->fmt_in.audio);
139 p_filter->fmt_out.audio = p_filter->fmt_in.audio;
141 static const struct vlc_filter_operations filter_ops =
143 .filter_audio = DoWork, .close = Close,
145 p_filter->ops = &filter_ops;
147 vlc_object_t *vlc = VLC_OBJECT(vlc_object_instance(p_filter));
149 var_Create(vlc, "audiobargraph_v-alarm", VLC_VAR_BOOL);
150 var_Create(vlc, "audiobargraph_v-i_values", VLC_VAR_STRING);
152 return VLC_SUCCESS;
155 static void SendValues(filter_t *p_filter, float *value, int nbChannels)
157 char msg[256];
158 size_t len = 0;
160 for (int i = 0; i < nbChannels; i++) {
161 if (len >= sizeof (msg))
162 break;
163 len += snprintf(msg + len, sizeof (msg) - len, "%f:", value[i]);
166 //msg_Dbg(p_filter, "values: %s", msg);
167 var_SetString(vlc_object_instance(p_filter), "audiobargraph_v-i_values",
168 msg);
171 /*****************************************************************************
172 * DoWork: treat an audio buffer
173 ****************************************************************************/
174 static block_t *DoWork( filter_t *p_filter, block_t *p_in_buf )
176 filter_sys_t *p_sys = p_filter->p_sys;
177 float *p_sample = (float *)p_in_buf->p_buffer;
178 float i_value[AOUT_CHAN_MAX];
180 int nbChannels = aout_FormatNbChannels(&p_filter->fmt_in.audio);
182 for (int i = 0; i < nbChannels; i++)
183 i_value[i] = 0.;
185 /* 1 - Compute the peak values */
186 for (size_t i = 0; i < p_in_buf->i_nb_samples; i++)
187 for (int j = 0; j<nbChannels; j++) {
188 float ch = *p_sample++;
189 if (ch > i_value[j])
190 i_value[j] = ch;
193 if (p_sys->silence) {
194 /* 2 - store the new value */
195 ValueDate_t *new = xmalloc(sizeof(*new));
196 new->value = 0.0;
197 for (int j = 0; j<nbChannels; j++) {
198 float ch = i_value[j];
199 if (ch > new->value)
200 new->value = ch;
202 new->value *= new->value;
203 new->date = p_in_buf->i_pts;
204 new->next = NULL;
205 if (p_sys->last != NULL)
206 p_sys->last->next = new;
207 p_sys->last = new;
208 if (p_sys->first == NULL)
209 p_sys->first = new;
211 /* 3 - delete too old values */
212 while (p_sys->first->date < new->date - p_sys->time_window) {
213 p_sys->started = 1; // we have enough values to compute a valid total
214 ValueDate_t *current = p_sys->first;
215 p_sys->first = p_sys->first->next;
216 free(current);
219 /* If last message was sent enough time ago */
220 if (p_sys->started && p_in_buf->i_pts > p_sys->lastAlarm + p_sys->repetition_time) {
222 /* 4 - compute the RMS */
223 ValueDate_t *current = p_sys->first;
224 float sum = 0.0;
225 int count = 0;
226 while (current != NULL) {
227 sum += current->value;
228 count++;
229 current = current->next;
231 sum /= count;
232 sum = sqrtf(sum);
234 /* 5 - compare it to the threshold */
235 var_SetBool(vlc_object_instance(p_filter), "audiobargraph_v-alarm",
236 sum < p_sys->alarm_threshold);
238 p_sys->lastAlarm = p_in_buf->i_pts;
242 if (p_sys->bargraph && nbChannels > 0 && p_sys->counter++ > p_sys->bargraph_repetition) {
243 SendValues(p_filter, i_value, nbChannels);
244 p_sys->counter = 0;
247 return p_in_buf;
250 /*****************************************************************************
251 * Close: close the plugin
252 *****************************************************************************/
253 static void Close( filter_t * p_filter )
255 filter_sys_t *p_sys = p_filter->p_sys;
256 vlc_object_t *vlc = VLC_OBJECT(vlc_object_instance(p_filter));
258 var_Destroy(vlc, "audiobargraph_v-i_values");
259 var_Destroy(vlc, "audiobargraph_v-alarm");
261 while (p_sys->first != NULL) {
262 ValueDate_t *current = p_sys->first;
263 p_sys->first = p_sys->first->next;
264 free(current);
266 free(p_sys);