(gst_pitch_set_property), (gst_pitch_get_property),
(gst_pitch_set_caps), (gst_pitch_start), (gst_pitch_message_new),
(gst_pitch_transform_ip):
* src/gstpitch.h:
* src/tuner.c: (main):
Simplified the code of the element and made it more oriented to
8 khz / mono sampling.
Implemented slidding window of 1 second with a half second
period.
Emmit fundamental frequency message each half second.
git-svn-id: file:///svnroot/tunertool/trunk@11
4bb5ff34-d565-4b58-9699-
12000fa1827a
+2008-07-30 Josep Torra <j.torra@telefonica.net>
+
+ * src/gstpitch.c: (gst_pitch_class_init), (gst_pitch_init),
+ (gst_pitch_set_property), (gst_pitch_get_property),
+ (gst_pitch_set_caps), (gst_pitch_start), (gst_pitch_message_new),
+ (gst_pitch_transform_ip):
+ * src/gstpitch.h:
+ * src/tuner.c: (main):
+ Simplified the code of the element and made it more oriented to
+ 8 khz / mono sampling.
+ Implemented slidding window of 1 second with a half second
+ period.
+ Emmit fundamental frequency message each half second.
+
2008-07-28 Jari Tenhunen <jari.tenhunen@iki.fi>
* debian/rules:
2008-07-28 Jari Tenhunen <jari.tenhunen@iki.fi>
* debian/rules:
GST_DEBUG_CATEGORY_STATIC (gst_pitch_debug);
#define GST_CAT_DEFAULT gst_pitch_debug
GST_DEBUG_CATEGORY_STATIC (gst_pitch_debug);
#define GST_CAT_DEFAULT gst_pitch_debug
+#define RATE 8000
+#define WANTED RATE * 2
+
/* Filter signals and args */
enum
{
/* Filter signals and args */
enum
{
GST_PAD_SINK,
GST_PAD_ALWAYS,
GST_STATIC_CAPS ("audio/x-raw-int, "
GST_PAD_SINK,
GST_PAD_ALWAYS,
GST_STATIC_CAPS ("audio/x-raw-int, "
- "rate = (int) [ 1, MAX ], "
- "channels = (int) [1, MAX], "
+ "rate = (int) 8000, "
+ "channels = (int) 1, "
"endianness = (int) BYTE_ORDER, "
"width = (int) 16, " "depth = (int) 16, " "signed = (boolean) true")
);
"endianness = (int) BYTE_ORDER, "
"width = (int) 16, " "depth = (int) 16, " "signed = (boolean) true")
);
"Post a fundamental frequency message for each passed interval",
TRUE, G_PARAM_READWRITE));
"Post a fundamental frequency message for each passed interval",
TRUE, G_PARAM_READWRITE));
- g_object_class_install_property (gobject_class, PROP_SIGNAL_INTERVAL,
- g_param_spec_uint64 ("interval", "Interval",
- "Interval of time between message posts (in nanoseconds)",
- 1, G_MAXUINT64, GST_SECOND / 10, G_PARAM_READWRITE));
-
g_object_class_install_property (gobject_class, PROP_SIGNAL_MINFREQ,
g_param_spec_int ("minfreq", "MinFreq",
"Initial scan frequency, default 30 Hz",
g_object_class_install_property (gobject_class, PROP_SIGNAL_MINFREQ,
g_param_spec_int ("minfreq", "MinFreq",
"Initial scan frequency, default 30 Hz",
"Final scan frequency, default 1500 Hz",
1, G_MAXINT, 1500, G_PARAM_READWRITE));
"Final scan frequency, default 1500 Hz",
1, G_MAXINT, 1500, G_PARAM_READWRITE));
- g_object_class_install_property (gobject_class, PROP_NFFT,
- g_param_spec_int ("nfft", "NFFT",
- "Number of samples taken for FFT",
- 1, G_MAXINT, 1024, G_PARAM_READWRITE));
GST_BASE_TRANSFORM_CLASS (klass)->transform_ip =
GST_DEBUG_FUNCPTR (gst_pitch_transform_ip);
GST_BASE_TRANSFORM_CLASS (klass)->transform_ip =
GST_DEBUG_FUNCPTR (gst_pitch_transform_ip);
filter->minfreq = 30;
filter->maxfreq = 1500;
filter->minfreq = 30;
filter->maxfreq = 1500;
- filter->interval = GST_SECOND / 10;
-
- filter->fft_cfg = kiss_fft_alloc (filter->nfft, 0, NULL, NULL);
- filter->signal =
- (kiss_fft_cpx *) g_malloc (filter->nfft * sizeof (kiss_fft_cpx));
- filter->spectrum =
- (kiss_fft_cpx *) g_malloc (filter->nfft * sizeof (kiss_fft_cpx));
case PROP_SIGNAL_FFREQ:
filter->message = g_value_get_boolean (value);
break;
case PROP_SIGNAL_FFREQ:
filter->message = g_value_get_boolean (value);
break;
- case PROP_SIGNAL_INTERVAL:
- filter->interval = gst_guint64_to_gdouble (g_value_get_uint64 (value));
- break;
case PROP_SIGNAL_MINFREQ:
filter->minfreq = g_value_get_int (value);
break;
case PROP_SIGNAL_MAXFREQ:
filter->maxfreq = g_value_get_int (value);
break;
case PROP_SIGNAL_MINFREQ:
filter->minfreq = g_value_get_int (value);
break;
case PROP_SIGNAL_MAXFREQ:
filter->maxfreq = g_value_get_int (value);
break;
- case PROP_NFFT:
- filter->nfft = g_value_get_int (value);
- g_free (filter->fft_cfg);
- g_free (filter->signal);
- g_free (filter->spectrum);
- filter->fft_cfg = kiss_fft_alloc (filter->nfft, 0, NULL, NULL);
- filter->signal =
- (kiss_fft_cpx *) g_malloc (filter->nfft * sizeof (kiss_fft_cpx));
- filter->spectrum =
- (kiss_fft_cpx *) g_malloc (filter->nfft * sizeof (kiss_fft_cpx));
- break;
-
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
case PROP_SIGNAL_FFREQ:
g_value_set_boolean (value, filter->message);
break;
case PROP_SIGNAL_FFREQ:
g_value_set_boolean (value, filter->message);
break;
- case PROP_SIGNAL_INTERVAL:
- g_value_set_uint64 (value, filter->interval);
- break;
case PROP_SIGNAL_MINFREQ:
g_value_set_int (value, filter->minfreq);
break;
case PROP_SIGNAL_MAXFREQ:
g_value_set_int (value, filter->maxfreq);
break;
case PROP_SIGNAL_MINFREQ:
g_value_set_int (value, filter->minfreq);
break;
case PROP_SIGNAL_MAXFREQ:
g_value_set_int (value, filter->maxfreq);
break;
- case PROP_NFFT:
- g_value_set_int (value, filter->nfft);
- break;
-
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
gst_pitch_set_caps (GstBaseTransform * trans, GstCaps * in, GstCaps * out)
{
GstPitch *filter = GST_PITCH (trans);
gst_pitch_set_caps (GstBaseTransform * trans, GstCaps * in, GstCaps * out)
{
GstPitch *filter = GST_PITCH (trans);
- GstStructure *structure;
- structure = gst_caps_get_structure (in, 0);
- gst_structure_get_int (structure, "rate", &filter->rate);
- gst_structure_get_int (structure, "width", &filter->width);
- gst_structure_get_int (structure, "channels", &filter->channels);
+ filter->fft_cfg = kiss_fft_alloc (RATE, 0, NULL, NULL);
+ filter->signal =
+ (kiss_fft_cpx *) g_malloc (RATE * sizeof (kiss_fft_cpx));
+ filter->spectrum =
+ (kiss_fft_cpx *) g_malloc (RATE * sizeof (kiss_fft_cpx));
GstPitch *filter = GST_PITCH (trans);
gst_adapter_clear (filter->adapter);
GstPitch *filter = GST_PITCH (trans);
gst_adapter_clear (filter->adapter);
- filter->num_frames = 0;
/* Extract fundamental frequency */
frequency = 0;
frequency_module = 0;
/* Extract fundamental frequency */
frequency = 0;
frequency_module = 0;
- min_i = filter->minfreq * filter->nfft / filter->rate;
- max_i = filter->maxfreq * filter->nfft / filter->rate;
+ min_i = filter->minfreq;
+ max_i = filter->maxfreq;
GST_DEBUG_OBJECT (filter, "min_freq = %d, max_freq = %d", filter->minfreq,
filter->maxfreq);
GST_DEBUG_OBJECT (filter, "min_i = %d, max_i = %d", min_i, max_i);
GST_DEBUG_OBJECT (filter, "min_freq = %d, max_freq = %d", filter->minfreq,
filter->maxfreq);
GST_DEBUG_OBJECT (filter, "min_i = %d, max_i = %d", min_i, max_i);
- for (i = min_i; (i <= max_i) && (i < filter->nfft); i++) {
+ for (i = min_i; (i <= max_i) && (i < RATE); i++) {
module = (filter->spectrum[i].r * filter->spectrum[i].r);
module += (filter->spectrum[i].i * filter->spectrum[i].i);
if (module > 0)
module = (filter->spectrum[i].r * filter->spectrum[i].r);
module += (filter->spectrum[i].i * filter->spectrum[i].i);
if (module > 0)
- GST_DEBUG_OBJECT (filter, "module[%d] = %d", i, module);
+ GST_LOG_OBJECT (filter, "module[%d] = %d", i, module);
if (module > frequency_module) {
frequency_module = module;
if (module > frequency_module) {
frequency_module = module;
- frequency = frequency * filter->rate / filter->nfft;
-
GST_DEBUG_OBJECT (filter, "preparing message, frequency = %d ", frequency);
s = gst_structure_new ("pitch", "frequency", G_TYPE_INT, frequency, NULL);
GST_DEBUG_OBJECT (filter, "preparing message, frequency = %d ", frequency);
s = gst_structure_new ("pitch", "frequency", G_TYPE_INT, frequency, NULL);
{
GstPitch *filter = GST_PITCH (trans);
gint16 *samples;
{
GstPitch *filter = GST_PITCH (trans);
gint16 *samples;
- gint wanted;
- gint i, j, k;
- gint32 acc;
-
- GST_DEBUG ("transform : %ld bytes", GST_BUFFER_SIZE (in));
+ GST_DEBUG_OBJECT (filter, "transform : %ld bytes", GST_BUFFER_SIZE (in));
gst_adapter_push (filter->adapter, gst_buffer_ref (in));
gst_adapter_push (filter->adapter, gst_buffer_ref (in));
/* required number of bytes */
/* required number of bytes */
- wanted = filter->channels * filter->nfft * 2;
+ avail = gst_adapter_available (filter->adapter);
+ GST_DEBUG_OBJECT (filter, "avail: %d wanted: %d", avail, WANTED);
- while (gst_adapter_available (filter->adapter) > wanted) {
- GST_DEBUG (" adapter loop");
- samples = (gint16 *) gst_adapter_peek (filter->adapter, wanted);
+ /* copy sample data in the complex vector */
+ samples = (gint16 *) gst_adapter_peek (filter->adapter, WANTED);
- for (i = 0, j = 0; i < filter->nfft; i++) {
- for (k = 0, acc = 0; k < filter->channels; k++)
- acc += samples[j++];
- filter->signal[i].r = (kiss_fft_scalar) (acc / filter->channels);
+ for (i = 0; i < RATE; i++) {
+ filter->signal[i].r = (kiss_fft_scalar) (samples[i]);
- gst_adapter_flush (filter->adapter, wanted);
+ /* flush half second of data to implement sliding window */
+ gst_adapter_flush (filter->adapter, WANTED >> 1);
+
+ GST_DEBUG ("perform fft");
kiss_fft (filter->fft_cfg, filter->signal, filter->spectrum);
kiss_fft (filter->fft_cfg, filter->signal, filter->spectrum);
- GST_DEBUG (" send message? %d", filter->num_frames);
- filter->num_frames += filter->nfft;
- /* do we need to message ? */
- if (filter->num_frames >=
- GST_CLOCK_TIME_TO_FRAMES (filter->interval, filter->rate)) {
- if (filter->message) {
- GstMessage *m = gst_pitch_message_new (filter);
-
- GST_DEBUG (" sending message");
- gst_element_post_message (GST_ELEMENT (filter), m);
- }
- filter->num_frames = 0;
+ if (filter->message) {
+ GstMessage *m = gst_pitch_message_new (filter);
+ gst_element_post_message (GST_ELEMENT (filter), m);
/* properties */
gboolean message; /* whether or not to post messages */
/* properties */
gboolean message; /* whether or not to post messages */
- gdouble interval; /* how many seconds between emits */
gint minfreq; /* initial frequency on scan for fundamental frequency */
gint maxfreq; /* final frequency on scan for fundamental frequency */
gint minfreq; /* initial frequency on scan for fundamental frequency */
gint maxfreq; /* final frequency on scan for fundamental frequency */
- gint nfft; /* number of samples taken for FFT */
-
- /* <private> */
- gint rate; /* caps variables */
- gint width;
- gint channels;
-
- gint num_frames; /* frame count (1 sample per channel) */
- /* since last emit */
kiss_fft_cfg fft_cfg;
kiss_fft_cpx *signal;
kiss_fft_cfg fft_cfg;
kiss_fft_cpx *signal;
src1 = gst_element_factory_make (DEFAULT_AUDIOSRC, "src1");
pitch = gst_element_factory_make ("pitch", "pitch");
src1 = gst_element_factory_make (DEFAULT_AUDIOSRC, "src1");
pitch = gst_element_factory_make ("pitch", "pitch");
- g_object_set (G_OBJECT (pitch), "nfft", 8000, "message", TRUE, "minfreq", 10,
- "maxfreq", 4000, "interval", GST_SECOND, NULL);
+ g_object_set (G_OBJECT (pitch), "message", TRUE, "minfreq", 10,
+ "maxfreq", 4000, NULL);
sink1 = gst_element_factory_make ("fakesink", "sink1");
g_object_set (G_OBJECT (sink1), "silent", 1, NULL);
sink1 = gst_element_factory_make ("fakesink", "sink1");
g_object_set (G_OBJECT (sink1), "silent", 1, NULL);