Make StreamInfo a PDO

custom
jacqueline 2 years ago
parent 3696512b38
commit 7b60f5f864
  1. 6
      src/audio/CMakeLists.txt
  2. 18
      src/audio/audio_decoder.cpp
  3. 2
      src/audio/audio_playback.cpp
  4. 6
      src/audio/fatfs_audio_input.cpp
  5. 6
      src/audio/i2s_audio_output.cpp
  6. 46
      src/audio/include/stream_info.hpp
  7. 85
      src/audio/stream_info.cpp

@ -1,8 +1,8 @@
idf_component_register( idf_component_register(
SRCS "audio_decoder.cpp" "audio_task.cpp" "chunk.cpp" "fatfs_audio_input.cpp" SRCS "audio_decoder.cpp" "audio_task.cpp" "chunk.cpp" "fatfs_audio_input.cpp"
"stream_info.cpp" "stream_message.cpp" "i2s_audio_output.cpp" "stream_message.cpp" "i2s_audio_output.cpp" "stream_buffer.cpp"
"stream_buffer.cpp" "audio_playback.cpp" "audio_element_handle.cpp" "audio_playback.cpp" "audio_element_handle.cpp" "stream_event.cpp"
"stream_event.cpp" "audio_element.cpp" "audio_element.cpp"
INCLUDE_DIRS "include" INCLUDE_DIRS "include"
REQUIRES "codecs" "drivers" "cbor" "result" "tasks" "span") REQUIRES "codecs" "drivers" "cbor" "result" "tasks" "span")

@ -37,8 +37,8 @@ auto AudioDecoder::ProcessStreamInfo(const StreamInfo& info)
-> cpp::result<void, AudioProcessingError> { -> cpp::result<void, AudioProcessingError> {
stream_info_ = info; stream_info_ = info;
if (info.ChunkSize()) { if (info.chunk_size) {
chunk_reader_.emplace(info.ChunkSize().value()); chunk_reader_.emplace(*info.chunk_size);
} else { } else {
// TODO. // TODO.
} }
@ -46,14 +46,14 @@ auto AudioDecoder::ProcessStreamInfo(const StreamInfo& info)
// Reuse the existing codec if we can. This will help with gapless playback, // Reuse the existing codec if we can. This will help with gapless playback,
// since we can potentially just continue to decode as we were before, // since we can potentially just continue to decode as we were before,
// without any setup overhead. // without any setup overhead.
if (current_codec_->CanHandleFile(info.Path().value_or(""))) { if (current_codec_->CanHandleFile(info.path.value_or(""))) {
current_codec_->ResetForNewStream(); current_codec_->ResetForNewStream();
return {}; return {};
} }
auto result = codecs::CreateCodecForFile(info.Path().value()); auto result = codecs::CreateCodecForFile(*info.path);
if (result.has_value()) { if (result) {
current_codec_ = std::move(result.value()); current_codec_ = std::move(*result);
} else { } else {
return cpp::fail(UNSUPPORTED_STREAM); return cpp::fail(UNSUPPORTED_STREAM);
} }
@ -62,10 +62,10 @@ auto AudioDecoder::ProcessStreamInfo(const StreamInfo& info)
// sample rate, chunk size, etc. // sample rate, chunk size, etc.
auto downstream_info = StreamEvent::CreateStreamInfo( auto downstream_info = StreamEvent::CreateStreamInfo(
input_events_, std::make_unique<StreamInfo>(info)); input_events_, std::make_unique<StreamInfo>(info));
downstream_info->stream_info->BitsPerSample(32); downstream_info->stream_info->bits_per_sample = 32;
downstream_info->stream_info->SampleRate(48'000); downstream_info->stream_info->sample_rate = 48'000;
chunk_size_ = 128; chunk_size_ = 128;
downstream_info->stream_info->ChunkSize(chunk_size_); downstream_info->stream_info->chunk_size = chunk_size_;
SendOrBufferEvent(std::move(downstream_info)); SendOrBufferEvent(std::move(downstream_info));

@ -57,7 +57,7 @@ AudioPlayback::~AudioPlayback() {
auto AudioPlayback::Play(const std::string& filename) -> void { auto AudioPlayback::Play(const std::string& filename) -> void {
auto info = std::make_unique<StreamInfo>(); auto info = std::make_unique<StreamInfo>();
info->Path(filename); info->path = filename;
auto event = StreamEvent::CreateStreamInfo(nullptr, std::move(info)); auto event = StreamEvent::CreateStreamInfo(nullptr, std::move(info));
xQueueSend(input_handle_, event.release(), portMAX_DELAY); xQueueSend(input_handle_, event.release(), portMAX_DELAY);

@ -40,10 +40,10 @@ auto FatfsAudioInput::ProcessStreamInfo(const StreamInfo& info)
is_file_open_ = false; is_file_open_ = false;
} }
if (!info.Path()) { if (!info.path) {
return cpp::fail(UNSUPPORTED_STREAM); return cpp::fail(UNSUPPORTED_STREAM);
} }
std::string path = info.Path().value(); std::string path = *info.path;
FRESULT res = f_open(&current_file_, path.c_str(), FA_READ); FRESULT res = f_open(&current_file_, path.c_str(), FA_READ);
if (res != FR_OK) { if (res != FR_OK) {
return cpp::fail(IO_ERROR); return cpp::fail(IO_ERROR);
@ -52,7 +52,7 @@ auto FatfsAudioInput::ProcessStreamInfo(const StreamInfo& info)
is_file_open_ = true; is_file_open_ = true;
std::unique_ptr<StreamInfo> new_info = std::make_unique<StreamInfo>(info); std::unique_ptr<StreamInfo> new_info = std::make_unique<StreamInfo>(info);
new_info->ChunkSize(kChunkSize); new_info->chunk_size = kChunkSize;
auto event = auto event =
StreamEvent::CreateStreamInfo(input_events_, std::move(new_info)); StreamEvent::CreateStreamInfo(input_events_, std::move(new_info));

@ -48,12 +48,12 @@ auto I2SAudioOutput::ProcessStreamInfo(const StreamInfo& info)
-> cpp::result<void, AudioProcessingError> { -> cpp::result<void, AudioProcessingError> {
// TODO(jacqueline): probs do something with the channel hey // TODO(jacqueline): probs do something with the channel hey
if (!info.BitsPerSample() && !info.SampleRate()) { if (!info.bits_per_sample && !info.sample_rate) {
return cpp::fail(UNSUPPORTED_STREAM); return cpp::fail(UNSUPPORTED_STREAM);
} }
drivers::AudioDac::BitsPerSample bps; drivers::AudioDac::BitsPerSample bps;
switch (*info.BitsPerSample()) { switch (*info.bits_per_sample) {
case 16: case 16:
bps = drivers::AudioDac::BPS_16; bps = drivers::AudioDac::BPS_16;
break; break;
@ -68,7 +68,7 @@ auto I2SAudioOutput::ProcessStreamInfo(const StreamInfo& info)
} }
drivers::AudioDac::SampleRate sample_rate; drivers::AudioDac::SampleRate sample_rate;
switch (*info.SampleRate()) { switch (*info.sample_rate) {
case 44100: case 44100:
sample_rate = drivers::AudioDac::SAMPLE_RATE_44_1; sample_rate = drivers::AudioDac::SAMPLE_RATE_44_1;
break; break;

@ -11,46 +11,12 @@
namespace audio { namespace audio {
class StreamInfo { struct StreamInfo {
public: std::optional<std::string> path;
static auto Parse(CborValue& container) -> cpp::result<StreamInfo, CborError>; std::optional<uint8_t> channels;
std::optional<uint8_t> bits_per_sample;
StreamInfo() = default; std::optional<uint16_t> sample_rate;
StreamInfo(const StreamInfo&) = default; std::optional<size_t> chunk_size;
~StreamInfo() = default;
auto Path() const -> const std::optional<std::string>& { return path_; }
auto Path(const std::string_view& d) -> void { path_ = d; }
auto Channels() const -> const std::optional<uint8_t>& { return channels_; }
auto BitsPerSample(uint8_t bpp) -> void { bits_per_sample_ = bpp; }
auto BitsPerSample() const -> const std::optional<uint8_t>& {
return bits_per_sample_;
}
auto SampleRate(uint16_t rate) -> void { sample_rate_ = rate; }
auto SampleRate() const -> const std::optional<uint16_t>& {
return sample_rate_;
}
auto ChunkSize() const -> const std::optional<std::size_t>& {
return chunk_size_;
}
auto ChunkSize(std::size_t s) -> void { chunk_size_ = s; }
auto Encode(CborEncoder& enc) -> std::optional<CborError>;
private:
std::optional<std::string> path_;
std::optional<uint8_t> channels_;
std::optional<uint8_t> bits_per_sample_;
std::optional<uint16_t> sample_rate_;
std::optional<size_t> chunk_size_;
}; };
} // namespace audio } // namespace audio

@ -1,85 +0,0 @@
#include "stream_info.hpp"
#include <cstdint>
#include <string>
#include "cbor.h"
#include "stream_message.hpp"
namespace audio {
static const std::string kKeyPath = "p";
static const std::string kKeyChannels = "c";
static const std::string kKeyBitsPerSample = "b";
static const std::string kKeySampleRate = "r";
auto StreamInfo::Parse(CborValue& container)
-> cpp::result<StreamInfo, CborError> {
CborValue map;
cbor_value_enter_container(&container, &map);
CborValue entry;
StreamInfo ret;
cbor_value_map_find_value(&map, kKeyPath.c_str(), &entry);
if (cbor_value_get_type(&entry) != CborInvalidType) {
char* val;
size_t len;
cbor_value_dup_text_string(&entry, &val, &len, NULL);
ret.path_ = std::string(val, len);
free(val);
}
cbor_value_map_find_value(&map, kKeyChannels.c_str(), &entry);
if (cbor_value_get_type(&entry) != CborInvalidType) {
uint64_t val;
cbor_value_get_uint64(&entry, &val);
ret.channels_ = val;
}
cbor_value_map_find_value(&map, kKeyBitsPerSample.c_str(), &entry);
if (cbor_value_get_type(&entry) != CborInvalidType) {
uint64_t val;
cbor_value_get_uint64(&entry, &val);
ret.bits_per_sample_ = val;
}
cbor_value_map_find_value(&map, kKeySampleRate.c_str(), &entry);
if (cbor_value_get_type(&entry) != CborInvalidType) {
uint64_t val;
cbor_value_get_uint64(&entry, &val);
ret.sample_rate_ = val;
}
return ret;
}
auto StreamInfo::Encode(CborEncoder& enc) -> std::optional<CborError> {
CborEncoder map;
size_t num_items = 0 + channels_.has_value() + bits_per_sample_.has_value() +
sample_rate_.has_value() + path_.has_value();
cbor_encoder_create_map(&enc, &map, num_items);
if (channels_) {
cbor_encode_text_string(&map, kKeyChannels.c_str(), kKeyChannels.size());
cbor_encode_uint(&map, channels_.value());
}
if (bits_per_sample_) {
cbor_encode_text_string(&map, kKeyBitsPerSample.c_str(),
kKeyBitsPerSample.size());
cbor_encode_uint(&map, bits_per_sample_.value());
}
if (sample_rate_) {
cbor_encode_text_string(&map, kKeySampleRate.c_str(),
kKeySampleRate.size());
cbor_encode_uint(&map, sample_rate_.value());
}
if (path_) {
cbor_encode_text_string(&map, kKeyPath.c_str(), kKeyPath.size());
cbor_encode_text_string(&map, path_.value().c_str(), path_.value().size());
}
cbor_encoder_close_container(&enc, &map);
return std::nullopt;
}
} // namespace audio
Loading…
Cancel
Save