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 ! ffmpegcolorspace ! xvimagesink
33  * ]| In this example a saw wave is generated. The wave is shown using a
34  * scope visualizer from libvisual, allowing you to visually verify that
35  * the saw wave is correct.
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 #include <gst/controller/gstcontroller.h>
47
48 #include "gstaudiotestsrc.h"
49
50
51 #ifndef M_PI
52 #define M_PI  3.14159265358979323846
53 #endif
54
55 #ifndef M_PI_2
56 #define M_PI_2  1.57079632679489661923
57 #endif
58
59 #define M_PI_M2 ( M_PI + M_PI )
60
61 GST_DEBUG_CATEGORY_STATIC (audio_test_src_debug);
62 #define GST_CAT_DEFAULT audio_test_src_debug
63
64 #define DEFAULT_SAMPLES_PER_BUFFER   1024
65 #define DEFAULT_WAVE                 GST_AUDIO_TEST_SRC_WAVE_SINE
66 #define DEFAULT_FREQ                 440.0
67 #define DEFAULT_VOLUME               0.8
68 #define DEFAULT_IS_LIVE              FALSE
69 #define DEFAULT_TIMESTAMP_OFFSET     G_GINT64_CONSTANT (0)
70 #define DEFAULT_CAN_ACTIVATE_PUSH    TRUE
71 #define DEFAULT_CAN_ACTIVATE_PULL    FALSE
72
73 enum
74 {
75   PROP_0,
76   PROP_SAMPLES_PER_BUFFER,
77   PROP_WAVE,
78   PROP_FREQ,
79   PROP_VOLUME,
80   PROP_IS_LIVE,
81   PROP_TIMESTAMP_OFFSET,
82   PROP_CAN_ACTIVATE_PUSH,
83   PROP_CAN_ACTIVATE_PULL,
84   PROP_LAST
85 };
86
87
88 static GstStaticPadTemplate gst_audio_test_src_src_template =
89     GST_STATIC_PAD_TEMPLATE ("src",
90     GST_PAD_SRC,
91     GST_PAD_ALWAYS,
92     GST_STATIC_CAPS ("audio/x-raw-int, "
93         "endianness = (int) BYTE_ORDER, "
94         "signed = (boolean) true, "
95         "width = (int) 16, "
96         "depth = (int) 16, "
97         "rate = (int) [ 1, MAX ], "
98         "channels = (int) [ 1, 2 ]; "
99         "audio/x-raw-int, "
100         "endianness = (int) BYTE_ORDER, "
101         "signed = (boolean) true, "
102         "width = (int) 32, "
103         "depth = (int) 32,"
104         "rate = (int) [ 1, MAX ], "
105         "channels = (int) [ 1, 2 ]; "
106         "audio/x-raw-float, "
107         "endianness = (int) BYTE_ORDER, "
108         "width = (int) { 32, 64 }, "
109         "rate = (int) [ 1, MAX ], " "channels = (int) [ 1, 2 ]")
110     );
111
112 #define gst_audio_test_src_parent_class parent_class
113 G_DEFINE_TYPE (GstAudioTestSrc, gst_audio_test_src, GST_TYPE_BASE_SRC);
114
115 #define GST_TYPE_AUDIO_TEST_SRC_WAVE (gst_audiostestsrc_wave_get_type())
116 static GType
117 gst_audiostestsrc_wave_get_type (void)
118 {
119   static GType audiostestsrc_wave_type = 0;
120   static const GEnumValue audiostestsrc_waves[] = {
121     {GST_AUDIO_TEST_SRC_WAVE_SINE, "Sine", "sine"},
122     {GST_AUDIO_TEST_SRC_WAVE_SQUARE, "Square", "square"},
123     {GST_AUDIO_TEST_SRC_WAVE_SAW, "Saw", "saw"},
124     {GST_AUDIO_TEST_SRC_WAVE_TRIANGLE, "Triangle", "triangle"},
125     {GST_AUDIO_TEST_SRC_WAVE_SILENCE, "Silence", "silence"},
126     {GST_AUDIO_TEST_SRC_WAVE_WHITE_NOISE, "White uniform noise", "white-noise"},
127     {GST_AUDIO_TEST_SRC_WAVE_PINK_NOISE, "Pink noise", "pink-noise"},
128     {GST_AUDIO_TEST_SRC_WAVE_SINE_TAB, "Sine table", "sine-table"},
129     {GST_AUDIO_TEST_SRC_WAVE_TICKS, "Periodic Ticks", "ticks"},
130     {GST_AUDIO_TEST_SRC_WAVE_GAUSSIAN_WHITE_NOISE, "White Gaussian noise",
131         "gaussian-noise"},
132     {GST_AUDIO_TEST_SRC_WAVE_RED_NOISE, "Red (brownian) noise", "red-noise"},
133     {GST_AUDIO_TEST_SRC_WAVE_BLUE_NOISE, "Blue noise", "blue-noise"},
134     {GST_AUDIO_TEST_SRC_WAVE_VIOLET_NOISE, "Violet noise", "violet-noise"},
135     {0, NULL, NULL},
136   };
137
138   if (G_UNLIKELY (audiostestsrc_wave_type == 0)) {
139     audiostestsrc_wave_type = g_enum_register_static ("GstAudioTestSrcWave",
140         audiostestsrc_waves);
141   }
142   return audiostestsrc_wave_type;
143 }
144
145 static void gst_audio_test_src_finalize (GObject * object);
146
147 static void gst_audio_test_src_set_property (GObject * object,
148     guint prop_id, const GValue * value, GParamSpec * pspec);
149 static void gst_audio_test_src_get_property (GObject * object,
150     guint prop_id, GValue * value, GParamSpec * pspec);
151
152 static gboolean gst_audio_test_src_setcaps (GstBaseSrc * basesrc,
153     GstCaps * caps);
154 static void gst_audio_test_src_src_fixate (GstPad * pad, GstCaps * caps);
155
156 static gboolean gst_audio_test_src_is_seekable (GstBaseSrc * basesrc);
157 static gboolean gst_audio_test_src_do_seek (GstBaseSrc * basesrc,
158     GstSegment * segment);
159 static gboolean gst_audio_test_src_query (GstBaseSrc * basesrc,
160     GstQuery * query);
161
162 static void gst_audio_test_src_change_wave (GstAudioTestSrc * src);
163
164 static void gst_audio_test_src_get_times (GstBaseSrc * basesrc,
165     GstBuffer * buffer, GstClockTime * start, GstClockTime * end);
166 static gboolean gst_audio_test_src_start (GstBaseSrc * basesrc);
167 static gboolean gst_audio_test_src_stop (GstBaseSrc * basesrc);
168 static GstFlowReturn gst_audio_test_src_create (GstBaseSrc * basesrc,
169     guint64 offset, guint length, GstBuffer ** buffer);
170
171 static void
172 gst_audio_test_src_class_init (GstAudioTestSrcClass * klass)
173 {
174   GObjectClass *gobject_class;
175   GstElementClass *gstelement_class;
176   GstBaseSrcClass *gstbasesrc_class;
177
178   gobject_class = (GObjectClass *) klass;
179   gstelement_class = (GstElementClass *) klass;
180   gstbasesrc_class = (GstBaseSrcClass *) klass;
181
182   gobject_class->set_property = gst_audio_test_src_set_property;
183   gobject_class->get_property = gst_audio_test_src_get_property;
184   gobject_class->finalize = gst_audio_test_src_finalize;
185
186   g_object_class_install_property (gobject_class, PROP_SAMPLES_PER_BUFFER,
187       g_param_spec_int ("samplesperbuffer", "Samples per buffer",
188           "Number of samples in each outgoing buffer",
189           1, G_MAXINT, DEFAULT_SAMPLES_PER_BUFFER,
190           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
191   g_object_class_install_property (gobject_class, PROP_WAVE,
192       g_param_spec_enum ("wave", "Waveform", "Oscillator waveform",
193           GST_TYPE_AUDIO_TEST_SRC_WAVE, GST_AUDIO_TEST_SRC_WAVE_SINE,
194           G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE | G_PARAM_STATIC_STRINGS));
195   g_object_class_install_property (gobject_class, PROP_FREQ,
196       g_param_spec_double ("freq", "Frequency", "Frequency of test signal",
197           0.0, 20000.0, DEFAULT_FREQ,
198           G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE | G_PARAM_STATIC_STRINGS));
199   g_object_class_install_property (gobject_class, PROP_VOLUME,
200       g_param_spec_double ("volume", "Volume", "Volume of test signal", 0.0,
201           1.0, DEFAULT_VOLUME,
202           G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE | G_PARAM_STATIC_STRINGS));
203   g_object_class_install_property (gobject_class, PROP_IS_LIVE,
204       g_param_spec_boolean ("is-live", "Is Live",
205           "Whether to act as a live source", DEFAULT_IS_LIVE,
206           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
207   g_object_class_install_property (G_OBJECT_CLASS (klass),
208       PROP_TIMESTAMP_OFFSET, g_param_spec_int64 ("timestamp-offset",
209           "Timestamp offset",
210           "An offset added to timestamps set on buffers (in ns)", G_MININT64,
211           G_MAXINT64, DEFAULT_TIMESTAMP_OFFSET,
212           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
213   g_object_class_install_property (gobject_class, PROP_CAN_ACTIVATE_PUSH,
214       g_param_spec_boolean ("can-activate-push", "Can activate push",
215           "Can activate in push mode", DEFAULT_CAN_ACTIVATE_PUSH,
216           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
217   g_object_class_install_property (gobject_class, PROP_CAN_ACTIVATE_PULL,
218       g_param_spec_boolean ("can-activate-pull", "Can activate pull",
219           "Can activate in pull mode", DEFAULT_CAN_ACTIVATE_PULL,
220           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
221
222   gst_element_class_add_pad_template (gstelement_class,
223       gst_static_pad_template_get (&gst_audio_test_src_src_template));
224   gst_element_class_set_details_simple (gstelement_class,
225       "Audio test source", "Source/Audio",
226       "Creates audio test signals of given frequency and volume",
227       "Stefan Kost <ensonic@users.sf.net>");
228
229   gstbasesrc_class->set_caps = GST_DEBUG_FUNCPTR (gst_audio_test_src_setcaps);
230   gstbasesrc_class->is_seekable =
231       GST_DEBUG_FUNCPTR (gst_audio_test_src_is_seekable);
232   gstbasesrc_class->do_seek = GST_DEBUG_FUNCPTR (gst_audio_test_src_do_seek);
233   gstbasesrc_class->query = GST_DEBUG_FUNCPTR (gst_audio_test_src_query);
234   gstbasesrc_class->get_times =
235       GST_DEBUG_FUNCPTR (gst_audio_test_src_get_times);
236   gstbasesrc_class->start = GST_DEBUG_FUNCPTR (gst_audio_test_src_start);
237   gstbasesrc_class->stop = GST_DEBUG_FUNCPTR (gst_audio_test_src_stop);
238   gstbasesrc_class->create = GST_DEBUG_FUNCPTR (gst_audio_test_src_create);
239 }
240
241 static void
242 gst_audio_test_src_init (GstAudioTestSrc * src)
243 {
244   GstPad *pad = GST_BASE_SRC_PAD (src);
245
246   gst_pad_set_fixatecaps_function (pad, gst_audio_test_src_src_fixate);
247
248   src->samplerate = 44100;
249   src->format = GST_AUDIO_TEST_SRC_FORMAT_NONE;
250
251   src->volume = DEFAULT_VOLUME;
252   src->freq = DEFAULT_FREQ;
253
254   /* we operate in time */
255   gst_base_src_set_format (GST_BASE_SRC (src), GST_FORMAT_TIME);
256   gst_base_src_set_live (GST_BASE_SRC (src), DEFAULT_IS_LIVE);
257
258   src->samples_per_buffer = DEFAULT_SAMPLES_PER_BUFFER;
259   src->generate_samples_per_buffer = src->samples_per_buffer;
260   src->timestamp_offset = DEFAULT_TIMESTAMP_OFFSET;
261   src->can_activate_pull = DEFAULT_CAN_ACTIVATE_PULL;
262
263   src->gen = NULL;
264
265   src->wave = DEFAULT_WAVE;
266   gst_base_src_set_blocksize (GST_BASE_SRC (src), -1);
267 }
268
269 static void
270 gst_audio_test_src_finalize (GObject * object)
271 {
272   GstAudioTestSrc *src = GST_AUDIO_TEST_SRC (object);
273
274   if (src->gen)
275     g_rand_free (src->gen);
276   src->gen = NULL;
277
278   G_OBJECT_CLASS (parent_class)->finalize (object);
279 }
280
281 static void
282 gst_audio_test_src_src_fixate (GstPad * pad, GstCaps * caps)
283 {
284   GstAudioTestSrc *src = GST_AUDIO_TEST_SRC (GST_PAD_PARENT (pad));
285   const gchar *name;
286   GstStructure *structure;
287
288   structure = gst_caps_get_structure (caps, 0);
289
290   GST_DEBUG_OBJECT (src, "fixating samplerate to %d", src->samplerate);
291
292   gst_structure_fixate_field_nearest_int (structure, "rate", src->samplerate);
293
294   name = gst_structure_get_name (structure);
295   if (strcmp (name, "audio/x-raw-int") == 0)
296     gst_structure_fixate_field_nearest_int (structure, "width", 32);
297   else if (strcmp (name, "audio/x-raw-float") == 0)
298     gst_structure_fixate_field_nearest_int (structure, "width", 64);
299
300   /* fixate to mono unless downstream requires stereo, for backwards compat */
301   gst_structure_fixate_field_nearest_int (structure, "channels", 1);
302 }
303
304 static gboolean
305 gst_audio_test_src_setcaps (GstBaseSrc * basesrc, GstCaps * caps)
306 {
307   GstAudioTestSrc *src = GST_AUDIO_TEST_SRC (basesrc);
308   const GstStructure *structure;
309   const gchar *name;
310   gint width;
311   gboolean ret;
312
313   structure = gst_caps_get_structure (caps, 0);
314   ret = gst_structure_get_int (structure, "rate", &src->samplerate);
315
316   GST_DEBUG_OBJECT (src, "negotiated to samplerate %d", src->samplerate);
317
318   name = gst_structure_get_name (structure);
319   if (strcmp (name, "audio/x-raw-int") == 0) {
320     ret &= gst_structure_get_int (structure, "width", &width);
321     src->format = (width == 32) ? GST_AUDIO_TEST_SRC_FORMAT_S32 :
322         GST_AUDIO_TEST_SRC_FORMAT_S16;
323   } else {
324     ret &= gst_structure_get_int (structure, "width", &width);
325     src->format = (width == 32) ? GST_AUDIO_TEST_SRC_FORMAT_F32 :
326         GST_AUDIO_TEST_SRC_FORMAT_F64;
327   }
328
329   /* allocate a new buffer suitable for this pad */
330   switch (src->format) {
331     case GST_AUDIO_TEST_SRC_FORMAT_S16:
332       src->sample_size = sizeof (gint16);
333       break;
334     case GST_AUDIO_TEST_SRC_FORMAT_S32:
335       src->sample_size = sizeof (gint32);
336       break;
337     case GST_AUDIO_TEST_SRC_FORMAT_F32:
338       src->sample_size = sizeof (gfloat);
339       break;
340     case GST_AUDIO_TEST_SRC_FORMAT_F64:
341       src->sample_size = sizeof (gdouble);
342       break;
343     default:
344       /* can't really happen */
345       ret = FALSE;
346       break;
347   }
348
349   ret &= gst_structure_get_int (structure, "channels", &src->channels);
350   GST_DEBUG_OBJECT (src, "negotiated to %d channels", src->channels);
351
352   gst_audio_test_src_change_wave (src);
353
354   return ret;
355 }
356
357 static gboolean
358 gst_audio_test_src_query (GstBaseSrc * basesrc, GstQuery * query)
359 {
360   GstAudioTestSrc *src = GST_AUDIO_TEST_SRC (basesrc);
361   gboolean res = FALSE;
362
363   switch (GST_QUERY_TYPE (query)) {
364     case GST_QUERY_CONVERT:
365     {
366       GstFormat src_fmt, dest_fmt;
367       gint64 src_val, dest_val;
368
369       gst_query_parse_convert (query, &src_fmt, &src_val, &dest_fmt, &dest_val);
370       if (src_fmt == dest_fmt) {
371         dest_val = src_val;
372         goto done;
373       }
374
375       switch (src_fmt) {
376         case GST_FORMAT_DEFAULT:
377           switch (dest_fmt) {
378             case GST_FORMAT_TIME:
379               /* samples to time */
380               dest_val =
381                   gst_util_uint64_scale_int (src_val, GST_SECOND,
382                   src->samplerate);
383               break;
384             default:
385               goto error;
386           }
387           break;
388         case GST_FORMAT_TIME:
389           switch (dest_fmt) {
390             case GST_FORMAT_DEFAULT:
391               /* time to samples */
392               dest_val =
393                   gst_util_uint64_scale_int (src_val, src->samplerate,
394                   GST_SECOND);
395               break;
396             default:
397               goto error;
398           }
399           break;
400         default:
401           goto error;
402       }
403     done:
404       gst_query_set_convert (query, src_fmt, src_val, dest_fmt, dest_val);
405       res = TRUE;
406       break;
407     }
408     case GST_QUERY_SCHEDULING:
409     {
410       /* if we can operate in pull mode */
411       gst_query_set_scheduling (query, src->can_activate_pull, TRUE, FALSE, 1,
412           -1, 1);
413       res = TRUE;
414       break;
415     }
416     default:
417       res = GST_BASE_SRC_CLASS (parent_class)->query (basesrc, query);
418       break;
419   }
420
421   return res;
422   /* ERROR */
423 error:
424   {
425     GST_DEBUG_OBJECT (src, "query failed");
426     return FALSE;
427   }
428 }
429
430 #define DEFINE_SINE(type,scale) \
431 static void \
432 gst_audio_test_src_create_sine_##type (GstAudioTestSrc * src, g##type * samples) \
433 { \
434   gint i, c; \
435   gdouble step, amp; \
436   \
437   step = M_PI_M2 * src->freq / src->samplerate; \
438   amp = src->volume * scale; \
439   \
440   i = 0; \
441   while (i < (src->generate_samples_per_buffer * src->channels)) { \
442     src->accumulator += step; \
443     if (src->accumulator >= M_PI_M2) \
444       src->accumulator -= M_PI_M2; \
445     \
446     for (c = 0; c < src->channels; ++c) { \
447       samples[i++] = (g##type) (sin (src->accumulator) * amp); \
448     } \
449   } \
450 }
451
452 DEFINE_SINE (int16, 32767.0);
453 DEFINE_SINE (int32, 2147483647.0);
454 DEFINE_SINE (float, 1.0);
455 DEFINE_SINE (double, 1.0);
456
457 static const ProcessFunc sine_funcs[] = {
458   (ProcessFunc) gst_audio_test_src_create_sine_int16,
459   (ProcessFunc) gst_audio_test_src_create_sine_int32,
460   (ProcessFunc) gst_audio_test_src_create_sine_float,
461   (ProcessFunc) gst_audio_test_src_create_sine_double
462 };
463
464 #define DEFINE_SQUARE(type,scale) \
465 static void \
466 gst_audio_test_src_create_square_##type (GstAudioTestSrc * src, g##type * samples) \
467 { \
468   gint i, c; \
469   gdouble step, amp; \
470   \
471   step = M_PI_M2 * src->freq / src->samplerate; \
472   amp = src->volume * scale; \
473   \
474   i = 0; \
475   while (i < (src->generate_samples_per_buffer * src->channels)) { \
476     src->accumulator += step; \
477     if (src->accumulator >= M_PI_M2) \
478       src->accumulator -= M_PI_M2; \
479     \
480     for (c = 0; c < src->channels; ++c) { \
481       samples[i++] = (g##type) ((src->accumulator < M_PI) ? amp : -amp); \
482     } \
483   } \
484 }
485
486 DEFINE_SQUARE (int16, 32767.0);
487 DEFINE_SQUARE (int32, 2147483647.0);
488 DEFINE_SQUARE (float, 1.0);
489 DEFINE_SQUARE (double, 1.0);
490
491 static const ProcessFunc square_funcs[] = {
492   (ProcessFunc) gst_audio_test_src_create_square_int16,
493   (ProcessFunc) gst_audio_test_src_create_square_int32,
494   (ProcessFunc) gst_audio_test_src_create_square_float,
495   (ProcessFunc) gst_audio_test_src_create_square_double
496 };
497
498 #define DEFINE_SAW(type,scale) \
499 static void \
500 gst_audio_test_src_create_saw_##type (GstAudioTestSrc * src, g##type * samples) \
501 { \
502   gint i, c; \
503   gdouble step, amp; \
504   \
505   step = M_PI_M2 * src->freq / src->samplerate; \
506   amp = (src->volume * scale) / M_PI; \
507   \
508   i = 0; \
509   while (i < (src->generate_samples_per_buffer * src->channels)) { \
510     src->accumulator += step; \
511     if (src->accumulator >= M_PI_M2) \
512       src->accumulator -= M_PI_M2; \
513     \
514     if (src->accumulator < M_PI) { \
515       for (c = 0; c < src->channels; ++c) \
516         samples[i++] = (g##type) (src->accumulator * amp); \
517     } else { \
518       for (c = 0; c < src->channels; ++c) \
519         samples[i++] = (g##type) ((M_PI_M2 - src->accumulator) * -amp); \
520     } \
521   } \
522 }
523
524 DEFINE_SAW (int16, 32767.0);
525 DEFINE_SAW (int32, 2147483647.0);
526 DEFINE_SAW (float, 1.0);
527 DEFINE_SAW (double, 1.0);
528
529 static const ProcessFunc saw_funcs[] = {
530   (ProcessFunc) gst_audio_test_src_create_saw_int16,
531   (ProcessFunc) gst_audio_test_src_create_saw_int32,
532   (ProcessFunc) gst_audio_test_src_create_saw_float,
533   (ProcessFunc) gst_audio_test_src_create_saw_double
534 };
535
536 #define DEFINE_TRIANGLE(type,scale) \
537 static void \
538 gst_audio_test_src_create_triangle_##type (GstAudioTestSrc * src, g##type * samples) \
539 { \
540   gint i, c; \
541   gdouble step, amp; \
542   \
543   step = M_PI_M2 * src->freq / src->samplerate; \
544   amp = (src->volume * scale) / M_PI_2; \
545   \
546   i = 0; \
547   while (i < (src->generate_samples_per_buffer * src->channels)) { \
548     src->accumulator += step; \
549     if (src->accumulator >= M_PI_M2) \
550       src->accumulator -= M_PI_M2; \
551     \
552     if (src->accumulator < (M_PI * 0.5)) { \
553       for (c = 0; c < src->channels; ++c) \
554         samples[i++] = (g##type) (src->accumulator * amp); \
555     } else if (src->accumulator < (M_PI * 1.5)) { \
556       for (c = 0; c < src->channels; ++c) \
557         samples[i++] = (g##type) ((src->accumulator - M_PI) * -amp); \
558     } else { \
559       for (c = 0; c < src->channels; ++c) \
560         samples[i++] = (g##type) ((M_PI_M2 - src->accumulator) * -amp); \
561     } \
562   } \
563 }
564
565 DEFINE_TRIANGLE (int16, 32767.0);
566 DEFINE_TRIANGLE (int32, 2147483647.0);
567 DEFINE_TRIANGLE (float, 1.0);
568 DEFINE_TRIANGLE (double, 1.0);
569
570 static const ProcessFunc triangle_funcs[] = {
571   (ProcessFunc) gst_audio_test_src_create_triangle_int16,
572   (ProcessFunc) gst_audio_test_src_create_triangle_int32,
573   (ProcessFunc) gst_audio_test_src_create_triangle_float,
574   (ProcessFunc) gst_audio_test_src_create_triangle_double
575 };
576
577 #define DEFINE_SILENCE(type) \
578 static void \
579 gst_audio_test_src_create_silence_##type (GstAudioTestSrc * src, g##type * samples) \
580 { \
581   memset (samples, 0, src->generate_samples_per_buffer * sizeof (g##type) * src->channels); \
582 }
583
584 DEFINE_SILENCE (int16);
585 DEFINE_SILENCE (int32);
586 DEFINE_SILENCE (float);
587 DEFINE_SILENCE (double);
588
589 static const ProcessFunc silence_funcs[] = {
590   (ProcessFunc) gst_audio_test_src_create_silence_int16,
591   (ProcessFunc) gst_audio_test_src_create_silence_int32,
592   (ProcessFunc) gst_audio_test_src_create_silence_float,
593   (ProcessFunc) gst_audio_test_src_create_silence_double
594 };
595
596 #define DEFINE_WHITE_NOISE(type,scale) \
597 static void \
598 gst_audio_test_src_create_white_noise_##type (GstAudioTestSrc * src, g##type * samples) \
599 { \
600   gint i, c; \
601   gdouble amp = (src->volume * scale); \
602   \
603   i = 0; \
604   while (i < (src->generate_samples_per_buffer * src->channels)) { \
605     for (c = 0; c < src->channels; ++c) \
606       samples[i++] = (g##type) (amp * g_rand_double_range (src->gen, -1.0, 1.0)); \
607   } \
608 }
609
610 DEFINE_WHITE_NOISE (int16, 32767.0);
611 DEFINE_WHITE_NOISE (int32, 2147483647.0);
612 DEFINE_WHITE_NOISE (float, 1.0);
613 DEFINE_WHITE_NOISE (double, 1.0);
614
615 static const ProcessFunc white_noise_funcs[] = {
616   (ProcessFunc) gst_audio_test_src_create_white_noise_int16,
617   (ProcessFunc) gst_audio_test_src_create_white_noise_int32,
618   (ProcessFunc) gst_audio_test_src_create_white_noise_float,
619   (ProcessFunc) gst_audio_test_src_create_white_noise_double
620 };
621
622 /* pink noise calculation is based on
623  * http://www.firstpr.com.au/dsp/pink-noise/phil_burk_19990905_patest_pink.c
624  * which has been released under public domain
625  * Many thanks Phil!
626  */
627 static void
628 gst_audio_test_src_init_pink_noise (GstAudioTestSrc * src)
629 {
630   gint i;
631   gint num_rows = 12;           /* arbitrary: 1 .. PINK_MAX_RANDOM_ROWS */
632   glong pmax;
633
634   src->pink.index = 0;
635   src->pink.index_mask = (1 << num_rows) - 1;
636   /* calculate maximum possible signed random value.
637    * Extra 1 for white noise always added. */
638   pmax = (num_rows + 1) * (1 << (PINK_RANDOM_BITS - 1));
639   src->pink.scalar = 1.0f / pmax;
640   /* Initialize rows. */
641   for (i = 0; i < num_rows; i++)
642     src->pink.rows[i] = 0;
643   src->pink.running_sum = 0;
644 }
645
646 /* Generate Pink noise values between -1.0 and +1.0 */
647 static gdouble
648 gst_audio_test_src_generate_pink_noise_value (GstAudioTestSrc * src)
649 {
650   GstPinkNoise *pink = &src->pink;
651   glong new_random;
652   glong sum;
653
654   /* Increment and mask index. */
655   pink->index = (pink->index + 1) & pink->index_mask;
656
657   /* If index is zero, don't update any random values. */
658   if (pink->index != 0) {
659     /* Determine how many trailing zeros in PinkIndex. */
660     /* This algorithm will hang if n==0 so test first. */
661     gint num_zeros = 0;
662     gint n = pink->index;
663
664     while ((n & 1) == 0) {
665       n = n >> 1;
666       num_zeros++;
667     }
668
669     /* Replace the indexed ROWS random value.
670      * Subtract and add back to RunningSum instead of adding all the random
671      * values together. Only one changes each time.
672      */
673     pink->running_sum -= pink->rows[num_zeros];
674     new_random = 32768.0 - (65536.0 * (gulong) g_rand_int (src->gen)
675         / (G_MAXUINT32 + 1.0));
676     pink->running_sum += new_random;
677     pink->rows[num_zeros] = new_random;
678   }
679
680   /* Add extra white noise value. */
681   new_random = 32768.0 - (65536.0 * (gulong) g_rand_int (src->gen)
682       / (G_MAXUINT32 + 1.0));
683   sum = pink->running_sum + new_random;
684
685   /* Scale to range of -1.0 to 0.9999. */
686   return (pink->scalar * sum);
687 }
688
689 #define DEFINE_PINK(type, scale) \
690 static void \
691 gst_audio_test_src_create_pink_noise_##type (GstAudioTestSrc * src, g##type * samples) \
692 { \
693   gint i, c; \
694   gdouble amp; \
695   \
696   amp = src->volume * scale; \
697   \
698   i = 0; \
699   while (i < (src->generate_samples_per_buffer * src->channels)) { \
700     for (c = 0; c < src->channels; ++c) { \
701       samples[i++] = \
702         (g##type) (gst_audio_test_src_generate_pink_noise_value (src) * \
703         amp); \
704     } \
705   } \
706 }
707
708 DEFINE_PINK (int16, 32767.0);
709 DEFINE_PINK (int32, 2147483647.0);
710 DEFINE_PINK (float, 1.0);
711 DEFINE_PINK (double, 1.0);
712
713 static const ProcessFunc pink_noise_funcs[] = {
714   (ProcessFunc) gst_audio_test_src_create_pink_noise_int16,
715   (ProcessFunc) gst_audio_test_src_create_pink_noise_int32,
716   (ProcessFunc) gst_audio_test_src_create_pink_noise_float,
717   (ProcessFunc) gst_audio_test_src_create_pink_noise_double
718 };
719
720 static void
721 gst_audio_test_src_init_sine_table (GstAudioTestSrc * src)
722 {
723   gint i;
724   gdouble ang = 0.0;
725   gdouble step = M_PI_M2 / 1024.0;
726   gdouble amp = src->volume;
727
728   for (i = 0; i < 1024; i++) {
729     src->wave_table[i] = sin (ang) * amp;
730     ang += step;
731   }
732 }
733
734 #define DEFINE_SINE_TABLE(type,scale) \
735 static void \
736 gst_audio_test_src_create_sine_table_##type (GstAudioTestSrc * src, g##type * samples) \
737 { \
738   gint i, c; \
739   gdouble step, scl; \
740   \
741   step = M_PI_M2 * src->freq / src->samplerate; \
742   scl = 1024.0 / M_PI_M2; \
743   \
744   i = 0; \
745   while (i < (src->generate_samples_per_buffer * src->channels)) { \
746     src->accumulator += step; \
747     if (src->accumulator >= M_PI_M2) \
748       src->accumulator -= M_PI_M2; \
749     \
750     for (c = 0; c < src->channels; ++c) \
751       samples[i++] = (g##type) scale * src->wave_table[(gint) (src->accumulator * scl)]; \
752   } \
753 }
754
755 DEFINE_SINE_TABLE (int16, 32767.0);
756 DEFINE_SINE_TABLE (int32, 2147483647.0);
757 DEFINE_SINE_TABLE (float, 1.0);
758 DEFINE_SINE_TABLE (double, 1.0);
759
760 static const ProcessFunc sine_table_funcs[] = {
761   (ProcessFunc) gst_audio_test_src_create_sine_table_int16,
762   (ProcessFunc) gst_audio_test_src_create_sine_table_int32,
763   (ProcessFunc) gst_audio_test_src_create_sine_table_float,
764   (ProcessFunc) gst_audio_test_src_create_sine_table_double
765 };
766
767 #define DEFINE_TICKS(type,scale) \
768 static void \
769 gst_audio_test_src_create_tick_##type (GstAudioTestSrc * src, g##type * samples) \
770 { \
771   gint i, c; \
772   gdouble step, scl; \
773   \
774   step = M_PI_M2 * src->freq / src->samplerate; \
775   scl = 1024.0 / M_PI_M2; \
776   \
777   for (i = 0; i < src->generate_samples_per_buffer; i++) { \
778     src->accumulator += step; \
779     if (src->accumulator >= M_PI_M2) \
780       src->accumulator -= M_PI_M2; \
781     \
782     if ((src->next_sample + i)%src->samplerate < 1600) { \
783       for (c = 0; c < src->channels; ++c) \
784         samples[(i * src->channels) + c] = (g##type) scale * src->wave_table[(gint) (src->accumulator * scl)]; \
785     } else { \
786       for (c = 0; c < src->channels; ++c) \
787         samples[(i * src->channels) + c] = 0; \
788     } \
789   } \
790 }
791
792 DEFINE_TICKS (int16, 32767.0);
793 DEFINE_TICKS (int32, 2147483647.0);
794 DEFINE_TICKS (float, 1.0);
795 DEFINE_TICKS (double, 1.0);
796
797 static const ProcessFunc tick_funcs[] = {
798   (ProcessFunc) gst_audio_test_src_create_tick_int16,
799   (ProcessFunc) gst_audio_test_src_create_tick_int32,
800   (ProcessFunc) gst_audio_test_src_create_tick_float,
801   (ProcessFunc) gst_audio_test_src_create_tick_double
802 };
803
804 /* Gaussian white noise using Box-Muller algorithm.  unit variance
805  * normally-distributed random numbers are generated in pairs as the real
806  * and imaginary parts of a compex random variable with
807  * uniformly-distributed argument and \chi^{2}-distributed modulus.
808  */
809
810 #define DEFINE_GAUSSIAN_WHITE_NOISE(type,scale) \
811 static void \
812 gst_audio_test_src_create_gaussian_white_noise_##type (GstAudioTestSrc * src, g##type * samples) \
813 { \
814   gint i, c; \
815   gdouble amp = (src->volume * scale); \
816   \
817   for (i = 0; i < src->generate_samples_per_buffer * src->channels; ) { \
818     for (c = 0; c < src->channels; ++c) { \
819       gdouble mag = sqrt (-2 * log (1.0 - g_rand_double (src->gen))); \
820       gdouble phs = g_rand_double_range (src->gen, 0.0, M_PI_M2); \
821       \
822       samples[i++] = (g##type) (amp * mag * cos (phs)); \
823       if (++c >= src->channels) \
824         break; \
825       samples[i++] = (g##type) (amp * mag * sin (phs)); \
826     } \
827   } \
828 }
829
830 DEFINE_GAUSSIAN_WHITE_NOISE (int16, 32767.0);
831 DEFINE_GAUSSIAN_WHITE_NOISE (int32, 2147483647.0);
832 DEFINE_GAUSSIAN_WHITE_NOISE (float, 1.0);
833 DEFINE_GAUSSIAN_WHITE_NOISE (double, 1.0);
834
835 static const ProcessFunc gaussian_white_noise_funcs[] = {
836   (ProcessFunc) gst_audio_test_src_create_gaussian_white_noise_int16,
837   (ProcessFunc) gst_audio_test_src_create_gaussian_white_noise_int32,
838   (ProcessFunc) gst_audio_test_src_create_gaussian_white_noise_float,
839   (ProcessFunc) gst_audio_test_src_create_gaussian_white_noise_double
840 };
841
842 /* Brownian (Red) Noise: noise where the power density decreases by 6 dB per
843  * octave with increasing frequency
844  *
845  * taken from http://vellocet.com/dsp/noise/VRand.html
846  * by Andrew Simper of Vellocet (andy@vellocet.com)
847  */
848
849 #define DEFINE_RED_NOISE(type,scale) \
850 static void \
851 gst_audio_test_src_create_red_noise_##type (GstAudioTestSrc * src, g##type * samples) \
852 { \
853   gint i, c; \
854   gdouble amp = (src->volume * scale); \
855   gdouble state = src->red.state; \
856   \
857   for (i = 0; i < src->generate_samples_per_buffer * src->channels; ) { \
858     for (c = 0; c < src->channels; ++c) { \
859       while (TRUE) { \
860         gdouble  r = g_rand_double_range (src->gen, -1.0, 1.0); \
861         state += r; \
862         if (state<-8.0f || state>8.0f) state -= r; \
863         else break; \
864       } \
865       samples[i++] = (g##type) (amp * state * 0.0625f); /* /16.0 */ \
866     } \
867   } \
868   src->red.state = state; \
869 }
870
871 DEFINE_RED_NOISE (int16, 32767.0);
872 DEFINE_RED_NOISE (int32, 2147483647.0);
873 DEFINE_RED_NOISE (float, 1.0);
874 DEFINE_RED_NOISE (double, 1.0);
875
876 static const ProcessFunc red_noise_funcs[] = {
877   (ProcessFunc) gst_audio_test_src_create_red_noise_int16,
878   (ProcessFunc) gst_audio_test_src_create_red_noise_int32,
879   (ProcessFunc) gst_audio_test_src_create_red_noise_float,
880   (ProcessFunc) gst_audio_test_src_create_red_noise_double
881 };
882
883 /* Blue Noise: apply spectral inversion to pink noise */
884
885 #define DEFINE_BLUE_NOISE(type) \
886 static void \
887 gst_audio_test_src_create_blue_noise_##type (GstAudioTestSrc * src, g##type * samples) \
888 { \
889   gint i, c; \
890   static gdouble flip=1.0; \
891   \
892   gst_audio_test_src_create_pink_noise_##type (src, samples); \
893   for (i = 0; i < src->generate_samples_per_buffer * src->channels; ) { \
894     for (c = 0; c < src->channels; ++c) { \
895       samples[i++] *= flip; \
896     } \
897     flip *= -1.0; \
898   } \
899 }
900
901 DEFINE_BLUE_NOISE (int16);
902 DEFINE_BLUE_NOISE (int32);
903 DEFINE_BLUE_NOISE (float);
904 DEFINE_BLUE_NOISE (double);
905
906 static const ProcessFunc blue_noise_funcs[] = {
907   (ProcessFunc) gst_audio_test_src_create_blue_noise_int16,
908   (ProcessFunc) gst_audio_test_src_create_blue_noise_int32,
909   (ProcessFunc) gst_audio_test_src_create_blue_noise_float,
910   (ProcessFunc) gst_audio_test_src_create_blue_noise_double
911 };
912
913
914 /* Violet Noise: apply spectral inversion to red noise */
915
916 #define DEFINE_VIOLET_NOISE(type) \
917 static void \
918 gst_audio_test_src_create_violet_noise_##type (GstAudioTestSrc * src, g##type * samples) \
919 { \
920   gint i, c; \
921   static gdouble flip=1.0; \
922   \
923   gst_audio_test_src_create_red_noise_##type (src, samples); \
924   for (i = 0; i < src->generate_samples_per_buffer * src->channels; ) { \
925     for (c = 0; c < src->channels; ++c) { \
926       samples[i++] *= flip; \
927     } \
928     flip *= -1.0; \
929   } \
930 }
931
932 DEFINE_VIOLET_NOISE (int16);
933 DEFINE_VIOLET_NOISE (int32);
934 DEFINE_VIOLET_NOISE (float);
935 DEFINE_VIOLET_NOISE (double);
936
937 static const ProcessFunc violet_noise_funcs[] = {
938   (ProcessFunc) gst_audio_test_src_create_violet_noise_int16,
939   (ProcessFunc) gst_audio_test_src_create_violet_noise_int32,
940   (ProcessFunc) gst_audio_test_src_create_violet_noise_float,
941   (ProcessFunc) gst_audio_test_src_create_violet_noise_double
942 };
943
944
945 /*
946  * gst_audio_test_src_change_wave:
947  * Assign function pointer of wave genrator.
948  */
949 static void
950 gst_audio_test_src_change_wave (GstAudioTestSrc * src)
951 {
952   if (src->format == -1) {
953     src->process = NULL;
954     return;
955   }
956
957   switch (src->wave) {
958     case GST_AUDIO_TEST_SRC_WAVE_SINE:
959       src->process = sine_funcs[src->format];
960       break;
961     case GST_AUDIO_TEST_SRC_WAVE_SQUARE:
962       src->process = square_funcs[src->format];
963       break;
964     case GST_AUDIO_TEST_SRC_WAVE_SAW:
965       src->process = saw_funcs[src->format];
966       break;
967     case GST_AUDIO_TEST_SRC_WAVE_TRIANGLE:
968       src->process = triangle_funcs[src->format];
969       break;
970     case GST_AUDIO_TEST_SRC_WAVE_SILENCE:
971       src->process = silence_funcs[src->format];
972       break;
973     case GST_AUDIO_TEST_SRC_WAVE_WHITE_NOISE:
974       if (!(src->gen))
975         src->gen = g_rand_new ();
976       src->process = white_noise_funcs[src->format];
977       break;
978     case GST_AUDIO_TEST_SRC_WAVE_PINK_NOISE:
979       if (!(src->gen))
980         src->gen = g_rand_new ();
981       gst_audio_test_src_init_pink_noise (src);
982       src->process = pink_noise_funcs[src->format];
983       break;
984     case GST_AUDIO_TEST_SRC_WAVE_SINE_TAB:
985       gst_audio_test_src_init_sine_table (src);
986       src->process = sine_table_funcs[src->format];
987       break;
988     case GST_AUDIO_TEST_SRC_WAVE_TICKS:
989       gst_audio_test_src_init_sine_table (src);
990       src->process = tick_funcs[src->format];
991       break;
992     case GST_AUDIO_TEST_SRC_WAVE_GAUSSIAN_WHITE_NOISE:
993       if (!(src->gen))
994         src->gen = g_rand_new ();
995       src->process = gaussian_white_noise_funcs[src->format];
996       break;
997     case GST_AUDIO_TEST_SRC_WAVE_RED_NOISE:
998       if (!(src->gen))
999         src->gen = g_rand_new ();
1000       src->red.state = 0.0;
1001       src->process = red_noise_funcs[src->format];
1002       break;
1003     case GST_AUDIO_TEST_SRC_WAVE_BLUE_NOISE:
1004       if (!(src->gen))
1005         src->gen = g_rand_new ();
1006       gst_audio_test_src_init_pink_noise (src);
1007       src->process = blue_noise_funcs[src->format];
1008       break;
1009     case GST_AUDIO_TEST_SRC_WAVE_VIOLET_NOISE:
1010       if (!(src->gen))
1011         src->gen = g_rand_new ();
1012       src->red.state = 0.0;
1013       src->process = violet_noise_funcs[src->format];
1014     default:
1015       GST_ERROR ("invalid wave-form");
1016       break;
1017   }
1018 }
1019
1020 /*
1021  * gst_audio_test_src_change_volume:
1022  * Recalc wave tables for precalculated waves.
1023  */
1024 static void
1025 gst_audio_test_src_change_volume (GstAudioTestSrc * src)
1026 {
1027   switch (src->wave) {
1028     case GST_AUDIO_TEST_SRC_WAVE_SINE_TAB:
1029       gst_audio_test_src_init_sine_table (src);
1030       break;
1031     default:
1032       break;
1033   }
1034 }
1035
1036 static void
1037 gst_audio_test_src_get_times (GstBaseSrc * basesrc, GstBuffer * buffer,
1038     GstClockTime * start, GstClockTime * end)
1039 {
1040   /* for live sources, sync on the timestamp of the buffer */
1041   if (gst_base_src_is_live (basesrc)) {
1042     GstClockTime timestamp = GST_BUFFER_TIMESTAMP (buffer);
1043
1044     if (GST_CLOCK_TIME_IS_VALID (timestamp)) {
1045       /* get duration to calculate end time */
1046       GstClockTime duration = GST_BUFFER_DURATION (buffer);
1047
1048       if (GST_CLOCK_TIME_IS_VALID (duration)) {
1049         *end = timestamp + duration;
1050       }
1051       *start = timestamp;
1052     }
1053   } else {
1054     *start = -1;
1055     *end = -1;
1056   }
1057 }
1058
1059 static gboolean
1060 gst_audio_test_src_start (GstBaseSrc * basesrc)
1061 {
1062   GstAudioTestSrc *src = GST_AUDIO_TEST_SRC (basesrc);
1063
1064   src->next_sample = 0;
1065   src->next_byte = 0;
1066   src->next_time = 0;
1067   src->check_seek_stop = FALSE;
1068   src->eos_reached = FALSE;
1069   src->tags_pushed = FALSE;
1070   src->accumulator = 0;
1071
1072   return TRUE;
1073 }
1074
1075 static gboolean
1076 gst_audio_test_src_stop (GstBaseSrc * basesrc)
1077 {
1078   return TRUE;
1079 }
1080
1081 /* seek to time, will be called when we operate in push mode. In pull mode we
1082  * get the requested byte offset. */
1083 static gboolean
1084 gst_audio_test_src_do_seek (GstBaseSrc * basesrc, GstSegment * segment)
1085 {
1086   GstAudioTestSrc *src = GST_AUDIO_TEST_SRC (basesrc);
1087   GstClockTime time;
1088
1089   GST_DEBUG_OBJECT (src, "seeking %" GST_SEGMENT_FORMAT, segment);
1090
1091   time = segment->position;
1092   src->reverse = (segment->rate < 0.0);
1093
1094   /* now move to the time indicated */
1095   src->next_sample =
1096       gst_util_uint64_scale_int (time, src->samplerate, GST_SECOND);
1097   src->next_byte = src->next_sample * src->sample_size * src->channels;
1098   src->next_time =
1099       gst_util_uint64_scale_int (src->next_sample, GST_SECOND, src->samplerate);
1100
1101   GST_DEBUG_OBJECT (src, "seeking next_sample=%" G_GINT64_FORMAT
1102       " next_time=%" GST_TIME_FORMAT, src->next_sample,
1103       GST_TIME_ARGS (src->next_time));
1104
1105   g_assert (src->next_time <= time);
1106
1107   if (!src->reverse) {
1108     if (GST_CLOCK_TIME_IS_VALID (segment->start)) {
1109       segment->time = segment->start;
1110     }
1111   } else {
1112     if (GST_CLOCK_TIME_IS_VALID (segment->stop)) {
1113       segment->time = segment->stop;
1114     }
1115   }
1116
1117   if (GST_CLOCK_TIME_IS_VALID (segment->stop)) {
1118     time = segment->stop;
1119     src->sample_stop = gst_util_uint64_scale_int (time, src->samplerate,
1120         GST_SECOND);
1121     src->check_seek_stop = TRUE;
1122   } else {
1123     src->check_seek_stop = FALSE;
1124   }
1125   src->eos_reached = FALSE;
1126
1127   return TRUE;
1128 }
1129
1130 static gboolean
1131 gst_audio_test_src_is_seekable (GstBaseSrc * basesrc)
1132 {
1133   /* we're seekable... */
1134   return TRUE;
1135 }
1136
1137 static GstFlowReturn
1138 gst_audio_test_src_create (GstBaseSrc * basesrc, guint64 offset,
1139     guint length, GstBuffer ** buffer)
1140 {
1141   GstAudioTestSrc *src;
1142   GstBuffer *buf;
1143   GstClockTime next_time;
1144   gint64 next_sample, next_byte;
1145   gint bytes, samples;
1146   GstElementClass *eclass;
1147   guint8 *data;
1148
1149   src = GST_AUDIO_TEST_SRC (basesrc);
1150
1151   /* example for tagging generated data */
1152   if (!src->tags_pushed) {
1153     GstTagList *taglist;
1154
1155     taglist = gst_tag_list_new ();
1156
1157     gst_tag_list_add (taglist, GST_TAG_MERGE_APPEND,
1158         GST_TAG_DESCRIPTION, "audiotest wave", NULL);
1159
1160     eclass = GST_ELEMENT_CLASS (parent_class);
1161     if (eclass->send_event)
1162       eclass->send_event (GST_ELEMENT_CAST (basesrc),
1163           gst_event_new_tag (taglist));
1164     src->tags_pushed = TRUE;
1165   }
1166
1167   if (src->eos_reached) {
1168     GST_INFO_OBJECT (src, "eos");
1169     return GST_FLOW_UNEXPECTED;
1170   }
1171
1172   /* if no length was given, use our default length in samples otherwise convert
1173    * the length in bytes to samples. */
1174   if (length == -1)
1175     samples = src->samples_per_buffer;
1176   else
1177     samples = length / (src->sample_size * src->channels);
1178
1179   /* if no offset was given, use our next logical byte */
1180   if (offset == -1)
1181     offset = src->next_byte;
1182
1183   /* now see if we are at the byteoffset we think we are */
1184   if (offset != src->next_byte) {
1185     GST_DEBUG_OBJECT (src, "seek to new offset %" G_GUINT64_FORMAT, offset);
1186     /* we have a discont in the expected sample offset, do a 'seek' */
1187     src->next_sample = offset / (src->sample_size * src->channels);
1188     src->next_time =
1189         gst_util_uint64_scale_int (src->next_sample, GST_SECOND,
1190         src->samplerate);
1191     src->next_byte = offset;
1192   }
1193
1194   /* check for eos */
1195   if (src->check_seek_stop &&
1196       (src->sample_stop > src->next_sample) &&
1197       (src->sample_stop < src->next_sample + samples)
1198       ) {
1199     /* calculate only partial buffer */
1200     src->generate_samples_per_buffer = src->sample_stop - src->next_sample;
1201     next_sample = src->sample_stop;
1202     src->eos_reached = TRUE;
1203   } else {
1204     /* calculate full buffer */
1205     src->generate_samples_per_buffer = samples;
1206     next_sample = src->next_sample + (src->reverse ? (-samples) : samples);
1207   }
1208
1209   bytes = src->generate_samples_per_buffer * src->sample_size * src->channels;
1210
1211   buf = gst_buffer_new_and_alloc (bytes);
1212
1213   next_byte = src->next_byte + (src->reverse ? (-bytes) : bytes);
1214   next_time = gst_util_uint64_scale_int (next_sample, GST_SECOND,
1215       src->samplerate);
1216
1217   GST_LOG_OBJECT (src, "samplerate %d", src->samplerate);
1218   GST_LOG_OBJECT (src, "next_sample %" G_GINT64_FORMAT ", ts %" GST_TIME_FORMAT,
1219       next_sample, GST_TIME_ARGS (next_time));
1220
1221   GST_BUFFER_OFFSET (buf) = src->next_sample;
1222   GST_BUFFER_OFFSET_END (buf) = next_sample;
1223   if (!src->reverse) {
1224     GST_BUFFER_TIMESTAMP (buf) = src->timestamp_offset + src->next_time;
1225     GST_BUFFER_DURATION (buf) = next_time - src->next_time;
1226   } else {
1227     GST_BUFFER_TIMESTAMP (buf) = src->timestamp_offset + next_time;
1228     GST_BUFFER_DURATION (buf) = src->next_time - next_time;
1229   }
1230
1231   gst_object_sync_values (G_OBJECT (src), GST_BUFFER_TIMESTAMP (buf));
1232
1233   src->next_time = next_time;
1234   src->next_sample = next_sample;
1235   src->next_byte = next_byte;
1236
1237   GST_LOG_OBJECT (src, "generating %u samples at ts %" GST_TIME_FORMAT,
1238       src->generate_samples_per_buffer,
1239       GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buf)));
1240
1241   data = gst_buffer_map (buf, NULL, NULL, GST_MAP_WRITE);
1242   src->process (src, data);
1243   gst_buffer_unmap (buf, data, bytes);
1244
1245   if (G_UNLIKELY ((src->wave == GST_AUDIO_TEST_SRC_WAVE_SILENCE)
1246           || (src->volume == 0.0))) {
1247     GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_GAP);
1248   }
1249
1250   *buffer = buf;
1251
1252   return GST_FLOW_OK;
1253 }
1254
1255 static void
1256 gst_audio_test_src_set_property (GObject * object, guint prop_id,
1257     const GValue * value, GParamSpec * pspec)
1258 {
1259   GstAudioTestSrc *src = GST_AUDIO_TEST_SRC (object);
1260
1261   switch (prop_id) {
1262     case PROP_SAMPLES_PER_BUFFER:
1263       src->samples_per_buffer = g_value_get_int (value);
1264       break;
1265     case PROP_WAVE:
1266       src->wave = g_value_get_enum (value);
1267       gst_audio_test_src_change_wave (src);
1268       break;
1269     case PROP_FREQ:
1270       src->freq = g_value_get_double (value);
1271       break;
1272     case PROP_VOLUME:
1273       src->volume = g_value_get_double (value);
1274       gst_audio_test_src_change_volume (src);
1275       break;
1276     case PROP_IS_LIVE:
1277       gst_base_src_set_live (GST_BASE_SRC (src), g_value_get_boolean (value));
1278       break;
1279     case PROP_TIMESTAMP_OFFSET:
1280       src->timestamp_offset = g_value_get_int64 (value);
1281       break;
1282     case PROP_CAN_ACTIVATE_PUSH:
1283       GST_BASE_SRC (src)->can_activate_push = g_value_get_boolean (value);
1284       break;
1285     case PROP_CAN_ACTIVATE_PULL:
1286       src->can_activate_pull = g_value_get_boolean (value);
1287       break;
1288     default:
1289       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1290       break;
1291   }
1292 }
1293
1294 static void
1295 gst_audio_test_src_get_property (GObject * object, guint prop_id,
1296     GValue * value, GParamSpec * pspec)
1297 {
1298   GstAudioTestSrc *src = GST_AUDIO_TEST_SRC (object);
1299
1300   switch (prop_id) {
1301     case PROP_SAMPLES_PER_BUFFER:
1302       g_value_set_int (value, src->samples_per_buffer);
1303       break;
1304     case PROP_WAVE:
1305       g_value_set_enum (value, src->wave);
1306       break;
1307     case PROP_FREQ:
1308       g_value_set_double (value, src->freq);
1309       break;
1310     case PROP_VOLUME:
1311       g_value_set_double (value, src->volume);
1312       break;
1313     case PROP_IS_LIVE:
1314       g_value_set_boolean (value, gst_base_src_is_live (GST_BASE_SRC (src)));
1315       break;
1316     case PROP_TIMESTAMP_OFFSET:
1317       g_value_set_int64 (value, src->timestamp_offset);
1318       break;
1319     case PROP_CAN_ACTIVATE_PUSH:
1320       g_value_set_boolean (value, GST_BASE_SRC (src)->can_activate_push);
1321       break;
1322     case PROP_CAN_ACTIVATE_PULL:
1323       g_value_set_boolean (value, src->can_activate_pull);
1324       break;
1325     default:
1326       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1327       break;
1328   }
1329 }
1330
1331 static gboolean
1332 plugin_init (GstPlugin * plugin)
1333 {
1334   /* initialize gst controller library */
1335   gst_controller_init (NULL, NULL);
1336
1337   GST_DEBUG_CATEGORY_INIT (audio_test_src_debug, "audiotestsrc", 0,
1338       "Audio Test Source");
1339
1340   return gst_element_register (plugin, "audiotestsrc",
1341       GST_RANK_NONE, GST_TYPE_AUDIO_TEST_SRC);
1342 }
1343
1344 GST_PLUGIN_DEFINE (GST_VERSION_MAJOR,
1345     GST_VERSION_MINOR,
1346     "audiotestsrc",
1347     "Creates audio test signals of given frequency and volume",
1348     plugin_init, VERSION, "LGPL", GST_PACKAGE_NAME, GST_PACKAGE_ORIGIN);