]> code.delx.au - pulseaudio/blob - src/pulsecore/resampler.c
big resampler rework: support integer-only resampling, support speex resampler
[pulseaudio] / src / pulsecore / resampler.c
1 /* $Id$ */
2
3 /***
4 This file is part of PulseAudio.
5
6 Copyright 2004-2006 Lennart Poettering
7
8 PulseAudio is free software; you can redistribute it and/or modify
9 it under the terms of the GNU Lesser General Public License as published
10 by the Free Software Foundation; either version 2 of the License,
11 or (at your option) any later version.
12
13 PulseAudio is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 General Public License for more details.
17
18 You should have received a copy of the GNU Lesser General Public License
19 along with PulseAudio; if not, write to the Free Software
20 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
21 USA.
22 ***/
23
24 #ifdef HAVE_CONFIG_H
25 #include <config.h>
26 #endif
27
28 #include <string.h>
29
30 #include <samplerate.h>
31
32 #include <liboil/liboilfuncs.h>
33 #include <liboil/liboil.h>
34
35 #include <pulse/xmalloc.h>
36 #include <pulsecore/sconv.h>
37 #include <pulsecore/log.h>
38 #include <pulsecore/macro.h>
39
40 #include "speexwrap.h"
41
42 #include "resampler.h"
43
44 struct pa_resampler {
45 pa_resample_method_t resample_method;
46 pa_sample_spec i_ss, o_ss;
47 pa_channel_map i_cm, o_cm;
48 size_t i_fz, o_fz, w_sz;
49 pa_mempool *mempool;
50
51 pa_memchunk buf1, buf2, buf3, buf4;
52 unsigned buf1_samples, buf2_samples, buf3_samples, buf4_samples;
53
54 pa_sample_format_t work_format;
55
56 pa_convert_func_t to_work_format_func;
57 pa_convert_func_t from_work_format_func;
58
59 int map_table[PA_CHANNELS_MAX][PA_CHANNELS_MAX];
60 int map_required;
61
62 void (*impl_free)(pa_resampler *r);
63 void (*impl_update_rates)(pa_resampler *r);
64 void (*impl_resample)(pa_resampler *r, const pa_memchunk *in, unsigned in_samples, pa_memchunk *out, unsigned *out_samples);
65
66 struct { /* data specific to the trivial resampler */
67 unsigned o_counter;
68 unsigned i_counter;
69 } trivial;
70
71 struct { /* data specific to libsamplerate */
72 SRC_STATE *state;
73 } src;
74
75 struct { /* data specific to speex */
76 SpeexResamplerState* state;
77 } speex;
78 };
79
80 static int libsamplerate_init(pa_resampler*r);
81 static int trivial_init(pa_resampler*r);
82 static int speex_init(pa_resampler*r);
83
84 static void calc_map_table(pa_resampler *r);
85
86 static int (* const init_table[])(pa_resampler*r) = {
87 [PA_RESAMPLER_SRC_SINC_BEST_QUALITY] = libsamplerate_init,
88 [PA_RESAMPLER_SRC_SINC_MEDIUM_QUALITY] = libsamplerate_init,
89 [PA_RESAMPLER_SRC_SINC_FASTEST] = libsamplerate_init,
90 [PA_RESAMPLER_SRC_ZERO_ORDER_HOLD] = libsamplerate_init,
91 [PA_RESAMPLER_SRC_LINEAR] = libsamplerate_init,
92 [PA_RESAMPLER_TRIVIAL] = trivial_init,
93 [PA_RESAMPLER_SPEEX_FLOAT_BASE+0] = speex_init,
94 [PA_RESAMPLER_SPEEX_FLOAT_BASE+1] = speex_init,
95 [PA_RESAMPLER_SPEEX_FLOAT_BASE+2] = speex_init,
96 [PA_RESAMPLER_SPEEX_FLOAT_BASE+3] = speex_init,
97 [PA_RESAMPLER_SPEEX_FLOAT_BASE+4] = speex_init,
98 [PA_RESAMPLER_SPEEX_FLOAT_BASE+5] = speex_init,
99 [PA_RESAMPLER_SPEEX_FLOAT_BASE+6] = speex_init,
100 [PA_RESAMPLER_SPEEX_FLOAT_BASE+7] = speex_init,
101 [PA_RESAMPLER_SPEEX_FLOAT_BASE+8] = speex_init,
102 [PA_RESAMPLER_SPEEX_FLOAT_BASE+9] = speex_init,
103 [PA_RESAMPLER_SPEEX_FLOAT_BASE+10] = speex_init,
104 [PA_RESAMPLER_SPEEX_FIXED_BASE+0] = speex_init,
105 [PA_RESAMPLER_SPEEX_FIXED_BASE+1] = speex_init,
106 [PA_RESAMPLER_SPEEX_FIXED_BASE+2] = speex_init,
107 [PA_RESAMPLER_SPEEX_FIXED_BASE+3] = speex_init,
108 [PA_RESAMPLER_SPEEX_FIXED_BASE+4] = speex_init,
109 [PA_RESAMPLER_SPEEX_FIXED_BASE+5] = speex_init,
110 [PA_RESAMPLER_SPEEX_FIXED_BASE+6] = speex_init,
111 [PA_RESAMPLER_SPEEX_FIXED_BASE+7] = speex_init,
112 [PA_RESAMPLER_SPEEX_FIXED_BASE+8] = speex_init,
113 [PA_RESAMPLER_SPEEX_FIXED_BASE+9] = speex_init,
114 [PA_RESAMPLER_SPEEX_FIXED_BASE+10] = speex_init,
115 [PA_RESAMPLER_AUTO] = NULL,
116 };
117
118 static inline size_t sample_size(pa_sample_format_t f) {
119 pa_sample_spec ss = {
120 .format = f,
121 .rate = 0,
122 .channels = 1
123 };
124
125 return pa_sample_size(&ss);
126 }
127
128 pa_resampler* pa_resampler_new(
129 pa_mempool *pool,
130 const pa_sample_spec *a,
131 const pa_channel_map *am,
132 const pa_sample_spec *b,
133 const pa_channel_map *bm,
134 pa_resample_method_t resample_method) {
135
136 pa_resampler *r = NULL;
137
138 pa_assert(pool);
139 pa_assert(a);
140 pa_assert(b);
141 pa_assert(pa_sample_spec_valid(a));
142 pa_assert(pa_sample_spec_valid(b));
143 pa_assert(resample_method >= 0);
144 pa_assert(resample_method < PA_RESAMPLER_MAX);
145
146 /* Fix method */
147 if (resample_method == PA_RESAMPLER_AUTO) {
148 if (a->format == PA_SAMPLE_FLOAT32LE || a->format == PA_SAMPLE_FLOAT32BE ||
149 b->format == PA_SAMPLE_FLOAT32LE || b->format == PA_SAMPLE_FLOAT32BE)
150 resample_method = PA_RESAMPLER_SPEEX_FLOAT_BASE + 0;
151 else
152 resample_method = PA_RESAMPLER_SPEEX_FIXED_BASE + 0;
153 }
154
155 r = pa_xnew(pa_resampler, 1);
156 r->mempool = pool;
157 r->resample_method = resample_method;
158
159 r->impl_free = NULL;
160 r->impl_update_rates = NULL;
161 r->impl_resample = NULL;
162
163 /* Fill sample specs */
164 r->i_ss = *a;
165 r->o_ss = *b;
166
167 if (am)
168 r->i_cm = *am;
169 else
170 pa_channel_map_init_auto(&r->i_cm, r->i_ss.channels, PA_CHANNEL_MAP_DEFAULT);
171
172 if (bm)
173 r->o_cm = *bm;
174 else
175 pa_channel_map_init_auto(&r->o_cm, r->o_ss.channels, PA_CHANNEL_MAP_DEFAULT);
176
177 r->i_fz = pa_frame_size(a);
178 r->o_fz = pa_frame_size(b);
179
180 pa_memchunk_reset(&r->buf1);
181 pa_memchunk_reset(&r->buf2);
182 pa_memchunk_reset(&r->buf3);
183 pa_memchunk_reset(&r->buf4);
184
185 r->buf1_samples = r->buf2_samples = r->buf3_samples = r->buf4_samples = 0;
186
187 calc_map_table(r);
188
189 pa_log_info("Using resampler '%s'", pa_resample_method_to_string(resample_method));
190
191 if (resample_method >= PA_RESAMPLER_SPEEX_FIXED_BASE && resample_method <= PA_RESAMPLER_SPEEX_FIXED_MAX)
192 r->work_format = PA_SAMPLE_S16NE;
193 else if (resample_method == PA_RESAMPLER_TRIVIAL) {
194
195 if (r->map_required || a->format != b->format) {
196
197 if (a->format == PA_SAMPLE_FLOAT32NE || a->format == PA_SAMPLE_FLOAT32RE)
198 r->work_format = PA_SAMPLE_FLOAT32NE;
199 else
200 r->work_format = PA_SAMPLE_S16NE;
201
202 } else
203 r->work_format = a->format;
204
205 } else
206 r->work_format = PA_SAMPLE_FLOAT32NE;
207
208 r->w_sz = sample_size(r->work_format);
209
210 if (r->i_ss.format == r->work_format)
211 r->to_work_format_func = NULL;
212 else if (r->work_format == PA_SAMPLE_FLOAT32NE) {
213 if (!(r->to_work_format_func = pa_get_convert_to_float32ne_function(r->i_ss.format)))
214 goto fail;
215 } else {
216 pa_assert(r->work_format == PA_SAMPLE_S16NE);
217 if (!(r->to_work_format_func = pa_get_convert_to_s16ne_function(r->i_ss.format)))
218 goto fail;
219 }
220
221 if (r->o_ss.format == r->work_format)
222 r->from_work_format_func = NULL;
223 else if (r->work_format == PA_SAMPLE_FLOAT32NE) {
224 if (!(r->from_work_format_func = pa_get_convert_from_float32ne_function(r->o_ss.format)))
225 goto fail;
226 } else {
227 pa_assert(r->work_format == PA_SAMPLE_S16NE);
228 if (!(r->from_work_format_func = pa_get_convert_from_s16ne_function(r->o_ss.format)))
229 goto fail;
230 }
231
232 /* initialize implementation */
233 if (init_table[resample_method](r) < 0)
234 goto fail;
235
236 return r;
237
238 fail:
239 if (r)
240 pa_xfree(r);
241
242 return NULL;
243 }
244
245 void pa_resampler_free(pa_resampler *r) {
246 pa_assert(r);
247
248 if (r->impl_free)
249 r->impl_free(r);
250
251 if (r->buf1.memblock)
252 pa_memblock_unref(r->buf1.memblock);
253 if (r->buf2.memblock)
254 pa_memblock_unref(r->buf2.memblock);
255 if (r->buf3.memblock)
256 pa_memblock_unref(r->buf3.memblock);
257 if (r->buf4.memblock)
258 pa_memblock_unref(r->buf4.memblock);
259
260 pa_xfree(r);
261 }
262
263 void pa_resampler_set_input_rate(pa_resampler *r, uint32_t rate) {
264 pa_assert(r);
265 pa_assert(rate > 0);
266
267 if (r->i_ss.rate == rate)
268 return;
269
270 r->i_ss.rate = rate;
271 r->impl_update_rates(r);
272 }
273
274 void pa_resampler_set_output_rate(pa_resampler *r, uint32_t rate) {
275 pa_assert(r);
276 pa_assert(rate > 0);
277
278 if (r->o_ss.rate == rate)
279 return;
280
281 r->o_ss.rate = rate;
282 r->impl_update_rates(r);
283 }
284
285 size_t pa_resampler_request(pa_resampler *r, size_t out_length) {
286 pa_assert(r);
287
288 return (((out_length / r->o_fz)*r->i_ss.rate)/r->o_ss.rate) * r->i_fz;
289 }
290
291 pa_resample_method_t pa_resampler_get_method(pa_resampler *r) {
292 pa_assert(r);
293
294 return r->resample_method;
295 }
296
297 static const char * const resample_methods[] = {
298 "src-sinc-best-quality",
299 "src-sinc-medium-quality",
300 "src-sinc-fastest",
301 "src-zero-order-hold",
302 "src-linear",
303 "trivial",
304 "speex-float-0",
305 "speex-float-1",
306 "speex-float-2",
307 "speex-float-3",
308 "speex-float-4",
309 "speex-float-5",
310 "speex-float-6",
311 "speex-float-7",
312 "speex-float-8",
313 "speex-float-9",
314 "speex-float-10",
315 "speex-fixed-0",
316 "speex-fixed-1",
317 "speex-fixed-2",
318 "speex-fixed-3",
319 "speex-fixed-4",
320 "speex-fixed-5",
321 "speex-fixed-6",
322 "speex-fixed-7",
323 "speex-fixed-8",
324 "speex-fixed-9",
325 "speex-fixed-10",
326 "auto"
327 };
328
329 const char *pa_resample_method_to_string(pa_resample_method_t m) {
330
331 if (m < 0 || m >= PA_RESAMPLER_MAX)
332 return NULL;
333
334 return resample_methods[m];
335 }
336
337 pa_resample_method_t pa_parse_resample_method(const char *string) {
338 pa_resample_method_t m;
339
340 pa_assert(string);
341
342 for (m = 0; m < PA_RESAMPLER_MAX; m++)
343 if (!strcmp(string, resample_methods[m]))
344 return m;
345
346 if (!strcmp(string, "speex-fixed"))
347 return PA_RESAMPLER_SPEEX_FIXED_BASE + 0;
348
349 if (!strcmp(string, "speex-float"))
350 return PA_RESAMPLER_SPEEX_FLOAT_BASE + 0;
351
352 return PA_RESAMPLER_INVALID;
353 }
354
355 static void calc_map_table(pa_resampler *r) {
356 unsigned oc;
357
358 pa_assert(r);
359
360 if (!(r->map_required = (r->i_ss.channels != r->o_ss.channels || !pa_channel_map_equal(&r->i_cm, &r->o_cm))))
361 return;
362
363 for (oc = 0; oc < r->o_ss.channels; oc++) {
364 unsigned ic, i = 0;
365
366 for (ic = 0; ic < r->i_ss.channels; ic++) {
367 pa_channel_position_t a, b;
368
369 a = r->i_cm.map[ic];
370 b = r->o_cm.map[oc];
371
372 if (a == b ||
373 (a == PA_CHANNEL_POSITION_MONO && b == PA_CHANNEL_POSITION_LEFT) ||
374 (a == PA_CHANNEL_POSITION_MONO && b == PA_CHANNEL_POSITION_RIGHT) ||
375 (a == PA_CHANNEL_POSITION_LEFT && b == PA_CHANNEL_POSITION_MONO) ||
376 (a == PA_CHANNEL_POSITION_RIGHT && b == PA_CHANNEL_POSITION_MONO))
377
378 r->map_table[oc][i++] = ic;
379 }
380
381 /* Add an end marker */
382 if (i < PA_CHANNELS_MAX)
383 r->map_table[oc][i] = -1;
384 }
385 }
386
387 static pa_memchunk* convert_to_work_format(pa_resampler *r, pa_memchunk *input) {
388 unsigned n_samples;
389 void *src, *dst;
390
391 pa_assert(r);
392 pa_assert(input);
393 pa_assert(input->memblock);
394
395 /* Convert the incoming sample into the work sample format and place them in buf1 */
396
397 if (!r->to_work_format_func || !input->length)
398 return input;
399
400 n_samples = (input->length / r->i_fz) * r->i_ss.channels;
401
402 r->buf1.index = 0;
403 r->buf1.length = r->w_sz * n_samples;
404
405 if (!r->buf1.memblock || r->buf1_samples < n_samples) {
406 if (r->buf1.memblock)
407 pa_memblock_unref(r->buf1.memblock);
408
409 r->buf1_samples = n_samples;
410 r->buf1.memblock = pa_memblock_new(r->mempool, r->buf1.length);
411 }
412
413 src = (uint8_t*) pa_memblock_acquire(input->memblock) + input->index;
414 dst = (uint8_t*) pa_memblock_acquire(r->buf1.memblock);
415
416 r->to_work_format_func(n_samples, src, dst);
417
418 pa_memblock_release(input->memblock);
419 pa_memblock_release(r->buf1.memblock);
420
421 return &r->buf1;
422 }
423
424 static pa_memchunk *remap_channels(pa_resampler *r, pa_memchunk *input) {
425 unsigned in_n_samples, out_n_samples, n_frames;
426 int i_skip, o_skip;
427 unsigned oc;
428 void *src, *dst;
429
430 pa_assert(r);
431 pa_assert(input);
432 pa_assert(input->memblock);
433
434 /* Remap channels and place the result int buf2 */
435
436 if (!r->map_required || !input->length)
437 return input;
438
439 in_n_samples = input->length / r->w_sz;
440 n_frames = in_n_samples / r->i_ss.channels;
441 out_n_samples = n_frames * r->o_ss.channels;
442
443 r->buf2.index = 0;
444 r->buf2.length = r->w_sz * out_n_samples;
445
446 if (!r->buf2.memblock || r->buf2_samples < out_n_samples) {
447 if (r->buf2.memblock)
448 pa_memblock_unref(r->buf2.memblock);
449
450 r->buf2_samples = out_n_samples;
451 r->buf2.memblock = pa_memblock_new(r->mempool, r->buf2.length);
452 }
453
454 src = ((uint8_t*) pa_memblock_acquire(input->memblock) + input->index);
455 dst = pa_memblock_acquire(r->buf2.memblock);
456
457 memset(dst, 0, r->buf2.length);
458
459 o_skip = r->w_sz * r->o_ss.channels;
460 i_skip = r->w_sz * r->i_ss.channels;
461
462 switch (r->work_format) {
463 case PA_SAMPLE_FLOAT32NE:
464
465 for (oc = 0; oc < r->o_ss.channels; oc++) {
466 unsigned i;
467 static const float one = 1.0;
468
469 for (i = 0; i < PA_CHANNELS_MAX && r->map_table[oc][i] >= 0; i++)
470 oil_vectoradd_f32(
471 (float*) dst + oc, o_skip,
472 (float*) dst + oc, o_skip,
473 (float*) src + r->map_table[oc][i], i_skip,
474 n_frames,
475 &one, &one);
476 }
477
478 break;
479
480 case PA_SAMPLE_S16NE:
481
482 for (oc = 0; oc < r->o_ss.channels; oc++) {
483 unsigned i;
484 static const int16_t one = 1;
485
486 for (i = 0; i < PA_CHANNELS_MAX && r->map_table[oc][i] >= 0; i++)
487 oil_vectoradd_s16(
488 (int16_t*) dst + oc, o_skip,
489 (int16_t*) dst + oc, o_skip,
490 (int16_t*) src + r->map_table[oc][i], i_skip,
491 n_frames,
492 &one, &one);
493 }
494
495 break;
496
497 default:
498 pa_assert_not_reached();
499 }
500
501 pa_memblock_release(input->memblock);
502 pa_memblock_release(r->buf2.memblock);
503
504 r->buf2.length = out_n_samples * r->w_sz;
505
506 return &r->buf2;
507 }
508
509 static pa_memchunk *resample(pa_resampler *r, pa_memchunk *input) {
510 unsigned in_n_frames, in_n_samples;
511 unsigned out_n_frames, out_n_samples;
512
513 pa_assert(r);
514 pa_assert(input);
515
516 /* Resample the data and place the result in buf3 */
517
518 if (!r->impl_resample || !input->length)
519 return input;
520
521 in_n_samples = input->length / r->w_sz;
522 in_n_frames = in_n_samples / r->o_ss.channels;
523
524 out_n_frames = ((in_n_frames*r->o_ss.rate)/r->i_ss.rate)+1024;
525 out_n_samples = out_n_frames * r->o_ss.channels;
526
527 r->buf3.index = 0;
528 r->buf3.length = r->w_sz * out_n_samples;
529
530 if (!r->buf3.memblock || r->buf3_samples < out_n_samples) {
531 if (r->buf3.memblock)
532 pa_memblock_unref(r->buf3.memblock);
533
534 r->buf3_samples = out_n_samples;
535 r->buf3.memblock = pa_memblock_new(r->mempool, r->buf3.length);
536 }
537
538 r->impl_resample(r, input, in_n_frames, &r->buf3, &out_n_frames);
539 r->buf3.length = out_n_frames * r->w_sz * r->o_ss.channels;
540
541 return &r->buf3;
542 }
543
544 static pa_memchunk *convert_from_work_format(pa_resampler *r, pa_memchunk *input) {
545 unsigned n_samples, n_frames;
546 void *src, *dst;
547
548 pa_assert(r);
549 pa_assert(input);
550
551 /* Convert the data into the correct sample type and place the result in buf4 */
552
553 if (!r->from_work_format_func || !input->length)
554 return input;
555
556 n_samples = input->length / r->w_sz;
557 n_frames = n_samples / r->o_ss.channels;
558
559 r->buf4.index = 0;
560 r->buf4.length = r->o_fz * n_frames;
561
562 if (!r->buf4.memblock || r->buf4_samples < n_samples) {
563 if (r->buf4.memblock)
564 pa_memblock_unref(r->buf4.memblock);
565
566 r->buf4_samples = n_samples;
567 r->buf4.memblock = pa_memblock_new(r->mempool, r->buf4.length);
568 }
569
570 src = (uint8_t*) pa_memblock_acquire(input->memblock) + input->index;
571 dst = pa_memblock_acquire(r->buf4.memblock);
572 r->from_work_format_func(n_samples, src, dst);
573 pa_memblock_release(input->memblock);
574 pa_memblock_release(r->buf4.memblock);
575
576 r->buf4.length = r->o_fz * n_frames;
577
578 return &r->buf4;
579 }
580
581 void pa_resampler_run(pa_resampler *r, const pa_memchunk *in, pa_memchunk *out) {
582 pa_memchunk *buf;
583
584 pa_assert(r);
585 pa_assert(in);
586 pa_assert(out);
587 pa_assert(in->length);
588 pa_assert(in->memblock);
589 pa_assert(in->length % r->i_fz == 0);
590
591 buf = (pa_memchunk*) in;
592 buf = convert_to_work_format(r, buf);
593 buf = remap_channels(r, buf);
594 buf = resample(r, buf);
595
596 if (buf->length) {
597 buf = convert_from_work_format(r, buf);
598 *out = *buf;
599
600 if (buf == in)
601 pa_memblock_ref(buf->memblock);
602 else
603 pa_memchunk_reset(buf);
604 } else
605 pa_memchunk_reset(out);
606 }
607
608 /*** libsamplerate based implementation ***/
609
610 static void libsamplerate_resample(pa_resampler *r, const pa_memchunk *input, unsigned in_n_frames, pa_memchunk *output, unsigned *out_n_frames) {
611 SRC_DATA data;
612
613 pa_assert(r);
614 pa_assert(input);
615 pa_assert(output);
616 pa_assert(out_n_frames);
617
618 memset(&data, 0, sizeof(data));
619
620 data.data_in = (float*) ((uint8_t*) pa_memblock_acquire(input->memblock) + input->index);
621 data.input_frames = in_n_frames;
622
623 data.data_out = (float*) ((uint8_t*) pa_memblock_acquire(output->memblock) + output->index);
624 data.output_frames = *out_n_frames;
625
626 data.src_ratio = (double) r->o_ss.rate / r->i_ss.rate;
627 data.end_of_input = 0;
628
629 pa_assert_se(src_process(r->src.state, &data) == 0);
630 pa_assert((unsigned) data.input_frames_used == in_n_frames);
631
632 pa_memblock_release(input->memblock);
633 pa_memblock_release(output->memblock);
634
635 *out_n_frames = data.output_frames_gen;
636 }
637
638 static void libsamplerate_update_rates(pa_resampler *r) {
639 pa_assert(r);
640
641 pa_assert_se(src_set_ratio(r->src.state, (double) r->o_ss.rate / r->i_ss.rate) == 0);
642 }
643
644 static void libsamplerate_free(pa_resampler *r) {
645 pa_assert(r);
646
647 if (r->src.state)
648 src_delete(r->src.state);
649 }
650
651 static int libsamplerate_init(pa_resampler *r) {
652 int err;
653
654 pa_assert(r);
655
656 if (!(r->src.state = src_new(r->resample_method, r->o_ss.channels, &err)))
657 return -1;
658
659 r->impl_free = libsamplerate_free;
660 r->impl_update_rates = libsamplerate_update_rates;
661 r->impl_resample = libsamplerate_resample;
662
663 return 0;
664 }
665
666 /*** speex based implementation ***/
667
668 static void speex_resample_float(pa_resampler *r, const pa_memchunk *input, unsigned in_n_frames, pa_memchunk *output, unsigned *out_n_frames) {
669 float *in, *out;
670 uint32_t inf = in_n_frames, outf = *out_n_frames;
671
672 pa_assert(r);
673 pa_assert(input);
674 pa_assert(output);
675 pa_assert(out_n_frames);
676
677 in = (float*) ((uint8_t*) pa_memblock_acquire(input->memblock) + input->index);
678 out = (float*) ((uint8_t*) pa_memblock_acquire(output->memblock) + output->index);
679
680 pa_assert_se(paspfl_resampler_process_interleaved_float(r->speex.state, in, &inf, out, &outf) == 0);
681
682 pa_memblock_release(input->memblock);
683 pa_memblock_release(output->memblock);
684
685 pa_assert(inf == in_n_frames);
686 *out_n_frames = outf;
687 }
688
689 static void speex_resample_int(pa_resampler *r, const pa_memchunk *input, unsigned in_n_frames, pa_memchunk *output, unsigned *out_n_frames) {
690 int16_t *in, *out;
691 uint32_t inf = in_n_frames, outf = *out_n_frames;
692
693 pa_assert(r);
694 pa_assert(input);
695 pa_assert(output);
696 pa_assert(out_n_frames);
697
698 in = (int16_t*) ((uint8_t*) pa_memblock_acquire(input->memblock) + input->index);
699 out = (int16_t*) ((uint8_t*) pa_memblock_acquire(output->memblock) + output->index);
700
701 pa_assert_se(paspfx_resampler_process_interleaved_int(r->speex.state, in, &inf, out, &outf) == 0);
702
703 pa_memblock_release(input->memblock);
704 pa_memblock_release(output->memblock);
705
706 pa_assert(inf == in_n_frames);
707 *out_n_frames = outf;
708 }
709
710 static void speex_update_rates(pa_resampler *r) {
711 pa_assert(r);
712
713 if (r->resample_method >= PA_RESAMPLER_SPEEX_FIXED_BASE && r->resample_method <= PA_RESAMPLER_SPEEX_FIXED_MAX)
714 pa_assert_se(paspfx_resampler_set_rate(r->speex.state, r->i_ss.rate, r->o_ss.rate) == 0);
715 else {
716 pa_assert(r->resample_method >= PA_RESAMPLER_SPEEX_FLOAT_BASE && r->resample_method <= PA_RESAMPLER_SPEEX_FLOAT_MAX);
717 pa_assert_se(paspfl_resampler_set_rate(r->speex.state, r->i_ss.rate, r->o_ss.rate) == 0);
718 }
719 }
720
721 static void speex_free(pa_resampler *r) {
722 pa_assert(r);
723
724 if (r->speex.state) {
725 if (r->resample_method >= PA_RESAMPLER_SPEEX_FIXED_BASE && r->resample_method <= PA_RESAMPLER_SPEEX_FIXED_MAX)
726 paspfx_resampler_destroy(r->speex.state);
727 else {
728 pa_assert(r->resample_method >= PA_RESAMPLER_SPEEX_FLOAT_BASE && r->resample_method <= PA_RESAMPLER_SPEEX_FLOAT_MAX);
729 paspfl_resampler_destroy(r->speex.state);
730 }
731 }
732 }
733
734 static int speex_init(pa_resampler *r) {
735 int q, err;
736
737 pa_assert(r);
738
739 r->impl_free = speex_free;
740 r->impl_update_rates = speex_update_rates;
741
742 if (r->resample_method >= PA_RESAMPLER_SPEEX_FIXED_BASE && r->resample_method <= PA_RESAMPLER_SPEEX_FIXED_MAX) {
743 q = r->resample_method - PA_RESAMPLER_SPEEX_FIXED_BASE;
744 r->impl_resample = speex_resample_int;
745
746 if (!(r->speex.state = paspfx_resampler_init(r->o_ss.channels, r->i_ss.rate, r->o_ss.rate, q, &err)))
747 return -1;
748
749 } else {
750 pa_assert(r->resample_method >= PA_RESAMPLER_SPEEX_FLOAT_BASE && r->resample_method <= PA_RESAMPLER_SPEEX_FLOAT_MAX);
751 q = r->resample_method - PA_RESAMPLER_SPEEX_FLOAT_BASE;
752 r->impl_resample = speex_resample_float;
753
754 if (!(r->speex.state = paspfl_resampler_init(r->o_ss.channels, r->i_ss.rate, r->o_ss.rate, q, &err)))
755 return -1;
756 }
757
758
759 return 0;
760 }
761
762 /* Trivial implementation */
763
764 static void trivial_resample(pa_resampler *r, const pa_memchunk *input, unsigned in_n_frames, pa_memchunk *output, unsigned *out_n_frames) {
765 size_t fz;
766 unsigned o_index;
767 void *src, *dst;
768
769 pa_assert(r);
770 pa_assert(input);
771 pa_assert(output);
772 pa_assert(out_n_frames);
773
774 fz = r->w_sz * r->o_ss.channels;
775
776 src = (uint8_t*) pa_memblock_acquire(input->memblock) + input->index;
777 dst = (uint8_t*) pa_memblock_acquire(output->memblock) + output->index;
778
779 for (o_index = 0;; o_index++, r->trivial.o_counter++) {
780 unsigned j;
781
782 j = ((r->trivial.o_counter * r->i_ss.rate) / r->o_ss.rate);
783 j = j > r->trivial.i_counter ? j - r->trivial.i_counter : 0;
784
785 if (j >= in_n_frames)
786 break;
787
788 pa_assert(o_index * fz < pa_memblock_get_length(output->memblock));
789
790 oil_memcpy((uint8_t*) dst + fz * o_index,
791 (uint8_t*) src + fz * j, fz);
792 }
793
794 pa_memblock_release(input->memblock);
795 pa_memblock_release(output->memblock);
796
797 *out_n_frames = o_index;
798
799 r->trivial.i_counter += in_n_frames;
800
801 /* Normalize counters */
802 while (r->trivial.i_counter >= r->i_ss.rate) {
803 pa_assert(r->trivial.o_counter >= r->o_ss.rate);
804
805 r->trivial.i_counter -= r->i_ss.rate;
806 r->trivial.o_counter -= r->o_ss.rate;
807 }
808 }
809
810 static void trivial_update_rates(pa_resampler *r) {
811 pa_assert(r);
812
813 r->trivial.i_counter = 0;
814 r->trivial.o_counter = 0;
815 }
816
817 static int trivial_init(pa_resampler*r) {
818 pa_assert(r);
819
820 r->trivial.o_counter = r->trivial.i_counter = 0;
821
822 r->impl_resample = trivial_resample;
823 r->impl_update_rates = trivial_update_rates;
824
825 return 0;
826 }
827
828