1 /* Derived code of GStreamer - AudioTestSrc element
2 * Copyright (C) 2005 Stefan Kost <ensonic@users.sf.net>
3 * Copyright (C) 2008 Josep Torra <j.torra@telefonica.net>
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Library General Public
7 * License as published by the Free Software Foundation; either
8 * version 2 of the License, or (at your option) any later version.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Library General Public License for more details.
15 * You should have received a copy of the GNU Library General Public
16 * License along with this library; if not, write to the
17 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 * Boston, MA 02111-1307, USA.
28 #include <gst/controller/gstcontroller.h>
30 #include "gsttonesrc.h"
33 #define M_PI 3.14159265358979323846
37 #define M_PI_2 1.57079632679489661923
40 #define M_PI_M2 ( M_PI + M_PI )
42 GST_DEBUG_CATEGORY_STATIC (tone_src_debug);
43 #define GST_CAT_DEFAULT tone_src_debug
45 static const GstElementDetails gst_tone_src_details =
46 GST_ELEMENT_DETAILS ("Tone source",
48 "Creates audio test signals of given frequency and volume",
49 "Stefan Kost <ensonic@users.sf.net>");
55 PROP_SAMPLES_PER_BUFFER,
61 static GstStaticPadTemplate gst_tone_src_src_template =
62 GST_STATIC_PAD_TEMPLATE ("src",
65 GST_STATIC_CAPS ("audio/x-raw-int, "
66 "endianness = (int) BYTE_ORDER, "
67 "signed = (boolean) true, "
70 "rate = (int) [ 1, MAX ], "
71 "channels = (int) 1; "
73 "endianness = (int) BYTE_ORDER, "
74 "signed = (boolean) true, "
77 "rate = (int) [ 1, MAX ], "
78 "channels = (int) 1; "
80 "endianness = (int) BYTE_ORDER, "
81 "width = (int) { 32, 64 }, "
82 "rate = (int) [ 1, MAX ], " "channels = (int) 1")
86 GST_BOILERPLATE (GstToneSrc, gst_tone_src, GstBaseSrc, GST_TYPE_BASE_SRC);
88 static void gst_tone_src_set_property (GObject * object,
89 guint prop_id, const GValue * value, GParamSpec * pspec);
90 static void gst_tone_src_get_property (GObject * object,
91 guint prop_id, GValue * value, GParamSpec * pspec);
93 static gboolean gst_tone_src_setcaps (GstBaseSrc * basesrc, GstCaps * caps);
94 static void gst_tone_src_src_fixate (GstPad * pad, GstCaps * caps);
96 static GstFlowReturn gst_tone_src_create (GstBaseSrc * basesrc,
97 guint64 offset, guint length, GstBuffer ** buffer);
99 #define DEFINE_OSCILATOR(type,scale) \
101 gst_tone_src_create_oscilator_##type (GstToneSrc * src, g##type * samples) \
106 step = M_PI_M2 * src->freq / src->samplerate; \
107 amp = src->volume * scale; \
109 for (i = 0; i < src->generate_samples_per_buffer; i++) { \
110 src->accumulator += step; \
111 if (src->accumulator >= M_PI_M2) \
112 src->accumulator -= M_PI_M2; \
114 samples[i] = (g##type) (sin (src->accumulator) * amp); \
118 DEFINE_OSCILATOR (int16, 32767.0);
119 DEFINE_OSCILATOR (int32, 2147483647.0);
120 DEFINE_OSCILATOR (float, 1.0);
121 DEFINE_OSCILATOR (double, 1.0);
123 static ProcessFunc oscilator_funcs[] = {
124 (ProcessFunc) gst_tone_src_create_oscilator_int16,
125 (ProcessFunc) gst_tone_src_create_oscilator_int32,
126 (ProcessFunc) gst_tone_src_create_oscilator_float,
127 (ProcessFunc) gst_tone_src_create_oscilator_double
131 gst_tone_src_base_init (gpointer g_class)
133 GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
135 gst_element_class_add_pad_template (element_class,
136 gst_static_pad_template_get (&gst_tone_src_src_template));
137 gst_element_class_set_details (element_class, &gst_tone_src_details);
141 gst_tone_src_class_init (GstToneSrcClass * klass)
143 GObjectClass *gobject_class;
144 GstBaseSrcClass *gstbasesrc_class;
146 gobject_class = (GObjectClass *) klass;
147 gstbasesrc_class = (GstBaseSrcClass *) klass;
149 gobject_class->set_property = gst_tone_src_set_property;
150 gobject_class->get_property = gst_tone_src_get_property;
152 g_object_class_install_property (gobject_class, PROP_SAMPLES_PER_BUFFER,
153 g_param_spec_int ("samplesperbuffer", "Samples per buffer",
154 "Number of samples in each outgoing buffer",
155 1, G_MAXINT, 1024, G_PARAM_READWRITE));
156 g_object_class_install_property (gobject_class, PROP_FREQ,
157 g_param_spec_double ("freq", "Frequency", "Frequency of test signal",
158 0.0, 20000.0, 440.0, G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE));
159 g_object_class_install_property (gobject_class, PROP_VOLUME,
160 g_param_spec_double ("volume", "Volume", "Volume of test signal", 0.0,
161 1.0, 0.8, G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE));
163 gstbasesrc_class->set_caps = GST_DEBUG_FUNCPTR (gst_tone_src_setcaps);
164 gstbasesrc_class->create = GST_DEBUG_FUNCPTR (gst_tone_src_create);
168 gst_tone_src_init (GstToneSrc * src, GstToneSrcClass * g_class)
170 GstPad *pad = GST_BASE_SRC_PAD (src);
172 gst_pad_set_fixatecaps_function (pad, gst_tone_src_src_fixate);
174 src->samplerate = 44100;
175 src->format = GST_TONE_SRC_FORMAT_NONE;
179 /* we operate in time */
180 gst_base_src_set_format (GST_BASE_SRC (src), GST_FORMAT_TIME);
181 gst_base_src_set_live (GST_BASE_SRC (src), FALSE);
183 src->samples_per_buffer = 1024;
184 src->generate_samples_per_buffer = src->samples_per_buffer;
188 gst_tone_src_src_fixate (GstPad * pad, GstCaps * caps)
190 GstToneSrc *src = GST_TONE_SRC (GST_PAD_PARENT (pad));
192 GstStructure *structure;
194 structure = gst_caps_get_structure (caps, 0);
196 gst_structure_fixate_field_nearest_int (structure, "rate", src->samplerate);
198 name = gst_structure_get_name (structure);
199 if (strcmp (name, "audio/x-raw-int") == 0)
200 gst_structure_fixate_field_nearest_int (structure, "width", 32);
201 else if (strcmp (name, "audio/x-raw-float") == 0)
202 gst_structure_fixate_field_nearest_int (structure, "width", 64);
206 gst_tone_src_setcaps (GstBaseSrc * basesrc, GstCaps * caps)
208 GstToneSrc *src = GST_TONE_SRC (basesrc);
209 const GstStructure *structure;
214 structure = gst_caps_get_structure (caps, 0);
215 ret = gst_structure_get_int (structure, "rate", &src->samplerate);
217 name = gst_structure_get_name (structure);
218 if (strcmp (name, "audio/x-raw-int") == 0) {
219 ret &= gst_structure_get_int (structure, "width", &width);
220 src->format = (width == 32) ? GST_TONE_SRC_FORMAT_S32 :
221 GST_TONE_SRC_FORMAT_S16;
223 ret &= gst_structure_get_int (structure, "width", &width);
224 src->format = (width == 32) ? GST_TONE_SRC_FORMAT_F32 :
225 GST_TONE_SRC_FORMAT_F64;
228 src->process = oscilator_funcs[src->format];
236 gst_tone_src_create (GstBaseSrc * basesrc, guint64 offset,
237 guint length, GstBuffer ** buffer)
242 GstClockTime next_time;
246 src = GST_TONE_SRC (basesrc);
248 /* allocate a new buffer suitable for this pad */
249 switch (src->format) {
250 case GST_TONE_SRC_FORMAT_S16:
251 sample_size = sizeof (gint16);
253 case GST_TONE_SRC_FORMAT_S32:
254 sample_size = sizeof (gint32);
256 case GST_TONE_SRC_FORMAT_F32:
257 sample_size = sizeof (gfloat);
259 case GST_TONE_SRC_FORMAT_F64:
260 sample_size = sizeof (gdouble);
264 GST_ELEMENT_ERROR (src, CORE, NEGOTIATION, (NULL),
265 ("format wasn't negotiated before get function"));
266 return GST_FLOW_NOT_NEGOTIATED;
270 n_samples = src->n_samples + src->samples_per_buffer;
271 next_time = gst_util_uint64_scale (n_samples, GST_SECOND,
272 (guint64) src->samplerate);
274 if ((res = gst_pad_alloc_buffer (basesrc->srcpad, src->n_samples,
275 src->generate_samples_per_buffer * sample_size,
276 GST_PAD_CAPS (basesrc->srcpad), &buf)) != GST_FLOW_OK) {
280 GST_BUFFER_TIMESTAMP (buf) = src->timestamp_offset + src->running_time;
281 GST_BUFFER_OFFSET_END (buf) = n_samples;
282 GST_BUFFER_DURATION (buf) = next_time - src->running_time;
284 gst_object_sync_values (G_OBJECT (src), src->running_time);
286 src->running_time = next_time;
287 src->n_samples = n_samples;
289 GST_LOG_OBJECT (src, "generating %u samples at ts %" GST_TIME_FORMAT,
290 length, GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buf)));
292 src->process (src, GST_BUFFER_DATA (buf));
294 if (G_UNLIKELY ((src->volume == 0.0))) {
295 GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_GAP);
304 gst_tone_src_set_property (GObject * object, guint prop_id,
305 const GValue * value, GParamSpec * pspec)
307 GstToneSrc *src = GST_TONE_SRC (object);
310 case PROP_SAMPLES_PER_BUFFER:
311 src->samples_per_buffer = g_value_get_int (value);
314 src->freq = g_value_get_double (value);
317 src->volume = g_value_get_double (value);
320 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
326 gst_tone_src_get_property (GObject * object, guint prop_id,
327 GValue * value, GParamSpec * pspec)
329 GstToneSrc *src = GST_TONE_SRC (object);
332 case PROP_SAMPLES_PER_BUFFER:
333 g_value_set_int (value, src->samples_per_buffer);
336 g_value_set_double (value, src->freq);
339 g_value_set_double (value, src->volume);
342 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
348 plugin_tonesrc_init (GstPlugin * plugin)
350 /* initialize gst controller library */
351 gst_controller_init (NULL, NULL);
353 GST_DEBUG_CATEGORY_INIT (tone_src_debug, "tonesrc", 0, "Audio Test Source");
355 return gst_element_register (plugin, "tonesrc",
356 GST_RANK_NONE, GST_TYPE_TONE_SRC);
360 GST_PLUGIN_DEFINE (GST_VERSION_MAJOR,
363 "Creates audio test signals of given frequency and volume",
364 plugin_init, VERSION, "LGPL", NULL, NULL);