summaryrefslogtreecommitdiff
path: root/src/audio/fatfs_audio_input.cpp
diff options
context:
space:
mode:
authorjacqueline <me@jacqueline.id.au>2023-07-26 17:11:23 +1000
committerjacqueline <me@jacqueline.id.au>2023-07-26 17:11:23 +1000
commit9b1b401dcb986a26d10bcc898be670653acc2d3f (patch)
tree697b14553dc75ddaab060406cd62ee4b08f05e9e /src/audio/fatfs_audio_input.cpp
parentf94be3db2f2bb6c1b359744cb915683095e4ee80 (diff)
downloadtangara-fw-9b1b401dcb986a26d10bcc898be670653acc2d3f.tar.gz
big cleanup of new encoder + stream buffer types
Diffstat (limited to 'src/audio/fatfs_audio_input.cpp')
-rw-r--r--src/audio/fatfs_audio_input.cpp76
1 files changed, 31 insertions, 45 deletions
diff --git a/src/audio/fatfs_audio_input.cpp b/src/audio/fatfs_audio_input.cpp
index 811c2702..d5df61df 100644
--- a/src/audio/fatfs_audio_input.cpp
+++ b/src/audio/fatfs_audio_input.cpp
@@ -145,21 +145,15 @@ FatfsAudioInput::FatfsAudioInput(
has_data_(xSemaphoreCreateBinary()),
streamer_buffer_(xStreamBufferCreate(kStreamerBufferSize, 1)),
streamer_(new FileStreamer(streamer_buffer_, has_data_)),
- file_buffer_info_(),
- file_buffer_len_(kFileBufferSize),
- file_buffer_(reinterpret_cast<std::byte*>(
- heap_caps_malloc(file_buffer_len_,
- MALLOC_CAP_8BIT | MALLOC_CAP_INTERNAL))),
- file_buffer_stream_(&file_buffer_info_, {file_buffer_, file_buffer_len_}),
+ input_buffer_(new RawStream(kFileBufferSize)),
source_mutex_(),
pending_path_(),
- current_format_() {}
+ is_first_read_(false) {}
FatfsAudioInput::~FatfsAudioInput() {
streamer_.reset();
vStreamBufferDelete(streamer_buffer_);
vSemaphoreDelete(has_data_);
- free(file_buffer_);
}
auto FatfsAudioInput::SetPath(std::future<std::optional<std::string>> fut)
@@ -185,10 +179,8 @@ auto FatfsAudioInput::SetPath() -> void {
CloseCurrentFile();
}
-auto FatfsAudioInput::Read(
- std::function<bool(StreamInfo::Format)> can_read,
- std::function<size_t(cpp::span<const std::byte>)> read,
- TickType_t max_wait) -> void {
+auto FatfsAudioInput::Read(std::function<void(Flags, InputStream&)> read_cb,
+ TickType_t max_wait) -> void {
// Wait until we have data to return.
xSemaphoreTake(has_data_, portMAX_DELAY);
@@ -205,7 +197,7 @@ auto FatfsAudioInput::Read(
auto res = pending_path_->Result();
pending_path_.reset();
- if (res || *res) {
+ if (res && *res) {
OpenFile(**res);
}
@@ -217,28 +209,22 @@ auto FatfsAudioInput::Read(
// Move data from the file streamer's buffer into our file buffer. We need our
// own buffer so that we can handle concatenating smaller file chunks into
// complete frames for the decoder.
- OutputStream writer{&file_buffer_stream_};
+ OutputStream writer{input_buffer_.get()};
std::size_t bytes_added =
xStreamBufferReceive(streamer_buffer_, writer.data().data(),
writer.data().size_bytes(), pdMS_TO_TICKS(0));
writer.add(bytes_added);
- // HACK: libmad needs at least MAD_HEADER_GUARD (= 8) extra bytes following a
- // frame, or else it refuses to decode it.
- if (IsCurrentFormatMp3() && !HasDataRemaining()) {
- ESP_LOGI(kTag, "applying MAD_HEADER_GUARD fix");
- cpp::span<std::byte> buf = writer.data();
- size_t pad_amount = std::min<size_t>(buf.size_bytes(), 8);
- std::fill_n(buf.begin(), pad_amount, static_cast<std::byte>(0));
- }
+ bool has_data_remaining = HasDataRemaining();
- InputStream reader{&file_buffer_stream_};
+ InputStream reader{input_buffer_.get()};
auto data_for_cb = reader.data();
- if (!data_for_cb.empty() && std::invoke(can_read, *current_format_)) {
- reader.consume(std::invoke(read, reader.data()));
+ if (!data_for_cb.empty()) {
+ std::invoke(read_cb, Flags{is_first_read_, !has_data_remaining}, reader);
+ is_first_read_ = false;
}
- if (!HasDataRemaining()) {
+ if (!has_data_remaining) {
// Out of data. We're finished. Note we don't care about anything left in
// the file buffer at this point; the callback as seen it, so if it didn't
// consume it then presumably whatever is left isn't enough to form a
@@ -273,18 +259,19 @@ auto FatfsAudioInput::OpenFile(const std::string& path) -> void {
return;
}
- if (*stream_type == codecs::StreamType::kPcm && tags.channels &&
- tags.bits_per_sample && tags.channels) {
- current_format_ = StreamInfo::Pcm{
- .channels = static_cast<uint8_t>(*tags.channels),
- .bits_per_sample = static_cast<uint8_t>(*tags.bits_per_sample),
- .sample_rate = static_cast<uint32_t>(*tags.sample_rate),
- };
+ StreamInfo::Format format;
+ if (*stream_type == codecs::StreamType::kPcm) {
+ if (tags.channels && tags.bits_per_sample && tags.channels) {
+ format = StreamInfo::Pcm{
+ .channels = static_cast<uint8_t>(*tags.channels),
+ .bits_per_sample = static_cast<uint8_t>(*tags.bits_per_sample),
+ .sample_rate = static_cast<uint32_t>(*tags.sample_rate)};
+ } else {
+ ESP_LOGW(kTag, "pcm stream missing format info");
+ return;
+ }
} else {
- current_format_ = StreamInfo::Encoded{
- .type = *stream_type,
- .duration_bytes = info.fsize,
- };
+ format = StreamInfo::Encoded{.type = *stream_type};
}
std::unique_ptr<FIL> file = std::make_unique<FIL>();
@@ -294,15 +281,17 @@ auto FatfsAudioInput::OpenFile(const std::string& path) -> void {
return;
}
- streamer_->Restart(std::move(file));
+ OutputStream writer{input_buffer_.get()};
+ writer.prepare(format, info.fsize);
+ streamer_->Restart(std::move(file));
+ is_first_read_ = true;
events::Audio().Dispatch(internal::InputFileOpened{});
}
auto FatfsAudioInput::CloseCurrentFile() -> void {
streamer_->Restart({});
xStreamBufferReset(streamer_buffer_);
- current_format_ = {};
}
auto FatfsAudioInput::HasDataRemaining() -> bool {
@@ -327,14 +316,11 @@ auto FatfsAudioInput::ContainerToStreamType(database::Encoding enc)
}
auto FatfsAudioInput::IsCurrentFormatMp3() -> bool {
- if (!current_format_) {
- return false;
- }
- if (!std::holds_alternative<StreamInfo::Encoded>(*current_format_)) {
+ auto format = input_buffer_->info().format_as<StreamInfo::Encoded>();
+ if (!format) {
return false;
}
- return std::get<StreamInfo::Encoded>(*current_format_).type ==
- codecs::StreamType::kMp3;
+ return format->type == codecs::StreamType::kMp3;
}
} // namespace audio