mirror of
https://gitlab.freedesktop.org/pulseaudio/pulseaudio.git
synced 2025-11-17 06:59:56 -05:00
* add a new resampler "copy" which is does not change sample rates but copies data unmodified from input to output.
* add a new API pa_resampler_max_block_size() which can be used to determine the maximum input buffer size for the resampler so that the bounce buffers don't grow larger then the mempool tile size git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1830 fefdeb5f-60dc-0310-8127-8f9354f1896f
This commit is contained in:
parent
d079b4863b
commit
fce8507179
2 changed files with 67 additions and 3 deletions
|
|
@ -45,6 +45,9 @@
|
||||||
|
|
||||||
#include "resampler.h"
|
#include "resampler.h"
|
||||||
|
|
||||||
|
/* Number of samples of extra space we allow the resamplers to return */
|
||||||
|
#define EXTRA_SAMPLES 128
|
||||||
|
|
||||||
struct pa_resampler {
|
struct pa_resampler {
|
||||||
pa_resample_method_t resample_method;
|
pa_resample_method_t resample_method;
|
||||||
pa_sample_spec i_ss, o_ss;
|
pa_sample_spec i_ss, o_ss;
|
||||||
|
|
@ -88,6 +91,7 @@ struct pa_resampler {
|
||||||
} ffmpeg;
|
} ffmpeg;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static int copy_init(pa_resampler *r);
|
||||||
static int trivial_init(pa_resampler*r);
|
static int trivial_init(pa_resampler*r);
|
||||||
static int speex_init(pa_resampler*r);
|
static int speex_init(pa_resampler*r);
|
||||||
static int ffmpeg_init(pa_resampler*r);
|
static int ffmpeg_init(pa_resampler*r);
|
||||||
|
|
@ -136,6 +140,7 @@ static int (* const init_table[])(pa_resampler*r) = {
|
||||||
[PA_RESAMPLER_SPEEX_FIXED_BASE+10] = speex_init,
|
[PA_RESAMPLER_SPEEX_FIXED_BASE+10] = speex_init,
|
||||||
[PA_RESAMPLER_FFMPEG] = ffmpeg_init,
|
[PA_RESAMPLER_FFMPEG] = ffmpeg_init,
|
||||||
[PA_RESAMPLER_AUTO] = NULL,
|
[PA_RESAMPLER_AUTO] = NULL,
|
||||||
|
[PA_RESAMPLER_COPY] = copy_init
|
||||||
};
|
};
|
||||||
|
|
||||||
static inline size_t sample_size(pa_sample_format_t f) {
|
static inline size_t sample_size(pa_sample_format_t f) {
|
||||||
|
|
@ -169,13 +174,23 @@ pa_resampler* pa_resampler_new(
|
||||||
|
|
||||||
/* Fix method */
|
/* Fix method */
|
||||||
|
|
||||||
|
if (!variable_rate && a->rate == b->rate) {
|
||||||
|
pa_log_info("Forcing resampler 'copy', because of fixed, identical sample rates.");
|
||||||
|
resample_method = PA_RESAMPLER_COPY;
|
||||||
|
}
|
||||||
|
|
||||||
if (!pa_resample_method_supported(resample_method)) {
|
if (!pa_resample_method_supported(resample_method)) {
|
||||||
pa_log_warn("Support for resampler '%s' not compiled in, reverting to 'auto'.", pa_resample_method_to_string(resample_method));
|
pa_log_warn("Support for resampler '%s' not compiled in, reverting to 'auto'.", pa_resample_method_to_string(resample_method));
|
||||||
resample_method = PA_RESAMPLER_AUTO;
|
resample_method = PA_RESAMPLER_AUTO;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (resample_method == PA_RESAMPLER_FFMPEG && variable_rate) {
|
if (resample_method == PA_RESAMPLER_FFMPEG && variable_rate) {
|
||||||
pa_log_info("Resampler 'ffmpeg' cannot do variable rate, reverting to resampler 'auto'." );
|
pa_log_info("Resampler 'ffmpeg' cannot do variable rate, reverting to resampler 'auto'.");
|
||||||
|
resample_method = PA_RESAMPLER_AUTO;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (resample_method == PA_RESAMPLER_COPY && (variable_rate || a->rate != b->rate)) {
|
||||||
|
pa_log_info("Resampler 'copy' cannot change sampling rate, reverting to resampler 'auto'.");
|
||||||
resample_method = PA_RESAMPLER_AUTO;
|
resample_method = PA_RESAMPLER_AUTO;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -321,6 +336,35 @@ size_t pa_resampler_request(pa_resampler *r, size_t out_length) {
|
||||||
return (((out_length / r->o_fz)*r->i_ss.rate)/r->o_ss.rate) * r->i_fz;
|
return (((out_length / r->o_fz)*r->i_ss.rate)/r->o_ss.rate) * r->i_fz;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
size_t pa_resampler_max_block_size(pa_resampler *r) {
|
||||||
|
size_t block_size_max;
|
||||||
|
pa_sample_spec ss;
|
||||||
|
size_t fs;
|
||||||
|
|
||||||
|
pa_assert(r);
|
||||||
|
|
||||||
|
block_size_max = pa_mempool_block_size_max(r->mempool);
|
||||||
|
|
||||||
|
/* We deduce the "largest" sample spec we're using during the
|
||||||
|
* conversion */
|
||||||
|
ss = r->i_ss;
|
||||||
|
if (r->o_ss.channels > ss.channels)
|
||||||
|
ss.channels = r->o_ss.channels;
|
||||||
|
|
||||||
|
/* We silently assume that the format enum is ordered by size */
|
||||||
|
if (r->o_ss.format > ss.format)
|
||||||
|
ss.format = r->o_ss.format;
|
||||||
|
if (r->work_format > ss.format)
|
||||||
|
ss.format = r->work_format;
|
||||||
|
|
||||||
|
if (r->o_ss.rate > ss.rate)
|
||||||
|
ss.rate = r->o_ss.rate;
|
||||||
|
|
||||||
|
fs = pa_frame_size(&ss);
|
||||||
|
|
||||||
|
return (((block_size_max/fs + EXTRA_SAMPLES)*r->i_ss.rate)/ss.rate)*r->i_fz;
|
||||||
|
}
|
||||||
|
|
||||||
pa_resample_method_t pa_resampler_get_method(pa_resampler *r) {
|
pa_resample_method_t pa_resampler_get_method(pa_resampler *r) {
|
||||||
pa_assert(r);
|
pa_assert(r);
|
||||||
|
|
||||||
|
|
@ -357,7 +401,8 @@ static const char * const resample_methods[] = {
|
||||||
"speex-fixed-9",
|
"speex-fixed-9",
|
||||||
"speex-fixed-10",
|
"speex-fixed-10",
|
||||||
"ffmpeg",
|
"ffmpeg",
|
||||||
"auto"
|
"auto",
|
||||||
|
"copy"
|
||||||
};
|
};
|
||||||
|
|
||||||
const char *pa_resample_method_to_string(pa_resample_method_t m) {
|
const char *pa_resample_method_to_string(pa_resample_method_t m) {
|
||||||
|
|
@ -568,7 +613,7 @@ static pa_memchunk *resample(pa_resampler *r, pa_memchunk *input) {
|
||||||
in_n_samples = input->length / r->w_sz;
|
in_n_samples = input->length / r->w_sz;
|
||||||
in_n_frames = in_n_samples / r->o_ss.channels;
|
in_n_frames = in_n_samples / r->o_ss.channels;
|
||||||
|
|
||||||
out_n_frames = ((in_n_frames*r->o_ss.rate)/r->i_ss.rate)+1024;
|
out_n_frames = ((in_n_frames*r->o_ss.rate)/r->i_ss.rate)+EXTRA_SAMPLES;
|
||||||
out_n_samples = out_n_frames * r->o_ss.channels;
|
out_n_samples = out_n_frames * r->o_ss.channels;
|
||||||
|
|
||||||
r->buf3.index = 0;
|
r->buf3.index = 0;
|
||||||
|
|
@ -875,6 +920,7 @@ static int trivial_init(pa_resampler*r) {
|
||||||
|
|
||||||
r->impl_resample = trivial_resample;
|
r->impl_resample = trivial_resample;
|
||||||
r->impl_update_rates = trivial_update_rates;
|
r->impl_update_rates = trivial_update_rates;
|
||||||
|
r->impl_free = NULL;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
@ -994,3 +1040,17 @@ static int ffmpeg_init(pa_resampler *r) {
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*** copy (noop) implementation ***/
|
||||||
|
|
||||||
|
static int copy_init(pa_resampler *r) {
|
||||||
|
pa_assert(r);
|
||||||
|
|
||||||
|
pa_assert(r->o_ss.rate == r->i_ss.rate);
|
||||||
|
|
||||||
|
r->impl_free = NULL;
|
||||||
|
r->impl_resample = NULL;
|
||||||
|
r->impl_update_rates = NULL;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -45,6 +45,7 @@ typedef enum pa_resample_method {
|
||||||
PA_RESAMPLER_SPEEX_FIXED_MAX = PA_RESAMPLER_SPEEX_FIXED_BASE + 10,
|
PA_RESAMPLER_SPEEX_FIXED_MAX = PA_RESAMPLER_SPEEX_FIXED_BASE + 10,
|
||||||
PA_RESAMPLER_FFMPEG,
|
PA_RESAMPLER_FFMPEG,
|
||||||
PA_RESAMPLER_AUTO, /* automatic select based on sample format */
|
PA_RESAMPLER_AUTO, /* automatic select based on sample format */
|
||||||
|
PA_RESAMPLER_COPY,
|
||||||
PA_RESAMPLER_MAX
|
PA_RESAMPLER_MAX
|
||||||
} pa_resample_method_t;
|
} pa_resample_method_t;
|
||||||
|
|
||||||
|
|
@ -62,6 +63,9 @@ void pa_resampler_free(pa_resampler *r);
|
||||||
/* Returns the size of an input memory block which is required to return the specified amount of output data */
|
/* Returns the size of an input memory block which is required to return the specified amount of output data */
|
||||||
size_t pa_resampler_request(pa_resampler *r, size_t out_length);
|
size_t pa_resampler_request(pa_resampler *r, size_t out_length);
|
||||||
|
|
||||||
|
/* Requires the maximum size of input blocks we can process without needing bounce buffers larger than the mempool tile size. */
|
||||||
|
size_t pa_resampler_max_block_size(pa_resampler *r);
|
||||||
|
|
||||||
/* Pass the specified memory chunk to the resampler and return the newly resampled data */
|
/* Pass the specified memory chunk to the resampler and return the newly resampled data */
|
||||||
void pa_resampler_run(pa_resampler *r, const pa_memchunk *in, pa_memchunk *out);
|
void pa_resampler_run(pa_resampler *r, const pa_memchunk *in, pa_memchunk *out);
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue