4 This file is part of polypaudio.
6 polypaudio is free software; you can redistribute it and/or modify
7 it under the terms of the GNU Lesser General Public License as published
8 by the Free Software Foundation; either version 2 of the License,
9 or (at your option) any later version.
11 polypaudio is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 General Public License for more details.
16 You should have received a copy of the GNU Lesser General Public License
17 along with polypaudio; if not, write to the Free Software
18 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
29 #include <samplerate.h>
31 #include "resampler.h"
37 struct pa_sample_spec i_ss
, o_ss
;
38 struct pa_channel_map i_cm
, o_cm
;
40 struct pa_memblock_stat
*memblock_stat
;
43 pa_resample_method_t resample_method
;
45 void (*impl_free
)(struct pa_resampler
*r
);
46 void (*impl_set_input_rate
)(struct pa_resampler
*r
, uint32_t rate
);
47 void (*impl_run
)(struct pa_resampler
*r
, const struct pa_memchunk
*in
, struct pa_memchunk
*out
);
50 struct impl_libsamplerate
{
52 unsigned i_alloc
, o_alloc
;
53 pa_convert_to_float32ne_func_t to_float32ne_func
;
54 pa_convert_from_float32ne_func_t from_float32ne_func
;
63 static int libsamplerate_init(struct pa_resampler
*r
);
64 static int trivial_init(struct pa_resampler
*r
);
66 struct pa_resampler
* pa_resampler_new(
67 const struct pa_sample_spec
*a
,
68 const struct pa_channel_map
*am
,
69 const struct pa_sample_spec
*b
,
70 const struct pa_channel_map
*bm
,
71 struct pa_memblock_stat
*s
,
72 pa_resample_method_t resample_method
) {
74 struct pa_resampler
*r
= NULL
;
75 assert(a
&& b
&& pa_sample_spec_valid(a
) && pa_sample_spec_valid(b
) && resample_method
!= PA_RESAMPLER_INVALID
);
77 if (a
->channels
!= b
->channels
&& a
->channels
!= 1 && b
->channels
!= 1)
80 r
= pa_xmalloc(sizeof(struct pa_resampler
));
83 r
->resample_method
= resample_method
;
86 r
->impl_set_input_rate
= NULL
;
89 /* Fill sample specs */
96 pa_channel_map_init_auto(&r
->i_cm
, r
->i_ss
.channels
);
101 pa_channel_map_init_auto(&r
->o_cm
, r
->o_ss
.channels
);
104 r
->i_fz
= pa_frame_size(a
);
105 r
->o_fz
= pa_frame_size(b
);
107 r
->channels
= a
->channels
;
108 if (b
->channels
< r
->channels
)
109 r
->channels
= b
->channels
;
111 /* Choose implementation */
112 if (a
->channels
!= b
->channels
|| a
->format
!= b
->format
|| resample_method
!= PA_RESAMPLER_TRIVIAL
|| !pa_channel_map_equal(&r
->i_cm
, &r
->o_cm
)) {
113 /* Use the libsamplerate based resampler for the complicated cases */
114 if (resample_method
== PA_RESAMPLER_TRIVIAL
)
115 r
->resample_method
= PA_RESAMPLER_SRC_ZERO_ORDER_HOLD
;
117 if (libsamplerate_init(r
) < 0)
121 /* Use our own simple non-fp resampler for the trivial cases and when the user selects it */
122 if (trivial_init(r
) < 0)
135 void pa_resampler_free(struct pa_resampler
*r
) {
144 void pa_resampler_set_input_rate(struct pa_resampler
*r
, uint32_t rate
) {
148 if (r
->impl_set_input_rate
)
149 r
->impl_set_input_rate(r
, rate
);
152 void pa_resampler_run(struct pa_resampler
*r
, const struct pa_memchunk
*in
, struct pa_memchunk
*out
) {
153 assert(r
&& in
&& out
&& r
->impl_run
);
155 r
->impl_run(r
, in
, out
);
158 size_t pa_resampler_request(struct pa_resampler
*r
, size_t out_length
) {
159 assert(r
&& (out_length
% r
->o_fz
) == 0);
160 return (((out_length
/ r
->o_fz
)*r
->i_ss
.rate
)/r
->o_ss
.rate
) * r
->i_fz
;
163 pa_resample_method_t
pa_resampler_get_method(struct pa_resampler
*r
) {
165 return r
->resample_method
;
168 /*** libsamplerate based implementation ***/
170 static void libsamplerate_free(struct pa_resampler
*r
) {
171 struct impl_libsamplerate
*i
;
172 assert(r
&& r
->impl_data
);
176 src_delete(i
->src_state
);
183 static void calc_map_table(struct pa_resampler
*r
) {
184 struct impl_libsamplerate
*u
;
187 assert(r
->impl_data
);
191 if ((u
->map_required
= (!pa_channel_map_equal(&r
->i_cm
, r
->o_cm
) || r
->i_ss
.channels
!= r
->o_ss
.channels
))) {
193 memset(u
->map_table
, -1, sizeof(u
->map_table
));
195 for (oc
= 0; oc
< r
->o_iss
.channels
; oc
++) {
198 for (ic
= 0; ic
< r
->i_ss
.channels
; ic
++) {
199 pa_channel_position_t a
, b
;
205 (a
== PA_CHANNEL_POSITION_MONO
&& b
== PA_CHANNEL_POSITION_LEFT
) ||
206 (a
== PA_CHANNEL_POSITION_MONO
&& b
== PA_CHANNEL_POSITION_RIGHT
) ||
207 (a
== PA_CHANNEL_POSITION_LEFT
&& b
== PA_CHANNEL_POSITION_MONO
) ||
208 (a
== PA_CHANNEL_POSITION_RIGHT
&& b
== PA_CHANNEL_POSITION_MONO
))
210 u
->map_table
[oc
][i
++] = ic
;
217 static float *remap_to_float(struct pa_resampler
*r
, const struct pa_memchunk
*in
) {
219 struct impl_libsamplerate
*u
;
221 assert(r
->impl_data
);
225 nsamples
= in
->length
/ u
->i_fz
;
229 if (u
->i_buf_samples
< nsamples
)
230 u
->i_buf
= pa_xrealloc(i
->i_buf
, sizeof(float) * (i
->i_buf_samples
= nsamples
));
232 i
->to_float32ne_func(ff_ins
, (uint8_t*) in
->memblock
->data
+in
->index
, i_nchannels
, i
->i_buf
);
240 static void libsamplerate_run(struct pa_resampler
*r
, const struct pa_memchunk
*in
, struct pa_memchunk
*out
) {
247 static void libsamplerate_run(struct pa_resampler
*r
, const struct pa_memchunk
*in
, struct pa_memchunk
*out
) {
248 unsigned i_nchannels
, o_nchannels
, ins
, ons
, eff_ins
, eff_ons
;
250 struct impl_libsamplerate
*i
;
251 assert(r
&& in
&& out
&& in
->length
&& in
->memblock
&& (in
->length
% r
->i_fz
) == 0 && r
->impl_data
);
254 /* How many input samples? */
255 ins
= in
->length
/r
->i_fz
;
258 /* pa_log("%u / %u = %u\n", in->length, r->i_fz, ins); */
260 /* How much space for output samples? */
262 ons
= (ins
*r
->o_ss
.rate
/r
->i_ss
.rate
)+1024;
266 /* How many channels? */
267 if (r
->i_ss
.channels
== r
->o_ss
.channels
) {
268 i_nchannels
= o_nchannels
= 1;
269 eff_ins
= ins
*r
->i_ss
.channels
; /* effective samples */
270 eff_ons
= ons
*r
->o_ss
.channels
;
272 i_nchannels
= r
->i_ss
.channels
;
273 o_nchannels
= r
->o_ss
.channels
;
278 /* pa_log("eff_ins = %u \n", eff_ins); */
281 out
->memblock
= pa_memblock_new(out
->length
= (ons
*r
->o_fz
), r
->memblock_stat
);
283 assert(out
->memblock
);
285 if (i
->i_alloc
< eff_ins
)
286 i
->i_buf
= pa_xrealloc(i
->i_buf
, sizeof(float) * (i
->i_alloc
= eff_ins
));
289 /* pa_log("eff_ins = %u \n", eff_ins); */
291 i
->to_float32ne_func(eff_ins
, (uint8_t*) in
->memblock
->data
+in
->index
, i_nchannels
, i
->i_buf
);
297 if (i
->o_alloc
< eff_ons
)
298 i
->o_buf
= pa_xrealloc(i
->o_buf
, sizeof(float) * (i
->o_alloc
= eff_ons
));
301 data
.data_in
= i
->i_buf
;
302 data
.input_frames
= ins
;
304 data
.data_out
= i
->o_buf
;
305 data
.output_frames
= ons
;
307 data
.src_ratio
= (double) r
->o_ss
.rate
/ r
->i_ss
.rate
;
308 data
.end_of_input
= 0;
310 ret
= src_process(i
->src_state
, &data
);
312 assert((unsigned) data
.input_frames_used
== ins
);
315 ons
= data
.output_frames_gen
;
317 if (r
->i_ss
.channels
== r
->o_ss
.channels
)
318 eff_ons
= ons
*r
->o_ss
.channels
;
325 i
->from_float32ne_func(eff_ons
, cbuf
, (uint8_t*)out
->memblock
->data
+out
->index
, o_nchannels
);
326 out
->length
= ons
*r
->o_fz
;
329 pa_memblock_unref(out
->memblock
);
330 out
->memblock
= NULL
;
334 static void libsamplerate_set_input_rate(struct pa_resampler
*r
, uint32_t rate
) {
336 struct impl_libsamplerate
*i
;
337 assert(r
&& rate
> 0 && r
->impl_data
);
340 ret
= src_set_ratio(i
->src_state
, (double) r
->o_ss
.rate
/ r
->i_ss
.rate
);
344 static int libsamplerate_init(struct pa_resampler
*r
) {
345 struct impl_libsamplerate
*i
= NULL
;
348 r
->impl_data
= i
= pa_xmalloc(sizeof(struct impl_libsamplerate
));
350 i
->to_float32ne_func
= pa_get_convert_to_float32ne_function(r
->i_ss
.format
);
351 i
->from_float32ne_func
= pa_get_convert_from_float32ne_function(r
->o_ss
.format
);
353 if (!i
->to_float32ne_func
|| !i
->from_float32ne_func
)
356 if (!(i
->src_state
= src_new(r
->resample_method
, r
->channels
, &err
)) || !i
->src_state
)
359 i
->i_buf
= i
->o_buf
= NULL
;
360 i
->i_alloc
= i
->o_alloc
= 0;
362 r
->impl_free
= libsamplerate_free
;
363 r
->impl_set_input_rate
= libsamplerate_set_input_rate
;
364 r
->impl_run
= libsamplerate_run
;
373 /* Trivial implementation */
375 static void trivial_run(struct pa_resampler
*r
, const struct pa_memchunk
*in
, struct pa_memchunk
*out
) {
378 struct impl_trivial
*i
;
379 assert(r
&& in
&& out
&& r
->impl_data
);
383 assert(fz
== r
->o_fz
);
385 nframes
= in
->length
/fz
;
387 if (r
->i_ss
.rate
== r
->o_ss
.rate
) {
389 /* In case there's no diefference in sample types, do nothing */
391 pa_memblock_ref(out
->memblock
);
393 i
->o_counter
+= nframes
;
395 /* Do real resampling */
399 /* The length of the new memory block rounded up */
400 l
= ((((nframes
+1) * r
->o_ss
.rate
) / r
->i_ss
.rate
) + 1) * fz
;
403 out
->memblock
= pa_memblock_new(l
, r
->memblock_stat
);
405 for (o_index
= 0;; o_index
++, i
->o_counter
++) {
408 j
= (i
->o_counter
* r
->i_ss
.rate
/ r
->o_ss
.rate
);
409 j
= j
> i
->i_counter
? j
- i
->i_counter
: 0;
414 assert(o_index
*fz
< out
->memblock
->length
);
416 memcpy((uint8_t*) out
->memblock
->data
+ fz
*o_index
,
417 (uint8_t*) in
->memblock
->data
+ in
->index
+ fz
*j
, fz
);
421 out
->length
= o_index
*fz
;
424 i
->i_counter
+= nframes
;
426 /* Normalize counters */
427 while (i
->i_counter
>= r
->i_ss
.rate
) {
428 i
->i_counter
-= r
->i_ss
.rate
;
429 assert(i
->o_counter
>= r
->o_ss
.rate
);
430 i
->o_counter
-= r
->o_ss
.rate
;
434 static void trivial_free(struct pa_resampler
*r
) {
436 pa_xfree(r
->impl_data
);
439 static void trivial_set_input_rate(struct pa_resampler
*r
, uint32_t rate
) {
440 struct impl_trivial
*i
;
441 assert(r
&& rate
> 0 && r
->impl_data
);
448 static int trivial_init(struct pa_resampler
*r
) {
449 struct impl_trivial
*i
;
450 assert(r
&& r
->i_ss
.format
== r
->o_ss
.format
&& r
->i_ss
.channels
== r
->o_ss
.channels
);
452 r
->impl_data
= i
= pa_xmalloc(sizeof(struct impl_trivial
));
453 i
->o_counter
= i
->i_counter
= 0;
455 r
->impl_run
= trivial_run
;
456 r
->impl_free
= trivial_free
;
457 r
->impl_set_input_rate
= trivial_set_input_rate
;
462 const char *pa_resample_method_to_string(pa_resample_method_t m
) {
463 static const char * const resample_methods
[] = {
464 "src-sinc-best-quality",
465 "src-sinc-medium-quality",
467 "src-zero-order-hold",
472 if (m
< 0 || m
>= PA_RESAMPLER_MAX
)
475 return resample_methods
[m
];
478 pa_resample_method_t
pa_parse_resample_method(const char *string
) {
481 if (!strcmp(string
, "src-sinc-best-quality"))
482 return PA_RESAMPLER_SRC_SINC_BEST_QUALITY
;
483 else if (!strcmp(string
, "src-sinc-medium-quality"))
484 return PA_RESAMPLER_SRC_SINC_MEDIUM_QUALITY
;
485 else if (!strcmp(string
, "src-sinc-fastest"))
486 return PA_RESAMPLER_SRC_SINC_FASTEST
;
487 else if (!strcmp(string
, "src-zero-order-hold"))
488 return PA_RESAMPLER_SRC_ZERO_ORDER_HOLD
;
489 else if (!strcmp(string
, "src-linear"))
490 return PA_RESAMPLER_SRC_LINEAR
;
491 else if (!strcmp(string
, "trivial"))
492 return PA_RESAMPLER_TRIVIAL
;
494 return PA_RESAMPLER_INVALID
;