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,
|
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
@ -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) {
|
||||||
|
@ -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
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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);
|
||||||
|
Loading…
Reference in New Issue
Block a user