Merge branch 'main' of codeberg.org:cool-tech-zone/tangara-fw

custom
jacqueline 9 months ago
commit 2afad172bd
  1. 1
      sdkconfig.common
  2. 7
      src/codecs/vorbis.cpp
  3. 63
      src/tangara/audio/playlist.cpp
  4. 9
      src/tangara/audio/playlist.hpp

@ -14,6 +14,7 @@ CONFIG_BT_CLASSIC_ENABLED=y
CONFIG_BT_A2DP_ENABLE=y CONFIG_BT_A2DP_ENABLE=y
# CONFIG_BT_BLE_ENABLED is not set # CONFIG_BT_BLE_ENABLED is not set
CONFIG_BT_STACK_NO_LOG=y CONFIG_BT_STACK_NO_LOG=y
CONFIG_BTC_TASK_STACK_SIZE=4096
CONFIG_BT_ALLOCATION_FROM_SPIRAM_FIRST=y CONFIG_BT_ALLOCATION_FROM_SPIRAM_FIRST=y
CONFIG_BTDM_CTRL_MODE_BR_EDR_ONLY=y CONFIG_BTDM_CTRL_MODE_BR_EDR_ONLY=y
CONFIG_SPI_MASTER_IN_IRAM=y CONFIG_SPI_MASTER_IN_IRAM=y

@ -137,10 +137,15 @@ auto TremorVorbisDecoder::DecodeTo(std::span<sample::Sample> output)
((output.size() - 1) * sizeof(sample::Sample)), &unused); ((output.size() - 1) * sizeof(sample::Sample)), &unused);
if (bytes_written == OV_HOLE) { if (bytes_written == OV_HOLE) {
ESP_LOGE(kTag, "got OV_HOLE"); ESP_LOGE(kTag, "got OV_HOLE");
return cpp::fail(Error::kMalformedData); return OutputInfo{
.samples_written = 0,
.is_stream_finished = false,
};
} else if (bytes_written == OV_EBADLINK) { } else if (bytes_written == OV_EBADLINK) {
ESP_LOGE(kTag, "got OV_EBADLINK"); ESP_LOGE(kTag, "got OV_EBADLINK");
return cpp::fail(Error::kMalformedData); return cpp::fail(Error::kMalformedData);
} else if (bytes_written == OV_EINVAL) {
return cpp::fail(Error::kMalformedData);
} }
return OutputInfo{ return OutputInfo{

@ -16,7 +16,12 @@ namespace audio {
[[maybe_unused]] static constexpr char kTag[] = "playlist"; [[maybe_unused]] static constexpr char kTag[] = "playlist";
Playlist::Playlist(std::string playlistFilepath) Playlist::Playlist(std::string playlistFilepath)
: filepath_(playlistFilepath), mutex_(), total_size_(0), pos_(0) {} : filepath_(playlistFilepath),
mutex_(),
total_size_(0),
pos_(-1),
offset_cache_(&memory::kSpiRamResource),
sample_size_(50) {}
auto Playlist::open() -> bool { auto Playlist::open() -> bool {
FRESULT res = FRESULT res =
@ -47,8 +52,10 @@ auto Playlist::size() const -> size_t {
auto Playlist::append(Item i) -> void { auto Playlist::append(Item i) -> void {
std::unique_lock<std::mutex> lock(mutex_); std::unique_lock<std::mutex> lock(mutex_);
auto offset = f_tell(&file_); auto offset = f_tell(&file_);
bool first_entry = current_value_.empty();
// Seek to end and append // Seek to end and append
auto res = f_lseek(&file_, f_size(&file_)); auto end = f_size(&file_);
auto res = f_lseek(&file_, end);
if (res != FR_OK) { if (res != FR_OK) {
ESP_LOGE(kTag, "Seek to end of file failed? Error %d", res); ESP_LOGE(kTag, "Seek to end of file failed? Error %d", res);
return; return;
@ -58,10 +65,13 @@ auto Playlist::append(Item i) -> void {
if (std::holds_alternative<std::string>(i)) { if (std::holds_alternative<std::string>(i)) {
path = std::get<std::string>(i); path = std::get<std::string>(i);
f_printf(&file_, "%s\n", path.c_str()); f_printf(&file_, "%s\n", path.c_str());
total_size_++; if (total_size_ % sample_size_ == 0) {
if (current_value_.empty()) { offset_cache_.push_back(end);
}
if (first_entry) {
current_value_ = path; current_value_ = path;
} }
total_size_++;
} }
// Restore position // Restore position
res = f_lseek(&file_, offset); res = f_lseek(&file_, offset);
@ -77,8 +87,26 @@ auto Playlist::append(Item i) -> void {
} }
auto Playlist::skipTo(size_t position) -> void { auto Playlist::skipTo(size_t position) -> void {
std::unique_lock<std::mutex> lock(mutex_);
// Check our cache and go to nearest entry
pos_ = position; pos_ = position;
consumeAndCount(position); auto remainder = position % sample_size_;
auto quotient = (position - remainder) / sample_size_;
if (offset_cache_.size() <= quotient) {
// Fall back case
ESP_LOGW(kTag, "File offset cache failed, falling back...");
f_rewind(&file_);
advanceBy(pos_);
return;
}
auto entry = offset_cache_.at(quotient);
// Go to byte offset
auto res = f_lseek(&file_, entry);
if (res != FR_OK) {
ESP_LOGW(kTag, "Error going to byte offset %llu for playlist entry index %d", entry, pos_);
}
// Count ahead entries
advanceBy(remainder+1);
} }
auto Playlist::next() -> void { auto Playlist::next() -> void {
@ -99,6 +127,7 @@ auto Playlist::value() const -> std::string {
} }
auto Playlist::clear() -> bool { auto Playlist::clear() -> bool {
std::unique_lock<std::mutex> lock(mutex_);
auto res = f_close(&file_); auto res = f_close(&file_);
if (res != FR_OK) { if (res != FR_OK) {
return false; return false;
@ -110,6 +139,7 @@ auto Playlist::clear() -> bool {
} }
total_size_ = 0; total_size_ = 0;
current_value_.clear(); current_value_.clear();
offset_cache_.clear();
pos_ = 0; pos_ = 0;
return true; return true;
} }
@ -128,6 +158,7 @@ auto Playlist::consumeAndCount(ssize_t upto) -> bool {
size_t count = 0; size_t count = 0;
f_rewind(&file_); f_rewind(&file_);
while (!f_eof(&file_)) { while (!f_eof(&file_)) {
auto offset = f_tell(&file_);
// TODO: Correctly handle lines longer than this // TODO: Correctly handle lines longer than this
// TODO: Also correctly handle the case where the last entry doesn't end in // TODO: Also correctly handle the case where the last entry doesn't end in
// \n // \n
@ -136,6 +167,9 @@ auto Playlist::consumeAndCount(ssize_t upto) -> bool {
ESP_LOGW(kTag, "Error consuming playlist file at line %d", count); ESP_LOGW(kTag, "Error consuming playlist file at line %d", count);
return false; return false;
} }
if (count % sample_size_ == 0) {
offset_cache_.push_back(offset);
}
count++; count++;
if (upto >= 0 && count > upto) { if (upto >= 0 && count > upto) {
@ -151,4 +185,23 @@ auto Playlist::consumeAndCount(ssize_t upto) -> bool {
return true; return true;
} }
auto Playlist::advanceBy(ssize_t amt) -> bool {
TCHAR buff[512];
size_t count = 0;
while (!f_eof(&file_)) {
auto res = f_gets(buff, 512, &file_);
if (res == NULL) {
ESP_LOGW(kTag, "Error consuming playlist file at line %d", count);
return false;
}
count++;
if (count >= amt) {
size_t len = strlen(buff);
current_value_.assign(buff, len - 1);
break;
}
}
return true;
}
} // namespace audio } // namespace audio

@ -50,7 +50,16 @@ class Playlist {
FIL file_; FIL file_;
std::string current_value_; std::string current_value_;
std::pmr::vector<FSIZE_t> offset_cache_; // List of offsets determined by sample size;
/*
* How many tracks per offset saved (ie, a value of 100 means every 100 tracks the file offset is saved)
* This speeds up searches, especially in the case of shuffling a lot of tracks.
*/
const uint32_t sample_size_;
auto consumeAndCount(ssize_t upto) -> bool; auto consumeAndCount(ssize_t upto) -> bool;
auto advanceBy(ssize_t amt) -> bool;
}; };
} // namespace audio } // namespace audio
Loading…
Cancel
Save