summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLennart Poettering <lennart@poettering.net>2007-09-16 21:56:38 +0000
committerLennart Poettering <lennart@poettering.net>2007-09-16 21:56:38 +0000
commitfce85071796577ceb59fc0ff413c5188c2e385c1 (patch)
tree4f3c721fec10142ac7476f58673213587a6544d6
parentd079b4863b2e0c758e81d117df4cdc967c342c22 (diff)
* 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
-rw-r--r--src/pulsecore/resampler.c66
-rw-r--r--src/pulsecore/resampler.h4
2 files changed, 67 insertions, 3 deletions
diff --git a/src/pulsecore/resampler.c b/src/pulsecore/resampler.c
index 7493eef0..c4b8179d 100644
--- a/src/pulsecore/resampler.c
+++ b/src/pulsecore/resampler.c
@@ -45,6 +45,9 @@
#include "resampler.h"
+/* Number of samples of extra space we allow the resamplers to return */
+#define EXTRA_SAMPLES 128
+
struct pa_resampler {
pa_resample_method_t resample_method;
pa_sample_spec i_ss, o_ss;
@@ -88,6 +91,7 @@ struct pa_resampler {
} ffmpeg;
};
+static int copy_init(pa_resampler *r);
static int trivial_init(pa_resampler*r);
static int speex_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_FFMPEG] = ffmpeg_init,
[PA_RESAMPLER_AUTO] = NULL,
+ [PA_RESAMPLER_COPY] = copy_init
};
static inline size_t sample_size(pa_sample_format_t f) {
@@ -169,13 +174,23 @@ pa_resampler* pa_resampler_new(
/* 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)) {
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;
}
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;
}
@@ -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;
}
+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_assert(r);
@@ -357,7 +401,8 @@ static const char * const resample_methods[] = {
"speex-fixed-9",
"speex-fixed-10",
"ffmpeg",
- "auto"
+ "auto",
+ "copy"
};
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_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;
r->buf3.index = 0;
@@ -875,6 +920,7 @@ static int trivial_init(pa_resampler*r) {
r->impl_resample = trivial_resample;
r->impl_update_rates = trivial_update_rates;
+ r->impl_free = NULL;
return 0;
}
@@ -994,3 +1040,17 @@ static int ffmpeg_init(pa_resampler *r) {
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;
+}
diff --git a/src/pulsecore/resampler.h b/src/pulsecore/resampler.h
index fed4d897..8de8ad71 100644
--- a/src/pulsecore/resampler.h
+++ b/src/pulsecore/resampler.h
@@ -45,6 +45,7 @@ typedef enum pa_resample_method {
PA_RESAMPLER_SPEEX_FIXED_MAX = PA_RESAMPLER_SPEEX_FIXED_BASE + 10,
PA_RESAMPLER_FFMPEG,
PA_RESAMPLER_AUTO, /* automatic select based on sample format */
+ PA_RESAMPLER_COPY,
PA_RESAMPLER_MAX
} 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 */
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 */
void pa_resampler_run(pa_resampler *r, const pa_memchunk *in, pa_memchunk *out);