aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/pcm_convert.c30
-rw-r--r--src/pcm_resample.c2
-rw-r--r--src/pcm_resample.h22
-rw-r--r--src/pcm_resample_fallback.c43
-rw-r--r--src/pcm_resample_libsamplerate.c37
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;
}