mirror of
https://gitlab.freedesktop.org/pulseaudio/pulseaudio.git
synced 2025-11-02 09:01:46 -05:00
merge glitch-free branch back into trunk
git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@2445 fefdeb5f-60dc-0310-8127-8f9354f1896f
This commit is contained in:
parent
91f092eadc
commit
045c1d602d
189 changed files with 12559 additions and 4959 deletions
|
|
@ -47,7 +47,7 @@
|
|||
#include "resampler.h"
|
||||
|
||||
/* Number of samples of extra space we allow the resamplers to return */
|
||||
#define EXTRA_SAMPLES 128
|
||||
#define EXTRA_FRAMES 128
|
||||
|
||||
struct pa_resampler {
|
||||
pa_resample_method_t method;
|
||||
|
|
@ -79,6 +79,15 @@ struct pa_resampler {
|
|||
unsigned i_counter;
|
||||
} trivial;
|
||||
|
||||
struct { /* data specific to the peak finder pseudo resampler */
|
||||
unsigned o_counter;
|
||||
unsigned i_counter;
|
||||
|
||||
float max_f[PA_CHANNELS_MAX];
|
||||
int16_t max_i[PA_CHANNELS_MAX];
|
||||
|
||||
} peaks;
|
||||
|
||||
#ifdef HAVE_LIBSAMPLERATE
|
||||
struct { /* data specific to libsamplerate */
|
||||
SRC_STATE *state;
|
||||
|
|
@ -99,6 +108,7 @@ 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);
|
||||
static int peaks_init(pa_resampler*r);
|
||||
#ifdef HAVE_LIBSAMPLERATE
|
||||
static int libsamplerate_init(pa_resampler*r);
|
||||
#endif
|
||||
|
|
@ -144,7 +154,8 @@ 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
|
||||
[PA_RESAMPLER_COPY] = copy_init,
|
||||
[PA_RESAMPLER_PEAKS] = peaks_init,
|
||||
};
|
||||
|
||||
static inline size_t sample_size(pa_sample_format_t f) {
|
||||
|
|
@ -242,9 +253,9 @@ pa_resampler* pa_resampler_new(
|
|||
if ((method >= PA_RESAMPLER_SPEEX_FIXED_BASE && method <= PA_RESAMPLER_SPEEX_FIXED_MAX) ||
|
||||
(method == PA_RESAMPLER_FFMPEG))
|
||||
r->work_format = PA_SAMPLE_S16NE;
|
||||
else if (method == PA_RESAMPLER_TRIVIAL || method == PA_RESAMPLER_COPY) {
|
||||
else if (method == PA_RESAMPLER_TRIVIAL || method == PA_RESAMPLER_COPY || method == PA_RESAMPLER_PEAKS) {
|
||||
|
||||
if (r->map_required || a->format != b->format) {
|
||||
if (r->map_required || a->format != b->format || method == PA_RESAMPLER_PEAKS) {
|
||||
|
||||
if (a->format == PA_SAMPLE_S32NE || a->format == PA_SAMPLE_S32RE ||
|
||||
a->format == PA_SAMPLE_FLOAT32NE || a->format == PA_SAMPLE_FLOAT32RE ||
|
||||
|
|
@ -347,6 +358,12 @@ 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_result(pa_resampler *r, size_t in_length) {
|
||||
pa_assert(r);
|
||||
|
||||
return (((in_length / r->i_fz)*r->o_ss.rate)/r->i_ss.rate) * r->o_fz;
|
||||
}
|
||||
|
||||
size_t pa_resampler_max_block_size(pa_resampler *r) {
|
||||
size_t block_size_max;
|
||||
pa_sample_spec ss;
|
||||
|
|
@ -358,22 +375,17 @@ size_t pa_resampler_max_block_size(pa_resampler *r) {
|
|||
|
||||
/* 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;
|
||||
ss.channels = PA_MAX(r->i_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;
|
||||
ss.format = PA_MAX(r->i_ss.format, r->o_ss.format);
|
||||
ss.format = PA_MAX(ss.format, r->work_format);
|
||||
|
||||
if (r->o_ss.rate > ss.rate)
|
||||
ss.rate = r->o_ss.rate;
|
||||
ss.rate = PA_MAX(r->i_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;
|
||||
return (((block_size_max/fs - EXTRA_FRAMES)*r->i_ss.rate)/ss.rate)*r->i_fz;
|
||||
}
|
||||
|
||||
void pa_resampler_reset(pa_resampler *r) {
|
||||
|
|
@ -420,7 +432,8 @@ static const char * const resample_methods[] = {
|
|||
"speex-fixed-10",
|
||||
"ffmpeg",
|
||||
"auto",
|
||||
"copy"
|
||||
"copy",
|
||||
"peaks"
|
||||
};
|
||||
|
||||
const char *pa_resample_method_to_string(pa_resample_method_t m) {
|
||||
|
|
@ -1069,7 +1082,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)+EXTRA_SAMPLES;
|
||||
out_n_frames = ((in_n_frames*r->o_ss.rate)/r->i_ss.rate)+EXTRA_FRAMES;
|
||||
out_n_samples = out_n_frames * r->o_ss.channels;
|
||||
|
||||
r->buf3.index = 0;
|
||||
|
|
@ -1400,6 +1413,113 @@ static int trivial_init(pa_resampler*r) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
/* Peak finder implementation */
|
||||
|
||||
static void peaks_resample(pa_resampler *r, const pa_memchunk *input, unsigned in_n_frames, pa_memchunk *output, unsigned *out_n_frames) {
|
||||
size_t fz;
|
||||
unsigned o_index;
|
||||
void *src, *dst;
|
||||
unsigned start = 0;
|
||||
|
||||
pa_assert(r);
|
||||
pa_assert(input);
|
||||
pa_assert(output);
|
||||
pa_assert(out_n_frames);
|
||||
|
||||
fz = r->w_sz * r->o_ss.channels;
|
||||
|
||||
src = (uint8_t*) pa_memblock_acquire(input->memblock) + input->index;
|
||||
dst = (uint8_t*) pa_memblock_acquire(output->memblock) + output->index;
|
||||
|
||||
for (o_index = 0;; o_index++, r->peaks.o_counter++) {
|
||||
unsigned j;
|
||||
|
||||
j = ((r->peaks.o_counter * r->i_ss.rate) / r->o_ss.rate);
|
||||
j = j > r->peaks.i_counter ? j - r->peaks.i_counter : 0;
|
||||
|
||||
if (j >= in_n_frames)
|
||||
break;
|
||||
|
||||
pa_assert(o_index * fz < pa_memblock_get_length(output->memblock));
|
||||
|
||||
if (r->work_format == PA_SAMPLE_S16NE) {
|
||||
unsigned i, c;
|
||||
int16_t *s = (int16_t*) ((uint8_t*) src + fz * j);
|
||||
int16_t *d = (int16_t*) ((uint8_t*) dst + fz * o_index);
|
||||
|
||||
for (i = start; i <= j; i++)
|
||||
for (c = 0; c < r->o_ss.channels; c++, s++) {
|
||||
int16_t n;
|
||||
|
||||
n = *s < 0 ? -*s : *s;
|
||||
|
||||
if (n > r->peaks.max_i[c])
|
||||
r->peaks.max_i[c] = n;
|
||||
}
|
||||
|
||||
for (c = 0; c < r->o_ss.channels; c++, d++)
|
||||
*d = r->peaks.max_i[c];
|
||||
|
||||
memset(r->peaks.max_i, 0, sizeof(r->peaks.max_i));
|
||||
} else {
|
||||
unsigned i, c;
|
||||
float *s = (float*) ((uint8_t*) src + fz * j);
|
||||
float *d = (float*) ((uint8_t*) dst + fz * o_index);
|
||||
|
||||
pa_assert(r->work_format == PA_SAMPLE_FLOAT32NE);
|
||||
|
||||
for (i = start; i <= j; i++)
|
||||
for (c = 0; c < r->o_ss.channels; c++, s++) {
|
||||
float n = fabsf(*s);
|
||||
|
||||
if (n > r->peaks.max_f[c])
|
||||
r->peaks.max_f[c] = n;
|
||||
}
|
||||
|
||||
for (c = 0; c < r->o_ss.channels; c++, d++)
|
||||
*d = r->peaks.max_f[c];
|
||||
|
||||
memset(r->peaks.max_f, 0, sizeof(r->peaks.max_f));
|
||||
}
|
||||
}
|
||||
|
||||
pa_memblock_release(input->memblock);
|
||||
pa_memblock_release(output->memblock);
|
||||
|
||||
*out_n_frames = o_index;
|
||||
|
||||
r->peaks.i_counter += in_n_frames;
|
||||
|
||||
/* Normalize counters */
|
||||
while (r->peaks.i_counter >= r->i_ss.rate) {
|
||||
pa_assert(r->peaks.o_counter >= r->o_ss.rate);
|
||||
|
||||
r->peaks.i_counter -= r->i_ss.rate;
|
||||
r->peaks.o_counter -= r->o_ss.rate;
|
||||
}
|
||||
}
|
||||
|
||||
static void peaks_update_rates_or_reset(pa_resampler *r) {
|
||||
pa_assert(r);
|
||||
|
||||
r->peaks.i_counter = 0;
|
||||
r->peaks.o_counter = 0;
|
||||
}
|
||||
|
||||
static int peaks_init(pa_resampler*r) {
|
||||
pa_assert(r);
|
||||
|
||||
r->peaks.o_counter = r->peaks.i_counter = 0;
|
||||
memset(r->peaks.max_i, 0, sizeof(r->peaks.max_i));
|
||||
memset(r->peaks.max_f, 0, sizeof(r->peaks.max_f));
|
||||
|
||||
r->impl_resample = peaks_resample;
|
||||
r->impl_update_rates = peaks_update_rates_or_reset;
|
||||
r->impl_reset = peaks_update_rates_or_reset;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*** ffmpeg based implementation ***/
|
||||
|
||||
static void ffmpeg_resample(pa_resampler *r, const pa_memchunk *input, unsigned in_n_frames, pa_memchunk *output, unsigned *out_n_frames) {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue