pcm_convert: return PCM buffer from pcm_convert()
Removed yet another superfluous buffer layer: return the PCM buffer from pcm_convert() instead of copying PCM data into the caller-supplied buffer.
This commit is contained in:
parent
e726e2a004
commit
356526457c
@ -191,9 +191,7 @@ decoder_data(struct decoder *decoder,
|
||||
float data_time, uint16_t bitRate,
|
||||
struct replay_gain_info *replay_gain_info)
|
||||
{
|
||||
static char *conv_buffer;
|
||||
static size_t conv_buffer_size;
|
||||
char *data;
|
||||
const char *data = _data;
|
||||
|
||||
assert(dc.state == DECODE_STATE_DECODE);
|
||||
assert(length % audio_format_frame_size(&dc.in_audio_format) == 0);
|
||||
@ -224,28 +222,16 @@ decoder_data(struct decoder *decoder,
|
||||
return cmd;
|
||||
}
|
||||
|
||||
if (audio_format_equals(&dc.in_audio_format, &dc.out_audio_format)) {
|
||||
data = _data;
|
||||
} else {
|
||||
size_t out_length =
|
||||
pcm_convert_size(&dc.in_audio_format, length,
|
||||
&dc.out_audio_format);
|
||||
if (out_length > conv_buffer_size) {
|
||||
g_free(conv_buffer);
|
||||
conv_buffer = g_malloc(out_length);
|
||||
conv_buffer_size = out_length;
|
||||
}
|
||||
|
||||
data = conv_buffer;
|
||||
length = pcm_convert(&dc.in_audio_format, _data,
|
||||
length, &dc.out_audio_format,
|
||||
data, &decoder->conv_state);
|
||||
if (!audio_format_equals(&dc.in_audio_format, &dc.out_audio_format)) {
|
||||
data = pcm_convert(&decoder->conv_state,
|
||||
&dc.in_audio_format, data, length,
|
||||
&dc.out_audio_format, &length);
|
||||
|
||||
/* under certain circumstances, pcm_convert() may
|
||||
return an empty buffer - this condition should be
|
||||
investigated further, but for now, do this check as
|
||||
a workaround: */
|
||||
if (length == 0)
|
||||
if (data == NULL)
|
||||
return DECODE_COMMAND_NONE;
|
||||
}
|
||||
|
||||
|
@ -142,8 +142,6 @@ void audio_output_finish(struct audio_output *audioOutput)
|
||||
|
||||
if (audioOutput->plugin->finish)
|
||||
audioOutput->plugin->finish(audioOutput->data);
|
||||
if (audioOutput->convBuffer)
|
||||
free(audioOutput->convBuffer);
|
||||
|
||||
notify_deinit(&audioOutput->notify);
|
||||
}
|
||||
|
@ -90,9 +90,6 @@ int audio_output_init(struct audio_output *ao, ConfigParam * param)
|
||||
ao->open = false;
|
||||
ao->reopen_after = 0;
|
||||
|
||||
ao->convBuffer = NULL;
|
||||
ao->convBufferLen = 0;
|
||||
|
||||
pcm_convert_init(&ao->convState);
|
||||
|
||||
if (format) {
|
||||
|
@ -79,8 +79,6 @@ struct audio_output {
|
||||
struct audio_format reqAudioFormat;
|
||||
|
||||
struct pcm_convert_state convState;
|
||||
char *convBuffer;
|
||||
size_t convBufferLen;
|
||||
|
||||
/**
|
||||
* The thread handle, or NULL if the output thread isn't
|
||||
|
@ -38,29 +38,6 @@ static void ao_command_finished(struct audio_output *ao)
|
||||
notify_signal(&audio_output_client_notify);
|
||||
}
|
||||
|
||||
static void convertAudioFormat(struct audio_output *audioOutput,
|
||||
const char **chunkArgPtr, size_t *sizeArgPtr)
|
||||
{
|
||||
size_t size = pcm_convert_size(&(audioOutput->inAudioFormat),
|
||||
*sizeArgPtr,
|
||||
&(audioOutput->outAudioFormat));
|
||||
|
||||
if (size > audioOutput->convBufferLen) {
|
||||
if (audioOutput->convBuffer != NULL)
|
||||
free(audioOutput->convBuffer);
|
||||
audioOutput->convBuffer = g_malloc(size);
|
||||
audioOutput->convBufferLen = size;
|
||||
}
|
||||
|
||||
*sizeArgPtr = pcm_convert(&(audioOutput->inAudioFormat),
|
||||
*chunkArgPtr, *sizeArgPtr,
|
||||
&(audioOutput->outAudioFormat),
|
||||
audioOutput->convBuffer,
|
||||
&audioOutput->convState);
|
||||
|
||||
*chunkArgPtr = audioOutput->convBuffer;
|
||||
}
|
||||
|
||||
static void ao_play(struct audio_output *ao)
|
||||
{
|
||||
const char *data = ao->args.play.data;
|
||||
@ -70,13 +47,15 @@ static void ao_play(struct audio_output *ao)
|
||||
assert(size > 0);
|
||||
|
||||
if (!audio_format_equals(&ao->inAudioFormat, &ao->outAudioFormat)) {
|
||||
convertAudioFormat(ao, &data, &size);
|
||||
data = pcm_convert(&ao->convState,
|
||||
&ao->inAudioFormat, data, size,
|
||||
&ao->outAudioFormat, &size);
|
||||
|
||||
/* under certain circumstances, pcm_convert() may
|
||||
return an empty buffer - this condition should be
|
||||
investigated further, but for now, do this check as
|
||||
a workaround: */
|
||||
if (size == 0)
|
||||
if (data == NULL)
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -48,12 +48,12 @@ void pcm_convert_deinit(struct pcm_convert_state *state)
|
||||
pcm_buffer_deinit(&state->channels_buffer);
|
||||
}
|
||||
|
||||
static size_t
|
||||
pcm_convert_16(const struct audio_format *src_format,
|
||||
static const int16_t *
|
||||
pcm_convert_16(struct pcm_convert_state *state,
|
||||
const struct audio_format *src_format,
|
||||
const void *src_buffer, size_t src_size,
|
||||
const struct audio_format *dest_format,
|
||||
int16_t *dest_buffer,
|
||||
struct pcm_convert_state *state)
|
||||
size_t *dest_size_r)
|
||||
{
|
||||
const int16_t *buf;
|
||||
size_t len;
|
||||
@ -82,18 +82,16 @@ pcm_convert_16(const struct audio_format *src_format,
|
||||
dest_format->sample_rate,
|
||||
&len);
|
||||
|
||||
assert(pcm_convert_size(src_format, src_size, dest_format) >= len);
|
||||
memcpy(dest_buffer, buf, len);
|
||||
|
||||
return len;
|
||||
*dest_size_r = len;
|
||||
return buf;
|
||||
}
|
||||
|
||||
static size_t
|
||||
pcm_convert_24(const struct audio_format *src_format,
|
||||
static const int32_t *
|
||||
pcm_convert_24(struct pcm_convert_state *state,
|
||||
const struct audio_format *src_format,
|
||||
const void *src_buffer, size_t src_size,
|
||||
const struct audio_format *dest_format,
|
||||
int32_t *dest_buffer,
|
||||
struct pcm_convert_state *state)
|
||||
size_t *dest_size_r)
|
||||
{
|
||||
const int32_t *buf;
|
||||
size_t len;
|
||||
@ -121,30 +119,30 @@ pcm_convert_24(const struct audio_format *src_format,
|
||||
dest_format->sample_rate,
|
||||
&len);
|
||||
|
||||
assert(pcm_convert_size(src_format, src_size, dest_format) >= len);
|
||||
memcpy(dest_buffer, buf, len);
|
||||
|
||||
return len;
|
||||
*dest_size_r = len;
|
||||
return buf;
|
||||
}
|
||||
|
||||
size_t pcm_convert(const struct audio_format *inFormat,
|
||||
const void *src, size_t src_size,
|
||||
const struct audio_format *outFormat,
|
||||
void *dest,
|
||||
struct pcm_convert_state *convState)
|
||||
const void *
|
||||
pcm_convert(struct pcm_convert_state *state,
|
||||
const struct audio_format *src_format,
|
||||
const void *src, size_t src_size,
|
||||
const struct audio_format *dest_format,
|
||||
size_t *dest_size_r)
|
||||
{
|
||||
switch (outFormat->bits) {
|
||||
switch (dest_format->bits) {
|
||||
case 16:
|
||||
return pcm_convert_16(inFormat, src, src_size,
|
||||
outFormat, (int16_t*)dest,
|
||||
convState);
|
||||
return pcm_convert_16(state,
|
||||
src_format, src, src_size,
|
||||
dest_format, dest_size_r);
|
||||
|
||||
case 24:
|
||||
return pcm_convert_24(inFormat, src, src_size,
|
||||
outFormat, (int32_t*)dest,
|
||||
convState);
|
||||
return pcm_convert_24(state,
|
||||
src_format, src, src_size,
|
||||
dest_format, dest_size_r);
|
||||
|
||||
default:
|
||||
g_error("cannot convert to %u bit\n", outFormat->bits);
|
||||
g_error("cannot convert to %u bit\n", dest_format->bits);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
@ -41,11 +41,12 @@ void pcm_convert_init(struct pcm_convert_state *state);
|
||||
|
||||
void pcm_convert_deinit(struct pcm_convert_state *state);
|
||||
|
||||
size_t pcm_convert(const struct audio_format *inFormat,
|
||||
const void *src, size_t src_size,
|
||||
const struct audio_format *outFormat,
|
||||
void *dest,
|
||||
struct pcm_convert_state *convState);
|
||||
const void *
|
||||
pcm_convert(struct pcm_convert_state *state,
|
||||
const struct audio_format *src_format,
|
||||
const void *src, size_t src_size,
|
||||
const struct audio_format *dest_format,
|
||||
size_t *dest_size_r);
|
||||
|
||||
size_t pcm_convert_size(const struct audio_format *inFormat, size_t inSize,
|
||||
const struct audio_format *outFormat);
|
||||
|
Loading…
Reference in New Issue
Block a user