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