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 ! videoconvert ! 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,
79 #if G_BYTE_ORDER == G_LITTLE_ENDIAN
80 #define FORMAT_STR "{ S16LE, S32LE, F32LE, F64LE }"
81 #define DEFAULT_FORMAT_STR "S16LE"
83 #define FORMAT_STR "{ S16BE, S32BE, F32BE, F64BE }"
84 #define DEFAULT_FORMAT_STR "S16BE"
87 static GstStaticPadTemplate gst_audio_test_src_src_template =
88 GST_STATIC_PAD_TEMPLATE ("src",
91 GST_STATIC_CAPS ("audio/x-raw, "
92 "format = (string) " FORMAT_STR ", "
93 "rate = (int) [ 1, MAX ], " "channels = (int) [ 1, 2 ]")
96 #define gst_audio_test_src_parent_class parent_class
97 G_DEFINE_TYPE (GstAudioTestSrc, gst_audio_test_src, GST_TYPE_BASE_SRC);
99 #define GST_TYPE_AUDIO_TEST_SRC_WAVE (gst_audiostestsrc_wave_get_type())
101 gst_audiostestsrc_wave_get_type (void)
103 static GType audiostestsrc_wave_type = 0;
104 static const GEnumValue audiostestsrc_waves[] = {
105 {GST_AUDIO_TEST_SRC_WAVE_SINE, "Sine", "sine"},
106 {GST_AUDIO_TEST_SRC_WAVE_SQUARE, "Square", "square"},
107 {GST_AUDIO_TEST_SRC_WAVE_SAW, "Saw", "saw"},
108 {GST_AUDIO_TEST_SRC_WAVE_TRIANGLE, "Triangle", "triangle"},
109 {GST_AUDIO_TEST_SRC_WAVE_SILENCE, "Silence", "silence"},
110 {GST_AUDIO_TEST_SRC_WAVE_WHITE_NOISE, "White uniform noise", "white-noise"},
111 {GST_AUDIO_TEST_SRC_WAVE_PINK_NOISE, "Pink noise", "pink-noise"},
112 {GST_AUDIO_TEST_SRC_WAVE_SINE_TAB, "Sine table", "sine-table"},
113 {GST_AUDIO_TEST_SRC_WAVE_TICKS, "Periodic Ticks", "ticks"},
114 {GST_AUDIO_TEST_SRC_WAVE_GAUSSIAN_WHITE_NOISE, "White Gaussian noise",
116 {GST_AUDIO_TEST_SRC_WAVE_RED_NOISE, "Red (brownian) noise", "red-noise"},
117 {GST_AUDIO_TEST_SRC_WAVE_BLUE_NOISE, "Blue noise", "blue-noise"},
118 {GST_AUDIO_TEST_SRC_WAVE_VIOLET_NOISE, "Violet noise", "violet-noise"},
122 if (G_UNLIKELY (audiostestsrc_wave_type == 0)) {
123 audiostestsrc_wave_type = g_enum_register_static ("GstAudioTestSrcWave",
124 audiostestsrc_waves);
126 return audiostestsrc_wave_type;
129 static void gst_audio_test_src_finalize (GObject * object);
131 static void gst_audio_test_src_set_property (GObject * object,
132 guint prop_id, const GValue * value, GParamSpec * pspec);
133 static void gst_audio_test_src_get_property (GObject * object,
134 guint prop_id, GValue * value, GParamSpec * pspec);
136 static gboolean gst_audio_test_src_setcaps (GstBaseSrc * basesrc,
138 static void gst_audio_test_src_fixate (GstBaseSrc * bsrc, GstCaps * caps);
140 static gboolean gst_audio_test_src_is_seekable (GstBaseSrc * basesrc);
141 static gboolean gst_audio_test_src_do_seek (GstBaseSrc * basesrc,
142 GstSegment * segment);
143 static gboolean gst_audio_test_src_query (GstBaseSrc * basesrc,
146 static void gst_audio_test_src_change_wave (GstAudioTestSrc * src);
148 static void gst_audio_test_src_get_times (GstBaseSrc * basesrc,
149 GstBuffer * buffer, GstClockTime * start, GstClockTime * end);
150 static gboolean gst_audio_test_src_start (GstBaseSrc * basesrc);
151 static gboolean gst_audio_test_src_stop (GstBaseSrc * basesrc);
152 static GstFlowReturn gst_audio_test_src_fill (GstBaseSrc * basesrc,
153 guint64 offset, guint length, GstBuffer * buffer);
156 gst_audio_test_src_class_init (GstAudioTestSrcClass * klass)
158 GObjectClass *gobject_class;
159 GstElementClass *gstelement_class;
160 GstBaseSrcClass *gstbasesrc_class;
162 gobject_class = (GObjectClass *) klass;
163 gstelement_class = (GstElementClass *) klass;
164 gstbasesrc_class = (GstBaseSrcClass *) klass;
166 gobject_class->set_property = gst_audio_test_src_set_property;
167 gobject_class->get_property = gst_audio_test_src_get_property;
168 gobject_class->finalize = gst_audio_test_src_finalize;
170 g_object_class_install_property (gobject_class, PROP_SAMPLES_PER_BUFFER,
171 g_param_spec_int ("samplesperbuffer", "Samples per buffer",
172 "Number of samples in each outgoing buffer",
173 1, G_MAXINT, DEFAULT_SAMPLES_PER_BUFFER,
174 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
175 g_object_class_install_property (gobject_class, PROP_WAVE,
176 g_param_spec_enum ("wave", "Waveform", "Oscillator waveform",
177 GST_TYPE_AUDIO_TEST_SRC_WAVE, GST_AUDIO_TEST_SRC_WAVE_SINE,
178 G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE | G_PARAM_STATIC_STRINGS));
179 g_object_class_install_property (gobject_class, PROP_FREQ,
180 g_param_spec_double ("freq", "Frequency", "Frequency of test signal",
181 0.0, 20000.0, DEFAULT_FREQ,
182 G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE | G_PARAM_STATIC_STRINGS));
183 g_object_class_install_property (gobject_class, PROP_VOLUME,
184 g_param_spec_double ("volume", "Volume", "Volume of test signal", 0.0,
186 G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE | G_PARAM_STATIC_STRINGS));
187 g_object_class_install_property (gobject_class, PROP_IS_LIVE,
188 g_param_spec_boolean ("is-live", "Is Live",
189 "Whether to act as a live source", DEFAULT_IS_LIVE,
190 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
191 g_object_class_install_property (G_OBJECT_CLASS (klass),
192 PROP_TIMESTAMP_OFFSET, g_param_spec_int64 ("timestamp-offset",
194 "An offset added to timestamps set on buffers (in ns)", G_MININT64,
195 G_MAXINT64, DEFAULT_TIMESTAMP_OFFSET,
196 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
197 g_object_class_install_property (gobject_class, PROP_CAN_ACTIVATE_PUSH,
198 g_param_spec_boolean ("can-activate-push", "Can activate push",
199 "Can activate in push mode", DEFAULT_CAN_ACTIVATE_PUSH,
200 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
201 g_object_class_install_property (gobject_class, PROP_CAN_ACTIVATE_PULL,
202 g_param_spec_boolean ("can-activate-pull", "Can activate pull",
203 "Can activate in pull mode", DEFAULT_CAN_ACTIVATE_PULL,
204 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
206 gst_element_class_add_pad_template (gstelement_class,
207 gst_static_pad_template_get (&gst_audio_test_src_src_template));
208 gst_element_class_set_details_simple (gstelement_class,
209 "Audio test source", "Source/Audio",
210 "Creates audio test signals of given frequency and volume",
211 "Stefan Kost <ensonic@users.sf.net>");
213 gstbasesrc_class->set_caps = GST_DEBUG_FUNCPTR (gst_audio_test_src_setcaps);
214 gstbasesrc_class->fixate = GST_DEBUG_FUNCPTR (gst_audio_test_src_fixate);
215 gstbasesrc_class->is_seekable =
216 GST_DEBUG_FUNCPTR (gst_audio_test_src_is_seekable);
217 gstbasesrc_class->do_seek = GST_DEBUG_FUNCPTR (gst_audio_test_src_do_seek);
218 gstbasesrc_class->query = GST_DEBUG_FUNCPTR (gst_audio_test_src_query);
219 gstbasesrc_class->get_times =
220 GST_DEBUG_FUNCPTR (gst_audio_test_src_get_times);
221 gstbasesrc_class->start = GST_DEBUG_FUNCPTR (gst_audio_test_src_start);
222 gstbasesrc_class->stop = GST_DEBUG_FUNCPTR (gst_audio_test_src_stop);
223 gstbasesrc_class->fill = GST_DEBUG_FUNCPTR (gst_audio_test_src_fill);
227 gst_audio_test_src_init (GstAudioTestSrc * src)
229 src->volume = DEFAULT_VOLUME;
230 src->freq = DEFAULT_FREQ;
232 /* we operate in time */
233 gst_base_src_set_format (GST_BASE_SRC (src), GST_FORMAT_TIME);
234 gst_base_src_set_live (GST_BASE_SRC (src), DEFAULT_IS_LIVE);
236 src->samples_per_buffer = DEFAULT_SAMPLES_PER_BUFFER;
237 src->generate_samples_per_buffer = src->samples_per_buffer;
238 src->timestamp_offset = DEFAULT_TIMESTAMP_OFFSET;
239 src->can_activate_pull = DEFAULT_CAN_ACTIVATE_PULL;
243 src->wave = DEFAULT_WAVE;
244 gst_base_src_set_blocksize (GST_BASE_SRC (src), -1);
248 gst_audio_test_src_finalize (GObject * object)
250 GstAudioTestSrc *src = GST_AUDIO_TEST_SRC (object);
253 g_rand_free (src->gen);
256 G_OBJECT_CLASS (parent_class)->finalize (object);
260 gst_audio_test_src_fixate (GstBaseSrc * bsrc, GstCaps * caps)
262 GstAudioTestSrc *src = GST_AUDIO_TEST_SRC (bsrc);
263 GstStructure *structure;
265 structure = gst_caps_get_structure (caps, 0);
267 GST_DEBUG_OBJECT (src, "fixating samplerate to %d", GST_AUDIO_DEF_RATE);
269 gst_structure_fixate_field_nearest_int (structure, "rate",
272 gst_structure_fixate_field_string (structure, "format", DEFAULT_FORMAT_STR);
274 /* fixate to mono unless downstream requires stereo, for backwards compat */
275 gst_structure_fixate_field_nearest_int (structure, "channels", 1);
277 GST_BASE_SRC_CLASS (parent_class)->fixate (bsrc, caps);
281 gst_audio_test_src_setcaps (GstBaseSrc * basesrc, GstCaps * caps)
283 GstAudioTestSrc *src = GST_AUDIO_TEST_SRC (basesrc);
286 if (!gst_audio_info_from_caps (&info, caps))
289 GST_DEBUG_OBJECT (src, "negotiated to caps %" GST_PTR_FORMAT, caps);
293 gst_audio_test_src_change_wave (src);
300 GST_ERROR_OBJECT (basesrc, "received invalid caps");
306 gst_audio_test_src_query (GstBaseSrc * basesrc, GstQuery * query)
308 GstAudioTestSrc *src = GST_AUDIO_TEST_SRC (basesrc);
309 gboolean res = FALSE;
311 switch (GST_QUERY_TYPE (query)) {
312 case GST_QUERY_CONVERT:
314 GstFormat src_fmt, dest_fmt;
315 gint64 src_val, dest_val;
317 gst_query_parse_convert (query, &src_fmt, &src_val, &dest_fmt, &dest_val);
319 if (!gst_audio_info_convert (&src->info, src_fmt, src_val, dest_fmt,
323 gst_query_set_convert (query, src_fmt, src_val, dest_fmt, dest_val);
327 case GST_QUERY_SCHEDULING:
329 /* if we can operate in pull mode */
330 gst_query_set_scheduling (query, src->can_activate_pull, TRUE, FALSE, 1,
336 res = GST_BASE_SRC_CLASS (parent_class)->query (basesrc, query);
344 GST_DEBUG_OBJECT (src, "query failed");
349 #define DEFINE_SINE(type,scale) \
351 gst_audio_test_src_create_sine_##type (GstAudioTestSrc * src, g##type * samples) \
353 gint i, c, channels; \
356 channels = GST_AUDIO_INFO_CHANNELS (&src->info); \
357 step = M_PI_M2 * src->freq / GST_AUDIO_INFO_RATE (&src->info); \
358 amp = src->volume * scale; \
361 while (i < (src->generate_samples_per_buffer * channels)) { \
362 src->accumulator += step; \
363 if (src->accumulator >= M_PI_M2) \
364 src->accumulator -= M_PI_M2; \
366 for (c = 0; c < channels; ++c) { \
367 samples[i++] = (g##type) (sin (src->accumulator) * amp); \
372 DEFINE_SINE (int16, 32767.0);
373 DEFINE_SINE (int32, 2147483647.0);
374 DEFINE_SINE (float, 1.0);
375 DEFINE_SINE (double, 1.0);
377 static const ProcessFunc sine_funcs[] = {
378 (ProcessFunc) gst_audio_test_src_create_sine_int16,
379 (ProcessFunc) gst_audio_test_src_create_sine_int32,
380 (ProcessFunc) gst_audio_test_src_create_sine_float,
381 (ProcessFunc) gst_audio_test_src_create_sine_double
384 #define DEFINE_SQUARE(type,scale) \
386 gst_audio_test_src_create_square_##type (GstAudioTestSrc * src, g##type * samples) \
388 gint i, c, channels; \
391 channels = GST_AUDIO_INFO_CHANNELS (&src->info); \
392 step = M_PI_M2 * src->freq / GST_AUDIO_INFO_RATE (&src->info); \
393 amp = src->volume * scale; \
396 while (i < (src->generate_samples_per_buffer * channels)) { \
397 src->accumulator += step; \
398 if (src->accumulator >= M_PI_M2) \
399 src->accumulator -= M_PI_M2; \
401 for (c = 0; c < channels; ++c) { \
402 samples[i++] = (g##type) ((src->accumulator < G_PI) ? amp : -amp); \
407 DEFINE_SQUARE (int16, 32767.0);
408 DEFINE_SQUARE (int32, 2147483647.0);
409 DEFINE_SQUARE (float, 1.0);
410 DEFINE_SQUARE (double, 1.0);
412 static const ProcessFunc square_funcs[] = {
413 (ProcessFunc) gst_audio_test_src_create_square_int16,
414 (ProcessFunc) gst_audio_test_src_create_square_int32,
415 (ProcessFunc) gst_audio_test_src_create_square_float,
416 (ProcessFunc) gst_audio_test_src_create_square_double
419 #define DEFINE_SAW(type,scale) \
421 gst_audio_test_src_create_saw_##type (GstAudioTestSrc * src, g##type * samples) \
423 gint i, c, channels; \
426 channels = GST_AUDIO_INFO_CHANNELS (&src->info); \
427 step = M_PI_M2 * src->freq / GST_AUDIO_INFO_RATE (&src->info); \
428 amp = (src->volume * scale) / G_PI; \
431 while (i < (src->generate_samples_per_buffer * channels)) { \
432 src->accumulator += step; \
433 if (src->accumulator >= M_PI_M2) \
434 src->accumulator -= M_PI_M2; \
436 if (src->accumulator < G_PI) { \
437 for (c = 0; c < channels; ++c) \
438 samples[i++] = (g##type) (src->accumulator * amp); \
440 for (c = 0; c < channels; ++c) \
441 samples[i++] = (g##type) ((M_PI_M2 - src->accumulator) * -amp); \
446 DEFINE_SAW (int16, 32767.0);
447 DEFINE_SAW (int32, 2147483647.0);
448 DEFINE_SAW (float, 1.0);
449 DEFINE_SAW (double, 1.0);
451 static const ProcessFunc saw_funcs[] = {
452 (ProcessFunc) gst_audio_test_src_create_saw_int16,
453 (ProcessFunc) gst_audio_test_src_create_saw_int32,
454 (ProcessFunc) gst_audio_test_src_create_saw_float,
455 (ProcessFunc) gst_audio_test_src_create_saw_double
458 #define DEFINE_TRIANGLE(type,scale) \
460 gst_audio_test_src_create_triangle_##type (GstAudioTestSrc * src, g##type * samples) \
462 gint i, c, channels; \
465 channels = GST_AUDIO_INFO_CHANNELS (&src->info); \
466 step = M_PI_M2 * src->freq / GST_AUDIO_INFO_RATE (&src->info); \
467 amp = (src->volume * scale) / G_PI_2; \
470 while (i < (src->generate_samples_per_buffer * channels)) { \
471 src->accumulator += step; \
472 if (src->accumulator >= M_PI_M2) \
473 src->accumulator -= M_PI_M2; \
475 if (src->accumulator < (G_PI_2)) { \
476 for (c = 0; c < channels; ++c) \
477 samples[i++] = (g##type) (src->accumulator * amp); \
478 } else if (src->accumulator < (G_PI * 1.5)) { \
479 for (c = 0; c < channels; ++c) \
480 samples[i++] = (g##type) ((src->accumulator - G_PI) * -amp); \
482 for (c = 0; c < channels; ++c) \
483 samples[i++] = (g##type) ((M_PI_M2 - src->accumulator) * -amp); \
488 DEFINE_TRIANGLE (int16, 32767.0);
489 DEFINE_TRIANGLE (int32, 2147483647.0);
490 DEFINE_TRIANGLE (float, 1.0);
491 DEFINE_TRIANGLE (double, 1.0);
493 static const ProcessFunc triangle_funcs[] = {
494 (ProcessFunc) gst_audio_test_src_create_triangle_int16,
495 (ProcessFunc) gst_audio_test_src_create_triangle_int32,
496 (ProcessFunc) gst_audio_test_src_create_triangle_float,
497 (ProcessFunc) gst_audio_test_src_create_triangle_double
500 #define DEFINE_SILENCE(type) \
502 gst_audio_test_src_create_silence_##type (GstAudioTestSrc * src, g##type * samples) \
504 memset (samples, 0, src->generate_samples_per_buffer * sizeof (g##type) * src->info.channels); \
507 DEFINE_SILENCE (int16);
508 DEFINE_SILENCE (int32);
509 DEFINE_SILENCE (float);
510 DEFINE_SILENCE (double);
512 static const ProcessFunc silence_funcs[] = {
513 (ProcessFunc) gst_audio_test_src_create_silence_int16,
514 (ProcessFunc) gst_audio_test_src_create_silence_int32,
515 (ProcessFunc) gst_audio_test_src_create_silence_float,
516 (ProcessFunc) gst_audio_test_src_create_silence_double
519 #define DEFINE_WHITE_NOISE(type,scale) \
521 gst_audio_test_src_create_white_noise_##type (GstAudioTestSrc * src, g##type * samples) \
524 gdouble amp = (src->volume * scale); \
525 gint channels = GST_AUDIO_INFO_CHANNELS (&src->info); \
528 while (i < (src->generate_samples_per_buffer * channels)) { \
529 for (c = 0; c < channels; ++c) \
530 samples[i++] = (g##type) (amp * g_rand_double_range (src->gen, -1.0, 1.0)); \
534 DEFINE_WHITE_NOISE (int16, 32767.0);
535 DEFINE_WHITE_NOISE (int32, 2147483647.0);
536 DEFINE_WHITE_NOISE (float, 1.0);
537 DEFINE_WHITE_NOISE (double, 1.0);
539 static const ProcessFunc white_noise_funcs[] = {
540 (ProcessFunc) gst_audio_test_src_create_white_noise_int16,
541 (ProcessFunc) gst_audio_test_src_create_white_noise_int32,
542 (ProcessFunc) gst_audio_test_src_create_white_noise_float,
543 (ProcessFunc) gst_audio_test_src_create_white_noise_double
546 /* pink noise calculation is based on
547 * http://www.firstpr.com.au/dsp/pink-noise/phil_burk_19990905_patest_pink.c
548 * which has been released under public domain
552 gst_audio_test_src_init_pink_noise (GstAudioTestSrc * src)
555 gint num_rows = 12; /* arbitrary: 1 .. PINK_MAX_RANDOM_ROWS */
559 src->pink.index_mask = (1 << num_rows) - 1;
560 /* calculate maximum possible signed random value.
561 * Extra 1 for white noise always added. */
562 pmax = (num_rows + 1) * (1 << (PINK_RANDOM_BITS - 1));
563 src->pink.scalar = 1.0f / pmax;
564 /* Initialize rows. */
565 for (i = 0; i < num_rows; i++)
566 src->pink.rows[i] = 0;
567 src->pink.running_sum = 0;
570 /* Generate Pink noise values between -1.0 and +1.0 */
572 gst_audio_test_src_generate_pink_noise_value (GstAudioTestSrc * src)
574 GstPinkNoise *pink = &src->pink;
578 /* Increment and mask index. */
579 pink->index = (pink->index + 1) & pink->index_mask;
581 /* If index is zero, don't update any random values. */
582 if (pink->index != 0) {
583 /* Determine how many trailing zeros in PinkIndex. */
584 /* This algorithm will hang if n==0 so test first. */
586 gint n = pink->index;
588 while ((n & 1) == 0) {
593 /* Replace the indexed ROWS random value.
594 * Subtract and add back to RunningSum instead of adding all the random
595 * values together. Only one changes each time.
597 pink->running_sum -= pink->rows[num_zeros];
598 new_random = 32768.0 - (65536.0 * (gulong) g_rand_int (src->gen)
599 / (G_MAXUINT32 + 1.0));
600 pink->running_sum += new_random;
601 pink->rows[num_zeros] = new_random;
604 /* Add extra white noise value. */
605 new_random = 32768.0 - (65536.0 * (gulong) g_rand_int (src->gen)
606 / (G_MAXUINT32 + 1.0));
607 sum = pink->running_sum + new_random;
609 /* Scale to range of -1.0 to 0.9999. */
610 return (pink->scalar * sum);
613 #define DEFINE_PINK(type, scale) \
615 gst_audio_test_src_create_pink_noise_##type (GstAudioTestSrc * src, g##type * samples) \
617 gint i, c, channels; \
620 amp = src->volume * scale; \
621 channels = GST_AUDIO_INFO_CHANNELS (&src->info); \
624 while (i < (src->generate_samples_per_buffer * channels)) { \
625 for (c = 0; c < channels; ++c) { \
627 (g##type) (gst_audio_test_src_generate_pink_noise_value (src) * \
633 DEFINE_PINK (int16, 32767.0);
634 DEFINE_PINK (int32, 2147483647.0);
635 DEFINE_PINK (float, 1.0);
636 DEFINE_PINK (double, 1.0);
638 static const ProcessFunc pink_noise_funcs[] = {
639 (ProcessFunc) gst_audio_test_src_create_pink_noise_int16,
640 (ProcessFunc) gst_audio_test_src_create_pink_noise_int32,
641 (ProcessFunc) gst_audio_test_src_create_pink_noise_float,
642 (ProcessFunc) gst_audio_test_src_create_pink_noise_double
646 gst_audio_test_src_init_sine_table (GstAudioTestSrc * src)
650 gdouble step = M_PI_M2 / 1024.0;
651 gdouble amp = src->volume;
653 for (i = 0; i < 1024; i++) {
654 src->wave_table[i] = sin (ang) * amp;
659 #define DEFINE_SINE_TABLE(type,scale) \
661 gst_audio_test_src_create_sine_table_##type (GstAudioTestSrc * src, g##type * samples) \
663 gint i, c, channels; \
666 channels = GST_AUDIO_INFO_CHANNELS (&src->info); \
667 step = M_PI_M2 * src->freq / GST_AUDIO_INFO_RATE (&src->info); \
668 scl = 1024.0 / M_PI_M2; \
671 while (i < (src->generate_samples_per_buffer * channels)) { \
672 src->accumulator += step; \
673 if (src->accumulator >= M_PI_M2) \
674 src->accumulator -= M_PI_M2; \
676 for (c = 0; c < channels; ++c) \
677 samples[i++] = (g##type) scale * src->wave_table[(gint) (src->accumulator * scl)]; \
681 DEFINE_SINE_TABLE (int16, 32767.0);
682 DEFINE_SINE_TABLE (int32, 2147483647.0);
683 DEFINE_SINE_TABLE (float, 1.0);
684 DEFINE_SINE_TABLE (double, 1.0);
686 static const ProcessFunc sine_table_funcs[] = {
687 (ProcessFunc) gst_audio_test_src_create_sine_table_int16,
688 (ProcessFunc) gst_audio_test_src_create_sine_table_int32,
689 (ProcessFunc) gst_audio_test_src_create_sine_table_float,
690 (ProcessFunc) gst_audio_test_src_create_sine_table_double
693 #define DEFINE_TICKS(type,scale) \
695 gst_audio_test_src_create_tick_##type (GstAudioTestSrc * src, g##type * samples) \
697 gint i, c, channels, samplerate; \
700 channels = GST_AUDIO_INFO_CHANNELS (&src->info); \
701 samplerate = GST_AUDIO_INFO_RATE (&src->info); \
702 step = M_PI_M2 * src->freq / samplerate; \
703 scl = 1024.0 / M_PI_M2; \
705 for (i = 0; i < src->generate_samples_per_buffer; i++) { \
706 src->accumulator += step; \
707 if (src->accumulator >= M_PI_M2) \
708 src->accumulator -= M_PI_M2; \
710 if ((src->next_sample + i)%samplerate < 1600) { \
711 for (c = 0; c < channels; ++c) \
712 samples[(i * channels) + c] = (g##type) scale * src->wave_table[(gint) (src->accumulator * scl)]; \
714 for (c = 0; c < channels; ++c) \
715 samples[(i * channels) + c] = 0; \
720 DEFINE_TICKS (int16, 32767.0);
721 DEFINE_TICKS (int32, 2147483647.0);
722 DEFINE_TICKS (float, 1.0);
723 DEFINE_TICKS (double, 1.0);
725 static const ProcessFunc tick_funcs[] = {
726 (ProcessFunc) gst_audio_test_src_create_tick_int16,
727 (ProcessFunc) gst_audio_test_src_create_tick_int32,
728 (ProcessFunc) gst_audio_test_src_create_tick_float,
729 (ProcessFunc) gst_audio_test_src_create_tick_double
732 /* Gaussian white noise using Box-Muller algorithm. unit variance
733 * normally-distributed random numbers are generated in pairs as the real
734 * and imaginary parts of a compex random variable with
735 * uniformly-distributed argument and \chi^{2}-distributed modulus.
738 #define DEFINE_GAUSSIAN_WHITE_NOISE(type,scale) \
740 gst_audio_test_src_create_gaussian_white_noise_##type (GstAudioTestSrc * src, g##type * samples) \
743 gdouble amp = (src->volume * scale); \
744 gint channels = GST_AUDIO_INFO_CHANNELS (&src->info); \
746 for (i = 0; i < src->generate_samples_per_buffer * channels; ) { \
747 for (c = 0; c < channels; ++c) { \
748 gdouble mag = sqrt (-2 * log (1.0 - g_rand_double (src->gen))); \
749 gdouble phs = g_rand_double_range (src->gen, 0.0, M_PI_M2); \
751 samples[i++] = (g##type) (amp * mag * cos (phs)); \
752 if (++c >= channels) \
754 samples[i++] = (g##type) (amp * mag * sin (phs)); \
759 DEFINE_GAUSSIAN_WHITE_NOISE (int16, 32767.0);
760 DEFINE_GAUSSIAN_WHITE_NOISE (int32, 2147483647.0);
761 DEFINE_GAUSSIAN_WHITE_NOISE (float, 1.0);
762 DEFINE_GAUSSIAN_WHITE_NOISE (double, 1.0);
764 static const ProcessFunc gaussian_white_noise_funcs[] = {
765 (ProcessFunc) gst_audio_test_src_create_gaussian_white_noise_int16,
766 (ProcessFunc) gst_audio_test_src_create_gaussian_white_noise_int32,
767 (ProcessFunc) gst_audio_test_src_create_gaussian_white_noise_float,
768 (ProcessFunc) gst_audio_test_src_create_gaussian_white_noise_double
771 /* Brownian (Red) Noise: noise where the power density decreases by 6 dB per
772 * octave with increasing frequency
774 * taken from http://vellocet.com/dsp/noise/VRand.html
775 * by Andrew Simper of Vellocet (andy@vellocet.com)
778 #define DEFINE_RED_NOISE(type,scale) \
780 gst_audio_test_src_create_red_noise_##type (GstAudioTestSrc * src, g##type * samples) \
783 gdouble amp = (src->volume * scale); \
784 gdouble state = src->red.state; \
785 gint channels = GST_AUDIO_INFO_CHANNELS (&src->info); \
787 for (i = 0; i < src->generate_samples_per_buffer * channels; ) { \
788 for (c = 0; c < channels; ++c) { \
790 gdouble r = g_rand_double_range (src->gen, -1.0, 1.0); \
792 if (state<-8.0f || state>8.0f) state -= r; \
795 samples[i++] = (g##type) (amp * state * 0.0625f); /* /16.0 */ \
798 src->red.state = state; \
801 DEFINE_RED_NOISE (int16, 32767.0);
802 DEFINE_RED_NOISE (int32, 2147483647.0);
803 DEFINE_RED_NOISE (float, 1.0);
804 DEFINE_RED_NOISE (double, 1.0);
806 static const ProcessFunc red_noise_funcs[] = {
807 (ProcessFunc) gst_audio_test_src_create_red_noise_int16,
808 (ProcessFunc) gst_audio_test_src_create_red_noise_int32,
809 (ProcessFunc) gst_audio_test_src_create_red_noise_float,
810 (ProcessFunc) gst_audio_test_src_create_red_noise_double
813 /* Blue Noise: apply spectral inversion to pink noise */
815 #define DEFINE_BLUE_NOISE(type) \
817 gst_audio_test_src_create_blue_noise_##type (GstAudioTestSrc * src, g##type * samples) \
820 static gdouble flip=1.0; \
821 gint channels = GST_AUDIO_INFO_CHANNELS (&src->info); \
823 gst_audio_test_src_create_pink_noise_##type (src, samples); \
824 for (i = 0; i < src->generate_samples_per_buffer * channels; ) { \
825 for (c = 0; c < channels; ++c) { \
826 samples[i++] *= flip; \
832 DEFINE_BLUE_NOISE (int16);
833 DEFINE_BLUE_NOISE (int32);
834 DEFINE_BLUE_NOISE (float);
835 DEFINE_BLUE_NOISE (double);
837 static const ProcessFunc blue_noise_funcs[] = {
838 (ProcessFunc) gst_audio_test_src_create_blue_noise_int16,
839 (ProcessFunc) gst_audio_test_src_create_blue_noise_int32,
840 (ProcessFunc) gst_audio_test_src_create_blue_noise_float,
841 (ProcessFunc) gst_audio_test_src_create_blue_noise_double
845 /* Violet Noise: apply spectral inversion to red noise */
847 #define DEFINE_VIOLET_NOISE(type) \
849 gst_audio_test_src_create_violet_noise_##type (GstAudioTestSrc * src, g##type * samples) \
852 static gdouble flip=1.0; \
853 gint channels = GST_AUDIO_INFO_CHANNELS (&src->info); \
855 gst_audio_test_src_create_red_noise_##type (src, samples); \
856 for (i = 0; i < src->generate_samples_per_buffer * channels; ) { \
857 for (c = 0; c < channels; ++c) { \
858 samples[i++] *= flip; \
864 DEFINE_VIOLET_NOISE (int16);
865 DEFINE_VIOLET_NOISE (int32);
866 DEFINE_VIOLET_NOISE (float);
867 DEFINE_VIOLET_NOISE (double);
869 static const ProcessFunc violet_noise_funcs[] = {
870 (ProcessFunc) gst_audio_test_src_create_violet_noise_int16,
871 (ProcessFunc) gst_audio_test_src_create_violet_noise_int32,
872 (ProcessFunc) gst_audio_test_src_create_violet_noise_float,
873 (ProcessFunc) gst_audio_test_src_create_violet_noise_double
878 * gst_audio_test_src_change_wave:
879 * Assign function pointer of wave genrator.
882 gst_audio_test_src_change_wave (GstAudioTestSrc * src)
886 switch (GST_AUDIO_FORMAT_INFO_FORMAT (src->info.finfo)) {
887 case GST_AUDIO_FORMAT_S16:
890 case GST_AUDIO_FORMAT_S32:
893 case GST_AUDIO_FORMAT_F32:
896 case GST_AUDIO_FORMAT_F64:
905 case GST_AUDIO_TEST_SRC_WAVE_SINE:
906 src->process = sine_funcs[idx];
908 case GST_AUDIO_TEST_SRC_WAVE_SQUARE:
909 src->process = square_funcs[idx];
911 case GST_AUDIO_TEST_SRC_WAVE_SAW:
912 src->process = saw_funcs[idx];
914 case GST_AUDIO_TEST_SRC_WAVE_TRIANGLE:
915 src->process = triangle_funcs[idx];
917 case GST_AUDIO_TEST_SRC_WAVE_SILENCE:
918 src->process = silence_funcs[idx];
920 case GST_AUDIO_TEST_SRC_WAVE_WHITE_NOISE:
922 src->gen = g_rand_new ();
923 src->process = white_noise_funcs[idx];
925 case GST_AUDIO_TEST_SRC_WAVE_PINK_NOISE:
927 src->gen = g_rand_new ();
928 gst_audio_test_src_init_pink_noise (src);
929 src->process = pink_noise_funcs[idx];
931 case GST_AUDIO_TEST_SRC_WAVE_SINE_TAB:
932 gst_audio_test_src_init_sine_table (src);
933 src->process = sine_table_funcs[idx];
935 case GST_AUDIO_TEST_SRC_WAVE_TICKS:
936 gst_audio_test_src_init_sine_table (src);
937 src->process = tick_funcs[idx];
939 case GST_AUDIO_TEST_SRC_WAVE_GAUSSIAN_WHITE_NOISE:
941 src->gen = g_rand_new ();
942 src->process = gaussian_white_noise_funcs[idx];
944 case GST_AUDIO_TEST_SRC_WAVE_RED_NOISE:
946 src->gen = g_rand_new ();
947 src->red.state = 0.0;
948 src->process = red_noise_funcs[idx];
950 case GST_AUDIO_TEST_SRC_WAVE_BLUE_NOISE:
952 src->gen = g_rand_new ();
953 gst_audio_test_src_init_pink_noise (src);
954 src->process = blue_noise_funcs[idx];
956 case GST_AUDIO_TEST_SRC_WAVE_VIOLET_NOISE:
958 src->gen = g_rand_new ();
959 src->red.state = 0.0;
960 src->process = violet_noise_funcs[idx];
962 GST_ERROR ("invalid wave-form");
968 * gst_audio_test_src_change_volume:
969 * Recalc wave tables for precalculated waves.
972 gst_audio_test_src_change_volume (GstAudioTestSrc * src)
975 case GST_AUDIO_TEST_SRC_WAVE_SINE_TAB:
976 gst_audio_test_src_init_sine_table (src);
984 gst_audio_test_src_get_times (GstBaseSrc * basesrc, GstBuffer * buffer,
985 GstClockTime * start, GstClockTime * end)
987 /* for live sources, sync on the timestamp of the buffer */
988 if (gst_base_src_is_live (basesrc)) {
989 GstClockTime timestamp = GST_BUFFER_TIMESTAMP (buffer);
991 if (GST_CLOCK_TIME_IS_VALID (timestamp)) {
992 /* get duration to calculate end time */
993 GstClockTime duration = GST_BUFFER_DURATION (buffer);
995 if (GST_CLOCK_TIME_IS_VALID (duration)) {
996 *end = timestamp + duration;
1007 gst_audio_test_src_start (GstBaseSrc * basesrc)
1009 GstAudioTestSrc *src = GST_AUDIO_TEST_SRC (basesrc);
1011 src->next_sample = 0;
1014 src->check_seek_stop = FALSE;
1015 src->eos_reached = FALSE;
1016 src->tags_pushed = FALSE;
1017 src->accumulator = 0;
1023 gst_audio_test_src_stop (GstBaseSrc * basesrc)
1028 /* seek to time, will be called when we operate in push mode. In pull mode we
1029 * get the requested byte offset. */
1031 gst_audio_test_src_do_seek (GstBaseSrc * basesrc, GstSegment * segment)
1033 GstAudioTestSrc *src = GST_AUDIO_TEST_SRC (basesrc);
1035 gint samplerate, bpf;
1037 GST_DEBUG_OBJECT (src, "seeking %" GST_SEGMENT_FORMAT, segment);
1039 time = segment->position;
1040 src->reverse = (segment->rate < 0.0);
1042 samplerate = GST_AUDIO_INFO_RATE (&src->info);
1043 bpf = GST_AUDIO_INFO_BPF (&src->info);
1045 /* now move to the time indicated */
1046 src->next_sample = gst_util_uint64_scale_int (time, samplerate, GST_SECOND);
1047 src->next_byte = src->next_sample * bpf;
1048 if (samplerate == 0)
1052 gst_util_uint64_scale_int (src->next_sample, GST_SECOND, samplerate);
1054 GST_DEBUG_OBJECT (src, "seeking next_sample=%" G_GINT64_FORMAT
1055 " next_time=%" GST_TIME_FORMAT, src->next_sample,
1056 GST_TIME_ARGS (src->next_time));
1058 g_assert (src->next_time <= time);
1060 if (!src->reverse) {
1061 if (GST_CLOCK_TIME_IS_VALID (segment->start)) {
1062 segment->time = segment->start;
1065 if (GST_CLOCK_TIME_IS_VALID (segment->stop)) {
1066 segment->time = segment->stop;
1070 if (GST_CLOCK_TIME_IS_VALID (segment->stop)) {
1071 time = segment->stop;
1072 src->sample_stop = gst_util_uint64_scale_int (time, samplerate, GST_SECOND);
1073 src->check_seek_stop = TRUE;
1075 src->check_seek_stop = FALSE;
1077 src->eos_reached = FALSE;
1083 gst_audio_test_src_is_seekable (GstBaseSrc * basesrc)
1085 /* we're seekable... */
1089 static GstFlowReturn
1090 gst_audio_test_src_fill (GstBaseSrc * basesrc, guint64 offset,
1091 guint length, GstBuffer * buffer)
1093 GstAudioTestSrc *src;
1094 GstClockTime next_time;
1095 gint64 next_sample, next_byte;
1096 gint bytes, samples;
1097 GstElementClass *eclass;
1099 gint samplerate, bpf;
1101 src = GST_AUDIO_TEST_SRC (basesrc);
1103 /* example for tagging generated data */
1104 if (!src->tags_pushed) {
1105 GstTagList *taglist;
1107 taglist = gst_tag_list_new ();
1109 gst_tag_list_add (taglist, GST_TAG_MERGE_APPEND,
1110 GST_TAG_DESCRIPTION, "audiotest wave", NULL);
1112 eclass = GST_ELEMENT_CLASS (parent_class);
1113 if (eclass->send_event)
1114 eclass->send_event (GST_ELEMENT_CAST (basesrc),
1115 gst_event_new_tag (taglist));
1116 src->tags_pushed = TRUE;
1119 if (src->eos_reached) {
1120 GST_INFO_OBJECT (src, "eos");
1121 return GST_FLOW_UNEXPECTED;
1124 samplerate = GST_AUDIO_INFO_RATE (&src->info);
1125 bpf = GST_AUDIO_INFO_BPF (&src->info);
1127 /* if no length was given, use our default length in samples otherwise convert
1128 * the length in bytes to samples. */
1130 samples = src->samples_per_buffer;
1132 samples = length / bpf;
1134 /* if no offset was given, use our next logical byte */
1136 offset = src->next_byte;
1138 /* now see if we are at the byteoffset we think we are */
1139 if (offset != src->next_byte) {
1140 GST_DEBUG_OBJECT (src, "seek to new offset %" G_GUINT64_FORMAT, offset);
1141 /* we have a discont in the expected sample offset, do a 'seek' */
1142 src->next_sample = offset / bpf;
1144 gst_util_uint64_scale_int (src->next_sample, GST_SECOND, samplerate);
1145 src->next_byte = offset;
1149 if (src->check_seek_stop &&
1150 (src->sample_stop > src->next_sample) &&
1151 (src->sample_stop < src->next_sample + samples)
1153 /* calculate only partial buffer */
1154 src->generate_samples_per_buffer = src->sample_stop - src->next_sample;
1155 next_sample = src->sample_stop;
1156 src->eos_reached = TRUE;
1158 /* calculate full buffer */
1159 src->generate_samples_per_buffer = samples;
1160 next_sample = src->next_sample + (src->reverse ? (-samples) : samples);
1163 bytes = src->generate_samples_per_buffer * bpf;
1165 next_byte = src->next_byte + (src->reverse ? (-bytes) : bytes);
1166 next_time = gst_util_uint64_scale_int (next_sample, GST_SECOND, samplerate);
1168 GST_LOG_OBJECT (src, "samplerate %d", samplerate);
1169 GST_LOG_OBJECT (src, "next_sample %" G_GINT64_FORMAT ", ts %" GST_TIME_FORMAT,
1170 next_sample, GST_TIME_ARGS (next_time));
1172 GST_BUFFER_OFFSET (buffer) = src->next_sample;
1173 GST_BUFFER_OFFSET_END (buffer) = next_sample;
1174 if (!src->reverse) {
1175 GST_BUFFER_TIMESTAMP (buffer) = src->timestamp_offset + src->next_time;
1176 GST_BUFFER_DURATION (buffer) = next_time - src->next_time;
1178 GST_BUFFER_TIMESTAMP (buffer) = src->timestamp_offset + next_time;
1179 GST_BUFFER_DURATION (buffer) = src->next_time - next_time;
1182 gst_object_sync_values (G_OBJECT (src), GST_BUFFER_TIMESTAMP (buffer));
1184 src->next_time = next_time;
1185 src->next_sample = next_sample;
1186 src->next_byte = next_byte;
1188 GST_LOG_OBJECT (src, "generating %u samples at ts %" GST_TIME_FORMAT,
1189 src->generate_samples_per_buffer,
1190 GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buffer)));
1192 data = gst_buffer_map (buffer, NULL, NULL, GST_MAP_WRITE);
1193 src->process (src, data);
1194 gst_buffer_unmap (buffer, data, bytes);
1196 if (G_UNLIKELY ((src->wave == GST_AUDIO_TEST_SRC_WAVE_SILENCE)
1197 || (src->volume == 0.0))) {
1198 GST_BUFFER_FLAG_SET (buffer, GST_BUFFER_FLAG_GAP);
1205 gst_audio_test_src_set_property (GObject * object, guint prop_id,
1206 const GValue * value, GParamSpec * pspec)
1208 GstAudioTestSrc *src = GST_AUDIO_TEST_SRC (object);
1211 case PROP_SAMPLES_PER_BUFFER:
1212 src->samples_per_buffer = g_value_get_int (value);
1215 src->wave = g_value_get_enum (value);
1216 gst_audio_test_src_change_wave (src);
1219 src->freq = g_value_get_double (value);
1222 src->volume = g_value_get_double (value);
1223 gst_audio_test_src_change_volume (src);
1226 gst_base_src_set_live (GST_BASE_SRC (src), g_value_get_boolean (value));
1228 case PROP_TIMESTAMP_OFFSET:
1229 src->timestamp_offset = g_value_get_int64 (value);
1231 case PROP_CAN_ACTIVATE_PUSH:
1232 GST_BASE_SRC (src)->can_activate_push = g_value_get_boolean (value);
1234 case PROP_CAN_ACTIVATE_PULL:
1235 src->can_activate_pull = g_value_get_boolean (value);
1238 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1244 gst_audio_test_src_get_property (GObject * object, guint prop_id,
1245 GValue * value, GParamSpec * pspec)
1247 GstAudioTestSrc *src = GST_AUDIO_TEST_SRC (object);
1250 case PROP_SAMPLES_PER_BUFFER:
1251 g_value_set_int (value, src->samples_per_buffer);
1254 g_value_set_enum (value, src->wave);
1257 g_value_set_double (value, src->freq);
1260 g_value_set_double (value, src->volume);
1263 g_value_set_boolean (value, gst_base_src_is_live (GST_BASE_SRC (src)));
1265 case PROP_TIMESTAMP_OFFSET:
1266 g_value_set_int64 (value, src->timestamp_offset);
1268 case PROP_CAN_ACTIVATE_PUSH:
1269 g_value_set_boolean (value, GST_BASE_SRC (src)->can_activate_push);
1271 case PROP_CAN_ACTIVATE_PULL:
1272 g_value_set_boolean (value, src->can_activate_pull);
1275 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1281 plugin_init (GstPlugin * plugin)
1283 /* initialize gst controller library */
1284 gst_controller_init (NULL, NULL);
1286 GST_DEBUG_CATEGORY_INIT (audio_test_src_debug, "audiotestsrc", 0,
1287 "Audio Test Source");
1289 return gst_element_register (plugin, "audiotestsrc",
1290 GST_RANK_NONE, GST_TYPE_AUDIO_TEST_SRC);
1293 GST_PLUGIN_DEFINE (GST_VERSION_MAJOR,
1296 "Creates audio test signals of given frequency and volume",
1297 plugin_init, VERSION, "LGPL", GST_PACKAGE_NAME, GST_PACKAGE_ORIGIN);