decoder/flac: refactor flac_convert() to class FlacPcmImport

This commit is contained in:
Max Kellermann 2016-07-11 23:12:14 +02:00
parent b9de3270f6
commit 44219d5e91
4 changed files with 105 additions and 78 deletions

View File

@ -24,33 +24,10 @@
#include "config.h"
#include "FlacCommon.hxx"
#include "FlacMetadata.hxx"
#include "FlacPcm.hxx"
#include "FlacDomain.hxx"
#include "CheckAudioFormat.hxx"
#include "util/Error.hxx"
#include "util/ConstBuffer.hxx"
#include "Log.hxx"
static SampleFormat
flac_sample_format(unsigned bits_per_sample)
{
switch (bits_per_sample) {
case 8:
return SampleFormat::S8;
case 16:
return SampleFormat::S16;
case 24:
return SampleFormat::S24_P32;
case 32:
return SampleFormat::S32;
default:
return SampleFormat::UNDEFINED;
}
}
bool
FlacDecoder::Initialize(unsigned sample_rate, unsigned bits_per_sample,
unsigned channels, FLAC__uint64 total_frames)
@ -58,25 +35,15 @@ FlacDecoder::Initialize(unsigned sample_rate, unsigned bits_per_sample,
assert(!initialized);
assert(!unsupported);
auto sample_format = flac_sample_format(bits_per_sample);
if (sample_format == SampleFormat::UNDEFINED) {
FormatWarning(flac_domain, "Unsupported FLAC bit depth: %u",
bits_per_sample);
unsupported = true;
return false;
}
::Error error;
if (!audio_format_init_checked(audio_format,
sample_rate,
sample_format,
channels, error)) {
if (!pcm_import.Open(sample_rate, bits_per_sample,
channels, error)) {
LogError(error);
unsupported = true;
return false;
}
frame_size = audio_format.GetFrameSize();
const auto audio_format = pcm_import.GetAudioFormat();
const auto duration = total_frames > 0
? SignedSongTime::FromScale<uint64_t>(total_frames,
@ -174,18 +141,13 @@ FlacDecoder::OnWrite(const FLAC__Frame &frame,
if (!initialized && !OnFirstFrame(frame.header))
return FLAC__STREAM_DECODER_WRITE_STATUS_ABORT;
size_t buffer_size = frame.header.blocksize * frame_size;
void *data = buffer.Get(buffer_size);
flac_convert(data, frame.header.channels,
audio_format.format, buf,
frame.header.blocksize);
const auto data = pcm_import.Import(buf, frame.header.blocksize);
unsigned bit_rate = nbytes * 8 * frame.header.sample_rate /
(1000 * frame.header.blocksize);
auto cmd = decoder_data(*GetDecoder(), GetInputStream(),
data, buffer_size,
data.data, data.size,
bit_rate);
switch (cmd) {
case DecoderCommand::NONE:

View File

@ -25,19 +25,12 @@
#define MPD_FLAC_COMMON_HXX
#include "FlacInput.hxx"
#include "FlacPcm.hxx"
#include "../DecoderAPI.hxx"
#include "pcm/PcmBuffer.hxx"
#include <FLAC/stream_decoder.h>
struct FlacDecoder : public FlacInput {
PcmBuffer buffer;
/**
* The size of one frame in the output buffer.
*/
unsigned frame_size;
/**
* Has decoder_initialized() been called yet?
*/
@ -48,11 +41,7 @@ struct FlacDecoder : public FlacInput {
*/
bool unsupported = false;
/**
* The validated audio format of the FLAC file. This
* attribute is defined if "initialized" is true.
*/
AudioFormat audio_format;
FlacPcmImport pcm_import;
/**
* End of last frame's position within the stream. This is
@ -62,7 +51,6 @@ struct FlacDecoder : public FlacInput {
Tag tag;
FlacDecoder(Decoder &_decoder, InputStream &_input_stream)
:FlacInput(_input_stream, &_decoder) {}

View File

@ -19,9 +19,54 @@
#include "config.h"
#include "FlacPcm.hxx"
#include "FlacDomain.hxx"
#include "CheckAudioFormat.hxx"
#include "util/Error.hxx"
#include "util/ConstBuffer.hxx"
#include <assert.h>
static SampleFormat
flac_sample_format(unsigned bits_per_sample)
{
switch (bits_per_sample) {
case 8:
return SampleFormat::S8;
case 16:
return SampleFormat::S16;
case 24:
return SampleFormat::S24_P32;
case 32:
return SampleFormat::S32;
default:
return SampleFormat::UNDEFINED;
}
}
bool
FlacPcmImport::Open(unsigned sample_rate, unsigned bits_per_sample,
unsigned channels, Error &error)
{
auto sample_format = flac_sample_format(bits_per_sample);
if (sample_format == SampleFormat::UNDEFINED) {
error.Format(flac_domain, "Unsupported FLAC bit depth: %u",
bits_per_sample);
return false;
}
if (!audio_format_init_checked(audio_format,
sample_rate,
sample_format,
channels, error))
return false;
return true;
}
template<typename T>
static void
FlacImportStereo(T *dest, const FLAC__int32 *const src[], size_t n_frames)
@ -53,30 +98,41 @@ FlacImport(T *dest, const FLAC__int32 *const src[], size_t n_frames,
FlacImportAny(dest, src, n_frames, n_channels);
}
void
flac_convert(void *dest,
unsigned int num_channels, SampleFormat sample_format,
const FLAC__int32 *const buf[],
size_t n_frames)
template<typename T>
static ConstBuffer<void>
FlacImport(PcmBuffer &buffer, const FLAC__int32 *const src[], size_t n_frames,
unsigned n_channels)
{
switch (sample_format) {
size_t n_samples = n_frames * n_channels;
size_t dest_size = n_samples * sizeof(T);
T *dest = (T *)buffer.Get(dest_size);
FlacImport(dest, src, n_frames, n_channels);
return {dest, dest_size};
}
ConstBuffer<void>
FlacPcmImport::Import(const FLAC__int32 *const src[], size_t n_frames)
{
switch (audio_format.format) {
case SampleFormat::S16:
FlacImport((int16_t *)dest, buf, n_frames, num_channels);
break;
return FlacImport<int16_t>(buffer, src, n_frames,
audio_format.channels);
case SampleFormat::S24_P32:
case SampleFormat::S32:
FlacImport((int32_t *)dest, buf, n_frames, num_channels);
break;
return FlacImport<int32_t>(buffer, src, n_frames,
audio_format.channels);
case SampleFormat::S8:
FlacImport((int8_t *)dest, buf, n_frames, num_channels);
break;
return FlacImport<int8_t>(buffer, src, n_frames,
audio_format.channels);
case SampleFormat::FLOAT:
case SampleFormat::DSD:
case SampleFormat::UNDEFINED:
assert(false);
gcc_unreachable();
break;
}
assert(false);
gcc_unreachable();
}

View File

@ -20,16 +20,37 @@
#ifndef MPD_FLAC_PCM_HXX
#define MPD_FLAC_PCM_HXX
#include "check.h"
#include "pcm/PcmBuffer.hxx"
#include "AudioFormat.hxx"
#include <FLAC/ordinals.h>
#include <stddef.h>
class Error;
template<typename T> struct ConstBuffer;
void
flac_convert(void *dest,
unsigned int num_channels, SampleFormat sample_format,
const FLAC__int32 *const buf[],
size_t n_frames);
/**
* This class imports libFLAC PCM data into a PCM format supported by
* MPD.
*/
class FlacPcmImport {
PcmBuffer buffer;
AudioFormat audio_format;
public:
/**
* @return false on error
*/
bool Open(unsigned sample_rate, unsigned bits_per_sample,
unsigned channels, Error &error);
const AudioFormat &GetAudioFormat() const {
return audio_format;
}
ConstBuffer<void> Import(const FLAC__int32 *const src[],
size_t n_frames);
};
#endif