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 /*****************************************************************************
26 *****************************************************************************/
31 #include <vlc_common.h>
32 #include <vlc_plugin.h>
34 #include <vlc_filter.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 /*****************************************************************************
63 *****************************************************************************/
64 static int Open( vlc_object_t
* );
65 static void Close( filter_t
* );
66 static block_t
*DoWork( filter_t
*, block_t
* );
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" )
88 typedef struct ValueDate_t
{
91 struct ValueDate_t
* next
;
97 int bargraph_repetition
;
99 vlc_tick_t time_window
;
100 float alarm_threshold
;
101 vlc_tick_t repetition_time
;
106 vlc_tick_t lastAlarm
;
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
));
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") );
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
);
155 static void SendValues(filter_t
*p_filter
, float *value
, int nbChannels
)
160 for (int i
= 0; i
< nbChannels
; i
++) {
161 if (len
>= sizeof (msg
))
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",
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
++)
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
++;
193 if (p_sys
->silence
) {
194 /* 2 - store the new value */
195 ValueDate_t
*new = xmalloc(sizeof(*new));
197 for (int j
= 0; j
<nbChannels
; j
++) {
198 float ch
= i_value
[j
];
202 new->value
*= new->value
;
203 new->date
= p_in_buf
->i_pts
;
205 if (p_sys
->last
!= NULL
)
206 p_sys
->last
->next
= new;
208 if (p_sys
->first
== NULL
)
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
;
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
;
226 while (current
!= NULL
) {
227 sum
+= current
->value
;
229 current
= current
->next
;
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
);
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
;