c80679927c0f24d432344990cc53b12f9657d546
[platform/upstream/gstreamer.git] / ext / spandsp / gsttonegeneratesrc.c
1 /* GStreamer
2  * Copyright (C) 2016 Iskratel d.o.o.
3  *   Author: Okrslar Ales <okrslar@iskratel.si>
4  * Copyright (C) 2016 Sebastian Dröge <sebastian@centricular.com>
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Library General Public
8  * License as published by the Free Software Foundation; either
9  * version 2 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Library General Public License for more details.
15  *
16  * You should have received a copy of the GNU Library General Public
17  * License along with this library; if not, write to the
18  * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
19  * Boston, MA 02110-1301, USA.
20  */
21
22 #ifdef HAVE_CONFIG_H
23 #include "config.h"
24 #endif
25
26 #include "gsttonegeneratesrc.h"
27
28 #undef IT_DBG
29
30 GST_DEBUG_CATEGORY_STATIC (tone_generate_src_debug);
31 #define GST_CAT_DEFAULT tone_generate_src_debug
32
33 #define DEFAULT_SAMPLES_PER_BUFFER   1024
34 #define DEFAULT_FREQ                 0
35 #define DEFAULT_VOLUME               0
36 #define DEFAULT_ON_TIME              1000
37 #define DEFAULT_OFF_TIME             1000
38 #define DEFAULT_REPEAT               FALSE
39
40 enum
41 {
42   PROP_0,
43   PROP_SAMPLES_PER_BUFFER,
44   PROP_FREQ,
45   PROP_VOLUME,
46   PROP_FREQ2,
47   PROP_VOLUME2,
48   PROP_ON_TIME,
49   PROP_OFF_TIME,
50   PROP_ON_TIME2,
51   PROP_OFF_TIME2,
52   PROP_REPEAT,
53   PROP_LAST
54 };
55
56 static GstStaticPadTemplate gst_tone_generate_src_src_template =
57 GST_STATIC_PAD_TEMPLATE ("src",
58     GST_PAD_SRC,
59     GST_PAD_ALWAYS,
60     GST_STATIC_CAPS ("audio/x-raw, "
61         "format = (string) " GST_AUDIO_NE (S16) ", "
62         "layout = (string) interleaved, " "rate = (int) 8000, " "channels = 1")
63     );
64
65 #define gst_tone_generate_src_parent_class parent_class
66 G_DEFINE_TYPE (GstToneGenerateSrc, gst_tone_generate_src, GST_TYPE_PUSH_SRC);
67
68 static void gst_tone_generate_src_finalize (GObject * object);
69 static void gst_tone_generate_src_set_property (GObject * object, guint prop_id,
70     const GValue * value, GParamSpec * pspec);
71 static void gst_tone_generate_src_get_property (GObject * object, guint prop_id,
72     GValue * value, GParamSpec * pspec);
73 static gboolean gst_tone_generate_src_start (GstBaseSrc * basesrc);
74 static gboolean gst_tone_generate_src_stop (GstBaseSrc * basesrc);
75 static GstFlowReturn gst_tone_generate_src_fill (GstPushSrc * basesrc,
76     GstBuffer * buffer);
77
78 static void
79 gst_tone_generate_src_class_init (GstToneGenerateSrcClass * klass)
80 {
81   GObjectClass *gobject_class;
82   GstElementClass *gstelement_class;
83   GstBaseSrcClass *gstbasesrc_class;
84   GstPushSrcClass *gstpushsrc_class;
85
86   gobject_class = (GObjectClass *) klass;
87   gstelement_class = (GstElementClass *) klass;
88   gstbasesrc_class = (GstBaseSrcClass *) klass;
89   gstpushsrc_class = (GstPushSrcClass *) klass;
90
91   gobject_class->set_property = gst_tone_generate_src_set_property;
92   gobject_class->get_property = gst_tone_generate_src_get_property;
93   gobject_class->finalize = gst_tone_generate_src_finalize;
94
95   g_object_class_install_property (gobject_class, PROP_SAMPLES_PER_BUFFER,
96       g_param_spec_int ("samplesperbuffer", "Samples per buffer",
97           "Number of samples in each outgoing buffer",
98           1, G_MAXINT, DEFAULT_SAMPLES_PER_BUFFER,
99           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
100
101   g_object_class_install_property (gobject_class, PROP_FREQ,
102       g_param_spec_int ("freq", "Frequency", "Frequency of test signal",
103           0, 20000, DEFAULT_FREQ, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
104
105   g_object_class_install_property (gobject_class, PROP_VOLUME,
106       g_param_spec_int ("volume", "Volume",
107           "Volume of first signal",
108           -50, 0, DEFAULT_VOLUME, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
109
110   g_object_class_install_property (gobject_class, PROP_FREQ2,
111       g_param_spec_int ("freq2", "Second Frequency",
112           "Frequency of second telephony tone component",
113           0, 20000, DEFAULT_FREQ, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
114
115   g_object_class_install_property (gobject_class, PROP_VOLUME2,
116       g_param_spec_int ("volume2", "Volume2",
117           "Volume of second tone signal",
118           -50, 0, DEFAULT_VOLUME, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
119
120   g_object_class_install_property (gobject_class, PROP_ON_TIME,
121       g_param_spec_int ("on-time", "Signal ON time first period",
122           "Time of the first period  when the tone signal is present", 1,
123           G_MAXINT, DEFAULT_ON_TIME, G_PARAM_READWRITE));
124
125   g_object_class_install_property (gobject_class, PROP_OFF_TIME,
126       g_param_spec_int ("off-time", "Signal OFF time first period ",
127           "Time of the first period  when the tone signal is off", 0, G_MAXINT,
128           DEFAULT_OFF_TIME, G_PARAM_READWRITE));
129
130   g_object_class_install_property (gobject_class, PROP_ON_TIME2,
131       g_param_spec_int ("on-time2", "Signal ON time second period",
132           "Time of the second period  when the tone signal is present", 1,
133           G_MAXINT, DEFAULT_ON_TIME, G_PARAM_READWRITE));
134
135   g_object_class_install_property (gobject_class, PROP_OFF_TIME2,
136       g_param_spec_int ("off-time2", "Signal OFF time first period ",
137           "Time of the second period  when the tone signal is off", 0, G_MAXINT,
138           DEFAULT_ON_TIME, G_PARAM_READWRITE));
139
140   g_object_class_install_property (gobject_class, PROP_REPEAT,
141       g_param_spec_boolean ("repeat", "Repeat the specified tone period ",
142           "Whether to repeat specified tone indefinitly", DEFAULT_REPEAT,
143           G_PARAM_READWRITE));
144
145   gst_element_class_add_static_pad_template (gstelement_class,
146       &gst_tone_generate_src_src_template);
147
148   gst_element_class_set_static_metadata (gstelement_class,
149       "Telephony Tone  Generator source", "Source/Audio",
150       "Creates telephony signals of given frequency, volume, cadence",
151       "Iskratel <www.iskratel.com>");
152
153   gstbasesrc_class->start = GST_DEBUG_FUNCPTR (gst_tone_generate_src_start);
154   gstbasesrc_class->stop = GST_DEBUG_FUNCPTR (gst_tone_generate_src_stop);
155   gstpushsrc_class->fill = GST_DEBUG_FUNCPTR (gst_tone_generate_src_fill);
156 }
157
158 static void
159 gst_tone_generate_src_init (GstToneGenerateSrc * src)
160 {
161   src->volume = DEFAULT_VOLUME;
162   src->freq = DEFAULT_FREQ;
163   src->on_time = DEFAULT_ON_TIME;
164   src->off_time = DEFAULT_OFF_TIME;
165   src->volume2 = DEFAULT_VOLUME;
166   src->freq2 = DEFAULT_FREQ;
167   src->on_time2 = DEFAULT_ON_TIME;
168   src->off_time2 = DEFAULT_OFF_TIME;
169   src->repeat = DEFAULT_REPEAT;
170
171   gst_base_src_set_format (GST_BASE_SRC (src), GST_FORMAT_TIME);
172
173   src->samples_per_buffer = DEFAULT_SAMPLES_PER_BUFFER;
174   gst_base_src_set_blocksize (GST_BASE_SRC (src), 2 * src->samples_per_buffer);
175 }
176
177 static void
178 gst_tone_generate_src_finalize (GObject * object)
179 {
180   GstToneGenerateSrc *src = GST_TONE_GENERATE_SRC (object);
181
182   if (src->tone_desc) {
183     tone_gen_descriptor_free (src->tone_desc);
184     src->tone_desc = NULL;
185   }
186
187   if (src->tone_state) {
188     tone_gen_free (src->tone_state);
189     src->tone_state = NULL;
190   }
191
192   G_OBJECT_CLASS (parent_class)->finalize (object);
193 }
194
195 static gboolean
196 gst_tone_generate_src_start (GstBaseSrc * basesrc)
197 {
198   GstToneGenerateSrc *src = GST_TONE_GENERATE_SRC (basesrc);
199
200   GST_OBJECT_LOCK (src);
201   src->properties_changed = FALSE;
202   GST_OBJECT_UNLOCK (src);
203
204   src->next_sample = 0;
205   src->next_time = 0;
206
207   return TRUE;
208 }
209
210 static gboolean
211 gst_tone_generate_src_stop (GstBaseSrc * basesrc)
212 {
213   GstToneGenerateSrc *src = GST_TONE_GENERATE_SRC (basesrc);
214
215   GST_OBJECT_LOCK (src);
216   if (src->tone_desc) {
217     tone_gen_descriptor_free (src->tone_desc);
218     src->tone_desc = NULL;
219   }
220
221   if (src->tone_state) {
222     tone_gen_free (src->tone_state);
223     src->tone_state = NULL;
224   }
225   src->properties_changed = FALSE;
226   GST_OBJECT_UNLOCK (src);
227
228   return TRUE;
229 }
230
231 static GstFlowReturn
232 gst_tone_generate_src_fill (GstPushSrc * basesrc, GstBuffer * buffer)
233 {
234   GstToneGenerateSrc *src;
235   GstClockTime next_time;
236   gint64 next_sample;
237   gint bytes, samples;
238   GstMapInfo map;
239   const gint samplerate = 8000, bpf = 2;
240
241   src = GST_TONE_GENERATE_SRC (basesrc);
242
243   bytes = gst_buffer_get_size (buffer);
244   samples = bytes / bpf;
245
246   /* calculate full buffer */
247   next_sample = src->next_sample + samples;
248
249   next_time = gst_util_uint64_scale_int (next_sample, GST_SECOND, samplerate);
250
251   GST_LOG_OBJECT (src, "samplerate %d", samplerate);
252   GST_LOG_OBJECT (src, "next_sample %" G_GINT64_FORMAT ", ts %" GST_TIME_FORMAT,
253       next_sample, GST_TIME_ARGS (next_time));
254
255   GST_BUFFER_OFFSET (buffer) = src->next_sample;
256   GST_BUFFER_OFFSET_END (buffer) = next_sample;
257   GST_BUFFER_TIMESTAMP (buffer) = src->next_time;
258   GST_BUFFER_DURATION (buffer) = next_time - src->next_time;
259
260   gst_object_sync_values (GST_OBJECT (src), GST_BUFFER_TIMESTAMP (buffer));
261
262   src->next_time = next_time;
263   src->next_sample = next_sample;
264
265   GST_LOG_OBJECT (src, "generating %u samples at ts %" GST_TIME_FORMAT,
266       samples, GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buffer)));
267
268   gst_buffer_map (buffer, &map, GST_MAP_WRITE);
269
270   GST_OBJECT_LOCK (src);
271   if (!src->tone_state || src->properties_changed) {
272     src->tone_desc = tone_gen_descriptor_init (src->tone_desc,
273         src->freq,
274         src->volume,
275         src->freq2,
276         src->volume2,
277         src->on_time,
278         src->off_time, src->on_time2, src->off_time2, src->repeat);
279
280     src->tone_state = tone_gen_init (src->tone_state, src->tone_desc);
281     src->properties_changed = FALSE;
282   }
283
284   tone_gen (src->tone_state, (int16_t *) map.data, samples);
285   GST_OBJECT_UNLOCK (src);
286
287   gst_buffer_unmap (buffer, &map);
288
289   return GST_FLOW_OK;
290 }
291
292 static void
293 gst_tone_generate_src_set_property (GObject * object, guint prop_id,
294     const GValue * value, GParamSpec * pspec)
295 {
296   GstToneGenerateSrc *src = GST_TONE_GENERATE_SRC (object);
297
298   switch (prop_id) {
299     case PROP_SAMPLES_PER_BUFFER:
300       src->samples_per_buffer = g_value_get_int (value);
301       gst_base_src_set_blocksize (GST_BASE_SRC_CAST (src),
302           2 * src->samples_per_buffer);
303       break;
304     case PROP_FREQ:
305       GST_OBJECT_LOCK (src);
306       src->freq = g_value_get_int (value);
307       src->properties_changed = TRUE;
308       GST_OBJECT_UNLOCK (src);
309       break;
310     case PROP_VOLUME:
311       GST_OBJECT_LOCK (src);
312       src->volume = g_value_get_int (value);
313       src->properties_changed = TRUE;
314       GST_OBJECT_UNLOCK (src);
315       break;
316     case PROP_FREQ2:
317       GST_OBJECT_LOCK (src);
318       src->freq2 = g_value_get_int (value);
319       src->properties_changed = TRUE;
320       GST_OBJECT_UNLOCK (src);
321       break;
322     case PROP_VOLUME2:
323       GST_OBJECT_LOCK (src);
324       src->volume2 = g_value_get_int (value);
325       src->properties_changed = TRUE;
326       GST_OBJECT_UNLOCK (src);
327       break;
328     case PROP_ON_TIME:
329       GST_OBJECT_LOCK (src);
330       src->on_time = g_value_get_int (value);
331       src->properties_changed = TRUE;
332       GST_OBJECT_UNLOCK (src);
333       break;
334     case PROP_ON_TIME2:
335       GST_OBJECT_LOCK (src);
336       src->on_time2 = g_value_get_int (value);
337       src->properties_changed = TRUE;
338       GST_OBJECT_UNLOCK (src);
339       break;
340     case PROP_OFF_TIME:
341       GST_OBJECT_LOCK (src);
342       src->off_time = g_value_get_int (value);
343       src->properties_changed = TRUE;
344       GST_OBJECT_UNLOCK (src);
345       break;
346     case PROP_OFF_TIME2:
347       GST_OBJECT_LOCK (src);
348       src->off_time2 = g_value_get_int (value);
349       src->properties_changed = TRUE;
350       GST_OBJECT_UNLOCK (src);
351       break;
352     case PROP_REPEAT:
353       GST_OBJECT_LOCK (src);
354       src->repeat = g_value_get_boolean (value);
355       src->properties_changed = TRUE;
356       GST_OBJECT_UNLOCK (src);
357       break;
358     default:
359       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
360       break;
361   }
362 }
363
364 static void
365 gst_tone_generate_src_get_property (GObject * object, guint prop_id,
366     GValue * value, GParamSpec * pspec)
367 {
368   GstToneGenerateSrc *src = GST_TONE_GENERATE_SRC (object);
369
370   switch (prop_id) {
371     case PROP_SAMPLES_PER_BUFFER:
372       g_value_set_int (value, src->samples_per_buffer);
373       break;
374     case PROP_FREQ:
375       g_value_set_int (value, src->freq);
376       break;
377     case PROP_VOLUME:
378       g_value_set_int (value, src->volume);
379       break;
380     case PROP_FREQ2:
381       g_value_set_int (value, src->freq2);
382       break;
383     case PROP_VOLUME2:
384       g_value_set_int (value, src->volume2);
385       break;
386     case PROP_ON_TIME:
387       g_value_set_int (value, src->on_time);
388       break;
389     case PROP_OFF_TIME:
390       g_value_set_int (value, src->off_time);
391       break;
392     case PROP_ON_TIME2:
393       g_value_set_int (value, src->on_time2);
394       break;
395     case PROP_OFF_TIME2:
396       g_value_set_int (value, src->off_time2);
397       break;
398     case PROP_REPEAT:
399       g_value_set_boolean (value, src->repeat);
400       break;
401     default:
402       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
403       break;
404   }
405 }
406
407 gboolean
408 gst_tone_generate_src_plugin_init (GstPlugin * plugin)
409 {
410   GST_DEBUG_CATEGORY_INIT (tone_generate_src_debug, "tonegeneratesrc", 0,
411       "Telephony Tone Test Source");
412
413   return gst_element_register (plugin, "tonegeneratesrc",
414       GST_RANK_NONE, GST_TYPE_TONE_GENERATE_SRC);
415 }