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