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.
47 #include "gstaudiotestsrc.h"
50 #define M_PI_M2 ( G_PI + G_PI )
52 GST_DEBUG_CATEGORY_STATIC (audio_test_src_debug);
53 #define GST_CAT_DEFAULT audio_test_src_debug
55 #define DEFAULT_SAMPLES_PER_BUFFER 1024
56 #define DEFAULT_WAVE GST_AUDIO_TEST_SRC_WAVE_SINE
57 #define DEFAULT_FREQ 440.0
58 #define DEFAULT_VOLUME 0.8
59 #define DEFAULT_IS_LIVE FALSE
60 #define DEFAULT_TIMESTAMP_OFFSET G_GINT64_CONSTANT (0)
61 #define DEFAULT_CAN_ACTIVATE_PUSH TRUE
62 #define DEFAULT_CAN_ACTIVATE_PULL FALSE
67 PROP_SAMPLES_PER_BUFFER,
72 PROP_TIMESTAMP_OFFSET,
73 PROP_CAN_ACTIVATE_PUSH,
74 PROP_CAN_ACTIVATE_PULL,
78 #if G_BYTE_ORDER == G_LITTLE_ENDIAN
79 #define FORMAT_STR "{ S16LE, S32LE, F32LE, F64LE }"
80 #define DEFAULT_FORMAT_STR "S16LE"
82 #define FORMAT_STR "{ S16BE, S32BE, F32BE, F64BE }"
83 #define DEFAULT_FORMAT_STR "S16BE"
86 static GstStaticPadTemplate gst_audio_test_src_src_template =
87 GST_STATIC_PAD_TEMPLATE ("src",
90 GST_STATIC_CAPS ("audio/x-raw, "
91 "format = (string) " FORMAT_STR ", "
92 "layout = (string) interleaved, "
93 "rate = (int) [ 1, MAX ], "
94 "channels = (int) 1; "
96 "format = (string) " FORMAT_STR ", "
97 "layout = (string) interleaved, "
98 "rate = (int) [ 1, MAX ], "
99 "channels = (int) 2, " "channel-mask = (bitmask) 0x3")
102 #define gst_audio_test_src_parent_class parent_class
103 G_DEFINE_TYPE (GstAudioTestSrc, gst_audio_test_src, GST_TYPE_BASE_SRC);
105 #define GST_TYPE_AUDIO_TEST_SRC_WAVE (gst_audiostestsrc_wave_get_type())
107 gst_audiostestsrc_wave_get_type (void)
109 static GType audiostestsrc_wave_type = 0;
110 static const GEnumValue audiostestsrc_waves[] = {
111 {GST_AUDIO_TEST_SRC_WAVE_SINE, "Sine", "sine"},
112 {GST_AUDIO_TEST_SRC_WAVE_SQUARE, "Square", "square"},
113 {GST_AUDIO_TEST_SRC_WAVE_SAW, "Saw", "saw"},
114 {GST_AUDIO_TEST_SRC_WAVE_TRIANGLE, "Triangle", "triangle"},
115 {GST_AUDIO_TEST_SRC_WAVE_SILENCE, "Silence", "silence"},
116 {GST_AUDIO_TEST_SRC_WAVE_WHITE_NOISE, "White uniform noise", "white-noise"},
117 {GST_AUDIO_TEST_SRC_WAVE_PINK_NOISE, "Pink noise", "pink-noise"},
118 {GST_AUDIO_TEST_SRC_WAVE_SINE_TAB, "Sine table", "sine-table"},
119 {GST_AUDIO_TEST_SRC_WAVE_TICKS, "Periodic Ticks", "ticks"},
120 {GST_AUDIO_TEST_SRC_WAVE_GAUSSIAN_WHITE_NOISE, "White Gaussian noise",
122 {GST_AUDIO_TEST_SRC_WAVE_RED_NOISE, "Red (brownian) noise", "red-noise"},
123 {GST_AUDIO_TEST_SRC_WAVE_BLUE_NOISE, "Blue noise", "blue-noise"},
124 {GST_AUDIO_TEST_SRC_WAVE_VIOLET_NOISE, "Violet noise", "violet-noise"},
128 if (G_UNLIKELY (audiostestsrc_wave_type == 0)) {
129 audiostestsrc_wave_type = g_enum_register_static ("GstAudioTestSrcWave",
130 audiostestsrc_waves);
132 return audiostestsrc_wave_type;
135 static void gst_audio_test_src_finalize (GObject * object);
137 static void gst_audio_test_src_set_property (GObject * object,
138 guint prop_id, const GValue * value, GParamSpec * pspec);
139 static void gst_audio_test_src_get_property (GObject * object,
140 guint prop_id, GValue * value, GParamSpec * pspec);
142 static gboolean gst_audio_test_src_setcaps (GstBaseSrc * basesrc,
144 static void gst_audio_test_src_fixate (GstBaseSrc * bsrc, GstCaps * caps);
146 static gboolean gst_audio_test_src_is_seekable (GstBaseSrc * basesrc);
147 static gboolean gst_audio_test_src_do_seek (GstBaseSrc * basesrc,
148 GstSegment * segment);
149 static gboolean gst_audio_test_src_query (GstBaseSrc * basesrc,
152 static void gst_audio_test_src_change_wave (GstAudioTestSrc * src);
154 static void gst_audio_test_src_get_times (GstBaseSrc * basesrc,
155 GstBuffer * buffer, GstClockTime * start, GstClockTime * end);
156 static gboolean gst_audio_test_src_start (GstBaseSrc * basesrc);
157 static gboolean gst_audio_test_src_stop (GstBaseSrc * basesrc);
158 static GstFlowReturn gst_audio_test_src_fill (GstBaseSrc * basesrc,
159 guint64 offset, guint length, GstBuffer * buffer);
162 gst_audio_test_src_class_init (GstAudioTestSrcClass * klass)
164 GObjectClass *gobject_class;
165 GstElementClass *gstelement_class;
166 GstBaseSrcClass *gstbasesrc_class;
168 gobject_class = (GObjectClass *) klass;
169 gstelement_class = (GstElementClass *) klass;
170 gstbasesrc_class = (GstBaseSrcClass *) klass;
172 gobject_class->set_property = gst_audio_test_src_set_property;
173 gobject_class->get_property = gst_audio_test_src_get_property;
174 gobject_class->finalize = gst_audio_test_src_finalize;
176 g_object_class_install_property (gobject_class, PROP_SAMPLES_PER_BUFFER,
177 g_param_spec_int ("samplesperbuffer", "Samples per buffer",
178 "Number of samples in each outgoing buffer",
179 1, G_MAXINT, DEFAULT_SAMPLES_PER_BUFFER,
180 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
181 g_object_class_install_property (gobject_class, PROP_WAVE,
182 g_param_spec_enum ("wave", "Waveform", "Oscillator waveform",
183 GST_TYPE_AUDIO_TEST_SRC_WAVE, GST_AUDIO_TEST_SRC_WAVE_SINE,
184 G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE | G_PARAM_STATIC_STRINGS));
185 g_object_class_install_property (gobject_class, PROP_FREQ,
186 g_param_spec_double ("freq", "Frequency", "Frequency of test signal",
187 0.0, 20000.0, DEFAULT_FREQ,
188 G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE | G_PARAM_STATIC_STRINGS));
189 g_object_class_install_property (gobject_class, PROP_VOLUME,
190 g_param_spec_double ("volume", "Volume", "Volume of test signal", 0.0,
192 G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE | G_PARAM_STATIC_STRINGS));
193 g_object_class_install_property (gobject_class, PROP_IS_LIVE,
194 g_param_spec_boolean ("is-live", "Is Live",
195 "Whether to act as a live source", DEFAULT_IS_LIVE,
196 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
197 g_object_class_install_property (G_OBJECT_CLASS (klass),
198 PROP_TIMESTAMP_OFFSET, g_param_spec_int64 ("timestamp-offset",
200 "An offset added to timestamps set on buffers (in ns)", G_MININT64,
201 G_MAXINT64, DEFAULT_TIMESTAMP_OFFSET,
202 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
203 g_object_class_install_property (gobject_class, PROP_CAN_ACTIVATE_PUSH,
204 g_param_spec_boolean ("can-activate-push", "Can activate push",
205 "Can activate in push mode", DEFAULT_CAN_ACTIVATE_PUSH,
206 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
207 g_object_class_install_property (gobject_class, PROP_CAN_ACTIVATE_PULL,
208 g_param_spec_boolean ("can-activate-pull", "Can activate pull",
209 "Can activate in pull mode", DEFAULT_CAN_ACTIVATE_PULL,
210 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
212 gst_element_class_add_pad_template (gstelement_class,
213 gst_static_pad_template_get (&gst_audio_test_src_src_template));
214 gst_element_class_set_details_simple (gstelement_class,
215 "Audio test source", "Source/Audio",
216 "Creates audio test signals of given frequency and volume",
217 "Stefan Kost <ensonic@users.sf.net>");
219 gstbasesrc_class->set_caps = GST_DEBUG_FUNCPTR (gst_audio_test_src_setcaps);
220 gstbasesrc_class->fixate = GST_DEBUG_FUNCPTR (gst_audio_test_src_fixate);
221 gstbasesrc_class->is_seekable =
222 GST_DEBUG_FUNCPTR (gst_audio_test_src_is_seekable);
223 gstbasesrc_class->do_seek = GST_DEBUG_FUNCPTR (gst_audio_test_src_do_seek);
224 gstbasesrc_class->query = GST_DEBUG_FUNCPTR (gst_audio_test_src_query);
225 gstbasesrc_class->get_times =
226 GST_DEBUG_FUNCPTR (gst_audio_test_src_get_times);
227 gstbasesrc_class->start = GST_DEBUG_FUNCPTR (gst_audio_test_src_start);
228 gstbasesrc_class->stop = GST_DEBUG_FUNCPTR (gst_audio_test_src_stop);
229 gstbasesrc_class->fill = GST_DEBUG_FUNCPTR (gst_audio_test_src_fill);
233 gst_audio_test_src_init (GstAudioTestSrc * src)
235 src->volume = DEFAULT_VOLUME;
236 src->freq = DEFAULT_FREQ;
238 /* we operate in time */
239 gst_base_src_set_format (GST_BASE_SRC (src), GST_FORMAT_TIME);
240 gst_base_src_set_live (GST_BASE_SRC (src), DEFAULT_IS_LIVE);
242 src->samples_per_buffer = DEFAULT_SAMPLES_PER_BUFFER;
243 src->generate_samples_per_buffer = src->samples_per_buffer;
244 src->timestamp_offset = DEFAULT_TIMESTAMP_OFFSET;
245 src->can_activate_pull = DEFAULT_CAN_ACTIVATE_PULL;
249 src->wave = DEFAULT_WAVE;
250 gst_base_src_set_blocksize (GST_BASE_SRC (src), -1);
254 gst_audio_test_src_finalize (GObject * object)
256 GstAudioTestSrc *src = GST_AUDIO_TEST_SRC (object);
259 g_rand_free (src->gen);
262 G_OBJECT_CLASS (parent_class)->finalize (object);
266 gst_audio_test_src_fixate (GstBaseSrc * bsrc, GstCaps * caps)
268 GstAudioTestSrc *src = GST_AUDIO_TEST_SRC (bsrc);
269 GstStructure *structure;
271 structure = gst_caps_get_structure (caps, 0);
273 GST_DEBUG_OBJECT (src, "fixating samplerate to %d", GST_AUDIO_DEF_RATE);
275 gst_structure_fixate_field_nearest_int (structure, "rate",
278 gst_structure_fixate_field_string (structure, "format", DEFAULT_FORMAT_STR);
280 /* fixate to mono unless downstream requires stereo, for backwards compat */
281 gst_structure_fixate_field_nearest_int (structure, "channels", 1);
283 GST_BASE_SRC_CLASS (parent_class)->fixate (bsrc, caps);
287 gst_audio_test_src_setcaps (GstBaseSrc * basesrc, GstCaps * caps)
289 GstAudioTestSrc *src = GST_AUDIO_TEST_SRC (basesrc);
292 if (!gst_audio_info_from_caps (&info, caps))
295 GST_DEBUG_OBJECT (src, "negotiated to caps %" GST_PTR_FORMAT, caps);
299 gst_base_src_set_blocksize (basesrc,
300 GST_AUDIO_INFO_BPF (&info) * src->samples_per_buffer);
301 gst_audio_test_src_change_wave (src);
308 GST_ERROR_OBJECT (basesrc, "received invalid caps");
314 gst_audio_test_src_query (GstBaseSrc * basesrc, GstQuery * query)
316 GstAudioTestSrc *src = GST_AUDIO_TEST_SRC (basesrc);
317 gboolean res = FALSE;
319 switch (GST_QUERY_TYPE (query)) {
320 case GST_QUERY_CONVERT:
322 GstFormat src_fmt, dest_fmt;
323 gint64 src_val, dest_val;
325 gst_query_parse_convert (query, &src_fmt, &src_val, &dest_fmt, &dest_val);
327 if (!gst_audio_info_convert (&src->info, src_fmt, src_val, dest_fmt,
331 gst_query_set_convert (query, src_fmt, src_val, dest_fmt, dest_val);
335 case GST_QUERY_SCHEDULING:
337 /* if we can operate in pull mode */
338 gst_query_set_scheduling (query, GST_SCHEDULING_FLAG_SEEKABLE, 1, -1, 0);
339 gst_query_add_scheduling_mode (query, GST_PAD_MODE_PUSH);
340 if (src->can_activate_pull)
341 gst_query_add_scheduling_mode (query, GST_PAD_MODE_PULL);
347 res = GST_BASE_SRC_CLASS (parent_class)->query (basesrc, query);
355 GST_DEBUG_OBJECT (src, "query failed");
360 #define DEFINE_SINE(type,scale) \
362 gst_audio_test_src_create_sine_##type (GstAudioTestSrc * src, g##type * samples) \
364 gint i, c, channels; \
367 channels = GST_AUDIO_INFO_CHANNELS (&src->info); \
368 step = M_PI_M2 * src->freq / GST_AUDIO_INFO_RATE (&src->info); \
369 amp = src->volume * scale; \
372 while (i < (src->generate_samples_per_buffer * channels)) { \
373 src->accumulator += step; \
374 if (src->accumulator >= M_PI_M2) \
375 src->accumulator -= M_PI_M2; \
377 for (c = 0; c < channels; ++c) { \
378 samples[i++] = (g##type) (sin (src->accumulator) * amp); \
383 DEFINE_SINE (int16, 32767.0);
384 DEFINE_SINE (int32, 2147483647.0);
385 DEFINE_SINE (float, 1.0);
386 DEFINE_SINE (double, 1.0);
388 static const ProcessFunc sine_funcs[] = {
389 (ProcessFunc) gst_audio_test_src_create_sine_int16,
390 (ProcessFunc) gst_audio_test_src_create_sine_int32,
391 (ProcessFunc) gst_audio_test_src_create_sine_float,
392 (ProcessFunc) gst_audio_test_src_create_sine_double
395 #define DEFINE_SQUARE(type,scale) \
397 gst_audio_test_src_create_square_##type (GstAudioTestSrc * src, g##type * samples) \
399 gint i, c, channels; \
402 channels = GST_AUDIO_INFO_CHANNELS (&src->info); \
403 step = M_PI_M2 * src->freq / GST_AUDIO_INFO_RATE (&src->info); \
404 amp = src->volume * scale; \
407 while (i < (src->generate_samples_per_buffer * channels)) { \
408 src->accumulator += step; \
409 if (src->accumulator >= M_PI_M2) \
410 src->accumulator -= M_PI_M2; \
412 for (c = 0; c < channels; ++c) { \
413 samples[i++] = (g##type) ((src->accumulator < G_PI) ? amp : -amp); \
418 DEFINE_SQUARE (int16, 32767.0);
419 DEFINE_SQUARE (int32, 2147483647.0);
420 DEFINE_SQUARE (float, 1.0);
421 DEFINE_SQUARE (double, 1.0);
423 static const ProcessFunc square_funcs[] = {
424 (ProcessFunc) gst_audio_test_src_create_square_int16,
425 (ProcessFunc) gst_audio_test_src_create_square_int32,
426 (ProcessFunc) gst_audio_test_src_create_square_float,
427 (ProcessFunc) gst_audio_test_src_create_square_double
430 #define DEFINE_SAW(type,scale) \
432 gst_audio_test_src_create_saw_##type (GstAudioTestSrc * src, g##type * samples) \
434 gint i, c, channels; \
437 channels = GST_AUDIO_INFO_CHANNELS (&src->info); \
438 step = M_PI_M2 * src->freq / GST_AUDIO_INFO_RATE (&src->info); \
439 amp = (src->volume * scale) / G_PI; \
442 while (i < (src->generate_samples_per_buffer * channels)) { \
443 src->accumulator += step; \
444 if (src->accumulator >= M_PI_M2) \
445 src->accumulator -= M_PI_M2; \
447 if (src->accumulator < G_PI) { \
448 for (c = 0; c < channels; ++c) \
449 samples[i++] = (g##type) (src->accumulator * amp); \
451 for (c = 0; c < channels; ++c) \
452 samples[i++] = (g##type) ((M_PI_M2 - src->accumulator) * -amp); \
457 DEFINE_SAW (int16, 32767.0);
458 DEFINE_SAW (int32, 2147483647.0);
459 DEFINE_SAW (float, 1.0);
460 DEFINE_SAW (double, 1.0);
462 static const ProcessFunc saw_funcs[] = {
463 (ProcessFunc) gst_audio_test_src_create_saw_int16,
464 (ProcessFunc) gst_audio_test_src_create_saw_int32,
465 (ProcessFunc) gst_audio_test_src_create_saw_float,
466 (ProcessFunc) gst_audio_test_src_create_saw_double
469 #define DEFINE_TRIANGLE(type,scale) \
471 gst_audio_test_src_create_triangle_##type (GstAudioTestSrc * src, g##type * samples) \
473 gint i, c, channels; \
476 channels = GST_AUDIO_INFO_CHANNELS (&src->info); \
477 step = M_PI_M2 * src->freq / GST_AUDIO_INFO_RATE (&src->info); \
478 amp = (src->volume * scale) / G_PI_2; \
481 while (i < (src->generate_samples_per_buffer * channels)) { \
482 src->accumulator += step; \
483 if (src->accumulator >= M_PI_M2) \
484 src->accumulator -= M_PI_M2; \
486 if (src->accumulator < (G_PI_2)) { \
487 for (c = 0; c < channels; ++c) \
488 samples[i++] = (g##type) (src->accumulator * amp); \
489 } else if (src->accumulator < (G_PI * 1.5)) { \
490 for (c = 0; c < channels; ++c) \
491 samples[i++] = (g##type) ((src->accumulator - G_PI) * -amp); \
493 for (c = 0; c < channels; ++c) \
494 samples[i++] = (g##type) ((M_PI_M2 - src->accumulator) * -amp); \
499 DEFINE_TRIANGLE (int16, 32767.0);
500 DEFINE_TRIANGLE (int32, 2147483647.0);
501 DEFINE_TRIANGLE (float, 1.0);
502 DEFINE_TRIANGLE (double, 1.0);
504 static const ProcessFunc triangle_funcs[] = {
505 (ProcessFunc) gst_audio_test_src_create_triangle_int16,
506 (ProcessFunc) gst_audio_test_src_create_triangle_int32,
507 (ProcessFunc) gst_audio_test_src_create_triangle_float,
508 (ProcessFunc) gst_audio_test_src_create_triangle_double
511 #define DEFINE_SILENCE(type) \
513 gst_audio_test_src_create_silence_##type (GstAudioTestSrc * src, g##type * samples) \
515 memset (samples, 0, src->generate_samples_per_buffer * sizeof (g##type) * src->info.channels); \
518 DEFINE_SILENCE (int16);
519 DEFINE_SILENCE (int32);
520 DEFINE_SILENCE (float);
521 DEFINE_SILENCE (double);
523 static const ProcessFunc silence_funcs[] = {
524 (ProcessFunc) gst_audio_test_src_create_silence_int16,
525 (ProcessFunc) gst_audio_test_src_create_silence_int32,
526 (ProcessFunc) gst_audio_test_src_create_silence_float,
527 (ProcessFunc) gst_audio_test_src_create_silence_double
530 #define DEFINE_WHITE_NOISE(type,scale) \
532 gst_audio_test_src_create_white_noise_##type (GstAudioTestSrc * src, g##type * samples) \
535 gdouble amp = (src->volume * scale); \
536 gint channels = GST_AUDIO_INFO_CHANNELS (&src->info); \
539 while (i < (src->generate_samples_per_buffer * channels)) { \
540 for (c = 0; c < channels; ++c) \
541 samples[i++] = (g##type) (amp * g_rand_double_range (src->gen, -1.0, 1.0)); \
545 DEFINE_WHITE_NOISE (int16, 32767.0);
546 DEFINE_WHITE_NOISE (int32, 2147483647.0);
547 DEFINE_WHITE_NOISE (float, 1.0);
548 DEFINE_WHITE_NOISE (double, 1.0);
550 static const ProcessFunc white_noise_funcs[] = {
551 (ProcessFunc) gst_audio_test_src_create_white_noise_int16,
552 (ProcessFunc) gst_audio_test_src_create_white_noise_int32,
553 (ProcessFunc) gst_audio_test_src_create_white_noise_float,
554 (ProcessFunc) gst_audio_test_src_create_white_noise_double
557 /* pink noise calculation is based on
558 * http://www.firstpr.com.au/dsp/pink-noise/phil_burk_19990905_patest_pink.c
559 * which has been released under public domain
563 gst_audio_test_src_init_pink_noise (GstAudioTestSrc * src)
566 gint num_rows = 12; /* arbitrary: 1 .. PINK_MAX_RANDOM_ROWS */
570 src->pink.index_mask = (1 << num_rows) - 1;
571 /* calculate maximum possible signed random value.
572 * Extra 1 for white noise always added. */
573 pmax = (num_rows + 1) * (1 << (PINK_RANDOM_BITS - 1));
574 src->pink.scalar = 1.0f / pmax;
575 /* Initialize rows. */
576 for (i = 0; i < num_rows; i++)
577 src->pink.rows[i] = 0;
578 src->pink.running_sum = 0;
581 /* Generate Pink noise values between -1.0 and +1.0 */
583 gst_audio_test_src_generate_pink_noise_value (GstAudioTestSrc * src)
585 GstPinkNoise *pink = &src->pink;
589 /* Increment and mask index. */
590 pink->index = (pink->index + 1) & pink->index_mask;
592 /* If index is zero, don't update any random values. */
593 if (pink->index != 0) {
594 /* Determine how many trailing zeros in PinkIndex. */
595 /* This algorithm will hang if n==0 so test first. */
597 gint n = pink->index;
599 while ((n & 1) == 0) {
604 /* Replace the indexed ROWS random value.
605 * Subtract and add back to RunningSum instead of adding all the random
606 * values together. Only one changes each time.
608 pink->running_sum -= pink->rows[num_zeros];
609 new_random = 32768.0 - (65536.0 * (gulong) g_rand_int (src->gen)
610 / (G_MAXUINT32 + 1.0));
611 pink->running_sum += new_random;
612 pink->rows[num_zeros] = new_random;
615 /* Add extra white noise value. */
616 new_random = 32768.0 - (65536.0 * (gulong) g_rand_int (src->gen)
617 / (G_MAXUINT32 + 1.0));
618 sum = pink->running_sum + new_random;
620 /* Scale to range of -1.0 to 0.9999. */
621 return (pink->scalar * sum);
624 #define DEFINE_PINK(type, scale) \
626 gst_audio_test_src_create_pink_noise_##type (GstAudioTestSrc * src, g##type * samples) \
628 gint i, c, channels; \
631 amp = src->volume * scale; \
632 channels = GST_AUDIO_INFO_CHANNELS (&src->info); \
635 while (i < (src->generate_samples_per_buffer * channels)) { \
636 for (c = 0; c < channels; ++c) { \
638 (g##type) (gst_audio_test_src_generate_pink_noise_value (src) * \
644 DEFINE_PINK (int16, 32767.0);
645 DEFINE_PINK (int32, 2147483647.0);
646 DEFINE_PINK (float, 1.0);
647 DEFINE_PINK (double, 1.0);
649 static const ProcessFunc pink_noise_funcs[] = {
650 (ProcessFunc) gst_audio_test_src_create_pink_noise_int16,
651 (ProcessFunc) gst_audio_test_src_create_pink_noise_int32,
652 (ProcessFunc) gst_audio_test_src_create_pink_noise_float,
653 (ProcessFunc) gst_audio_test_src_create_pink_noise_double
657 gst_audio_test_src_init_sine_table (GstAudioTestSrc * src)
661 gdouble step = M_PI_M2 / 1024.0;
662 gdouble amp = src->volume;
664 for (i = 0; i < 1024; i++) {
665 src->wave_table[i] = sin (ang) * amp;
670 #define DEFINE_SINE_TABLE(type,scale) \
672 gst_audio_test_src_create_sine_table_##type (GstAudioTestSrc * src, g##type * samples) \
674 gint i, c, channels; \
677 channels = GST_AUDIO_INFO_CHANNELS (&src->info); \
678 step = M_PI_M2 * src->freq / GST_AUDIO_INFO_RATE (&src->info); \
679 scl = 1024.0 / M_PI_M2; \
682 while (i < (src->generate_samples_per_buffer * channels)) { \
683 src->accumulator += step; \
684 if (src->accumulator >= M_PI_M2) \
685 src->accumulator -= M_PI_M2; \
687 for (c = 0; c < channels; ++c) \
688 samples[i++] = (g##type) scale * src->wave_table[(gint) (src->accumulator * scl)]; \
692 DEFINE_SINE_TABLE (int16, 32767.0);
693 DEFINE_SINE_TABLE (int32, 2147483647.0);
694 DEFINE_SINE_TABLE (float, 1.0);
695 DEFINE_SINE_TABLE (double, 1.0);
697 static const ProcessFunc sine_table_funcs[] = {
698 (ProcessFunc) gst_audio_test_src_create_sine_table_int16,
699 (ProcessFunc) gst_audio_test_src_create_sine_table_int32,
700 (ProcessFunc) gst_audio_test_src_create_sine_table_float,
701 (ProcessFunc) gst_audio_test_src_create_sine_table_double
704 #define DEFINE_TICKS(type,scale) \
706 gst_audio_test_src_create_tick_##type (GstAudioTestSrc * src, g##type * samples) \
708 gint i, c, channels, samplerate; \
711 channels = GST_AUDIO_INFO_CHANNELS (&src->info); \
712 samplerate = GST_AUDIO_INFO_RATE (&src->info); \
713 step = M_PI_M2 * src->freq / samplerate; \
714 scl = 1024.0 / M_PI_M2; \
716 for (i = 0; i < src->generate_samples_per_buffer; i++) { \
717 src->accumulator += step; \
718 if (src->accumulator >= M_PI_M2) \
719 src->accumulator -= M_PI_M2; \
721 if ((src->next_sample + i)%samplerate < 1600) { \
722 for (c = 0; c < channels; ++c) \
723 samples[(i * channels) + c] = (g##type) scale * src->wave_table[(gint) (src->accumulator * scl)]; \
725 for (c = 0; c < channels; ++c) \
726 samples[(i * channels) + c] = 0; \
731 DEFINE_TICKS (int16, 32767.0);
732 DEFINE_TICKS (int32, 2147483647.0);
733 DEFINE_TICKS (float, 1.0);
734 DEFINE_TICKS (double, 1.0);
736 static const ProcessFunc tick_funcs[] = {
737 (ProcessFunc) gst_audio_test_src_create_tick_int16,
738 (ProcessFunc) gst_audio_test_src_create_tick_int32,
739 (ProcessFunc) gst_audio_test_src_create_tick_float,
740 (ProcessFunc) gst_audio_test_src_create_tick_double
743 /* Gaussian white noise using Box-Muller algorithm. unit variance
744 * normally-distributed random numbers are generated in pairs as the real
745 * and imaginary parts of a compex random variable with
746 * uniformly-distributed argument and \chi^{2}-distributed modulus.
749 #define DEFINE_GAUSSIAN_WHITE_NOISE(type,scale) \
751 gst_audio_test_src_create_gaussian_white_noise_##type (GstAudioTestSrc * src, g##type * samples) \
754 gdouble amp = (src->volume * scale); \
755 gint channels = GST_AUDIO_INFO_CHANNELS (&src->info); \
757 for (i = 0; i < src->generate_samples_per_buffer * channels; ) { \
758 for (c = 0; c < channels; ++c) { \
759 gdouble mag = sqrt (-2 * log (1.0 - g_rand_double (src->gen))); \
760 gdouble phs = g_rand_double_range (src->gen, 0.0, M_PI_M2); \
762 samples[i++] = (g##type) (amp * mag * cos (phs)); \
763 if (++c >= channels) \
765 samples[i++] = (g##type) (amp * mag * sin (phs)); \
770 DEFINE_GAUSSIAN_WHITE_NOISE (int16, 32767.0);
771 DEFINE_GAUSSIAN_WHITE_NOISE (int32, 2147483647.0);
772 DEFINE_GAUSSIAN_WHITE_NOISE (float, 1.0);
773 DEFINE_GAUSSIAN_WHITE_NOISE (double, 1.0);
775 static const ProcessFunc gaussian_white_noise_funcs[] = {
776 (ProcessFunc) gst_audio_test_src_create_gaussian_white_noise_int16,
777 (ProcessFunc) gst_audio_test_src_create_gaussian_white_noise_int32,
778 (ProcessFunc) gst_audio_test_src_create_gaussian_white_noise_float,
779 (ProcessFunc) gst_audio_test_src_create_gaussian_white_noise_double
782 /* Brownian (Red) Noise: noise where the power density decreases by 6 dB per
783 * octave with increasing frequency
785 * taken from http://vellocet.com/dsp/noise/VRand.html
786 * by Andrew Simper of Vellocet (andy@vellocet.com)
789 #define DEFINE_RED_NOISE(type,scale) \
791 gst_audio_test_src_create_red_noise_##type (GstAudioTestSrc * src, g##type * samples) \
794 gdouble amp = (src->volume * scale); \
795 gdouble state = src->red.state; \
796 gint channels = GST_AUDIO_INFO_CHANNELS (&src->info); \
798 for (i = 0; i < src->generate_samples_per_buffer * channels; ) { \
799 for (c = 0; c < channels; ++c) { \
801 gdouble r = g_rand_double_range (src->gen, -1.0, 1.0); \
803 if (state < -8.0f || state > 8.0f) state -= r; \
806 samples[i++] = (g##type) (amp * state * 0.0625f); /* /16.0 */ \
809 src->red.state = state; \
812 DEFINE_RED_NOISE (int16, 32767.0);
813 DEFINE_RED_NOISE (int32, 2147483647.0);
814 DEFINE_RED_NOISE (float, 1.0);
815 DEFINE_RED_NOISE (double, 1.0);
817 static const ProcessFunc red_noise_funcs[] = {
818 (ProcessFunc) gst_audio_test_src_create_red_noise_int16,
819 (ProcessFunc) gst_audio_test_src_create_red_noise_int32,
820 (ProcessFunc) gst_audio_test_src_create_red_noise_float,
821 (ProcessFunc) gst_audio_test_src_create_red_noise_double
824 /* Blue Noise: apply spectral inversion to pink noise */
826 #define DEFINE_BLUE_NOISE(type) \
828 gst_audio_test_src_create_blue_noise_##type (GstAudioTestSrc * src, g##type * samples) \
831 static gdouble flip=1.0; \
832 gint channels = GST_AUDIO_INFO_CHANNELS (&src->info); \
834 gst_audio_test_src_create_pink_noise_##type (src, samples); \
835 for (i = 0; i < src->generate_samples_per_buffer * channels; ) { \
836 for (c = 0; c < channels; ++c) { \
837 samples[i++] *= flip; \
843 DEFINE_BLUE_NOISE (int16);
844 DEFINE_BLUE_NOISE (int32);
845 DEFINE_BLUE_NOISE (float);
846 DEFINE_BLUE_NOISE (double);
848 static const ProcessFunc blue_noise_funcs[] = {
849 (ProcessFunc) gst_audio_test_src_create_blue_noise_int16,
850 (ProcessFunc) gst_audio_test_src_create_blue_noise_int32,
851 (ProcessFunc) gst_audio_test_src_create_blue_noise_float,
852 (ProcessFunc) gst_audio_test_src_create_blue_noise_double
856 /* Violet Noise: apply spectral inversion to red noise */
858 #define DEFINE_VIOLET_NOISE(type) \
860 gst_audio_test_src_create_violet_noise_##type (GstAudioTestSrc * src, g##type * samples) \
863 static gdouble flip=1.0; \
864 gint channels = GST_AUDIO_INFO_CHANNELS (&src->info); \
866 gst_audio_test_src_create_red_noise_##type (src, samples); \
867 for (i = 0; i < src->generate_samples_per_buffer * channels; ) { \
868 for (c = 0; c < channels; ++c) { \
869 samples[i++] *= flip; \
875 DEFINE_VIOLET_NOISE (int16);
876 DEFINE_VIOLET_NOISE (int32);
877 DEFINE_VIOLET_NOISE (float);
878 DEFINE_VIOLET_NOISE (double);
880 static const ProcessFunc violet_noise_funcs[] = {
881 (ProcessFunc) gst_audio_test_src_create_violet_noise_int16,
882 (ProcessFunc) gst_audio_test_src_create_violet_noise_int32,
883 (ProcessFunc) gst_audio_test_src_create_violet_noise_float,
884 (ProcessFunc) gst_audio_test_src_create_violet_noise_double
889 * gst_audio_test_src_change_wave:
890 * Assign function pointer of wave generator.
893 gst_audio_test_src_change_wave (GstAudioTestSrc * src)
897 /* not negotiated yet? */
898 if (src->info.finfo == NULL) {
903 switch (GST_AUDIO_FORMAT_INFO_FORMAT (src->info.finfo)) {
904 case GST_AUDIO_FORMAT_S16:
907 case GST_AUDIO_FORMAT_S32:
910 case GST_AUDIO_FORMAT_F32:
913 case GST_AUDIO_FORMAT_F64:
922 case GST_AUDIO_TEST_SRC_WAVE_SINE:
923 src->process = sine_funcs[idx];
925 case GST_AUDIO_TEST_SRC_WAVE_SQUARE:
926 src->process = square_funcs[idx];
928 case GST_AUDIO_TEST_SRC_WAVE_SAW:
929 src->process = saw_funcs[idx];
931 case GST_AUDIO_TEST_SRC_WAVE_TRIANGLE:
932 src->process = triangle_funcs[idx];
934 case GST_AUDIO_TEST_SRC_WAVE_SILENCE:
935 src->process = silence_funcs[idx];
937 case GST_AUDIO_TEST_SRC_WAVE_WHITE_NOISE:
939 src->gen = g_rand_new ();
940 src->process = white_noise_funcs[idx];
942 case GST_AUDIO_TEST_SRC_WAVE_PINK_NOISE:
944 src->gen = g_rand_new ();
945 gst_audio_test_src_init_pink_noise (src);
946 src->process = pink_noise_funcs[idx];
948 case GST_AUDIO_TEST_SRC_WAVE_SINE_TAB:
949 gst_audio_test_src_init_sine_table (src);
950 src->process = sine_table_funcs[idx];
952 case GST_AUDIO_TEST_SRC_WAVE_TICKS:
953 gst_audio_test_src_init_sine_table (src);
954 src->process = tick_funcs[idx];
956 case GST_AUDIO_TEST_SRC_WAVE_GAUSSIAN_WHITE_NOISE:
958 src->gen = g_rand_new ();
959 src->process = gaussian_white_noise_funcs[idx];
961 case GST_AUDIO_TEST_SRC_WAVE_RED_NOISE:
963 src->gen = g_rand_new ();
964 src->red.state = 0.0;
965 src->process = red_noise_funcs[idx];
967 case GST_AUDIO_TEST_SRC_WAVE_BLUE_NOISE:
969 src->gen = g_rand_new ();
970 gst_audio_test_src_init_pink_noise (src);
971 src->process = blue_noise_funcs[idx];
973 case GST_AUDIO_TEST_SRC_WAVE_VIOLET_NOISE:
975 src->gen = g_rand_new ();
976 src->red.state = 0.0;
977 src->process = violet_noise_funcs[idx];
980 GST_ERROR ("invalid wave-form");
986 * gst_audio_test_src_change_volume:
987 * Recalc wave tables for precalculated waves.
990 gst_audio_test_src_change_volume (GstAudioTestSrc * src)
993 case GST_AUDIO_TEST_SRC_WAVE_SINE_TAB:
994 gst_audio_test_src_init_sine_table (src);
1002 gst_audio_test_src_get_times (GstBaseSrc * basesrc, GstBuffer * buffer,
1003 GstClockTime * start, GstClockTime * end)
1005 /* for live sources, sync on the timestamp of the buffer */
1006 if (gst_base_src_is_live (basesrc)) {
1007 GstClockTime timestamp = GST_BUFFER_TIMESTAMP (buffer);
1009 if (GST_CLOCK_TIME_IS_VALID (timestamp)) {
1010 /* get duration to calculate end time */
1011 GstClockTime duration = GST_BUFFER_DURATION (buffer);
1013 if (GST_CLOCK_TIME_IS_VALID (duration)) {
1014 *end = timestamp + duration;
1025 gst_audio_test_src_start (GstBaseSrc * basesrc)
1027 GstAudioTestSrc *src = GST_AUDIO_TEST_SRC (basesrc);
1029 src->next_sample = 0;
1032 src->check_seek_stop = FALSE;
1033 src->eos_reached = FALSE;
1034 src->tags_pushed = FALSE;
1035 src->accumulator = 0;
1041 gst_audio_test_src_stop (GstBaseSrc * basesrc)
1046 /* seek to time, will be called when we operate in push mode. In pull mode we
1047 * get the requested byte offset. */
1049 gst_audio_test_src_do_seek (GstBaseSrc * basesrc, GstSegment * segment)
1051 GstAudioTestSrc *src = GST_AUDIO_TEST_SRC (basesrc);
1053 gint samplerate, bpf;
1055 GST_DEBUG_OBJECT (src, "seeking %" GST_SEGMENT_FORMAT, segment);
1057 time = segment->position;
1058 src->reverse = (segment->rate < 0.0);
1060 samplerate = GST_AUDIO_INFO_RATE (&src->info);
1061 bpf = GST_AUDIO_INFO_BPF (&src->info);
1063 /* now move to the time indicated */
1064 src->next_sample = gst_util_uint64_scale_int (time, samplerate, GST_SECOND);
1065 src->next_byte = src->next_sample * bpf;
1066 if (samplerate == 0)
1070 gst_util_uint64_scale_int (src->next_sample, GST_SECOND, samplerate);
1072 GST_DEBUG_OBJECT (src, "seeking next_sample=%" G_GINT64_FORMAT
1073 " next_time=%" GST_TIME_FORMAT, src->next_sample,
1074 GST_TIME_ARGS (src->next_time));
1076 g_assert (src->next_time <= time);
1078 if (!src->reverse) {
1079 if (GST_CLOCK_TIME_IS_VALID (segment->start)) {
1080 segment->time = segment->start;
1083 if (GST_CLOCK_TIME_IS_VALID (segment->stop)) {
1084 segment->time = segment->stop;
1088 if (GST_CLOCK_TIME_IS_VALID (segment->stop)) {
1089 time = segment->stop;
1090 src->sample_stop = gst_util_uint64_scale_int (time, samplerate, GST_SECOND);
1091 src->check_seek_stop = TRUE;
1093 src->check_seek_stop = FALSE;
1095 src->eos_reached = FALSE;
1101 gst_audio_test_src_is_seekable (GstBaseSrc * basesrc)
1103 /* we're seekable... */
1107 static GstFlowReturn
1108 gst_audio_test_src_fill (GstBaseSrc * basesrc, guint64 offset,
1109 guint length, GstBuffer * buffer)
1111 GstAudioTestSrc *src;
1112 GstClockTime next_time;
1113 gint64 next_sample, next_byte;
1114 gint bytes, samples;
1115 GstElementClass *eclass;
1117 gint samplerate, bpf;
1119 src = GST_AUDIO_TEST_SRC (basesrc);
1121 /* example for tagging generated data */
1122 if (!src->tags_pushed) {
1123 GstTagList *taglist;
1125 taglist = gst_tag_list_new (GST_TAG_DESCRIPTION, "audiotest wave", NULL);
1127 eclass = GST_ELEMENT_CLASS (parent_class);
1128 if (eclass->send_event)
1129 eclass->send_event (GST_ELEMENT_CAST (basesrc),
1130 gst_event_new_tag (taglist));
1132 gst_tag_list_free (taglist);
1133 src->tags_pushed = TRUE;
1136 if (src->eos_reached) {
1137 GST_INFO_OBJECT (src, "eos");
1138 return GST_FLOW_EOS;
1141 samplerate = GST_AUDIO_INFO_RATE (&src->info);
1142 bpf = GST_AUDIO_INFO_BPF (&src->info);
1144 /* if no length was given, use our default length in samples otherwise convert
1145 * the length in bytes to samples. */
1147 samples = src->samples_per_buffer;
1149 samples = length / bpf;
1151 /* if no offset was given, use our next logical byte */
1153 offset = src->next_byte;
1155 /* now see if we are at the byteoffset we think we are */
1156 if (offset != src->next_byte) {
1157 GST_DEBUG_OBJECT (src, "seek to new offset %" G_GUINT64_FORMAT, offset);
1158 /* we have a discont in the expected sample offset, do a 'seek' */
1159 src->next_sample = offset / bpf;
1161 gst_util_uint64_scale_int (src->next_sample, GST_SECOND, samplerate);
1162 src->next_byte = offset;
1166 if (src->check_seek_stop &&
1167 (src->sample_stop > src->next_sample) &&
1168 (src->sample_stop < src->next_sample + samples)
1170 /* calculate only partial buffer */
1171 src->generate_samples_per_buffer = src->sample_stop - src->next_sample;
1172 next_sample = src->sample_stop;
1173 src->eos_reached = TRUE;
1175 /* calculate full buffer */
1176 src->generate_samples_per_buffer = samples;
1177 next_sample = src->next_sample + (src->reverse ? (-samples) : samples);
1180 bytes = src->generate_samples_per_buffer * bpf;
1182 next_byte = src->next_byte + (src->reverse ? (-bytes) : bytes);
1183 next_time = gst_util_uint64_scale_int (next_sample, GST_SECOND, samplerate);
1185 GST_LOG_OBJECT (src, "samplerate %d", samplerate);
1186 GST_LOG_OBJECT (src, "next_sample %" G_GINT64_FORMAT ", ts %" GST_TIME_FORMAT,
1187 next_sample, GST_TIME_ARGS (next_time));
1189 GST_BUFFER_OFFSET (buffer) = src->next_sample;
1190 GST_BUFFER_OFFSET_END (buffer) = next_sample;
1191 if (!src->reverse) {
1192 GST_BUFFER_TIMESTAMP (buffer) = src->timestamp_offset + src->next_time;
1193 GST_BUFFER_DURATION (buffer) = next_time - src->next_time;
1195 GST_BUFFER_TIMESTAMP (buffer) = src->timestamp_offset + next_time;
1196 GST_BUFFER_DURATION (buffer) = src->next_time - next_time;
1199 gst_object_sync_values (GST_OBJECT (src), GST_BUFFER_TIMESTAMP (buffer));
1201 src->next_time = next_time;
1202 src->next_sample = next_sample;
1203 src->next_byte = next_byte;
1205 GST_LOG_OBJECT (src, "generating %u samples at ts %" GST_TIME_FORMAT,
1206 src->generate_samples_per_buffer,
1207 GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buffer)));
1209 data = gst_buffer_map (buffer, NULL, NULL, GST_MAP_WRITE);
1210 src->process (src, data);
1211 gst_buffer_unmap (buffer, data, bytes);
1213 if (G_UNLIKELY ((src->wave == GST_AUDIO_TEST_SRC_WAVE_SILENCE)
1214 || (src->volume == 0.0))) {
1215 GST_BUFFER_FLAG_SET (buffer, GST_BUFFER_FLAG_GAP);
1222 gst_audio_test_src_set_property (GObject * object, guint prop_id,
1223 const GValue * value, GParamSpec * pspec)
1225 GstAudioTestSrc *src = GST_AUDIO_TEST_SRC (object);
1228 case PROP_SAMPLES_PER_BUFFER:
1229 src->samples_per_buffer = g_value_get_int (value);
1230 gst_base_src_set_blocksize (GST_BASE_SRC_CAST (src),
1231 GST_AUDIO_INFO_BPF (&src->info) * src->samples_per_buffer);
1234 src->wave = g_value_get_enum (value);
1235 gst_audio_test_src_change_wave (src);
1238 src->freq = g_value_get_double (value);
1241 src->volume = g_value_get_double (value);
1242 gst_audio_test_src_change_volume (src);
1245 gst_base_src_set_live (GST_BASE_SRC (src), g_value_get_boolean (value));
1247 case PROP_TIMESTAMP_OFFSET:
1248 src->timestamp_offset = g_value_get_int64 (value);
1250 case PROP_CAN_ACTIVATE_PUSH:
1251 GST_BASE_SRC (src)->can_activate_push = g_value_get_boolean (value);
1253 case PROP_CAN_ACTIVATE_PULL:
1254 src->can_activate_pull = g_value_get_boolean (value);
1257 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1263 gst_audio_test_src_get_property (GObject * object, guint prop_id,
1264 GValue * value, GParamSpec * pspec)
1266 GstAudioTestSrc *src = GST_AUDIO_TEST_SRC (object);
1269 case PROP_SAMPLES_PER_BUFFER:
1270 g_value_set_int (value, src->samples_per_buffer);
1273 g_value_set_enum (value, src->wave);
1276 g_value_set_double (value, src->freq);
1279 g_value_set_double (value, src->volume);
1282 g_value_set_boolean (value, gst_base_src_is_live (GST_BASE_SRC (src)));
1284 case PROP_TIMESTAMP_OFFSET:
1285 g_value_set_int64 (value, src->timestamp_offset);
1287 case PROP_CAN_ACTIVATE_PUSH:
1288 g_value_set_boolean (value, GST_BASE_SRC (src)->can_activate_push);
1290 case PROP_CAN_ACTIVATE_PULL:
1291 g_value_set_boolean (value, src->can_activate_pull);
1294 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1300 plugin_init (GstPlugin * plugin)
1302 GST_DEBUG_CATEGORY_INIT (audio_test_src_debug, "audiotestsrc", 0,
1303 "Audio Test Source");
1305 return gst_element_register (plugin, "audiotestsrc",
1306 GST_RANK_NONE, GST_TYPE_AUDIO_TEST_SRC);
1309 GST_PLUGIN_DEFINE (GST_VERSION_MAJOR,
1312 "Creates audio test signals of given frequency and volume",
1313 plugin_init, VERSION, "LGPL", GST_PACKAGE_NAME, GST_PACKAGE_ORIGIN);