replace foxenflac with miniflac

it's better!
custom
jacqueline 1 year ago
parent b5d86a9497
commit 62d51a304e
  1. 2022
      lib/libfoxenflac/flac.c
  2. 297
      lib/libfoxenflac/include/foxen/flac.h
  3. 6
      lib/miniflac/CMakeLists.txt
  4. 5
      lib/miniflac/miniflac.c
  5. 6092
      lib/miniflac/miniflac.h
  6. 4
      src/codecs/CMakeLists.txt
  7. 4
      src/codecs/codec.cpp
  8. 110
      src/codecs/foxenflac.cpp
  9. 17
      src/codecs/include/miniflac.hpp
  10. 176
      src/codecs/miniflac.cpp
  11. 4
      src/database/track.cpp
  12. 2
      tools/cmake/common.cmake

File diff suppressed because it is too large Load Diff

@ -1,297 +0,0 @@
/*
* libfoxenflac -- Tiny FLAC Decoder Library
* Copyright (C) 2018-2022 Andreas Stöckel
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
/**
* @file flac.h
*
* Provides a decoder for FLAC (Free Lossless Audio Codec).
*
* @author Andreas Stöckel
*/
#ifndef FOXEN_FLAC_H
#define FOXEN_FLAC_H
#include <stdint.h>
#ifndef FX_EXPORT
#if __EMSCRIPTEN__
#import <emscripten.h>
#define FX_EXPORT EMSCRIPTEN_KEEPALIVE
#else
#define FX_EXPORT
#endif /* __EMSCRIPTEN__ */
#endif /* FX_EXPORT */
#ifdef __cplusplus
extern "C" {
#endif
/**
* Value returned by the fx_flac_get_streaminfo() method if the given streaminfo
* key is invalid.
*/
#define FLAC_INVALID_METADATA_KEY 0x7FFFFFFFFFFFFFFFULL
/**
* Maximum number of channels that can be encoded in a FLAC stream.
*/
#define FLAC_MAX_CHANNEL_COUNT 8U
/**
* Maximum block size that can be used if the stream is encoded in the FLAC
* Subset format and the sample rate is smaller than 48000 kHz.
*/
#define FLAC_SUBSET_MAX_BLOCK_SIZE_48KHZ 4608U
/**
* Maximum block size than can always be safely used if the stream is encoded
* in the FLAC Subset format.
*/
#define FLAC_SUBSET_MAX_BLOCK_SIZE 16384U
/**
* Maximum block size in samples that can be used in a FLAC stream.
*/
#define FLAC_MAX_BLOCK_SIZE 65535U
/**
* Opaque struct representing a FLAC decoder.
*/
struct fx_flac;
/**
* Typedef for the fx_flac struct.
*/
typedef struct fx_flac fx_flac_t;
/**
* Enum representing the state of a FLAC decoder instance.
*/
typedef enum {
/**
* The decoder is in an error state; the decoder cannot recover from this
* error. This error may for example occur if the data in the stream is
* invalid, or the stream has a format that is outside the maximum specs
* that are supported by the decoder. Call fx_flac_reset() and start anew!
*/
FLAC_ERR = -1,
/**
* The decoder is currently in its initial state, fx_flac_process() has not
* been called.
*/
FLAC_INIT = 0,
/**
* The decoder found the beginning of the metadata packet!
*/
FLAC_IN_METADATA = 1,
/**
* The decoder is done reading the current metadata block, this may be
* followed by more metadata blocks, in which case the state is reset to
* FLAC_IN_METADATA.
*/
FLAC_END_OF_METADATA = 2,
/**
* The decoder is currently searching for an audio frame.
*/
FLAC_SEARCH_FRAME = 3,
/**
* The decoder is currently inside the stream of audio frames.
*/
FLAC_IN_FRAME = 4,
/**
* The decoder successfully decoded an entire frame. Write the data to the
* client.
*/
FLAC_DECODED_FRAME = 5,
/**
* The decoder reached the end of a block.
*/
FLAC_END_OF_FRAME = 6
} fx_flac_state_t;
/**
* Enum used in fx_flac_get_streaminfo() to query metadata about the stream.
*/
typedef enum {
FLAC_KEY_MIN_BLOCK_SIZE = 0,
FLAC_KEY_MAX_BLOCK_SIZE = 1,
FLAC_KEY_MIN_FRAME_SIZE = 2,
FLAC_KEY_MAX_FRAME_SIZE = 3,
FLAC_KEY_SAMPLE_RATE = 4,
FLAC_KEY_N_CHANNELS = 5,
FLAC_KEY_SAMPLE_SIZE = 6,
FLAC_KEY_N_SAMPLES = 7,
FLAC_KEY_MD5_SUM_0 = 128,
FLAC_KEY_MD5_SUM_1 = 129,
FLAC_KEY_MD5_SUM_2 = 130,
FLAC_KEY_MD5_SUM_3 = 131,
FLAC_KEY_MD5_SUM_4 = 132,
FLAC_KEY_MD5_SUM_5 = 133,
FLAC_KEY_MD5_SUM_6 = 134,
FLAC_KEY_MD5_SUM_7 = 135,
FLAC_KEY_MD5_SUM_8 = 136,
FLAC_KEY_MD5_SUM_9 = 137,
FLAC_KEY_MD5_SUM_A = 138,
FLAC_KEY_MD5_SUM_B = 139,
FLAC_KEY_MD5_SUM_C = 140,
FLAC_KEY_MD5_SUM_D = 141,
FLAC_KEY_MD5_SUM_E = 142,
FLAC_KEY_MD5_SUM_F = 143,
} fx_flac_streaminfo_key_t;
/**
* Returns the size of the FLAC decoder instance in bytes. This assumes that the
* FLAC audio that is being decoded uses the maximum settings, i.e. the largest
* bit depth and block size. See fx_flac_init() regarding parameters.
*
* @return zero if the given parameters are out of range, the number of bytes
* required to hold the FLAC decoder structure otherwise.
*/
FX_EXPORT uint32_t fx_flac_size(uint32_t max_block_size, uint8_t max_channels);
/**
* Initializes the FLAC decoder at the given memory location. Each decoder can
* decode exactly one stream at a time.
*
* @param mem is a pointer at the memory region at which the FLAC decoder should
* store its private data. The memory region must be at last as large as
* indicated by fx_flac_size(). May be NULL, in which case NULL is returned.
* @param max_block_size is the maximum block size for which the FLAC instance
* will provide a buffer. For streams in the Subset format (which is used per
* default in most FLAC encoders), max_block_size should can be set to 4608 if
* the sample rate is <= 48000kHz, otherwise, for larger sample rates,
* max_block_size must be set to 16384.
* @param max_channels is the maximum number of channels that will be decoded.
* @return a pointer at the FLAC decoder instance; note that this pointer may be
* different from what was passed to mem. However, you may still pass the
* original `mem` as `inst` parameter to other functions. Returns NULL if the
* input pointer is NULL or the given parameters are invalid.
*/
FX_EXPORT fx_flac_t *fx_flac_init(void *mem, uint16_t max_block_size,
uint8_t max_channels);
/**
* Macro which calls malloc to allocate memory for a new fx_flac instance. The
* returned pointer must be freed using free. Returns NULL if the allocation
* fails or the given parameters are invalid.
*
* Note that this code is implemented as a macro to prevent explicitly having
* a dependency on malloc while still providing a convenient allocation routine.
*/
#define FX_FLAC_ALLOC(max_block_size, max_channels) \
(fx_flac_size((max_block_size), (max_channels)) == 0U) \
? NULL \
: fx_flac_init(malloc(fx_flac_size((max_block_size), (max_channels))), \
(max_block_size), (max_channels))
/**
* Returns a new fx_flac instance that is sufficient to decode FLAC streams in
* the FLAC Subset format with DAT parameters, i.e. up to 48 kHz, and two
* channels. This will allocate about 40 kiB of memory.
*/
#define FX_FLAC_ALLOC_SUBSET_FORMAT_DAT() \
FX_FLAC_ALLOC(FLAC_SUBSET_MAX_BLOCK_SIZE_48KHZ, 2U)
/**
* Returns a new fx_flac instance that is sufficient to decode FLAC streams in
* the FLAC Subset format. This will allocate about 1.5 MiB of memory.
*/
#define FX_FLAC_ALLOC_SUBSET_FORMAT_ANY() \
FX_FLAC_ALLOC(FLAC_SUBSET_MAX_BLOCK_SIZE, FLAC_MAX_CHANNEL_COUNT)
/**
* Returns a new fx_flac instance that is sufficient to decode any valid FLAC
* stream. Note that this will allocate between 2-3 MiB of memory.
*/
#define FX_FLAC_ALLOC_DEFAULT() \
FX_FLAC_ALLOC(FLAC_MAX_BLOCK_SIZE, FLAC_MAX_CHANNEL_COUNT)
/**
* Resets the FLAC decoder.
*
* @param inst is the FLAC decoder that should be reset.
*/
FX_EXPORT void fx_flac_reset(fx_flac_t *inst);
/**
* Returns the current decoder state.
*
* @param inst is the FLAC decoder instance for which the state should be
* returned.
* @return the current state of the decoder.
*/
FX_EXPORT fx_flac_state_t fx_flac_get_state(const fx_flac_t *inst);
/**
* Returns metadata about the FLAC stream that is currently being parsed. This
* function may only be called if the decoder is in the state
* FLAC_END_OF_METADATA or greater, otherwise the result may be undefined
* (it will likely return zero for most of the metadata keys).
*
* @param inst is a pointer at the FLAC decoder instance for which the metadata
* should be retrieved.
* @param key is the metadata that should be retrieved.
* @return the requested metadata value or FLAC_INVALID_METADATA_KEY if the
* given key is unknown.
*/
FX_EXPORT int64_t fx_flac_get_streaminfo(const fx_flac_t *inst,
fx_flac_streaminfo_key_t key);
/**
* Decodes the given raw FLAC data; the given data must be RAW FLAC data as
* specified in the FLAC format specification https://xiph.org/flac/format.html
* This function will always return right after the decoder transitions to a new
* relevant state.
*
* @param inst is the decoder instance.
* @param in is a pointer at the encoded bytestream.
* @param in_len is a pointer at a integer containing the number of valid bytes
* in "in". After the function returns, in will contain the number of bytes that
* were actually read. This number may be zero if the decoder is in the FLAC_ERR
* or FLAC_STREAM_DONE state, or the internal buffers are full and need to be
* flushed to the provided output first.
* @param out is a pointer at a memory region that will accept the decoded
* interleaved audio data. Samples are decoded as 32-bit signed integer; the
* minimum and maximum value will depend on the original bit depth of the audio
* stored in the bitstream. If this is NULL, the decoder will silently discard
* the output.
* @param out_len is a pointer at an integer containing the number of available
* signed 32-bit integers at the memory address pointed at by out. After the
* function returns, this value will contain the number of samples that were
* written. If this is NULL, the deocder will silently discard the output.
* @return the current state of the decoder. If the state transitions to
* FLAC_END_OF_METADATA, FLAC_END_OF_FRAME or FLAC_END_OF_STREAM this function
* will return immediately; only the data up to the point causing the transition
* has been read.
*/
FX_EXPORT fx_flac_state_t fx_flac_process(fx_flac_t *inst, const uint8_t *in,
uint32_t *in_len, int32_t *out,
uint32_t *out_len);
#ifdef __cplusplus
}
#endif
#endif /* FOXEN_FLAC_H */

@ -1,8 +1,4 @@
# Copyright 2023 jacqueline <me@jacqueline.id.au> # Copyright 2023 jacqueline <me@jacqueline.id.au>
# #
# SPDX-License-Identifier: GPL-3.0-only # SPDX-License-Identifier: GPL-3.0-only
idf_component_register(SRCS miniflac.c INCLUDE_DIRS .)
idf_component_register(
SRCS "flac.c"
INCLUDE_DIRS "include"
)

@ -0,0 +1,5 @@
#define MINIFLAC_IMPLEMENTATION
#define MINIFLAC_API
#define MINIFLAC_PRIVATE static inline
#include "miniflac.h"

File diff suppressed because it is too large Load Diff

@ -3,9 +3,9 @@
# SPDX-License-Identifier: GPL-3.0-only # SPDX-License-Identifier: GPL-3.0-only
idf_component_register( idf_component_register(
SRCS "codec.cpp" "mad.cpp" "foxenflac.cpp" "opus.cpp" "vorbis.cpp" SRCS "codec.cpp" "mad.cpp" "miniflac.cpp" "opus.cpp" "vorbis.cpp"
"source_buffer.cpp" "source_buffer.cpp"
INCLUDE_DIRS "include" INCLUDE_DIRS "include"
REQUIRES "result" "span" "libmad" "libfoxenflac" "tremor" "opusfile" "memory") REQUIRES "result" "span" "libmad" "miniflac" "tremor" "opusfile" "memory")
target_compile_options("${COMPONENT_LIB}" PRIVATE ${EXTRA_WARNINGS}) target_compile_options("${COMPONENT_LIB}" PRIVATE ${EXTRA_WARNINGS})

@ -9,8 +9,8 @@
#include <memory> #include <memory>
#include <optional> #include <optional>
#include "foxenflac.hpp"
#include "mad.hpp" #include "mad.hpp"
#include "miniflac.hpp"
#include "opus.hpp" #include "opus.hpp"
#include "types.hpp" #include "types.hpp"
#include "vorbis.hpp" #include "vorbis.hpp"
@ -41,7 +41,7 @@ auto CreateCodecForType(StreamType type) -> std::optional<ICodec*> {
case StreamType::kVorbis: case StreamType::kVorbis:
return new TremorVorbisDecoder(); return new TremorVorbisDecoder();
case StreamType::kFlac: case StreamType::kFlac:
return new FoxenFlacDecoder(); return new MiniFlacDecoder();
case StreamType::kOpus: case StreamType::kOpus:
return new XiphOpusDecoder(); return new XiphOpusDecoder();
default: default:

@ -1,110 +0,0 @@
/*
* Copyright 2023 jacqueline <me@jacqueline.id.au>
*
* SPDX-License-Identifier: GPL-3.0-only
*/
#include "foxenflac.hpp"
#include <stdint.h>
#include <sys/_stdint.h>
#include <cstdlib>
#include "esp_log.h"
#include "foxen/flac.h"
#include "sample.hpp"
namespace codecs {
[[maybe_unused]] static const char kTag[] = "flac";
FoxenFlacDecoder::FoxenFlacDecoder()
: input_(),
buffer_(),
flac_(fx_flac_init(
heap_caps_malloc(fx_flac_size(FLAC_SUBSET_MAX_BLOCK_SIZE_48KHZ, 2),
MALLOC_CAP_SPIRAM),
FLAC_SUBSET_MAX_BLOCK_SIZE_48KHZ,
2)) {}
FoxenFlacDecoder::~FoxenFlacDecoder() {
free(flac_);
}
auto FoxenFlacDecoder::OpenStream(std::shared_ptr<IStream> input)
-> cpp::result<OutputFormat, Error> {
input_ = input;
bool eof = false;
fx_flac_state_t state;
do {
eof = buffer_.Refill(input_.get());
buffer_.ConsumeBytes([&](cpp::span<std::byte> buf) -> size_t {
uint32_t bytes_used = buf.size();
state =
fx_flac_process(flac_, reinterpret_cast<const uint8_t*>(buf.data()),
&bytes_used, NULL, NULL);
return bytes_used;
});
} while (state != FLAC_END_OF_METADATA && !eof);
if (state != FLAC_END_OF_METADATA) {
if (state == FLAC_ERR) {
return cpp::fail(Error::kMalformedData);
} else {
return cpp::fail(Error::kOutOfInput);
}
}
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 cpp::fail(Error::kMalformedData);
}
OutputFormat format{
.num_channels = static_cast<uint8_t>(channels),
.sample_rate_hz = static_cast<uint32_t>(fs),
};
uint64_t num_samples = fx_flac_get_streaminfo(flac_, FLAC_KEY_N_SAMPLES);
if (num_samples > 0) {
format.total_samples = num_samples * channels;
}
return format;
}
auto FoxenFlacDecoder::DecodeTo(cpp::span<sample::Sample> output)
-> cpp::result<OutputInfo, Error> {
bool is_eof = buffer_.Refill(input_.get());
cpp::span<int32_t> output32{reinterpret_cast<int32_t*>(output.data()),
output.size() / 2};
uint32_t samples_written = output32.size();
fx_flac_state_t state;
buffer_.ConsumeBytes([&](cpp::span<std::byte> buf) -> size_t {
uint32_t bytes_read = buf.size_bytes();
state = fx_flac_process(flac_, reinterpret_cast<const uint8_t*>(buf.data()),
&bytes_read, output32.data(), &samples_written);
return bytes_read;
});
if (state == FLAC_ERR) {
return cpp::fail(Error::kMalformedData);
}
for (size_t i = 0; i < samples_written; i++) {
output[i] = output32[i] >> 16;
}
return OutputInfo{.samples_written = samples_written,
.is_stream_finished = samples_written == 0 && is_eof};
}
auto FoxenFlacDecoder::SeekTo(size_t target) -> cpp::result<void, Error> {
return {};
}
} // namespace codecs

@ -6,6 +6,7 @@
#pragma once #pragma once
#include <sys/_stdint.h>
#include <cstddef> #include <cstddef>
#include <cstdint> #include <cstdint>
#include <memory> #include <memory>
@ -13,7 +14,7 @@
#include <string> #include <string>
#include <utility> #include <utility>
#include "foxen/flac.h" #include "miniflac.h"
#include "sample.hpp" #include "sample.hpp"
#include "source_buffer.hpp" #include "source_buffer.hpp"
#include "span.hpp" #include "span.hpp"
@ -22,10 +23,10 @@
namespace codecs { namespace codecs {
class FoxenFlacDecoder : public ICodec { class MiniFlacDecoder : public ICodec {
public: public:
FoxenFlacDecoder(); MiniFlacDecoder();
~FoxenFlacDecoder(); ~MiniFlacDecoder();
auto OpenStream(std::shared_ptr<IStream> input) auto OpenStream(std::shared_ptr<IStream> input)
-> cpp::result<OutputFormat, Error> override; -> cpp::result<OutputFormat, Error> override;
@ -35,14 +36,16 @@ class FoxenFlacDecoder : public ICodec {
auto SeekTo(std::size_t target_sample) -> cpp::result<void, Error> override; auto SeekTo(std::size_t target_sample) -> cpp::result<void, Error> override;
FoxenFlacDecoder(const FoxenFlacDecoder&) = delete; MiniFlacDecoder(const MiniFlacDecoder&) = delete;
FoxenFlacDecoder& operator=(const FoxenFlacDecoder&) = delete; MiniFlacDecoder& operator=(const MiniFlacDecoder&) = delete;
private: private:
std::shared_ptr<IStream> input_; std::shared_ptr<IStream> input_;
SourceBuffer buffer_; SourceBuffer buffer_;
fx_flac_t* flac_; std::unique_ptr<miniflac_t> flac_;
std::array<int32_t*, 2> samples_by_channel_;
std::optional<size_t> current_sample_;
}; };
} // namespace codecs } // namespace codecs

@ -0,0 +1,176 @@
/*
* Copyright 2023 jacqueline <me@jacqueline.id.au>
*
* SPDX-License-Identifier: GPL-3.0-only
*/
#include "miniflac.hpp"
#include <stdint.h>
#include <sys/_stdint.h>
#include <cstdlib>
#include "esp_heap_caps.h"
#include "esp_log.h"
#include "miniflac.h"
#include "result.hpp"
#include "sample.hpp"
namespace codecs {
[[maybe_unused]] static const char kTag[] = "flac";
static constexpr size_t kMaxFrameSize = 4608;
MiniFlacDecoder::MiniFlacDecoder()
: input_(),
buffer_(),
flac_(reinterpret_cast<miniflac_t*>(
heap_caps_malloc(sizeof(miniflac_t),
MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT))),
current_sample_() {
miniflac_init(flac_.get(), MINIFLAC_CONTAINER_UNKNOWN);
for (int i = 0; i < samples_by_channel_.size(); i++) {
// Full decoded frames too big to fit in internal ram :(
samples_by_channel_[i] = reinterpret_cast<int32_t*>(
heap_caps_malloc(kMaxFrameSize * sizeof(int32_t), MALLOC_CAP_SPIRAM));
}
}
MiniFlacDecoder::~MiniFlacDecoder() {
for (int i = 0; i < samples_by_channel_.size(); i++) {
heap_caps_free(samples_by_channel_[i]);
}
}
auto MiniFlacDecoder::OpenStream(std::shared_ptr<IStream> input)
-> cpp::result<OutputFormat, Error> {
input_ = input;
MINIFLAC_RESULT res;
auto read_until_result = [&](auto fn) {
while (true) {
bool eof = buffer_.Refill(input_.get());
buffer_.ConsumeBytes(fn);
if (res == MINIFLAC_CONTINUE && !eof) {
continue;
}
break;
}
};
uint32_t sample_rate = 0;
read_until_result([&](cpp::span<std::byte> buf) -> size_t {
uint32_t bytes_used = 0;
res = miniflac_streaminfo_sample_rate(
flac_.get(), reinterpret_cast<const uint8_t*>(buf.data()),
buf.size_bytes(), &bytes_used, &sample_rate);
return bytes_used;
});
if (res != MINIFLAC_OK) {
return cpp::fail(Error::kMalformedData);
}
uint8_t channels = 0;
read_until_result([&](cpp::span<std::byte> buf) -> size_t {
uint32_t bytes_used = 0;
res = miniflac_streaminfo_channels(
flac_.get(), reinterpret_cast<const uint8_t*>(buf.data()),
buf.size_bytes(), &bytes_used, &channels);
return bytes_used;
});
if (res != MINIFLAC_OK) {
return cpp::fail(Error::kMalformedData);
}
uint64_t total_samples = 0;
read_until_result([&](cpp::span<std::byte> buf) -> size_t {
uint32_t bytes_used = 0;
res = miniflac_streaminfo_total_samples(
flac_.get(), reinterpret_cast<const uint8_t*>(buf.data()),
buf.size_bytes(), &bytes_used, &total_samples);
return bytes_used;
});
if (res != MINIFLAC_OK) {
return cpp::fail(Error::kMalformedData);
}
if (channels == 0 || channels > 2) {
return cpp::fail(Error::kMalformedData);
}
OutputFormat format{
.num_channels = static_cast<uint8_t>(channels),
.sample_rate_hz = static_cast<uint32_t>(sample_rate),
.total_samples = total_samples * channels,
};
return format;
}
auto MiniFlacDecoder::DecodeTo(cpp::span<sample::Sample> output)
-> cpp::result<OutputInfo, Error> {
bool is_eof = false;
if (!current_sample_) {
MINIFLAC_RESULT res = MINIFLAC_CONTINUE;
while (res == MINIFLAC_CONTINUE && !is_eof) {
is_eof = buffer_.Refill(input_.get());
buffer_.ConsumeBytes([&](cpp::span<std::byte> buf) -> size_t {
// FIXME: We should do a miniflac_sync first, in order to check that
// our sample buffers have enough space for the next frame.
uint32_t bytes_read = 0;
res = miniflac_decode(
flac_.get(), reinterpret_cast<const uint8_t*>(buf.data()),
buf.size_bytes(), &bytes_read, samples_by_channel_.data());
return bytes_read;
});
}
if (res == MINIFLAC_OK) {
current_sample_ = 0;
} else if (is_eof) {
return OutputInfo{
.samples_written = 0,
.is_stream_finished = true,
};
} else {
return cpp::fail(Error::kMalformedData);
}
}
size_t samples_written = 0;
if (current_sample_) {
const uint8_t shift = flac_->frame.header.bps - 16;
while (*current_sample_ < flac_->frame.header.block_size) {
if (samples_written + flac_->frame.header.channels >= output.size()) {
// We can't fit the next full PCM frame into the buffer.
return OutputInfo{.samples_written = samples_written,
.is_stream_finished = false};
}
for (int channel = 0; channel < flac_->frame.header.channels; channel++) {
output[samples_written++] = sample::FromSigned(
samples_by_channel_[channel][*current_sample_] >> shift, 16);
}
(*current_sample_)++;
}
}
current_sample_.reset();
return OutputInfo{.samples_written = samples_written,
.is_stream_finished = samples_written == 0 && is_eof};
}
auto MiniFlacDecoder::SeekTo(size_t target) -> cpp::result<void, Error> {
return {};
}
} // namespace codecs

@ -203,7 +203,7 @@ auto TrackTags::disc() const -> const std::optional<uint8_t>& {
} }
auto TrackTags::disc(const std::string_view s) -> void { auto TrackTags::disc(const std::string_view s) -> void {
disc_ = std::stoi({s.data(), s.size()}); disc_ = std::strtol(s.data(), nullptr, 10);
} }
auto TrackTags::track() const -> const std::optional<uint16_t>& { auto TrackTags::track() const -> const std::optional<uint16_t>& {
@ -211,7 +211,7 @@ auto TrackTags::track() const -> const std::optional<uint16_t>& {
} }
auto TrackTags::track(const std::string_view s) -> void { auto TrackTags::track(const std::string_view s) -> void {
track_ = std::stoi({s.data(), s.size()}); track_ = std::strtol(s.data(), nullptr, 10);
} }
auto TrackTags::albumOrder() const -> uint32_t { auto TrackTags::albumOrder() const -> uint32_t {

@ -16,7 +16,6 @@ list(APPEND EXTRA_COMPONENT_DIRS "$ENV{PROJ_PATH}/lib/esp-idf-lua")
list(APPEND EXTRA_COMPONENT_DIRS "$ENV{PROJ_PATH}/lib/fatfs") list(APPEND EXTRA_COMPONENT_DIRS "$ENV{PROJ_PATH}/lib/fatfs")
list(APPEND EXTRA_COMPONENT_DIRS "$ENV{PROJ_PATH}/lib/komihash") list(APPEND EXTRA_COMPONENT_DIRS "$ENV{PROJ_PATH}/lib/komihash")
list(APPEND EXTRA_COMPONENT_DIRS "$ENV{PROJ_PATH}/lib/libcppbor") list(APPEND EXTRA_COMPONENT_DIRS "$ENV{PROJ_PATH}/lib/libcppbor")
list(APPEND EXTRA_COMPONENT_DIRS "$ENV{PROJ_PATH}/lib/libfoxenflac")
list(APPEND EXTRA_COMPONENT_DIRS "$ENV{PROJ_PATH}/lib/libmad") list(APPEND EXTRA_COMPONENT_DIRS "$ENV{PROJ_PATH}/lib/libmad")
list(APPEND EXTRA_COMPONENT_DIRS "$ENV{PROJ_PATH}/lib/libtags") list(APPEND EXTRA_COMPONENT_DIRS "$ENV{PROJ_PATH}/lib/libtags")
list(APPEND EXTRA_COMPONENT_DIRS "$ENV{PROJ_PATH}/lib/lua-linenoise") list(APPEND EXTRA_COMPONENT_DIRS "$ENV{PROJ_PATH}/lib/lua-linenoise")
@ -24,6 +23,7 @@ list(APPEND EXTRA_COMPONENT_DIRS "$ENV{PROJ_PATH}/lib/lua-term")
list(APPEND EXTRA_COMPONENT_DIRS "$ENV{PROJ_PATH}/lib/luavgl") list(APPEND EXTRA_COMPONENT_DIRS "$ENV{PROJ_PATH}/lib/luavgl")
list(APPEND EXTRA_COMPONENT_DIRS "$ENV{PROJ_PATH}/lib/lvgl") list(APPEND EXTRA_COMPONENT_DIRS "$ENV{PROJ_PATH}/lib/lvgl")
list(APPEND EXTRA_COMPONENT_DIRS "$ENV{PROJ_PATH}/lib/millershuffle") list(APPEND EXTRA_COMPONENT_DIRS "$ENV{PROJ_PATH}/lib/millershuffle")
list(APPEND EXTRA_COMPONENT_DIRS "$ENV{PROJ_PATH}/lib/miniflac")
list(APPEND EXTRA_COMPONENT_DIRS "$ENV{PROJ_PATH}/lib/ogg") list(APPEND EXTRA_COMPONENT_DIRS "$ENV{PROJ_PATH}/lib/ogg")
list(APPEND EXTRA_COMPONENT_DIRS "$ENV{PROJ_PATH}/lib/opusfile") list(APPEND EXTRA_COMPONENT_DIRS "$ENV{PROJ_PATH}/lib/opusfile")
list(APPEND EXTRA_COMPONENT_DIRS "$ENV{PROJ_PATH}/lib/result") list(APPEND EXTRA_COMPONENT_DIRS "$ENV{PROJ_PATH}/lib/result")

Loading…
Cancel
Save