compatibility fix for new GST_DEBUG stuff.
[platform/upstream/gstreamer.git] / gst / audioscale / gstaudioscale.c
1 /* GStreamer
2  * Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu>
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Library General Public
6  * License as published by the Free Software Foundation; either
7  * version 2 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Library General Public License for more details.
13  *
14  * You should have received a copy of the GNU Library General Public
15  * License along with this library; if not, write to the
16  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17  * Boston, MA 02111-1307, USA.
18  */
19
20
21 #ifdef HAVE_CONFIG_H
22 #include "config.h"
23 #endif
24 #include <string.h>
25 #include <math.h>
26
27 /*#define DEBUG_ENABLED */
28 #include <gstaudioscale.h>
29 #include <gst/audio/audio.h>
30 #include <gst/resample/resample.h>
31
32 /* elementfactory information */
33 static GstElementDetails audioscale_details = {
34   "Audio scaler",
35   "Filter/Audio",
36   "LGPL",
37   "Audio resampler",
38   VERSION,
39   "Wim Taymans <wim.taymans@chello.be>",
40   "(C) 2000",
41 };
42
43 /* Audioscale signals and args */
44 enum {
45   /* FILL ME */
46   LAST_SIGNAL
47 };
48
49 enum {
50   ARG_0,
51   ARG_FREQUENCY,
52   ARG_FILTERLEN,
53   ARG_METHOD,
54   /* FILL ME */
55 };
56
57 static GstPadTemplate *
58 sink_template (void)
59 {
60   static GstPadTemplate *template = NULL;
61
62   if (!template) {
63     template = gst_pad_template_new ("sink",
64                                     GST_PAD_SINK,
65                                     GST_PAD_ALWAYS,
66                                     gst_caps_new
67                                     ("audioscale_sink",
68                                      "audio/raw", GST_AUDIO_INT_PAD_TEMPLATE_PROPS), NULL);
69   }
70   return template;
71 }
72
73 static GstPadTemplate *
74 src_template (void)
75 {
76   static GstPadTemplate *template = NULL;
77
78   if (!template) {
79     template = gst_pad_template_new ("src",
80                                     GST_PAD_SRC,
81                                     GST_PAD_ALWAYS,
82                                     gst_caps_new
83                                     ("audioscale_src",
84                                      "audio/raw", GST_AUDIO_INT_PAD_TEMPLATE_PROPS), NULL);
85   }
86   return template;
87 }
88
89 #define GST_TYPE_AUDIOSCALE_METHOD (gst_audioscale_method_get_type())
90 static GType
91 gst_audioscale_method_get_type (void)
92 {
93   static GType audioscale_method_type = 0;
94   static GEnumValue audioscale_methods[] = {
95     { RESAMPLE_NEAREST,  "0", "Nearest" },
96     { RESAMPLE_BILINEAR, "1", "Bilinear" },
97     { RESAMPLE_SINC,     "2", "Sinc" },
98     { 0, NULL, NULL },
99   };
100   if(!audioscale_method_type){
101     audioscale_method_type = g_enum_register_static("GstAudioscaleMethod",
102                                                     audioscale_methods);
103   }
104   return audioscale_method_type;
105 }
106
107 static void     gst_audioscale_class_init       (AudioscaleClass *klass);
108 static void     gst_audioscale_init             (Audioscale *audioscale);
109
110 static void     gst_audioscale_chain            (GstPad *pad, GstBuffer *buf);
111
112 static void gst_audioscale_set_property (GObject * object, guint prop_id,
113                                          const GValue * value, GParamSpec * pspec);
114 static void gst_audioscale_get_property (GObject * object, guint prop_id,
115                                          GValue * value, GParamSpec * pspec);
116
117 static GstElementClass *parent_class = NULL;
118
119 /*static guint gst_audioscale_signals[LAST_SIGNAL] = { 0 }; */
120
121 GType
122 audioscale_get_type (void)
123 {
124   static GType audioscale_type = 0;
125
126   if (!audioscale_type) {
127     static const GTypeInfo audioscale_info = {
128       sizeof(AudioscaleClass),      NULL,
129       NULL,
130       (GClassInitFunc)gst_audioscale_class_init,
131       NULL,
132       NULL,
133       sizeof(Audioscale),
134       0,
135       (GInstanceInitFunc)gst_audioscale_init,
136     };
137     audioscale_type = g_type_register_static(GST_TYPE_ELEMENT, "Audioscale", &audioscale_info, 0);
138   }
139   return audioscale_type;
140 }
141
142 static void
143 gst_audioscale_class_init (AudioscaleClass *klass)
144 {
145   GObjectClass *gobject_class;
146   GstElementClass *gstelement_class;
147
148   gobject_class = (GObjectClass*)klass;
149   gstelement_class = (GstElementClass*)klass;
150
151   g_object_class_install_property(G_OBJECT_CLASS(klass), ARG_FREQUENCY,
152         g_param_spec_int ("frequency","frequency","frequency",
153                           0,G_MAXINT,44100,G_PARAM_READWRITE|G_PARAM_CONSTRUCT));
154   g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_FILTERLEN,
155         g_param_spec_int ("filter_length", "filter_length", "filter_length",
156                           0, G_MAXINT, 16, G_PARAM_READWRITE|G_PARAM_CONSTRUCT));
157   g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_METHOD,
158         g_param_spec_enum ("method", "method", "method", GST_TYPE_AUDIOSCALE_METHOD,
159                            RESAMPLE_SINC, G_PARAM_READWRITE|G_PARAM_CONSTRUCT));
160
161   parent_class = g_type_class_ref(GST_TYPE_ELEMENT);
162
163   gobject_class->set_property = gst_audioscale_set_property;
164   gobject_class->get_property = gst_audioscale_get_property;
165
166 }
167
168 static GstPadLinkReturn
169 gst_audioscale_sinkconnect (GstPad * pad, GstCaps * caps)
170 {
171   Audioscale *audioscale;
172   resample_t *r;
173   GstCaps *newcaps;
174   gint rate;
175
176   audioscale = GST_AUDIOSCALE (gst_pad_get_parent (pad));
177   r = audioscale->resample;
178
179   gst_caps_get_int (caps, "rate",     &rate);
180   gst_caps_get_int (caps, "channels", &r->channels);
181
182   r->i_rate = rate;
183   
184   resample_reinit(r);
185   
186   newcaps = gst_caps_copy (caps);
187   gst_caps_set (newcaps, "rate", GST_PROPS_INT_TYPE, audioscale->targetfrequency, NULL);
188
189   if (GST_CAPS_IS_FIXED (caps))
190     return gst_pad_try_set_caps (audioscale->srcpad, newcaps);
191   else
192     return GST_PAD_LINK_DELAYED;
193 }
194
195 static void *
196 gst_audioscale_get_buffer (void *priv, unsigned int size)
197 {
198   Audioscale * audioscale = priv;
199
200   audioscale->outbuf = gst_buffer_new();
201   GST_BUFFER_SIZE(audioscale->outbuf) = size;
202   GST_BUFFER_DATA(audioscale->outbuf) = g_malloc(size);
203   GST_BUFFER_TIMESTAMP(audioscale->outbuf) = audioscale->offset * GST_SECOND / audioscale->targetfrequency;
204   audioscale->offset += size / sizeof(gint16) / audioscale->resample->channels;
205
206   return GST_BUFFER_DATA(audioscale->outbuf);
207 }
208
209 static void
210 gst_audioscale_init (Audioscale *audioscale)
211 {
212   resample_t *r;
213
214   audioscale->sinkpad = gst_pad_new_from_template (GST_PAD_TEMPLATE_GET (sink_template), "sink");
215   gst_element_add_pad(GST_ELEMENT(audioscale),audioscale->sinkpad);
216   gst_pad_set_chain_function(audioscale->sinkpad,gst_audioscale_chain);
217   gst_pad_set_link_function (audioscale->sinkpad, gst_audioscale_sinkconnect);
218
219   audioscale->srcpad = gst_pad_new_from_template (GST_PAD_TEMPLATE_GET (src_template), "src");
220
221   gst_element_add_pad(GST_ELEMENT(audioscale),audioscale->srcpad);
222
223   r = g_new0(resample_t,1);
224   audioscale->resample = r;
225
226   r->priv = audioscale;
227   r->get_buffer = gst_audioscale_get_buffer;
228   r->method = RESAMPLE_SINC;
229   r->channels = 0;
230   r->filter_length = 16;
231   r->i_rate = -1;
232   r->o_rate = -1;
233   r->format = RESAMPLE_S16;
234   /*r->verbose = 1; */
235
236   resample_init(r);
237
238   /* we will be reinitialized when the G_PARAM_CONSTRUCTs hit */
239 }
240
241 static void
242 gst_audioscale_chain (GstPad *pad, GstBuffer *buf)
243 {
244   Audioscale *audioscale;
245   guchar *data;
246   gulong size;
247
248   g_return_if_fail(pad != NULL);
249   g_return_if_fail(GST_IS_PAD(pad));
250   g_return_if_fail(buf != NULL);
251
252   audioscale = GST_AUDIOSCALE (gst_pad_get_parent (pad));
253   data = GST_BUFFER_DATA(buf);
254   size = GST_BUFFER_SIZE(buf);
255
256   GST_DEBUG (
257              "gst_audioscale_chain: got buffer of %ld bytes in '%s'\n",
258              size, gst_element_get_name (GST_ELEMENT (audioscale)));
259
260
261   resample_scale (audioscale->resample, data, size);
262
263   gst_pad_push (audioscale->srcpad, audioscale->outbuf);
264
265   gst_buffer_unref (buf);
266 }
267
268 static void
269 gst_audioscale_set_property (GObject * object, guint prop_id,
270                              const GValue * value, GParamSpec * pspec)
271 {
272   Audioscale *src;
273   resample_t *r;
274
275   /* it's not null if we got it, but it might not be ours */
276   g_return_if_fail(GST_IS_AUDIOSCALE(object));
277   src = GST_AUDIOSCALE(object);
278   r = src->resample;
279
280   switch (prop_id) {
281     case ARG_FREQUENCY:
282       src->targetfrequency = g_value_get_int (value);
283       r->o_rate = src->targetfrequency;
284       break;
285     case ARG_FILTERLEN:
286       r->filter_length = g_value_get_int (value);
287       GST_DEBUG_OBJECT (GST_ELEMENT(src), "new filter length %d\n", r->filter_length);
288       break;
289     case ARG_METHOD:
290       r->method = g_value_get_enum (value);
291       break;
292     default:
293       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
294       break;
295   }
296
297   resample_reinit (r);
298 }
299
300 static void
301 gst_audioscale_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec)
302 {
303   Audioscale *src;
304   resample_t *r;
305
306   src = GST_AUDIOSCALE (object);
307   r = src->resample;
308
309   switch (prop_id) {
310     case ARG_FREQUENCY:
311       g_value_set_int (value, src->targetfrequency);
312       break;
313     case ARG_FILTERLEN:
314       g_value_set_int (value, r->filter_length);
315       break;
316     case ARG_METHOD:
317       g_value_set_enum (value, r->method);
318       break;
319     default:
320       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
321       break;
322   }
323 }
324
325
326 static gboolean
327 plugin_init (GModule *module, GstPlugin *plugin)
328 {
329   GstElementFactory *factory;
330
331   /* create an elementfactory for the audioscale element */
332   factory = gst_element_factory_new ("audioscale", GST_TYPE_AUDIOSCALE, &audioscale_details);
333   g_return_val_if_fail(factory != NULL, FALSE);
334   gst_plugin_add_feature (plugin, GST_PLUGIN_FEATURE (factory));
335
336   /* load support library */
337   if (!gst_library_load ("gstresample"))
338     return FALSE;
339
340   return TRUE;
341 }
342
343 GstPluginDesc plugin_desc = {
344   GST_VERSION_MAJOR,
345   GST_VERSION_MINOR,
346   "audioscale",
347   plugin_init
348 };