flite: handle samplesperbuffer

This commit is contained in:
David Schleef 2010-01-16 15:32:02 -08:00
parent 43147671c1
commit 82c07135d4

View file

@ -24,6 +24,7 @@
#include <gst/gst.h> #include <gst/gst.h>
#include <gst/base/gstbasesrc.h> #include <gst/base/gstbasesrc.h>
#include <gst/base/gstadapter.h>
#include <gst/audio/multichannel.h> #include <gst/audio/multichannel.h>
#include <flite/flite.h> #include <flite/flite.h>
@ -46,10 +47,14 @@ struct _GstFliteTestSrc
{ {
GstBaseSrc parent; GstBaseSrc parent;
GstAdapter *adapter;
int samplerate; int samplerate;
int n_channels; int n_channels;
GstAudioChannelPosition *layout; GstAudioChannelPosition *layout;
int samples_per_buffer;
int channel; int channel;
cst_voice *voice; cst_voice *voice;
@ -73,9 +78,12 @@ GST_ELEMENT_DETAILS ("Flite speech test source",
"Creates audio test signals identifying channels", "Creates audio test signals identifying channels",
"David Schleef <ds@schleef.org>"); "David Schleef <ds@schleef.org>");
#define DEFAULT_SAMPLES_PER_BUFFER 1024
enum enum
{ {
PROP_0, PROP_0,
PROP_SAMPLES_PER_BUFFER,
PROP_LAST PROP_LAST
}; };
@ -137,6 +145,13 @@ gst_flite_test_src_class_init (GstFliteTestSrcClass * klass)
gstbasesrc_class->stop = GST_DEBUG_FUNCPTR (gst_flite_test_src_stop); gstbasesrc_class->stop = GST_DEBUG_FUNCPTR (gst_flite_test_src_stop);
gstbasesrc_class->create = GST_DEBUG_FUNCPTR (gst_flite_test_src_create); gstbasesrc_class->create = GST_DEBUG_FUNCPTR (gst_flite_test_src_create);
gstbasesrc_class->set_caps = GST_DEBUG_FUNCPTR (gst_flite_test_src_set_caps); gstbasesrc_class->set_caps = GST_DEBUG_FUNCPTR (gst_flite_test_src_set_caps);
g_object_class_install_property (gobject_class, PROP_SAMPLES_PER_BUFFER,
g_param_spec_int ("samplesperbuffer", "Samples per buffer",
"Number of samples in each outgoing buffer",
1, G_MAXINT, DEFAULT_SAMPLES_PER_BUFFER,
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
} }
static void static void
@ -147,6 +162,7 @@ gst_flite_test_src_init (GstFliteTestSrc * src, GstFliteTestSrcClass * g_class)
#endif #endif
src->samplerate = 48000; src->samplerate = 48000;
src->samples_per_buffer = DEFAULT_SAMPLES_PER_BUFFER;
/* we operate in time */ /* we operate in time */
gst_base_src_set_format (GST_BASE_SRC (src), GST_FORMAT_TIME); gst_base_src_set_format (GST_BASE_SRC (src), GST_FORMAT_TIME);
@ -294,6 +310,8 @@ gst_flite_test_src_start (GstBaseSrc * basesrc)
{ {
GstFliteTestSrc *src = GST_FLITE_TEST_SRC (basesrc); GstFliteTestSrc *src = GST_FLITE_TEST_SRC (basesrc);
src->adapter = gst_adapter_new ();
src->voice = register_cmu_us_kal (); src->voice = register_cmu_us_kal ();
src->n_channels = 2; src->n_channels = 2;
@ -303,6 +321,10 @@ gst_flite_test_src_start (GstBaseSrc * basesrc)
static gboolean static gboolean
gst_flite_test_src_stop (GstBaseSrc * basesrc) gst_flite_test_src_stop (GstBaseSrc * basesrc)
{ {
GstFliteTestSrc *src = GST_FLITE_TEST_SRC (basesrc);
g_object_unref (src->adapter);
return TRUE; return TRUE;
} }
@ -336,37 +358,46 @@ gst_flite_test_src_create (GstBaseSrc * basesrc, guint64 offset,
guint length, GstBuffer ** buffer) guint length, GstBuffer ** buffer)
{ {
GstFliteTestSrc *src; GstFliteTestSrc *src;
GstBuffer *buf; int n_bytes;
cst_wave *wave;
char *text;
int i;
gint16 *data;
src = GST_FLITE_TEST_SRC (basesrc); src = GST_FLITE_TEST_SRC (basesrc);
text = get_channel_name (src, src->channel); n_bytes = src->n_channels * sizeof (gint16) * src->samples_per_buffer;
wave = flite_text_to_wave (text, src->voice); while (gst_adapter_available (src->adapter) < n_bytes) {
g_free (text); GstBuffer *buf;
cst_wave_resample (wave, 48000); char *text;
int i;
gint16 *data;
cst_wave *wave;
GST_DEBUG ("type %s, sample_rate %d, num_samples %d, num_channels %d", text = get_channel_name (src, src->channel);
wave->type, wave->sample_rate, wave->num_samples, wave->num_channels);
buf = gst_buffer_new_and_alloc (src->n_channels * sizeof (gint16) * wave = flite_text_to_wave (text, src->voice);
wave->num_samples); g_free (text);
cst_wave_resample (wave, 48000);
data = (void *) GST_BUFFER_DATA (buf); GST_DEBUG ("type %s, sample_rate %d, num_samples %d, num_channels %d",
memset (data, 0, src->n_channels * sizeof (gint16) * wave->num_samples); wave->type, wave->sample_rate, wave->num_samples, wave->num_channels);
for (i = 0; i < wave->num_samples; i++) {
data[i * src->n_channels + src->channel] = wave->samples[i]; buf = gst_buffer_new_and_alloc (src->n_channels * sizeof (gint16) *
wave->num_samples);
data = (void *) GST_BUFFER_DATA (buf);
memset (data, 0, src->n_channels * sizeof (gint16) * wave->num_samples);
for (i = 0; i < wave->num_samples; i++) {
data[i * src->n_channels + src->channel] = wave->samples[i];
}
src->channel++;
if (src->channel == src->n_channels) {
src->channel = 0;
}
gst_adapter_push (src->adapter, buf);
} }
src->channel++; *buffer = gst_adapter_take_buffer (src->adapter, n_bytes);
if (src->channel == src->n_channels)
src->channel = 0;
*buffer = buf;
return GST_FLOW_OK; return GST_FLOW_OK;
} }
@ -375,11 +406,12 @@ static void
gst_flite_test_src_set_property (GObject * object, guint prop_id, gst_flite_test_src_set_property (GObject * object, guint prop_id,
const GValue * value, GParamSpec * pspec) const GValue * value, GParamSpec * pspec)
{ {
#if 0
GstFliteTestSrc *src = GST_FLITE_TEST_SRC (object); GstFliteTestSrc *src = GST_FLITE_TEST_SRC (object);
#endif
switch (prop_id) { switch (prop_id) {
case PROP_SAMPLES_PER_BUFFER:
src->samples_per_buffer = g_value_get_int (value);
break;
default: default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break; break;
@ -390,11 +422,12 @@ static void
gst_flite_test_src_get_property (GObject * object, guint prop_id, gst_flite_test_src_get_property (GObject * object, guint prop_id,
GValue * value, GParamSpec * pspec) GValue * value, GParamSpec * pspec)
{ {
#if 0
GstFliteTestSrc *src = GST_FLITE_TEST_SRC (object); GstFliteTestSrc *src = GST_FLITE_TEST_SRC (object);
#endif
switch (prop_id) { switch (prop_id) {
case PROP_SAMPLES_PER_BUFFER:
g_value_set_int (value, src->samples_per_buffer);
break;
default: default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break; break;