Merge branch 'master' into 0.11
[platform/upstream/gstreamer.git] / gst / audiotestsrc / gstaudiotestsrc.c
1 /* GStreamer
2  * Copyright (C) 2005 Stefan Kost <ensonic@users.sf.net>
3  *
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.
8  *
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.
13  *
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.
18  */
19 /**
20  * SECTION:element-audiotestsrc
21  *
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.
24  *
25  * <refsect2>
26  * <title>Example launch line</title>
27  * |[
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).
31  * |[
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.
36  * </refsect2>
37  */
38
39 #ifdef HAVE_CONFIG_H
40 #include "config.h"
41 #endif
42
43 #include <math.h>
44 #include <stdlib.h>
45 #include <string.h>
46
47 #include "gstaudiotestsrc.h"
48
49
50 #define M_PI_M2 ( G_PI + G_PI )
51
52 GST_DEBUG_CATEGORY_STATIC (audio_test_src_debug);
53 #define GST_CAT_DEFAULT audio_test_src_debug
54
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
63
64 enum
65 {
66   PROP_0,
67   PROP_SAMPLES_PER_BUFFER,
68   PROP_WAVE,
69   PROP_FREQ,
70   PROP_VOLUME,
71   PROP_IS_LIVE,
72   PROP_TIMESTAMP_OFFSET,
73   PROP_CAN_ACTIVATE_PUSH,
74   PROP_CAN_ACTIVATE_PULL,
75   PROP_LAST
76 };
77
78 #if G_BYTE_ORDER == G_LITTLE_ENDIAN
79 #define FORMAT_STR "{ S16LE, S32LE, F32LE, F64LE }"
80 #define DEFAULT_FORMAT_STR "S16LE"
81 #else
82 #define FORMAT_STR "{ S16BE, S32BE, F32BE, F64BE }"
83 #define DEFAULT_FORMAT_STR "S16BE"
84 #endif
85
86 static GstStaticPadTemplate gst_audio_test_src_src_template =
87     GST_STATIC_PAD_TEMPLATE ("src",
88     GST_PAD_SRC,
89     GST_PAD_ALWAYS,
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; "
95         "audio/x-raw, "
96         "format = (string) " FORMAT_STR ", "
97         "layout = (string) interleaved, "
98         "rate = (int) [ 1, MAX ], "
99         "channels = (int) 2, " "channel-mask = (bitmask) 0x3")
100     );
101
102 #define gst_audio_test_src_parent_class parent_class
103 G_DEFINE_TYPE (GstAudioTestSrc, gst_audio_test_src, GST_TYPE_BASE_SRC);
104
105 #define GST_TYPE_AUDIO_TEST_SRC_WAVE (gst_audiostestsrc_wave_get_type())
106 static GType
107 gst_audiostestsrc_wave_get_type (void)
108 {
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",
121         "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"},
125     {0, NULL, NULL},
126   };
127
128   if (G_UNLIKELY (audiostestsrc_wave_type == 0)) {
129     audiostestsrc_wave_type = g_enum_register_static ("GstAudioTestSrcWave",
130         audiostestsrc_waves);
131   }
132   return audiostestsrc_wave_type;
133 }
134
135 static void gst_audio_test_src_finalize (GObject * object);
136
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);
141
142 static gboolean gst_audio_test_src_setcaps (GstBaseSrc * basesrc,
143     GstCaps * caps);
144 static void gst_audio_test_src_fixate (GstBaseSrc * bsrc, GstCaps * caps);
145
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,
150     GstQuery * query);
151
152 static void gst_audio_test_src_change_wave (GstAudioTestSrc * src);
153
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);
160
161 static void
162 gst_audio_test_src_class_init (GstAudioTestSrcClass * klass)
163 {
164   GObjectClass *gobject_class;
165   GstElementClass *gstelement_class;
166   GstBaseSrcClass *gstbasesrc_class;
167
168   gobject_class = (GObjectClass *) klass;
169   gstelement_class = (GstElementClass *) klass;
170   gstbasesrc_class = (GstBaseSrcClass *) klass;
171
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;
175
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,
191           1.0, DEFAULT_VOLUME,
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",
199           "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));
211
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>");
218
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);
230 }
231
232 static void
233 gst_audio_test_src_init (GstAudioTestSrc * src)
234 {
235   src->volume = DEFAULT_VOLUME;
236   src->freq = DEFAULT_FREQ;
237
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);
241
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;
246
247   src->gen = NULL;
248
249   src->wave = DEFAULT_WAVE;
250   gst_base_src_set_blocksize (GST_BASE_SRC (src), -1);
251 }
252
253 static void
254 gst_audio_test_src_finalize (GObject * object)
255 {
256   GstAudioTestSrc *src = GST_AUDIO_TEST_SRC (object);
257
258   if (src->gen)
259     g_rand_free (src->gen);
260   src->gen = NULL;
261
262   G_OBJECT_CLASS (parent_class)->finalize (object);
263 }
264
265 static void
266 gst_audio_test_src_fixate (GstBaseSrc * bsrc, GstCaps * caps)
267 {
268   GstAudioTestSrc *src = GST_AUDIO_TEST_SRC (bsrc);
269   GstStructure *structure;
270
271   structure = gst_caps_get_structure (caps, 0);
272
273   GST_DEBUG_OBJECT (src, "fixating samplerate to %d", GST_AUDIO_DEF_RATE);
274
275   gst_structure_fixate_field_nearest_int (structure, "rate",
276       GST_AUDIO_DEF_RATE);
277
278   gst_structure_fixate_field_string (structure, "format", DEFAULT_FORMAT_STR);
279
280   /* fixate to mono unless downstream requires stereo, for backwards compat */
281   gst_structure_fixate_field_nearest_int (structure, "channels", 1);
282
283   GST_BASE_SRC_CLASS (parent_class)->fixate (bsrc, caps);
284 }
285
286 static gboolean
287 gst_audio_test_src_setcaps (GstBaseSrc * basesrc, GstCaps * caps)
288 {
289   GstAudioTestSrc *src = GST_AUDIO_TEST_SRC (basesrc);
290   GstAudioInfo info;
291
292   if (!gst_audio_info_from_caps (&info, caps))
293     goto invalid_caps;
294
295   GST_DEBUG_OBJECT (src, "negotiated to caps %" GST_PTR_FORMAT, caps);
296
297   src->info = info;
298
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);
302
303   return TRUE;
304
305   /* ERROR */
306 invalid_caps:
307   {
308     GST_ERROR_OBJECT (basesrc, "received invalid caps");
309     return FALSE;
310   }
311 }
312
313 static gboolean
314 gst_audio_test_src_query (GstBaseSrc * basesrc, GstQuery * query)
315 {
316   GstAudioTestSrc *src = GST_AUDIO_TEST_SRC (basesrc);
317   gboolean res = FALSE;
318
319   switch (GST_QUERY_TYPE (query)) {
320     case GST_QUERY_CONVERT:
321     {
322       GstFormat src_fmt, dest_fmt;
323       gint64 src_val, dest_val;
324
325       gst_query_parse_convert (query, &src_fmt, &src_val, &dest_fmt, &dest_val);
326
327       if (!gst_audio_info_convert (&src->info, src_fmt, src_val, dest_fmt,
328               &dest_val))
329         goto error;
330
331       gst_query_set_convert (query, src_fmt, src_val, dest_fmt, dest_val);
332       res = TRUE;
333       break;
334     }
335     case GST_QUERY_SCHEDULING:
336     {
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);
342
343       res = TRUE;
344       break;
345     }
346     default:
347       res = GST_BASE_SRC_CLASS (parent_class)->query (basesrc, query);
348       break;
349   }
350
351   return res;
352   /* ERROR */
353 error:
354   {
355     GST_DEBUG_OBJECT (src, "query failed");
356     return FALSE;
357   }
358 }
359
360 #define DEFINE_SINE(type,scale) \
361 static void \
362 gst_audio_test_src_create_sine_##type (GstAudioTestSrc * src, g##type * samples) \
363 { \
364   gint i, c, channels; \
365   gdouble step, amp; \
366   \
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; \
370   \
371   i = 0; \
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; \
376     \
377     for (c = 0; c < channels; ++c) { \
378       samples[i++] = (g##type) (sin (src->accumulator) * amp); \
379     } \
380   } \
381 }
382
383 DEFINE_SINE (int16, 32767.0);
384 DEFINE_SINE (int32, 2147483647.0);
385 DEFINE_SINE (float, 1.0);
386 DEFINE_SINE (double, 1.0);
387
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
393 };
394
395 #define DEFINE_SQUARE(type,scale) \
396 static void \
397 gst_audio_test_src_create_square_##type (GstAudioTestSrc * src, g##type * samples) \
398 { \
399   gint i, c, channels; \
400   gdouble step, amp; \
401   \
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; \
405   \
406   i = 0; \
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; \
411     \
412     for (c = 0; c < channels; ++c) { \
413       samples[i++] = (g##type) ((src->accumulator < G_PI) ? amp : -amp); \
414     } \
415   } \
416 }
417
418 DEFINE_SQUARE (int16, 32767.0);
419 DEFINE_SQUARE (int32, 2147483647.0);
420 DEFINE_SQUARE (float, 1.0);
421 DEFINE_SQUARE (double, 1.0);
422
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
428 };
429
430 #define DEFINE_SAW(type,scale) \
431 static void \
432 gst_audio_test_src_create_saw_##type (GstAudioTestSrc * src, g##type * samples) \
433 { \
434   gint i, c, channels; \
435   gdouble step, amp; \
436   \
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; \
440   \
441   i = 0; \
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; \
446     \
447     if (src->accumulator < G_PI) { \
448       for (c = 0; c < channels; ++c) \
449         samples[i++] = (g##type) (src->accumulator * amp); \
450     } else { \
451       for (c = 0; c < channels; ++c) \
452         samples[i++] = (g##type) ((M_PI_M2 - src->accumulator) * -amp); \
453     } \
454   } \
455 }
456
457 DEFINE_SAW (int16, 32767.0);
458 DEFINE_SAW (int32, 2147483647.0);
459 DEFINE_SAW (float, 1.0);
460 DEFINE_SAW (double, 1.0);
461
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
467 };
468
469 #define DEFINE_TRIANGLE(type,scale) \
470 static void \
471 gst_audio_test_src_create_triangle_##type (GstAudioTestSrc * src, g##type * samples) \
472 { \
473   gint i, c, channels; \
474   gdouble step, amp; \
475   \
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; \
479   \
480   i = 0; \
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; \
485     \
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); \
492     } else { \
493       for (c = 0; c < channels; ++c) \
494         samples[i++] = (g##type) ((M_PI_M2 - src->accumulator) * -amp); \
495     } \
496   } \
497 }
498
499 DEFINE_TRIANGLE (int16, 32767.0);
500 DEFINE_TRIANGLE (int32, 2147483647.0);
501 DEFINE_TRIANGLE (float, 1.0);
502 DEFINE_TRIANGLE (double, 1.0);
503
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
509 };
510
511 #define DEFINE_SILENCE(type) \
512 static void \
513 gst_audio_test_src_create_silence_##type (GstAudioTestSrc * src, g##type * samples) \
514 { \
515   memset (samples, 0, src->generate_samples_per_buffer * sizeof (g##type) * src->info.channels); \
516 }
517
518 DEFINE_SILENCE (int16);
519 DEFINE_SILENCE (int32);
520 DEFINE_SILENCE (float);
521 DEFINE_SILENCE (double);
522
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
528 };
529
530 #define DEFINE_WHITE_NOISE(type,scale) \
531 static void \
532 gst_audio_test_src_create_white_noise_##type (GstAudioTestSrc * src, g##type * samples) \
533 { \
534   gint i, c; \
535   gdouble amp = (src->volume * scale); \
536   gint channels = GST_AUDIO_INFO_CHANNELS (&src->info); \
537   \
538   i = 0; \
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)); \
542   } \
543 }
544
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);
549
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
555 };
556
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
560  * Many thanks Phil!
561  */
562 static void
563 gst_audio_test_src_init_pink_noise (GstAudioTestSrc * src)
564 {
565   gint i;
566   gint num_rows = 12;           /* arbitrary: 1 .. PINK_MAX_RANDOM_ROWS */
567   glong pmax;
568
569   src->pink.index = 0;
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;
579 }
580
581 /* Generate Pink noise values between -1.0 and +1.0 */
582 static gdouble
583 gst_audio_test_src_generate_pink_noise_value (GstAudioTestSrc * src)
584 {
585   GstPinkNoise *pink = &src->pink;
586   glong new_random;
587   glong sum;
588
589   /* Increment and mask index. */
590   pink->index = (pink->index + 1) & pink->index_mask;
591
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. */
596     gint num_zeros = 0;
597     gint n = pink->index;
598
599     while ((n & 1) == 0) {
600       n = n >> 1;
601       num_zeros++;
602     }
603
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.
607      */
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;
613   }
614
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;
619
620   /* Scale to range of -1.0 to 0.9999. */
621   return (pink->scalar * sum);
622 }
623
624 #define DEFINE_PINK(type, scale) \
625 static void \
626 gst_audio_test_src_create_pink_noise_##type (GstAudioTestSrc * src, g##type * samples) \
627 { \
628   gint i, c, channels; \
629   gdouble amp; \
630   \
631   amp = src->volume * scale; \
632   channels = GST_AUDIO_INFO_CHANNELS (&src->info); \
633   \
634   i = 0; \
635   while (i < (src->generate_samples_per_buffer * channels)) { \
636     for (c = 0; c < channels; ++c) { \
637       samples[i++] = \
638         (g##type) (gst_audio_test_src_generate_pink_noise_value (src) * \
639         amp); \
640     } \
641   } \
642 }
643
644 DEFINE_PINK (int16, 32767.0);
645 DEFINE_PINK (int32, 2147483647.0);
646 DEFINE_PINK (float, 1.0);
647 DEFINE_PINK (double, 1.0);
648
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
654 };
655
656 static void
657 gst_audio_test_src_init_sine_table (GstAudioTestSrc * src)
658 {
659   gint i;
660   gdouble ang = 0.0;
661   gdouble step = M_PI_M2 / 1024.0;
662   gdouble amp = src->volume;
663
664   for (i = 0; i < 1024; i++) {
665     src->wave_table[i] = sin (ang) * amp;
666     ang += step;
667   }
668 }
669
670 #define DEFINE_SINE_TABLE(type,scale) \
671 static void \
672 gst_audio_test_src_create_sine_table_##type (GstAudioTestSrc * src, g##type * samples) \
673 { \
674   gint i, c, channels; \
675   gdouble step, scl; \
676   \
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; \
680   \
681   i = 0; \
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; \
686     \
687     for (c = 0; c < channels; ++c) \
688       samples[i++] = (g##type) scale * src->wave_table[(gint) (src->accumulator * scl)]; \
689   } \
690 }
691
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);
696
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
702 };
703
704 #define DEFINE_TICKS(type,scale) \
705 static void \
706 gst_audio_test_src_create_tick_##type (GstAudioTestSrc * src, g##type * samples) \
707 { \
708   gint i, c, channels, samplerate; \
709   gdouble step, scl; \
710   \
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; \
715   \
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; \
720     \
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)]; \
724     } else { \
725       for (c = 0; c < channels; ++c) \
726         samples[(i * channels) + c] = 0; \
727     } \
728   } \
729 }
730
731 DEFINE_TICKS (int16, 32767.0);
732 DEFINE_TICKS (int32, 2147483647.0);
733 DEFINE_TICKS (float, 1.0);
734 DEFINE_TICKS (double, 1.0);
735
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
741 };
742
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.
747  */
748
749 #define DEFINE_GAUSSIAN_WHITE_NOISE(type,scale) \
750 static void \
751 gst_audio_test_src_create_gaussian_white_noise_##type (GstAudioTestSrc * src, g##type * samples) \
752 { \
753   gint i, c; \
754   gdouble amp = (src->volume * scale); \
755   gint channels = GST_AUDIO_INFO_CHANNELS (&src->info); \
756   \
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); \
761       \
762       samples[i++] = (g##type) (amp * mag * cos (phs)); \
763       if (++c >= channels) \
764         break; \
765       samples[i++] = (g##type) (amp * mag * sin (phs)); \
766     } \
767   } \
768 }
769
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);
774
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
780 };
781
782 /* Brownian (Red) Noise: noise where the power density decreases by 6 dB per
783  * octave with increasing frequency
784  *
785  * taken from http://vellocet.com/dsp/noise/VRand.html
786  * by Andrew Simper of Vellocet (andy@vellocet.com)
787  */
788
789 #define DEFINE_RED_NOISE(type,scale) \
790 static void \
791 gst_audio_test_src_create_red_noise_##type (GstAudioTestSrc * src, g##type * samples) \
792 { \
793   gint i, c; \
794   gdouble amp = (src->volume * scale); \
795   gdouble state = src->red.state; \
796   gint channels = GST_AUDIO_INFO_CHANNELS (&src->info); \
797   \
798   for (i = 0; i < src->generate_samples_per_buffer * channels; ) { \
799     for (c = 0; c < channels; ++c) { \
800       while (TRUE) { \
801         gdouble r = g_rand_double_range (src->gen, -1.0, 1.0); \
802         state += r; \
803         if (state < -8.0f || state > 8.0f) state -= r; \
804         else break; \
805       } \
806       samples[i++] = (g##type) (amp * state * 0.0625f); /* /16.0 */ \
807     } \
808   } \
809   src->red.state = state; \
810 }
811
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);
816
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
822 };
823
824 /* Blue Noise: apply spectral inversion to pink noise */
825
826 #define DEFINE_BLUE_NOISE(type) \
827 static void \
828 gst_audio_test_src_create_blue_noise_##type (GstAudioTestSrc * src, g##type * samples) \
829 { \
830   gint i, c; \
831   static gdouble flip=1.0; \
832   gint channels = GST_AUDIO_INFO_CHANNELS (&src->info); \
833   \
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; \
838     } \
839     flip *= -1.0; \
840   } \
841 }
842
843 DEFINE_BLUE_NOISE (int16);
844 DEFINE_BLUE_NOISE (int32);
845 DEFINE_BLUE_NOISE (float);
846 DEFINE_BLUE_NOISE (double);
847
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
853 };
854
855
856 /* Violet Noise: apply spectral inversion to red noise */
857
858 #define DEFINE_VIOLET_NOISE(type) \
859 static void \
860 gst_audio_test_src_create_violet_noise_##type (GstAudioTestSrc * src, g##type * samples) \
861 { \
862   gint i, c; \
863   static gdouble flip=1.0; \
864   gint channels = GST_AUDIO_INFO_CHANNELS (&src->info); \
865   \
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; \
870     } \
871     flip *= -1.0; \
872   } \
873 }
874
875 DEFINE_VIOLET_NOISE (int16);
876 DEFINE_VIOLET_NOISE (int32);
877 DEFINE_VIOLET_NOISE (float);
878 DEFINE_VIOLET_NOISE (double);
879
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
885 };
886
887
888 /*
889  * gst_audio_test_src_change_wave:
890  * Assign function pointer of wave generator.
891  */
892 static void
893 gst_audio_test_src_change_wave (GstAudioTestSrc * src)
894 {
895   gint idx;
896
897   /* not negotiated yet? */
898   if (src->info.finfo == NULL) {
899     src->process = NULL;
900     return;
901   }
902
903   switch (GST_AUDIO_FORMAT_INFO_FORMAT (src->info.finfo)) {
904     case GST_AUDIO_FORMAT_S16:
905       idx = 0;
906       break;
907     case GST_AUDIO_FORMAT_S32:
908       idx = 1;
909       break;
910     case GST_AUDIO_FORMAT_F32:
911       idx = 2;
912       break;
913     case GST_AUDIO_FORMAT_F64:
914       idx = 3;
915       break;
916     default:
917       src->process = NULL;
918       return;
919   }
920
921   switch (src->wave) {
922     case GST_AUDIO_TEST_SRC_WAVE_SINE:
923       src->process = sine_funcs[idx];
924       break;
925     case GST_AUDIO_TEST_SRC_WAVE_SQUARE:
926       src->process = square_funcs[idx];
927       break;
928     case GST_AUDIO_TEST_SRC_WAVE_SAW:
929       src->process = saw_funcs[idx];
930       break;
931     case GST_AUDIO_TEST_SRC_WAVE_TRIANGLE:
932       src->process = triangle_funcs[idx];
933       break;
934     case GST_AUDIO_TEST_SRC_WAVE_SILENCE:
935       src->process = silence_funcs[idx];
936       break;
937     case GST_AUDIO_TEST_SRC_WAVE_WHITE_NOISE:
938       if (!(src->gen))
939         src->gen = g_rand_new ();
940       src->process = white_noise_funcs[idx];
941       break;
942     case GST_AUDIO_TEST_SRC_WAVE_PINK_NOISE:
943       if (!(src->gen))
944         src->gen = g_rand_new ();
945       gst_audio_test_src_init_pink_noise (src);
946       src->process = pink_noise_funcs[idx];
947       break;
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];
951       break;
952     case GST_AUDIO_TEST_SRC_WAVE_TICKS:
953       gst_audio_test_src_init_sine_table (src);
954       src->process = tick_funcs[idx];
955       break;
956     case GST_AUDIO_TEST_SRC_WAVE_GAUSSIAN_WHITE_NOISE:
957       if (!(src->gen))
958         src->gen = g_rand_new ();
959       src->process = gaussian_white_noise_funcs[idx];
960       break;
961     case GST_AUDIO_TEST_SRC_WAVE_RED_NOISE:
962       if (!(src->gen))
963         src->gen = g_rand_new ();
964       src->red.state = 0.0;
965       src->process = red_noise_funcs[idx];
966       break;
967     case GST_AUDIO_TEST_SRC_WAVE_BLUE_NOISE:
968       if (!(src->gen))
969         src->gen = g_rand_new ();
970       gst_audio_test_src_init_pink_noise (src);
971       src->process = blue_noise_funcs[idx];
972       break;
973     case GST_AUDIO_TEST_SRC_WAVE_VIOLET_NOISE:
974       if (!(src->gen))
975         src->gen = g_rand_new ();
976       src->red.state = 0.0;
977       src->process = violet_noise_funcs[idx];
978       break;
979     default:
980       GST_ERROR ("invalid wave-form");
981       break;
982   }
983 }
984
985 /*
986  * gst_audio_test_src_change_volume:
987  * Recalc wave tables for precalculated waves.
988  */
989 static void
990 gst_audio_test_src_change_volume (GstAudioTestSrc * src)
991 {
992   switch (src->wave) {
993     case GST_AUDIO_TEST_SRC_WAVE_SINE_TAB:
994       gst_audio_test_src_init_sine_table (src);
995       break;
996     default:
997       break;
998   }
999 }
1000
1001 static void
1002 gst_audio_test_src_get_times (GstBaseSrc * basesrc, GstBuffer * buffer,
1003     GstClockTime * start, GstClockTime * end)
1004 {
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);
1008
1009     if (GST_CLOCK_TIME_IS_VALID (timestamp)) {
1010       /* get duration to calculate end time */
1011       GstClockTime duration = GST_BUFFER_DURATION (buffer);
1012
1013       if (GST_CLOCK_TIME_IS_VALID (duration)) {
1014         *end = timestamp + duration;
1015       }
1016       *start = timestamp;
1017     }
1018   } else {
1019     *start = -1;
1020     *end = -1;
1021   }
1022 }
1023
1024 static gboolean
1025 gst_audio_test_src_start (GstBaseSrc * basesrc)
1026 {
1027   GstAudioTestSrc *src = GST_AUDIO_TEST_SRC (basesrc);
1028
1029   src->next_sample = 0;
1030   src->next_byte = 0;
1031   src->next_time = 0;
1032   src->check_seek_stop = FALSE;
1033   src->eos_reached = FALSE;
1034   src->tags_pushed = FALSE;
1035   src->accumulator = 0;
1036
1037   return TRUE;
1038 }
1039
1040 static gboolean
1041 gst_audio_test_src_stop (GstBaseSrc * basesrc)
1042 {
1043   return TRUE;
1044 }
1045
1046 /* seek to time, will be called when we operate in push mode. In pull mode we
1047  * get the requested byte offset. */
1048 static gboolean
1049 gst_audio_test_src_do_seek (GstBaseSrc * basesrc, GstSegment * segment)
1050 {
1051   GstAudioTestSrc *src = GST_AUDIO_TEST_SRC (basesrc);
1052   GstClockTime time;
1053   gint samplerate, bpf;
1054
1055   GST_DEBUG_OBJECT (src, "seeking %" GST_SEGMENT_FORMAT, segment);
1056
1057   time = segment->position;
1058   src->reverse = (segment->rate < 0.0);
1059
1060   samplerate = GST_AUDIO_INFO_RATE (&src->info);
1061   bpf = GST_AUDIO_INFO_BPF (&src->info);
1062
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)
1067     src->next_time = 0;
1068   else
1069     src->next_time =
1070         gst_util_uint64_scale_int (src->next_sample, GST_SECOND, samplerate);
1071
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));
1075
1076   g_assert (src->next_time <= time);
1077
1078   if (!src->reverse) {
1079     if (GST_CLOCK_TIME_IS_VALID (segment->start)) {
1080       segment->time = segment->start;
1081     }
1082   } else {
1083     if (GST_CLOCK_TIME_IS_VALID (segment->stop)) {
1084       segment->time = segment->stop;
1085     }
1086   }
1087
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;
1092   } else {
1093     src->check_seek_stop = FALSE;
1094   }
1095   src->eos_reached = FALSE;
1096
1097   return TRUE;
1098 }
1099
1100 static gboolean
1101 gst_audio_test_src_is_seekable (GstBaseSrc * basesrc)
1102 {
1103   /* we're seekable... */
1104   return TRUE;
1105 }
1106
1107 static GstFlowReturn
1108 gst_audio_test_src_fill (GstBaseSrc * basesrc, guint64 offset,
1109     guint length, GstBuffer * buffer)
1110 {
1111   GstAudioTestSrc *src;
1112   GstClockTime next_time;
1113   gint64 next_sample, next_byte;
1114   gint bytes, samples;
1115   GstElementClass *eclass;
1116   guint8 *data;
1117   gint samplerate, bpf;
1118
1119   src = GST_AUDIO_TEST_SRC (basesrc);
1120
1121   /* example for tagging generated data */
1122   if (!src->tags_pushed) {
1123     GstTagList *taglist;
1124
1125     taglist = gst_tag_list_new (GST_TAG_DESCRIPTION, "audiotest wave", NULL);
1126
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));
1131     else
1132       gst_tag_list_free (taglist);
1133     src->tags_pushed = TRUE;
1134   }
1135
1136   if (src->eos_reached) {
1137     GST_INFO_OBJECT (src, "eos");
1138     return GST_FLOW_EOS;
1139   }
1140
1141   samplerate = GST_AUDIO_INFO_RATE (&src->info);
1142   bpf = GST_AUDIO_INFO_BPF (&src->info);
1143
1144   /* if no length was given, use our default length in samples otherwise convert
1145    * the length in bytes to samples. */
1146   if (length == -1)
1147     samples = src->samples_per_buffer;
1148   else
1149     samples = length / bpf;
1150
1151   /* if no offset was given, use our next logical byte */
1152   if (offset == -1)
1153     offset = src->next_byte;
1154
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;
1160     src->next_time =
1161         gst_util_uint64_scale_int (src->next_sample, GST_SECOND, samplerate);
1162     src->next_byte = offset;
1163   }
1164
1165   /* check for eos */
1166   if (src->check_seek_stop &&
1167       (src->sample_stop > src->next_sample) &&
1168       (src->sample_stop < src->next_sample + samples)
1169       ) {
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;
1174   } else {
1175     /* calculate full buffer */
1176     src->generate_samples_per_buffer = samples;
1177     next_sample = src->next_sample + (src->reverse ? (-samples) : samples);
1178   }
1179
1180   bytes = src->generate_samples_per_buffer * bpf;
1181
1182   next_byte = src->next_byte + (src->reverse ? (-bytes) : bytes);
1183   next_time = gst_util_uint64_scale_int (next_sample, GST_SECOND, samplerate);
1184
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));
1188
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;
1194   } else {
1195     GST_BUFFER_TIMESTAMP (buffer) = src->timestamp_offset + next_time;
1196     GST_BUFFER_DURATION (buffer) = src->next_time - next_time;
1197   }
1198
1199   gst_object_sync_values (GST_OBJECT (src), GST_BUFFER_TIMESTAMP (buffer));
1200
1201   src->next_time = next_time;
1202   src->next_sample = next_sample;
1203   src->next_byte = next_byte;
1204
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)));
1208
1209   data = gst_buffer_map (buffer, NULL, NULL, GST_MAP_WRITE);
1210   src->process (src, data);
1211   gst_buffer_unmap (buffer, data, bytes);
1212
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);
1216   }
1217
1218   return GST_FLOW_OK;
1219 }
1220
1221 static void
1222 gst_audio_test_src_set_property (GObject * object, guint prop_id,
1223     const GValue * value, GParamSpec * pspec)
1224 {
1225   GstAudioTestSrc *src = GST_AUDIO_TEST_SRC (object);
1226
1227   switch (prop_id) {
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);
1232       break;
1233     case PROP_WAVE:
1234       src->wave = g_value_get_enum (value);
1235       gst_audio_test_src_change_wave (src);
1236       break;
1237     case PROP_FREQ:
1238       src->freq = g_value_get_double (value);
1239       break;
1240     case PROP_VOLUME:
1241       src->volume = g_value_get_double (value);
1242       gst_audio_test_src_change_volume (src);
1243       break;
1244     case PROP_IS_LIVE:
1245       gst_base_src_set_live (GST_BASE_SRC (src), g_value_get_boolean (value));
1246       break;
1247     case PROP_TIMESTAMP_OFFSET:
1248       src->timestamp_offset = g_value_get_int64 (value);
1249       break;
1250     case PROP_CAN_ACTIVATE_PUSH:
1251       GST_BASE_SRC (src)->can_activate_push = g_value_get_boolean (value);
1252       break;
1253     case PROP_CAN_ACTIVATE_PULL:
1254       src->can_activate_pull = g_value_get_boolean (value);
1255       break;
1256     default:
1257       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1258       break;
1259   }
1260 }
1261
1262 static void
1263 gst_audio_test_src_get_property (GObject * object, guint prop_id,
1264     GValue * value, GParamSpec * pspec)
1265 {
1266   GstAudioTestSrc *src = GST_AUDIO_TEST_SRC (object);
1267
1268   switch (prop_id) {
1269     case PROP_SAMPLES_PER_BUFFER:
1270       g_value_set_int (value, src->samples_per_buffer);
1271       break;
1272     case PROP_WAVE:
1273       g_value_set_enum (value, src->wave);
1274       break;
1275     case PROP_FREQ:
1276       g_value_set_double (value, src->freq);
1277       break;
1278     case PROP_VOLUME:
1279       g_value_set_double (value, src->volume);
1280       break;
1281     case PROP_IS_LIVE:
1282       g_value_set_boolean (value, gst_base_src_is_live (GST_BASE_SRC (src)));
1283       break;
1284     case PROP_TIMESTAMP_OFFSET:
1285       g_value_set_int64 (value, src->timestamp_offset);
1286       break;
1287     case PROP_CAN_ACTIVATE_PUSH:
1288       g_value_set_boolean (value, GST_BASE_SRC (src)->can_activate_push);
1289       break;
1290     case PROP_CAN_ACTIVATE_PULL:
1291       g_value_set_boolean (value, src->can_activate_pull);
1292       break;
1293     default:
1294       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1295       break;
1296   }
1297 }
1298
1299 static gboolean
1300 plugin_init (GstPlugin * plugin)
1301 {
1302   GST_DEBUG_CATEGORY_INIT (audio_test_src_debug, "audiotestsrc", 0,
1303       "Audio Test Source");
1304
1305   return gst_element_register (plugin, "audiotestsrc",
1306       GST_RANK_NONE, GST_TYPE_AUDIO_TEST_SRC);
1307 }
1308
1309 GST_PLUGIN_DEFINE (GST_VERSION_MAJOR,
1310     GST_VERSION_MINOR,
1311     "audiotestsrc",
1312     "Creates audio test signals of given frequency and volume",
1313     plugin_init, VERSION, "LGPL", GST_PACKAGE_NAME, GST_PACKAGE_ORIGIN);