38c6ba8469784dfd9966a48ea11b043eab48b914
[platform/upstream/gstreamer.git] / gst / audioresample / resample.c
1 /* Resampling library
2  * Copyright (C) <2001> David A. Schleef <ds@schleef.org>
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 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 #ifdef HAVE_CONFIG_H
21 #include <config.h>
22 #endif
23
24
25 #include <string.h>
26 #include <math.h>
27 #include <stdio.h>
28 #include <stdlib.h>
29 #include <limits.h>
30 #include <liboil/liboil.h>
31
32 #include <audioresample/resample.h>
33 #include <audioresample/buffer.h>
34 #include <audioresample/debug.h>
35
36 void resample_scale_ref (ResampleState * r);
37 void resample_scale_functable (ResampleState * r);
38
39
40
41 void
42 resample_init (void)
43 {
44   static int inited = 0;
45
46   if (!inited) {
47     oil_init ();
48     inited = 1;
49   }
50 }
51
52 ResampleState *
53 resample_new (void)
54 {
55   ResampleState *r;
56
57   r = malloc (sizeof (ResampleState));
58   memset (r, 0, sizeof (ResampleState));
59
60   r->filter_length = 16;
61
62   r->i_start = 0;
63   if (r->filter_length & 1) {
64     r->o_start = 0;
65   } else {
66     r->o_start = r->o_inc * 0.5;
67   }
68
69   r->queue = audioresample_buffer_queue_new ();
70   r->out_tmp = malloc (10000 * sizeof (double));
71
72   r->need_reinit = 1;
73
74   return r;
75 }
76
77 void
78 resample_free (ResampleState * r)
79 {
80   if (r->buffer) {
81     free (r->buffer);
82   }
83   if (r->ft) {
84     functable_free (r->ft);
85   }
86   if (r->queue) {
87     audioresample_buffer_queue_free (r->queue);
88   }
89   if (r->out_tmp) {
90     free (r->out_tmp);
91   }
92
93   free (r);
94 }
95
96 static void
97 resample_buffer_free (AudioresampleBuffer * buffer, void *priv)
98 {
99   if (buffer->priv2) {
100     ((void (*)(void *)) buffer->priv2) (buffer->priv);
101   }
102 }
103
104 void
105 resample_add_input_data (ResampleState * r, void *data, int size,
106     void (*free_func) (void *), void *closure)
107 {
108   AudioresampleBuffer *buffer;
109
110   RESAMPLE_DEBUG ("data %p size %d", data, size);
111
112   buffer = audioresample_buffer_new_with_data (data, size);
113   buffer->free = resample_buffer_free;
114   buffer->priv2 = free_func;
115   buffer->priv = closure;
116
117   audioresample_buffer_queue_push (r->queue, buffer);
118 }
119
120 void
121 resample_input_eos (ResampleState * r)
122 {
123   AudioresampleBuffer *buffer;
124   int sample_size;
125
126   sample_size = r->n_channels * resample_format_size (r->format);
127
128   buffer = audioresample_buffer_new_and_alloc (sample_size *
129       (r->filter_length / 2));
130   memset (buffer->data, 0, buffer->length);
131
132   audioresample_buffer_queue_push (r->queue, buffer);
133
134   r->eos = 1;
135 }
136
137 int
138 resample_get_output_size (ResampleState * r)
139 {
140   return floor (audioresample_buffer_queue_get_depth (r->queue) * r->o_rate /
141       r->i_rate);
142 }
143
144 int
145 resample_get_output_data (ResampleState * r, void *data, int size)
146 {
147   r->o_buf = data;
148   r->o_size = size;
149
150   switch (r->method) {
151     case 0:
152       resample_scale_ref (r);
153       break;
154     case 1:
155       resample_scale_functable (r);
156       break;
157     default:
158       break;
159   }
160
161   return size - r->o_size;
162 }
163
164 void
165 resample_set_filter_length (ResampleState * r, int length)
166 {
167   r->filter_length = length;
168   r->need_reinit = 1;
169 }
170
171 void
172 resample_set_input_rate (ResampleState * r, double rate)
173 {
174   r->i_rate = rate;
175   r->need_reinit = 1;
176 }
177
178 void
179 resample_set_output_rate (ResampleState * r, double rate)
180 {
181   r->o_rate = rate;
182   r->need_reinit = 1;
183 }
184
185 void
186 resample_set_n_channels (ResampleState * r, int n_channels)
187 {
188   r->n_channels = n_channels;
189   r->need_reinit = 1;
190 }
191
192 void
193 resample_set_format (ResampleState * r, ResampleFormat format)
194 {
195   r->format = format;
196   r->need_reinit = 1;
197 }
198
199 void
200 resample_set_method (ResampleState * r, int method)
201 {
202   r->method = method;
203   r->need_reinit = 1;
204 }
205
206 int
207 resample_format_size (ResampleFormat format)
208 {
209   switch (format) {
210     case RESAMPLE_FORMAT_S16:
211       return 2;
212     case RESAMPLE_FORMAT_S32:
213     case RESAMPLE_FORMAT_F32:
214       return 4;
215     case RESAMPLE_FORMAT_F64:
216       return 8;
217   }
218   return 0;
219 }