pcm_resample: use pcm_buffer (1/2)
Return a temporary buffer from pcm_resample_*() and pcm_convert().
This commit is contained in:
@@ -76,16 +76,15 @@ pcm_convert_16(const struct audio_format *src_format,
|
|||||||
g_error("pcm_convert_channels_16() failed");
|
g_error("pcm_convert_channels_16() failed");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (src_format->sample_rate == dest_format->sample_rate) {
|
if (src_format->sample_rate != dest_format->sample_rate)
|
||||||
assert(dest_size >= len);
|
buf = pcm_resample_16(&state->resample,
|
||||||
memcpy(dest_buffer, buf, len);
|
dest_format->channels,
|
||||||
} else {
|
|
||||||
len = pcm_resample_16(dest_format->channels,
|
|
||||||
src_format->sample_rate, buf, len,
|
src_format->sample_rate, buf, len,
|
||||||
dest_format->sample_rate,
|
dest_format->sample_rate,
|
||||||
dest_buffer, dest_size,
|
&len);
|
||||||
&state->resample);
|
|
||||||
}
|
assert(dest_size >= len);
|
||||||
|
memcpy(dest_buffer, buf, len);
|
||||||
|
|
||||||
return len;
|
return len;
|
||||||
}
|
}
|
||||||
@@ -117,16 +116,15 @@ pcm_convert_24(const struct audio_format *src_format,
|
|||||||
g_error("pcm_convert_channels_24() failed");
|
g_error("pcm_convert_channels_24() failed");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (src_format->sample_rate == dest_format->sample_rate) {
|
if (src_format->sample_rate != dest_format->sample_rate)
|
||||||
assert(dest_size >= len);
|
buf = pcm_resample_24(&state->resample,
|
||||||
memcpy(dest_buffer, buf, len);
|
dest_format->channels,
|
||||||
} else {
|
|
||||||
len = pcm_resample_24(dest_format->channels,
|
|
||||||
src_format->sample_rate, buf, len,
|
src_format->sample_rate, buf, len,
|
||||||
dest_format->sample_rate,
|
dest_format->sample_rate,
|
||||||
(int32_t*)dest_buffer, dest_size,
|
&len);
|
||||||
&state->resample);
|
|
||||||
}
|
assert(dest_size >= len);
|
||||||
|
memcpy(dest_buffer, buf, len);
|
||||||
|
|
||||||
return len;
|
return len;
|
||||||
}
|
}
|
||||||
|
@@ -23,4 +23,6 @@
|
|||||||
void pcm_resample_init(struct pcm_resample_state *state)
|
void pcm_resample_init(struct pcm_resample_state *state)
|
||||||
{
|
{
|
||||||
memset(state, 0, sizeof(*state));
|
memset(state, 0, sizeof(*state));
|
||||||
|
|
||||||
|
pcm_buffer_init(&state->buffer);
|
||||||
}
|
}
|
||||||
|
@@ -20,6 +20,7 @@
|
|||||||
#ifndef MPD_PCM_RESAMPLE_H
|
#ifndef MPD_PCM_RESAMPLE_H
|
||||||
#define MPD_PCM_RESAMPLE_H
|
#define MPD_PCM_RESAMPLE_H
|
||||||
|
|
||||||
|
#include "pcm_buffer.h"
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
@@ -44,30 +45,29 @@ struct pcm_resample_state {
|
|||||||
} prev;
|
} prev;
|
||||||
|
|
||||||
bool error;
|
bool error;
|
||||||
#else
|
|
||||||
/* struct must not be empty */
|
|
||||||
int dummy;
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
struct pcm_buffer buffer;
|
||||||
};
|
};
|
||||||
|
|
||||||
void pcm_resample_init(struct pcm_resample_state *state);
|
void pcm_resample_init(struct pcm_resample_state *state);
|
||||||
|
|
||||||
void pcm_resample_deinit(struct pcm_resample_state *state);
|
void pcm_resample_deinit(struct pcm_resample_state *state);
|
||||||
|
|
||||||
size_t
|
const int16_t *
|
||||||
pcm_resample_16(uint8_t channels,
|
pcm_resample_16(struct pcm_resample_state *state,
|
||||||
|
uint8_t channels,
|
||||||
unsigned src_rate,
|
unsigned src_rate,
|
||||||
const int16_t *src_buffer, size_t src_size,
|
const int16_t *src_buffer, size_t src_size,
|
||||||
unsigned dest_rate,
|
unsigned dest_rate,
|
||||||
int16_t *dest_buffer, size_t dest_size,
|
size_t *dest_size_r);
|
||||||
struct pcm_resample_state *state);
|
|
||||||
|
|
||||||
size_t
|
const int32_t *
|
||||||
pcm_resample_24(uint8_t channels,
|
pcm_resample_24(struct pcm_resample_state *state,
|
||||||
|
uint8_t channels,
|
||||||
unsigned src_rate,
|
unsigned src_rate,
|
||||||
const int32_t *src_buffer, size_t src_size,
|
const int32_t *src_buffer, size_t src_size,
|
||||||
unsigned dest_rate,
|
unsigned dest_rate,
|
||||||
int32_t *dest_buffer, size_t dest_size,
|
size_t *dest_size_r);
|
||||||
struct pcm_resample_state *state);
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@@ -22,25 +22,28 @@
|
|||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <glib.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 */
|
/* resampling code blatantly ripped from ESD */
|
||||||
size_t
|
const int16_t *
|
||||||
pcm_resample_16(uint8_t channels,
|
pcm_resample_16(struct pcm_resample_state *state,
|
||||||
|
uint8_t channels,
|
||||||
unsigned src_rate,
|
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,
|
unsigned dest_rate,
|
||||||
int16_t *dest_buffer, size_t dest_size,
|
size_t *dest_size_r)
|
||||||
G_GNUC_UNUSED struct pcm_resample_state *state)
|
|
||||||
{
|
{
|
||||||
unsigned src_pos, dest_pos = 0;
|
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((src_size % (sizeof(*src_buffer) * channels)) == 0);
|
||||||
assert((dest_size % (sizeof(*dest_buffer) * channels)) == 0);
|
|
||||||
|
|
||||||
switch (channels) {
|
switch (channels) {
|
||||||
case 1:
|
case 1:
|
||||||
@@ -61,19 +64,26 @@ pcm_resample_16(uint8_t channels,
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
return dest_size;
|
*dest_size_r = dest_size;
|
||||||
|
return dest_buffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t
|
const int32_t *
|
||||||
pcm_resample_24(uint8_t channels,
|
pcm_resample_24(struct pcm_resample_state *state,
|
||||||
|
uint8_t channels,
|
||||||
unsigned src_rate,
|
unsigned src_rate,
|
||||||
const int32_t *src_buffer, G_GNUC_UNUSED size_t src_size,
|
const int32_t *src_buffer, G_GNUC_UNUSED size_t src_size,
|
||||||
unsigned dest_rate,
|
unsigned dest_rate,
|
||||||
int32_t *dest_buffer, size_t dest_size,
|
size_t *dest_size_r)
|
||||||
G_GNUC_UNUSED struct pcm_resample_state *state)
|
|
||||||
{
|
{
|
||||||
unsigned src_pos, dest_pos = 0;
|
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) {
|
switch (channels) {
|
||||||
case 1:
|
case 1:
|
||||||
@@ -94,5 +104,6 @@ pcm_resample_24(uint8_t channels,
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
return dest_size;
|
*dest_size_r = dest_size;
|
||||||
|
return dest_buffer;
|
||||||
}
|
}
|
||||||
|
@@ -29,11 +29,12 @@
|
|||||||
#undef G_LOG_DOMAIN
|
#undef G_LOG_DOMAIN
|
||||||
#define G_LOG_DOMAIN "pcm"
|
#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)
|
if (state->state != NULL)
|
||||||
state->state = src_delete(state->state);
|
state->state = src_delete(state->state);
|
||||||
|
|
||||||
|
pcm_buffer_deinit(&state->buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int pcm_resample_get_converter(void)
|
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);
|
src_set_ratio(state->state, data->src_ratio);
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t
|
const int16_t *
|
||||||
pcm_resample_16(uint8_t channels,
|
pcm_resample_16(struct pcm_resample_state *state,
|
||||||
|
uint8_t channels,
|
||||||
unsigned src_rate,
|
unsigned src_rate,
|
||||||
const int16_t *src_buffer, size_t src_size,
|
const int16_t *src_buffer, size_t src_size,
|
||||||
unsigned dest_rate,
|
unsigned dest_rate,
|
||||||
int16_t *dest_buffer, size_t dest_size,
|
size_t *dest_size_r)
|
||||||
struct pcm_resample_state *state)
|
|
||||||
{
|
{
|
||||||
SRC_DATA *data = &state->data;
|
SRC_DATA *data = &state->data;
|
||||||
size_t data_in_size;
|
size_t data_in_size;
|
||||||
size_t data_out_size;
|
size_t data_out_size;
|
||||||
int error;
|
int error;
|
||||||
|
int16_t *dest_buffer;
|
||||||
|
|
||||||
assert((src_size % (sizeof(*src_buffer) * channels)) == 0);
|
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);
|
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->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;
|
data_out_size = data->output_frames * sizeof(float) * channels;
|
||||||
if (data_out_size > state->data_out_size) {
|
if (data_out_size > state->data_out_size) {
|
||||||
state->data_out_size = data_out_size;
|
state->data_out_size = data_out_size;
|
||||||
@@ -158,10 +159,13 @@ pcm_resample_16(uint8_t channels,
|
|||||||
return 0;
|
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,
|
src_float_to_short_array(data->data_out, dest_buffer,
|
||||||
data->output_frames_gen * channels);
|
data->output_frames_gen * channels);
|
||||||
|
|
||||||
return data->output_frames_gen * sizeof(*dest_buffer) * channels;
|
return dest_buffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef HAVE_LIBSAMPLERATE_NOINT
|
#ifdef HAVE_LIBSAMPLERATE_NOINT
|
||||||
@@ -184,21 +188,21 @@ src_float_to_int_array (const float *in, int *out, int len)
|
|||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
size_t
|
const int32_t *
|
||||||
pcm_resample_24(uint8_t channels,
|
pcm_resample_24(struct pcm_resample_state *state,
|
||||||
|
uint8_t channels,
|
||||||
unsigned src_rate,
|
unsigned src_rate,
|
||||||
const int32_t *src_buffer, size_t src_size,
|
const int32_t *src_buffer, size_t src_size,
|
||||||
unsigned dest_rate,
|
unsigned dest_rate,
|
||||||
int32_t *dest_buffer, size_t dest_size,
|
size_t *dest_size_r)
|
||||||
struct pcm_resample_state *state)
|
|
||||||
{
|
{
|
||||||
SRC_DATA *data = &state->data;
|
SRC_DATA *data = &state->data;
|
||||||
size_t data_in_size;
|
size_t data_in_size;
|
||||||
size_t data_out_size;
|
size_t data_out_size;
|
||||||
int error;
|
int error;
|
||||||
|
int32_t *dest_buffer;
|
||||||
|
|
||||||
assert((src_size % (sizeof(*src_buffer) * channels)) == 0);
|
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);
|
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->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;
|
data_out_size = data->output_frames * sizeof(float) * channels;
|
||||||
if (data_out_size > state->data_out_size) {
|
if (data_out_size > state->data_out_size) {
|
||||||
state->data_out_size = data_out_size;
|
state->data_out_size = data_out_size;
|
||||||
@@ -231,8 +235,11 @@ pcm_resample_24(uint8_t channels,
|
|||||||
return 0;
|
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,
|
src_float_to_int_array(data->data_out, dest_buffer,
|
||||||
data->output_frames_gen * channels);
|
data->output_frames_gen * channels);
|
||||||
|
|
||||||
return data->output_frames_gen * sizeof(*dest_buffer) * channels;
|
return dest_buffer;
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user