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