2 * Copyright (C) 2010 David Schleef <ds@schleef.org>
3 * Copyright (C) 2005 Stefan Kost <ensonic@users.sf.net>
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Library General Public
7 * License as published by the Free Software Foundation; either
8 * version 2 of the License, or (at your option) any later version.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Library General Public License for more details.
15 * You should have received a copy of the GNU Library General Public
16 * License along with this library; if not, write to the
17 * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
18 * Boston, MA 02110-1301, USA.
26 #include <gst/base/gstbasesrc.h>
27 #include <gst/base/gstadapter.h>
28 #include <gst/audio/audio.h>
30 #include <flite/flite.h>
32 #define GST_TYPE_FLITE_TEST_SRC \
33 (gst_flite_test_src_get_type())
34 #define GST_FLITE_TEST_SRC(obj) \
35 (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_FLITE_TEST_SRC,GstFliteTestSrc))
36 #define GST_FLITE_TEST_SRC_CLASS(klass) \
37 (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_FLITE_TEST_SRC,GstFliteTestSrcClass))
38 #define GST_IS_FLITE_TEST_SRC(obj) \
39 (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_FLITE_TEST_SRC))
40 #define GST_IS_FLITE_TEST_SRC_CLASS(klass) \
41 (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_FLITE_TEST_SRC))
43 typedef struct _GstFliteTestSrc GstFliteTestSrc;
44 typedef struct _GstFliteTestSrcClass GstFliteTestSrcClass;
46 struct _GstFliteTestSrc
54 int samples_per_buffer;
61 struct _GstFliteTestSrcClass
63 GstBaseSrcClass parent_class;
66 GType gst_flite_test_src_get_type (void);
70 GST_DEBUG_CATEGORY_STATIC (flite_test_src_debug);
71 #define GST_CAT_DEFAULT flite_test_src_debug
73 #define DEFAULT_SAMPLES_PER_BUFFER 1024
78 PROP_SAMPLES_PER_BUFFER,
83 static GstStaticPadTemplate gst_flite_test_src_src_template =
84 GST_STATIC_PAD_TEMPLATE ("src",
87 GST_STATIC_CAPS ("audio/x-raw, "
88 "format = (string) " GST_AUDIO_NE (S16) ", "
89 "layout = (string) interleaved, "
90 "rate = (int) 48000, " "channels = (int) [1, 8]")
93 GST_ELEMENT_REGISTER_DECLARE (flitetestsrc);
94 #define gst_flite_test_src_parent_class parent_class
95 G_DEFINE_TYPE (GstFliteTestSrc, gst_flite_test_src, GST_TYPE_BASE_SRC);
96 GST_ELEMENT_REGISTER_DEFINE_WITH_CODE (flitetestsrc, "flitetestsrc",
97 GST_RANK_NONE, gst_flite_test_src_get_type (), flite_init ());
99 static void gst_flite_test_src_set_property (GObject * object,
100 guint prop_id, const GValue * value, GParamSpec * pspec);
101 static void gst_flite_test_src_get_property (GObject * object,
102 guint prop_id, GValue * value, GParamSpec * pspec);
104 static gboolean gst_flite_test_src_start (GstBaseSrc * basesrc);
105 static gboolean gst_flite_test_src_stop (GstBaseSrc * basesrc);
106 static GstFlowReturn gst_flite_test_src_create (GstBaseSrc * basesrc,
107 guint64 offset, guint length, GstBuffer ** buffer);
109 gst_flite_test_src_set_caps (GstBaseSrc * basesrc, GstCaps * caps);
110 static GstCaps *gst_flite_test_src_fixate (GstBaseSrc * bsrc, GstCaps * caps);
113 gst_flite_test_src_class_init (GstFliteTestSrcClass * klass)
115 GObjectClass *gobject_class;
116 GstElementClass *gstelement_class;
117 GstBaseSrcClass *gstbasesrc_class;
119 gobject_class = (GObjectClass *) klass;
120 gstelement_class = (GstElementClass *) klass;
121 gstbasesrc_class = (GstBaseSrcClass *) klass;
123 gobject_class->set_property = gst_flite_test_src_set_property;
124 gobject_class->get_property = gst_flite_test_src_get_property;
126 g_object_class_install_property (gobject_class, PROP_SAMPLES_PER_BUFFER,
127 g_param_spec_int ("samplesperbuffer", "Samples per buffer",
128 "Number of samples in each outgoing buffer",
129 1, G_MAXINT, DEFAULT_SAMPLES_PER_BUFFER,
130 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
132 gst_element_class_add_static_pad_template (gstelement_class,
133 &gst_flite_test_src_src_template);
135 gst_element_class_set_static_metadata (gstelement_class,
136 "Flite speech test source", "Source/Audio",
137 "Creates audio test signals identifying channels",
138 "David Schleef <ds@schleef.org>");
140 gstbasesrc_class->start = GST_DEBUG_FUNCPTR (gst_flite_test_src_start);
141 gstbasesrc_class->stop = GST_DEBUG_FUNCPTR (gst_flite_test_src_stop);
142 gstbasesrc_class->create = GST_DEBUG_FUNCPTR (gst_flite_test_src_create);
143 gstbasesrc_class->set_caps = GST_DEBUG_FUNCPTR (gst_flite_test_src_set_caps);
144 gstbasesrc_class->fixate = GST_DEBUG_FUNCPTR (gst_flite_test_src_fixate);
146 GST_DEBUG_CATEGORY_INIT (flite_test_src_debug, "flitetestsrc", 0,
147 "Flite Audio Test Source");
151 gst_flite_test_src_init (GstFliteTestSrc * src)
153 src->samples_per_buffer = DEFAULT_SAMPLES_PER_BUFFER;
155 /* we operate in time */
156 gst_base_src_set_format (GST_BASE_SRC (src), GST_FORMAT_TIME);
158 gst_base_src_set_blocksize (GST_BASE_SRC (src), -1);
162 n_bits_set (guint64 x)
168 for (i = 0; i < 64; i++) {
178 gst_flite_test_src_fixate (GstBaseSrc * bsrc, GstCaps * caps)
180 GstStructure *structure;
183 caps = gst_caps_truncate (caps);
184 caps = gst_caps_make_writable (caps);
186 structure = gst_caps_get_structure (caps, 0);
188 gst_structure_fixate_field_nearest_int (structure, "channels", 2);
189 gst_structure_get_int (structure, "channels", &channels);
192 gst_structure_remove_field (structure, "channel-mask");
194 guint64 channel_mask = 0;
197 if (!gst_structure_get (structure, "channel-mask", GST_TYPE_BITMASK,
198 &channel_mask, NULL)) {
202 GST_AUDIO_CHANNEL_POSITION_MASK (FRONT_LEFT) |
203 GST_AUDIO_CHANNEL_POSITION_MASK (FRONT_RIGHT) |
204 GST_AUDIO_CHANNEL_POSITION_MASK (REAR_LEFT) |
205 GST_AUDIO_CHANNEL_POSITION_MASK (REAR_RIGHT) |
206 GST_AUDIO_CHANNEL_POSITION_MASK (FRONT_CENTER) |
207 GST_AUDIO_CHANNEL_POSITION_MASK (LFE1) |
208 GST_AUDIO_CHANNEL_POSITION_MASK (SIDE_LEFT) |
209 GST_AUDIO_CHANNEL_POSITION_MASK (SIDE_RIGHT);
213 GST_AUDIO_CHANNEL_POSITION_MASK (FRONT_LEFT) |
214 GST_AUDIO_CHANNEL_POSITION_MASK (FRONT_RIGHT) |
215 GST_AUDIO_CHANNEL_POSITION_MASK (REAR_LEFT) |
216 GST_AUDIO_CHANNEL_POSITION_MASK (REAR_RIGHT) |
217 GST_AUDIO_CHANNEL_POSITION_MASK (FRONT_CENTER) |
218 GST_AUDIO_CHANNEL_POSITION_MASK (LFE1) |
219 GST_AUDIO_CHANNEL_POSITION_MASK (REAR_CENTER);
223 GST_AUDIO_CHANNEL_POSITION_MASK (FRONT_LEFT) |
224 GST_AUDIO_CHANNEL_POSITION_MASK (FRONT_RIGHT) |
225 GST_AUDIO_CHANNEL_POSITION_MASK (REAR_LEFT) |
226 GST_AUDIO_CHANNEL_POSITION_MASK (REAR_RIGHT) |
227 GST_AUDIO_CHANNEL_POSITION_MASK (FRONT_CENTER) |
228 GST_AUDIO_CHANNEL_POSITION_MASK (LFE1);
232 GST_AUDIO_CHANNEL_POSITION_MASK (FRONT_LEFT) |
233 GST_AUDIO_CHANNEL_POSITION_MASK (FRONT_RIGHT) |
234 GST_AUDIO_CHANNEL_POSITION_MASK (REAR_LEFT) |
235 GST_AUDIO_CHANNEL_POSITION_MASK (REAR_RIGHT) |
236 GST_AUDIO_CHANNEL_POSITION_MASK (FRONT_CENTER);
240 GST_AUDIO_CHANNEL_POSITION_MASK (FRONT_LEFT) |
241 GST_AUDIO_CHANNEL_POSITION_MASK (FRONT_RIGHT) |
242 GST_AUDIO_CHANNEL_POSITION_MASK (REAR_LEFT) |
243 GST_AUDIO_CHANNEL_POSITION_MASK (REAR_RIGHT);
247 GST_AUDIO_CHANNEL_POSITION_MASK (FRONT_LEFT) |
248 GST_AUDIO_CHANNEL_POSITION_MASK (FRONT_RIGHT) |
249 GST_AUDIO_CHANNEL_POSITION_MASK (LFE1);
253 GST_AUDIO_CHANNEL_POSITION_MASK (FRONT_LEFT) |
254 GST_AUDIO_CHANNEL_POSITION_MASK (FRONT_RIGHT);
262 while (n_bits_set (channel_mask) > channels) {
263 channel_mask &= ~(G_GUINT64_CONSTANT (1) << x);
267 gst_structure_set (structure, "channel-mask", GST_TYPE_BITMASK,
271 return GST_BASE_SRC_CLASS (parent_class)->fixate (bsrc, caps);
275 gst_flite_test_src_set_caps (GstBaseSrc * basesrc, GstCaps * caps)
277 GstFliteTestSrc *src = GST_FLITE_TEST_SRC (basesrc);
279 gst_audio_info_init (&src->info);
280 if (!gst_audio_info_from_caps (&src->info, caps)) {
281 GST_ERROR_OBJECT (src, "Invalid caps");
290 gst_flite_test_src_query (GstBaseSrc * basesrc, GstQuery * query)
292 GstFliteTestSrc *src = GST_FLITE_TEST_SRC (basesrc);
293 gboolean res = FALSE;
295 switch (GST_QUERY_TYPE (query)) {
296 case GST_QUERY_CONVERT:
298 GstFormat src_fmt, dest_fmt;
299 gint64 src_val, dest_val;
301 gst_query_parse_convert (query, &src_fmt, &src_val, &dest_fmt, &dest_val);
302 if (src_fmt == dest_fmt) {
308 case GST_FORMAT_DEFAULT:
310 case GST_FORMAT_TIME:
311 /* samples to time */
313 gst_util_uint64_scale_int (src_val, GST_SECOND,
320 case GST_FORMAT_TIME:
322 case GST_FORMAT_DEFAULT:
323 /* time to samples */
325 gst_util_uint64_scale_int (src_val, src->samplerate,
336 gst_query_set_convert (query, src_fmt, src_val, dest_fmt, dest_val);
341 res = GST_BASE_SRC_CLASS (parent_class)->query (basesrc, query);
349 GST_DEBUG_OBJECT (src, "query failed");
358 gst_flite_test_src_get_times (GstBaseSrc * basesrc, GstBuffer * buffer,
359 GstClockTime * start, GstClockTime * end)
361 /* for live sources, sync on the timestamp of the buffer */
362 if (gst_base_src_is_live (basesrc)) {
363 GstClockTime timestamp = GST_BUFFER_TIMESTAMP (buffer);
365 if (GST_CLOCK_TIME_IS_VALID (timestamp)) {
366 /* get duration to calculate end time */
367 GstClockTime duration = GST_BUFFER_DURATION (buffer);
369 if (GST_CLOCK_TIME_IS_VALID (duration)) {
370 *end = timestamp + duration;
381 /* there is no header for libflite_cmu_us_kal */
382 cst_voice *register_cmu_us_kal ();
385 gst_flite_test_src_start (GstBaseSrc * basesrc)
387 GstFliteTestSrc *src = GST_FLITE_TEST_SRC (basesrc);
389 src->adapter = gst_adapter_new ();
391 src->voice = register_cmu_us_kal ();
397 gst_flite_test_src_stop (GstBaseSrc * basesrc)
399 GstFliteTestSrc *src = GST_FLITE_TEST_SRC (basesrc);
401 g_object_unref (src->adapter);
407 get_channel_name (GstFliteTestSrc * src, int channel)
409 static const char *numbers[10] = {
410 "zero", "one", "two", "three", "four", "five", "six", "seven", "eight",
413 static const char *names[64] = {
414 "front left", "front right", "front center", "lfe 1", "rear left",
415 "rear right", "front left of center", "front right of center",
416 "rear center", "lfe 2", "side left", "side right", "top front left",
417 "top front right", "top front center", "top center", "top rear left",
418 "top rear right", "top side left", "top side right", "top rear center",
419 "bottom front center", "bottom front left", "bottom front right",
420 "wide left", "wide right", "surround left", "surround right"
424 if (src->info.position[channel] == GST_AUDIO_CHANNEL_POSITION_INVALID) {
426 } else if (src->info.position[channel] == GST_AUDIO_CHANNEL_POSITION_NONE) {
428 } else if (src->info.position[channel] == GST_AUDIO_CHANNEL_POSITION_MONO) {
431 name = names[src->info.position[channel]];
434 return g_strdup_printf ("%s, %s", numbers[channel], name);
438 gst_flite_test_src_create (GstBaseSrc * basesrc, guint64 offset,
439 guint length, GstBuffer ** buffer)
441 GstFliteTestSrc *src;
444 src = GST_FLITE_TEST_SRC (basesrc);
446 n_bytes = src->info.channels * sizeof (gint16) * src->samples_per_buffer;
448 while (gst_adapter_available (src->adapter) < n_bytes) {
457 text = get_channel_name (src, src->channel);
459 wave = flite_text_to_wave (text, src->voice);
461 cst_wave_resample (wave, src->info.rate);
463 GST_DEBUG ("type %s, sample_rate %d, num_samples %d, num_channels %d",
464 wave->type, wave->sample_rate, wave->num_samples, wave->num_channels);
466 size = src->info.channels * sizeof (gint16) * wave->num_samples;
467 buf = gst_buffer_new_and_alloc (size);
469 gst_buffer_map (buf, &map, GST_MAP_WRITE);
470 data = (gint16 *) map.data;
471 memset (data, 0, size);
472 for (i = 0; i < wave->num_samples; i++) {
473 data[i * src->info.channels + src->channel] = wave->samples[i];
475 gst_buffer_unmap (buf, &map);
478 if (src->channel == src->info.channels) {
482 gst_adapter_push (src->adapter, buf);
485 *buffer = gst_adapter_take_buffer (src->adapter, n_bytes);
491 gst_flite_test_src_set_property (GObject * object, guint prop_id,
492 const GValue * value, GParamSpec * pspec)
494 GstFliteTestSrc *src = GST_FLITE_TEST_SRC (object);
497 case PROP_SAMPLES_PER_BUFFER:
498 src->samples_per_buffer = g_value_get_int (value);
501 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
507 gst_flite_test_src_get_property (GObject * object, guint prop_id,
508 GValue * value, GParamSpec * pspec)
510 GstFliteTestSrc *src = GST_FLITE_TEST_SRC (object);
513 case PROP_SAMPLES_PER_BUFFER:
514 g_value_set_int (value, src->samples_per_buffer);
517 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);