]> code.delx.au - pulseaudio/blob - src/pulsecore/resampler.c
add makefiles to speex/ and ffmpeg/ to easy compilation from emacs
[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 unsigned initial_i_rate, initial_o_rate;
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 if (a->format == PA_SAMPLE_FLOAT32LE || a->format == PA_SAMPLE_FLOAT32BE ||
165 b->format == PA_SAMPLE_FLOAT32LE || b->format == PA_SAMPLE_FLOAT32BE)
166 resample_method = PA_RESAMPLER_SPEEX_FLOAT_BASE + 0;
167 else
168 resample_method = PA_RESAMPLER_SPEEX_FIXED_BASE + 0;
169 }
170
171 r = pa_xnew(pa_resampler, 1);
172 r->mempool = pool;
173 r->resample_method = resample_method;
174
175 r->impl_free = NULL;
176 r->impl_update_rates = NULL;
177 r->impl_resample = NULL;
178
179 /* Fill sample specs */
180 r->i_ss = *a;
181 r->o_ss = *b;
182
183 if (am)
184 r->i_cm = *am;
185 else
186 pa_channel_map_init_auto(&r->i_cm, r->i_ss.channels, PA_CHANNEL_MAP_DEFAULT);
187
188 if (bm)
189 r->o_cm = *bm;
190 else
191 pa_channel_map_init_auto(&r->o_cm, r->o_ss.channels, PA_CHANNEL_MAP_DEFAULT);
192
193 r->i_fz = pa_frame_size(a);
194 r->o_fz = pa_frame_size(b);
195
196 pa_memchunk_reset(&r->buf1);
197 pa_memchunk_reset(&r->buf2);
198 pa_memchunk_reset(&r->buf3);
199 pa_memchunk_reset(&r->buf4);
200
201 r->buf1_samples = r->buf2_samples = r->buf3_samples = r->buf4_samples = 0;
202
203 calc_map_table(r);
204
205 pa_log_info("Using resampler '%s'", pa_resample_method_to_string(resample_method));
206
207 if ((resample_method >= PA_RESAMPLER_SPEEX_FIXED_BASE && resample_method <= PA_RESAMPLER_SPEEX_FIXED_MAX) ||
208 (resample_method == PA_RESAMPLER_FFMPEG))
209 r->work_format = PA_SAMPLE_S16NE;
210 else if (resample_method == PA_RESAMPLER_TRIVIAL) {
211
212 if (r->map_required || a->format != b->format) {
213
214 if (a->format == PA_SAMPLE_FLOAT32NE || a->format == PA_SAMPLE_FLOAT32RE)
215 r->work_format = PA_SAMPLE_FLOAT32NE;
216 else
217 r->work_format = PA_SAMPLE_S16NE;
218
219 } else
220 r->work_format = a->format;
221
222 } else
223 r->work_format = PA_SAMPLE_FLOAT32NE;
224
225 r->w_sz = sample_size(r->work_format);
226
227 if (r->i_ss.format == r->work_format)
228 r->to_work_format_func = NULL;
229 else if (r->work_format == PA_SAMPLE_FLOAT32NE) {
230 if (!(r->to_work_format_func = pa_get_convert_to_float32ne_function(r->i_ss.format)))
231 goto fail;
232 } else {
233 pa_assert(r->work_format == PA_SAMPLE_S16NE);
234 if (!(r->to_work_format_func = pa_get_convert_to_s16ne_function(r->i_ss.format)))
235 goto fail;
236 }
237
238 if (r->o_ss.format == r->work_format)
239 r->from_work_format_func = NULL;
240 else if (r->work_format == PA_SAMPLE_FLOAT32NE) {
241 if (!(r->from_work_format_func = pa_get_convert_from_float32ne_function(r->o_ss.format)))
242 goto fail;
243 } else {
244 pa_assert(r->work_format == PA_SAMPLE_S16NE);
245 if (!(r->from_work_format_func = pa_get_convert_from_s16ne_function(r->o_ss.format)))
246 goto fail;
247 }
248
249 /* initialize implementation */
250 if (init_table[resample_method](r) < 0)
251 goto fail;
252
253 return r;
254
255 fail:
256 if (r)
257 pa_xfree(r);
258
259 return NULL;
260 }
261
262 void pa_resampler_free(pa_resampler *r) {
263 pa_assert(r);
264
265 if (r->impl_free)
266 r->impl_free(r);
267
268 if (r->buf1.memblock)
269 pa_memblock_unref(r->buf1.memblock);
270 if (r->buf2.memblock)
271 pa_memblock_unref(r->buf2.memblock);
272 if (r->buf3.memblock)
273 pa_memblock_unref(r->buf3.memblock);
274 if (r->buf4.memblock)
275 pa_memblock_unref(r->buf4.memblock);
276
277 pa_xfree(r);
278 }
279
280 void pa_resampler_set_input_rate(pa_resampler *r, uint32_t rate) {
281 pa_assert(r);
282 pa_assert(rate > 0);
283
284 if (r->i_ss.rate == rate)
285 return;
286
287 r->i_ss.rate = rate;
288
289 r->impl_update_rates(r);
290 }
291
292 void pa_resampler_set_output_rate(pa_resampler *r, uint32_t rate) {
293 pa_assert(r);
294 pa_assert(rate > 0);
295
296 if (r->o_ss.rate == rate)
297 return;
298
299 r->o_ss.rate = rate;
300
301 r->impl_update_rates(r);
302 }
303
304 size_t pa_resampler_request(pa_resampler *r, size_t out_length) {
305 pa_assert(r);
306
307 return (((out_length / r->o_fz)*r->i_ss.rate)/r->o_ss.rate) * r->i_fz;
308 }
309
310 pa_resample_method_t pa_resampler_get_method(pa_resampler *r) {
311 pa_assert(r);
312
313 return r->resample_method;
314 }
315
316 static const char * const resample_methods[] = {
317 "src-sinc-best-quality",
318 "src-sinc-medium-quality",
319 "src-sinc-fastest",
320 "src-zero-order-hold",
321 "src-linear",
322 "trivial",
323 "speex-float-0",
324 "speex-float-1",
325 "speex-float-2",
326 "speex-float-3",
327 "speex-float-4",
328 "speex-float-5",
329 "speex-float-6",
330 "speex-float-7",
331 "speex-float-8",
332 "speex-float-9",
333 "speex-float-10",
334 "speex-fixed-0",
335 "speex-fixed-1",
336 "speex-fixed-2",
337 "speex-fixed-3",
338 "speex-fixed-4",
339 "speex-fixed-5",
340 "speex-fixed-6",
341 "speex-fixed-7",
342 "speex-fixed-8",
343 "speex-fixed-9",
344 "speex-fixed-10",
345 "ffmpeg",
346 "auto"
347 };
348
349 const char *pa_resample_method_to_string(pa_resample_method_t m) {
350
351 if (m < 0 || m >= PA_RESAMPLER_MAX)
352 return NULL;
353
354 return resample_methods[m];
355 }
356
357 pa_resample_method_t pa_parse_resample_method(const char *string) {
358 pa_resample_method_t m;
359
360 pa_assert(string);
361
362 for (m = 0; m < PA_RESAMPLER_MAX; m++)
363 if (!strcmp(string, resample_methods[m]))
364 return m;
365
366 if (!strcmp(string, "speex-fixed"))
367 return PA_RESAMPLER_SPEEX_FIXED_BASE + 0;
368
369 if (!strcmp(string, "speex-float"))
370 return PA_RESAMPLER_SPEEX_FLOAT_BASE + 0;
371
372 return PA_RESAMPLER_INVALID;
373 }
374
375 static void calc_map_table(pa_resampler *r) {
376 unsigned oc;
377
378 pa_assert(r);
379
380 if (!(r->map_required = (r->i_ss.channels != r->o_ss.channels || !pa_channel_map_equal(&r->i_cm, &r->o_cm))))
381 return;
382
383 for (oc = 0; oc < r->o_ss.channels; oc++) {
384 unsigned ic, i = 0;
385
386 for (ic = 0; ic < r->i_ss.channels; ic++) {
387 pa_channel_position_t a, b;
388
389 a = r->i_cm.map[ic];
390 b = r->o_cm.map[oc];
391
392 if (a == b ||
393 (a == PA_CHANNEL_POSITION_MONO && b == PA_CHANNEL_POSITION_LEFT) ||
394 (a == PA_CHANNEL_POSITION_MONO && b == PA_CHANNEL_POSITION_RIGHT) ||
395 (a == PA_CHANNEL_POSITION_LEFT && b == PA_CHANNEL_POSITION_MONO) ||
396 (a == PA_CHANNEL_POSITION_RIGHT && b == PA_CHANNEL_POSITION_MONO))
397
398 r->map_table[oc][i++] = ic;
399 }
400
401 /* Add an end marker */
402 if (i < PA_CHANNELS_MAX)
403 r->map_table[oc][i] = -1;
404 }
405 }
406
407 static pa_memchunk* convert_to_work_format(pa_resampler *r, pa_memchunk *input) {
408 unsigned n_samples;
409 void *src, *dst;
410
411 pa_assert(r);
412 pa_assert(input);
413 pa_assert(input->memblock);
414
415 /* Convert the incoming sample into the work sample format and place them in buf1 */
416
417 if (!r->to_work_format_func || !input->length)
418 return input;
419
420 n_samples = (input->length / r->i_fz) * r->i_ss.channels;
421
422 r->buf1.index = 0;
423 r->buf1.length = r->w_sz * n_samples;
424
425 if (!r->buf1.memblock || r->buf1_samples < n_samples) {
426 if (r->buf1.memblock)
427 pa_memblock_unref(r->buf1.memblock);
428
429 r->buf1_samples = n_samples;
430 r->buf1.memblock = pa_memblock_new(r->mempool, r->buf1.length);
431 }
432
433 src = (uint8_t*) pa_memblock_acquire(input->memblock) + input->index;
434 dst = (uint8_t*) pa_memblock_acquire(r->buf1.memblock);
435
436 r->to_work_format_func(n_samples, src, dst);
437
438 pa_memblock_release(input->memblock);
439 pa_memblock_release(r->buf1.memblock);
440
441 return &r->buf1;
442 }
443
444 static pa_memchunk *remap_channels(pa_resampler *r, pa_memchunk *input) {
445 unsigned in_n_samples, out_n_samples, n_frames;
446 int i_skip, o_skip;
447 unsigned oc;
448 void *src, *dst;
449
450 pa_assert(r);
451 pa_assert(input);
452 pa_assert(input->memblock);
453
454 /* Remap channels and place the result int buf2 */
455
456 if (!r->map_required || !input->length)
457 return input;
458
459 in_n_samples = input->length / r->w_sz;
460 n_frames = in_n_samples / r->i_ss.channels;
461 out_n_samples = n_frames * r->o_ss.channels;
462
463 r->buf2.index = 0;
464 r->buf2.length = r->w_sz * out_n_samples;
465
466 if (!r->buf2.memblock || r->buf2_samples < out_n_samples) {
467 if (r->buf2.memblock)
468 pa_memblock_unref(r->buf2.memblock);
469
470 r->buf2_samples = out_n_samples;
471 r->buf2.memblock = pa_memblock_new(r->mempool, r->buf2.length);
472 }
473
474 src = ((uint8_t*) pa_memblock_acquire(input->memblock) + input->index);
475 dst = pa_memblock_acquire(r->buf2.memblock);
476
477 memset(dst, 0, r->buf2.length);
478
479 o_skip = r->w_sz * r->o_ss.channels;
480 i_skip = r->w_sz * r->i_ss.channels;
481
482 switch (r->work_format) {
483 case PA_SAMPLE_FLOAT32NE:
484
485 for (oc = 0; oc < r->o_ss.channels; oc++) {
486 unsigned i;
487 static const float one = 1.0;
488
489 for (i = 0; i < PA_CHANNELS_MAX && r->map_table[oc][i] >= 0; i++)
490 oil_vectoradd_f32(
491 (float*) dst + oc, o_skip,
492 (float*) dst + oc, o_skip,
493 (float*) src + r->map_table[oc][i], i_skip,
494 n_frames,
495 &one, &one);
496 }
497
498 break;
499
500 case PA_SAMPLE_S16NE:
501
502 for (oc = 0; oc < r->o_ss.channels; oc++) {
503 unsigned i;
504 static const int16_t one = 1;
505
506 for (i = 0; i < PA_CHANNELS_MAX && r->map_table[oc][i] >= 0; i++)
507 oil_vectoradd_s16(
508 (int16_t*) dst + oc, o_skip,
509 (int16_t*) dst + oc, o_skip,
510 (int16_t*) src + r->map_table[oc][i], i_skip,
511 n_frames,
512 &one, &one);
513 }
514
515 break;
516
517 default:
518 pa_assert_not_reached();
519 }
520
521 pa_memblock_release(input->memblock);
522 pa_memblock_release(r->buf2.memblock);
523
524 r->buf2.length = out_n_samples * r->w_sz;
525
526 return &r->buf2;
527 }
528
529 static pa_memchunk *resample(pa_resampler *r, pa_memchunk *input) {
530 unsigned in_n_frames, in_n_samples;
531 unsigned out_n_frames, out_n_samples;
532
533 pa_assert(r);
534 pa_assert(input);
535
536 /* Resample the data and place the result in buf3 */
537
538 if (!r->impl_resample || !input->length)
539 return input;
540
541 in_n_samples = input->length / r->w_sz;
542 in_n_frames = in_n_samples / r->o_ss.channels;
543
544 out_n_frames = ((in_n_frames*r->o_ss.rate)/r->i_ss.rate)+1024;
545 out_n_samples = out_n_frames * r->o_ss.channels;
546
547 r->buf3.index = 0;
548 r->buf3.length = r->w_sz * out_n_samples;
549
550 if (!r->buf3.memblock || r->buf3_samples < out_n_samples) {
551 if (r->buf3.memblock)
552 pa_memblock_unref(r->buf3.memblock);
553
554 r->buf3_samples = out_n_samples;
555 r->buf3.memblock = pa_memblock_new(r->mempool, r->buf3.length);
556 }
557
558 r->impl_resample(r, input, in_n_frames, &r->buf3, &out_n_frames);
559 r->buf3.length = out_n_frames * r->w_sz * r->o_ss.channels;
560
561 return &r->buf3;
562 }
563
564 static pa_memchunk *convert_from_work_format(pa_resampler *r, pa_memchunk *input) {
565 unsigned n_samples, n_frames;
566 void *src, *dst;
567
568 pa_assert(r);
569 pa_assert(input);
570
571 /* Convert the data into the correct sample type and place the result in buf4 */
572
573 if (!r->from_work_format_func || !input->length)
574 return input;
575
576 n_samples = input->length / r->w_sz;
577 n_frames = n_samples / r->o_ss.channels;
578
579 r->buf4.index = 0;
580 r->buf4.length = r->o_fz * n_frames;
581
582 if (!r->buf4.memblock || r->buf4_samples < n_samples) {
583 if (r->buf4.memblock)
584 pa_memblock_unref(r->buf4.memblock);
585
586 r->buf4_samples = n_samples;
587 r->buf4.memblock = pa_memblock_new(r->mempool, r->buf4.length);
588 }
589
590 src = (uint8_t*) pa_memblock_acquire(input->memblock) + input->index;
591 dst = pa_memblock_acquire(r->buf4.memblock);
592 r->from_work_format_func(n_samples, src, dst);
593 pa_memblock_release(input->memblock);
594 pa_memblock_release(r->buf4.memblock);
595
596 r->buf4.length = r->o_fz * n_frames;
597
598 return &r->buf4;
599 }
600
601 void pa_resampler_run(pa_resampler *r, const pa_memchunk *in, pa_memchunk *out) {
602 pa_memchunk *buf;
603
604 pa_assert(r);
605 pa_assert(in);
606 pa_assert(out);
607 pa_assert(in->length);
608 pa_assert(in->memblock);
609 pa_assert(in->length % r->i_fz == 0);
610
611 buf = (pa_memchunk*) in;
612 buf = convert_to_work_format(r, buf);
613 buf = remap_channels(r, buf);
614 buf = resample(r, buf);
615
616 if (buf->length) {
617 buf = convert_from_work_format(r, buf);
618 *out = *buf;
619
620 if (buf == in)
621 pa_memblock_ref(buf->memblock);
622 else
623 pa_memchunk_reset(buf);
624 } else
625 pa_memchunk_reset(out);
626 }
627
628 /*** libsamplerate based implementation ***/
629
630 static void libsamplerate_resample(pa_resampler *r, const pa_memchunk *input, unsigned in_n_frames, pa_memchunk *output, unsigned *out_n_frames) {
631 SRC_DATA data;
632
633 pa_assert(r);
634 pa_assert(input);
635 pa_assert(output);
636 pa_assert(out_n_frames);
637
638 memset(&data, 0, sizeof(data));
639
640 data.data_in = (float*) ((uint8_t*) pa_memblock_acquire(input->memblock) + input->index);
641 data.input_frames = in_n_frames;
642
643 data.data_out = (float*) ((uint8_t*) pa_memblock_acquire(output->memblock) + output->index);
644 data.output_frames = *out_n_frames;
645
646 data.src_ratio = (double) r->o_ss.rate / r->i_ss.rate;
647 data.end_of_input = 0;
648
649 pa_assert_se(src_process(r->src.state, &data) == 0);
650 pa_assert((unsigned) data.input_frames_used == in_n_frames);
651
652 pa_memblock_release(input->memblock);
653 pa_memblock_release(output->memblock);
654
655 *out_n_frames = data.output_frames_gen;
656 }
657
658 static void libsamplerate_update_rates(pa_resampler *r) {
659 pa_assert(r);
660
661 pa_assert_se(src_set_ratio(r->src.state, (double) r->o_ss.rate / r->i_ss.rate) == 0);
662 }
663
664 static void libsamplerate_free(pa_resampler *r) {
665 pa_assert(r);
666
667 if (r->src.state)
668 src_delete(r->src.state);
669 }
670
671 static int libsamplerate_init(pa_resampler *r) {
672 int err;
673
674 pa_assert(r);
675
676 if (!(r->src.state = src_new(r->resample_method, r->o_ss.channels, &err)))
677 return -1;
678
679 r->impl_free = libsamplerate_free;
680 r->impl_update_rates = libsamplerate_update_rates;
681 r->impl_resample = libsamplerate_resample;
682
683 return 0;
684 }
685
686 /*** speex based implementation ***/
687
688 static void speex_resample_float(pa_resampler *r, const pa_memchunk *input, unsigned in_n_frames, pa_memchunk *output, unsigned *out_n_frames) {
689 float *in, *out;
690 uint32_t inf = in_n_frames, outf = *out_n_frames;
691
692 pa_assert(r);
693 pa_assert(input);
694 pa_assert(output);
695 pa_assert(out_n_frames);
696
697 in = (float*) ((uint8_t*) pa_memblock_acquire(input->memblock) + input->index);
698 out = (float*) ((uint8_t*) pa_memblock_acquire(output->memblock) + output->index);
699
700 pa_assert_se(paspfl_resampler_process_interleaved_float(r->speex.state, in, &inf, out, &outf) == 0);
701
702 pa_memblock_release(input->memblock);
703 pa_memblock_release(output->memblock);
704
705 pa_assert(inf == in_n_frames);
706 *out_n_frames = outf;
707 }
708
709 static void speex_resample_int(pa_resampler *r, const pa_memchunk *input, unsigned in_n_frames, pa_memchunk *output, unsigned *out_n_frames) {
710 int16_t *in, *out;
711 uint32_t inf = in_n_frames, outf = *out_n_frames;
712
713 pa_assert(r);
714 pa_assert(input);
715 pa_assert(output);
716 pa_assert(out_n_frames);
717
718 in = (int16_t*) ((uint8_t*) pa_memblock_acquire(input->memblock) + input->index);
719 out = (int16_t*) ((uint8_t*) pa_memblock_acquire(output->memblock) + output->index);
720
721 pa_assert_se(paspfx_resampler_process_interleaved_int(r->speex.state, in, &inf, out, &outf) == 0);
722
723 pa_memblock_release(input->memblock);
724 pa_memblock_release(output->memblock);
725
726 pa_assert(inf == in_n_frames);
727 *out_n_frames = outf;
728 }
729
730 static void speex_update_rates(pa_resampler *r) {
731 pa_assert(r);
732
733 if (r->resample_method >= PA_RESAMPLER_SPEEX_FIXED_BASE && r->resample_method <= PA_RESAMPLER_SPEEX_FIXED_MAX)
734 pa_assert_se(paspfx_resampler_set_rate(r->speex.state, r->i_ss.rate, r->o_ss.rate) == 0);
735 else {
736 pa_assert(r->resample_method >= PA_RESAMPLER_SPEEX_FLOAT_BASE && r->resample_method <= PA_RESAMPLER_SPEEX_FLOAT_MAX);
737 pa_assert_se(paspfl_resampler_set_rate(r->speex.state, r->i_ss.rate, r->o_ss.rate) == 0);
738 }
739 }
740
741 static void speex_free(pa_resampler *r) {
742 pa_assert(r);
743
744 if (r->speex.state) {
745 if (r->resample_method >= PA_RESAMPLER_SPEEX_FIXED_BASE && r->resample_method <= PA_RESAMPLER_SPEEX_FIXED_MAX)
746 paspfx_resampler_destroy(r->speex.state);
747 else {
748 pa_assert(r->resample_method >= PA_RESAMPLER_SPEEX_FLOAT_BASE && r->resample_method <= PA_RESAMPLER_SPEEX_FLOAT_MAX);
749 paspfl_resampler_destroy(r->speex.state);
750 }
751 }
752 }
753
754 static int speex_init(pa_resampler *r) {
755 int q, err;
756
757 pa_assert(r);
758
759 r->impl_free = speex_free;
760 r->impl_update_rates = speex_update_rates;
761
762 if (r->resample_method >= PA_RESAMPLER_SPEEX_FIXED_BASE && r->resample_method <= PA_RESAMPLER_SPEEX_FIXED_MAX) {
763 q = r->resample_method - PA_RESAMPLER_SPEEX_FIXED_BASE;
764 r->impl_resample = speex_resample_int;
765
766 if (!(r->speex.state = paspfx_resampler_init(r->o_ss.channels, r->i_ss.rate, r->o_ss.rate, q, &err)))
767 return -1;
768
769 } else {
770 pa_assert(r->resample_method >= PA_RESAMPLER_SPEEX_FLOAT_BASE && r->resample_method <= PA_RESAMPLER_SPEEX_FLOAT_MAX);
771 q = r->resample_method - PA_RESAMPLER_SPEEX_FLOAT_BASE;
772 r->impl_resample = speex_resample_float;
773
774 if (!(r->speex.state = paspfl_resampler_init(r->o_ss.channels, r->i_ss.rate, r->o_ss.rate, q, &err)))
775 return -1;
776 }
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 short *src, *dst;
852 int consumed;
853 int c;
854
855 pa_assert(r);
856 pa_assert(input);
857 pa_assert(output);
858 pa_assert(out_n_frames);
859
860 src = (short*) ((uint8_t*) pa_memblock_acquire(input->memblock) + input->index);
861 dst = (short*) ((uint8_t*) pa_memblock_acquire(output->memblock) + output->index);
862
863 for (c = 0; c < r->o_ss.channels; c++)
864 *out_n_frames = av_resample(r->ffmpeg.state,
865 dst + r->w_sz*c,
866 src + r->w_sz*c,
867 &consumed,
868 in_n_frames, *out_n_frames,
869 c >= r->o_ss.channels-1);
870
871 pa_assert(*out_n_frames > 0);
872 pa_assert(consumed == in_n_frames);
873
874 pa_memblock_release(input->memblock);
875 pa_memblock_release(output->memblock);
876 }
877
878 static void ffmpeg_free(pa_resampler *r) {
879 pa_assert(r);
880
881 if (r->ffmpeg.state)
882 av_resample_close(r->ffmpeg.state);
883 }
884
885 static int ffmpeg_init(pa_resampler *r) {
886 pa_assert(r);
887
888 /* We could probably implement different quality levels by
889 * adjusting the filter parameters here. However, ffmpeg
890 * internally only uses these hardcoded values, so let's use them
891 * here for now as well until ffmpeg makes this configurable. */
892
893 if (!(r->ffmpeg.state = av_resample_init(r->o_ss.rate, r->i_ss.rate, 16, 10, 0, 0.8)))
894 return -1;
895
896 r->impl_free = ffmpeg_free;
897 r->impl_resample = ffmpeg_resample;
898
899 return 0;
900 }