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