4 This file is part of PulseAudio.
6 Copyright 2004-2006 Lennart Poettering
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.
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.
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
30 #if HAVE_LIBSAMPLERATE
31 #include <samplerate.h>
34 #include <liboil/liboilfuncs.h>
35 #include <liboil/liboil.h>
37 #include <pulse/xmalloc.h>
38 #include <pulsecore/sconv.h>
39 #include <pulsecore/log.h>
40 #include <pulsecore/macro.h>
42 #include "speexwrap.h"
44 #include "ffmpeg/avcodec.h"
46 #include "resampler.h"
48 /* Number of samples of extra space we allow the resamplers to return */
49 #define EXTRA_SAMPLES 128
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
;
58 pa_memchunk buf1
, buf2
, buf3
, buf4
;
59 unsigned buf1_samples
, buf2_samples
, buf3_samples
, buf4_samples
;
61 pa_sample_format_t work_format
;
63 pa_convert_func_t to_work_format_func
;
64 pa_convert_func_t from_work_format_func
;
66 int map_table
[PA_CHANNELS_MAX
][PA_CHANNELS_MAX
];
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
);
73 struct { /* data specific to the trivial resampler */
78 #ifdef HAVE_LIBSAMPLERATE
79 struct { /* data specific to libsamplerate */
84 struct { /* data specific to speex */
85 SpeexResamplerState
* state
;
88 struct { /* data specific to ffmpeg */
89 struct AVResampleContext
*state
;
90 pa_memchunk buf
[PA_CHANNELS_MAX
];
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
);
102 static void calc_map_table(pa_resampler
*r
);
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
,
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
,
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
146 static inline size_t sample_size(pa_sample_format_t f
) {
147 pa_sample_spec ss
= {
153 return pa_sample_size(&ss
);
156 pa_resampler
* pa_resampler_new(
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
,
165 pa_resampler
*r
= NULL
;
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
);
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
;
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
;
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
;
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
;
197 if (resample_method
== PA_RESAMPLER_AUTO
)
198 resample_method
= PA_RESAMPLER_SPEEX_FLOAT_BASE
+ 3;
200 r
= pa_xnew(pa_resampler
, 1);
202 r
->resample_method
= resample_method
;
205 r
->impl_update_rates
= NULL
;
206 r
->impl_resample
= NULL
;
208 /* Fill sample specs */
215 pa_channel_map_init_auto(&r
->i_cm
, r
->i_ss
.channels
, PA_CHANNEL_MAP_DEFAULT
);
220 pa_channel_map_init_auto(&r
->o_cm
, r
->o_ss
.channels
, PA_CHANNEL_MAP_DEFAULT
);
222 r
->i_fz
= pa_frame_size(a
);
223 r
->o_fz
= pa_frame_size(b
);
225 pa_memchunk_reset(&r
->buf1
);
226 pa_memchunk_reset(&r
->buf2
);
227 pa_memchunk_reset(&r
->buf3
);
228 pa_memchunk_reset(&r
->buf4
);
230 r
->buf1_samples
= r
->buf2_samples
= r
->buf3_samples
= r
->buf4_samples
= 0;
234 pa_log_info("Using resampler '%s'", pa_resample_method_to_string(resample_method
));
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
|| resample_method
== PA_RESAMPLER_COPY
) {
241 if (r
->map_required
|| a
->format
!= b
->format
) {
243 if (a
->format
== PA_SAMPLE_S32NE
|| a
->format
== PA_SAMPLE_S32RE
||
244 a
->format
== PA_SAMPLE_FLOAT32NE
|| a
->format
== PA_SAMPLE_FLOAT32RE
||
245 b
->format
== PA_SAMPLE_S32NE
|| b
->format
== PA_SAMPLE_S32RE
||
246 b
->format
== PA_SAMPLE_FLOAT32NE
|| b
->format
== PA_SAMPLE_FLOAT32RE
)
247 r
->work_format
= PA_SAMPLE_FLOAT32NE
;
249 r
->work_format
= PA_SAMPLE_S16NE
;
252 r
->work_format
= a
->format
;
255 r
->work_format
= PA_SAMPLE_FLOAT32NE
;
257 pa_log_info("Using %s as working format.", pa_sample_format_to_string(r
->work_format
));
259 r
->w_sz
= sample_size(r
->work_format
);
261 if (r
->i_ss
.format
== r
->work_format
)
262 r
->to_work_format_func
= NULL
;
263 else if (r
->work_format
== PA_SAMPLE_FLOAT32NE
) {
264 if (!(r
->to_work_format_func
= pa_get_convert_to_float32ne_function(r
->i_ss
.format
)))
267 pa_assert(r
->work_format
== PA_SAMPLE_S16NE
);
268 if (!(r
->to_work_format_func
= pa_get_convert_to_s16ne_function(r
->i_ss
.format
)))
272 if (r
->o_ss
.format
== r
->work_format
)
273 r
->from_work_format_func
= NULL
;
274 else if (r
->work_format
== PA_SAMPLE_FLOAT32NE
) {
275 if (!(r
->from_work_format_func
= pa_get_convert_from_float32ne_function(r
->o_ss
.format
)))
278 pa_assert(r
->work_format
== PA_SAMPLE_S16NE
);
279 if (!(r
->from_work_format_func
= pa_get_convert_from_s16ne_function(r
->o_ss
.format
)))
283 /* initialize implementation */
284 if (init_table
[resample_method
](r
) < 0)
296 void pa_resampler_free(pa_resampler
*r
) {
302 if (r
->buf1
.memblock
)
303 pa_memblock_unref(r
->buf1
.memblock
);
304 if (r
->buf2
.memblock
)
305 pa_memblock_unref(r
->buf2
.memblock
);
306 if (r
->buf3
.memblock
)
307 pa_memblock_unref(r
->buf3
.memblock
);
308 if (r
->buf4
.memblock
)
309 pa_memblock_unref(r
->buf4
.memblock
);
314 void pa_resampler_set_input_rate(pa_resampler
*r
, uint32_t rate
) {
318 if (r
->i_ss
.rate
== rate
)
323 r
->impl_update_rates(r
);
326 void pa_resampler_set_output_rate(pa_resampler
*r
, uint32_t rate
) {
330 if (r
->o_ss
.rate
== rate
)
335 r
->impl_update_rates(r
);
338 size_t pa_resampler_request(pa_resampler
*r
, size_t out_length
) {
341 return (((out_length
/ r
->o_fz
)*r
->i_ss
.rate
)/r
->o_ss
.rate
) * r
->i_fz
;
344 size_t pa_resampler_max_block_size(pa_resampler
*r
) {
345 size_t block_size_max
;
351 block_size_max
= pa_mempool_block_size_max(r
->mempool
);
353 /* We deduce the "largest" sample spec we're using during the
356 if (r
->o_ss
.channels
> ss
.channels
)
357 ss
.channels
= r
->o_ss
.channels
;
359 /* We silently assume that the format enum is ordered by size */
360 if (r
->o_ss
.format
> ss
.format
)
361 ss
.format
= r
->o_ss
.format
;
362 if (r
->work_format
> ss
.format
)
363 ss
.format
= r
->work_format
;
365 if (r
->o_ss
.rate
> ss
.rate
)
366 ss
.rate
= r
->o_ss
.rate
;
368 fs
= pa_frame_size(&ss
);
370 return (((block_size_max
/fs
+ EXTRA_SAMPLES
)*r
->i_ss
.rate
)/ss
.rate
)*r
->i_fz
;
373 pa_resample_method_t
pa_resampler_get_method(pa_resampler
*r
) {
376 return r
->resample_method
;
379 static const char * const resample_methods
[] = {
380 "src-sinc-best-quality",
381 "src-sinc-medium-quality",
383 "src-zero-order-hold",
413 const char *pa_resample_method_to_string(pa_resample_method_t m
) {
415 if (m
< 0 || m
>= PA_RESAMPLER_MAX
)
418 return resample_methods
[m
];
421 int pa_resample_method_supported(pa_resample_method_t m
) {
423 if (m
< 0 || m
>= PA_RESAMPLER_MAX
)
426 #ifndef HAVE_LIBSAMPLERATE
427 if (m
<= PA_RESAMPLER_SRC_LINEAR
)
434 pa_resample_method_t
pa_parse_resample_method(const char *string
) {
435 pa_resample_method_t m
;
439 for (m
= 0; m
< PA_RESAMPLER_MAX
; m
++)
440 if (!strcmp(string
, resample_methods
[m
]))
443 if (!strcmp(string
, "speex-fixed"))
444 return PA_RESAMPLER_SPEEX_FIXED_BASE
+ 3;
446 if (!strcmp(string
, "speex-float"))
447 return PA_RESAMPLER_SPEEX_FLOAT_BASE
+ 3;
449 return PA_RESAMPLER_INVALID
;
452 static void calc_map_table(pa_resampler
*r
) {
457 if (!(r
->map_required
= (r
->i_ss
.channels
!= r
->o_ss
.channels
|| !pa_channel_map_equal(&r
->i_cm
, &r
->o_cm
))))
460 for (oc
= 0; oc
< r
->o_ss
.channels
; oc
++) {
463 for (ic
= 0; ic
< r
->i_ss
.channels
; ic
++) {
464 pa_channel_position_t a
, b
;
470 (a
== PA_CHANNEL_POSITION_MONO
&& b
== PA_CHANNEL_POSITION_LEFT
) ||
471 (a
== PA_CHANNEL_POSITION_MONO
&& b
== PA_CHANNEL_POSITION_RIGHT
) ||
472 (a
== PA_CHANNEL_POSITION_LEFT
&& b
== PA_CHANNEL_POSITION_MONO
) ||
473 (a
== PA_CHANNEL_POSITION_RIGHT
&& b
== PA_CHANNEL_POSITION_MONO
))
475 r
->map_table
[oc
][i
++] = ic
;
478 /* Add an end marker */
479 if (i
< PA_CHANNELS_MAX
)
480 r
->map_table
[oc
][i
] = -1;
484 static pa_memchunk
* convert_to_work_format(pa_resampler
*r
, pa_memchunk
*input
) {
490 pa_assert(input
->memblock
);
492 /* Convert the incoming sample into the work sample format and place them in buf1 */
494 if (!r
->to_work_format_func
|| !input
->length
)
497 n_samples
= (input
->length
/ r
->i_fz
) * r
->i_ss
.channels
;
500 r
->buf1
.length
= r
->w_sz
* n_samples
;
502 if (!r
->buf1
.memblock
|| r
->buf1_samples
< n_samples
) {
503 if (r
->buf1
.memblock
)
504 pa_memblock_unref(r
->buf1
.memblock
);
506 r
->buf1_samples
= n_samples
;
507 r
->buf1
.memblock
= pa_memblock_new(r
->mempool
, r
->buf1
.length
);
510 src
= (uint8_t*) pa_memblock_acquire(input
->memblock
) + input
->index
;
511 dst
= (uint8_t*) pa_memblock_acquire(r
->buf1
.memblock
);
513 r
->to_work_format_func(n_samples
, src
, dst
);
515 pa_memblock_release(input
->memblock
);
516 pa_memblock_release(r
->buf1
.memblock
);
521 static pa_memchunk
*remap_channels(pa_resampler
*r
, pa_memchunk
*input
) {
522 unsigned in_n_samples
, out_n_samples
, n_frames
;
529 pa_assert(input
->memblock
);
531 /* Remap channels and place the result int buf2 */
533 if (!r
->map_required
|| !input
->length
)
536 in_n_samples
= input
->length
/ r
->w_sz
;
537 n_frames
= in_n_samples
/ r
->i_ss
.channels
;
538 out_n_samples
= n_frames
* r
->o_ss
.channels
;
541 r
->buf2
.length
= r
->w_sz
* out_n_samples
;
543 if (!r
->buf2
.memblock
|| r
->buf2_samples
< out_n_samples
) {
544 if (r
->buf2
.memblock
)
545 pa_memblock_unref(r
->buf2
.memblock
);
547 r
->buf2_samples
= out_n_samples
;
548 r
->buf2
.memblock
= pa_memblock_new(r
->mempool
, r
->buf2
.length
);
551 src
= ((uint8_t*) pa_memblock_acquire(input
->memblock
) + input
->index
);
552 dst
= pa_memblock_acquire(r
->buf2
.memblock
);
554 memset(dst
, 0, r
->buf2
.length
);
556 o_skip
= r
->w_sz
* r
->o_ss
.channels
;
557 i_skip
= r
->w_sz
* r
->i_ss
.channels
;
559 switch (r
->work_format
) {
560 case PA_SAMPLE_FLOAT32NE
:
562 for (oc
= 0; oc
< r
->o_ss
.channels
; oc
++) {
564 static const float one
= 1.0;
566 for (i
= 0; i
< PA_CHANNELS_MAX
&& r
->map_table
[oc
][i
] >= 0; i
++)
568 (float*) dst
+ oc
, o_skip
,
569 (float*) dst
+ oc
, o_skip
,
570 (float*) src
+ r
->map_table
[oc
][i
], i_skip
,
577 case PA_SAMPLE_S16NE
:
579 for (oc
= 0; oc
< r
->o_ss
.channels
; oc
++) {
581 static const int16_t one
= 1;
583 for (i
= 0; i
< PA_CHANNELS_MAX
&& r
->map_table
[oc
][i
] >= 0; i
++)
585 (int16_t*) dst
+ oc
, o_skip
,
586 (int16_t*) dst
+ oc
, o_skip
,
587 (int16_t*) src
+ r
->map_table
[oc
][i
], i_skip
,
595 pa_assert_not_reached();
598 pa_memblock_release(input
->memblock
);
599 pa_memblock_release(r
->buf2
.memblock
);
601 r
->buf2
.length
= out_n_samples
* r
->w_sz
;
606 static pa_memchunk
*resample(pa_resampler
*r
, pa_memchunk
*input
) {
607 unsigned in_n_frames
, in_n_samples
;
608 unsigned out_n_frames
, out_n_samples
;
613 /* Resample the data and place the result in buf3 */
615 if (!r
->impl_resample
|| !input
->length
)
618 in_n_samples
= input
->length
/ r
->w_sz
;
619 in_n_frames
= in_n_samples
/ r
->o_ss
.channels
;
621 out_n_frames
= ((in_n_frames
*r
->o_ss
.rate
)/r
->i_ss
.rate
)+EXTRA_SAMPLES
;
622 out_n_samples
= out_n_frames
* r
->o_ss
.channels
;
625 r
->buf3
.length
= r
->w_sz
* out_n_samples
;
627 if (!r
->buf3
.memblock
|| r
->buf3_samples
< out_n_samples
) {
628 if (r
->buf3
.memblock
)
629 pa_memblock_unref(r
->buf3
.memblock
);
631 r
->buf3_samples
= out_n_samples
;
632 r
->buf3
.memblock
= pa_memblock_new(r
->mempool
, r
->buf3
.length
);
635 r
->impl_resample(r
, input
, in_n_frames
, &r
->buf3
, &out_n_frames
);
636 r
->buf3
.length
= out_n_frames
* r
->w_sz
* r
->o_ss
.channels
;
641 static pa_memchunk
*convert_from_work_format(pa_resampler
*r
, pa_memchunk
*input
) {
642 unsigned n_samples
, n_frames
;
648 /* Convert the data into the correct sample type and place the result in buf4 */
650 if (!r
->from_work_format_func
|| !input
->length
)
653 n_samples
= input
->length
/ r
->w_sz
;
654 n_frames
= n_samples
/ r
->o_ss
.channels
;
657 r
->buf4
.length
= r
->o_fz
* n_frames
;
659 if (!r
->buf4
.memblock
|| r
->buf4_samples
< n_samples
) {
660 if (r
->buf4
.memblock
)
661 pa_memblock_unref(r
->buf4
.memblock
);
663 r
->buf4_samples
= n_samples
;
664 r
->buf4
.memblock
= pa_memblock_new(r
->mempool
, r
->buf4
.length
);
667 src
= (uint8_t*) pa_memblock_acquire(input
->memblock
) + input
->index
;
668 dst
= pa_memblock_acquire(r
->buf4
.memblock
);
669 r
->from_work_format_func(n_samples
, src
, dst
);
670 pa_memblock_release(input
->memblock
);
671 pa_memblock_release(r
->buf4
.memblock
);
673 r
->buf4
.length
= r
->o_fz
* n_frames
;
678 void pa_resampler_run(pa_resampler
*r
, const pa_memchunk
*in
, pa_memchunk
*out
) {
684 pa_assert(in
->length
);
685 pa_assert(in
->memblock
);
686 pa_assert(in
->length
% r
->i_fz
== 0);
688 buf
= (pa_memchunk
*) in
;
689 buf
= convert_to_work_format(r
, buf
);
690 buf
= remap_channels(r
, buf
);
691 buf
= resample(r
, buf
);
694 buf
= convert_from_work_format(r
, buf
);
698 pa_memblock_ref(buf
->memblock
);
700 pa_memchunk_reset(buf
);
702 pa_memchunk_reset(out
);
705 /*** libsamplerate based implementation ***/
707 #ifdef HAVE_LIBSAMPLERATE
708 static void libsamplerate_resample(pa_resampler
*r
, const pa_memchunk
*input
, unsigned in_n_frames
, pa_memchunk
*output
, unsigned *out_n_frames
) {
714 pa_assert(out_n_frames
);
716 memset(&data
, 0, sizeof(data
));
718 data
.data_in
= (float*) ((uint8_t*) pa_memblock_acquire(input
->memblock
) + input
->index
);
719 data
.input_frames
= in_n_frames
;
721 data
.data_out
= (float*) ((uint8_t*) pa_memblock_acquire(output
->memblock
) + output
->index
);
722 data
.output_frames
= *out_n_frames
;
724 data
.src_ratio
= (double) r
->o_ss
.rate
/ r
->i_ss
.rate
;
725 data
.end_of_input
= 0;
727 pa_assert_se(src_process(r
->src
.state
, &data
) == 0);
728 pa_assert((unsigned) data
.input_frames_used
== in_n_frames
);
730 pa_memblock_release(input
->memblock
);
731 pa_memblock_release(output
->memblock
);
733 *out_n_frames
= data
.output_frames_gen
;
736 static void libsamplerate_update_rates(pa_resampler
*r
) {
739 pa_assert_se(src_set_ratio(r
->src
.state
, (double) r
->o_ss
.rate
/ r
->i_ss
.rate
) == 0);
742 static void libsamplerate_free(pa_resampler
*r
) {
746 src_delete(r
->src
.state
);
749 static int libsamplerate_init(pa_resampler
*r
) {
754 if (!(r
->src
.state
= src_new(r
->resample_method
, r
->o_ss
.channels
, &err
)))
757 r
->impl_free
= libsamplerate_free
;
758 r
->impl_update_rates
= libsamplerate_update_rates
;
759 r
->impl_resample
= libsamplerate_resample
;
765 /*** speex based implementation ***/
767 static void speex_resample_float(pa_resampler
*r
, const pa_memchunk
*input
, unsigned in_n_frames
, pa_memchunk
*output
, unsigned *out_n_frames
) {
769 uint32_t inf
= in_n_frames
, outf
= *out_n_frames
;
774 pa_assert(out_n_frames
);
776 in
= (float*) ((uint8_t*) pa_memblock_acquire(input
->memblock
) + input
->index
);
777 out
= (float*) ((uint8_t*) pa_memblock_acquire(output
->memblock
) + output
->index
);
779 pa_assert_se(paspfl_resampler_process_interleaved_float(r
->speex
.state
, in
, &inf
, out
, &outf
) == 0);
781 pa_memblock_release(input
->memblock
);
782 pa_memblock_release(output
->memblock
);
784 pa_assert(inf
== in_n_frames
);
785 *out_n_frames
= outf
;
788 static void speex_resample_int(pa_resampler
*r
, const pa_memchunk
*input
, unsigned in_n_frames
, pa_memchunk
*output
, unsigned *out_n_frames
) {
790 uint32_t inf
= in_n_frames
, outf
= *out_n_frames
;
795 pa_assert(out_n_frames
);
797 in
= (int16_t*) ((uint8_t*) pa_memblock_acquire(input
->memblock
) + input
->index
);
798 out
= (int16_t*) ((uint8_t*) pa_memblock_acquire(output
->memblock
) + output
->index
);
800 pa_assert_se(paspfx_resampler_process_interleaved_int(r
->speex
.state
, in
, &inf
, out
, &outf
) == 0);
802 pa_memblock_release(input
->memblock
);
803 pa_memblock_release(output
->memblock
);
805 pa_assert(inf
== in_n_frames
);
806 *out_n_frames
= outf
;
809 static void speex_update_rates(pa_resampler
*r
) {
812 if (r
->resample_method
>= PA_RESAMPLER_SPEEX_FIXED_BASE
&& r
->resample_method
<= PA_RESAMPLER_SPEEX_FIXED_MAX
)
813 pa_assert_se(paspfx_resampler_set_rate(r
->speex
.state
, r
->i_ss
.rate
, r
->o_ss
.rate
) == 0);
815 pa_assert(r
->resample_method
>= PA_RESAMPLER_SPEEX_FLOAT_BASE
&& r
->resample_method
<= PA_RESAMPLER_SPEEX_FLOAT_MAX
);
816 pa_assert_se(paspfl_resampler_set_rate(r
->speex
.state
, r
->i_ss
.rate
, r
->o_ss
.rate
) == 0);
820 static void speex_free(pa_resampler
*r
) {
826 if (r
->resample_method
>= PA_RESAMPLER_SPEEX_FIXED_BASE
&& r
->resample_method
<= PA_RESAMPLER_SPEEX_FIXED_MAX
)
827 paspfx_resampler_destroy(r
->speex
.state
);
829 pa_assert(r
->resample_method
>= PA_RESAMPLER_SPEEX_FLOAT_BASE
&& r
->resample_method
<= PA_RESAMPLER_SPEEX_FLOAT_MAX
);
830 paspfl_resampler_destroy(r
->speex
.state
);
834 static int speex_init(pa_resampler
*r
) {
839 r
->impl_free
= speex_free
;
840 r
->impl_update_rates
= speex_update_rates
;
842 if (r
->resample_method
>= PA_RESAMPLER_SPEEX_FIXED_BASE
&& r
->resample_method
<= PA_RESAMPLER_SPEEX_FIXED_MAX
) {
843 q
= r
->resample_method
- PA_RESAMPLER_SPEEX_FIXED_BASE
;
845 pa_log_info("Choosing speex quality setting %i.", q
);
847 if (!(r
->speex
.state
= paspfx_resampler_init(r
->o_ss
.channels
, r
->i_ss
.rate
, r
->o_ss
.rate
, q
, &err
)))
850 r
->impl_resample
= speex_resample_int
;
852 pa_assert(r
->resample_method
>= PA_RESAMPLER_SPEEX_FLOAT_BASE
&& r
->resample_method
<= PA_RESAMPLER_SPEEX_FLOAT_MAX
);
853 q
= r
->resample_method
- PA_RESAMPLER_SPEEX_FLOAT_BASE
;
855 pa_log_info("Choosing speex quality setting %i.", q
);
857 if (!(r
->speex
.state
= paspfl_resampler_init(r
->o_ss
.channels
, r
->i_ss
.rate
, r
->o_ss
.rate
, q
, &err
)))
860 r
->impl_resample
= speex_resample_float
;
866 /* Trivial implementation */
868 static void trivial_resample(pa_resampler
*r
, const pa_memchunk
*input
, unsigned in_n_frames
, pa_memchunk
*output
, unsigned *out_n_frames
) {
876 pa_assert(out_n_frames
);
878 fz
= r
->w_sz
* r
->o_ss
.channels
;
880 src
= (uint8_t*) pa_memblock_acquire(input
->memblock
) + input
->index
;
881 dst
= (uint8_t*) pa_memblock_acquire(output
->memblock
) + output
->index
;
883 for (o_index
= 0;; o_index
++, r
->trivial
.o_counter
++) {
886 j
= ((r
->trivial
.o_counter
* r
->i_ss
.rate
) / r
->o_ss
.rate
);
887 j
= j
> r
->trivial
.i_counter
? j
- r
->trivial
.i_counter
: 0;
889 if (j
>= in_n_frames
)
892 pa_assert(o_index
* fz
< pa_memblock_get_length(output
->memblock
));
894 oil_memcpy((uint8_t*) dst
+ fz
* o_index
,
895 (uint8_t*) src
+ fz
* j
, fz
);
898 pa_memblock_release(input
->memblock
);
899 pa_memblock_release(output
->memblock
);
901 *out_n_frames
= o_index
;
903 r
->trivial
.i_counter
+= in_n_frames
;
905 /* Normalize counters */
906 while (r
->trivial
.i_counter
>= r
->i_ss
.rate
) {
907 pa_assert(r
->trivial
.o_counter
>= r
->o_ss
.rate
);
909 r
->trivial
.i_counter
-= r
->i_ss
.rate
;
910 r
->trivial
.o_counter
-= r
->o_ss
.rate
;
914 static void trivial_update_rates(pa_resampler
*r
) {
917 r
->trivial
.i_counter
= 0;
918 r
->trivial
.o_counter
= 0;
921 static int trivial_init(pa_resampler
*r
) {
924 r
->trivial
.o_counter
= r
->trivial
.i_counter
= 0;
926 r
->impl_resample
= trivial_resample
;
927 r
->impl_update_rates
= trivial_update_rates
;
933 /*** ffmpeg based implementation ***/
935 static void ffmpeg_resample(pa_resampler
*r
, const pa_memchunk
*input
, unsigned in_n_frames
, pa_memchunk
*output
, unsigned *out_n_frames
) {
936 unsigned used_frames
= 0, c
;
941 pa_assert(out_n_frames
);
943 for (c
= 0; c
< r
->o_ss
.channels
; c
++) {
946 int16_t *p
, *t
, *k
, *q
, *s
;
950 /* Allocate a new block */
951 b
= pa_memblock_new(r
->mempool
, r
->ffmpeg
.buf
[c
].length
+ in_n_frames
* sizeof(int16_t));
952 p
= pa_memblock_acquire(b
);
954 /* Copy the remaining data into it */
955 l
= r
->ffmpeg
.buf
[c
].length
;
956 if (r
->ffmpeg
.buf
[c
].memblock
) {
957 t
= (int16_t*) ((uint8_t*) pa_memblock_acquire(r
->ffmpeg
.buf
[c
].memblock
) + r
->ffmpeg
.buf
[c
].index
);
959 pa_memblock_release(r
->ffmpeg
.buf
[c
].memblock
);
960 pa_memblock_unref(r
->ffmpeg
.buf
[c
].memblock
);
961 pa_memchunk_reset(&r
->ffmpeg
.buf
[c
]);
964 /* Now append the new data, splitting up channels */
965 t
= ((int16_t*) ((uint8_t*) pa_memblock_acquire(input
->memblock
) + input
->index
)) + c
;
966 k
= (int16_t*) ((uint8_t*) p
+ l
);
967 for (u
= 0; u
< in_n_frames
; u
++) {
969 t
+= r
->o_ss
.channels
;
972 pa_memblock_release(input
->memblock
);
974 /* Calculate the resulting number of frames */
975 in
= in_n_frames
+ l
/ sizeof(int16_t);
977 /* Allocate buffer for the result */
978 w
= pa_memblock_new(r
->mempool
, *out_n_frames
* sizeof(int16_t));
979 q
= pa_memblock_acquire(w
);
982 used_frames
= av_resample(r
->ffmpeg
.state
,
986 c
>= (unsigned) r
->o_ss
.channels
-1);
988 pa_memblock_release(b
);
990 /* Now store the remaining samples away */
991 pa_assert(consumed_frames
<= (int) in
);
992 if (consumed_frames
< (int) in
) {
993 r
->ffmpeg
.buf
[c
].memblock
= b
;
994 r
->ffmpeg
.buf
[c
].index
= consumed_frames
* sizeof(int16_t);
995 r
->ffmpeg
.buf
[c
].length
= (in
- consumed_frames
) * sizeof(int16_t);
997 pa_memblock_unref(b
);
999 /* And place the results in the output buffer */
1000 s
= (short*) ((uint8_t*) pa_memblock_acquire(output
->memblock
) + output
->index
) + c
;
1001 for (u
= 0; u
< used_frames
; u
++) {
1004 s
+= r
->o_ss
.channels
;
1006 pa_memblock_release(output
->memblock
);
1007 pa_memblock_release(w
);
1008 pa_memblock_unref(w
);
1011 *out_n_frames
= used_frames
;
1014 static void ffmpeg_free(pa_resampler
*r
) {
1019 if (r
->ffmpeg
.state
)
1020 av_resample_close(r
->ffmpeg
.state
);
1022 for (c
= 0; c
< PA_ELEMENTSOF(r
->ffmpeg
.buf
); c
++)
1023 if (r
->ffmpeg
.buf
[c
].memblock
)
1024 pa_memblock_unref(r
->ffmpeg
.buf
[c
].memblock
);
1027 static int ffmpeg_init(pa_resampler
*r
) {
1032 /* We could probably implement different quality levels by
1033 * adjusting the filter parameters here. However, ffmpeg
1034 * internally only uses these hardcoded values, so let's use them
1035 * here for now as well until ffmpeg makes this configurable. */
1037 if (!(r
->ffmpeg
.state
= av_resample_init(r
->o_ss
.rate
, r
->i_ss
.rate
, 16, 10, 0, 0.8)))
1040 r
->impl_free
= ffmpeg_free
;
1041 r
->impl_resample
= ffmpeg_resample
;
1043 for (c
= 0; c
< PA_ELEMENTSOF(r
->ffmpeg
.buf
); c
++)
1044 pa_memchunk_reset(&r
->ffmpeg
.buf
[c
]);
1049 /*** copy (noop) implementation ***/
1051 static int copy_init(pa_resampler
*r
) {
1054 pa_assert(r
->o_ss
.rate
== r
->i_ss
.rate
);
1056 r
->impl_free
= NULL
;
1057 r
->impl_resample
= NULL
;
1058 r
->impl_update_rates
= NULL
;