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.
This commit is contained in:
@@ -196,4 +196,95 @@ void flac_error_common_cb(const char *plugin,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* keep this inlined, this is just macro but prettier :) */
|
||||||
|
static inline int flacSendChunk(FlacData * data)
|
||||||
|
{
|
||||||
|
if (decoder_data(data->decoder, data->inStream,
|
||||||
|
1, data->chunk,
|
||||||
|
data->chunk_length, data->time,
|
||||||
|
data->bitRate,
|
||||||
|
data->replayGainInfo) == DECODE_COMMAND_STOP)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
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 =
|
||||||
|
audio_format_sample_size(&data->audio_format);
|
||||||
|
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(data->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;
|
||||||
|
|
||||||
|
if (flacSendChunk(data) < 0) {
|
||||||
|
return
|
||||||
|
FLAC__STREAM_DECODER_WRITE_STATUS_ABORT;
|
||||||
|
}
|
||||||
|
data->chunk_length = 0;
|
||||||
|
if (decoder_get_command(data->decoder) == DECODE_COMMAND_SEEK) {
|
||||||
|
return
|
||||||
|
FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE;
|
||||||
|
}
|
||||||
|
|
||||||
#endif /* HAVE_FLAC || HAVE_OGGFLAC */
|
#endif /* HAVE_FLAC || HAVE_OGGFLAC */
|
||||||
|
@@ -164,18 +164,9 @@ void flac_error_common_cb(const char *plugin,
|
|||||||
struct tag *copyVorbisCommentBlockToMpdTag(const FLAC__StreamMetadata * block,
|
struct tag *copyVorbisCommentBlockToMpdTag(const FLAC__StreamMetadata * block,
|
||||||
struct tag *tag);
|
struct tag *tag);
|
||||||
|
|
||||||
/* keep this inlined, this is just macro but prettier :) */
|
FLAC__StreamDecoderWriteStatus
|
||||||
static inline int flacSendChunk(FlacData * data)
|
flac_common_write(FlacData *data, const FLAC__Frame * frame,
|
||||||
{
|
const FLAC__int32 *const buf[]);
|
||||||
if (decoder_data(data->decoder, data->inStream,
|
|
||||||
1, data->chunk,
|
|
||||||
data->chunk_length, data->time,
|
|
||||||
data->bitRate,
|
|
||||||
data->replayGainInfo) == DECODE_COMMAND_STOP)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif /* HAVE_FLAC || HAVE_OGGFLAC */
|
#endif /* HAVE_FLAC || HAVE_OGGFLAC */
|
||||||
|
|
||||||
|
@@ -195,59 +195,16 @@ static void flacMetadata(mpd_unused const flac_decoder * dec,
|
|||||||
flac_metadata_common_cb(block, (FlacData *) vdata);
|
flac_metadata_common_cb(block, (FlacData *) vdata);
|
||||||
}
|
}
|
||||||
|
|
||||||
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++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static FLAC__StreamDecoderWriteStatus flacWrite(const flac_decoder *dec,
|
static FLAC__StreamDecoderWriteStatus flacWrite(const flac_decoder *dec,
|
||||||
const FLAC__Frame * frame,
|
const FLAC__Frame * frame,
|
||||||
const FLAC__int32 * const buf[],
|
const FLAC__int32 * const buf[],
|
||||||
void *vdata)
|
void *vdata)
|
||||||
{
|
{
|
||||||
FlacData *data = (FlacData *) vdata;
|
|
||||||
FLAC__uint32 samples = frame->header.blocksize;
|
FLAC__uint32 samples = frame->header.blocksize;
|
||||||
unsigned int c_samp;
|
FlacData *data = (FlacData *) vdata;
|
||||||
const unsigned int num_channels = frame->header.channels;
|
|
||||||
const unsigned int bytes_per_sample =
|
|
||||||
audio_format_sample_size(&data->audio_format);
|
|
||||||
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;
|
|
||||||
float timeChange;
|
float timeChange;
|
||||||
FLAC__uint64 newPosition = 0;
|
FLAC__uint64 newPosition = 0;
|
||||||
|
|
||||||
assert(data->audio_format.bits > 0);
|
|
||||||
|
|
||||||
timeChange = ((float)samples) / frame->header.sample_rate;
|
timeChange = ((float)samples) / frame->header.sample_rate;
|
||||||
data->time += timeChange;
|
data->time += timeChange;
|
||||||
|
|
||||||
@@ -261,34 +218,7 @@ static FLAC__StreamDecoderWriteStatus flacWrite(const flac_decoder *dec,
|
|||||||
}
|
}
|
||||||
data->position = newPosition;
|
data->position = newPosition;
|
||||||
|
|
||||||
for (c_samp = 0; c_samp < frame->header.blocksize;
|
return flac_common_write(data, frame, buf);
|
||||||
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;
|
|
||||||
|
|
||||||
if (flacSendChunk(data) < 0) {
|
|
||||||
return
|
|
||||||
FLAC__STREAM_DECODER_WRITE_STATUS_ABORT;
|
|
||||||
}
|
|
||||||
data->chunk_length = 0;
|
|
||||||
if (decoder_get_command(data->decoder) == DECODE_COMMAND_SEEK) {
|
|
||||||
return
|
|
||||||
FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct tag *flacMetadataDup(char *file, int *vorbisCommentFound)
|
static struct tag *flacMetadataDup(char *file, int *vorbisCommentFound)
|
||||||
|
@@ -157,50 +157,12 @@ static FLAC__StreamDecoderWriteStatus oggflacWrite(mpd_unused const
|
|||||||
{
|
{
|
||||||
FlacData *data = (FlacData *) vdata;
|
FlacData *data = (FlacData *) vdata;
|
||||||
FLAC__uint32 samples = frame->header.blocksize;
|
FLAC__uint32 samples = frame->header.blocksize;
|
||||||
FLAC__uint16 u16;
|
|
||||||
unsigned char *uc;
|
|
||||||
unsigned int c_samp, c_chan;
|
|
||||||
unsigned int i;
|
|
||||||
float timeChange;
|
float timeChange;
|
||||||
|
|
||||||
timeChange = ((float)samples) / frame->header.sample_rate;
|
timeChange = ((float)samples) / frame->header.sample_rate;
|
||||||
data->time += timeChange;
|
data->time += timeChange;
|
||||||
|
|
||||||
/* ogg123 uses a complicated method of calculating bitrate
|
return flac_common_write(data, frame, buf);
|
||||||
* with averaging which I'm not too fond of.
|
|
||||||
* (waste of memory/CPU cycles, especially given this is _lossless_)
|
|
||||||
* a get_decode_position() is not available in OggFLAC, either
|
|
||||||
*
|
|
||||||
* this does not give an accurate bitrate:
|
|
||||||
* (bytes_last_read was set in the read callback)
|
|
||||||
data->bitRate = ((8.0 * data->bytes_last_read *
|
|
||||||
frame->header.sample_rate)
|
|
||||||
/((float)samples * 1000)) + 0.5;
|
|
||||||
*/
|
|
||||||
|
|
||||||
for (c_samp = 0; c_samp < frame->header.blocksize; c_samp++) {
|
|
||||||
for (c_chan = 0; c_chan < frame->header.channels;
|
|
||||||
c_chan++) {
|
|
||||||
u16 = buf[c_chan][c_samp];
|
|
||||||
uc = (unsigned char *)&u16;
|
|
||||||
for (i = 0; i < audio_format_sample_size(&data->audio_format); i++) {
|
|
||||||
if (data->chunk_length >= FLAC_CHUNK_SIZE) {
|
|
||||||
if (flacSendChunk(data) < 0) {
|
|
||||||
return
|
|
||||||
FLAC__STREAM_DECODER_WRITE_STATUS_ABORT;
|
|
||||||
}
|
|
||||||
data->chunk_length = 0;
|
|
||||||
if (decoder_get_command(data->decoder) == DECODE_COMMAND_SEEK) {
|
|
||||||
return
|
|
||||||
FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
data->chunk[data->chunk_length++] = *(uc++);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* used by TagDup */
|
/* used by TagDup */
|
||||||
@@ -372,12 +334,6 @@ static int oggflac_decode(struct decoder * mpd_decoder, InputStream * inStream)
|
|||||||
(OggFLAC__seekable_stream_decoder_get_state(decoder));
|
(OggFLAC__seekable_stream_decoder_get_state(decoder));
|
||||||
OggFLAC__seekable_stream_decoder_finish(decoder);
|
OggFLAC__seekable_stream_decoder_finish(decoder);
|
||||||
}
|
}
|
||||||
/* send last little bit */
|
|
||||||
if (data.chunk_length > 0 &&
|
|
||||||
decoder_get_command(mpd_decoder) == DECODE_COMMAND_NONE) {
|
|
||||||
flacSendChunk(&data);
|
|
||||||
decoder_flush(mpd_decoder);
|
|
||||||
}
|
|
||||||
|
|
||||||
fail:
|
fail:
|
||||||
oggflac_cleanup(&data, decoder);
|
oggflac_cleanup(&data, decoder);
|
||||||
|
Reference in New Issue
Block a user