decoder/flac: refactor flac_convert() to class FlacPcmImport
This commit is contained in:
		@@ -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,
 | 
			
		||||
	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:
 | 
			
		||||
		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[],
 | 
			
		||||
/**
 | 
			
		||||
 * 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
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user