2 * Copyright (C) 2005 Stefan Kost <ensonic@users.sf.net>
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Library General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Library General Public License for more details.
14 * You should have received a copy of the GNU Library General Public
15 * License along with this library; if not, write to the
16 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17 * Boston, MA 02111-1307, USA.
20 * SECTION:element-audiotestsrc
22 * AudioTestSrc can be used to generate basic audio signals. It support several
23 * different waveforms and allows to set the base frequency and volume.
26 * <title>Example launch line</title>
28 * gst-launch audiotestsrc ! audioconvert ! alsasink
29 * ]| This pipeline produces a sine with default frequency, 440 Hz, and the
30 * default volume, 0.8 (relative to a maximum 1.0).
32 * gst-launch audiotestsrc wave=2 freq=200 ! audioconvert ! tee name=t ! queue ! alsasink t. ! queue ! libvisual_lv_scope ! ffmpegcolorspace ! xvimagesink
33 * ]| In this example a saw wave is generated. The wave is shown using a
34 * scope visualizer from libvisual, allowing you to visually verify that
35 * the saw wave is correct.
46 #include <gst/controller/gstcontroller.h>
48 #include "gstaudiotestsrc.h"
52 #define M_PI 3.14159265358979323846
56 #define M_PI_2 1.57079632679489661923
59 #define M_PI_M2 ( M_PI + M_PI )
61 GST_DEBUG_CATEGORY_STATIC (audio_test_src_debug);
62 #define GST_CAT_DEFAULT audio_test_src_debug
64 #define DEFAULT_SAMPLES_PER_BUFFER 1024
65 #define DEFAULT_WAVE GST_AUDIO_TEST_SRC_WAVE_SINE
66 #define DEFAULT_FREQ 440.0
67 #define DEFAULT_VOLUME 0.8
68 #define DEFAULT_IS_LIVE FALSE
69 #define DEFAULT_TIMESTAMP_OFFSET G_GINT64_CONSTANT (0)
70 #define DEFAULT_CAN_ACTIVATE_PUSH TRUE
71 #define DEFAULT_CAN_ACTIVATE_PULL FALSE
76 PROP_SAMPLES_PER_BUFFER,
81 PROP_TIMESTAMP_OFFSET,
82 PROP_CAN_ACTIVATE_PUSH,
83 PROP_CAN_ACTIVATE_PULL,
88 static GstStaticPadTemplate gst_audio_test_src_src_template =
89 GST_STATIC_PAD_TEMPLATE ("src",
92 GST_STATIC_CAPS ("audio/x-raw-int, "
93 "endianness = (int) BYTE_ORDER, "
94 "signed = (boolean) true, "
97 "rate = (int) [ 1, MAX ], "
98 "channels = (int) [ 1, 2 ]; "
100 "endianness = (int) BYTE_ORDER, "
101 "signed = (boolean) true, "
104 "rate = (int) [ 1, MAX ], "
105 "channels = (int) [ 1, 2 ]; "
106 "audio/x-raw-float, "
107 "endianness = (int) BYTE_ORDER, "
108 "width = (int) { 32, 64 }, "
109 "rate = (int) [ 1, MAX ], " "channels = (int) [ 1, 2 ]")
113 GST_BOILERPLATE (GstAudioTestSrc, gst_audio_test_src, GstBaseSrc,
116 #define GST_TYPE_AUDIO_TEST_SRC_WAVE (gst_audiostestsrc_wave_get_type())
118 gst_audiostestsrc_wave_get_type (void)
120 static GType audiostestsrc_wave_type = 0;
121 static const GEnumValue audiostestsrc_waves[] = {
122 {GST_AUDIO_TEST_SRC_WAVE_SINE, "Sine", "sine"},
123 {GST_AUDIO_TEST_SRC_WAVE_SQUARE, "Square", "square"},
124 {GST_AUDIO_TEST_SRC_WAVE_SAW, "Saw", "saw"},
125 {GST_AUDIO_TEST_SRC_WAVE_TRIANGLE, "Triangle", "triangle"},
126 {GST_AUDIO_TEST_SRC_WAVE_SILENCE, "Silence", "silence"},
127 {GST_AUDIO_TEST_SRC_WAVE_WHITE_NOISE, "White uniform noise", "white-noise"},
128 {GST_AUDIO_TEST_SRC_WAVE_PINK_NOISE, "Pink noise", "pink-noise"},
129 {GST_AUDIO_TEST_SRC_WAVE_SINE_TAB, "Sine table", "sine-table"},
130 {GST_AUDIO_TEST_SRC_WAVE_TICKS, "Periodic Ticks", "ticks"},
131 {GST_AUDIO_TEST_SRC_WAVE_GAUSSIAN_WHITE_NOISE, "White Gaussian noise",
136 if (G_UNLIKELY (audiostestsrc_wave_type == 0)) {
137 audiostestsrc_wave_type = g_enum_register_static ("GstAudioTestSrcWave",
138 audiostestsrc_waves);
140 return audiostestsrc_wave_type;
143 static void gst_audio_test_src_finalize (GObject * object);
145 static void gst_audio_test_src_set_property (GObject * object,
146 guint prop_id, const GValue * value, GParamSpec * pspec);
147 static void gst_audio_test_src_get_property (GObject * object,
148 guint prop_id, GValue * value, GParamSpec * pspec);
150 static gboolean gst_audio_test_src_setcaps (GstBaseSrc * basesrc,
152 static void gst_audio_test_src_src_fixate (GstPad * pad, GstCaps * caps);
154 static gboolean gst_audio_test_src_is_seekable (GstBaseSrc * basesrc);
155 static gboolean gst_audio_test_src_check_get_range (GstBaseSrc * basesrc);
156 static gboolean gst_audio_test_src_do_seek (GstBaseSrc * basesrc,
157 GstSegment * segment);
158 static gboolean gst_audio_test_src_query (GstBaseSrc * basesrc,
161 static void gst_audio_test_src_change_wave (GstAudioTestSrc * src);
163 static void gst_audio_test_src_get_times (GstBaseSrc * basesrc,
164 GstBuffer * buffer, GstClockTime * start, GstClockTime * end);
165 static gboolean gst_audio_test_src_start (GstBaseSrc * basesrc);
166 static gboolean gst_audio_test_src_stop (GstBaseSrc * basesrc);
167 static GstFlowReturn gst_audio_test_src_create (GstBaseSrc * basesrc,
168 guint64 offset, guint length, GstBuffer ** buffer);
172 gst_audio_test_src_base_init (gpointer g_class)
174 GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
176 gst_element_class_add_pad_template (element_class,
177 gst_static_pad_template_get (&gst_audio_test_src_src_template));
178 gst_element_class_set_details_simple (element_class,
179 "Audio test source", "Source/Audio",
180 "Creates audio test signals of given frequency and volume",
181 "Stefan Kost <ensonic@users.sf.net>");
185 gst_audio_test_src_class_init (GstAudioTestSrcClass * klass)
187 GObjectClass *gobject_class;
188 GstBaseSrcClass *gstbasesrc_class;
190 gobject_class = (GObjectClass *) klass;
191 gstbasesrc_class = (GstBaseSrcClass *) klass;
193 gobject_class->set_property = gst_audio_test_src_set_property;
194 gobject_class->get_property = gst_audio_test_src_get_property;
195 gobject_class->finalize = gst_audio_test_src_finalize;
197 g_object_class_install_property (gobject_class, PROP_SAMPLES_PER_BUFFER,
198 g_param_spec_int ("samplesperbuffer", "Samples per buffer",
199 "Number of samples in each outgoing buffer",
200 1, G_MAXINT, DEFAULT_SAMPLES_PER_BUFFER,
201 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
202 g_object_class_install_property (gobject_class, PROP_WAVE,
203 g_param_spec_enum ("wave", "Waveform", "Oscillator waveform",
204 GST_TYPE_AUDIO_TEST_SRC_WAVE, GST_AUDIO_TEST_SRC_WAVE_SINE,
205 G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE | G_PARAM_STATIC_STRINGS));
206 g_object_class_install_property (gobject_class, PROP_FREQ,
207 g_param_spec_double ("freq", "Frequency", "Frequency of test signal",
208 0.0, 20000.0, DEFAULT_FREQ,
209 G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE | G_PARAM_STATIC_STRINGS));
210 g_object_class_install_property (gobject_class, PROP_VOLUME,
211 g_param_spec_double ("volume", "Volume", "Volume of test signal", 0.0,
213 G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE | G_PARAM_STATIC_STRINGS));
214 g_object_class_install_property (gobject_class, PROP_IS_LIVE,
215 g_param_spec_boolean ("is-live", "Is Live",
216 "Whether to act as a live source", DEFAULT_IS_LIVE,
217 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
218 g_object_class_install_property (G_OBJECT_CLASS (klass),
219 PROP_TIMESTAMP_OFFSET, g_param_spec_int64 ("timestamp-offset",
221 "An offset added to timestamps set on buffers (in ns)", G_MININT64,
222 G_MAXINT64, DEFAULT_TIMESTAMP_OFFSET,
223 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
224 g_object_class_install_property (gobject_class, PROP_CAN_ACTIVATE_PUSH,
225 g_param_spec_boolean ("can-activate-push", "Can activate push",
226 "Can activate in push mode", DEFAULT_CAN_ACTIVATE_PUSH,
227 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
228 g_object_class_install_property (gobject_class, PROP_CAN_ACTIVATE_PULL,
229 g_param_spec_boolean ("can-activate-pull", "Can activate pull",
230 "Can activate in pull mode", DEFAULT_CAN_ACTIVATE_PULL,
231 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
233 gstbasesrc_class->set_caps = GST_DEBUG_FUNCPTR (gst_audio_test_src_setcaps);
234 gstbasesrc_class->is_seekable =
235 GST_DEBUG_FUNCPTR (gst_audio_test_src_is_seekable);
236 gstbasesrc_class->check_get_range =
237 GST_DEBUG_FUNCPTR (gst_audio_test_src_check_get_range);
238 gstbasesrc_class->do_seek = GST_DEBUG_FUNCPTR (gst_audio_test_src_do_seek);
239 gstbasesrc_class->query = GST_DEBUG_FUNCPTR (gst_audio_test_src_query);
240 gstbasesrc_class->get_times =
241 GST_DEBUG_FUNCPTR (gst_audio_test_src_get_times);
242 gstbasesrc_class->start = GST_DEBUG_FUNCPTR (gst_audio_test_src_start);
243 gstbasesrc_class->stop = GST_DEBUG_FUNCPTR (gst_audio_test_src_stop);
244 gstbasesrc_class->create = GST_DEBUG_FUNCPTR (gst_audio_test_src_create);
248 gst_audio_test_src_init (GstAudioTestSrc * src, GstAudioTestSrcClass * g_class)
250 GstPad *pad = GST_BASE_SRC_PAD (src);
252 gst_pad_set_fixatecaps_function (pad, gst_audio_test_src_src_fixate);
254 src->samplerate = 44100;
255 src->format = GST_AUDIO_TEST_SRC_FORMAT_NONE;
257 src->volume = DEFAULT_VOLUME;
258 src->freq = DEFAULT_FREQ;
260 /* we operate in time */
261 gst_base_src_set_format (GST_BASE_SRC (src), GST_FORMAT_TIME);
262 gst_base_src_set_live (GST_BASE_SRC (src), DEFAULT_IS_LIVE);
264 src->samples_per_buffer = DEFAULT_SAMPLES_PER_BUFFER;
265 src->generate_samples_per_buffer = src->samples_per_buffer;
266 src->timestamp_offset = DEFAULT_TIMESTAMP_OFFSET;
267 src->can_activate_pull = DEFAULT_CAN_ACTIVATE_PULL;
271 src->wave = DEFAULT_WAVE;
272 gst_base_src_set_blocksize (GST_BASE_SRC (src), -1);
276 gst_audio_test_src_finalize (GObject * object)
278 GstAudioTestSrc *src = GST_AUDIO_TEST_SRC (object);
281 g_rand_free (src->gen);
284 G_OBJECT_CLASS (parent_class)->finalize (object);
288 gst_audio_test_src_src_fixate (GstPad * pad, GstCaps * caps)
290 GstAudioTestSrc *src = GST_AUDIO_TEST_SRC (GST_PAD_PARENT (pad));
292 GstStructure *structure;
294 structure = gst_caps_get_structure (caps, 0);
296 GST_DEBUG_OBJECT (src, "fixating samplerate to %d", src->samplerate);
298 gst_structure_fixate_field_nearest_int (structure, "rate", src->samplerate);
300 name = gst_structure_get_name (structure);
301 if (strcmp (name, "audio/x-raw-int") == 0)
302 gst_structure_fixate_field_nearest_int (structure, "width", 32);
303 else if (strcmp (name, "audio/x-raw-float") == 0)
304 gst_structure_fixate_field_nearest_int (structure, "width", 64);
306 /* fixate to mono unless downstream requires stereo, for backwards compat */
307 gst_structure_fixate_field_nearest_int (structure, "channels", 1);
311 gst_audio_test_src_setcaps (GstBaseSrc * basesrc, GstCaps * caps)
313 GstAudioTestSrc *src = GST_AUDIO_TEST_SRC (basesrc);
314 const GstStructure *structure;
319 structure = gst_caps_get_structure (caps, 0);
320 ret = gst_structure_get_int (structure, "rate", &src->samplerate);
322 GST_DEBUG_OBJECT (src, "negotiated to samplerate %d", src->samplerate);
324 name = gst_structure_get_name (structure);
325 if (strcmp (name, "audio/x-raw-int") == 0) {
326 ret &= gst_structure_get_int (structure, "width", &width);
327 src->format = (width == 32) ? GST_AUDIO_TEST_SRC_FORMAT_S32 :
328 GST_AUDIO_TEST_SRC_FORMAT_S16;
330 ret &= gst_structure_get_int (structure, "width", &width);
331 src->format = (width == 32) ? GST_AUDIO_TEST_SRC_FORMAT_F32 :
332 GST_AUDIO_TEST_SRC_FORMAT_F64;
335 /* allocate a new buffer suitable for this pad */
336 switch (src->format) {
337 case GST_AUDIO_TEST_SRC_FORMAT_S16:
338 src->sample_size = sizeof (gint16);
340 case GST_AUDIO_TEST_SRC_FORMAT_S32:
341 src->sample_size = sizeof (gint32);
343 case GST_AUDIO_TEST_SRC_FORMAT_F32:
344 src->sample_size = sizeof (gfloat);
346 case GST_AUDIO_TEST_SRC_FORMAT_F64:
347 src->sample_size = sizeof (gdouble);
350 /* can't really happen */
355 ret &= gst_structure_get_int (structure, "channels", &src->channels);
356 GST_DEBUG_OBJECT (src, "negotiated to %d channels", src->channels);
358 gst_audio_test_src_change_wave (src);
364 gst_audio_test_src_query (GstBaseSrc * basesrc, GstQuery * query)
366 GstAudioTestSrc *src = GST_AUDIO_TEST_SRC (basesrc);
367 gboolean res = FALSE;
369 switch (GST_QUERY_TYPE (query)) {
370 case GST_QUERY_CONVERT:
372 GstFormat src_fmt, dest_fmt;
373 gint64 src_val, dest_val;
375 gst_query_parse_convert (query, &src_fmt, &src_val, &dest_fmt, &dest_val);
376 if (src_fmt == dest_fmt) {
382 case GST_FORMAT_DEFAULT:
384 case GST_FORMAT_TIME:
385 /* samples to time */
387 gst_util_uint64_scale_int (src_val, GST_SECOND,
394 case GST_FORMAT_TIME:
396 case GST_FORMAT_DEFAULT:
397 /* time to samples */
399 gst_util_uint64_scale_int (src_val, src->samplerate,
410 gst_query_set_convert (query, src_fmt, src_val, dest_fmt, dest_val);
415 res = GST_BASE_SRC_CLASS (parent_class)->query (basesrc, query);
423 GST_DEBUG_OBJECT (src, "query failed");
428 #define DEFINE_SINE(type,scale) \
430 gst_audio_test_src_create_sine_##type (GstAudioTestSrc * src, g##type * samples) \
435 step = M_PI_M2 * src->freq / src->samplerate; \
436 amp = src->volume * scale; \
439 while (i < (src->generate_samples_per_buffer * src->channels)) { \
440 src->accumulator += step; \
441 if (src->accumulator >= M_PI_M2) \
442 src->accumulator -= M_PI_M2; \
444 for (c = 0; c < src->channels; ++c) { \
445 samples[i++] = (g##type) (sin (src->accumulator) * amp); \
450 DEFINE_SINE (int16, 32767.0);
451 DEFINE_SINE (int32, 2147483647.0);
452 DEFINE_SINE (float, 1.0);
453 DEFINE_SINE (double, 1.0);
455 static const ProcessFunc sine_funcs[] = {
456 (ProcessFunc) gst_audio_test_src_create_sine_int16,
457 (ProcessFunc) gst_audio_test_src_create_sine_int32,
458 (ProcessFunc) gst_audio_test_src_create_sine_float,
459 (ProcessFunc) gst_audio_test_src_create_sine_double
462 #define DEFINE_SQUARE(type,scale) \
464 gst_audio_test_src_create_square_##type (GstAudioTestSrc * src, g##type * samples) \
469 step = M_PI_M2 * src->freq / src->samplerate; \
470 amp = src->volume * scale; \
473 while (i < (src->generate_samples_per_buffer * src->channels)) { \
474 src->accumulator += step; \
475 if (src->accumulator >= M_PI_M2) \
476 src->accumulator -= M_PI_M2; \
478 for (c = 0; c < src->channels; ++c) { \
479 samples[i++] = (g##type) ((src->accumulator < M_PI) ? amp : -amp); \
484 DEFINE_SQUARE (int16, 32767.0);
485 DEFINE_SQUARE (int32, 2147483647.0);
486 DEFINE_SQUARE (float, 1.0);
487 DEFINE_SQUARE (double, 1.0);
489 static const ProcessFunc square_funcs[] = {
490 (ProcessFunc) gst_audio_test_src_create_square_int16,
491 (ProcessFunc) gst_audio_test_src_create_square_int32,
492 (ProcessFunc) gst_audio_test_src_create_square_float,
493 (ProcessFunc) gst_audio_test_src_create_square_double
496 #define DEFINE_SAW(type,scale) \
498 gst_audio_test_src_create_saw_##type (GstAudioTestSrc * src, g##type * samples) \
503 step = M_PI_M2 * src->freq / src->samplerate; \
504 amp = (src->volume * scale) / M_PI; \
507 while (i < (src->generate_samples_per_buffer * src->channels)) { \
508 src->accumulator += step; \
509 if (src->accumulator >= M_PI_M2) \
510 src->accumulator -= M_PI_M2; \
512 if (src->accumulator < M_PI) { \
513 for (c = 0; c < src->channels; ++c) \
514 samples[i++] = (g##type) (src->accumulator * amp); \
516 for (c = 0; c < src->channels; ++c) \
517 samples[i++] = (g##type) ((M_PI_M2 - src->accumulator) * -amp); \
522 DEFINE_SAW (int16, 32767.0);
523 DEFINE_SAW (int32, 2147483647.0);
524 DEFINE_SAW (float, 1.0);
525 DEFINE_SAW (double, 1.0);
527 static const ProcessFunc saw_funcs[] = {
528 (ProcessFunc) gst_audio_test_src_create_saw_int16,
529 (ProcessFunc) gst_audio_test_src_create_saw_int32,
530 (ProcessFunc) gst_audio_test_src_create_saw_float,
531 (ProcessFunc) gst_audio_test_src_create_saw_double
534 #define DEFINE_TRIANGLE(type,scale) \
536 gst_audio_test_src_create_triangle_##type (GstAudioTestSrc * src, g##type * samples) \
541 step = M_PI_M2 * src->freq / src->samplerate; \
542 amp = (src->volume * scale) / M_PI_2; \
545 while (i < (src->generate_samples_per_buffer * src->channels)) { \
546 src->accumulator += step; \
547 if (src->accumulator >= M_PI_M2) \
548 src->accumulator -= M_PI_M2; \
550 if (src->accumulator < (M_PI * 0.5)) { \
551 for (c = 0; c < src->channels; ++c) \
552 samples[i++] = (g##type) (src->accumulator * amp); \
553 } else if (src->accumulator < (M_PI * 1.5)) { \
554 for (c = 0; c < src->channels; ++c) \
555 samples[i++] = (g##type) ((src->accumulator - M_PI) * -amp); \
557 for (c = 0; c < src->channels; ++c) \
558 samples[i++] = (g##type) ((M_PI_M2 - src->accumulator) * -amp); \
563 DEFINE_TRIANGLE (int16, 32767.0);
564 DEFINE_TRIANGLE (int32, 2147483647.0);
565 DEFINE_TRIANGLE (float, 1.0);
566 DEFINE_TRIANGLE (double, 1.0);
568 static const ProcessFunc triangle_funcs[] = {
569 (ProcessFunc) gst_audio_test_src_create_triangle_int16,
570 (ProcessFunc) gst_audio_test_src_create_triangle_int32,
571 (ProcessFunc) gst_audio_test_src_create_triangle_float,
572 (ProcessFunc) gst_audio_test_src_create_triangle_double
575 #define DEFINE_SILENCE(type) \
577 gst_audio_test_src_create_silence_##type (GstAudioTestSrc * src, g##type * samples) \
579 memset (samples, 0, src->generate_samples_per_buffer * sizeof (g##type) * src->channels); \
582 DEFINE_SILENCE (int16);
583 DEFINE_SILENCE (int32);
584 DEFINE_SILENCE (float);
585 DEFINE_SILENCE (double);
587 static const ProcessFunc silence_funcs[] = {
588 (ProcessFunc) gst_audio_test_src_create_silence_int16,
589 (ProcessFunc) gst_audio_test_src_create_silence_int32,
590 (ProcessFunc) gst_audio_test_src_create_silence_float,
591 (ProcessFunc) gst_audio_test_src_create_silence_double
594 #define DEFINE_WHITE_NOISE(type,scale) \
596 gst_audio_test_src_create_white_noise_##type (GstAudioTestSrc * src, g##type * samples) \
599 gdouble amp = (src->volume * scale); \
602 while (i < (src->generate_samples_per_buffer * src->channels)) { \
603 for (c = 0; c < src->channels; ++c) \
604 samples[i++] = (g##type) (amp * g_rand_double_range (src->gen, -1.0, 1.0)); \
608 DEFINE_WHITE_NOISE (int16, 32767.0);
609 DEFINE_WHITE_NOISE (int32, 2147483647.0);
610 DEFINE_WHITE_NOISE (float, 1.0);
611 DEFINE_WHITE_NOISE (double, 1.0);
613 static const ProcessFunc white_noise_funcs[] = {
614 (ProcessFunc) gst_audio_test_src_create_white_noise_int16,
615 (ProcessFunc) gst_audio_test_src_create_white_noise_int32,
616 (ProcessFunc) gst_audio_test_src_create_white_noise_float,
617 (ProcessFunc) gst_audio_test_src_create_white_noise_double
620 /* pink noise calculation is based on
621 * http://www.firstpr.com.au/dsp/pink-noise/phil_burk_19990905_patest_pink.c
622 * which has been released under public domain
626 gst_audio_test_src_init_pink_noise (GstAudioTestSrc * src)
629 gint num_rows = 12; /* arbitrary: 1 .. PINK_MAX_RANDOM_ROWS */
633 src->pink.index_mask = (1 << num_rows) - 1;
634 /* calculate maximum possible signed random value.
635 * Extra 1 for white noise always added. */
636 pmax = (num_rows + 1) * (1 << (PINK_RANDOM_BITS - 1));
637 src->pink.scalar = 1.0f / pmax;
638 /* Initialize rows. */
639 for (i = 0; i < num_rows; i++)
640 src->pink.rows[i] = 0;
641 src->pink.running_sum = 0;
644 /* Generate Pink noise values between -1.0 and +1.0 */
646 gst_audio_test_src_generate_pink_noise_value (GstAudioTestSrc * src)
648 GstPinkNoise *pink = &src->pink;
652 /* Increment and mask index. */
653 pink->index = (pink->index + 1) & pink->index_mask;
655 /* If index is zero, don't update any random values. */
656 if (pink->index != 0) {
657 /* Determine how many trailing zeros in PinkIndex. */
658 /* This algorithm will hang if n==0 so test first. */
660 gint n = pink->index;
662 while ((n & 1) == 0) {
667 /* Replace the indexed ROWS random value.
668 * Subtract and add back to RunningSum instead of adding all the random
669 * values together. Only one changes each time.
671 pink->running_sum -= pink->rows[num_zeros];
672 new_random = 32768.0 - (65536.0 * (gulong) g_rand_int (src->gen)
673 / (G_MAXUINT32 + 1.0));
674 pink->running_sum += new_random;
675 pink->rows[num_zeros] = new_random;
678 /* Add extra white noise value. */
679 new_random = 32768.0 - (65536.0 * (gulong) g_rand_int (src->gen)
680 / (G_MAXUINT32 + 1.0));
681 sum = pink->running_sum + new_random;
683 /* Scale to range of -1.0 to 0.9999. */
684 return (pink->scalar * sum);
687 #define DEFINE_PINK(type, scale) \
689 gst_audio_test_src_create_pink_noise_##type (GstAudioTestSrc * src, g##type * samples) \
694 amp = src->volume * scale; \
697 while (i < (src->generate_samples_per_buffer * src->channels)) { \
698 for (c = 0; c < src->channels; ++c) { \
700 (g##type) (gst_audio_test_src_generate_pink_noise_value (src) * \
706 DEFINE_PINK (int16, 32767.0);
707 DEFINE_PINK (int32, 2147483647.0);
708 DEFINE_PINK (float, 1.0);
709 DEFINE_PINK (double, 1.0);
711 static const ProcessFunc pink_noise_funcs[] = {
712 (ProcessFunc) gst_audio_test_src_create_pink_noise_int16,
713 (ProcessFunc) gst_audio_test_src_create_pink_noise_int32,
714 (ProcessFunc) gst_audio_test_src_create_pink_noise_float,
715 (ProcessFunc) gst_audio_test_src_create_pink_noise_double
719 gst_audio_test_src_init_sine_table (GstAudioTestSrc * src)
723 gdouble step = M_PI_M2 / 1024.0;
724 gdouble amp = src->volume;
726 for (i = 0; i < 1024; i++) {
727 src->wave_table[i] = sin (ang) * amp;
732 #define DEFINE_SINE_TABLE(type,scale) \
734 gst_audio_test_src_create_sine_table_##type (GstAudioTestSrc * src, g##type * samples) \
739 step = M_PI_M2 * src->freq / src->samplerate; \
740 scl = 1024.0 / M_PI_M2; \
743 while (i < (src->generate_samples_per_buffer * src->channels)) { \
744 src->accumulator += step; \
745 if (src->accumulator >= M_PI_M2) \
746 src->accumulator -= M_PI_M2; \
748 for (c = 0; c < src->channels; ++c) \
749 samples[i++] = (g##type) scale * src->wave_table[(gint) (src->accumulator * scl)]; \
753 DEFINE_SINE_TABLE (int16, 32767.0);
754 DEFINE_SINE_TABLE (int32, 2147483647.0);
755 DEFINE_SINE_TABLE (float, 1.0);
756 DEFINE_SINE_TABLE (double, 1.0);
758 static const ProcessFunc sine_table_funcs[] = {
759 (ProcessFunc) gst_audio_test_src_create_sine_table_int16,
760 (ProcessFunc) gst_audio_test_src_create_sine_table_int32,
761 (ProcessFunc) gst_audio_test_src_create_sine_table_float,
762 (ProcessFunc) gst_audio_test_src_create_sine_table_double
765 #define DEFINE_TICKS(type,scale) \
767 gst_audio_test_src_create_tick_##type (GstAudioTestSrc * src, g##type * samples) \
772 step = M_PI_M2 * src->freq / src->samplerate; \
773 scl = 1024.0 / M_PI_M2; \
775 for (i = 0; i < src->generate_samples_per_buffer; i++) { \
776 src->accumulator += step; \
777 if (src->accumulator >= M_PI_M2) \
778 src->accumulator -= M_PI_M2; \
780 if ((src->next_sample + i)%src->samplerate < 1600) { \
781 for (c = 0; c < src->channels; ++c) \
782 samples[(i * src->channels) + c] = (g##type) scale * src->wave_table[(gint) (src->accumulator * scl)]; \
784 for (c = 0; c < src->channels; ++c) \
785 samples[(i * src->channels) + c] = 0; \
790 DEFINE_TICKS (int16, 32767.0);
791 DEFINE_TICKS (int32, 2147483647.0);
792 DEFINE_TICKS (float, 1.0);
793 DEFINE_TICKS (double, 1.0);
795 static const ProcessFunc tick_funcs[] = {
796 (ProcessFunc) gst_audio_test_src_create_tick_int16,
797 (ProcessFunc) gst_audio_test_src_create_tick_int32,
798 (ProcessFunc) gst_audio_test_src_create_tick_float,
799 (ProcessFunc) gst_audio_test_src_create_tick_double
802 /* Gaussian white noise using Box-Muller algorithm. unit variance
803 * normally-distributed random numbers are generated in pairs as the real
804 * and imaginary parts of a compex random variable with
805 * uniformly-distributed argument and \chi^{2}-distributed modulus.
808 #define DEFINE_GAUSSIAN_WHITE_NOISE(type,scale) \
810 gst_audio_test_src_create_gaussian_white_noise_##type (GstAudioTestSrc * src, g##type * samples) \
813 gdouble amp = (src->volume * scale); \
815 for (i = 0; i < src->generate_samples_per_buffer * src->channels; ) { \
816 for (c = 0; c < src->channels; ++c) { \
817 gdouble mag = sqrt (-2 * log (1.0 - g_rand_double (src->gen))); \
818 gdouble phs = g_rand_double_range (src->gen, 0.0, M_PI_M2); \
820 samples[i++] = (g##type) (amp * mag * cos (phs)); \
821 if (++c >= src->channels) \
823 samples[i++] = (g##type) (amp * mag * sin (phs)); \
828 DEFINE_GAUSSIAN_WHITE_NOISE (int16, 32767.0);
829 DEFINE_GAUSSIAN_WHITE_NOISE (int32, 2147483647.0);
830 DEFINE_GAUSSIAN_WHITE_NOISE (float, 1.0);
831 DEFINE_GAUSSIAN_WHITE_NOISE (double, 1.0);
833 static const ProcessFunc gaussian_white_noise_funcs[] = {
834 (ProcessFunc) gst_audio_test_src_create_gaussian_white_noise_int16,
835 (ProcessFunc) gst_audio_test_src_create_gaussian_white_noise_int32,
836 (ProcessFunc) gst_audio_test_src_create_gaussian_white_noise_float,
837 (ProcessFunc) gst_audio_test_src_create_gaussian_white_noise_double
841 * gst_audio_test_src_change_wave:
842 * Assign function pointer of wave genrator.
845 gst_audio_test_src_change_wave (GstAudioTestSrc * src)
847 if (src->format == -1) {
853 case GST_AUDIO_TEST_SRC_WAVE_SINE:
854 src->process = sine_funcs[src->format];
856 case GST_AUDIO_TEST_SRC_WAVE_SQUARE:
857 src->process = square_funcs[src->format];
859 case GST_AUDIO_TEST_SRC_WAVE_SAW:
860 src->process = saw_funcs[src->format];
862 case GST_AUDIO_TEST_SRC_WAVE_TRIANGLE:
863 src->process = triangle_funcs[src->format];
865 case GST_AUDIO_TEST_SRC_WAVE_SILENCE:
866 src->process = silence_funcs[src->format];
868 case GST_AUDIO_TEST_SRC_WAVE_WHITE_NOISE:
870 src->gen = g_rand_new ();
871 src->process = white_noise_funcs[src->format];
873 case GST_AUDIO_TEST_SRC_WAVE_PINK_NOISE:
875 src->gen = g_rand_new ();
876 gst_audio_test_src_init_pink_noise (src);
877 src->process = pink_noise_funcs[src->format];
879 case GST_AUDIO_TEST_SRC_WAVE_SINE_TAB:
880 gst_audio_test_src_init_sine_table (src);
881 src->process = sine_table_funcs[src->format];
883 case GST_AUDIO_TEST_SRC_WAVE_TICKS:
884 gst_audio_test_src_init_sine_table (src);
885 src->process = tick_funcs[src->format];
887 case GST_AUDIO_TEST_SRC_WAVE_GAUSSIAN_WHITE_NOISE:
889 src->gen = g_rand_new ();
890 src->process = gaussian_white_noise_funcs[src->format];
893 GST_ERROR ("invalid wave-form");
899 * gst_audio_test_src_change_volume:
900 * Recalc wave tables for precalculated waves.
903 gst_audio_test_src_change_volume (GstAudioTestSrc * src)
906 case GST_AUDIO_TEST_SRC_WAVE_SINE_TAB:
907 gst_audio_test_src_init_sine_table (src);
915 gst_audio_test_src_get_times (GstBaseSrc * basesrc, GstBuffer * buffer,
916 GstClockTime * start, GstClockTime * end)
918 /* for live sources, sync on the timestamp of the buffer */
919 if (gst_base_src_is_live (basesrc)) {
920 GstClockTime timestamp = GST_BUFFER_TIMESTAMP (buffer);
922 if (GST_CLOCK_TIME_IS_VALID (timestamp)) {
923 /* get duration to calculate end time */
924 GstClockTime duration = GST_BUFFER_DURATION (buffer);
926 if (GST_CLOCK_TIME_IS_VALID (duration)) {
927 *end = timestamp + duration;
938 gst_audio_test_src_start (GstBaseSrc * basesrc)
940 GstAudioTestSrc *src = GST_AUDIO_TEST_SRC (basesrc);
942 src->next_sample = 0;
945 src->check_seek_stop = FALSE;
946 src->eos_reached = FALSE;
947 src->tags_pushed = FALSE;
948 src->accumulator = 0;
954 gst_audio_test_src_stop (GstBaseSrc * basesrc)
959 /* seek to time, will be called when we operate in push mode. In pull mode we
960 * get the requested byte offset. */
962 gst_audio_test_src_do_seek (GstBaseSrc * basesrc, GstSegment * segment)
964 GstAudioTestSrc *src = GST_AUDIO_TEST_SRC (basesrc);
967 GST_DEBUG_OBJECT (src, "seeking %" GST_SEGMENT_FORMAT, segment);
969 time = segment->last_stop;
970 src->reverse = (segment->rate < 0.0);
972 /* now move to the time indicated */
974 gst_util_uint64_scale_int (time, src->samplerate, GST_SECOND);
975 src->next_byte = src->next_sample * src->sample_size * src->channels;
977 gst_util_uint64_scale_int (src->next_sample, GST_SECOND, src->samplerate);
979 GST_DEBUG_OBJECT (src, "seeking next_sample=%" G_GINT64_FORMAT
980 " next_time=%" GST_TIME_FORMAT, src->next_sample,
981 GST_TIME_ARGS (src->next_time));
983 g_assert (src->next_time <= time);
986 if (GST_CLOCK_TIME_IS_VALID (segment->start)) {
987 segment->time = segment->start;
990 if (GST_CLOCK_TIME_IS_VALID (segment->stop)) {
991 segment->time = segment->stop;
995 if (GST_CLOCK_TIME_IS_VALID (segment->stop)) {
996 time = segment->stop;
997 src->sample_stop = gst_util_uint64_scale_int (time, src->samplerate,
999 src->check_seek_stop = TRUE;
1001 src->check_seek_stop = FALSE;
1003 src->eos_reached = FALSE;
1009 gst_audio_test_src_is_seekable (GstBaseSrc * basesrc)
1011 /* we're seekable... */
1016 gst_audio_test_src_check_get_range (GstBaseSrc * basesrc)
1018 GstAudioTestSrc *src;
1020 src = GST_AUDIO_TEST_SRC (basesrc);
1022 /* if we can operate in pull mode */
1023 return src->can_activate_pull;
1026 static GstFlowReturn
1027 gst_audio_test_src_create (GstBaseSrc * basesrc, guint64 offset,
1028 guint length, GstBuffer ** buffer)
1031 GstAudioTestSrc *src;
1033 GstClockTime next_time;
1034 gint64 next_sample, next_byte;
1035 gint bytes, samples;
1036 GstElementClass *eclass;
1038 src = GST_AUDIO_TEST_SRC (basesrc);
1040 /* example for tagging generated data */
1041 if (!src->tags_pushed) {
1042 GstTagList *taglist;
1044 taglist = gst_tag_list_new ();
1046 gst_tag_list_add (taglist, GST_TAG_MERGE_APPEND,
1047 GST_TAG_DESCRIPTION, "audiotest wave", NULL);
1049 eclass = GST_ELEMENT_CLASS (parent_class);
1050 if (eclass->send_event)
1051 eclass->send_event (GST_ELEMENT_CAST (basesrc),
1052 gst_event_new_tag (taglist));
1053 src->tags_pushed = TRUE;
1056 if (src->eos_reached) {
1057 GST_INFO_OBJECT (src, "eos");
1058 return GST_FLOW_UNEXPECTED;
1061 /* if no length was given, use our default length in samples otherwise convert
1062 * the length in bytes to samples. */
1064 samples = src->samples_per_buffer;
1066 samples = length / (src->sample_size * src->channels);
1068 /* if no offset was given, use our next logical byte */
1070 offset = src->next_byte;
1072 /* now see if we are at the byteoffset we think we are */
1073 if (offset != src->next_byte) {
1074 GST_DEBUG_OBJECT (src, "seek to new offset %" G_GUINT64_FORMAT, offset);
1075 /* we have a discont in the expected sample offset, do a 'seek' */
1076 src->next_sample = offset / (src->sample_size * src->channels);
1078 gst_util_uint64_scale_int (src->next_sample, GST_SECOND,
1080 src->next_byte = offset;
1084 if (src->check_seek_stop &&
1085 (src->sample_stop > src->next_sample) &&
1086 (src->sample_stop < src->next_sample + samples)
1088 /* calculate only partial buffer */
1089 src->generate_samples_per_buffer = src->sample_stop - src->next_sample;
1090 next_sample = src->sample_stop;
1091 src->eos_reached = TRUE;
1093 /* calculate full buffer */
1094 src->generate_samples_per_buffer = samples;
1095 next_sample = src->next_sample + (src->reverse ? (-samples) : samples);
1098 bytes = src->generate_samples_per_buffer * src->sample_size * src->channels;
1100 if ((res = gst_pad_alloc_buffer (basesrc->srcpad, src->next_sample,
1101 bytes, GST_PAD_CAPS (basesrc->srcpad), &buf)) != GST_FLOW_OK) {
1105 next_byte = src->next_byte + (src->reverse ? (-bytes) : bytes);
1106 next_time = gst_util_uint64_scale_int (next_sample, GST_SECOND,
1109 GST_LOG_OBJECT (src, "samplerate %d", src->samplerate);
1110 GST_LOG_OBJECT (src, "next_sample %" G_GINT64_FORMAT ", ts %" GST_TIME_FORMAT,
1111 next_sample, GST_TIME_ARGS (next_time));
1113 GST_BUFFER_OFFSET (buf) = src->next_sample;
1114 GST_BUFFER_OFFSET_END (buf) = next_sample;
1115 if (!src->reverse) {
1116 GST_BUFFER_TIMESTAMP (buf) = src->timestamp_offset + src->next_time;
1117 GST_BUFFER_DURATION (buf) = next_time - src->next_time;
1119 GST_BUFFER_TIMESTAMP (buf) = src->timestamp_offset + next_time;
1120 GST_BUFFER_DURATION (buf) = src->next_time - next_time;
1123 gst_object_sync_values (G_OBJECT (src), GST_BUFFER_TIMESTAMP (buf));
1125 src->next_time = next_time;
1126 src->next_sample = next_sample;
1127 src->next_byte = next_byte;
1129 GST_LOG_OBJECT (src, "generating %u samples at ts %" GST_TIME_FORMAT,
1130 src->generate_samples_per_buffer,
1131 GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buf)));
1133 src->process (src, GST_BUFFER_DATA (buf));
1135 if (G_UNLIKELY ((src->wave == GST_AUDIO_TEST_SRC_WAVE_SILENCE)
1136 || (src->volume == 0.0))) {
1137 GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_GAP);
1146 gst_audio_test_src_set_property (GObject * object, guint prop_id,
1147 const GValue * value, GParamSpec * pspec)
1149 GstAudioTestSrc *src = GST_AUDIO_TEST_SRC (object);
1152 case PROP_SAMPLES_PER_BUFFER:
1153 src->samples_per_buffer = g_value_get_int (value);
1156 src->wave = g_value_get_enum (value);
1157 gst_audio_test_src_change_wave (src);
1160 src->freq = g_value_get_double (value);
1163 src->volume = g_value_get_double (value);
1164 gst_audio_test_src_change_volume (src);
1167 gst_base_src_set_live (GST_BASE_SRC (src), g_value_get_boolean (value));
1169 case PROP_TIMESTAMP_OFFSET:
1170 src->timestamp_offset = g_value_get_int64 (value);
1172 case PROP_CAN_ACTIVATE_PUSH:
1173 GST_BASE_SRC (src)->can_activate_push = g_value_get_boolean (value);
1175 case PROP_CAN_ACTIVATE_PULL:
1176 src->can_activate_pull = g_value_get_boolean (value);
1179 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1185 gst_audio_test_src_get_property (GObject * object, guint prop_id,
1186 GValue * value, GParamSpec * pspec)
1188 GstAudioTestSrc *src = GST_AUDIO_TEST_SRC (object);
1191 case PROP_SAMPLES_PER_BUFFER:
1192 g_value_set_int (value, src->samples_per_buffer);
1195 g_value_set_enum (value, src->wave);
1198 g_value_set_double (value, src->freq);
1201 g_value_set_double (value, src->volume);
1204 g_value_set_boolean (value, gst_base_src_is_live (GST_BASE_SRC (src)));
1206 case PROP_TIMESTAMP_OFFSET:
1207 g_value_set_int64 (value, src->timestamp_offset);
1209 case PROP_CAN_ACTIVATE_PUSH:
1210 g_value_set_boolean (value, GST_BASE_SRC (src)->can_activate_push);
1212 case PROP_CAN_ACTIVATE_PULL:
1213 g_value_set_boolean (value, src->can_activate_pull);
1216 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1222 plugin_init (GstPlugin * plugin)
1224 /* initialize gst controller library */
1225 gst_controller_init (NULL, NULL);
1227 GST_DEBUG_CATEGORY_INIT (audio_test_src_debug, "audiotestsrc", 0,
1228 "Audio Test Source");
1230 return gst_element_register (plugin, "audiotestsrc",
1231 GST_RANK_NONE, GST_TYPE_AUDIO_TEST_SRC);
1234 GST_PLUGIN_DEFINE (GST_VERSION_MAJOR,
1237 "Creates audio test signals of given frequency and volume",
1238 plugin_init, VERSION, "LGPL", GST_PACKAGE_NAME, GST_PACKAGE_ORIGIN);