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