]> code.delx.au - pulseaudio/blob - src/pulsecore/resampler.c
d98d482dc6425b46f684ec96c94077f88be6be2a
[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 "ffmpeg/avcodec.h"
43
44 #include "resampler.h"
45
46 struct pa_resampler {
47 pa_resample_method_t resample_method;
48 pa_sample_spec i_ss, o_ss;
49 pa_channel_map i_cm, o_cm;
50 size_t i_fz, o_fz, w_sz;
51 pa_mempool *mempool;
52
53 pa_memchunk buf1, buf2, buf3, buf4;
54 unsigned buf1_samples, buf2_samples, buf3_samples, buf4_samples;
55
56 pa_sample_format_t work_format;
57
58 pa_convert_func_t to_work_format_func;
59 pa_convert_func_t from_work_format_func;
60
61 int map_table[PA_CHANNELS_MAX][PA_CHANNELS_MAX];
62 int map_required;
63
64 void (*impl_free)(pa_resampler *r);
65 void (*impl_update_rates)(pa_resampler *r);
66 void (*impl_resample)(pa_resampler *r, const pa_memchunk *in, unsigned in_samples, pa_memchunk *out, unsigned *out_samples);
67
68 struct { /* data specific to the trivial resampler */
69 unsigned o_counter;
70 unsigned i_counter;
71 } trivial;
72
73 struct { /* data specific to libsamplerate */
74 SRC_STATE *state;
75 } src;
76
77 struct { /* data specific to speex */
78 SpeexResamplerState* state;
79 } speex;
80
81 struct { /* data specific to ffmpeg */
82 struct AVResampleContext *state;
83 pa_memchunk buf[PA_CHANNELS_MAX];
84 } ffmpeg;
85 };
86
87 static int libsamplerate_init(pa_resampler*r);
88 static int trivial_init(pa_resampler*r);
89 static int speex_init(pa_resampler*r);
90 static int ffmpeg_init(pa_resampler*r);
91
92 static void calc_map_table(pa_resampler *r);
93
94 static int (* const init_table[])(pa_resampler*r) = {
95 [PA_RESAMPLER_SRC_SINC_BEST_QUALITY] = libsamplerate_init,
96 [PA_RESAMPLER_SRC_SINC_MEDIUM_QUALITY] = libsamplerate_init,
97 [PA_RESAMPLER_SRC_SINC_FASTEST] = libsamplerate_init,
98 [PA_RESAMPLER_SRC_ZERO_ORDER_HOLD] = libsamplerate_init,
99 [PA_RESAMPLER_SRC_LINEAR] = libsamplerate_init,
100 [PA_RESAMPLER_TRIVIAL] = trivial_init,
101 [PA_RESAMPLER_SPEEX_FLOAT_BASE+0] = speex_init,
102 [PA_RESAMPLER_SPEEX_FLOAT_BASE+1] = speex_init,
103 [PA_RESAMPLER_SPEEX_FLOAT_BASE+2] = speex_init,
104 [PA_RESAMPLER_SPEEX_FLOAT_BASE+3] = speex_init,
105 [PA_RESAMPLER_SPEEX_FLOAT_BASE+4] = speex_init,
106 [PA_RESAMPLER_SPEEX_FLOAT_BASE+5] = speex_init,
107 [PA_RESAMPLER_SPEEX_FLOAT_BASE+6] = speex_init,
108 [PA_RESAMPLER_SPEEX_FLOAT_BASE+7] = speex_init,
109 [PA_RESAMPLER_SPEEX_FLOAT_BASE+8] = speex_init,
110 [PA_RESAMPLER_SPEEX_FLOAT_BASE+9] = speex_init,
111 [PA_RESAMPLER_SPEEX_FLOAT_BASE+10] = speex_init,
112 [PA_RESAMPLER_SPEEX_FIXED_BASE+0] = speex_init,
113 [PA_RESAMPLER_SPEEX_FIXED_BASE+1] = speex_init,
114 [PA_RESAMPLER_SPEEX_FIXED_BASE+2] = speex_init,
115 [PA_RESAMPLER_SPEEX_FIXED_BASE+3] = speex_init,
116 [PA_RESAMPLER_SPEEX_FIXED_BASE+4] = speex_init,
117 [PA_RESAMPLER_SPEEX_FIXED_BASE+5] = speex_init,
118 [PA_RESAMPLER_SPEEX_FIXED_BASE+6] = speex_init,
119 [PA_RESAMPLER_SPEEX_FIXED_BASE+7] = speex_init,
120 [PA_RESAMPLER_SPEEX_FIXED_BASE+8] = speex_init,
121 [PA_RESAMPLER_SPEEX_FIXED_BASE+9] = speex_init,
122 [PA_RESAMPLER_SPEEX_FIXED_BASE+10] = speex_init,
123 [PA_RESAMPLER_FFMPEG] = ffmpeg_init,
124 [PA_RESAMPLER_AUTO] = NULL,
125 };
126
127 static inline size_t sample_size(pa_sample_format_t f) {
128 pa_sample_spec ss = {
129 .format = f,
130 .rate = 0,
131 .channels = 1
132 };
133
134 return pa_sample_size(&ss);
135 }
136
137 pa_resampler* pa_resampler_new(
138 pa_mempool *pool,
139 const pa_sample_spec *a,
140 const pa_channel_map *am,
141 const pa_sample_spec *b,
142 const pa_channel_map *bm,
143 pa_resample_method_t resample_method,
144 int variable_rate) {
145
146 pa_resampler *r = NULL;
147
148 pa_assert(pool);
149 pa_assert(a);
150 pa_assert(b);
151 pa_assert(pa_sample_spec_valid(a));
152 pa_assert(pa_sample_spec_valid(b));
153 pa_assert(resample_method >= 0);
154 pa_assert(resample_method < PA_RESAMPLER_MAX);
155
156 /* Fix method */
157
158 if (resample_method == PA_RESAMPLER_FFMPEG && variable_rate) {
159 pa_log_info("Resampler 'ffmpeg' cannot do variable rate, reverting to resampler 'auto'." );
160 resample_method = PA_RESAMPLER_AUTO;
161 }
162
163 if (resample_method == PA_RESAMPLER_AUTO)
164 resample_method = PA_RESAMPLER_SPEEX_FLOAT_BASE + 0;
165
166 r = pa_xnew(pa_resampler, 1);
167 r->mempool = pool;
168 r->resample_method = resample_method;
169
170 r->impl_free = NULL;
171 r->impl_update_rates = NULL;
172 r->impl_resample = NULL;
173
174 /* Fill sample specs */
175 r->i_ss = *a;
176 r->o_ss = *b;
177
178 if (am)
179 r->i_cm = *am;
180 else
181 pa_channel_map_init_auto(&r->i_cm, r->i_ss.channels, PA_CHANNEL_MAP_DEFAULT);
182
183 if (bm)
184 r->o_cm = *bm;
185 else
186 pa_channel_map_init_auto(&r->o_cm, r->o_ss.channels, PA_CHANNEL_MAP_DEFAULT);
187
188 r->i_fz = pa_frame_size(a);
189 r->o_fz = pa_frame_size(b);
190
191 pa_memchunk_reset(&r->buf1);
192 pa_memchunk_reset(&r->buf2);
193 pa_memchunk_reset(&r->buf3);
194 pa_memchunk_reset(&r->buf4);
195
196 r->buf1_samples = r->buf2_samples = r->buf3_samples = r->buf4_samples = 0;
197
198 calc_map_table(r);
199
200 pa_log_info("Using resampler '%s'", pa_resample_method_to_string(resample_method));
201
202 if ((resample_method >= PA_RESAMPLER_SPEEX_FIXED_BASE && resample_method <= PA_RESAMPLER_SPEEX_FIXED_MAX) ||
203 (resample_method == PA_RESAMPLER_FFMPEG))
204 r->work_format = PA_SAMPLE_S16NE;
205 else if (resample_method == PA_RESAMPLER_TRIVIAL) {
206
207 if (r->map_required || a->format != b->format) {
208
209 if (a->format == PA_SAMPLE_FLOAT32NE || a->format == PA_SAMPLE_FLOAT32RE)
210 r->work_format = PA_SAMPLE_FLOAT32NE;
211 else
212 r->work_format = PA_SAMPLE_S16NE;
213
214 } else
215 r->work_format = a->format;
216
217 } else
218 r->work_format = PA_SAMPLE_FLOAT32NE;
219
220 r->w_sz = sample_size(r->work_format);
221
222 if (r->i_ss.format == r->work_format)
223 r->to_work_format_func = NULL;
224 else if (r->work_format == PA_SAMPLE_FLOAT32NE) {
225 if (!(r->to_work_format_func = pa_get_convert_to_float32ne_function(r->i_ss.format)))
226 goto fail;
227 } else {
228 pa_assert(r->work_format == PA_SAMPLE_S16NE);
229 if (!(r->to_work_format_func = pa_get_convert_to_s16ne_function(r->i_ss.format)))
230 goto fail;
231 }
232
233 if (r->o_ss.format == r->work_format)
234 r->from_work_format_func = NULL;
235 else if (r->work_format == PA_SAMPLE_FLOAT32NE) {
236 if (!(r->from_work_format_func = pa_get_convert_from_float32ne_function(r->o_ss.format)))
237 goto fail;
238 } else {
239 pa_assert(r->work_format == PA_SAMPLE_S16NE);
240 if (!(r->from_work_format_func = pa_get_convert_from_s16ne_function(r->o_ss.format)))
241 goto fail;
242 }
243
244 /* initialize implementation */
245 if (init_table[resample_method](r) < 0)
246 goto fail;
247
248 return r;
249
250 fail:
251 if (r)
252 pa_xfree(r);
253
254 return NULL;
255 }
256
257 void pa_resampler_free(pa_resampler *r) {
258 pa_assert(r);
259
260 if (r->impl_free)
261 r->impl_free(r);
262
263 if (r->buf1.memblock)
264 pa_memblock_unref(r->buf1.memblock);
265 if (r->buf2.memblock)
266 pa_memblock_unref(r->buf2.memblock);
267 if (r->buf3.memblock)
268 pa_memblock_unref(r->buf3.memblock);
269 if (r->buf4.memblock)
270 pa_memblock_unref(r->buf4.memblock);
271
272 pa_xfree(r);
273 }
274
275 void pa_resampler_set_input_rate(pa_resampler *r, uint32_t rate) {
276 pa_assert(r);
277 pa_assert(rate > 0);
278
279 if (r->i_ss.rate == rate)
280 return;
281
282 r->i_ss.rate = rate;
283
284 r->impl_update_rates(r);
285 }
286
287 void pa_resampler_set_output_rate(pa_resampler *r, uint32_t rate) {
288 pa_assert(r);
289 pa_assert(rate > 0);
290
291 if (r->o_ss.rate == rate)
292 return;
293
294 r->o_ss.rate = rate;
295
296 r->impl_update_rates(r);
297 }
298
299 size_t pa_resampler_request(pa_resampler *r, size_t out_length) {
300 pa_assert(r);
301
302 return (((out_length / r->o_fz)*r->i_ss.rate)/r->o_ss.rate) * r->i_fz;
303 }
304
305 pa_resample_method_t pa_resampler_get_method(pa_resampler *r) {
306 pa_assert(r);
307
308 return r->resample_method;
309 }
310
311 static const char * const resample_methods[] = {
312 "src-sinc-best-quality",
313 "src-sinc-medium-quality",
314 "src-sinc-fastest",
315 "src-zero-order-hold",
316 "src-linear",
317 "trivial",
318 "speex-float-0",
319 "speex-float-1",
320 "speex-float-2",
321 "speex-float-3",
322 "speex-float-4",
323 "speex-float-5",
324 "speex-float-6",
325 "speex-float-7",
326 "speex-float-8",
327 "speex-float-9",
328 "speex-float-10",
329 "speex-fixed-0",
330 "speex-fixed-1",
331 "speex-fixed-2",
332 "speex-fixed-3",
333 "speex-fixed-4",
334 "speex-fixed-5",
335 "speex-fixed-6",
336 "speex-fixed-7",
337 "speex-fixed-8",
338 "speex-fixed-9",
339 "speex-fixed-10",
340 "ffmpeg",
341 "auto"
342 };
343
344 const char *pa_resample_method_to_string(pa_resample_method_t m) {
345
346 if (m < 0 || m >= PA_RESAMPLER_MAX)
347 return NULL;
348
349 return resample_methods[m];
350 }
351
352 pa_resample_method_t pa_parse_resample_method(const char *string) {
353 pa_resample_method_t m;
354
355 pa_assert(string);
356
357 for (m = 0; m < PA_RESAMPLER_MAX; m++)
358 if (!strcmp(string, resample_methods[m]))
359 return m;
360
361 if (!strcmp(string, "speex-fixed"))
362 return PA_RESAMPLER_SPEEX_FIXED_BASE + 0;
363
364 if (!strcmp(string, "speex-float"))
365 return PA_RESAMPLER_SPEEX_FLOAT_BASE + 0;
366
367 return PA_RESAMPLER_INVALID;
368 }
369
370 static void calc_map_table(pa_resampler *r) {
371 unsigned oc;
372
373 pa_assert(r);
374
375 if (!(r->map_required = (r->i_ss.channels != r->o_ss.channels || !pa_channel_map_equal(&r->i_cm, &r->o_cm))))
376 return;
377
378 for (oc = 0; oc < r->o_ss.channels; oc++) {
379 unsigned ic, i = 0;
380
381 for (ic = 0; ic < r->i_ss.channels; ic++) {
382 pa_channel_position_t a, b;
383
384 a = r->i_cm.map[ic];
385 b = r->o_cm.map[oc];
386
387 if (a == b ||
388 (a == PA_CHANNEL_POSITION_MONO && b == PA_CHANNEL_POSITION_LEFT) ||
389 (a == PA_CHANNEL_POSITION_MONO && b == PA_CHANNEL_POSITION_RIGHT) ||
390 (a == PA_CHANNEL_POSITION_LEFT && b == PA_CHANNEL_POSITION_MONO) ||
391 (a == PA_CHANNEL_POSITION_RIGHT && b == PA_CHANNEL_POSITION_MONO))
392
393 r->map_table[oc][i++] = ic;
394 }
395
396 /* Add an end marker */
397 if (i < PA_CHANNELS_MAX)
398 r->map_table[oc][i] = -1;
399 }
400 }
401
402 static pa_memchunk* convert_to_work_format(pa_resampler *r, pa_memchunk *input) {
403 unsigned n_samples;
404 void *src, *dst;
405
406 pa_assert(r);
407 pa_assert(input);
408 pa_assert(input->memblock);
409
410 /* Convert the incoming sample into the work sample format and place them in buf1 */
411
412 if (!r->to_work_format_func || !input->length)
413 return input;
414
415 n_samples = (input->length / r->i_fz) * r->i_ss.channels;
416
417 r->buf1.index = 0;
418 r->buf1.length = r->w_sz * n_samples;
419
420 if (!r->buf1.memblock || r->buf1_samples < n_samples) {
421 if (r->buf1.memblock)
422 pa_memblock_unref(r->buf1.memblock);
423
424 r->buf1_samples = n_samples;
425 r->buf1.memblock = pa_memblock_new(r->mempool, r->buf1.length);
426 }
427
428 src = (uint8_t*) pa_memblock_acquire(input->memblock) + input->index;
429 dst = (uint8_t*) pa_memblock_acquire(r->buf1.memblock);
430
431 r->to_work_format_func(n_samples, src, dst);
432
433 pa_memblock_release(input->memblock);
434 pa_memblock_release(r->buf1.memblock);
435
436 return &r->buf1;
437 }
438
439 static pa_memchunk *remap_channels(pa_resampler *r, pa_memchunk *input) {
440 unsigned in_n_samples, out_n_samples, n_frames;
441 int i_skip, o_skip;
442 unsigned oc;
443 void *src, *dst;
444
445 pa_assert(r);
446 pa_assert(input);
447 pa_assert(input->memblock);
448
449 /* Remap channels and place the result int buf2 */
450
451 if (!r->map_required || !input->length)
452 return input;
453
454 in_n_samples = input->length / r->w_sz;
455 n_frames = in_n_samples / r->i_ss.channels;
456 out_n_samples = n_frames * r->o_ss.channels;
457
458 r->buf2.index = 0;
459 r->buf2.length = r->w_sz * out_n_samples;
460
461 if (!r->buf2.memblock || r->buf2_samples < out_n_samples) {
462 if (r->buf2.memblock)
463 pa_memblock_unref(r->buf2.memblock);
464
465 r->buf2_samples = out_n_samples;
466 r->buf2.memblock = pa_memblock_new(r->mempool, r->buf2.length);
467 }
468
469 src = ((uint8_t*) pa_memblock_acquire(input->memblock) + input->index);
470 dst = pa_memblock_acquire(r->buf2.memblock);
471
472 memset(dst, 0, r->buf2.length);
473
474 o_skip = r->w_sz * r->o_ss.channels;
475 i_skip = r->w_sz * r->i_ss.channels;
476
477 switch (r->work_format) {
478 case PA_SAMPLE_FLOAT32NE:
479
480 for (oc = 0; oc < r->o_ss.channels; oc++) {
481 unsigned i;
482 static const float one = 1.0;
483
484 for (i = 0; i < PA_CHANNELS_MAX && r->map_table[oc][i] >= 0; i++)
485 oil_vectoradd_f32(
486 (float*) dst + oc, o_skip,
487 (float*) dst + oc, o_skip,
488 (float*) src + r->map_table[oc][i], i_skip,
489 n_frames,
490 &one, &one);
491 }
492
493 break;
494
495 case PA_SAMPLE_S16NE:
496
497 for (oc = 0; oc < r->o_ss.channels; oc++) {
498 unsigned i;
499 static const int16_t one = 1;
500
501 for (i = 0; i < PA_CHANNELS_MAX && r->map_table[oc][i] >= 0; i++)
502 oil_vectoradd_s16(
503 (int16_t*) dst + oc, o_skip,
504 (int16_t*) dst + oc, o_skip,
505 (int16_t*) src + r->map_table[oc][i], i_skip,
506 n_frames,
507 &one, &one);
508 }
509
510 break;
511
512 default:
513 pa_assert_not_reached();
514 }
515
516 pa_memblock_release(input->memblock);
517 pa_memblock_release(r->buf2.memblock);
518
519 r->buf2.length = out_n_samples * r->w_sz;
520
521 return &r->buf2;
522 }
523
524 static pa_memchunk *resample(pa_resampler *r, pa_memchunk *input) {
525 unsigned in_n_frames, in_n_samples;
526 unsigned out_n_frames, out_n_samples;
527
528 pa_assert(r);
529 pa_assert(input);
530
531 /* Resample the data and place the result in buf3 */
532
533 if (!r->impl_resample || !input->length)
534 return input;
535
536 in_n_samples = input->length / r->w_sz;
537 in_n_frames = in_n_samples / r->o_ss.channels;
538
539 out_n_frames = ((in_n_frames*r->o_ss.rate)/r->i_ss.rate)+1024;
540 out_n_samples = out_n_frames * r->o_ss.channels;
541
542 r->buf3.index = 0;
543 r->buf3.length = r->w_sz * out_n_samples;
544
545 if (!r->buf3.memblock || r->buf3_samples < out_n_samples) {
546 if (r->buf3.memblock)
547 pa_memblock_unref(r->buf3.memblock);
548
549 r->buf3_samples = out_n_samples;
550 r->buf3.memblock = pa_memblock_new(r->mempool, r->buf3.length);
551 }
552
553 r->impl_resample(r, input, in_n_frames, &r->buf3, &out_n_frames);
554 r->buf3.length = out_n_frames * r->w_sz * r->o_ss.channels;
555
556 return &r->buf3;
557 }
558
559 static pa_memchunk *convert_from_work_format(pa_resampler *r, pa_memchunk *input) {
560 unsigned n_samples, n_frames;
561 void *src, *dst;
562
563 pa_assert(r);
564 pa_assert(input);
565
566 /* Convert the data into the correct sample type and place the result in buf4 */
567
568 if (!r->from_work_format_func || !input->length)
569 return input;
570
571 n_samples = input->length / r->w_sz;
572 n_frames = n_samples / r->o_ss.channels;
573
574 r->buf4.index = 0;
575 r->buf4.length = r->o_fz * n_frames;
576
577 if (!r->buf4.memblock || r->buf4_samples < n_samples) {
578 if (r->buf4.memblock)
579 pa_memblock_unref(r->buf4.memblock);
580
581 r->buf4_samples = n_samples;
582 r->buf4.memblock = pa_memblock_new(r->mempool, r->buf4.length);
583 }
584
585 src = (uint8_t*) pa_memblock_acquire(input->memblock) + input->index;
586 dst = pa_memblock_acquire(r->buf4.memblock);
587 r->from_work_format_func(n_samples, src, dst);
588 pa_memblock_release(input->memblock);
589 pa_memblock_release(r->buf4.memblock);
590
591 r->buf4.length = r->o_fz * n_frames;
592
593 return &r->buf4;
594 }
595
596 void pa_resampler_run(pa_resampler *r, const pa_memchunk *in, pa_memchunk *out) {
597 pa_memchunk *buf;
598
599 pa_assert(r);
600 pa_assert(in);
601 pa_assert(out);
602 pa_assert(in->length);
603 pa_assert(in->memblock);
604 pa_assert(in->length % r->i_fz == 0);
605
606 buf = (pa_memchunk*) in;
607 buf = convert_to_work_format(r, buf);
608 buf = remap_channels(r, buf);
609 buf = resample(r, buf);
610
611 if (buf->length) {
612 buf = convert_from_work_format(r, buf);
613 *out = *buf;
614
615 if (buf == in)
616 pa_memblock_ref(buf->memblock);
617 else
618 pa_memchunk_reset(buf);
619 } else
620 pa_memchunk_reset(out);
621 }
622
623 /*** libsamplerate based implementation ***/
624
625 static void libsamplerate_resample(pa_resampler *r, const pa_memchunk *input, unsigned in_n_frames, pa_memchunk *output, unsigned *out_n_frames) {
626 SRC_DATA data;
627
628 pa_assert(r);
629 pa_assert(input);
630 pa_assert(output);
631 pa_assert(out_n_frames);
632
633 memset(&data, 0, sizeof(data));
634
635 data.data_in = (float*) ((uint8_t*) pa_memblock_acquire(input->memblock) + input->index);
636 data.input_frames = in_n_frames;
637
638 data.data_out = (float*) ((uint8_t*) pa_memblock_acquire(output->memblock) + output->index);
639 data.output_frames = *out_n_frames;
640
641 data.src_ratio = (double) r->o_ss.rate / r->i_ss.rate;
642 data.end_of_input = 0;
643
644 pa_assert_se(src_process(r->src.state, &data) == 0);
645 pa_assert((unsigned) data.input_frames_used == in_n_frames);
646
647 pa_memblock_release(input->memblock);
648 pa_memblock_release(output->memblock);
649
650 *out_n_frames = data.output_frames_gen;
651 }
652
653 static void libsamplerate_update_rates(pa_resampler *r) {
654 pa_assert(r);
655
656 pa_assert_se(src_set_ratio(r->src.state, (double) r->o_ss.rate / r->i_ss.rate) == 0);
657 }
658
659 static void libsamplerate_free(pa_resampler *r) {
660 pa_assert(r);
661
662 if (r->src.state)
663 src_delete(r->src.state);
664 }
665
666 static int libsamplerate_init(pa_resampler *r) {
667 int err;
668
669 pa_assert(r);
670
671 if (!(r->src.state = src_new(r->resample_method, r->o_ss.channels, &err)))
672 return -1;
673
674 r->impl_free = libsamplerate_free;
675 r->impl_update_rates = libsamplerate_update_rates;
676 r->impl_resample = libsamplerate_resample;
677
678 return 0;
679 }
680
681 /*** speex based implementation ***/
682
683 static void speex_resample_float(pa_resampler *r, const pa_memchunk *input, unsigned in_n_frames, pa_memchunk *output, unsigned *out_n_frames) {
684 float *in, *out;
685 uint32_t inf = in_n_frames, outf = *out_n_frames;
686
687 pa_assert(r);
688 pa_assert(input);
689 pa_assert(output);
690 pa_assert(out_n_frames);
691
692 in = (float*) ((uint8_t*) pa_memblock_acquire(input->memblock) + input->index);
693 out = (float*) ((uint8_t*) pa_memblock_acquire(output->memblock) + output->index);
694
695 pa_assert_se(paspfl_resampler_process_interleaved_float(r->speex.state, in, &inf, out, &outf) == 0);
696
697 pa_memblock_release(input->memblock);
698 pa_memblock_release(output->memblock);
699
700 pa_assert(inf == in_n_frames);
701 *out_n_frames = outf;
702 }
703
704 static void speex_resample_int(pa_resampler *r, const pa_memchunk *input, unsigned in_n_frames, pa_memchunk *output, unsigned *out_n_frames) {
705 int16_t *in, *out;
706 uint32_t inf = in_n_frames, outf = *out_n_frames;
707
708 pa_assert(r);
709 pa_assert(input);
710 pa_assert(output);
711 pa_assert(out_n_frames);
712
713 in = (int16_t*) ((uint8_t*) pa_memblock_acquire(input->memblock) + input->index);
714 out = (int16_t*) ((uint8_t*) pa_memblock_acquire(output->memblock) + output->index);
715
716 pa_assert_se(paspfx_resampler_process_interleaved_int(r->speex.state, in, &inf, out, &outf) == 0);
717
718 pa_memblock_release(input->memblock);
719 pa_memblock_release(output->memblock);
720
721 pa_assert(inf == in_n_frames);
722 *out_n_frames = outf;
723 }
724
725 static void speex_update_rates(pa_resampler *r) {
726 pa_assert(r);
727
728 if (r->resample_method >= PA_RESAMPLER_SPEEX_FIXED_BASE && r->resample_method <= PA_RESAMPLER_SPEEX_FIXED_MAX)
729 pa_assert_se(paspfx_resampler_set_rate(r->speex.state, r->i_ss.rate, r->o_ss.rate) == 0);
730 else {
731 pa_assert(r->resample_method >= PA_RESAMPLER_SPEEX_FLOAT_BASE && r->resample_method <= PA_RESAMPLER_SPEEX_FLOAT_MAX);
732 pa_assert_se(paspfl_resampler_set_rate(r->speex.state, r->i_ss.rate, r->o_ss.rate) == 0);
733 }
734 }
735
736 static void speex_free(pa_resampler *r) {
737 pa_assert(r);
738
739 if (!r->speex.state)
740 return;
741
742 if (r->resample_method >= PA_RESAMPLER_SPEEX_FIXED_BASE && r->resample_method <= PA_RESAMPLER_SPEEX_FIXED_MAX)
743 paspfx_resampler_destroy(r->speex.state);
744 else {
745 pa_assert(r->resample_method >= PA_RESAMPLER_SPEEX_FLOAT_BASE && r->resample_method <= PA_RESAMPLER_SPEEX_FLOAT_MAX);
746 paspfl_resampler_destroy(r->speex.state);
747 }
748 }
749
750 static int speex_init(pa_resampler *r) {
751 int q, err;
752
753 pa_assert(r);
754
755 r->impl_free = speex_free;
756 r->impl_update_rates = speex_update_rates;
757
758 if (r->resample_method >= PA_RESAMPLER_SPEEX_FIXED_BASE && r->resample_method <= PA_RESAMPLER_SPEEX_FIXED_MAX) {
759 q = r->resample_method - PA_RESAMPLER_SPEEX_FIXED_BASE;
760
761 pa_log_info("Choosing speex quality setting %i.", q);
762
763 if (!(r->speex.state = paspfx_resampler_init(r->o_ss.channels, r->i_ss.rate, r->o_ss.rate, q, &err)))
764 return -1;
765
766 r->impl_resample = speex_resample_int;
767 } else {
768 pa_assert(r->resample_method >= PA_RESAMPLER_SPEEX_FLOAT_BASE && r->resample_method <= PA_RESAMPLER_SPEEX_FLOAT_MAX);
769 q = r->resample_method - PA_RESAMPLER_SPEEX_FLOAT_BASE;
770
771 pa_log_info("Choosing speex quality setting %i.", q);
772
773 if (!(r->speex.state = paspfl_resampler_init(r->o_ss.channels, r->i_ss.rate, r->o_ss.rate, q, &err)))
774 return -1;
775
776 r->impl_resample = speex_resample_float;
777 }
778
779 return 0;
780 }
781
782 /* Trivial implementation */
783
784 static void trivial_resample(pa_resampler *r, const pa_memchunk *input, unsigned in_n_frames, pa_memchunk *output, unsigned *out_n_frames) {
785 size_t fz;
786 unsigned o_index;
787 void *src, *dst;
788
789 pa_assert(r);
790 pa_assert(input);
791 pa_assert(output);
792 pa_assert(out_n_frames);
793
794 fz = r->w_sz * r->o_ss.channels;
795
796 src = (uint8_t*) pa_memblock_acquire(input->memblock) + input->index;
797 dst = (uint8_t*) pa_memblock_acquire(output->memblock) + output->index;
798
799 for (o_index = 0;; o_index++, r->trivial.o_counter++) {
800 unsigned j;
801
802 j = ((r->trivial.o_counter * r->i_ss.rate) / r->o_ss.rate);
803 j = j > r->trivial.i_counter ? j - r->trivial.i_counter : 0;
804
805 if (j >= in_n_frames)
806 break;
807
808 pa_assert(o_index * fz < pa_memblock_get_length(output->memblock));
809
810 oil_memcpy((uint8_t*) dst + fz * o_index,
811 (uint8_t*) src + fz * j, fz);
812 }
813
814 pa_memblock_release(input->memblock);
815 pa_memblock_release(output->memblock);
816
817 *out_n_frames = o_index;
818
819 r->trivial.i_counter += in_n_frames;
820
821 /* Normalize counters */
822 while (r->trivial.i_counter >= r->i_ss.rate) {
823 pa_assert(r->trivial.o_counter >= r->o_ss.rate);
824
825 r->trivial.i_counter -= r->i_ss.rate;
826 r->trivial.o_counter -= r->o_ss.rate;
827 }
828 }
829
830 static void trivial_update_rates(pa_resampler *r) {
831 pa_assert(r);
832
833 r->trivial.i_counter = 0;
834 r->trivial.o_counter = 0;
835 }
836
837 static int trivial_init(pa_resampler*r) {
838 pa_assert(r);
839
840 r->trivial.o_counter = r->trivial.i_counter = 0;
841
842 r->impl_resample = trivial_resample;
843 r->impl_update_rates = trivial_update_rates;
844
845 return 0;
846 }
847
848 /*** ffmpeg based implementation ***/
849
850 static void ffmpeg_resample(pa_resampler *r, const pa_memchunk *input, unsigned in_n_frames, pa_memchunk *output, unsigned *out_n_frames) {
851 unsigned used_frames = 0, c;
852
853 pa_assert(r);
854 pa_assert(input);
855 pa_assert(output);
856 pa_assert(out_n_frames);
857
858 for (c = 0; c < r->o_ss.channels; c++) {
859 unsigned u;
860 pa_memblock *b, *w;
861 int16_t *p, *t, *k, *q, *s;
862 int consumed_frames;
863 unsigned in, l;
864
865 /* Allocate a new block */
866 b = pa_memblock_new(r->mempool, r->ffmpeg.buf[c].length + in_n_frames * sizeof(int16_t));
867 p = pa_memblock_acquire(b);
868
869 /* Copy the remaining data into it */
870 l = r->ffmpeg.buf[c].length;
871 if (r->ffmpeg.buf[c].memblock) {
872 t = (int16_t*) ((uint8_t*) pa_memblock_acquire(r->ffmpeg.buf[c].memblock) + r->ffmpeg.buf[c].index);
873 memcpy(p, t, l);
874 pa_memblock_release(r->ffmpeg.buf[c].memblock);
875 pa_memblock_unref(r->ffmpeg.buf[c].memblock);
876 pa_memchunk_reset(&r->ffmpeg.buf[c]);
877 }
878
879 /* Now append the new data, splitting up channels */
880 t = ((int16_t*) ((uint8_t*) pa_memblock_acquire(input->memblock) + input->index)) + c;
881 k = (int16_t*) ((uint8_t*) p + l);
882 for (u = 0; u < in_n_frames; u++) {
883 *k = *t;
884 t += r->o_ss.channels;
885 k ++;
886 }
887 pa_memblock_release(input->memblock);
888
889 /* Calculate the resulting number of frames */
890 in = in_n_frames + l / sizeof(int16_t);
891
892 /* Allocate buffer for the result */
893 w = pa_memblock_new(r->mempool, *out_n_frames * sizeof(int16_t));
894 q = pa_memblock_acquire(w);
895
896 /* Now, resample */
897 used_frames = av_resample(r->ffmpeg.state,
898 q, p,
899 &consumed_frames,
900 in, *out_n_frames,
901 c >= (unsigned) r->o_ss.channels-1);
902
903 pa_memblock_release(b);
904
905 /* Now store the remaining samples away */
906 pa_assert(consumed_frames <= (int) in);
907 if (consumed_frames < (int) in) {
908 r->ffmpeg.buf[c].memblock = b;
909 r->ffmpeg.buf[c].index = consumed_frames * sizeof(int16_t);
910 r->ffmpeg.buf[c].length = (in - consumed_frames) * sizeof(int16_t);
911 } else
912 pa_memblock_unref(b);
913
914 /* And place the results in the output buffer */
915 s = (short*) ((uint8_t*) pa_memblock_acquire(output->memblock) + output->index) + c;
916 for (u = 0; u < used_frames; u++) {
917 *s = *q;
918 q++;
919 s += r->o_ss.channels;
920 }
921 pa_memblock_release(output->memblock);
922 pa_memblock_release(w);
923 pa_memblock_unref(w);
924 }
925
926 *out_n_frames = used_frames;
927 }
928
929 static void ffmpeg_free(pa_resampler *r) {
930 unsigned c;
931
932 pa_assert(r);
933
934 if (r->ffmpeg.state)
935 av_resample_close(r->ffmpeg.state);
936
937 for (c = 0; c < PA_ELEMENTSOF(r->ffmpeg.buf); c++)
938 if (r->ffmpeg.buf[c].memblock)
939 pa_memblock_unref(r->ffmpeg.buf[c].memblock);
940 }
941
942 static int ffmpeg_init(pa_resampler *r) {
943 unsigned c;
944
945 pa_assert(r);
946
947 /* We could probably implement different quality levels by
948 * adjusting the filter parameters here. However, ffmpeg
949 * internally only uses these hardcoded values, so let's use them
950 * here for now as well until ffmpeg makes this configurable. */
951
952 if (!(r->ffmpeg.state = av_resample_init(r->o_ss.rate, r->i_ss.rate, 16, 10, 0, 0.8)))
953 return -1;
954
955 r->impl_free = ffmpeg_free;
956 r->impl_resample = ffmpeg_resample;
957
958 for (c = 0; c < PA_ELEMENTSOF(r->ffmpeg.buf); c++)
959 pa_memchunk_reset(&r->ffmpeg.buf[c]);
960
961 return 0;
962 }