diff options
author | Max Kellermann <max@duempel.org> | 2008-09-23 23:59:54 +0200 |
---|---|---|
committer | Eric Wong <normalperson@yhbt.net> | 2008-09-29 01:50:43 -0700 |
commit | a1c420d3f82da922821de8fd85bbea5eae54c3c3 (patch) | |
tree | abc873ac26655b9782d17649d162110ddfa2c3a3 /src/inputPlugins/_flac_common.c | |
parent | cc7fbb61e13ead2b4637f28aaa0c61441aed84a2 (diff) | |
download | mpd-a1c420d3f82da922821de8fd85bbea5eae54c3c3.tar.gz mpd-a1c420d3f82da922821de8fd85bbea5eae54c3c3.tar.xz mpd-a1c420d3f82da922821de8fd85bbea5eae54c3c3.zip |
flac: moved code from flacWrite() to _flac_common.c
There is still a lot of duplicated code in flac_plugin.c and
oggflac_plugin.c. Move code from flac_plugin.c to _flac_common.c, and
use the new function flac_common_write() also in oggflac_plugin.c,
porting lots of optimizations over to it.
Diffstat (limited to '')
-rw-r--r-- | src/inputPlugins/_flac_common.c | 85 |
1 files changed, 85 insertions, 0 deletions
diff --git a/src/inputPlugins/_flac_common.c b/src/inputPlugins/_flac_common.c index 9950f75db..ddf25a0b9 100644 --- a/src/inputPlugins/_flac_common.c +++ b/src/inputPlugins/_flac_common.c @@ -194,4 +194,89 @@ void flac_error_common_cb(const char *plugin, } } +/* keep this inlined, this is just macro but prettier :) */ +static inline enum dc_action flacSendChunk(FlacData * data) +{ + enum dc_action ret = ob_send(data->chunk, data->chunk_length, + data->time, data->bitRate, + data->replayGainInfo); + data->chunk_length = 0; + return ret; +} + +static void flac_convert_stereo16(unsigned char *dest, + const FLAC__int32 * const buf[], + unsigned int position, unsigned int end) +{ + for (; position < end; ++position) { + *(uint16_t*)dest = buf[0][position]; + dest += 2; + *(uint16_t*)dest = buf[1][position]; + dest += 2; + } +} + +static void flac_convert(unsigned char *dest, + unsigned int num_channels, + unsigned int bytes_per_sample, + const FLAC__int32 * const buf[], + unsigned int position, unsigned int end) +{ + unsigned int c_chan, i; + FLAC__uint16 u16; + unsigned char *uc; + + for (; position < end; ++position) { + for (c_chan = 0; c_chan < num_channels; c_chan++) { + u16 = buf[c_chan][position]; + uc = (unsigned char *)&u16; + for (i = 0; i < bytes_per_sample; i++) { + *dest++ = *uc++; + } + } + } +} + +FLAC__StreamDecoderWriteStatus +flac_common_write(FlacData *data, const FLAC__Frame * frame, + const FLAC__int32 *const buf[]) +{ + unsigned int c_samp; + const unsigned int num_channels = frame->header.channels; + const unsigned int bytes_per_sample = (dc.audio_format.bits / 8); + const unsigned int bytes_per_channel = + bytes_per_sample * frame->header.channels; + const unsigned int max_samples = FLAC_CHUNK_SIZE / bytes_per_channel; + unsigned int num_samples; + + assert(dc.audio_format.bits > 0); + + for (c_samp = 0; c_samp < frame->header.blocksize; + c_samp += num_samples) { + num_samples = frame->header.blocksize - c_samp; + if (num_samples > max_samples) + num_samples = max_samples; + + if (num_channels == 2 && bytes_per_sample == 2) + flac_convert_stereo16(data->chunk, + buf, c_samp, + c_samp + num_samples); + else + flac_convert(data->chunk, + num_channels, bytes_per_sample, buf, + c_samp, c_samp + num_samples); + data->chunk_length = num_samples * bytes_per_channel; + + switch (flacSendChunk(data)) { + case DC_ACTION_STOP: + return FLAC__STREAM_DECODER_WRITE_STATUS_ABORT; + case DC_ACTION_SEEK: + return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE; + default: break; /* compilers are complainers */ + } + } + + return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE; +} + #endif /* HAVE_FLAC || HAVE_OGGFLAC */ |