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:
Max Kellermann 2009-01-17 13:11:16 +01:00
parent e726e2a004
commit 356526457c
7 changed files with 43 additions and 86 deletions

View File

@ -191,9 +191,7 @@ decoder_data(struct decoder *decoder,
float data_time, uint16_t bitRate, float data_time, uint16_t bitRate,
struct replay_gain_info *replay_gain_info) struct replay_gain_info *replay_gain_info)
{ {
static char *conv_buffer; const char *data = _data;
static size_t conv_buffer_size;
char *data;
assert(dc.state == DECODE_STATE_DECODE); assert(dc.state == DECODE_STATE_DECODE);
assert(length % audio_format_frame_size(&dc.in_audio_format) == 0); assert(length % audio_format_frame_size(&dc.in_audio_format) == 0);
@ -224,28 +222,16 @@ decoder_data(struct decoder *decoder,
return cmd; return cmd;
} }
if (audio_format_equals(&dc.in_audio_format, &dc.out_audio_format)) { if (!audio_format_equals(&dc.in_audio_format, &dc.out_audio_format)) {
data = _data; data = pcm_convert(&decoder->conv_state,
} else { &dc.in_audio_format, data, length,
size_t out_length = &dc.out_audio_format, &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);
/* under certain circumstances, pcm_convert() may /* under certain circumstances, pcm_convert() may
return an empty buffer - this condition should be return an empty buffer - this condition should be
investigated further, but for now, do this check as investigated further, but for now, do this check as
a workaround: */ a workaround: */
if (length == 0) if (data == NULL)
return DECODE_COMMAND_NONE; return DECODE_COMMAND_NONE;
} }

View File

@ -142,8 +142,6 @@ void audio_output_finish(struct audio_output *audioOutput)
if (audioOutput->plugin->finish) if (audioOutput->plugin->finish)
audioOutput->plugin->finish(audioOutput->data); audioOutput->plugin->finish(audioOutput->data);
if (audioOutput->convBuffer)
free(audioOutput->convBuffer);
notify_deinit(&audioOutput->notify); notify_deinit(&audioOutput->notify);
} }

View File

@ -90,9 +90,6 @@ int audio_output_init(struct audio_output *ao, ConfigParam * param)
ao->open = false; ao->open = false;
ao->reopen_after = 0; ao->reopen_after = 0;
ao->convBuffer = NULL;
ao->convBufferLen = 0;
pcm_convert_init(&ao->convState); pcm_convert_init(&ao->convState);
if (format) { if (format) {

View File

@ -79,8 +79,6 @@ struct audio_output {
struct audio_format reqAudioFormat; struct audio_format reqAudioFormat;
struct pcm_convert_state convState; struct pcm_convert_state convState;
char *convBuffer;
size_t convBufferLen;
/** /**
* The thread handle, or NULL if the output thread isn't * The thread handle, or NULL if the output thread isn't

View File

@ -38,29 +38,6 @@ static void ao_command_finished(struct audio_output *ao)
notify_signal(&audio_output_client_notify); 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) static void ao_play(struct audio_output *ao)
{ {
const char *data = ao->args.play.data; const char *data = ao->args.play.data;
@ -70,13 +47,15 @@ static void ao_play(struct audio_output *ao)
assert(size > 0); assert(size > 0);
if (!audio_format_equals(&ao->inAudioFormat, &ao->outAudioFormat)) { 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 /* under certain circumstances, pcm_convert() may
return an empty buffer - this condition should be return an empty buffer - this condition should be
investigated further, but for now, do this check as investigated further, but for now, do this check as
a workaround: */ a workaround: */
if (size == 0) if (data == NULL)
return; return;
} }

View File

@ -48,12 +48,12 @@ void pcm_convert_deinit(struct pcm_convert_state *state)
pcm_buffer_deinit(&state->channels_buffer); pcm_buffer_deinit(&state->channels_buffer);
} }
static size_t static const int16_t *
pcm_convert_16(const struct audio_format *src_format, pcm_convert_16(struct pcm_convert_state *state,
const struct audio_format *src_format,
const void *src_buffer, size_t src_size, const void *src_buffer, size_t src_size,
const struct audio_format *dest_format, const struct audio_format *dest_format,
int16_t *dest_buffer, size_t *dest_size_r)
struct pcm_convert_state *state)
{ {
const int16_t *buf; const int16_t *buf;
size_t len; size_t len;
@ -82,18 +82,16 @@ pcm_convert_16(const struct audio_format *src_format,
dest_format->sample_rate, dest_format->sample_rate,
&len); &len);
assert(pcm_convert_size(src_format, src_size, dest_format) >= len); *dest_size_r = len;
memcpy(dest_buffer, buf, len); return buf;
return len;
} }
static size_t static const int32_t *
pcm_convert_24(const struct audio_format *src_format, pcm_convert_24(struct pcm_convert_state *state,
const struct audio_format *src_format,
const void *src_buffer, size_t src_size, const void *src_buffer, size_t src_size,
const struct audio_format *dest_format, const struct audio_format *dest_format,
int32_t *dest_buffer, size_t *dest_size_r)
struct pcm_convert_state *state)
{ {
const int32_t *buf; const int32_t *buf;
size_t len; size_t len;
@ -121,30 +119,30 @@ pcm_convert_24(const struct audio_format *src_format,
dest_format->sample_rate, dest_format->sample_rate,
&len); &len);
assert(pcm_convert_size(src_format, src_size, dest_format) >= len); *dest_size_r = len;
memcpy(dest_buffer, buf, len); return buf;
return len;
} }
size_t pcm_convert(const struct audio_format *inFormat, const void *
const void *src, size_t src_size, pcm_convert(struct pcm_convert_state *state,
const struct audio_format *outFormat, const struct audio_format *src_format,
void *dest, const void *src, size_t src_size,
struct pcm_convert_state *convState) const struct audio_format *dest_format,
size_t *dest_size_r)
{ {
switch (outFormat->bits) { switch (dest_format->bits) {
case 16: case 16:
return pcm_convert_16(inFormat, src, src_size, return pcm_convert_16(state,
outFormat, (int16_t*)dest, src_format, src, src_size,
convState); dest_format, dest_size_r);
case 24: case 24:
return pcm_convert_24(inFormat, src, src_size, return pcm_convert_24(state,
outFormat, (int32_t*)dest, src_format, src, src_size,
convState); dest_format, dest_size_r);
default: default:
g_error("cannot convert to %u bit\n", outFormat->bits); g_error("cannot convert to %u bit\n", dest_format->bits);
return 0; return 0;
} }
} }

View File

@ -41,11 +41,12 @@ void pcm_convert_init(struct pcm_convert_state *state);
void pcm_convert_deinit(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 *
const void *src, size_t src_size, pcm_convert(struct pcm_convert_state *state,
const struct audio_format *outFormat, const struct audio_format *src_format,
void *dest, const void *src, size_t src_size,
struct pcm_convert_state *convState); const struct audio_format *dest_format,
size_t *dest_size_r);
size_t pcm_convert_size(const struct audio_format *inFormat, size_t inSize, size_t pcm_convert_size(const struct audio_format *inFormat, size_t inSize,
const struct audio_format *outFormat); const struct audio_format *outFormat);