Make StreamInfo a PDO
This commit is contained in:
@@ -1,8 +1,8 @@
|
||||
idf_component_register(
|
||||
SRCS "audio_decoder.cpp" "audio_task.cpp" "chunk.cpp" "fatfs_audio_input.cpp"
|
||||
"stream_info.cpp" "stream_message.cpp" "i2s_audio_output.cpp"
|
||||
"stream_buffer.cpp" "audio_playback.cpp" "audio_element_handle.cpp"
|
||||
"stream_event.cpp" "audio_element.cpp"
|
||||
"stream_message.cpp" "i2s_audio_output.cpp" "stream_buffer.cpp"
|
||||
"audio_playback.cpp" "audio_element_handle.cpp" "stream_event.cpp"
|
||||
"audio_element.cpp"
|
||||
INCLUDE_DIRS "include"
|
||||
REQUIRES "codecs" "drivers" "cbor" "result" "tasks" "span")
|
||||
|
||||
|
||||
@@ -37,8 +37,8 @@ auto AudioDecoder::ProcessStreamInfo(const StreamInfo& info)
|
||||
-> cpp::result<void, AudioProcessingError> {
|
||||
stream_info_ = info;
|
||||
|
||||
if (info.ChunkSize()) {
|
||||
chunk_reader_.emplace(info.ChunkSize().value());
|
||||
if (info.chunk_size) {
|
||||
chunk_reader_.emplace(*info.chunk_size);
|
||||
} else {
|
||||
// TODO.
|
||||
}
|
||||
@@ -46,14 +46,14 @@ auto AudioDecoder::ProcessStreamInfo(const StreamInfo& info)
|
||||
// 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,
|
||||
// without any setup overhead.
|
||||
if (current_codec_->CanHandleFile(info.Path().value_or(""))) {
|
||||
if (current_codec_->CanHandleFile(info.path.value_or(""))) {
|
||||
current_codec_->ResetForNewStream();
|
||||
return {};
|
||||
}
|
||||
|
||||
auto result = codecs::CreateCodecForFile(info.Path().value());
|
||||
if (result.has_value()) {
|
||||
current_codec_ = std::move(result.value());
|
||||
auto result = codecs::CreateCodecForFile(*info.path);
|
||||
if (result) {
|
||||
current_codec_ = std::move(*result);
|
||||
} else {
|
||||
return cpp::fail(UNSUPPORTED_STREAM);
|
||||
}
|
||||
@@ -62,10 +62,10 @@ auto AudioDecoder::ProcessStreamInfo(const StreamInfo& info)
|
||||
// sample rate, chunk size, etc.
|
||||
auto downstream_info = StreamEvent::CreateStreamInfo(
|
||||
input_events_, std::make_unique<StreamInfo>(info));
|
||||
downstream_info->stream_info->BitsPerSample(32);
|
||||
downstream_info->stream_info->SampleRate(48'000);
|
||||
downstream_info->stream_info->bits_per_sample = 32;
|
||||
downstream_info->stream_info->sample_rate = 48'000;
|
||||
chunk_size_ = 128;
|
||||
downstream_info->stream_info->ChunkSize(chunk_size_);
|
||||
downstream_info->stream_info->chunk_size = chunk_size_;
|
||||
|
||||
SendOrBufferEvent(std::move(downstream_info));
|
||||
|
||||
|
||||
@@ -57,7 +57,7 @@ AudioPlayback::~AudioPlayback() {
|
||||
|
||||
auto AudioPlayback::Play(const std::string& filename) -> void {
|
||||
auto info = std::make_unique<StreamInfo>();
|
||||
info->Path(filename);
|
||||
info->path = filename;
|
||||
auto event = StreamEvent::CreateStreamInfo(nullptr, std::move(info));
|
||||
|
||||
xQueueSend(input_handle_, event.release(), portMAX_DELAY);
|
||||
|
||||
@@ -40,10 +40,10 @@ auto FatfsAudioInput::ProcessStreamInfo(const StreamInfo& info)
|
||||
is_file_open_ = false;
|
||||
}
|
||||
|
||||
if (!info.Path()) {
|
||||
if (!info.path) {
|
||||
return cpp::fail(UNSUPPORTED_STREAM);
|
||||
}
|
||||
std::string path = info.Path().value();
|
||||
std::string path = *info.path;
|
||||
FRESULT res = f_open(¤t_file_, path.c_str(), FA_READ);
|
||||
if (res != FR_OK) {
|
||||
return cpp::fail(IO_ERROR);
|
||||
@@ -52,7 +52,7 @@ auto FatfsAudioInput::ProcessStreamInfo(const StreamInfo& info)
|
||||
is_file_open_ = true;
|
||||
|
||||
std::unique_ptr<StreamInfo> new_info = std::make_unique<StreamInfo>(info);
|
||||
new_info->ChunkSize(kChunkSize);
|
||||
new_info->chunk_size = kChunkSize;
|
||||
|
||||
auto event =
|
||||
StreamEvent::CreateStreamInfo(input_events_, std::move(new_info));
|
||||
|
||||
@@ -48,12 +48,12 @@ auto I2SAudioOutput::ProcessStreamInfo(const StreamInfo& info)
|
||||
-> cpp::result<void, AudioProcessingError> {
|
||||
// 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);
|
||||
}
|
||||
|
||||
drivers::AudioDac::BitsPerSample bps;
|
||||
switch (*info.BitsPerSample()) {
|
||||
switch (*info.bits_per_sample) {
|
||||
case 16:
|
||||
bps = drivers::AudioDac::BPS_16;
|
||||
break;
|
||||
@@ -68,7 +68,7 @@ auto I2SAudioOutput::ProcessStreamInfo(const StreamInfo& info)
|
||||
}
|
||||
|
||||
drivers::AudioDac::SampleRate sample_rate;
|
||||
switch (*info.SampleRate()) {
|
||||
switch (*info.sample_rate) {
|
||||
case 44100:
|
||||
sample_rate = drivers::AudioDac::SAMPLE_RATE_44_1;
|
||||
break;
|
||||
|
||||
@@ -11,46 +11,12 @@
|
||||
|
||||
namespace audio {
|
||||
|
||||
class StreamInfo {
|
||||
public:
|
||||
static auto Parse(CborValue& container) -> cpp::result<StreamInfo, CborError>;
|
||||
|
||||
StreamInfo() = default;
|
||||
StreamInfo(const StreamInfo&) = default;
|
||||
|
||||
~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_;
|
||||
struct StreamInfo {
|
||||
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
|
||||
|
||||
@@ -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
|
||||
Reference in New Issue
Block a user