Imported Upstream version 0.10.23
[profile/ivi/gst-plugins-bad.git] / ext / flite / gstflitetestsrc.c
1 /* GStreamer
2  * Copyright (C) 2010 David Schleef <ds@schleef.org>
3  * Copyright (C) 2005 Stefan Kost <ensonic@users.sf.net>
4  *
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.
9  *
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.
14  *
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.
19  */
20
21 #ifdef HAVE_CONFIG_H
22 #include "config.h"
23 #endif
24
25 #include <gst/gst.h>
26 #include <gst/base/gstbasesrc.h>
27 #include <gst/base/gstadapter.h>
28 #include <gst/audio/multichannel.h>
29
30 #include <flite/flite.h>
31
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))
42
43 typedef struct _GstFliteTestSrc GstFliteTestSrc;
44 typedef struct _GstFliteTestSrcClass GstFliteTestSrcClass;
45
46 struct _GstFliteTestSrc
47 {
48   GstBaseSrc parent;
49
50   GstAdapter *adapter;
51
52   int samplerate;
53   int n_channels;
54   GstAudioChannelPosition *layout;
55
56   int samples_per_buffer;
57
58   int channel;
59
60   cst_voice *voice;
61 };
62
63 struct _GstFliteTestSrcClass
64 {
65   GstBaseSrcClass parent_class;
66 };
67
68 GType gst_flite_test_src_get_type (void);
69
70
71
72 GST_DEBUG_CATEGORY_STATIC (flite_test_src_debug);
73 #define GST_CAT_DEFAULT flite_test_src_debug
74
75 #define DEFAULT_SAMPLES_PER_BUFFER 1024
76
77 enum
78 {
79   PROP_0,
80   PROP_SAMPLES_PER_BUFFER,
81   PROP_LAST
82 };
83
84
85 static GstStaticPadTemplate gst_flite_test_src_src_template =
86 GST_STATIC_PAD_TEMPLATE ("src",
87     GST_PAD_SRC,
88     GST_PAD_ALWAYS,
89     GST_STATIC_CAPS ("audio/x-raw-int, "
90         "endianness = (int) BYTE_ORDER, "
91         "signed = (boolean) true, "
92         "width = (int) 16, "
93         "depth = (int) 16, " "rate = (int) 48000, " "channels = (int) [1,8]")
94     );
95
96
97 GST_BOILERPLATE (GstFliteTestSrc, gst_flite_test_src, GstBaseSrc,
98     GST_TYPE_BASE_SRC);
99
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);
104
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);
109 static gboolean
110 gst_flite_test_src_set_caps (GstBaseSrc * basesrc, GstCaps * caps);
111
112
113 static void
114 gst_flite_test_src_base_init (gpointer g_class)
115 {
116   GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
117
118   GST_DEBUG_CATEGORY_INIT (flite_test_src_debug, "flitetestsrc", 0,
119       "Flite Audio Test Source");
120
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>");
127 }
128
129 static void
130 gst_flite_test_src_class_init (GstFliteTestSrcClass * klass)
131 {
132   GObjectClass *gobject_class;
133   GstBaseSrcClass *gstbasesrc_class;
134
135   gobject_class = (GObjectClass *) klass;
136   gstbasesrc_class = (GstBaseSrcClass *) klass;
137
138   gobject_class->set_property = gst_flite_test_src_set_property;
139   gobject_class->get_property = gst_flite_test_src_get_property;
140
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);
145
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));
151
152 }
153
154 static void
155 gst_flite_test_src_init (GstFliteTestSrc * src, GstFliteTestSrcClass * g_class)
156 {
157 #if 0
158   GstPad *pad = GST_BASE_SRC_PAD (src);
159 #endif
160
161   src->samplerate = 48000;
162   src->samples_per_buffer = DEFAULT_SAMPLES_PER_BUFFER;
163
164   /* we operate in time */
165   gst_base_src_set_format (GST_BASE_SRC (src), GST_FORMAT_TIME);
166
167   gst_base_src_set_blocksize (GST_BASE_SRC (src), -1);
168 }
169
170 static gboolean
171 gst_flite_test_src_set_caps (GstBaseSrc * basesrc, GstCaps * caps)
172 {
173   GstFliteTestSrc *src = GST_FLITE_TEST_SRC (basesrc);
174   GstStructure *structure;
175   gboolean ret;
176
177   structure = gst_caps_get_structure (caps, 0);
178
179   ret = gst_structure_get_int (structure, "channels", &src->n_channels);
180
181   g_free (src->layout);
182
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;
187     } else {
188       src->layout[0] = GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT;
189       src->layout[1] = GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT;
190     }
191   } else {
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. */
196       int i;
197       src->layout =
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;
201       }
202     }
203   }
204
205   return ret;
206 }
207
208 #if 0
209 static gboolean
210 gst_flite_test_src_query (GstBaseSrc * basesrc, GstQuery * query)
211 {
212   GstFliteTestSrc *src = GST_FLITE_TEST_SRC (basesrc);
213   gboolean res = FALSE;
214
215   switch (GST_QUERY_TYPE (query)) {
216     case GST_QUERY_CONVERT:
217     {
218       GstFormat src_fmt, dest_fmt;
219       gint64 src_val, dest_val;
220
221       gst_query_parse_convert (query, &src_fmt, &src_val, &dest_fmt, &dest_val);
222       if (src_fmt == dest_fmt) {
223         dest_val = src_val;
224         goto done;
225       }
226
227       switch (src_fmt) {
228         case GST_FORMAT_DEFAULT:
229           switch (dest_fmt) {
230             case GST_FORMAT_TIME:
231               /* samples to time */
232               dest_val =
233                   gst_util_uint64_scale_int (src_val, GST_SECOND,
234                   src->samplerate);
235               break;
236             default:
237               goto error;
238           }
239           break;
240         case GST_FORMAT_TIME:
241           switch (dest_fmt) {
242             case GST_FORMAT_DEFAULT:
243               /* time to samples */
244               dest_val =
245                   gst_util_uint64_scale_int (src_val, src->samplerate,
246                   GST_SECOND);
247               break;
248             default:
249               goto error;
250           }
251           break;
252         default:
253           goto error;
254       }
255     done:
256       gst_query_set_convert (query, src_fmt, src_val, dest_fmt, dest_val);
257       res = TRUE;
258       break;
259     }
260     default:
261       res = GST_BASE_SRC_CLASS (parent_class)->query (basesrc, query);
262       break;
263   }
264
265   return res;
266   /* ERROR */
267 error:
268   {
269     GST_DEBUG_OBJECT (src, "query failed");
270     return FALSE;
271   }
272 }
273 #endif
274
275
276 #if 0
277 static void
278 gst_flite_test_src_get_times (GstBaseSrc * basesrc, GstBuffer * buffer,
279     GstClockTime * start, GstClockTime * end)
280 {
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);
284
285     if (GST_CLOCK_TIME_IS_VALID (timestamp)) {
286       /* get duration to calculate end time */
287       GstClockTime duration = GST_BUFFER_DURATION (buffer);
288
289       if (GST_CLOCK_TIME_IS_VALID (duration)) {
290         *end = timestamp + duration;
291       }
292       *start = timestamp;
293     }
294   } else {
295     *start = -1;
296     *end = -1;
297   }
298 }
299 #endif
300
301 cst_voice *register_cmu_us_kal ();
302
303
304
305 static gboolean
306 gst_flite_test_src_start (GstBaseSrc * basesrc)
307 {
308   GstFliteTestSrc *src = GST_FLITE_TEST_SRC (basesrc);
309
310   src->adapter = gst_adapter_new ();
311
312   src->voice = register_cmu_us_kal ();
313   src->n_channels = 2;
314
315   return TRUE;
316 }
317
318 static gboolean
319 gst_flite_test_src_stop (GstBaseSrc * basesrc)
320 {
321   GstFliteTestSrc *src = GST_FLITE_TEST_SRC (basesrc);
322
323   g_object_unref (src->adapter);
324
325   return TRUE;
326 }
327
328 static char *
329 get_channel_name (GstFliteTestSrc * src, int channel)
330 {
331   const char *numbers[10] = {
332     "zero", "one", "two", "three", "four", "five", "six", "seven", "eight",
333     "nine"
334   };
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",
340     "none"
341   };
342   const char *name;
343
344   if (src->layout[channel] == GST_AUDIO_CHANNEL_POSITION_INVALID) {
345     name = "invalid";
346   } else {
347     name = names[src->layout[channel]];
348   }
349
350   return g_strdup_printf ("%s, %s", numbers[channel], name);
351 }
352
353 static GstFlowReturn
354 gst_flite_test_src_create (GstBaseSrc * basesrc, guint64 offset,
355     guint length, GstBuffer ** buffer)
356 {
357   GstFliteTestSrc *src;
358   int n_bytes;
359
360   src = GST_FLITE_TEST_SRC (basesrc);
361
362   n_bytes = src->n_channels * sizeof (gint16) * src->samples_per_buffer;
363
364   while (gst_adapter_available (src->adapter) < n_bytes) {
365     GstBuffer *buf;
366     char *text;
367     int i;
368     gint16 *data;
369     cst_wave *wave;
370
371     text = get_channel_name (src, src->channel);
372
373     wave = flite_text_to_wave (text, src->voice);
374     g_free (text);
375     cst_wave_resample (wave, 48000);
376
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);
379
380     buf = gst_buffer_new_and_alloc (src->n_channels * sizeof (gint16) *
381         wave->num_samples);
382
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];
387     }
388
389     src->channel++;
390     if (src->channel == src->n_channels) {
391       src->channel = 0;
392     }
393
394     gst_adapter_push (src->adapter, buf);
395   }
396
397   *buffer = gst_adapter_take_buffer (src->adapter, n_bytes);
398
399   return GST_FLOW_OK;
400 }
401
402 static void
403 gst_flite_test_src_set_property (GObject * object, guint prop_id,
404     const GValue * value, GParamSpec * pspec)
405 {
406   GstFliteTestSrc *src = GST_FLITE_TEST_SRC (object);
407
408   switch (prop_id) {
409     case PROP_SAMPLES_PER_BUFFER:
410       src->samples_per_buffer = g_value_get_int (value);
411       break;
412     default:
413       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
414       break;
415   }
416 }
417
418 static void
419 gst_flite_test_src_get_property (GObject * object, guint prop_id,
420     GValue * value, GParamSpec * pspec)
421 {
422   GstFliteTestSrc *src = GST_FLITE_TEST_SRC (object);
423
424   switch (prop_id) {
425     case PROP_SAMPLES_PER_BUFFER:
426       g_value_set_int (value, src->samples_per_buffer);
427       break;
428     default:
429       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
430       break;
431   }
432 }