summaryrefslogtreecommitdiff
path: root/src/audio/fatfs_audio_input.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/audio/fatfs_audio_input.cpp')
-rw-r--r--src/audio/fatfs_audio_input.cpp165
1 files changed, 103 insertions, 62 deletions
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.hpp<D-c>ccc
#include <cstdint>
#include <memory>
+#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<drivers::SdStorage> 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<InputCommand*>(command);
-
- if (uxQueueSpacesAvailable(output_queue_) < 2) {
- return OUTPUT_FULL;
- }
-
+auto FatfsAudioInput::ProcessStreamInfo(StreamInfo& info)
+ -> cpp::result<void, StreamError> {
if (is_file_open_) {
f_close(&current_file_);
+ is_file_open_ = false;
}
- FRESULT res = f_open(&current_file_, real->filename.c_str(), FA_READ);
+ FRESULT res = f_open(&current_file_, info.path.c_str(), FA_READ);
if (res != FR_OK) {
- delete real;
- return ERROR;
- }
-
- if (real->seek_to && f_lseek(&current_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<input_key_service_add_key*>(command);
- delete real;
+auto FatfsAudioInput::ProcessChunk(uint8_t* data, std::size_t length)
+ -> cpp::result<void, StreamError> {
+ // 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<void, StreamError> {
+ // 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(&current_file_, file_buffer_write_pos_, read_size,
+ &bytes_read);
+ if (!FR_OK) {
+ return ERROR; // TODO;
+ }
+
+ if (f_eof(&current_file_)) {
+ f_close(&current_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(&current_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(&current_file_)) {
- f_close(&current_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