decoder/flac: refactor flac_convert() to class FlacPcmImport
This commit is contained in:
parent
b9de3270f6
commit
44219d5e91
@ -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:
|
||||
|
@ -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) {}
|
||||
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user