diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/pcm_convert.c | 30 | ||||
-rw-r--r-- | src/pcm_resample.c | 2 | ||||
-rw-r--r-- | src/pcm_resample.h | 22 | ||||
-rw-r--r-- | src/pcm_resample_fallback.c | 43 | ||||
-rw-r--r-- | src/pcm_resample_libsamplerate.c | 37 |
5 files changed, 76 insertions, 58 deletions
diff --git a/src/pcm_convert.c b/src/pcm_convert.c index b9db24b9a..9f285eae5 100644 --- a/src/pcm_convert.c +++ b/src/pcm_convert.c @@ -76,16 +76,15 @@ pcm_convert_16(const struct audio_format *src_format, g_error("pcm_convert_channels_16() failed"); } - if (src_format->sample_rate == dest_format->sample_rate) { - assert(dest_size >= len); - memcpy(dest_buffer, buf, len); - } else { - len = pcm_resample_16(dest_format->channels, + if (src_format->sample_rate != dest_format->sample_rate) + buf = pcm_resample_16(&state->resample, + dest_format->channels, src_format->sample_rate, buf, len, dest_format->sample_rate, - dest_buffer, dest_size, - &state->resample); - } + &len); + + assert(dest_size >= len); + memcpy(dest_buffer, buf, len); return len; } @@ -117,16 +116,15 @@ pcm_convert_24(const struct audio_format *src_format, g_error("pcm_convert_channels_24() failed"); } - if (src_format->sample_rate == dest_format->sample_rate) { - assert(dest_size >= len); - memcpy(dest_buffer, buf, len); - } else { - len = pcm_resample_24(dest_format->channels, + if (src_format->sample_rate != dest_format->sample_rate) + buf = pcm_resample_24(&state->resample, + dest_format->channels, src_format->sample_rate, buf, len, dest_format->sample_rate, - (int32_t*)dest_buffer, dest_size, - &state->resample); - } + &len); + + assert(dest_size >= len); + memcpy(dest_buffer, buf, len); return len; } diff --git a/src/pcm_resample.c b/src/pcm_resample.c index 097e13929..0a6fa0148 100644 --- a/src/pcm_resample.c +++ b/src/pcm_resample.c @@ -23,4 +23,6 @@ void pcm_resample_init(struct pcm_resample_state *state) { memset(state, 0, sizeof(*state)); + + pcm_buffer_init(&state->buffer); } diff --git a/src/pcm_resample.h b/src/pcm_resample.h index 69bf6316d..8a428d90b 100644 --- a/src/pcm_resample.h +++ b/src/pcm_resample.h @@ -20,6 +20,7 @@ #ifndef MPD_PCM_RESAMPLE_H #define MPD_PCM_RESAMPLE_H +#include "pcm_buffer.h" #include "config.h" #include <stdint.h> @@ -44,30 +45,29 @@ struct pcm_resample_state { } prev; bool error; -#else - /* struct must not be empty */ - int dummy; #endif + + struct pcm_buffer buffer; }; void pcm_resample_init(struct pcm_resample_state *state); void pcm_resample_deinit(struct pcm_resample_state *state); -size_t -pcm_resample_16(uint8_t channels, +const int16_t * +pcm_resample_16(struct pcm_resample_state *state, + uint8_t channels, unsigned src_rate, const int16_t *src_buffer, size_t src_size, unsigned dest_rate, - int16_t *dest_buffer, size_t dest_size, - struct pcm_resample_state *state); + size_t *dest_size_r); -size_t -pcm_resample_24(uint8_t channels, +const int32_t * +pcm_resample_24(struct pcm_resample_state *state, + uint8_t channels, unsigned src_rate, const int32_t *src_buffer, size_t src_size, unsigned dest_rate, - int32_t *dest_buffer, size_t dest_size, - struct pcm_resample_state *state); + size_t *dest_size_r); #endif diff --git a/src/pcm_resample_fallback.c b/src/pcm_resample_fallback.c index 560d68a87..dedb2eabc 100644 --- a/src/pcm_resample_fallback.c +++ b/src/pcm_resample_fallback.c @@ -22,25 +22,28 @@ #include <assert.h> #include <glib.h> -void pcm_resample_deinit(G_GNUC_UNUSED struct pcm_resample_state *state) +void pcm_resample_deinit(struct pcm_resample_state *state) { - /* no state, nothing to do */ + pcm_buffer_deinit(&state->buffer); } /* resampling code blatantly ripped from ESD */ -size_t -pcm_resample_16(uint8_t channels, +const int16_t * +pcm_resample_16(struct pcm_resample_state *state, + uint8_t channels, unsigned src_rate, - const int16_t *src_buffer, G_GNUC_UNUSED size_t src_size, + const int16_t *src_buffer, size_t src_size, unsigned dest_rate, - int16_t *dest_buffer, size_t dest_size, - G_GNUC_UNUSED struct pcm_resample_state *state) + size_t *dest_size_r) { unsigned src_pos, dest_pos = 0; - unsigned dest_samples = dest_size / sizeof(*dest_buffer); + unsigned src_samples = src_size / sizeof(*src_buffer); + unsigned dest_samples = + (src_samples * dest_rate + src_rate - 1) / src_rate; + size_t dest_size = dest_samples * sizeof(*src_buffer); + int16_t *dest_buffer = pcm_buffer_get(&state->buffer, dest_size); assert((src_size % (sizeof(*src_buffer) * channels)) == 0); - assert((dest_size % (sizeof(*dest_buffer) * channels)) == 0); switch (channels) { case 1: @@ -61,19 +64,26 @@ pcm_resample_16(uint8_t channels, break; } - return dest_size; + *dest_size_r = dest_size; + return dest_buffer; } -size_t -pcm_resample_24(uint8_t channels, +const int32_t * +pcm_resample_24(struct pcm_resample_state *state, + uint8_t channels, unsigned src_rate, const int32_t *src_buffer, G_GNUC_UNUSED size_t src_size, unsigned dest_rate, - int32_t *dest_buffer, size_t dest_size, - G_GNUC_UNUSED struct pcm_resample_state *state) + size_t *dest_size_r) { unsigned src_pos, dest_pos = 0; - unsigned dest_samples = dest_size / sizeof(*dest_buffer); + unsigned src_samples = src_size / sizeof(*src_buffer); + unsigned dest_samples = + (src_samples * dest_rate + src_rate - 1) / src_rate; + size_t dest_size = dest_samples * sizeof(*src_buffer); + int32_t *dest_buffer = pcm_buffer_get(&state->buffer, dest_size); + + assert((src_size % (sizeof(*src_buffer) * channels)) == 0); switch (channels) { case 1: @@ -94,5 +104,6 @@ pcm_resample_24(uint8_t channels, break; } - return dest_size; + *dest_size_r = dest_size; + return dest_buffer; } diff --git a/src/pcm_resample_libsamplerate.c b/src/pcm_resample_libsamplerate.c index ff7a7f95f..7e58db4a4 100644 --- a/src/pcm_resample_libsamplerate.c +++ b/src/pcm_resample_libsamplerate.c @@ -29,11 +29,12 @@ #undef G_LOG_DOMAIN #define G_LOG_DOMAIN "pcm" -void pcm_resample_deinit(G_GNUC_UNUSED struct pcm_resample_state *state) +void pcm_resample_deinit(struct pcm_resample_state *state) { if (state->state != NULL) state->state = src_delete(state->state); + pcm_buffer_deinit(&state->buffer); } static int pcm_resample_get_converter(void) @@ -111,21 +112,21 @@ pcm_resample_set(struct pcm_resample_state *state, src_set_ratio(state->state, data->src_ratio); } -size_t -pcm_resample_16(uint8_t channels, +const int16_t * +pcm_resample_16(struct pcm_resample_state *state, + uint8_t channels, unsigned src_rate, const int16_t *src_buffer, size_t src_size, unsigned dest_rate, - int16_t *dest_buffer, size_t dest_size, - struct pcm_resample_state *state) + size_t *dest_size_r) { SRC_DATA *data = &state->data; size_t data_in_size; size_t data_out_size; int error; + int16_t *dest_buffer; assert((src_size % (sizeof(*src_buffer) * channels)) == 0); - assert((dest_size % (sizeof(*dest_buffer) * channels)) == 0); pcm_resample_set(state, channels, src_rate, dest_rate); @@ -140,7 +141,7 @@ pcm_resample_16(uint8_t channels, data->data_in = g_realloc(data->data_in, data_in_size); } - data->output_frames = dest_size / sizeof(*dest_buffer) / channels; + data->output_frames = (src_size * dest_rate + src_rate - 1) / src_rate; data_out_size = data->output_frames * sizeof(float) * channels; if (data_out_size > state->data_out_size) { state->data_out_size = data_out_size; @@ -158,10 +159,13 @@ pcm_resample_16(uint8_t channels, return 0; } + *dest_size_r = data->output_frames_gen * + sizeof(*dest_buffer) * channels; + dest_buffer = pcm_buffer_get(&state->buffer, *dest_size_r); src_float_to_short_array(data->data_out, dest_buffer, data->output_frames_gen * channels); - return data->output_frames_gen * sizeof(*dest_buffer) * channels; + return dest_buffer; } #ifdef HAVE_LIBSAMPLERATE_NOINT @@ -184,21 +188,21 @@ src_float_to_int_array (const float *in, int *out, int len) #endif -size_t -pcm_resample_24(uint8_t channels, +const int32_t * +pcm_resample_24(struct pcm_resample_state *state, + uint8_t channels, unsigned src_rate, const int32_t *src_buffer, size_t src_size, unsigned dest_rate, - int32_t *dest_buffer, size_t dest_size, - struct pcm_resample_state *state) + size_t *dest_size_r) { SRC_DATA *data = &state->data; size_t data_in_size; size_t data_out_size; int error; + int32_t *dest_buffer; assert((src_size % (sizeof(*src_buffer) * channels)) == 0); - assert((dest_size % (sizeof(*dest_buffer) * channels)) == 0); pcm_resample_set(state, channels, src_rate, dest_rate); @@ -213,7 +217,7 @@ pcm_resample_24(uint8_t channels, data->data_in = g_realloc(data->data_in, data_in_size); } - data->output_frames = dest_size / sizeof(*dest_buffer) / channels; + data->output_frames = (src_size * dest_rate + src_rate - 1) / src_rate; data_out_size = data->output_frames * sizeof(float) * channels; if (data_out_size > state->data_out_size) { state->data_out_size = data_out_size; @@ -231,8 +235,11 @@ pcm_resample_24(uint8_t channels, return 0; } + *dest_size_r = data->output_frames_gen * + sizeof(*dest_buffer) * channels; + dest_buffer = pcm_buffer_get(&state->buffer, *dest_size_r); src_float_to_int_array(data->data_out, dest_buffer, data->output_frames_gen * channels); - return data->output_frames_gen * sizeof(*dest_buffer) * channels; + return dest_buffer; } |