|
1 |
|
2 #ifndef HAVE_CONFIG_H |
|
3 #include "config.h" |
|
4 #endif |
|
5 |
|
6 #include <glib.h> |
|
7 #include <string.h> |
|
8 |
|
9 #include "buffer.h" |
|
10 #include "debug.h" |
|
11 |
|
12 static void audioresample_buffer_free_mem (AudioresampleBuffer * buffer, |
|
13 void *); |
|
14 static void audioresample_buffer_free_subbuffer (AudioresampleBuffer * buffer, |
|
15 void *priv); |
|
16 #ifdef __SYMBIAN32__ |
|
17 EXPORT_C |
|
18 #endif |
|
19 |
|
20 |
|
21 |
|
22 AudioresampleBuffer * |
|
23 audioresample_buffer_new (void) |
|
24 { |
|
25 AudioresampleBuffer *buffer; |
|
26 |
|
27 buffer = g_new0 (AudioresampleBuffer, 1); |
|
28 buffer->ref_count = 1; |
|
29 return buffer; |
|
30 } |
|
31 #ifdef __SYMBIAN32__ |
|
32 EXPORT_C |
|
33 #endif |
|
34 |
|
35 |
|
36 AudioresampleBuffer * |
|
37 audioresample_buffer_new_and_alloc (int size) |
|
38 { |
|
39 AudioresampleBuffer *buffer = audioresample_buffer_new (); |
|
40 |
|
41 buffer->data = g_malloc (size); |
|
42 buffer->length = size; |
|
43 buffer->free = audioresample_buffer_free_mem; |
|
44 |
|
45 return buffer; |
|
46 } |
|
47 #ifdef __SYMBIAN32__ |
|
48 EXPORT_C |
|
49 #endif |
|
50 |
|
51 |
|
52 AudioresampleBuffer * |
|
53 audioresample_buffer_new_with_data (void *data, int size) |
|
54 { |
|
55 AudioresampleBuffer *buffer = audioresample_buffer_new (); |
|
56 |
|
57 buffer->data = data; |
|
58 buffer->length = size; |
|
59 buffer->free = audioresample_buffer_free_mem; |
|
60 |
|
61 return buffer; |
|
62 } |
|
63 #ifdef __SYMBIAN32__ |
|
64 EXPORT_C |
|
65 #endif |
|
66 |
|
67 |
|
68 AudioresampleBuffer * |
|
69 audioresample_buffer_new_subbuffer (AudioresampleBuffer * buffer, int offset, |
|
70 int length) |
|
71 { |
|
72 AudioresampleBuffer *subbuffer = audioresample_buffer_new (); |
|
73 |
|
74 if (buffer->parent) { |
|
75 audioresample_buffer_ref (buffer->parent); |
|
76 subbuffer->parent = buffer->parent; |
|
77 } else { |
|
78 audioresample_buffer_ref (buffer); |
|
79 subbuffer->parent = buffer; |
|
80 } |
|
81 subbuffer->data = buffer->data + offset; |
|
82 subbuffer->length = length; |
|
83 subbuffer->free = audioresample_buffer_free_subbuffer; |
|
84 |
|
85 return subbuffer; |
|
86 } |
|
87 #ifdef __SYMBIAN32__ |
|
88 EXPORT_C |
|
89 #endif |
|
90 |
|
91 |
|
92 void |
|
93 audioresample_buffer_ref (AudioresampleBuffer * buffer) |
|
94 { |
|
95 buffer->ref_count++; |
|
96 } |
|
97 #ifdef __SYMBIAN32__ |
|
98 EXPORT_C |
|
99 #endif |
|
100 |
|
101 |
|
102 void |
|
103 audioresample_buffer_unref (AudioresampleBuffer * buffer) |
|
104 { |
|
105 buffer->ref_count--; |
|
106 if (buffer->ref_count == 0) { |
|
107 if (buffer->free) |
|
108 buffer->free (buffer, buffer->priv); |
|
109 g_free (buffer); |
|
110 } |
|
111 } |
|
112 |
|
113 static void |
|
114 audioresample_buffer_free_mem (AudioresampleBuffer * buffer, void *priv) |
|
115 { |
|
116 g_free (buffer->data); |
|
117 } |
|
118 |
|
119 static void |
|
120 audioresample_buffer_free_subbuffer (AudioresampleBuffer * buffer, void *priv) |
|
121 { |
|
122 audioresample_buffer_unref (buffer->parent); |
|
123 } |
|
124 #ifdef __SYMBIAN32__ |
|
125 EXPORT_C |
|
126 #endif |
|
127 |
|
128 |
|
129 |
|
130 AudioresampleBufferQueue * |
|
131 audioresample_buffer_queue_new (void) |
|
132 { |
|
133 return g_new0 (AudioresampleBufferQueue, 1); |
|
134 } |
|
135 #ifdef __SYMBIAN32__ |
|
136 EXPORT_C |
|
137 #endif |
|
138 |
|
139 |
|
140 int |
|
141 audioresample_buffer_queue_get_depth (AudioresampleBufferQueue * queue) |
|
142 { |
|
143 return queue->depth; |
|
144 } |
|
145 #ifdef __SYMBIAN32__ |
|
146 EXPORT_C |
|
147 #endif |
|
148 |
|
149 |
|
150 int |
|
151 audioresample_buffer_queue_get_offset (AudioresampleBufferQueue * queue) |
|
152 { |
|
153 return queue->offset; |
|
154 } |
|
155 #ifdef __SYMBIAN32__ |
|
156 EXPORT_C |
|
157 #endif |
|
158 |
|
159 |
|
160 void |
|
161 audioresample_buffer_queue_free (AudioresampleBufferQueue * queue) |
|
162 { |
|
163 GList *g; |
|
164 |
|
165 for (g = g_list_first (queue->buffers); g; g = g_list_next (g)) { |
|
166 audioresample_buffer_unref ((AudioresampleBuffer *) g->data); |
|
167 } |
|
168 g_list_free (queue->buffers); |
|
169 g_free (queue); |
|
170 } |
|
171 #ifdef __SYMBIAN32__ |
|
172 EXPORT_C |
|
173 #endif |
|
174 |
|
175 |
|
176 void |
|
177 audioresample_buffer_queue_push (AudioresampleBufferQueue * queue, |
|
178 AudioresampleBuffer * buffer) |
|
179 { |
|
180 queue->buffers = g_list_append (queue->buffers, buffer); |
|
181 queue->depth += buffer->length; |
|
182 } |
|
183 #ifdef __SYMBIAN32__ |
|
184 EXPORT_C |
|
185 #endif |
|
186 |
|
187 |
|
188 AudioresampleBuffer * |
|
189 audioresample_buffer_queue_pull (AudioresampleBufferQueue * queue, int length) |
|
190 { |
|
191 GList *g; |
|
192 AudioresampleBuffer *newbuffer; |
|
193 AudioresampleBuffer *buffer; |
|
194 AudioresampleBuffer *subbuffer; |
|
195 |
|
196 g_return_val_if_fail (length > 0, NULL); |
|
197 |
|
198 if (queue->depth < length) { |
|
199 return NULL; |
|
200 } |
|
201 |
|
202 RESAMPLE_LOG ("pulling %d, %d available", length, queue->depth); |
|
203 |
|
204 g = g_list_first (queue->buffers); |
|
205 buffer = g->data; |
|
206 |
|
207 if (buffer->length > length) { |
|
208 newbuffer = audioresample_buffer_new_subbuffer (buffer, 0, length); |
|
209 |
|
210 subbuffer = audioresample_buffer_new_subbuffer (buffer, length, |
|
211 buffer->length - length); |
|
212 g->data = subbuffer; |
|
213 audioresample_buffer_unref (buffer); |
|
214 } else { |
|
215 int offset = 0; |
|
216 |
|
217 newbuffer = audioresample_buffer_new_and_alloc (length); |
|
218 |
|
219 while (offset < length) { |
|
220 g = g_list_first (queue->buffers); |
|
221 buffer = g->data; |
|
222 |
|
223 if (buffer->length > length - offset) { |
|
224 int n = length - offset; |
|
225 |
|
226 memcpy (newbuffer->data + offset, buffer->data, n); |
|
227 subbuffer = |
|
228 audioresample_buffer_new_subbuffer (buffer, n, buffer->length - n); |
|
229 g->data = subbuffer; |
|
230 audioresample_buffer_unref (buffer); |
|
231 offset += n; |
|
232 } else { |
|
233 memcpy (newbuffer->data + offset, buffer->data, buffer->length); |
|
234 |
|
235 queue->buffers = g_list_delete_link (queue->buffers, g); |
|
236 offset += buffer->length; |
|
237 audioresample_buffer_unref (buffer); |
|
238 } |
|
239 } |
|
240 } |
|
241 |
|
242 queue->depth -= length; |
|
243 queue->offset += length; |
|
244 |
|
245 return newbuffer; |
|
246 } |
|
247 #ifdef __SYMBIAN32__ |
|
248 EXPORT_C |
|
249 #endif |
|
250 |
|
251 |
|
252 AudioresampleBuffer * |
|
253 audioresample_buffer_queue_peek (AudioresampleBufferQueue * queue, int length) |
|
254 { |
|
255 GList *g; |
|
256 AudioresampleBuffer *newbuffer; |
|
257 AudioresampleBuffer *buffer; |
|
258 int offset = 0; |
|
259 |
|
260 g_return_val_if_fail (length > 0, NULL); |
|
261 |
|
262 if (queue->depth < length) { |
|
263 return NULL; |
|
264 } |
|
265 |
|
266 RESAMPLE_LOG ("peeking %d, %d available", length, queue->depth); |
|
267 |
|
268 g = g_list_first (queue->buffers); |
|
269 buffer = g->data; |
|
270 if (buffer->length > length) { |
|
271 newbuffer = audioresample_buffer_new_subbuffer (buffer, 0, length); |
|
272 } else { |
|
273 newbuffer = audioresample_buffer_new_and_alloc (length); |
|
274 while (offset < length) { |
|
275 buffer = g->data; |
|
276 |
|
277 if (buffer->length > length - offset) { |
|
278 int n = length - offset; |
|
279 |
|
280 memcpy (newbuffer->data + offset, buffer->data, n); |
|
281 offset += n; |
|
282 } else { |
|
283 memcpy (newbuffer->data + offset, buffer->data, buffer->length); |
|
284 offset += buffer->length; |
|
285 } |
|
286 g = g_list_next (g); |
|
287 } |
|
288 } |
|
289 |
|
290 return newbuffer; |
|
291 } |
|
292 #ifdef __SYMBIAN32__ |
|
293 EXPORT_C |
|
294 #endif |
|
295 |
|
296 |
|
297 void |
|
298 audioresample_buffer_queue_flush (AudioresampleBufferQueue * queue) |
|
299 { |
|
300 GList *g; |
|
301 |
|
302 for (g = g_list_first (queue->buffers); g; g = g_list_next (g)) { |
|
303 audioresample_buffer_unref ((AudioresampleBuffer *) g->data); |
|
304 } |
|
305 g_list_free (queue->buffers); |
|
306 queue->buffers = NULL; |
|
307 queue->depth = 0; |
|
308 queue->offset = 0; |
|
309 } |