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>
41 #include <pulsecore/strbuf.h>
43 #include "speexwrap.h"
45 #include "ffmpeg/avcodec.h"
47 #include "resampler.h"
49 /* Number of samples of extra space we allow the resamplers to return */
50 #define EXTRA_SAMPLES 128
53 pa_resample_method_t method
;
54 pa_resample_flags_t flags
;
56 pa_sample_spec i_ss
, o_ss
;
57 pa_channel_map i_cm
, o_cm
;
58 size_t i_fz
, o_fz
, w_sz
;
61 pa_memchunk buf1
, buf2
, buf3
, buf4
;
62 unsigned buf1_samples
, buf2_samples
, buf3_samples
, buf4_samples
;
64 pa_sample_format_t work_format
;
66 pa_convert_func_t to_work_format_func
;
67 pa_convert_func_t from_work_format_func
;
69 float map_table
[PA_CHANNELS_MAX
][PA_CHANNELS_MAX
];
70 pa_bool_t map_required
;
72 void (*impl_free
)(pa_resampler
*r
);
73 void (*impl_update_rates
)(pa_resampler
*r
);
74 void (*impl_resample
)(pa_resampler
*r
, const pa_memchunk
*in
, unsigned in_samples
, pa_memchunk
*out
, unsigned *out_samples
);
76 struct { /* data specific to the trivial resampler */
81 #ifdef HAVE_LIBSAMPLERATE
82 struct { /* data specific to libsamplerate */
87 struct { /* data specific to speex */
88 SpeexResamplerState
* state
;
91 struct { /* data specific to ffmpeg */
92 struct AVResampleContext
*state
;
93 pa_memchunk buf
[PA_CHANNELS_MAX
];
97 static int copy_init(pa_resampler
*r
);
98 static int trivial_init(pa_resampler
*r
);
99 static int speex_init(pa_resampler
*r
);
100 static int ffmpeg_init(pa_resampler
*r
);
101 #ifdef HAVE_LIBSAMPLERATE
102 static int libsamplerate_init(pa_resampler
*r
);
105 static void calc_map_table(pa_resampler
*r
);
107 static int (* const init_table
[])(pa_resampler
*r
) = {
108 #ifdef HAVE_LIBSAMPLERATE
109 [PA_RESAMPLER_SRC_SINC_BEST_QUALITY
] = libsamplerate_init
,
110 [PA_RESAMPLER_SRC_SINC_MEDIUM_QUALITY
] = libsamplerate_init
,
111 [PA_RESAMPLER_SRC_SINC_FASTEST
] = libsamplerate_init
,
112 [PA_RESAMPLER_SRC_ZERO_ORDER_HOLD
] = libsamplerate_init
,
113 [PA_RESAMPLER_SRC_LINEAR
] = libsamplerate_init
,
115 [PA_RESAMPLER_SRC_SINC_BEST_QUALITY
] = NULL
,
116 [PA_RESAMPLER_SRC_SINC_MEDIUM_QUALITY
] = NULL
,
117 [PA_RESAMPLER_SRC_SINC_FASTEST
] = NULL
,
118 [PA_RESAMPLER_SRC_ZERO_ORDER_HOLD
] = NULL
,
119 [PA_RESAMPLER_SRC_LINEAR
] = NULL
,
121 [PA_RESAMPLER_TRIVIAL
] = trivial_init
,
122 [PA_RESAMPLER_SPEEX_FLOAT_BASE
+0] = speex_init
,
123 [PA_RESAMPLER_SPEEX_FLOAT_BASE
+1] = speex_init
,
124 [PA_RESAMPLER_SPEEX_FLOAT_BASE
+2] = speex_init
,
125 [PA_RESAMPLER_SPEEX_FLOAT_BASE
+3] = speex_init
,
126 [PA_RESAMPLER_SPEEX_FLOAT_BASE
+4] = speex_init
,
127 [PA_RESAMPLER_SPEEX_FLOAT_BASE
+5] = speex_init
,
128 [PA_RESAMPLER_SPEEX_FLOAT_BASE
+6] = speex_init
,
129 [PA_RESAMPLER_SPEEX_FLOAT_BASE
+7] = speex_init
,
130 [PA_RESAMPLER_SPEEX_FLOAT_BASE
+8] = speex_init
,
131 [PA_RESAMPLER_SPEEX_FLOAT_BASE
+9] = speex_init
,
132 [PA_RESAMPLER_SPEEX_FLOAT_BASE
+10] = speex_init
,
133 [PA_RESAMPLER_SPEEX_FIXED_BASE
+0] = speex_init
,
134 [PA_RESAMPLER_SPEEX_FIXED_BASE
+1] = speex_init
,
135 [PA_RESAMPLER_SPEEX_FIXED_BASE
+2] = speex_init
,
136 [PA_RESAMPLER_SPEEX_FIXED_BASE
+3] = speex_init
,
137 [PA_RESAMPLER_SPEEX_FIXED_BASE
+4] = speex_init
,
138 [PA_RESAMPLER_SPEEX_FIXED_BASE
+5] = speex_init
,
139 [PA_RESAMPLER_SPEEX_FIXED_BASE
+6] = speex_init
,
140 [PA_RESAMPLER_SPEEX_FIXED_BASE
+7] = speex_init
,
141 [PA_RESAMPLER_SPEEX_FIXED_BASE
+8] = speex_init
,
142 [PA_RESAMPLER_SPEEX_FIXED_BASE
+9] = speex_init
,
143 [PA_RESAMPLER_SPEEX_FIXED_BASE
+10] = speex_init
,
144 [PA_RESAMPLER_FFMPEG
] = ffmpeg_init
,
145 [PA_RESAMPLER_AUTO
] = NULL
,
146 [PA_RESAMPLER_COPY
] = copy_init
149 static inline size_t sample_size(pa_sample_format_t f
) {
150 pa_sample_spec ss
= {
156 return pa_sample_size(&ss
);
159 pa_resampler
* pa_resampler_new(
161 const pa_sample_spec
*a
,
162 const pa_channel_map
*am
,
163 const pa_sample_spec
*b
,
164 const pa_channel_map
*bm
,
165 pa_resample_method_t method
,
166 pa_resample_flags_t flags
) {
168 pa_resampler
*r
= NULL
;
173 pa_assert(pa_sample_spec_valid(a
));
174 pa_assert(pa_sample_spec_valid(b
));
175 pa_assert(method
>= 0);
176 pa_assert(method
< PA_RESAMPLER_MAX
);
180 if (!(flags
& PA_RESAMPLER_VARIABLE_RATE
) && a
->rate
== b
->rate
) {
181 pa_log_info("Forcing resampler 'copy', because of fixed, identical sample rates.");
182 method
= PA_RESAMPLER_COPY
;
185 if (!pa_resample_method_supported(method
)) {
186 pa_log_warn("Support for resampler '%s' not compiled in, reverting to 'auto'.", pa_resample_method_to_string(method
));
187 method
= PA_RESAMPLER_AUTO
;
190 if (method
== PA_RESAMPLER_FFMPEG
&& (flags
& PA_RESAMPLER_VARIABLE_RATE
)) {
191 pa_log_info("Resampler 'ffmpeg' cannot do variable rate, reverting to resampler 'auto'.");
192 method
= PA_RESAMPLER_AUTO
;
195 if (method
== PA_RESAMPLER_COPY
&& ((flags
& PA_RESAMPLER_VARIABLE_RATE
) || a
->rate
!= b
->rate
)) {
196 pa_log_info("Resampler 'copy' cannot change sampling rate, reverting to resampler 'auto'.");
197 method
= PA_RESAMPLER_AUTO
;
200 if (method
== PA_RESAMPLER_AUTO
)
201 method
= PA_RESAMPLER_SPEEX_FLOAT_BASE
+ 3;
203 r
= pa_xnew(pa_resampler
, 1);
209 r
->impl_update_rates
= NULL
;
210 r
->impl_resample
= NULL
;
212 /* Fill sample specs */
218 else if (!pa_channel_map_init_auto(&r
->i_cm
, r
->i_ss
.channels
, PA_CHANNEL_MAP_DEFAULT
))
223 else if (!pa_channel_map_init_auto(&r
->o_cm
, r
->o_ss
.channels
, PA_CHANNEL_MAP_DEFAULT
))
226 r
->i_fz
= pa_frame_size(a
);
227 r
->o_fz
= pa_frame_size(b
);
229 pa_memchunk_reset(&r
->buf1
);
230 pa_memchunk_reset(&r
->buf2
);
231 pa_memchunk_reset(&r
->buf3
);
232 pa_memchunk_reset(&r
->buf4
);
234 r
->buf1_samples
= r
->buf2_samples
= r
->buf3_samples
= r
->buf4_samples
= 0;
238 pa_log_info("Using resampler '%s'", pa_resample_method_to_string(method
));
240 if ((method
>= PA_RESAMPLER_SPEEX_FIXED_BASE
&& method
<= PA_RESAMPLER_SPEEX_FIXED_MAX
) ||
241 (method
== PA_RESAMPLER_FFMPEG
))
242 r
->work_format
= PA_SAMPLE_S16NE
;
243 else if (method
== PA_RESAMPLER_TRIVIAL
|| method
== PA_RESAMPLER_COPY
) {
245 if (r
->map_required
|| a
->format
!= b
->format
) {
247 if (a
->format
== PA_SAMPLE_S32NE
|| a
->format
== PA_SAMPLE_S32RE
||
248 a
->format
== PA_SAMPLE_FLOAT32NE
|| a
->format
== PA_SAMPLE_FLOAT32RE
||
249 b
->format
== PA_SAMPLE_S32NE
|| b
->format
== PA_SAMPLE_S32RE
||
250 b
->format
== PA_SAMPLE_FLOAT32NE
|| b
->format
== PA_SAMPLE_FLOAT32RE
)
251 r
->work_format
= PA_SAMPLE_FLOAT32NE
;
253 r
->work_format
= PA_SAMPLE_S16NE
;
256 r
->work_format
= a
->format
;
259 r
->work_format
= PA_SAMPLE_FLOAT32NE
;
261 pa_log_info("Using %s as working format.", pa_sample_format_to_string(r
->work_format
));
263 r
->w_sz
= sample_size(r
->work_format
);
265 if (r
->i_ss
.format
== r
->work_format
)
266 r
->to_work_format_func
= NULL
;
267 else if (r
->work_format
== PA_SAMPLE_FLOAT32NE
) {
268 if (!(r
->to_work_format_func
= pa_get_convert_to_float32ne_function(r
->i_ss
.format
)))
271 pa_assert(r
->work_format
== PA_SAMPLE_S16NE
);
272 if (!(r
->to_work_format_func
= pa_get_convert_to_s16ne_function(r
->i_ss
.format
)))
276 if (r
->o_ss
.format
== r
->work_format
)
277 r
->from_work_format_func
= NULL
;
278 else if (r
->work_format
== PA_SAMPLE_FLOAT32NE
) {
279 if (!(r
->from_work_format_func
= pa_get_convert_from_float32ne_function(r
->o_ss
.format
)))
282 pa_assert(r
->work_format
== PA_SAMPLE_S16NE
);
283 if (!(r
->from_work_format_func
= pa_get_convert_from_s16ne_function(r
->o_ss
.format
)))
287 /* initialize implementation */
288 if (init_table
[method
](r
) < 0)
300 void pa_resampler_free(pa_resampler
*r
) {
306 if (r
->buf1
.memblock
)
307 pa_memblock_unref(r
->buf1
.memblock
);
308 if (r
->buf2
.memblock
)
309 pa_memblock_unref(r
->buf2
.memblock
);
310 if (r
->buf3
.memblock
)
311 pa_memblock_unref(r
->buf3
.memblock
);
312 if (r
->buf4
.memblock
)
313 pa_memblock_unref(r
->buf4
.memblock
);
318 void pa_resampler_set_input_rate(pa_resampler
*r
, uint32_t rate
) {
322 if (r
->i_ss
.rate
== rate
)
327 r
->impl_update_rates(r
);
330 void pa_resampler_set_output_rate(pa_resampler
*r
, uint32_t rate
) {
334 if (r
->o_ss
.rate
== rate
)
339 r
->impl_update_rates(r
);
342 size_t pa_resampler_request(pa_resampler
*r
, size_t out_length
) {
345 return (((out_length
/ r
->o_fz
)*r
->i_ss
.rate
)/r
->o_ss
.rate
) * r
->i_fz
;
348 size_t pa_resampler_max_block_size(pa_resampler
*r
) {
349 size_t block_size_max
;
355 block_size_max
= pa_mempool_block_size_max(r
->mempool
);
357 /* We deduce the "largest" sample spec we're using during the
360 if (r
->o_ss
.channels
> ss
.channels
)
361 ss
.channels
= r
->o_ss
.channels
;
363 /* We silently assume that the format enum is ordered by size */
364 if (r
->o_ss
.format
> ss
.format
)
365 ss
.format
= r
->o_ss
.format
;
366 if (r
->work_format
> ss
.format
)
367 ss
.format
= r
->work_format
;
369 if (r
->o_ss
.rate
> ss
.rate
)
370 ss
.rate
= r
->o_ss
.rate
;
372 fs
= pa_frame_size(&ss
);
374 return (((block_size_max
/fs
+ EXTRA_SAMPLES
)*r
->i_ss
.rate
)/ss
.rate
)*r
->i_fz
;
377 pa_resample_method_t
pa_resampler_get_method(pa_resampler
*r
) {
383 static const char * const resample_methods
[] = {
384 "src-sinc-best-quality",
385 "src-sinc-medium-quality",
387 "src-zero-order-hold",
417 const char *pa_resample_method_to_string(pa_resample_method_t m
) {
419 if (m
< 0 || m
>= PA_RESAMPLER_MAX
)
422 return resample_methods
[m
];
425 int pa_resample_method_supported(pa_resample_method_t m
) {
427 if (m
< 0 || m
>= PA_RESAMPLER_MAX
)
430 #ifndef HAVE_LIBSAMPLERATE
431 if (m
<= PA_RESAMPLER_SRC_LINEAR
)
438 pa_resample_method_t
pa_parse_resample_method(const char *string
) {
439 pa_resample_method_t m
;
443 for (m
= 0; m
< PA_RESAMPLER_MAX
; m
++)
444 if (!strcmp(string
, resample_methods
[m
]))
447 if (!strcmp(string
, "speex-fixed"))
448 return PA_RESAMPLER_SPEEX_FIXED_BASE
+ 3;
450 if (!strcmp(string
, "speex-float"))
451 return PA_RESAMPLER_SPEEX_FLOAT_BASE
+ 3;
453 return PA_RESAMPLER_INVALID
;
456 static pa_bool_t
on_left(pa_channel_position_t p
) {
459 p
== PA_CHANNEL_POSITION_FRONT_LEFT
||
460 p
== PA_CHANNEL_POSITION_REAR_LEFT
||
461 p
== PA_CHANNEL_POSITION_FRONT_LEFT_OF_CENTER
||
462 p
== PA_CHANNEL_POSITION_SIDE_LEFT
||
463 p
== PA_CHANNEL_POSITION_TOP_FRONT_LEFT
||
464 p
== PA_CHANNEL_POSITION_TOP_REAR_LEFT
;
467 static pa_bool_t
on_right(pa_channel_position_t p
) {
470 p
== PA_CHANNEL_POSITION_FRONT_RIGHT
||
471 p
== PA_CHANNEL_POSITION_REAR_RIGHT
||
472 p
== PA_CHANNEL_POSITION_FRONT_RIGHT_OF_CENTER
||
473 p
== PA_CHANNEL_POSITION_SIDE_RIGHT
||
474 p
== PA_CHANNEL_POSITION_TOP_FRONT_RIGHT
||
475 p
== PA_CHANNEL_POSITION_TOP_REAR_RIGHT
;
478 static pa_bool_t
on_center(pa_channel_position_t p
) {
481 p
== PA_CHANNEL_POSITION_FRONT_CENTER
||
482 p
== PA_CHANNEL_POSITION_REAR_CENTER
||
483 p
== PA_CHANNEL_POSITION_TOP_CENTER
||
484 p
== PA_CHANNEL_POSITION_TOP_FRONT_CENTER
||
485 p
== PA_CHANNEL_POSITION_TOP_REAR_CENTER
;
488 static pa_bool_t
on_lfe(pa_channel_position_t p
) {
490 p
== PA_CHANNEL_POSITION_LFE
;
493 static void calc_map_table(pa_resampler
*r
) {
495 pa_bool_t ic_connected
[PA_CHANNELS_MAX
];
502 if (!(r
->map_required
= (r
->i_ss
.channels
!= r
->o_ss
.channels
|| (!(r
->flags
& PA_RESAMPLER_NO_REMAP
) && !pa_channel_map_equal(&r
->i_cm
, &r
->o_cm
)))))
505 memset(r
->map_table
, 0, sizeof(r
->map_table
));
506 memset(ic_connected
, 0, sizeof(ic_connected
));
507 remix
= (r
->flags
& (PA_RESAMPLER_NO_REMAP
|PA_RESAMPLER_NO_REMIX
)) == 0;
509 for (oc
= 0; oc
< r
->o_ss
.channels
; oc
++) {
510 pa_bool_t oc_connected
= FALSE
;
511 pa_channel_position_t b
= r
->o_cm
.map
[oc
];
513 for (ic
= 0; ic
< r
->i_ss
.channels
; ic
++) {
514 pa_channel_position_t a
= r
->i_cm
.map
[ic
];
516 if (r
->flags
& PA_RESAMPLER_NO_REMAP
) {
517 /* We shall not do any remapping. Hence, just check by index */
520 r
->map_table
[oc
][ic
] = 1.0;
525 if (r
->flags
& PA_RESAMPLER_NO_REMIX
) {
526 /* We shall not do any remixing. Hence, just check by name */
529 r
->map_table
[oc
][ic
] = 1.0;
536 /* OK, we shall do the full monty: upmixing and
537 * downmixing. Our algorithm is relatively simple, does
538 * not do spacialization, delay elements or apply lowpass
539 * filters for LFE. Patches are always welcome,
540 * though. Oh, and it doesn't do any matrix
541 * decoding. (Which probably wouldn't make any sense
544 * This code is not idempotent: downmixing an upmixed
545 * stereo stream is not identical to the original. The
546 * volume will not match, and the two channels will be a
547 * linear combination of both.
549 * This is losely based on random suggestions found on the
550 * Internet, such as this:
551 * http://www.halfgaar.net/surround-sound-in-linux and the
554 * The algorithm works basically like this:
556 * 1) Connect all channels with matching names.
559 * S:Mono: Copy into all D:channels
560 * D:Mono: Copy in all S:channels
562 * 3) Mix D:Left, D:Right:
563 * D:Left: If not connected, avg all S:Left
564 * D:Right: If not connected, avg all S:Right
567 * If not connected, avg all S:Center
568 * If still not connected, avg all S:Left, S:Right
571 * If not connected, avg all S:*
573 * 6) Make sure S:Left/S:Right is used: S:Left/S:Right: If
574 * not connected, mix into all D:left and all D:right
575 * channels. Gain is 0.1, the current left and right
576 * should be multiplied by 0.9.
578 * 7) Make sure S:Center, S:LFE is used:
580 * S:Center, S:LFE: If not connected, mix into all
581 * D:left, all D:right, all D:center channels, gain is
582 * 0.375. The current (as result of 1..6) factors
583 * should be multiplied by 0.75. (Alt. suggestion: 0.25
586 * S: and D: shall relate to the source resp. destination channels.
588 * Rationale: 1, 2 are probably obvious. For 3: this
589 * copies front to rear if needed. For 4: we try to find
590 * some suitable C source for C, if we don't find any, we
591 * avg L and R. For 5: LFE is mixed from all channels. For
592 * 6: the rear channels should not be dropped entirely,
593 * however have only minimal impact. For 7: movies usually
594 * encode speech on the center channel. Thus we have to
595 * make sure this channel is distributed to L and R if not
596 * available in the output. Also, LFE is used to achieve a
597 * greater dynamic range, and thus we should try to do our
598 * best to pass it to L+R.
601 if (a
== b
|| a
== PA_CHANNEL_POSITION_MONO
|| b
== PA_CHANNEL_POSITION_MONO
) {
602 r
->map_table
[oc
][ic
] = 1.0;
605 ic_connected
[ic
] = TRUE
;
609 if (!oc_connected
&& remix
) {
610 /* OK, we shall remix */
615 /* We are not connected and on the left side, let's
616 * average all left side input channels. */
618 for (ic
= 0; ic
< r
->i_ss
.channels
; ic
++)
619 if (on_left(r
->i_cm
.map
[ic
]))
623 for (ic
= 0; ic
< r
->i_ss
.channels
; ic
++)
624 if (on_left(r
->i_cm
.map
[ic
])) {
625 r
->map_table
[oc
][ic
] = 1.0 / n
;
626 ic_connected
[ic
] = TRUE
;
629 /* We ignore the case where there is no left input
630 * channel. Something is really wrong in this case
633 } else if (on_right(b
)) {
636 /* We are not connected and on the right side, let's
637 * average all right side input channels. */
639 for (ic
= 0; ic
< r
->i_ss
.channels
; ic
++)
640 if (on_right(r
->i_cm
.map
[ic
]))
644 for (ic
= 0; ic
< r
->i_ss
.channels
; ic
++)
645 if (on_right(r
->i_cm
.map
[ic
])) {
646 r
->map_table
[oc
][ic
] = 1.0 / n
;
647 ic_connected
[ic
] = TRUE
;
650 /* We ignore the case where there is no right input
651 * channel. Something is really wrong in this case
654 } else if (on_center(b
)) {
657 /* We are not connected and at the center. Let's
658 * average all center input channels. */
660 for (ic
= 0; ic
< r
->i_ss
.channels
; ic
++)
661 if (on_center(r
->i_cm
.map
[ic
]))
665 for (ic
= 0; ic
< r
->i_ss
.channels
; ic
++)
666 if (on_center(r
->i_cm
.map
[ic
])) {
667 r
->map_table
[oc
][ic
] = 1.0 / n
;
668 ic_connected
[ic
] = TRUE
;
672 /* Hmm, no center channel around, let's synthesize
673 * it by mixing L and R.*/
677 for (ic
= 0; ic
< r
->i_ss
.channels
; ic
++)
678 if (on_left(r
->i_cm
.map
[ic
]) || on_right(r
->i_cm
.map
[ic
]))
682 for (ic
= 0; ic
< r
->i_ss
.channels
; ic
++)
683 if (on_left(r
->i_cm
.map
[ic
]) || on_right(r
->i_cm
.map
[ic
])) {
684 r
->map_table
[oc
][ic
] = 1.0 / n
;
685 ic_connected
[ic
] = TRUE
;
688 /* We ignore the case where there is not even a
689 * left or right input channel. Something is
690 * really wrong in this case anyway. */
693 } else if (on_lfe(b
)) {
695 /* We are not connected and an LFE. Let's average all
696 * channels for LFE. */
698 for (ic
= 0; ic
< r
->i_ss
.channels
; ic
++) {
699 r
->map_table
[oc
][ic
] = 1.0 / r
->i_ss
.channels
;
701 /* Please note that a channel connected to LFE
702 * doesn't really count as connected. */
710 ic_unconnected_left
= 0,
711 ic_unconnected_right
= 0,
712 ic_unconnected_center
= 0,
713 ic_unconnected_lfe
= 0;
715 for (ic
= 0; ic
< r
->i_ss
.channels
; ic
++) {
716 pa_channel_position_t a
= r
->i_cm
.map
[ic
];
718 if (ic_connected
[ic
])
722 ic_unconnected_left
++;
723 else if (on_right(a
))
724 ic_unconnected_right
++;
725 else if (on_center(a
))
726 ic_unconnected_center
++;
728 ic_unconnected_lfe
++;
731 if (ic_unconnected_left
> 0) {
733 /* OK, so there are unconnected input channels on the
734 * left. Let's multiply all already connected channels on
735 * the left side by .9 and add in our averaged unconnected
736 * channels multplied by .1 */
738 for (oc
= 0; oc
< r
->o_ss
.channels
; oc
++) {
740 if (!on_left(r
->o_cm
.map
[oc
]))
743 for (ic
= 0; ic
< r
->i_ss
.channels
; ic
++) {
745 if (ic_connected
[ic
]) {
746 r
->map_table
[oc
][ic
] *= .9;
750 if (on_left(r
->i_cm
.map
[ic
]))
751 r
->map_table
[oc
][ic
] = .1 / ic_unconnected_left
;
756 if (ic_unconnected_right
> 0) {
758 /* OK, so there are unconnected input channels on the
759 * right. Let's multiply all already connected channels on
760 * the right side by .9 and add in our averaged unconnected
761 * channels multplied by .1 */
763 for (oc
= 0; oc
< r
->o_ss
.channels
; oc
++) {
765 if (!on_right(r
->o_cm
.map
[oc
]))
768 for (ic
= 0; ic
< r
->i_ss
.channels
; ic
++) {
770 if (ic_connected
[ic
]) {
771 r
->map_table
[oc
][ic
] *= .9;
775 if (on_right(r
->i_cm
.map
[ic
]))
776 r
->map_table
[oc
][ic
] = .1 / ic_unconnected_right
;
781 if (ic_unconnected_center
> 0) {
782 pa_bool_t mixed_in
= FALSE
;
784 /* OK, so there are unconnected input channels on the
785 * center. Let's multiply all already connected channels on
786 * the center side by .9 and add in our averaged unconnected
787 * channels multplied by .1 */
789 for (oc
= 0; oc
< r
->o_ss
.channels
; oc
++) {
791 if (!on_center(r
->o_cm
.map
[oc
]))
794 for (ic
= 0; ic
< r
->i_ss
.channels
; ic
++) {
796 if (ic_connected
[ic
]) {
797 r
->map_table
[oc
][ic
] *= .9;
801 if (on_center(r
->i_cm
.map
[ic
])) {
802 r
->map_table
[oc
][ic
] = .1 / ic_unconnected_center
;
810 /* Hmm, as it appears there was no center channel we
811 could mix our center channel in. In this case, mix
812 it into left and right. Using .375 and 0.75 as
815 for (oc
= 0; oc
< r
->o_ss
.channels
; oc
++) {
817 if (!on_left(r
->o_cm
.map
[oc
]) && !on_right(r
->o_cm
.map
[oc
]))
820 for (ic
= 0; ic
< r
->i_ss
.channels
; ic
++) {
822 if (ic_connected
[ic
]) {
823 r
->map_table
[oc
][ic
] *= .75;
827 if (on_center(r
->i_cm
.map
[ic
]))
828 r
->map_table
[oc
][ic
] = .375 / ic_unconnected_center
;
834 if (ic_unconnected_lfe
> 0) {
836 /* OK, so there is an unconnected LFE channel. Let's mix
837 * it into all channels, with factor 0.375 */
839 for (ic
= 0; ic
< r
->i_ss
.channels
; ic
++) {
841 if (!on_lfe(r
->i_cm
.map
[ic
]))
844 for (oc
= 0; oc
< r
->o_ss
.channels
; oc
++)
845 r
->map_table
[oc
][ic
] = 0.375 / ic_unconnected_lfe
;
853 pa_strbuf_printf(s
, " ");
854 for (ic
= 0; ic
< r
->i_ss
.channels
; ic
++)
855 pa_strbuf_printf(s
, " I%02u ", ic
);
856 pa_strbuf_puts(s
, "\n +");
858 for (ic
= 0; ic
< r
->i_ss
.channels
; ic
++)
859 pa_strbuf_printf(s
, "------");
860 pa_strbuf_puts(s
, "\n");
862 for (oc
= 0; oc
< r
->o_ss
.channels
; oc
++) {
863 pa_strbuf_printf(s
, "O%02u |", oc
);
865 for (ic
= 0; ic
< r
->i_ss
.channels
; ic
++)
866 pa_strbuf_printf(s
, " %1.3f", r
->map_table
[oc
][ic
]);
868 pa_strbuf_puts(s
, "\n");
871 pa_log_debug("Channel matrix:\n%s", t
= pa_strbuf_tostring_free(s
));
875 static pa_memchunk
* convert_to_work_format(pa_resampler
*r
, pa_memchunk
*input
) {
881 pa_assert(input
->memblock
);
883 /* Convert the incoming sample into the work sample format and place them in buf1 */
885 if (!r
->to_work_format_func
|| !input
->length
)
888 n_samples
= (input
->length
/ r
->i_fz
) * r
->i_ss
.channels
;
891 r
->buf1
.length
= r
->w_sz
* n_samples
;
893 if (!r
->buf1
.memblock
|| r
->buf1_samples
< n_samples
) {
894 if (r
->buf1
.memblock
)
895 pa_memblock_unref(r
->buf1
.memblock
);
897 r
->buf1_samples
= n_samples
;
898 r
->buf1
.memblock
= pa_memblock_new(r
->mempool
, r
->buf1
.length
);
901 src
= (uint8_t*) pa_memblock_acquire(input
->memblock
) + input
->index
;
902 dst
= (uint8_t*) pa_memblock_acquire(r
->buf1
.memblock
);
904 r
->to_work_format_func(n_samples
, src
, dst
);
906 pa_memblock_release(input
->memblock
);
907 pa_memblock_release(r
->buf1
.memblock
);
912 static void vectoradd_s16_with_fraction(
913 int16_t *d
, int dstr
,
914 const int16_t *s1
, int sstr1
,
915 const int16_t *s2
, int sstr2
,
917 float s3
, float s4
) {
921 i3
= (int32_t) (s3
* 0x10000);
922 i4
= (int32_t) (s4
* 0x10000);
930 a
= (a
* i3
) / 0x10000;
931 b
= (b
* i4
) / 0x10000;
933 *d
= (int16_t) (a
+ b
);
935 s1
= (const int16_t*) ((const uint8_t*) s1
+ sstr1
);
936 s2
= (const int16_t*) ((const uint8_t*) s2
+ sstr2
);
937 d
= (int16_t*) ((uint8_t*) d
+ dstr
);
942 static pa_memchunk
*remap_channels(pa_resampler
*r
, pa_memchunk
*input
) {
943 unsigned in_n_samples
, out_n_samples
, n_frames
;
950 pa_assert(input
->memblock
);
952 /* Remap channels and place the result int buf2 */
954 if (!r
->map_required
|| !input
->length
)
957 in_n_samples
= input
->length
/ r
->w_sz
;
958 n_frames
= in_n_samples
/ r
->i_ss
.channels
;
959 out_n_samples
= n_frames
* r
->o_ss
.channels
;
962 r
->buf2
.length
= r
->w_sz
* out_n_samples
;
964 if (!r
->buf2
.memblock
|| r
->buf2_samples
< out_n_samples
) {
965 if (r
->buf2
.memblock
)
966 pa_memblock_unref(r
->buf2
.memblock
);
968 r
->buf2_samples
= out_n_samples
;
969 r
->buf2
.memblock
= pa_memblock_new(r
->mempool
, r
->buf2
.length
);
972 src
= ((uint8_t*) pa_memblock_acquire(input
->memblock
) + input
->index
);
973 dst
= pa_memblock_acquire(r
->buf2
.memblock
);
975 memset(dst
, 0, r
->buf2
.length
);
977 o_skip
= r
->w_sz
* r
->o_ss
.channels
;
978 i_skip
= r
->w_sz
* r
->i_ss
.channels
;
980 switch (r
->work_format
) {
981 case PA_SAMPLE_FLOAT32NE
:
983 for (oc
= 0; oc
< r
->o_ss
.channels
; oc
++) {
985 static const float one
= 1.0;
987 for (ic
= 0; ic
< r
->i_ss
.channels
; ic
++) {
989 if (r
->map_table
[oc
][ic
] <= 0.0)
993 (float*) dst
+ oc
, o_skip
,
994 (float*) dst
+ oc
, o_skip
,
995 (float*) src
+ ic
, i_skip
,
997 &one
, &r
->map_table
[oc
][ic
]);
1003 case PA_SAMPLE_S16NE
:
1005 for (oc
= 0; oc
< r
->o_ss
.channels
; oc
++) {
1008 for (ic
= 0; ic
< r
->i_ss
.channels
; ic
++) {
1010 if (r
->map_table
[oc
][ic
] <= 0.0)
1013 if (r
->map_table
[oc
][ic
] >= 1.0) {
1014 static const int16_t one
= 1;
1017 (int16_t*) dst
+ oc
, o_skip
,
1018 (int16_t*) dst
+ oc
, o_skip
,
1019 (int16_t*) src
+ ic
, i_skip
,
1025 vectoradd_s16_with_fraction(
1026 (int16_t*) dst
+ oc
, o_skip
,
1027 (int16_t*) dst
+ oc
, o_skip
,
1028 (int16_t*) src
+ ic
, i_skip
,
1030 1.0, r
->map_table
[oc
][ic
]);
1037 pa_assert_not_reached();
1040 pa_memblock_release(input
->memblock
);
1041 pa_memblock_release(r
->buf2
.memblock
);
1043 r
->buf2
.length
= out_n_samples
* r
->w_sz
;
1048 static pa_memchunk
*resample(pa_resampler
*r
, pa_memchunk
*input
) {
1049 unsigned in_n_frames
, in_n_samples
;
1050 unsigned out_n_frames
, out_n_samples
;
1055 /* Resample the data and place the result in buf3 */
1057 if (!r
->impl_resample
|| !input
->length
)
1060 in_n_samples
= input
->length
/ r
->w_sz
;
1061 in_n_frames
= in_n_samples
/ r
->o_ss
.channels
;
1063 out_n_frames
= ((in_n_frames
*r
->o_ss
.rate
)/r
->i_ss
.rate
)+EXTRA_SAMPLES
;
1064 out_n_samples
= out_n_frames
* r
->o_ss
.channels
;
1067 r
->buf3
.length
= r
->w_sz
* out_n_samples
;
1069 if (!r
->buf3
.memblock
|| r
->buf3_samples
< out_n_samples
) {
1070 if (r
->buf3
.memblock
)
1071 pa_memblock_unref(r
->buf3
.memblock
);
1073 r
->buf3_samples
= out_n_samples
;
1074 r
->buf3
.memblock
= pa_memblock_new(r
->mempool
, r
->buf3
.length
);
1077 r
->impl_resample(r
, input
, in_n_frames
, &r
->buf3
, &out_n_frames
);
1078 r
->buf3
.length
= out_n_frames
* r
->w_sz
* r
->o_ss
.channels
;
1083 static pa_memchunk
*convert_from_work_format(pa_resampler
*r
, pa_memchunk
*input
) {
1084 unsigned n_samples
, n_frames
;
1090 /* Convert the data into the correct sample type and place the result in buf4 */
1092 if (!r
->from_work_format_func
|| !input
->length
)
1095 n_samples
= input
->length
/ r
->w_sz
;
1096 n_frames
= n_samples
/ r
->o_ss
.channels
;
1099 r
->buf4
.length
= r
->o_fz
* n_frames
;
1101 if (!r
->buf4
.memblock
|| r
->buf4_samples
< n_samples
) {
1102 if (r
->buf4
.memblock
)
1103 pa_memblock_unref(r
->buf4
.memblock
);
1105 r
->buf4_samples
= n_samples
;
1106 r
->buf4
.memblock
= pa_memblock_new(r
->mempool
, r
->buf4
.length
);
1109 src
= (uint8_t*) pa_memblock_acquire(input
->memblock
) + input
->index
;
1110 dst
= pa_memblock_acquire(r
->buf4
.memblock
);
1111 r
->from_work_format_func(n_samples
, src
, dst
);
1112 pa_memblock_release(input
->memblock
);
1113 pa_memblock_release(r
->buf4
.memblock
);
1115 r
->buf4
.length
= r
->o_fz
* n_frames
;
1120 void pa_resampler_run(pa_resampler
*r
, const pa_memchunk
*in
, pa_memchunk
*out
) {
1126 pa_assert(in
->length
);
1127 pa_assert(in
->memblock
);
1128 pa_assert(in
->length
% r
->i_fz
== 0);
1130 buf
= (pa_memchunk
*) in
;
1131 buf
= convert_to_work_format(r
, buf
);
1132 buf
= remap_channels(r
, buf
);
1133 buf
= resample(r
, buf
);
1136 buf
= convert_from_work_format(r
, buf
);
1140 pa_memblock_ref(buf
->memblock
);
1142 pa_memchunk_reset(buf
);
1144 pa_memchunk_reset(out
);
1147 /*** libsamplerate based implementation ***/
1149 #ifdef HAVE_LIBSAMPLERATE
1150 static void libsamplerate_resample(pa_resampler
*r
, const pa_memchunk
*input
, unsigned in_n_frames
, pa_memchunk
*output
, unsigned *out_n_frames
) {
1156 pa_assert(out_n_frames
);
1158 memset(&data
, 0, sizeof(data
));
1160 data
.data_in
= (float*) ((uint8_t*) pa_memblock_acquire(input
->memblock
) + input
->index
);
1161 data
.input_frames
= in_n_frames
;
1163 data
.data_out
= (float*) ((uint8_t*) pa_memblock_acquire(output
->memblock
) + output
->index
);
1164 data
.output_frames
= *out_n_frames
;
1166 data
.src_ratio
= (double) r
->o_ss
.rate
/ r
->i_ss
.rate
;
1167 data
.end_of_input
= 0;
1169 pa_assert_se(src_process(r
->src
.state
, &data
) == 0);
1170 pa_assert((unsigned) data
.input_frames_used
== in_n_frames
);
1172 pa_memblock_release(input
->memblock
);
1173 pa_memblock_release(output
->memblock
);
1175 *out_n_frames
= data
.output_frames_gen
;
1178 static void libsamplerate_update_rates(pa_resampler
*r
) {
1181 pa_assert_se(src_set_ratio(r
->src
.state
, (double) r
->o_ss
.rate
/ r
->i_ss
.rate
) == 0);
1184 static void libsamplerate_free(pa_resampler
*r
) {
1188 src_delete(r
->src
.state
);
1191 static int libsamplerate_init(pa_resampler
*r
) {
1196 if (!(r
->src
.state
= src_new(r
->method
, r
->o_ss
.channels
, &err
)))
1199 r
->impl_free
= libsamplerate_free
;
1200 r
->impl_update_rates
= libsamplerate_update_rates
;
1201 r
->impl_resample
= libsamplerate_resample
;
1207 /*** speex based implementation ***/
1209 static void speex_resample_float(pa_resampler
*r
, const pa_memchunk
*input
, unsigned in_n_frames
, pa_memchunk
*output
, unsigned *out_n_frames
) {
1211 uint32_t inf
= in_n_frames
, outf
= *out_n_frames
;
1216 pa_assert(out_n_frames
);
1218 in
= (float*) ((uint8_t*) pa_memblock_acquire(input
->memblock
) + input
->index
);
1219 out
= (float*) ((uint8_t*) pa_memblock_acquire(output
->memblock
) + output
->index
);
1221 pa_assert_se(paspfl_resampler_process_interleaved_float(r
->speex
.state
, in
, &inf
, out
, &outf
) == 0);
1223 pa_memblock_release(input
->memblock
);
1224 pa_memblock_release(output
->memblock
);
1226 pa_assert(inf
== in_n_frames
);
1227 *out_n_frames
= outf
;
1230 static void speex_resample_int(pa_resampler
*r
, const pa_memchunk
*input
, unsigned in_n_frames
, pa_memchunk
*output
, unsigned *out_n_frames
) {
1232 uint32_t inf
= in_n_frames
, outf
= *out_n_frames
;
1237 pa_assert(out_n_frames
);
1239 in
= (int16_t*) ((uint8_t*) pa_memblock_acquire(input
->memblock
) + input
->index
);
1240 out
= (int16_t*) ((uint8_t*) pa_memblock_acquire(output
->memblock
) + output
->index
);
1242 pa_assert_se(paspfx_resampler_process_interleaved_int(r
->speex
.state
, in
, &inf
, out
, &outf
) == 0);
1244 pa_memblock_release(input
->memblock
);
1245 pa_memblock_release(output
->memblock
);
1247 pa_assert(inf
== in_n_frames
);
1248 *out_n_frames
= outf
;
1251 static void speex_update_rates(pa_resampler
*r
) {
1254 if (r
->method
>= PA_RESAMPLER_SPEEX_FIXED_BASE
&& r
->method
<= PA_RESAMPLER_SPEEX_FIXED_MAX
)
1255 pa_assert_se(paspfx_resampler_set_rate(r
->speex
.state
, r
->i_ss
.rate
, r
->o_ss
.rate
) == 0);
1257 pa_assert(r
->method
>= PA_RESAMPLER_SPEEX_FLOAT_BASE
&& r
->method
<= PA_RESAMPLER_SPEEX_FLOAT_MAX
);
1258 pa_assert_se(paspfl_resampler_set_rate(r
->speex
.state
, r
->i_ss
.rate
, r
->o_ss
.rate
) == 0);
1262 static void speex_free(pa_resampler
*r
) {
1265 if (!r
->speex
.state
)
1268 if (r
->method
>= PA_RESAMPLER_SPEEX_FIXED_BASE
&& r
->method
<= PA_RESAMPLER_SPEEX_FIXED_MAX
)
1269 paspfx_resampler_destroy(r
->speex
.state
);
1271 pa_assert(r
->method
>= PA_RESAMPLER_SPEEX_FLOAT_BASE
&& r
->method
<= PA_RESAMPLER_SPEEX_FLOAT_MAX
);
1272 paspfl_resampler_destroy(r
->speex
.state
);
1276 static int speex_init(pa_resampler
*r
) {
1281 r
->impl_free
= speex_free
;
1282 r
->impl_update_rates
= speex_update_rates
;
1284 if (r
->method
>= PA_RESAMPLER_SPEEX_FIXED_BASE
&& r
->method
<= PA_RESAMPLER_SPEEX_FIXED_MAX
) {
1285 q
= r
->method
- PA_RESAMPLER_SPEEX_FIXED_BASE
;
1287 pa_log_info("Choosing speex quality setting %i.", q
);
1289 if (!(r
->speex
.state
= paspfx_resampler_init(r
->o_ss
.channels
, r
->i_ss
.rate
, r
->o_ss
.rate
, q
, &err
)))
1292 r
->impl_resample
= speex_resample_int
;
1294 pa_assert(r
->method
>= PA_RESAMPLER_SPEEX_FLOAT_BASE
&& r
->method
<= PA_RESAMPLER_SPEEX_FLOAT_MAX
);
1295 q
= r
->method
- PA_RESAMPLER_SPEEX_FLOAT_BASE
;
1297 pa_log_info("Choosing speex quality setting %i.", q
);
1299 if (!(r
->speex
.state
= paspfl_resampler_init(r
->o_ss
.channels
, r
->i_ss
.rate
, r
->o_ss
.rate
, q
, &err
)))
1302 r
->impl_resample
= speex_resample_float
;
1308 /* Trivial implementation */
1310 static void trivial_resample(pa_resampler
*r
, const pa_memchunk
*input
, unsigned in_n_frames
, pa_memchunk
*output
, unsigned *out_n_frames
) {
1318 pa_assert(out_n_frames
);
1320 fz
= r
->w_sz
* r
->o_ss
.channels
;
1322 src
= (uint8_t*) pa_memblock_acquire(input
->memblock
) + input
->index
;
1323 dst
= (uint8_t*) pa_memblock_acquire(output
->memblock
) + output
->index
;
1325 for (o_index
= 0;; o_index
++, r
->trivial
.o_counter
++) {
1328 j
= ((r
->trivial
.o_counter
* r
->i_ss
.rate
) / r
->o_ss
.rate
);
1329 j
= j
> r
->trivial
.i_counter
? j
- r
->trivial
.i_counter
: 0;
1331 if (j
>= in_n_frames
)
1334 pa_assert(o_index
* fz
< pa_memblock_get_length(output
->memblock
));
1336 oil_memcpy((uint8_t*) dst
+ fz
* o_index
,
1337 (uint8_t*) src
+ fz
* j
, fz
);
1340 pa_memblock_release(input
->memblock
);
1341 pa_memblock_release(output
->memblock
);
1343 *out_n_frames
= o_index
;
1345 r
->trivial
.i_counter
+= in_n_frames
;
1347 /* Normalize counters */
1348 while (r
->trivial
.i_counter
>= r
->i_ss
.rate
) {
1349 pa_assert(r
->trivial
.o_counter
>= r
->o_ss
.rate
);
1351 r
->trivial
.i_counter
-= r
->i_ss
.rate
;
1352 r
->trivial
.o_counter
-= r
->o_ss
.rate
;
1356 static void trivial_update_rates(pa_resampler
*r
) {
1359 r
->trivial
.i_counter
= 0;
1360 r
->trivial
.o_counter
= 0;
1363 static int trivial_init(pa_resampler
*r
) {
1366 r
->trivial
.o_counter
= r
->trivial
.i_counter
= 0;
1368 r
->impl_resample
= trivial_resample
;
1369 r
->impl_update_rates
= trivial_update_rates
;
1370 r
->impl_free
= NULL
;
1375 /*** ffmpeg based implementation ***/
1377 static void ffmpeg_resample(pa_resampler
*r
, const pa_memchunk
*input
, unsigned in_n_frames
, pa_memchunk
*output
, unsigned *out_n_frames
) {
1378 unsigned used_frames
= 0, c
;
1383 pa_assert(out_n_frames
);
1385 for (c
= 0; c
< r
->o_ss
.channels
; c
++) {
1388 int16_t *p
, *t
, *k
, *q
, *s
;
1389 int consumed_frames
;
1392 /* Allocate a new block */
1393 b
= pa_memblock_new(r
->mempool
, r
->ffmpeg
.buf
[c
].length
+ in_n_frames
* sizeof(int16_t));
1394 p
= pa_memblock_acquire(b
);
1396 /* Copy the remaining data into it */
1397 l
= r
->ffmpeg
.buf
[c
].length
;
1398 if (r
->ffmpeg
.buf
[c
].memblock
) {
1399 t
= (int16_t*) ((uint8_t*) pa_memblock_acquire(r
->ffmpeg
.buf
[c
].memblock
) + r
->ffmpeg
.buf
[c
].index
);
1401 pa_memblock_release(r
->ffmpeg
.buf
[c
].memblock
);
1402 pa_memblock_unref(r
->ffmpeg
.buf
[c
].memblock
);
1403 pa_memchunk_reset(&r
->ffmpeg
.buf
[c
]);
1406 /* Now append the new data, splitting up channels */
1407 t
= ((int16_t*) ((uint8_t*) pa_memblock_acquire(input
->memblock
) + input
->index
)) + c
;
1408 k
= (int16_t*) ((uint8_t*) p
+ l
);
1409 for (u
= 0; u
< in_n_frames
; u
++) {
1411 t
+= r
->o_ss
.channels
;
1414 pa_memblock_release(input
->memblock
);
1416 /* Calculate the resulting number of frames */
1417 in
= in_n_frames
+ l
/ sizeof(int16_t);
1419 /* Allocate buffer for the result */
1420 w
= pa_memblock_new(r
->mempool
, *out_n_frames
* sizeof(int16_t));
1421 q
= pa_memblock_acquire(w
);
1424 used_frames
= av_resample(r
->ffmpeg
.state
,
1428 c
>= (unsigned) r
->o_ss
.channels
-1);
1430 pa_memblock_release(b
);
1432 /* Now store the remaining samples away */
1433 pa_assert(consumed_frames
<= (int) in
);
1434 if (consumed_frames
< (int) in
) {
1435 r
->ffmpeg
.buf
[c
].memblock
= b
;
1436 r
->ffmpeg
.buf
[c
].index
= consumed_frames
* sizeof(int16_t);
1437 r
->ffmpeg
.buf
[c
].length
= (in
- consumed_frames
) * sizeof(int16_t);
1439 pa_memblock_unref(b
);
1441 /* And place the results in the output buffer */
1442 s
= (short*) ((uint8_t*) pa_memblock_acquire(output
->memblock
) + output
->index
) + c
;
1443 for (u
= 0; u
< used_frames
; u
++) {
1446 s
+= r
->o_ss
.channels
;
1448 pa_memblock_release(output
->memblock
);
1449 pa_memblock_release(w
);
1450 pa_memblock_unref(w
);
1453 *out_n_frames
= used_frames
;
1456 static void ffmpeg_free(pa_resampler
*r
) {
1461 if (r
->ffmpeg
.state
)
1462 av_resample_close(r
->ffmpeg
.state
);
1464 for (c
= 0; c
< PA_ELEMENTSOF(r
->ffmpeg
.buf
); c
++)
1465 if (r
->ffmpeg
.buf
[c
].memblock
)
1466 pa_memblock_unref(r
->ffmpeg
.buf
[c
].memblock
);
1469 static int ffmpeg_init(pa_resampler
*r
) {
1474 /* We could probably implement different quality levels by
1475 * adjusting the filter parameters here. However, ffmpeg
1476 * internally only uses these hardcoded values, so let's use them
1477 * here for now as well until ffmpeg makes this configurable. */
1479 if (!(r
->ffmpeg
.state
= av_resample_init(r
->o_ss
.rate
, r
->i_ss
.rate
, 16, 10, 0, 0.8)))
1482 r
->impl_free
= ffmpeg_free
;
1483 r
->impl_resample
= ffmpeg_resample
;
1485 for (c
= 0; c
< PA_ELEMENTSOF(r
->ffmpeg
.buf
); c
++)
1486 pa_memchunk_reset(&r
->ffmpeg
.buf
[c
]);
1491 /*** copy (noop) implementation ***/
1493 static int copy_init(pa_resampler
*r
) {
1496 pa_assert(r
->o_ss
.rate
== r
->i_ss
.rate
);
1498 r
->impl_free
= NULL
;
1499 r
->impl_resample
= NULL
;
1500 r
->impl_update_rates
= NULL
;