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., 51 Franklin St, Fifth Floor,
17 * Boston, MA 02110-1301, 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 ], " "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 GstCaps *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_static_metadata (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 caps = gst_caps_make_writable (caps);
267 structure = gst_caps_get_structure (caps, 0);
269 GST_DEBUG_OBJECT (src, "fixating samplerate to %d", GST_AUDIO_DEF_RATE);
271 gst_structure_fixate_field_nearest_int (structure, "rate",
274 gst_structure_fixate_field_string (structure, "format", DEFAULT_FORMAT_STR);
276 /* fixate to mono unless downstream requires stereo, for backwards compat */
277 gst_structure_fixate_field_nearest_int (structure, "channels", 1);
279 caps = GST_BASE_SRC_CLASS (parent_class)->fixate (bsrc, caps);
285 gst_audio_test_src_setcaps (GstBaseSrc * basesrc, GstCaps * caps)
287 GstAudioTestSrc *src = GST_AUDIO_TEST_SRC (basesrc);
290 if (!gst_audio_info_from_caps (&info, caps))
293 GST_DEBUG_OBJECT (src, "negotiated to caps %" GST_PTR_FORMAT, caps);
297 gst_base_src_set_blocksize (basesrc,
298 GST_AUDIO_INFO_BPF (&info) * src->samples_per_buffer);
299 gst_audio_test_src_change_wave (src);
306 GST_ERROR_OBJECT (basesrc, "received invalid caps");
312 gst_audio_test_src_query (GstBaseSrc * basesrc, GstQuery * query)
314 GstAudioTestSrc *src = GST_AUDIO_TEST_SRC (basesrc);
315 gboolean res = FALSE;
317 switch (GST_QUERY_TYPE (query)) {
318 case GST_QUERY_CONVERT:
320 GstFormat src_fmt, dest_fmt;
321 gint64 src_val, dest_val;
323 gst_query_parse_convert (query, &src_fmt, &src_val, &dest_fmt, &dest_val);
325 if (!gst_audio_info_convert (&src->info, src_fmt, src_val, dest_fmt,
329 gst_query_set_convert (query, src_fmt, src_val, dest_fmt, dest_val);
333 case GST_QUERY_SCHEDULING:
335 /* if we can operate in pull mode */
336 gst_query_set_scheduling (query, GST_SCHEDULING_FLAG_SEEKABLE, 1, -1, 0);
337 gst_query_add_scheduling_mode (query, GST_PAD_MODE_PUSH);
338 if (src->can_activate_pull)
339 gst_query_add_scheduling_mode (query, GST_PAD_MODE_PULL);
345 res = GST_BASE_SRC_CLASS (parent_class)->query (basesrc, query);
353 GST_DEBUG_OBJECT (src, "query failed");
358 #define DEFINE_SINE(type,scale) \
360 gst_audio_test_src_create_sine_##type (GstAudioTestSrc * src, g##type * samples) \
362 gint i, c, channels; \
365 channels = GST_AUDIO_INFO_CHANNELS (&src->info); \
366 step = M_PI_M2 * src->freq / GST_AUDIO_INFO_RATE (&src->info); \
367 amp = src->volume * scale; \
370 while (i < (src->generate_samples_per_buffer * channels)) { \
371 src->accumulator += step; \
372 if (src->accumulator >= M_PI_M2) \
373 src->accumulator -= M_PI_M2; \
375 for (c = 0; c < channels; ++c) { \
376 samples[i++] = (g##type) (sin (src->accumulator) * amp); \
381 DEFINE_SINE (int16, 32767.0);
382 DEFINE_SINE (int32, 2147483647.0);
383 DEFINE_SINE (float, 1.0);
384 DEFINE_SINE (double, 1.0);
386 static const ProcessFunc sine_funcs[] = {
387 (ProcessFunc) gst_audio_test_src_create_sine_int16,
388 (ProcessFunc) gst_audio_test_src_create_sine_int32,
389 (ProcessFunc) gst_audio_test_src_create_sine_float,
390 (ProcessFunc) gst_audio_test_src_create_sine_double
393 #define DEFINE_SQUARE(type,scale) \
395 gst_audio_test_src_create_square_##type (GstAudioTestSrc * src, g##type * samples) \
397 gint i, c, channels; \
400 channels = GST_AUDIO_INFO_CHANNELS (&src->info); \
401 step = M_PI_M2 * src->freq / GST_AUDIO_INFO_RATE (&src->info); \
402 amp = src->volume * scale; \
405 while (i < (src->generate_samples_per_buffer * channels)) { \
406 src->accumulator += step; \
407 if (src->accumulator >= M_PI_M2) \
408 src->accumulator -= M_PI_M2; \
410 for (c = 0; c < channels; ++c) { \
411 samples[i++] = (g##type) ((src->accumulator < G_PI) ? amp : -amp); \
416 DEFINE_SQUARE (int16, 32767.0);
417 DEFINE_SQUARE (int32, 2147483647.0);
418 DEFINE_SQUARE (float, 1.0);
419 DEFINE_SQUARE (double, 1.0);
421 static const ProcessFunc square_funcs[] = {
422 (ProcessFunc) gst_audio_test_src_create_square_int16,
423 (ProcessFunc) gst_audio_test_src_create_square_int32,
424 (ProcessFunc) gst_audio_test_src_create_square_float,
425 (ProcessFunc) gst_audio_test_src_create_square_double
428 #define DEFINE_SAW(type,scale) \
430 gst_audio_test_src_create_saw_##type (GstAudioTestSrc * src, g##type * samples) \
432 gint i, c, channels; \
435 channels = GST_AUDIO_INFO_CHANNELS (&src->info); \
436 step = M_PI_M2 * src->freq / GST_AUDIO_INFO_RATE (&src->info); \
437 amp = (src->volume * scale) / G_PI; \
440 while (i < (src->generate_samples_per_buffer * channels)) { \
441 src->accumulator += step; \
442 if (src->accumulator >= M_PI_M2) \
443 src->accumulator -= M_PI_M2; \
445 if (src->accumulator < G_PI) { \
446 for (c = 0; c < channels; ++c) \
447 samples[i++] = (g##type) (src->accumulator * amp); \
449 for (c = 0; c < channels; ++c) \
450 samples[i++] = (g##type) ((M_PI_M2 - src->accumulator) * -amp); \
455 DEFINE_SAW (int16, 32767.0);
456 DEFINE_SAW (int32, 2147483647.0);
457 DEFINE_SAW (float, 1.0);
458 DEFINE_SAW (double, 1.0);
460 static const ProcessFunc saw_funcs[] = {
461 (ProcessFunc) gst_audio_test_src_create_saw_int16,
462 (ProcessFunc) gst_audio_test_src_create_saw_int32,
463 (ProcessFunc) gst_audio_test_src_create_saw_float,
464 (ProcessFunc) gst_audio_test_src_create_saw_double
467 #define DEFINE_TRIANGLE(type,scale) \
469 gst_audio_test_src_create_triangle_##type (GstAudioTestSrc * src, g##type * samples) \
471 gint i, c, channels; \
474 channels = GST_AUDIO_INFO_CHANNELS (&src->info); \
475 step = M_PI_M2 * src->freq / GST_AUDIO_INFO_RATE (&src->info); \
476 amp = (src->volume * scale) / G_PI_2; \
479 while (i < (src->generate_samples_per_buffer * channels)) { \
480 src->accumulator += step; \
481 if (src->accumulator >= M_PI_M2) \
482 src->accumulator -= M_PI_M2; \
484 if (src->accumulator < (G_PI_2)) { \
485 for (c = 0; c < channels; ++c) \
486 samples[i++] = (g##type) (src->accumulator * amp); \
487 } else if (src->accumulator < (G_PI * 1.5)) { \
488 for (c = 0; c < channels; ++c) \
489 samples[i++] = (g##type) ((src->accumulator - G_PI) * -amp); \
491 for (c = 0; c < channels; ++c) \
492 samples[i++] = (g##type) ((M_PI_M2 - src->accumulator) * -amp); \
497 DEFINE_TRIANGLE (int16, 32767.0);
498 DEFINE_TRIANGLE (int32, 2147483647.0);
499 DEFINE_TRIANGLE (float, 1.0);
500 DEFINE_TRIANGLE (double, 1.0);
502 static const ProcessFunc triangle_funcs[] = {
503 (ProcessFunc) gst_audio_test_src_create_triangle_int16,
504 (ProcessFunc) gst_audio_test_src_create_triangle_int32,
505 (ProcessFunc) gst_audio_test_src_create_triangle_float,
506 (ProcessFunc) gst_audio_test_src_create_triangle_double
509 #define DEFINE_SILENCE(type) \
511 gst_audio_test_src_create_silence_##type (GstAudioTestSrc * src, g##type * samples) \
513 memset (samples, 0, src->generate_samples_per_buffer * sizeof (g##type) * src->info.channels); \
516 DEFINE_SILENCE (int16);
517 DEFINE_SILENCE (int32);
518 DEFINE_SILENCE (float);
519 DEFINE_SILENCE (double);
521 static const ProcessFunc silence_funcs[] = {
522 (ProcessFunc) gst_audio_test_src_create_silence_int16,
523 (ProcessFunc) gst_audio_test_src_create_silence_int32,
524 (ProcessFunc) gst_audio_test_src_create_silence_float,
525 (ProcessFunc) gst_audio_test_src_create_silence_double
528 #define DEFINE_WHITE_NOISE(type,scale) \
530 gst_audio_test_src_create_white_noise_##type (GstAudioTestSrc * src, g##type * samples) \
533 gdouble amp = (src->volume * scale); \
534 gint channels = GST_AUDIO_INFO_CHANNELS (&src->info); \
537 while (i < (src->generate_samples_per_buffer * channels)) { \
538 for (c = 0; c < channels; ++c) \
539 samples[i++] = (g##type) (amp * g_rand_double_range (src->gen, -1.0, 1.0)); \
543 DEFINE_WHITE_NOISE (int16, 32767.0);
544 DEFINE_WHITE_NOISE (int32, 2147483647.0);
545 DEFINE_WHITE_NOISE (float, 1.0);
546 DEFINE_WHITE_NOISE (double, 1.0);
548 static const ProcessFunc white_noise_funcs[] = {
549 (ProcessFunc) gst_audio_test_src_create_white_noise_int16,
550 (ProcessFunc) gst_audio_test_src_create_white_noise_int32,
551 (ProcessFunc) gst_audio_test_src_create_white_noise_float,
552 (ProcessFunc) gst_audio_test_src_create_white_noise_double
555 /* pink noise calculation is based on
556 * http://www.firstpr.com.au/dsp/pink-noise/phil_burk_19990905_patest_pink.c
557 * which has been released under public domain
561 gst_audio_test_src_init_pink_noise (GstAudioTestSrc * src)
564 gint num_rows = 12; /* arbitrary: 1 .. PINK_MAX_RANDOM_ROWS */
568 src->pink.index_mask = (1 << num_rows) - 1;
569 /* calculate maximum possible signed random value.
570 * Extra 1 for white noise always added. */
571 pmax = (num_rows + 1) * (1 << (PINK_RANDOM_BITS - 1));
572 src->pink.scalar = 1.0f / pmax;
573 /* Initialize rows. */
574 for (i = 0; i < num_rows; i++)
575 src->pink.rows[i] = 0;
576 src->pink.running_sum = 0;
579 /* Generate Pink noise values between -1.0 and +1.0 */
581 gst_audio_test_src_generate_pink_noise_value (GstAudioTestSrc * src)
583 GstPinkNoise *pink = &src->pink;
587 /* Increment and mask index. */
588 pink->index = (pink->index + 1) & pink->index_mask;
590 /* If index is zero, don't update any random values. */
591 if (pink->index != 0) {
592 /* Determine how many trailing zeros in PinkIndex. */
593 /* This algorithm will hang if n==0 so test first. */
595 gint n = pink->index;
597 while ((n & 1) == 0) {
602 /* Replace the indexed ROWS random value.
603 * Subtract and add back to RunningSum instead of adding all the random
604 * values together. Only one changes each time.
606 pink->running_sum -= pink->rows[num_zeros];
607 new_random = 32768.0 - (65536.0 * (gulong) g_rand_int (src->gen)
608 / (G_MAXUINT32 + 1.0));
609 pink->running_sum += new_random;
610 pink->rows[num_zeros] = new_random;
613 /* Add extra white noise value. */
614 new_random = 32768.0 - (65536.0 * (gulong) g_rand_int (src->gen)
615 / (G_MAXUINT32 + 1.0));
616 sum = pink->running_sum + new_random;
618 /* Scale to range of -1.0 to 0.9999. */
619 return (pink->scalar * sum);
622 #define DEFINE_PINK(type, scale) \
624 gst_audio_test_src_create_pink_noise_##type (GstAudioTestSrc * src, g##type * samples) \
626 gint i, c, channels; \
629 amp = src->volume * scale; \
630 channels = GST_AUDIO_INFO_CHANNELS (&src->info); \
633 while (i < (src->generate_samples_per_buffer * channels)) { \
634 for (c = 0; c < channels; ++c) { \
636 (g##type) (gst_audio_test_src_generate_pink_noise_value (src) * \
642 DEFINE_PINK (int16, 32767.0);
643 DEFINE_PINK (int32, 2147483647.0);
644 DEFINE_PINK (float, 1.0);
645 DEFINE_PINK (double, 1.0);
647 static const ProcessFunc pink_noise_funcs[] = {
648 (ProcessFunc) gst_audio_test_src_create_pink_noise_int16,
649 (ProcessFunc) gst_audio_test_src_create_pink_noise_int32,
650 (ProcessFunc) gst_audio_test_src_create_pink_noise_float,
651 (ProcessFunc) gst_audio_test_src_create_pink_noise_double
655 gst_audio_test_src_init_sine_table (GstAudioTestSrc * src)
659 gdouble step = M_PI_M2 / 1024.0;
660 gdouble amp = src->volume;
662 for (i = 0; i < 1024; i++) {
663 src->wave_table[i] = sin (ang) * amp;
668 #define DEFINE_SINE_TABLE(type,scale) \
670 gst_audio_test_src_create_sine_table_##type (GstAudioTestSrc * src, g##type * samples) \
672 gint i, c, channels; \
675 channels = GST_AUDIO_INFO_CHANNELS (&src->info); \
676 step = M_PI_M2 * src->freq / GST_AUDIO_INFO_RATE (&src->info); \
677 scl = 1024.0 / M_PI_M2; \
680 while (i < (src->generate_samples_per_buffer * channels)) { \
681 src->accumulator += step; \
682 if (src->accumulator >= M_PI_M2) \
683 src->accumulator -= M_PI_M2; \
685 for (c = 0; c < channels; ++c) \
686 samples[i++] = (g##type) scale * src->wave_table[(gint) (src->accumulator * scl)]; \
690 DEFINE_SINE_TABLE (int16, 32767.0);
691 DEFINE_SINE_TABLE (int32, 2147483647.0);
692 DEFINE_SINE_TABLE (float, 1.0);
693 DEFINE_SINE_TABLE (double, 1.0);
695 static const ProcessFunc sine_table_funcs[] = {
696 (ProcessFunc) gst_audio_test_src_create_sine_table_int16,
697 (ProcessFunc) gst_audio_test_src_create_sine_table_int32,
698 (ProcessFunc) gst_audio_test_src_create_sine_table_float,
699 (ProcessFunc) gst_audio_test_src_create_sine_table_double
702 #define DEFINE_TICKS(type,scale) \
704 gst_audio_test_src_create_tick_##type (GstAudioTestSrc * src, g##type * samples) \
706 gint i, c, channels, samplerate; \
709 channels = GST_AUDIO_INFO_CHANNELS (&src->info); \
710 samplerate = GST_AUDIO_INFO_RATE (&src->info); \
711 step = M_PI_M2 * src->freq / samplerate; \
712 scl = 1024.0 / M_PI_M2; \
714 for (i = 0; i < src->generate_samples_per_buffer; i++) { \
715 src->accumulator += step; \
716 if (src->accumulator >= M_PI_M2) \
717 src->accumulator -= M_PI_M2; \
719 if ((src->next_sample + i)%samplerate < 1600) { \
720 for (c = 0; c < channels; ++c) \
721 samples[(i * channels) + c] = (g##type) scale * src->wave_table[(gint) (src->accumulator * scl)]; \
723 for (c = 0; c < channels; ++c) \
724 samples[(i * channels) + c] = 0; \
729 DEFINE_TICKS (int16, 32767.0);
730 DEFINE_TICKS (int32, 2147483647.0);
731 DEFINE_TICKS (float, 1.0);
732 DEFINE_TICKS (double, 1.0);
734 static const ProcessFunc tick_funcs[] = {
735 (ProcessFunc) gst_audio_test_src_create_tick_int16,
736 (ProcessFunc) gst_audio_test_src_create_tick_int32,
737 (ProcessFunc) gst_audio_test_src_create_tick_float,
738 (ProcessFunc) gst_audio_test_src_create_tick_double
741 /* Gaussian white noise using Box-Muller algorithm. unit variance
742 * normally-distributed random numbers are generated in pairs as the real
743 * and imaginary parts of a compex random variable with
744 * uniformly-distributed argument and \chi^{2}-distributed modulus.
747 #define DEFINE_GAUSSIAN_WHITE_NOISE(type,scale) \
749 gst_audio_test_src_create_gaussian_white_noise_##type (GstAudioTestSrc * src, g##type * samples) \
752 gdouble amp = (src->volume * scale); \
753 gint channels = GST_AUDIO_INFO_CHANNELS (&src->info); \
755 for (i = 0; i < src->generate_samples_per_buffer * channels; ) { \
756 for (c = 0; c < channels; ++c) { \
757 gdouble mag = sqrt (-2 * log (1.0 - g_rand_double (src->gen))); \
758 gdouble phs = g_rand_double_range (src->gen, 0.0, M_PI_M2); \
760 samples[i++] = (g##type) (amp * mag * cos (phs)); \
761 if (++c >= channels) \
763 samples[i++] = (g##type) (amp * mag * sin (phs)); \
768 DEFINE_GAUSSIAN_WHITE_NOISE (int16, 32767.0);
769 DEFINE_GAUSSIAN_WHITE_NOISE (int32, 2147483647.0);
770 DEFINE_GAUSSIAN_WHITE_NOISE (float, 1.0);
771 DEFINE_GAUSSIAN_WHITE_NOISE (double, 1.0);
773 static const ProcessFunc gaussian_white_noise_funcs[] = {
774 (ProcessFunc) gst_audio_test_src_create_gaussian_white_noise_int16,
775 (ProcessFunc) gst_audio_test_src_create_gaussian_white_noise_int32,
776 (ProcessFunc) gst_audio_test_src_create_gaussian_white_noise_float,
777 (ProcessFunc) gst_audio_test_src_create_gaussian_white_noise_double
780 /* Brownian (Red) Noise: noise where the power density decreases by 6 dB per
781 * octave with increasing frequency
783 * taken from http://vellocet.com/dsp/noise/VRand.html
784 * by Andrew Simper of Vellocet (andy@vellocet.com)
787 #define DEFINE_RED_NOISE(type,scale) \
789 gst_audio_test_src_create_red_noise_##type (GstAudioTestSrc * src, g##type * samples) \
792 gdouble amp = (src->volume * scale); \
793 gdouble state = src->red.state; \
794 gint channels = GST_AUDIO_INFO_CHANNELS (&src->info); \
796 for (i = 0; i < src->generate_samples_per_buffer * channels; ) { \
797 for (c = 0; c < channels; ++c) { \
799 gdouble r = g_rand_double_range (src->gen, -1.0, 1.0); \
801 if (state < -8.0f || state > 8.0f) state -= r; \
804 samples[i++] = (g##type) (amp * state * 0.0625f); /* /16.0 */ \
807 src->red.state = state; \
810 DEFINE_RED_NOISE (int16, 32767.0);
811 DEFINE_RED_NOISE (int32, 2147483647.0);
812 DEFINE_RED_NOISE (float, 1.0);
813 DEFINE_RED_NOISE (double, 1.0);
815 static const ProcessFunc red_noise_funcs[] = {
816 (ProcessFunc) gst_audio_test_src_create_red_noise_int16,
817 (ProcessFunc) gst_audio_test_src_create_red_noise_int32,
818 (ProcessFunc) gst_audio_test_src_create_red_noise_float,
819 (ProcessFunc) gst_audio_test_src_create_red_noise_double
822 /* Blue Noise: apply spectral inversion to pink noise */
824 #define DEFINE_BLUE_NOISE(type) \
826 gst_audio_test_src_create_blue_noise_##type (GstAudioTestSrc * src, g##type * samples) \
829 static gdouble flip=1.0; \
830 gint channels = GST_AUDIO_INFO_CHANNELS (&src->info); \
832 gst_audio_test_src_create_pink_noise_##type (src, samples); \
833 for (i = 0; i < src->generate_samples_per_buffer * channels; ) { \
834 for (c = 0; c < channels; ++c) { \
835 samples[i++] *= flip; \
841 DEFINE_BLUE_NOISE (int16);
842 DEFINE_BLUE_NOISE (int32);
843 DEFINE_BLUE_NOISE (float);
844 DEFINE_BLUE_NOISE (double);
846 static const ProcessFunc blue_noise_funcs[] = {
847 (ProcessFunc) gst_audio_test_src_create_blue_noise_int16,
848 (ProcessFunc) gst_audio_test_src_create_blue_noise_int32,
849 (ProcessFunc) gst_audio_test_src_create_blue_noise_float,
850 (ProcessFunc) gst_audio_test_src_create_blue_noise_double
854 /* Violet Noise: apply spectral inversion to red noise */
856 #define DEFINE_VIOLET_NOISE(type) \
858 gst_audio_test_src_create_violet_noise_##type (GstAudioTestSrc * src, g##type * samples) \
861 static gdouble flip=1.0; \
862 gint channels = GST_AUDIO_INFO_CHANNELS (&src->info); \
864 gst_audio_test_src_create_red_noise_##type (src, samples); \
865 for (i = 0; i < src->generate_samples_per_buffer * channels; ) { \
866 for (c = 0; c < channels; ++c) { \
867 samples[i++] *= flip; \
873 DEFINE_VIOLET_NOISE (int16);
874 DEFINE_VIOLET_NOISE (int32);
875 DEFINE_VIOLET_NOISE (float);
876 DEFINE_VIOLET_NOISE (double);
878 static const ProcessFunc violet_noise_funcs[] = {
879 (ProcessFunc) gst_audio_test_src_create_violet_noise_int16,
880 (ProcessFunc) gst_audio_test_src_create_violet_noise_int32,
881 (ProcessFunc) gst_audio_test_src_create_violet_noise_float,
882 (ProcessFunc) gst_audio_test_src_create_violet_noise_double
887 * gst_audio_test_src_change_wave:
888 * Assign function pointer of wave generator.
891 gst_audio_test_src_change_wave (GstAudioTestSrc * src)
895 /* not negotiated yet? */
896 if (src->info.finfo == NULL) {
901 switch (GST_AUDIO_FORMAT_INFO_FORMAT (src->info.finfo)) {
902 case GST_AUDIO_FORMAT_S16:
905 case GST_AUDIO_FORMAT_S32:
908 case GST_AUDIO_FORMAT_F32:
911 case GST_AUDIO_FORMAT_F64:
920 case GST_AUDIO_TEST_SRC_WAVE_SINE:
921 src->process = sine_funcs[idx];
923 case GST_AUDIO_TEST_SRC_WAVE_SQUARE:
924 src->process = square_funcs[idx];
926 case GST_AUDIO_TEST_SRC_WAVE_SAW:
927 src->process = saw_funcs[idx];
929 case GST_AUDIO_TEST_SRC_WAVE_TRIANGLE:
930 src->process = triangle_funcs[idx];
932 case GST_AUDIO_TEST_SRC_WAVE_SILENCE:
933 src->process = silence_funcs[idx];
935 case GST_AUDIO_TEST_SRC_WAVE_WHITE_NOISE:
937 src->gen = g_rand_new ();
938 src->process = white_noise_funcs[idx];
940 case GST_AUDIO_TEST_SRC_WAVE_PINK_NOISE:
942 src->gen = g_rand_new ();
943 gst_audio_test_src_init_pink_noise (src);
944 src->process = pink_noise_funcs[idx];
946 case GST_AUDIO_TEST_SRC_WAVE_SINE_TAB:
947 gst_audio_test_src_init_sine_table (src);
948 src->process = sine_table_funcs[idx];
950 case GST_AUDIO_TEST_SRC_WAVE_TICKS:
951 gst_audio_test_src_init_sine_table (src);
952 src->process = tick_funcs[idx];
954 case GST_AUDIO_TEST_SRC_WAVE_GAUSSIAN_WHITE_NOISE:
956 src->gen = g_rand_new ();
957 src->process = gaussian_white_noise_funcs[idx];
959 case GST_AUDIO_TEST_SRC_WAVE_RED_NOISE:
961 src->gen = g_rand_new ();
962 src->red.state = 0.0;
963 src->process = red_noise_funcs[idx];
965 case GST_AUDIO_TEST_SRC_WAVE_BLUE_NOISE:
967 src->gen = g_rand_new ();
968 gst_audio_test_src_init_pink_noise (src);
969 src->process = blue_noise_funcs[idx];
971 case GST_AUDIO_TEST_SRC_WAVE_VIOLET_NOISE:
973 src->gen = g_rand_new ();
974 src->red.state = 0.0;
975 src->process = violet_noise_funcs[idx];
978 GST_ERROR ("invalid wave-form");
984 * gst_audio_test_src_change_volume:
985 * Recalc wave tables for precalculated waves.
988 gst_audio_test_src_change_volume (GstAudioTestSrc * src)
991 case GST_AUDIO_TEST_SRC_WAVE_SINE_TAB:
992 gst_audio_test_src_init_sine_table (src);
1000 gst_audio_test_src_get_times (GstBaseSrc * basesrc, GstBuffer * buffer,
1001 GstClockTime * start, GstClockTime * end)
1003 /* for live sources, sync on the timestamp of the buffer */
1004 if (gst_base_src_is_live (basesrc)) {
1005 GstClockTime timestamp = GST_BUFFER_TIMESTAMP (buffer);
1007 if (GST_CLOCK_TIME_IS_VALID (timestamp)) {
1008 /* get duration to calculate end time */
1009 GstClockTime duration = GST_BUFFER_DURATION (buffer);
1011 if (GST_CLOCK_TIME_IS_VALID (duration)) {
1012 *end = timestamp + duration;
1023 gst_audio_test_src_start (GstBaseSrc * basesrc)
1025 GstAudioTestSrc *src = GST_AUDIO_TEST_SRC (basesrc);
1027 src->next_sample = 0;
1030 src->check_seek_stop = FALSE;
1031 src->eos_reached = FALSE;
1032 src->tags_pushed = FALSE;
1033 src->accumulator = 0;
1039 gst_audio_test_src_stop (GstBaseSrc * basesrc)
1044 /* seek to time, will be called when we operate in push mode. In pull mode we
1045 * get the requested byte offset. */
1047 gst_audio_test_src_do_seek (GstBaseSrc * basesrc, GstSegment * segment)
1049 GstAudioTestSrc *src = GST_AUDIO_TEST_SRC (basesrc);
1051 gint samplerate, bpf;
1054 GST_DEBUG_OBJECT (src, "seeking %" GST_SEGMENT_FORMAT, segment);
1056 time = segment->position;
1057 src->reverse = (segment->rate < 0.0);
1059 samplerate = GST_AUDIO_INFO_RATE (&src->info);
1060 bpf = GST_AUDIO_INFO_BPF (&src->info);
1062 /* now move to the time indicated, don't see to the sample *after* the time */
1063 next_sample = gst_util_uint64_scale_int (time, samplerate, GST_SECOND);
1064 src->next_byte = next_sample * bpf;
1065 if (samplerate == 0)
1069 gst_util_uint64_scale_round (next_sample, GST_SECOND, samplerate);
1071 GST_DEBUG_OBJECT (src, "seeking next_sample=%" G_GINT64_FORMAT
1072 " next_time=%" GST_TIME_FORMAT, next_sample,
1073 GST_TIME_ARGS (src->next_time));
1075 g_assert (src->next_time <= time);
1077 src->next_sample = next_sample;
1079 if (!src->reverse) {
1080 if (GST_CLOCK_TIME_IS_VALID (segment->start)) {
1081 segment->time = segment->start;
1084 if (GST_CLOCK_TIME_IS_VALID (segment->stop)) {
1085 segment->time = segment->stop;
1089 if (GST_CLOCK_TIME_IS_VALID (segment->stop)) {
1090 time = segment->stop;
1092 gst_util_uint64_scale_round (time, samplerate, GST_SECOND);
1093 src->check_seek_stop = TRUE;
1095 src->check_seek_stop = FALSE;
1097 src->eos_reached = FALSE;
1103 gst_audio_test_src_is_seekable (GstBaseSrc * basesrc)
1105 /* we're seekable... */
1109 static GstFlowReturn
1110 gst_audio_test_src_fill (GstBaseSrc * basesrc, guint64 offset,
1111 guint length, GstBuffer * buffer)
1113 GstAudioTestSrc *src;
1114 GstClockTime next_time;
1115 gint64 next_sample, next_byte;
1116 gint bytes, samples;
1117 GstElementClass *eclass;
1119 gint samplerate, bpf;
1121 src = GST_AUDIO_TEST_SRC (basesrc);
1123 /* example for tagging generated data */
1124 if (!src->tags_pushed) {
1125 GstTagList *taglist;
1127 taglist = gst_tag_list_new (GST_TAG_DESCRIPTION, "audiotest wave", NULL);
1129 eclass = GST_ELEMENT_CLASS (parent_class);
1130 if (eclass->send_event)
1131 eclass->send_event (GST_ELEMENT_CAST (basesrc),
1132 gst_event_new_tag (taglist));
1134 gst_tag_list_unref (taglist);
1135 src->tags_pushed = TRUE;
1138 if (src->eos_reached) {
1139 GST_INFO_OBJECT (src, "eos");
1140 return GST_FLOW_EOS;
1143 samplerate = GST_AUDIO_INFO_RATE (&src->info);
1144 bpf = GST_AUDIO_INFO_BPF (&src->info);
1146 /* if no length was given, use our default length in samples otherwise convert
1147 * the length in bytes to samples. */
1149 samples = src->samples_per_buffer;
1151 samples = length / bpf;
1153 /* if no offset was given, use our next logical byte */
1155 offset = src->next_byte;
1157 /* now see if we are at the byteoffset we think we are */
1158 if (offset != src->next_byte) {
1159 GST_DEBUG_OBJECT (src, "seek to new offset %" G_GUINT64_FORMAT, offset);
1160 /* we have a discont in the expected sample offset, do a 'seek' */
1161 src->next_sample = offset / bpf;
1163 gst_util_uint64_scale_int (src->next_sample, GST_SECOND, samplerate);
1164 src->next_byte = offset;
1168 if (src->check_seek_stop &&
1169 (src->sample_stop > src->next_sample) &&
1170 (src->sample_stop < src->next_sample + samples)
1172 /* calculate only partial buffer */
1173 src->generate_samples_per_buffer = src->sample_stop - src->next_sample;
1174 next_sample = src->sample_stop;
1175 src->eos_reached = TRUE;
1177 /* calculate full buffer */
1178 src->generate_samples_per_buffer = samples;
1179 next_sample = src->next_sample + (src->reverse ? (-samples) : samples);
1182 bytes = src->generate_samples_per_buffer * bpf;
1184 next_byte = src->next_byte + (src->reverse ? (-bytes) : bytes);
1185 next_time = gst_util_uint64_scale_int (next_sample, GST_SECOND, samplerate);
1187 GST_LOG_OBJECT (src, "samplerate %d", samplerate);
1188 GST_LOG_OBJECT (src, "next_sample %" G_GINT64_FORMAT ", ts %" GST_TIME_FORMAT,
1189 next_sample, GST_TIME_ARGS (next_time));
1191 gst_buffer_set_size (buffer, bytes);
1193 GST_BUFFER_OFFSET (buffer) = src->next_sample;
1194 GST_BUFFER_OFFSET_END (buffer) = next_sample;
1195 if (!src->reverse) {
1196 GST_BUFFER_TIMESTAMP (buffer) = src->timestamp_offset + src->next_time;
1197 GST_BUFFER_DURATION (buffer) = next_time - src->next_time;
1199 GST_BUFFER_TIMESTAMP (buffer) = src->timestamp_offset + next_time;
1200 GST_BUFFER_DURATION (buffer) = src->next_time - next_time;
1203 gst_object_sync_values (GST_OBJECT (src), GST_BUFFER_TIMESTAMP (buffer));
1205 src->next_time = next_time;
1206 src->next_sample = next_sample;
1207 src->next_byte = next_byte;
1209 GST_LOG_OBJECT (src, "generating %u samples at ts %" GST_TIME_FORMAT,
1210 src->generate_samples_per_buffer,
1211 GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buffer)));
1213 gst_buffer_map (buffer, &map, GST_MAP_WRITE);
1214 src->process (src, map.data);
1215 gst_buffer_unmap (buffer, &map);
1217 if (G_UNLIKELY ((src->wave == GST_AUDIO_TEST_SRC_WAVE_SILENCE)
1218 || (src->volume == 0.0))) {
1219 GST_BUFFER_FLAG_SET (buffer, GST_BUFFER_FLAG_GAP);
1226 gst_audio_test_src_set_property (GObject * object, guint prop_id,
1227 const GValue * value, GParamSpec * pspec)
1229 GstAudioTestSrc *src = GST_AUDIO_TEST_SRC (object);
1232 case PROP_SAMPLES_PER_BUFFER:
1233 src->samples_per_buffer = g_value_get_int (value);
1234 gst_base_src_set_blocksize (GST_BASE_SRC_CAST (src),
1235 GST_AUDIO_INFO_BPF (&src->info) * src->samples_per_buffer);
1238 src->wave = g_value_get_enum (value);
1239 gst_audio_test_src_change_wave (src);
1242 src->freq = g_value_get_double (value);
1245 src->volume = g_value_get_double (value);
1246 gst_audio_test_src_change_volume (src);
1249 gst_base_src_set_live (GST_BASE_SRC (src), g_value_get_boolean (value));
1251 case PROP_TIMESTAMP_OFFSET:
1252 src->timestamp_offset = g_value_get_int64 (value);
1254 case PROP_CAN_ACTIVATE_PUSH:
1255 GST_BASE_SRC (src)->can_activate_push = g_value_get_boolean (value);
1257 case PROP_CAN_ACTIVATE_PULL:
1258 src->can_activate_pull = g_value_get_boolean (value);
1261 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1267 gst_audio_test_src_get_property (GObject * object, guint prop_id,
1268 GValue * value, GParamSpec * pspec)
1270 GstAudioTestSrc *src = GST_AUDIO_TEST_SRC (object);
1273 case PROP_SAMPLES_PER_BUFFER:
1274 g_value_set_int (value, src->samples_per_buffer);
1277 g_value_set_enum (value, src->wave);
1280 g_value_set_double (value, src->freq);
1283 g_value_set_double (value, src->volume);
1286 g_value_set_boolean (value, gst_base_src_is_live (GST_BASE_SRC (src)));
1288 case PROP_TIMESTAMP_OFFSET:
1289 g_value_set_int64 (value, src->timestamp_offset);
1291 case PROP_CAN_ACTIVATE_PUSH:
1292 g_value_set_boolean (value, GST_BASE_SRC (src)->can_activate_push);
1294 case PROP_CAN_ACTIVATE_PULL:
1295 g_value_set_boolean (value, src->can_activate_pull);
1298 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1304 plugin_init (GstPlugin * plugin)
1306 GST_DEBUG_CATEGORY_INIT (audio_test_src_debug, "audiotestsrc", 0,
1307 "Audio Test Source");
1309 return gst_element_register (plugin, "audiotestsrc",
1310 GST_RANK_NONE, GST_TYPE_AUDIO_TEST_SRC);
1313 GST_PLUGIN_DEFINE (GST_VERSION_MAJOR,
1316 "Creates audio test signals of given frequency and volume",
1317 plugin_init, VERSION, "LGPL", GST_PACKAGE_NAME, GST_PACKAGE_ORIGIN);