From a7df2855889055976956a58d2a36f23626371ee9 Mon Sep 17 00:00:00 2001 From: jacqueline Date: Wed, 23 Nov 2022 17:15:06 +1100 Subject: Mostly done pipeline arch. Now onto cleanup and building. --- src/audio/fatfs_audio_input.cpp | 165 +++++++++++++++++++++++++--------------- 1 file changed, 103 insertions(+), 62 deletions(-) (limited to 'src/audio/fatfs_audio_input.cpp') diff --git a/src/audio/fatfs_audio_input.cpp b/src/audio/fatfs_audio_input.cpp index 0cf1abe5..351fd017 100644 --- a/src/audio/fatfs_audio_input.cpp +++ b/src/audio/fatfs_audio_input.cpp @@ -1,6 +1,8 @@ #include "fatfs_audio_input.hppccc #include #include +#include "chunk.hpp" +#include "fatfs_audio_input.hpp" #include "esp_heap_caps.h" @@ -10,31 +12,32 @@ namespace audio { -static const TickType_t kMaxWaitTicks = portMAX_DELAY; +static const TickType_t kServiceInterval = pdMS_TO_TICKS(50); -// Large output buffer size, so that we can keep a get as much of the input file -// into memory as soon as possible. -static constexpr std::size_t kOutputBufferSize = 1024 * 128; -static constexpr std::size_t kQueueItemSize = sizeof(IAudioElement::Command); +static const std::size_t kFileBufferSize = 1024 * 128; +static const std::size_t kMinFileReadSize = 1024 * 4; +static const std::size_t kOutputBufferSize = 1024 * 4; FatfsAudioInput::FatfsAudioInput(std::shared_ptr storage) : IAudioElement(), storage_(storage) { - working_buffer_ = heap_caps_malloc(kMaxFrameSize, MALLOC_CAP_SPIRAM); + file_buffer_ = heap_caps_malloc(kMaxFrameSize, MALLOC_CAP_SPIRAM); + file_buffer_read_pos_ = file_buffer_; + file_buffer_write_pos_ = file_buffer_; + chunk_buffer_ = heap_caps_malloc(kMaxChunkSize, MALLOC_CAP_SPIRAM); output_buffer_memory_ = - heap_caps_malloc(kOutputBufferSize + 1, MALLOC_CAP_SPIRAM); - output_buffer_ = - xMessageBufferCreateStatic(kOutputBufferSize, output_buffer_memory_, - &output_buffer_metadata_); + heap_caps_malloc(kOutputBufferSize, MALLOC_CAP_SPIRAM); + output_buffer_ = xMessageBufferCreateStatic( + kOutputBufferSize, output_buffer_memory_, &output_buffer_metadata_); } FatfsAudioInput::~FatfsAudioInput() { - free(working_buffer_); + free(file_buffer_); + free(chunk_buffer_); vMessageBufferDelete(output_buffer_); free(output_buffer_memory_); } - auto FatfsAudioInput::InputBuffer() -> MessageBufferHandle_t { return input_buffer_; } @@ -43,80 +46,118 @@ auto FatfsAudioInput::OutputBuffer() -> MessageBufferHandle_t { return output_buffer_; } -auto FatfsAudioInput::ProcessElementCommand(void* command) -> ProcessResult { - InputCommand *real = std::reinterpret_cast(command); - - if (uxQueueSpacesAvailable(output_queue_) < 2) { - return OUTPUT_FULL; - } - +auto FatfsAudioInput::ProcessStreamInfo(StreamInfo& info) + -> cpp::result { if (is_file_open_) { f_close(¤t_file_); + is_file_open_ = false; } - FRESULT res = f_open(¤t_file_, real->filename.c_str(), FA_READ); + FRESULT res = f_open(¤t_file_, info.path.c_str(), FA_READ); if (res != FR_OK) { - delete real; - return ERROR; - } - - if (real->seek_to && f_lseek(¤t_file_, real->seek_to) { - return ERROR; + return cpp::fail(IO_ERROR); } is_file_open_ = true; - if (real->interrupt) { - Command sequence_update; - sequence_update.type = SEQUENCE_NUMBER; - sequence_update.sequence_number = current_sequence_++; - xQueueSendToFront(output_queue_, &sequence_update, kMaxWaitTicks); - } - - OutputCommand *data = new OutputCommand; - data->extension = "mp3"; - Command file_info; - file_info.type = ELEMENT; - file_info.sequence_number = current_sequence_; - file_info.data = &data; - xQueueSendToBack(output_queue_, &file_info, kMaxWaitTicks); + // TODO: pass on stream info. - delete real; - return OK; + return {}; } -auto FatfsAudioInput::SkipElementCommand(void* command) -> void { - InputCommand *real = std::reinterpret_cast(command); - delete real; +auto FatfsAudioInput::ProcessChunk(uint8_t* data, std::size_t length) + -> cpp::result { + // TODO. + return {}; } -auto FatfsAudioInput::ProcessData(uint8_t* data, uint16_t length) -> void { - // Not used, since we have no input stream. +static auto GetRingBufferDistance() -> size_t { + if (file_buffer_read_pos_ == file_buffer_write_pos_) { + return 0; + } + if (file_buffer_read_pos_ < file_buffer_write_pos_) { + return file_buffer_write_pos_ - file_buffer_read_pos_; + } + return + // Read position to end of buffer. + (file_buffer_ + kFileBufferSize - file_buffer_read_pos_) + // Start of buffer to write position. + + (file_buffer_write_pos_ - file_buffer_) } -auto FatfsAudioInput::ProcessIdle() -> ProcessResult { - if (!is_file_open_) { - return OK; +virtual auto FatfsAudioInput::ProcessIdle() -> cpp::result { + // First, see if we're able to fill up the input buffer with any more of the + // file's contents. + if (is_file_open_) { + size_t ringbuf_distance = GetRingBufferDistance(); + if (kFileBufferSize - ringbuf_distance > kMinFileReadSize) { + size_t read_size; + if (file_buffer_write_pos_ < file_buffer_read_pos_) { + // Don't worry about the start of buffer -> read pos size; we can get to + // it next iteration. + read_size = file_buffer_read_pos_ - file_buffer_write_pos_; + } else { + read_size = file_buffer_ - file_buffer_write_pos_; + } + + UINT bytes_read = 0; + FRESULT result = f_read(¤t_file_, file_buffer_write_pos_, read_size, + &bytes_read); + if (!FR_OK) { + return ERROR; // TODO; + } + + if (f_eof(¤t_file_)) { + f_close(¤t_file_); + is_file_open_ = false; + + // TODO: open the next file? + } + + file_buffer_write_pos_ += bytes_read; + if (file_buffer_write_pos_ == file_buffer_ + kFileBufferSize) { + file_buffer_write_pos_ = file_buffer_; + } + } } - if (xStreamBufferSpacesAvailable(output_buffer) < kMaxFrameSize) { - return OUTPUT_FULL; + // Now stream data into the output buffer until it's full. + pending_read_pos_ = nullptr; + EncodeWriteResult result = + WriteChunksToStream(&output_buffer_, chunk_buffer_, kMaxChunkSize, + &SendChunk, kServiceInterval); + + switch (result) { + case CHUNK_WRITE_TIMEOUT: + case CHUNK_OUT_OF_DATA: + return; // TODO. + default: + return; // TODO. } +} - UINT bytes_read = 0; - FRESULT result = f_read(¤t_file_, working_buffer_, kMaxFrameSize, &bytes_read); - if (!FR_OK) { - return ERROR; +auto FatfsAudioInput::SendChunk(uint8_t* buffer, size_t size) -> size_t { + if (pending_read_pos_ != nullptr) { + file_buffer_read_pos_ = pending_read_pos_; } - xStreamBufferSend(&output_buffer_, working_buffer_, bytes_read, kMaxWaitTicks); - - if (f_eof(¤t_file_)) { - f_close(¤t_file_); - is_file_open_ = false; + if (file_buffer_read_pos_ == file_buffer_write_pos_) { + return 0; } + std::size_t write_size; + if (file_buffer_read_pos_ > file_buffer_write_pos_) { + write_size = file_buffer_ + kFileBufferSize - file_buffer_read_pos_; + } else { + write_size = file_buffer_write_pos_ - file_buffer_read_pos_; + } + write_size = std::min(write_size, size); + memcpy(buffer, file_buffer_read_pos_, write_size); - return OK; + pending_read_pos_ = file_buffer_read_pos_ + write_size; + if (pending_read_pos_ == file_buffer_ + kFileBufferSize) { + pending_read_pos_ = file_buffer_; + } + return write_size; } } // namespace audio -- cgit v1.2.3