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