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 "config.h"
#include "FlacCommon.hxx" #include "FlacCommon.hxx"
#include "FlacMetadata.hxx" #include "FlacMetadata.hxx"
#include "FlacPcm.hxx"
#include "FlacDomain.hxx"
#include "CheckAudioFormat.hxx"
#include "util/Error.hxx" #include "util/Error.hxx"
#include "util/ConstBuffer.hxx"
#include "Log.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 bool
FlacDecoder::Initialize(unsigned sample_rate, unsigned bits_per_sample, FlacDecoder::Initialize(unsigned sample_rate, unsigned bits_per_sample,
unsigned channels, FLAC__uint64 total_frames) unsigned channels, FLAC__uint64 total_frames)
@ -58,25 +35,15 @@ FlacDecoder::Initialize(unsigned sample_rate, unsigned bits_per_sample,
assert(!initialized); assert(!initialized);
assert(!unsupported); 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; ::Error error;
if (!audio_format_init_checked(audio_format, if (!pcm_import.Open(sample_rate, bits_per_sample,
sample_rate, channels, error)) {
sample_format,
channels, error)) {
LogError(error); LogError(error);
unsupported = true; unsupported = true;
return false; return false;
} }
frame_size = audio_format.GetFrameSize(); const auto audio_format = pcm_import.GetAudioFormat();
const auto duration = total_frames > 0 const auto duration = total_frames > 0
? SignedSongTime::FromScale<uint64_t>(total_frames, ? SignedSongTime::FromScale<uint64_t>(total_frames,
@ -174,18 +141,13 @@ FlacDecoder::OnWrite(const FLAC__Frame &frame,
if (!initialized && !OnFirstFrame(frame.header)) if (!initialized && !OnFirstFrame(frame.header))
return FLAC__STREAM_DECODER_WRITE_STATUS_ABORT; return FLAC__STREAM_DECODER_WRITE_STATUS_ABORT;
size_t buffer_size = frame.header.blocksize * frame_size; const auto data = pcm_import.Import(buf, frame.header.blocksize);
void *data = buffer.Get(buffer_size);
flac_convert(data, frame.header.channels,
audio_format.format, buf,
frame.header.blocksize);
unsigned bit_rate = nbytes * 8 * frame.header.sample_rate / unsigned bit_rate = nbytes * 8 * frame.header.sample_rate /
(1000 * frame.header.blocksize); (1000 * frame.header.blocksize);
auto cmd = decoder_data(*GetDecoder(), GetInputStream(), auto cmd = decoder_data(*GetDecoder(), GetInputStream(),
data, buffer_size, data.data, data.size,
bit_rate); bit_rate);
switch (cmd) { switch (cmd) {
case DecoderCommand::NONE: case DecoderCommand::NONE:

View File

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

View File

@ -19,9 +19,54 @@
#include "config.h" #include "config.h"
#include "FlacPcm.hxx" #include "FlacPcm.hxx"
#include "FlacDomain.hxx"
#include "CheckAudioFormat.hxx"
#include "util/Error.hxx"
#include "util/ConstBuffer.hxx"
#include <assert.h> #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> template<typename T>
static void static void
FlacImportStereo(T *dest, const FLAC__int32 *const src[], size_t n_frames) 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); FlacImportAny(dest, src, n_frames, n_channels);
} }
void template<typename T>
flac_convert(void *dest, static ConstBuffer<void>
unsigned int num_channels, SampleFormat sample_format, FlacImport(PcmBuffer &buffer, const FLAC__int32 *const src[], size_t n_frames,
const FLAC__int32 *const buf[], unsigned n_channels)
size_t n_frames)
{ {
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: case SampleFormat::S16:
FlacImport((int16_t *)dest, buf, n_frames, num_channels); return FlacImport<int16_t>(buffer, src, n_frames,
break; audio_format.channels);
case SampleFormat::S24_P32: case SampleFormat::S24_P32:
case SampleFormat::S32: case SampleFormat::S32:
FlacImport((int32_t *)dest, buf, n_frames, num_channels); return FlacImport<int32_t>(buffer, src, n_frames,
break; audio_format.channels);
case SampleFormat::S8: case SampleFormat::S8:
FlacImport((int8_t *)dest, buf, n_frames, num_channels); return FlacImport<int8_t>(buffer, src, n_frames,
break; audio_format.channels);
case SampleFormat::FLOAT: case SampleFormat::FLOAT:
case SampleFormat::DSD: case SampleFormat::DSD:
case SampleFormat::UNDEFINED: case SampleFormat::UNDEFINED:
assert(false); break;
gcc_unreachable();
} }
assert(false);
gcc_unreachable();
} }

View File

@ -20,16 +20,37 @@
#ifndef MPD_FLAC_PCM_HXX #ifndef MPD_FLAC_PCM_HXX
#define MPD_FLAC_PCM_HXX #define MPD_FLAC_PCM_HXX
#include "check.h"
#include "pcm/PcmBuffer.hxx"
#include "AudioFormat.hxx" #include "AudioFormat.hxx"
#include <FLAC/ordinals.h> #include <FLAC/ordinals.h>
#include <stddef.h> class Error;
template<typename T> struct ConstBuffer;
void /**
flac_convert(void *dest, * This class imports libFLAC PCM data into a PCM format supported by
unsigned int num_channels, SampleFormat sample_format, * MPD.
const FLAC__int32 *const buf[], */
size_t n_frames); 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 #endif