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 "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:
|
||||||
|
@ -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) {}
|
||||||
|
|
||||||
|
@ -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();
|
||||||
}
|
}
|
||||||
|
@ -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
|
||||||
|
Loading…
Reference in New Issue
Block a user