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., 59 Temple Place - Suite 330,
18 * Boston, MA 02111-1307, USA.
26 #include <gst/base/gstbasesrc.h>
27 #include <gst/base/gstadapter.h>
28 #include <gst/audio/multichannel.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 GstAudioChannelPosition *layout;
56 int samples_per_buffer;
63 struct _GstFliteTestSrcClass
65 GstBaseSrcClass parent_class;
68 GType gst_flite_test_src_get_type (void);
72 GST_DEBUG_CATEGORY_STATIC (flite_test_src_debug);
73 #define GST_CAT_DEFAULT flite_test_src_debug
75 #define DEFAULT_SAMPLES_PER_BUFFER 1024
80 PROP_SAMPLES_PER_BUFFER,
85 static GstStaticPadTemplate gst_flite_test_src_src_template =
86 GST_STATIC_PAD_TEMPLATE ("src",
89 GST_STATIC_CAPS ("audio/x-raw-int, "
90 "endianness = (int) BYTE_ORDER, "
91 "signed = (boolean) true, "
93 "depth = (int) 16, " "rate = (int) 48000, " "channels = (int) [1,8]")
97 GST_BOILERPLATE (GstFliteTestSrc, gst_flite_test_src, GstBaseSrc,
100 static void gst_flite_test_src_set_property (GObject * object,
101 guint prop_id, const GValue * value, GParamSpec * pspec);
102 static void gst_flite_test_src_get_property (GObject * object,
103 guint prop_id, GValue * value, GParamSpec * pspec);
105 static gboolean gst_flite_test_src_start (GstBaseSrc * basesrc);
106 static gboolean gst_flite_test_src_stop (GstBaseSrc * basesrc);
107 static GstFlowReturn gst_flite_test_src_create (GstBaseSrc * basesrc,
108 guint64 offset, guint length, GstBuffer ** buffer);
110 gst_flite_test_src_set_caps (GstBaseSrc * basesrc, GstCaps * caps);
114 gst_flite_test_src_base_init (gpointer g_class)
116 GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
118 GST_DEBUG_CATEGORY_INIT (flite_test_src_debug, "flitetestsrc", 0,
119 "Flite Audio Test Source");
121 gst_element_class_add_static_pad_template (element_class,
122 &gst_flite_test_src_src_template);
123 gst_element_class_set_details_simple (element_class,
124 "Flite speech test source", "Source/Audio",
125 "Creates audio test signals identifying channels",
126 "David Schleef <ds@schleef.org>");
130 gst_flite_test_src_class_init (GstFliteTestSrcClass * klass)
132 GObjectClass *gobject_class;
133 GstBaseSrcClass *gstbasesrc_class;
135 gobject_class = (GObjectClass *) klass;
136 gstbasesrc_class = (GstBaseSrcClass *) klass;
138 gobject_class->set_property = gst_flite_test_src_set_property;
139 gobject_class->get_property = gst_flite_test_src_get_property;
141 gstbasesrc_class->start = GST_DEBUG_FUNCPTR (gst_flite_test_src_start);
142 gstbasesrc_class->stop = GST_DEBUG_FUNCPTR (gst_flite_test_src_stop);
143 gstbasesrc_class->create = GST_DEBUG_FUNCPTR (gst_flite_test_src_create);
144 gstbasesrc_class->set_caps = GST_DEBUG_FUNCPTR (gst_flite_test_src_set_caps);
146 g_object_class_install_property (gobject_class, PROP_SAMPLES_PER_BUFFER,
147 g_param_spec_int ("samplesperbuffer", "Samples per buffer",
148 "Number of samples in each outgoing buffer",
149 1, G_MAXINT, DEFAULT_SAMPLES_PER_BUFFER,
150 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
155 gst_flite_test_src_init (GstFliteTestSrc * src, GstFliteTestSrcClass * g_class)
158 GstPad *pad = GST_BASE_SRC_PAD (src);
161 src->samplerate = 48000;
162 src->samples_per_buffer = DEFAULT_SAMPLES_PER_BUFFER;
164 /* we operate in time */
165 gst_base_src_set_format (GST_BASE_SRC (src), GST_FORMAT_TIME);
167 gst_base_src_set_blocksize (GST_BASE_SRC (src), -1);
171 gst_flite_test_src_set_caps (GstBaseSrc * basesrc, GstCaps * caps)
173 GstFliteTestSrc *src = GST_FLITE_TEST_SRC (basesrc);
174 GstStructure *structure;
177 structure = gst_caps_get_structure (caps, 0);
179 ret = gst_structure_get_int (structure, "channels", &src->n_channels);
181 g_free (src->layout);
183 if (src->n_channels < 3) {
184 src->layout = g_malloc (sizeof (GstAudioChannelPosition) * 2);
185 if (src->n_channels == 1) {
186 src->layout[0] = GST_AUDIO_CHANNEL_POSITION_FRONT_MONO;
188 src->layout[0] = GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT;
189 src->layout[1] = GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT;
192 src->layout = gst_audio_get_channel_positions (structure);
193 if (src->layout == NULL) {
194 /* thanks, libgstaudio, for returning us NULL instead of
195 * doing this yourself. */
198 g_malloc (sizeof (GstAudioChannelPosition) * src->n_channels);
199 for (i = 0; i < src->n_channels; i++) {
200 src->layout[i] = GST_AUDIO_CHANNEL_POSITION_NONE;
210 gst_flite_test_src_query (GstBaseSrc * basesrc, GstQuery * query)
212 GstFliteTestSrc *src = GST_FLITE_TEST_SRC (basesrc);
213 gboolean res = FALSE;
215 switch (GST_QUERY_TYPE (query)) {
216 case GST_QUERY_CONVERT:
218 GstFormat src_fmt, dest_fmt;
219 gint64 src_val, dest_val;
221 gst_query_parse_convert (query, &src_fmt, &src_val, &dest_fmt, &dest_val);
222 if (src_fmt == dest_fmt) {
228 case GST_FORMAT_DEFAULT:
230 case GST_FORMAT_TIME:
231 /* samples to time */
233 gst_util_uint64_scale_int (src_val, GST_SECOND,
240 case GST_FORMAT_TIME:
242 case GST_FORMAT_DEFAULT:
243 /* time to samples */
245 gst_util_uint64_scale_int (src_val, src->samplerate,
256 gst_query_set_convert (query, src_fmt, src_val, dest_fmt, dest_val);
261 res = GST_BASE_SRC_CLASS (parent_class)->query (basesrc, query);
269 GST_DEBUG_OBJECT (src, "query failed");
278 gst_flite_test_src_get_times (GstBaseSrc * basesrc, GstBuffer * buffer,
279 GstClockTime * start, GstClockTime * end)
281 /* for live sources, sync on the timestamp of the buffer */
282 if (gst_base_src_is_live (basesrc)) {
283 GstClockTime timestamp = GST_BUFFER_TIMESTAMP (buffer);
285 if (GST_CLOCK_TIME_IS_VALID (timestamp)) {
286 /* get duration to calculate end time */
287 GstClockTime duration = GST_BUFFER_DURATION (buffer);
289 if (GST_CLOCK_TIME_IS_VALID (duration)) {
290 *end = timestamp + duration;
301 cst_voice *register_cmu_us_kal ();
306 gst_flite_test_src_start (GstBaseSrc * basesrc)
308 GstFliteTestSrc *src = GST_FLITE_TEST_SRC (basesrc);
310 src->adapter = gst_adapter_new ();
312 src->voice = register_cmu_us_kal ();
319 gst_flite_test_src_stop (GstBaseSrc * basesrc)
321 GstFliteTestSrc *src = GST_FLITE_TEST_SRC (basesrc);
323 g_object_unref (src->adapter);
329 get_channel_name (GstFliteTestSrc * src, int channel)
331 const char *numbers[10] = {
332 "zero", "one", "two", "three", "four", "five", "six", "seven", "eight",
335 const char *names[GST_AUDIO_CHANNEL_POSITION_NUM] = {
336 "mono", "front left", "front right", "rear center",
337 "rear left", "rear right", "low frequency effects",
338 "front center", "front left center", "front right center",
339 "side left", "side right",
344 if (src->layout[channel] == GST_AUDIO_CHANNEL_POSITION_INVALID) {
347 name = names[src->layout[channel]];
350 return g_strdup_printf ("%s, %s", numbers[channel], name);
354 gst_flite_test_src_create (GstBaseSrc * basesrc, guint64 offset,
355 guint length, GstBuffer ** buffer)
357 GstFliteTestSrc *src;
360 src = GST_FLITE_TEST_SRC (basesrc);
362 n_bytes = src->n_channels * sizeof (gint16) * src->samples_per_buffer;
364 while (gst_adapter_available (src->adapter) < n_bytes) {
371 text = get_channel_name (src, src->channel);
373 wave = flite_text_to_wave (text, src->voice);
375 cst_wave_resample (wave, 48000);
377 GST_DEBUG ("type %s, sample_rate %d, num_samples %d, num_channels %d",
378 wave->type, wave->sample_rate, wave->num_samples, wave->num_channels);
380 buf = gst_buffer_new_and_alloc (src->n_channels * sizeof (gint16) *
383 data = (void *) GST_BUFFER_DATA (buf);
384 memset (data, 0, src->n_channels * sizeof (gint16) * wave->num_samples);
385 for (i = 0; i < wave->num_samples; i++) {
386 data[i * src->n_channels + src->channel] = wave->samples[i];
390 if (src->channel == src->n_channels) {
394 gst_adapter_push (src->adapter, buf);
397 *buffer = gst_adapter_take_buffer (src->adapter, n_bytes);
403 gst_flite_test_src_set_property (GObject * object, guint prop_id,
404 const GValue * value, GParamSpec * pspec)
406 GstFliteTestSrc *src = GST_FLITE_TEST_SRC (object);
409 case PROP_SAMPLES_PER_BUFFER:
410 src->samples_per_buffer = g_value_get_int (value);
413 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
419 gst_flite_test_src_get_property (GObject * object, guint prop_id,
420 GValue * value, GParamSpec * pspec)
422 GstFliteTestSrc *src = GST_FLITE_TEST_SRC (object);
425 case PROP_SAMPLES_PER_BUFFER:
426 g_value_set_int (value, src->samples_per_buffer);
429 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);