From a2c1dfbabddc2b4abaf8bf27c9ed9d1b99594859 Mon Sep 17 00:00:00 2001 From: jacqueline Date: Thu, 15 Jun 2023 10:33:46 +1000 Subject: Add vorbis and flac decoders, flesh out codec interface vorbis doesn't quite work yet, not sure why. will pick it up again later. --- src/codecs/foxenflac.cpp | 80 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 80 insertions(+) create mode 100644 src/codecs/foxenflac.cpp (limited to 'src/codecs/foxenflac.cpp') diff --git a/src/codecs/foxenflac.cpp b/src/codecs/foxenflac.cpp new file mode 100644 index 00000000..a2d6f000 --- /dev/null +++ b/src/codecs/foxenflac.cpp @@ -0,0 +1,80 @@ +/* + * Copyright 2023 jacqueline + * + * SPDX-License-Identifier: GPL-3.0-only + */ + +#include "foxenflac.hpp" +#include + +#include + +#include "esp_log.h" +#include "foxen/flac.h" + +namespace codecs { + +FoxenFlacDecoder::FoxenFlacDecoder() + : flac_(FX_FLAC_ALLOC(FLAC_MAX_BLOCK_SIZE, 2)) {} + +FoxenFlacDecoder::~FoxenFlacDecoder() { + free(flac_); +} + +auto FoxenFlacDecoder::BeginStream(const cpp::span input) + -> Result { + uint32_t bytes_used = input.size_bytes(); + fx_flac_state_t state = + fx_flac_process(flac_, reinterpret_cast(input.data()), + &bytes_used, NULL, NULL); + if (state != FLAC_END_OF_METADATA) { + return {bytes_used, cpp::fail(Error::kMalformedData)}; + } + + int64_t channels = fx_flac_get_streaminfo(flac_, FLAC_KEY_N_CHANNELS); + int64_t fs = fx_flac_get_streaminfo(flac_, FLAC_KEY_SAMPLE_RATE); + if (channels == FLAC_INVALID_METADATA_KEY || + fs == FLAC_INVALID_METADATA_KEY) { + return {bytes_used, cpp::fail(Error::kMalformedData)}; + } + + return {bytes_used, + OutputFormat{ + .num_channels = static_cast(channels), + .bits_per_sample = 32, // libfoxenflac output is fixed-size. + .sample_rate_hz = static_cast(fs), + }}; +} + +auto FoxenFlacDecoder::ContinueStream(cpp::span input, + cpp::span output) + -> Result { + cpp::span output_as_samples{ + reinterpret_cast(output.data()), output.size_bytes() / 4}; + uint32_t bytes_read = input.size_bytes(); + uint32_t samples_written = output_as_samples.size(); + + fx_flac_state_t state = + fx_flac_process(flac_, reinterpret_cast(input.data()), + &bytes_read, output_as_samples.data(), &samples_written); + if (state == FLAC_ERR) { + return {bytes_read, cpp::fail(Error::kMalformedData)}; + } + + if (samples_written > 0) { + return {bytes_read, + OutputInfo{.bytes_written = samples_written * 4, + .is_finished_writing = state == FLAC_END_OF_FRAME}}; + } + + // No error, but no samples written. We must be out of data. + return {bytes_read, cpp::fail(Error::kOutOfInput)}; +} + +auto FoxenFlacDecoder::SeekStream(cpp::span input, + std::size_t target_sample) -> Result { + // TODO(jacqueline): Implement me. + return {0, {}}; +} + +} // namespace codecs -- cgit v1.2.3