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"
51 #define M_PI_M2 ( G_PI + G_PI )
53 GST_DEBUG_CATEGORY_STATIC (audio_test_src_debug);
54 #define GST_CAT_DEFAULT audio_test_src_debug
56 #define DEFAULT_SAMPLES_PER_BUFFER 1024
57 #define DEFAULT_WAVE GST_AUDIO_TEST_SRC_WAVE_SINE
58 #define DEFAULT_FREQ 440.0
59 #define DEFAULT_VOLUME 0.8
60 #define DEFAULT_IS_LIVE FALSE
61 #define DEFAULT_TIMESTAMP_OFFSET G_GINT64_CONSTANT (0)
62 #define DEFAULT_CAN_ACTIVATE_PUSH TRUE
63 #define DEFAULT_CAN_ACTIVATE_PULL FALSE
68 PROP_SAMPLES_PER_BUFFER,
73 PROP_TIMESTAMP_OFFSET,
74 PROP_CAN_ACTIVATE_PUSH,
75 PROP_CAN_ACTIVATE_PULL,
80 static GstStaticPadTemplate gst_audio_test_src_src_template =
81 GST_STATIC_PAD_TEMPLATE ("src",
84 GST_STATIC_CAPS ("audio/x-raw-int, "
85 "endianness = (int) BYTE_ORDER, "
86 "signed = (boolean) true, "
89 "rate = (int) [ 1, MAX ], "
90 "channels = (int) [ 1, 2 ]; "
92 "endianness = (int) BYTE_ORDER, "
93 "signed = (boolean) true, "
96 "rate = (int) [ 1, MAX ], "
97 "channels = (int) [ 1, 2 ]; "
99 "endianness = (int) BYTE_ORDER, "
100 "width = (int) { 32, 64 }, "
101 "rate = (int) [ 1, MAX ], " "channels = (int) [ 1, 2 ]")
105 GST_BOILERPLATE (GstAudioTestSrc, gst_audio_test_src, GstBaseSrc,
108 #define GST_TYPE_AUDIO_TEST_SRC_WAVE (gst_audiostestsrc_wave_get_type())
110 gst_audiostestsrc_wave_get_type (void)
112 static GType audiostestsrc_wave_type = 0;
113 static const GEnumValue audiostestsrc_waves[] = {
114 {GST_AUDIO_TEST_SRC_WAVE_SINE, "Sine", "sine"},
115 {GST_AUDIO_TEST_SRC_WAVE_SQUARE, "Square", "square"},
116 {GST_AUDIO_TEST_SRC_WAVE_SAW, "Saw", "saw"},
117 {GST_AUDIO_TEST_SRC_WAVE_TRIANGLE, "Triangle", "triangle"},
118 {GST_AUDIO_TEST_SRC_WAVE_SILENCE, "Silence", "silence"},
119 {GST_AUDIO_TEST_SRC_WAVE_WHITE_NOISE, "White uniform noise", "white-noise"},
120 {GST_AUDIO_TEST_SRC_WAVE_PINK_NOISE, "Pink noise", "pink-noise"},
121 {GST_AUDIO_TEST_SRC_WAVE_SINE_TAB, "Sine table", "sine-table"},
122 {GST_AUDIO_TEST_SRC_WAVE_TICKS, "Periodic Ticks", "ticks"},
123 {GST_AUDIO_TEST_SRC_WAVE_GAUSSIAN_WHITE_NOISE, "White Gaussian noise",
125 {GST_AUDIO_TEST_SRC_WAVE_RED_NOISE, "Red (brownian) noise", "red-noise"},
126 {GST_AUDIO_TEST_SRC_WAVE_BLUE_NOISE, "Blue noise", "blue-noise"},
127 {GST_AUDIO_TEST_SRC_WAVE_VIOLET_NOISE, "Violet noise", "violet-noise"},
131 if (G_UNLIKELY (audiostestsrc_wave_type == 0)) {
132 audiostestsrc_wave_type = g_enum_register_static ("GstAudioTestSrcWave",
133 audiostestsrc_waves);
135 return audiostestsrc_wave_type;
138 static void gst_audio_test_src_finalize (GObject * object);
140 static void gst_audio_test_src_set_property (GObject * object,
141 guint prop_id, const GValue * value, GParamSpec * pspec);
142 static void gst_audio_test_src_get_property (GObject * object,
143 guint prop_id, GValue * value, GParamSpec * pspec);
145 static gboolean gst_audio_test_src_setcaps (GstBaseSrc * basesrc,
147 static void gst_audio_test_src_src_fixate (GstPad * pad, GstCaps * caps);
149 static gboolean gst_audio_test_src_is_seekable (GstBaseSrc * basesrc);
150 static gboolean gst_audio_test_src_check_get_range (GstBaseSrc * basesrc);
151 static gboolean gst_audio_test_src_do_seek (GstBaseSrc * basesrc,
152 GstSegment * segment);
153 static gboolean gst_audio_test_src_query (GstBaseSrc * basesrc,
156 static void gst_audio_test_src_change_wave (GstAudioTestSrc * src);
158 static void gst_audio_test_src_get_times (GstBaseSrc * basesrc,
159 GstBuffer * buffer, GstClockTime * start, GstClockTime * end);
160 static gboolean gst_audio_test_src_start (GstBaseSrc * basesrc);
161 static gboolean gst_audio_test_src_stop (GstBaseSrc * basesrc);
162 static GstFlowReturn gst_audio_test_src_create (GstBaseSrc * basesrc,
163 guint64 offset, guint length, GstBuffer ** buffer);
167 gst_audio_test_src_base_init (gpointer g_class)
169 GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
171 gst_element_class_add_static_pad_template (element_class,
172 &gst_audio_test_src_src_template);
173 gst_element_class_set_details_simple (element_class,
174 "Audio test source", "Source/Audio",
175 "Creates audio test signals of given frequency and volume",
176 "Stefan Kost <ensonic@users.sf.net>");
180 gst_audio_test_src_class_init (GstAudioTestSrcClass * klass)
182 GObjectClass *gobject_class;
183 GstBaseSrcClass *gstbasesrc_class;
185 gobject_class = (GObjectClass *) klass;
186 gstbasesrc_class = (GstBaseSrcClass *) klass;
188 gobject_class->set_property = gst_audio_test_src_set_property;
189 gobject_class->get_property = gst_audio_test_src_get_property;
190 gobject_class->finalize = gst_audio_test_src_finalize;
192 g_object_class_install_property (gobject_class, PROP_SAMPLES_PER_BUFFER,
193 g_param_spec_int ("samplesperbuffer", "Samples per buffer",
194 "Number of samples in each outgoing buffer",
195 1, G_MAXINT, DEFAULT_SAMPLES_PER_BUFFER,
196 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
197 g_object_class_install_property (gobject_class, PROP_WAVE,
198 g_param_spec_enum ("wave", "Waveform", "Oscillator waveform",
199 GST_TYPE_AUDIO_TEST_SRC_WAVE, GST_AUDIO_TEST_SRC_WAVE_SINE,
200 G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE | G_PARAM_STATIC_STRINGS));
201 g_object_class_install_property (gobject_class, PROP_FREQ,
202 g_param_spec_double ("freq", "Frequency", "Frequency of test signal",
203 0.0, 20000.0, DEFAULT_FREQ,
204 G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE | G_PARAM_STATIC_STRINGS));
205 g_object_class_install_property (gobject_class, PROP_VOLUME,
206 g_param_spec_double ("volume", "Volume", "Volume of test signal", 0.0,
208 G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE | G_PARAM_STATIC_STRINGS));
209 g_object_class_install_property (gobject_class, PROP_IS_LIVE,
210 g_param_spec_boolean ("is-live", "Is Live",
211 "Whether to act as a live source", DEFAULT_IS_LIVE,
212 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
213 g_object_class_install_property (G_OBJECT_CLASS (klass),
214 PROP_TIMESTAMP_OFFSET, g_param_spec_int64 ("timestamp-offset",
216 "An offset added to timestamps set on buffers (in ns)", G_MININT64,
217 G_MAXINT64, DEFAULT_TIMESTAMP_OFFSET,
218 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
219 g_object_class_install_property (gobject_class, PROP_CAN_ACTIVATE_PUSH,
220 g_param_spec_boolean ("can-activate-push", "Can activate push",
221 "Can activate in push mode", DEFAULT_CAN_ACTIVATE_PUSH,
222 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
223 g_object_class_install_property (gobject_class, PROP_CAN_ACTIVATE_PULL,
224 g_param_spec_boolean ("can-activate-pull", "Can activate pull",
225 "Can activate in pull mode", DEFAULT_CAN_ACTIVATE_PULL,
226 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
228 gstbasesrc_class->set_caps = GST_DEBUG_FUNCPTR (gst_audio_test_src_setcaps);
229 gstbasesrc_class->is_seekable =
230 GST_DEBUG_FUNCPTR (gst_audio_test_src_is_seekable);
231 gstbasesrc_class->check_get_range =
232 GST_DEBUG_FUNCPTR (gst_audio_test_src_check_get_range);
233 gstbasesrc_class->do_seek = GST_DEBUG_FUNCPTR (gst_audio_test_src_do_seek);
234 gstbasesrc_class->query = GST_DEBUG_FUNCPTR (gst_audio_test_src_query);
235 gstbasesrc_class->get_times =
236 GST_DEBUG_FUNCPTR (gst_audio_test_src_get_times);
237 gstbasesrc_class->start = GST_DEBUG_FUNCPTR (gst_audio_test_src_start);
238 gstbasesrc_class->stop = GST_DEBUG_FUNCPTR (gst_audio_test_src_stop);
239 gstbasesrc_class->create = GST_DEBUG_FUNCPTR (gst_audio_test_src_create);
243 gst_audio_test_src_init (GstAudioTestSrc * src, GstAudioTestSrcClass * g_class)
245 GstPad *pad = GST_BASE_SRC_PAD (src);
247 gst_pad_set_fixatecaps_function (pad, gst_audio_test_src_src_fixate);
249 src->samplerate = 44100;
250 src->format = GST_AUDIO_TEST_SRC_FORMAT_NONE;
252 src->volume = DEFAULT_VOLUME;
253 src->freq = DEFAULT_FREQ;
255 /* we operate in time */
256 gst_base_src_set_format (GST_BASE_SRC (src), GST_FORMAT_TIME);
257 gst_base_src_set_live (GST_BASE_SRC (src), DEFAULT_IS_LIVE);
259 src->samples_per_buffer = DEFAULT_SAMPLES_PER_BUFFER;
260 src->generate_samples_per_buffer = src->samples_per_buffer;
261 src->timestamp_offset = DEFAULT_TIMESTAMP_OFFSET;
262 src->can_activate_pull = DEFAULT_CAN_ACTIVATE_PULL;
266 src->wave = DEFAULT_WAVE;
267 gst_base_src_set_blocksize (GST_BASE_SRC (src), -1);
271 gst_audio_test_src_finalize (GObject * object)
273 GstAudioTestSrc *src = GST_AUDIO_TEST_SRC (object);
276 g_rand_free (src->gen);
279 G_OBJECT_CLASS (parent_class)->finalize (object);
283 gst_audio_test_src_src_fixate (GstPad * pad, GstCaps * caps)
285 GstAudioTestSrc *src = GST_AUDIO_TEST_SRC (GST_PAD_PARENT (pad));
287 GstStructure *structure;
289 structure = gst_caps_get_structure (caps, 0);
291 GST_DEBUG_OBJECT (src, "fixating samplerate to %d", src->samplerate);
293 gst_structure_fixate_field_nearest_int (structure, "rate", src->samplerate);
295 name = gst_structure_get_name (structure);
296 if (strcmp (name, "audio/x-raw-int") == 0)
297 gst_structure_fixate_field_nearest_int (structure, "width", 32);
298 else if (strcmp (name, "audio/x-raw-float") == 0)
299 gst_structure_fixate_field_nearest_int (structure, "width", 64);
301 /* fixate to mono unless downstream requires stereo, for backwards compat */
302 gst_structure_fixate_field_nearest_int (structure, "channels", 1);
306 gst_audio_test_src_setcaps (GstBaseSrc * basesrc, GstCaps * caps)
308 GstAudioTestSrc *src = GST_AUDIO_TEST_SRC (basesrc);
309 const GstStructure *structure;
314 structure = gst_caps_get_structure (caps, 0);
315 ret = gst_structure_get_int (structure, "rate", &src->samplerate);
317 GST_DEBUG_OBJECT (src, "negotiated to samplerate %d", src->samplerate);
319 name = gst_structure_get_name (structure);
320 if (strcmp (name, "audio/x-raw-int") == 0) {
321 ret &= gst_structure_get_int (structure, "width", &width);
322 src->format = (width == 32) ? GST_AUDIO_TEST_SRC_FORMAT_S32 :
323 GST_AUDIO_TEST_SRC_FORMAT_S16;
325 ret &= gst_structure_get_int (structure, "width", &width);
326 src->format = (width == 32) ? GST_AUDIO_TEST_SRC_FORMAT_F32 :
327 GST_AUDIO_TEST_SRC_FORMAT_F64;
330 /* allocate a new buffer suitable for this pad */
331 switch (src->format) {
332 case GST_AUDIO_TEST_SRC_FORMAT_S16:
333 src->sample_size = sizeof (gint16);
335 case GST_AUDIO_TEST_SRC_FORMAT_S32:
336 src->sample_size = sizeof (gint32);
338 case GST_AUDIO_TEST_SRC_FORMAT_F32:
339 src->sample_size = sizeof (gfloat);
341 case GST_AUDIO_TEST_SRC_FORMAT_F64:
342 src->sample_size = sizeof (gdouble);
345 /* can't really happen */
350 ret &= gst_structure_get_int (structure, "channels", &src->channels);
351 GST_DEBUG_OBJECT (src, "negotiated to %d channels", src->channels);
353 gst_audio_test_src_change_wave (src);
359 gst_audio_test_src_query (GstBaseSrc * basesrc, GstQuery * query)
361 GstAudioTestSrc *src = GST_AUDIO_TEST_SRC (basesrc);
362 gboolean res = FALSE;
364 switch (GST_QUERY_TYPE (query)) {
365 case GST_QUERY_CONVERT:
367 GstFormat src_fmt, dest_fmt;
368 gint64 src_val, dest_val;
370 gst_query_parse_convert (query, &src_fmt, &src_val, &dest_fmt, &dest_val);
371 if (src_fmt == dest_fmt) {
377 case GST_FORMAT_DEFAULT:
379 case GST_FORMAT_TIME:
380 /* samples to time */
382 gst_util_uint64_scale_int (src_val, GST_SECOND,
389 case GST_FORMAT_TIME:
391 case GST_FORMAT_DEFAULT:
392 /* time to samples */
394 gst_util_uint64_scale_int (src_val, src->samplerate,
405 gst_query_set_convert (query, src_fmt, src_val, dest_fmt, dest_val);
410 res = GST_BASE_SRC_CLASS (parent_class)->query (basesrc, query);
418 GST_DEBUG_OBJECT (src, "query failed");
423 #define DEFINE_SINE(type,scale) \
425 gst_audio_test_src_create_sine_##type (GstAudioTestSrc * src, g##type * samples) \
430 step = M_PI_M2 * src->freq / src->samplerate; \
431 amp = src->volume * scale; \
434 while (i < (src->generate_samples_per_buffer * src->channels)) { \
435 src->accumulator += step; \
436 if (src->accumulator >= M_PI_M2) \
437 src->accumulator -= M_PI_M2; \
439 for (c = 0; c < src->channels; ++c) { \
440 samples[i++] = (g##type) (sin (src->accumulator) * amp); \
445 DEFINE_SINE (int16, 32767.0);
446 DEFINE_SINE (int32, 2147483647.0);
447 DEFINE_SINE (float, 1.0);
448 DEFINE_SINE (double, 1.0);
450 static const ProcessFunc sine_funcs[] = {
451 (ProcessFunc) gst_audio_test_src_create_sine_int16,
452 (ProcessFunc) gst_audio_test_src_create_sine_int32,
453 (ProcessFunc) gst_audio_test_src_create_sine_float,
454 (ProcessFunc) gst_audio_test_src_create_sine_double
457 #define DEFINE_SQUARE(type,scale) \
459 gst_audio_test_src_create_square_##type (GstAudioTestSrc * src, g##type * samples) \
464 step = M_PI_M2 * src->freq / src->samplerate; \
465 amp = src->volume * scale; \
468 while (i < (src->generate_samples_per_buffer * src->channels)) { \
469 src->accumulator += step; \
470 if (src->accumulator >= M_PI_M2) \
471 src->accumulator -= M_PI_M2; \
473 for (c = 0; c < src->channels; ++c) { \
474 samples[i++] = (g##type) ((src->accumulator < G_PI) ? amp : -amp); \
479 DEFINE_SQUARE (int16, 32767.0);
480 DEFINE_SQUARE (int32, 2147483647.0);
481 DEFINE_SQUARE (float, 1.0);
482 DEFINE_SQUARE (double, 1.0);
484 static const ProcessFunc square_funcs[] = {
485 (ProcessFunc) gst_audio_test_src_create_square_int16,
486 (ProcessFunc) gst_audio_test_src_create_square_int32,
487 (ProcessFunc) gst_audio_test_src_create_square_float,
488 (ProcessFunc) gst_audio_test_src_create_square_double
491 #define DEFINE_SAW(type,scale) \
493 gst_audio_test_src_create_saw_##type (GstAudioTestSrc * src, g##type * samples) \
498 step = M_PI_M2 * src->freq / src->samplerate; \
499 amp = (src->volume * scale) / G_PI; \
502 while (i < (src->generate_samples_per_buffer * src->channels)) { \
503 src->accumulator += step; \
504 if (src->accumulator >= M_PI_M2) \
505 src->accumulator -= M_PI_M2; \
507 if (src->accumulator < G_PI) { \
508 for (c = 0; c < src->channels; ++c) \
509 samples[i++] = (g##type) (src->accumulator * amp); \
511 for (c = 0; c < src->channels; ++c) \
512 samples[i++] = (g##type) ((M_PI_M2 - src->accumulator) * -amp); \
517 DEFINE_SAW (int16, 32767.0);
518 DEFINE_SAW (int32, 2147483647.0);
519 DEFINE_SAW (float, 1.0);
520 DEFINE_SAW (double, 1.0);
522 static const ProcessFunc saw_funcs[] = {
523 (ProcessFunc) gst_audio_test_src_create_saw_int16,
524 (ProcessFunc) gst_audio_test_src_create_saw_int32,
525 (ProcessFunc) gst_audio_test_src_create_saw_float,
526 (ProcessFunc) gst_audio_test_src_create_saw_double
529 #define DEFINE_TRIANGLE(type,scale) \
531 gst_audio_test_src_create_triangle_##type (GstAudioTestSrc * src, g##type * samples) \
536 step = M_PI_M2 * src->freq / src->samplerate; \
537 amp = (src->volume * scale) / G_PI_2; \
540 while (i < (src->generate_samples_per_buffer * src->channels)) { \
541 src->accumulator += step; \
542 if (src->accumulator >= M_PI_M2) \
543 src->accumulator -= M_PI_M2; \
545 if (src->accumulator < (G_PI_2)) { \
546 for (c = 0; c < src->channels; ++c) \
547 samples[i++] = (g##type) (src->accumulator * amp); \
548 } else if (src->accumulator < (G_PI * 1.5)) { \
549 for (c = 0; c < src->channels; ++c) \
550 samples[i++] = (g##type) ((src->accumulator - G_PI) * -amp); \
552 for (c = 0; c < src->channels; ++c) \
553 samples[i++] = (g##type) ((M_PI_M2 - src->accumulator) * -amp); \
558 DEFINE_TRIANGLE (int16, 32767.0);
559 DEFINE_TRIANGLE (int32, 2147483647.0);
560 DEFINE_TRIANGLE (float, 1.0);
561 DEFINE_TRIANGLE (double, 1.0);
563 static const ProcessFunc triangle_funcs[] = {
564 (ProcessFunc) gst_audio_test_src_create_triangle_int16,
565 (ProcessFunc) gst_audio_test_src_create_triangle_int32,
566 (ProcessFunc) gst_audio_test_src_create_triangle_float,
567 (ProcessFunc) gst_audio_test_src_create_triangle_double
570 #define DEFINE_SILENCE(type) \
572 gst_audio_test_src_create_silence_##type (GstAudioTestSrc * src, g##type * samples) \
574 memset (samples, 0, src->generate_samples_per_buffer * sizeof (g##type) * src->channels); \
577 DEFINE_SILENCE (int16);
578 DEFINE_SILENCE (int32);
579 DEFINE_SILENCE (float);
580 DEFINE_SILENCE (double);
582 static const ProcessFunc silence_funcs[] = {
583 (ProcessFunc) gst_audio_test_src_create_silence_int16,
584 (ProcessFunc) gst_audio_test_src_create_silence_int32,
585 (ProcessFunc) gst_audio_test_src_create_silence_float,
586 (ProcessFunc) gst_audio_test_src_create_silence_double
589 #define DEFINE_WHITE_NOISE(type,scale) \
591 gst_audio_test_src_create_white_noise_##type (GstAudioTestSrc * src, g##type * samples) \
594 gdouble amp = (src->volume * scale); \
597 while (i < (src->generate_samples_per_buffer * src->channels)) { \
598 for (c = 0; c < src->channels; ++c) \
599 samples[i++] = (g##type) (amp * g_rand_double_range (src->gen, -1.0, 1.0)); \
603 DEFINE_WHITE_NOISE (int16, 32767.0);
604 DEFINE_WHITE_NOISE (int32, 2147483647.0);
605 DEFINE_WHITE_NOISE (float, 1.0);
606 DEFINE_WHITE_NOISE (double, 1.0);
608 static const ProcessFunc white_noise_funcs[] = {
609 (ProcessFunc) gst_audio_test_src_create_white_noise_int16,
610 (ProcessFunc) gst_audio_test_src_create_white_noise_int32,
611 (ProcessFunc) gst_audio_test_src_create_white_noise_float,
612 (ProcessFunc) gst_audio_test_src_create_white_noise_double
615 /* pink noise calculation is based on
616 * http://www.firstpr.com.au/dsp/pink-noise/phil_burk_19990905_patest_pink.c
617 * which has been released under public domain
621 gst_audio_test_src_init_pink_noise (GstAudioTestSrc * src)
624 gint num_rows = 12; /* arbitrary: 1 .. PINK_MAX_RANDOM_ROWS */
628 src->pink.index_mask = (1 << num_rows) - 1;
629 /* calculate maximum possible signed random value.
630 * Extra 1 for white noise always added. */
631 pmax = (num_rows + 1) * (1 << (PINK_RANDOM_BITS - 1));
632 src->pink.scalar = 1.0f / pmax;
633 /* Initialize rows. */
634 for (i = 0; i < num_rows; i++)
635 src->pink.rows[i] = 0;
636 src->pink.running_sum = 0;
639 /* Generate Pink noise values between -1.0 and +1.0 */
641 gst_audio_test_src_generate_pink_noise_value (GstAudioTestSrc * src)
643 GstPinkNoise *pink = &src->pink;
647 /* Increment and mask index. */
648 pink->index = (pink->index + 1) & pink->index_mask;
650 /* If index is zero, don't update any random values. */
651 if (pink->index != 0) {
652 /* Determine how many trailing zeros in PinkIndex. */
653 /* This algorithm will hang if n==0 so test first. */
655 gint n = pink->index;
657 while ((n & 1) == 0) {
662 /* Replace the indexed ROWS random value.
663 * Subtract and add back to RunningSum instead of adding all the random
664 * values together. Only one changes each time.
666 pink->running_sum -= pink->rows[num_zeros];
667 new_random = 32768.0 - (65536.0 * (gulong) g_rand_int (src->gen)
668 / (G_MAXUINT32 + 1.0));
669 pink->running_sum += new_random;
670 pink->rows[num_zeros] = new_random;
673 /* Add extra white noise value. */
674 new_random = 32768.0 - (65536.0 * (gulong) g_rand_int (src->gen)
675 / (G_MAXUINT32 + 1.0));
676 sum = pink->running_sum + new_random;
678 /* Scale to range of -1.0 to 0.9999. */
679 return (pink->scalar * sum);
682 #define DEFINE_PINK(type, scale) \
684 gst_audio_test_src_create_pink_noise_##type (GstAudioTestSrc * src, g##type * samples) \
689 amp = src->volume * scale; \
692 while (i < (src->generate_samples_per_buffer * src->channels)) { \
693 for (c = 0; c < src->channels; ++c) { \
695 (g##type) (gst_audio_test_src_generate_pink_noise_value (src) * \
701 DEFINE_PINK (int16, 32767.0);
702 DEFINE_PINK (int32, 2147483647.0);
703 DEFINE_PINK (float, 1.0);
704 DEFINE_PINK (double, 1.0);
706 static const ProcessFunc pink_noise_funcs[] = {
707 (ProcessFunc) gst_audio_test_src_create_pink_noise_int16,
708 (ProcessFunc) gst_audio_test_src_create_pink_noise_int32,
709 (ProcessFunc) gst_audio_test_src_create_pink_noise_float,
710 (ProcessFunc) gst_audio_test_src_create_pink_noise_double
714 gst_audio_test_src_init_sine_table (GstAudioTestSrc * src)
718 gdouble step = M_PI_M2 / 1024.0;
719 gdouble amp = src->volume;
721 for (i = 0; i < 1024; i++) {
722 src->wave_table[i] = sin (ang) * amp;
727 #define DEFINE_SINE_TABLE(type,scale) \
729 gst_audio_test_src_create_sine_table_##type (GstAudioTestSrc * src, g##type * samples) \
734 step = M_PI_M2 * src->freq / src->samplerate; \
735 scl = 1024.0 / M_PI_M2; \
738 while (i < (src->generate_samples_per_buffer * src->channels)) { \
739 src->accumulator += step; \
740 if (src->accumulator >= M_PI_M2) \
741 src->accumulator -= M_PI_M2; \
743 for (c = 0; c < src->channels; ++c) \
744 samples[i++] = (g##type) scale * src->wave_table[(gint) (src->accumulator * scl)]; \
748 DEFINE_SINE_TABLE (int16, 32767.0);
749 DEFINE_SINE_TABLE (int32, 2147483647.0);
750 DEFINE_SINE_TABLE (float, 1.0);
751 DEFINE_SINE_TABLE (double, 1.0);
753 static const ProcessFunc sine_table_funcs[] = {
754 (ProcessFunc) gst_audio_test_src_create_sine_table_int16,
755 (ProcessFunc) gst_audio_test_src_create_sine_table_int32,
756 (ProcessFunc) gst_audio_test_src_create_sine_table_float,
757 (ProcessFunc) gst_audio_test_src_create_sine_table_double
760 #define DEFINE_TICKS(type,scale) \
762 gst_audio_test_src_create_tick_##type (GstAudioTestSrc * src, g##type * samples) \
767 step = M_PI_M2 * src->freq / src->samplerate; \
768 scl = 1024.0 / M_PI_M2; \
770 for (i = 0; i < src->generate_samples_per_buffer; i++) { \
771 src->accumulator += step; \
772 if (src->accumulator >= M_PI_M2) \
773 src->accumulator -= M_PI_M2; \
775 if ((src->next_sample + i)%src->samplerate < 1600) { \
776 for (c = 0; c < src->channels; ++c) \
777 samples[(i * src->channels) + c] = (g##type) scale * src->wave_table[(gint) (src->accumulator * scl)]; \
779 for (c = 0; c < src->channels; ++c) \
780 samples[(i * src->channels) + c] = 0; \
785 DEFINE_TICKS (int16, 32767.0);
786 DEFINE_TICKS (int32, 2147483647.0);
787 DEFINE_TICKS (float, 1.0);
788 DEFINE_TICKS (double, 1.0);
790 static const ProcessFunc tick_funcs[] = {
791 (ProcessFunc) gst_audio_test_src_create_tick_int16,
792 (ProcessFunc) gst_audio_test_src_create_tick_int32,
793 (ProcessFunc) gst_audio_test_src_create_tick_float,
794 (ProcessFunc) gst_audio_test_src_create_tick_double
797 /* Gaussian white noise using Box-Muller algorithm. unit variance
798 * normally-distributed random numbers are generated in pairs as the real
799 * and imaginary parts of a compex random variable with
800 * uniformly-distributed argument and \chi^{2}-distributed modulus.
803 #define DEFINE_GAUSSIAN_WHITE_NOISE(type,scale) \
805 gst_audio_test_src_create_gaussian_white_noise_##type (GstAudioTestSrc * src, g##type * samples) \
808 gdouble amp = (src->volume * scale); \
810 for (i = 0; i < src->generate_samples_per_buffer * src->channels; ) { \
811 for (c = 0; c < src->channels; ++c) { \
812 gdouble mag = sqrt (-2 * log (1.0 - g_rand_double (src->gen))); \
813 gdouble phs = g_rand_double_range (src->gen, 0.0, M_PI_M2); \
815 samples[i++] = (g##type) (amp * mag * cos (phs)); \
816 if (++c >= src->channels) \
818 samples[i++] = (g##type) (amp * mag * sin (phs)); \
823 DEFINE_GAUSSIAN_WHITE_NOISE (int16, 32767.0);
824 DEFINE_GAUSSIAN_WHITE_NOISE (int32, 2147483647.0);
825 DEFINE_GAUSSIAN_WHITE_NOISE (float, 1.0);
826 DEFINE_GAUSSIAN_WHITE_NOISE (double, 1.0);
828 static const ProcessFunc gaussian_white_noise_funcs[] = {
829 (ProcessFunc) gst_audio_test_src_create_gaussian_white_noise_int16,
830 (ProcessFunc) gst_audio_test_src_create_gaussian_white_noise_int32,
831 (ProcessFunc) gst_audio_test_src_create_gaussian_white_noise_float,
832 (ProcessFunc) gst_audio_test_src_create_gaussian_white_noise_double
835 /* Brownian (Red) Noise: noise where the power density decreases by 6 dB per
836 * octave with increasing frequency
838 * taken from http://vellocet.com/dsp/noise/VRand.html
839 * by Andrew Simper of Vellocet (andy@vellocet.com)
842 #define DEFINE_RED_NOISE(type,scale) \
844 gst_audio_test_src_create_red_noise_##type (GstAudioTestSrc * src, g##type * samples) \
847 gdouble amp = (src->volume * scale); \
848 gdouble state = src->red.state; \
850 for (i = 0; i < src->generate_samples_per_buffer * src->channels; ) { \
851 for (c = 0; c < src->channels; ++c) { \
853 gdouble r = g_rand_double_range (src->gen, -1.0, 1.0); \
855 if (state < -8.0f || state > 8.0f) state -= r; \
858 samples[i++] = (g##type) (amp * state * 0.0625f); /* /16.0 */ \
861 src->red.state = state; \
864 DEFINE_RED_NOISE (int16, 32767.0);
865 DEFINE_RED_NOISE (int32, 2147483647.0);
866 DEFINE_RED_NOISE (float, 1.0);
867 DEFINE_RED_NOISE (double, 1.0);
869 static const ProcessFunc red_noise_funcs[] = {
870 (ProcessFunc) gst_audio_test_src_create_red_noise_int16,
871 (ProcessFunc) gst_audio_test_src_create_red_noise_int32,
872 (ProcessFunc) gst_audio_test_src_create_red_noise_float,
873 (ProcessFunc) gst_audio_test_src_create_red_noise_double
876 /* Blue Noise: apply spectral inversion to pink noise */
878 #define DEFINE_BLUE_NOISE(type) \
880 gst_audio_test_src_create_blue_noise_##type (GstAudioTestSrc * src, g##type * samples) \
883 static gdouble flip=1.0; \
885 gst_audio_test_src_create_pink_noise_##type (src, samples); \
886 for (i = 0; i < src->generate_samples_per_buffer * src->channels; ) { \
887 for (c = 0; c < src->channels; ++c) { \
888 samples[i++] *= flip; \
894 DEFINE_BLUE_NOISE (int16);
895 DEFINE_BLUE_NOISE (int32);
896 DEFINE_BLUE_NOISE (float);
897 DEFINE_BLUE_NOISE (double);
899 static const ProcessFunc blue_noise_funcs[] = {
900 (ProcessFunc) gst_audio_test_src_create_blue_noise_int16,
901 (ProcessFunc) gst_audio_test_src_create_blue_noise_int32,
902 (ProcessFunc) gst_audio_test_src_create_blue_noise_float,
903 (ProcessFunc) gst_audio_test_src_create_blue_noise_double
907 /* Violet Noise: apply spectral inversion to red noise */
909 #define DEFINE_VIOLET_NOISE(type) \
911 gst_audio_test_src_create_violet_noise_##type (GstAudioTestSrc * src, g##type * samples) \
914 static gdouble flip=1.0; \
916 gst_audio_test_src_create_red_noise_##type (src, samples); \
917 for (i = 0; i < src->generate_samples_per_buffer * src->channels; ) { \
918 for (c = 0; c < src->channels; ++c) { \
919 samples[i++] *= flip; \
925 DEFINE_VIOLET_NOISE (int16);
926 DEFINE_VIOLET_NOISE (int32);
927 DEFINE_VIOLET_NOISE (float);
928 DEFINE_VIOLET_NOISE (double);
930 static const ProcessFunc violet_noise_funcs[] = {
931 (ProcessFunc) gst_audio_test_src_create_violet_noise_int16,
932 (ProcessFunc) gst_audio_test_src_create_violet_noise_int32,
933 (ProcessFunc) gst_audio_test_src_create_violet_noise_float,
934 (ProcessFunc) gst_audio_test_src_create_violet_noise_double
939 * gst_audio_test_src_change_wave:
940 * Assign function pointer of wave genrator.
943 gst_audio_test_src_change_wave (GstAudioTestSrc * src)
945 if (src->format == -1) {
951 case GST_AUDIO_TEST_SRC_WAVE_SINE:
952 src->process = sine_funcs[src->format];
954 case GST_AUDIO_TEST_SRC_WAVE_SQUARE:
955 src->process = square_funcs[src->format];
957 case GST_AUDIO_TEST_SRC_WAVE_SAW:
958 src->process = saw_funcs[src->format];
960 case GST_AUDIO_TEST_SRC_WAVE_TRIANGLE:
961 src->process = triangle_funcs[src->format];
963 case GST_AUDIO_TEST_SRC_WAVE_SILENCE:
964 src->process = silence_funcs[src->format];
966 case GST_AUDIO_TEST_SRC_WAVE_WHITE_NOISE:
968 src->gen = g_rand_new ();
969 src->process = white_noise_funcs[src->format];
971 case GST_AUDIO_TEST_SRC_WAVE_PINK_NOISE:
973 src->gen = g_rand_new ();
974 gst_audio_test_src_init_pink_noise (src);
975 src->process = pink_noise_funcs[src->format];
977 case GST_AUDIO_TEST_SRC_WAVE_SINE_TAB:
978 gst_audio_test_src_init_sine_table (src);
979 src->process = sine_table_funcs[src->format];
981 case GST_AUDIO_TEST_SRC_WAVE_TICKS:
982 gst_audio_test_src_init_sine_table (src);
983 src->process = tick_funcs[src->format];
985 case GST_AUDIO_TEST_SRC_WAVE_GAUSSIAN_WHITE_NOISE:
987 src->gen = g_rand_new ();
988 src->process = gaussian_white_noise_funcs[src->format];
990 case GST_AUDIO_TEST_SRC_WAVE_RED_NOISE:
992 src->gen = g_rand_new ();
993 src->red.state = 0.0;
994 src->process = red_noise_funcs[src->format];
996 case GST_AUDIO_TEST_SRC_WAVE_BLUE_NOISE:
998 src->gen = g_rand_new ();
999 gst_audio_test_src_init_pink_noise (src);
1000 src->process = blue_noise_funcs[src->format];
1002 case GST_AUDIO_TEST_SRC_WAVE_VIOLET_NOISE:
1004 src->gen = g_rand_new ();
1005 src->red.state = 0.0;
1006 src->process = violet_noise_funcs[src->format];
1009 GST_ERROR ("invalid wave-form");
1015 * gst_audio_test_src_change_volume:
1016 * Recalc wave tables for precalculated waves.
1019 gst_audio_test_src_change_volume (GstAudioTestSrc * src)
1021 switch (src->wave) {
1022 case GST_AUDIO_TEST_SRC_WAVE_SINE_TAB:
1023 gst_audio_test_src_init_sine_table (src);
1031 gst_audio_test_src_get_times (GstBaseSrc * basesrc, GstBuffer * buffer,
1032 GstClockTime * start, GstClockTime * end)
1034 /* for live sources, sync on the timestamp of the buffer */
1035 if (gst_base_src_is_live (basesrc)) {
1036 GstClockTime timestamp = GST_BUFFER_TIMESTAMP (buffer);
1038 if (GST_CLOCK_TIME_IS_VALID (timestamp)) {
1039 /* get duration to calculate end time */
1040 GstClockTime duration = GST_BUFFER_DURATION (buffer);
1042 if (GST_CLOCK_TIME_IS_VALID (duration)) {
1043 *end = timestamp + duration;
1054 gst_audio_test_src_start (GstBaseSrc * basesrc)
1056 GstAudioTestSrc *src = GST_AUDIO_TEST_SRC (basesrc);
1058 src->next_sample = 0;
1061 src->check_seek_stop = FALSE;
1062 src->eos_reached = FALSE;
1063 src->tags_pushed = FALSE;
1064 src->accumulator = 0;
1070 gst_audio_test_src_stop (GstBaseSrc * basesrc)
1075 /* seek to time, will be called when we operate in push mode. In pull mode we
1076 * get the requested byte offset. */
1078 gst_audio_test_src_do_seek (GstBaseSrc * basesrc, GstSegment * segment)
1080 GstAudioTestSrc *src = GST_AUDIO_TEST_SRC (basesrc);
1083 GST_DEBUG_OBJECT (src, "seeking %" GST_SEGMENT_FORMAT, segment);
1085 time = segment->last_stop;
1086 src->reverse = (segment->rate < 0.0);
1088 /* now move to the time indicated */
1090 gst_util_uint64_scale_int (time, src->samplerate, GST_SECOND);
1091 src->next_byte = src->next_sample * src->sample_size * src->channels;
1093 gst_util_uint64_scale_int (src->next_sample, GST_SECOND, src->samplerate);
1095 GST_DEBUG_OBJECT (src, "seeking next_sample=%" G_GINT64_FORMAT
1096 " next_time=%" GST_TIME_FORMAT, src->next_sample,
1097 GST_TIME_ARGS (src->next_time));
1099 g_assert (src->next_time <= time);
1101 if (!src->reverse) {
1102 if (GST_CLOCK_TIME_IS_VALID (segment->start)) {
1103 segment->time = segment->start;
1106 if (GST_CLOCK_TIME_IS_VALID (segment->stop)) {
1107 segment->time = segment->stop;
1111 if (GST_CLOCK_TIME_IS_VALID (segment->stop)) {
1112 time = segment->stop;
1113 src->sample_stop = gst_util_uint64_scale_int (time, src->samplerate,
1115 src->check_seek_stop = TRUE;
1117 src->check_seek_stop = FALSE;
1119 src->eos_reached = FALSE;
1125 gst_audio_test_src_is_seekable (GstBaseSrc * basesrc)
1127 /* we're seekable... */
1132 gst_audio_test_src_check_get_range (GstBaseSrc * basesrc)
1134 GstAudioTestSrc *src;
1136 src = GST_AUDIO_TEST_SRC (basesrc);
1138 /* if we can operate in pull mode */
1139 return src->can_activate_pull;
1142 static GstFlowReturn
1143 gst_audio_test_src_create (GstBaseSrc * basesrc, guint64 offset,
1144 guint length, GstBuffer ** buffer)
1147 GstAudioTestSrc *src;
1149 GstClockTime next_time;
1150 gint64 next_sample, next_byte;
1151 gint bytes, samples;
1152 GstElementClass *eclass;
1154 src = GST_AUDIO_TEST_SRC (basesrc);
1156 /* example for tagging generated data */
1157 if (!src->tags_pushed) {
1158 GstTagList *taglist;
1160 taglist = gst_tag_list_new ();
1162 gst_tag_list_add (taglist, GST_TAG_MERGE_APPEND,
1163 GST_TAG_DESCRIPTION, "audiotest wave", NULL);
1165 eclass = GST_ELEMENT_CLASS (parent_class);
1166 if (eclass->send_event)
1167 eclass->send_event (GST_ELEMENT_CAST (basesrc),
1168 gst_event_new_tag (taglist));
1170 gst_tag_list_free (taglist);
1171 src->tags_pushed = TRUE;
1174 if (src->eos_reached) {
1175 GST_INFO_OBJECT (src, "eos");
1176 return GST_FLOW_UNEXPECTED;
1179 /* if no length was given, use our default length in samples otherwise convert
1180 * the length in bytes to samples. */
1182 samples = src->samples_per_buffer;
1184 samples = length / (src->sample_size * src->channels);
1186 /* if no offset was given, use our next logical byte */
1188 offset = src->next_byte;
1190 /* now see if we are at the byteoffset we think we are */
1191 if (offset != src->next_byte) {
1192 GST_DEBUG_OBJECT (src, "seek to new offset %" G_GUINT64_FORMAT, offset);
1193 /* we have a discont in the expected sample offset, do a 'seek' */
1194 src->next_sample = offset / (src->sample_size * src->channels);
1196 gst_util_uint64_scale_int (src->next_sample, GST_SECOND,
1198 src->next_byte = offset;
1202 if (src->check_seek_stop &&
1203 (src->sample_stop > src->next_sample) &&
1204 (src->sample_stop < src->next_sample + samples)
1206 /* calculate only partial buffer */
1207 src->generate_samples_per_buffer = src->sample_stop - src->next_sample;
1208 next_sample = src->sample_stop;
1209 src->eos_reached = TRUE;
1211 /* calculate full buffer */
1212 src->generate_samples_per_buffer = samples;
1213 next_sample = src->next_sample + (src->reverse ? (-samples) : samples);
1216 bytes = src->generate_samples_per_buffer * src->sample_size * src->channels;
1218 if ((res = gst_pad_alloc_buffer (basesrc->srcpad, src->next_sample,
1219 bytes, GST_PAD_CAPS (basesrc->srcpad), &buf)) != GST_FLOW_OK) {
1223 next_byte = src->next_byte + (src->reverse ? (-bytes) : bytes);
1224 next_time = gst_util_uint64_scale_int (next_sample, GST_SECOND,
1227 GST_LOG_OBJECT (src, "samplerate %d", src->samplerate);
1228 GST_LOG_OBJECT (src, "next_sample %" G_GINT64_FORMAT ", ts %" GST_TIME_FORMAT,
1229 next_sample, GST_TIME_ARGS (next_time));
1231 GST_BUFFER_OFFSET (buf) = src->next_sample;
1232 GST_BUFFER_OFFSET_END (buf) = next_sample;
1233 if (!src->reverse) {
1234 GST_BUFFER_TIMESTAMP (buf) = src->timestamp_offset + src->next_time;
1235 GST_BUFFER_DURATION (buf) = next_time - src->next_time;
1237 GST_BUFFER_TIMESTAMP (buf) = src->timestamp_offset + next_time;
1238 GST_BUFFER_DURATION (buf) = src->next_time - next_time;
1241 gst_object_sync_values (G_OBJECT (src), GST_BUFFER_TIMESTAMP (buf));
1243 src->next_time = next_time;
1244 src->next_sample = next_sample;
1245 src->next_byte = next_byte;
1247 GST_LOG_OBJECT (src, "generating %u samples at ts %" GST_TIME_FORMAT,
1248 src->generate_samples_per_buffer,
1249 GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buf)));
1251 src->process (src, GST_BUFFER_DATA (buf));
1253 if (G_UNLIKELY ((src->wave == GST_AUDIO_TEST_SRC_WAVE_SILENCE)
1254 || (src->volume == 0.0))) {
1255 GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_GAP);
1264 gst_audio_test_src_set_property (GObject * object, guint prop_id,
1265 const GValue * value, GParamSpec * pspec)
1267 GstAudioTestSrc *src = GST_AUDIO_TEST_SRC (object);
1270 case PROP_SAMPLES_PER_BUFFER:
1271 src->samples_per_buffer = g_value_get_int (value);
1274 src->wave = g_value_get_enum (value);
1275 gst_audio_test_src_change_wave (src);
1278 src->freq = g_value_get_double (value);
1281 src->volume = g_value_get_double (value);
1282 gst_audio_test_src_change_volume (src);
1285 gst_base_src_set_live (GST_BASE_SRC (src), g_value_get_boolean (value));
1287 case PROP_TIMESTAMP_OFFSET:
1288 src->timestamp_offset = g_value_get_int64 (value);
1290 case PROP_CAN_ACTIVATE_PUSH:
1291 GST_BASE_SRC (src)->can_activate_push = g_value_get_boolean (value);
1293 case PROP_CAN_ACTIVATE_PULL:
1294 src->can_activate_pull = g_value_get_boolean (value);
1297 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1303 gst_audio_test_src_get_property (GObject * object, guint prop_id,
1304 GValue * value, GParamSpec * pspec)
1306 GstAudioTestSrc *src = GST_AUDIO_TEST_SRC (object);
1309 case PROP_SAMPLES_PER_BUFFER:
1310 g_value_set_int (value, src->samples_per_buffer);
1313 g_value_set_enum (value, src->wave);
1316 g_value_set_double (value, src->freq);
1319 g_value_set_double (value, src->volume);
1322 g_value_set_boolean (value, gst_base_src_is_live (GST_BASE_SRC (src)));
1324 case PROP_TIMESTAMP_OFFSET:
1325 g_value_set_int64 (value, src->timestamp_offset);
1327 case PROP_CAN_ACTIVATE_PUSH:
1328 g_value_set_boolean (value, GST_BASE_SRC (src)->can_activate_push);
1330 case PROP_CAN_ACTIVATE_PULL:
1331 g_value_set_boolean (value, src->can_activate_pull);
1334 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1340 plugin_init (GstPlugin * plugin)
1342 /* initialize gst controller library */
1343 gst_controller_init (NULL, NULL);
1345 GST_DEBUG_CATEGORY_INIT (audio_test_src_debug, "audiotestsrc", 0,
1346 "Audio Test Source");
1348 return gst_element_register (plugin, "audiotestsrc",
1349 GST_RANK_NONE, GST_TYPE_AUDIO_TEST_SRC);
1352 GST_PLUGIN_DEFINE (GST_VERSION_MAJOR,
1355 "Creates audio test signals of given frequency and volume",
1356 plugin_init, VERSION, "LGPL", GST_PACKAGE_NAME, GST_PACKAGE_ORIGIN);