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