Added offset for track seeking, wav impl. only rn

custom
ailurux 1 year ago
parent e466522c25
commit 62f6179abe
  1. 11
      src/audio/audio_decoder.cpp
  2. 12
      src/audio/audio_fsm.cpp
  3. 9
      src/audio/audio_source.cpp
  4. 8
      src/audio/fatfs_audio_input.cpp
  5. 2
      src/audio/include/audio_decoder.hpp
  6. 5
      src/audio/include/audio_events.hpp
  7. 3
      src/audio/include/audio_fsm.hpp
  8. 6
      src/audio/include/audio_source.hpp
  9. 4
      src/audio/include/fatfs_audio_input.hpp
  10. 2
      src/codecs/include/codec.hpp
  11. 2
      src/codecs/include/mad.hpp
  12. 2
      src/codecs/include/miniflac.hpp
  13. 2
      src/codecs/include/opus.hpp
  14. 2
      src/codecs/include/vorbis.hpp
  15. 2
      src/codecs/include/wav.hpp
  16. 2
      src/codecs/mad.cpp
  17. 2
      src/codecs/miniflac.cpp
  18. 2
      src/codecs/opus.cpp
  19. 2
      src/codecs/vorbis.cpp
  20. 6
      src/codecs/wav.cpp

@ -51,9 +51,10 @@ static constexpr std::size_t kCodecBufferLength =
drivers::kI2SBufferLengthFrames * sizeof(sample::Sample); drivers::kI2SBufferLengthFrames * sizeof(sample::Sample);
Timer::Timer(std::shared_ptr<Track> t, Timer::Timer(std::shared_ptr<Track> t,
const codecs::ICodec::OutputFormat& format) const codecs::ICodec::OutputFormat& format,
uint32_t current_seconds)
: track_(t), : track_(t),
current_seconds_(0), current_seconds_(current_seconds),
current_sample_in_second_(0), current_sample_in_second_(0),
samples_per_second_(format.sample_rate_hz * format.num_channels), samples_per_second_(format.sample_rate_hz * format.num_channels),
total_duration_seconds_(format.total_samples.value_or(0) / total_duration_seconds_(format.total_samples.value_or(0) /
@ -131,7 +132,7 @@ auto Decoder::BeginDecoding(std::shared_ptr<TaggedStream> stream) -> bool {
return false; return false;
} }
auto open_res = codec_->OpenStream(stream); auto open_res = codec_->OpenStream(stream, stream->Offset());
if (open_res.has_error()) { if (open_res.has_error()) {
ESP_LOGE(kTag, "codec failed to start: %s", ESP_LOGE(kTag, "codec failed to start: %s",
codecs::ICodec::ErrorString(open_res.error()).c_str()); codecs::ICodec::ErrorString(open_res.error()).c_str());
@ -147,6 +148,7 @@ auto Decoder::BeginDecoding(std::shared_ptr<TaggedStream> stream) -> bool {
ESP_LOGI(kTag, "stream started ok"); ESP_LOGI(kTag, "stream started ok");
events::Audio().Dispatch(internal::InputFileOpened{}); events::Audio().Dispatch(internal::InputFileOpened{});
// TODO: How does this need to change?
auto tags = std::make_shared<Track>(Track{ auto tags = std::make_shared<Track>(Track{
.tags = stream->tags(), .tags = stream->tags(),
.db_info = {}, .db_info = {},
@ -155,7 +157,8 @@ auto Decoder::BeginDecoding(std::shared_ptr<TaggedStream> stream) -> bool {
}); });
timer_.reset(new Timer(tags, open_res.value())); timer_.reset(new Timer(tags, open_res.value()));
PlaybackUpdate ev{.seconds_elapsed = 0, .track = tags}; // TODO: How does *this?* need to change?
PlaybackUpdate ev{.seconds_elapsed = stream->Offset(), .track = tags};
events::Audio().Dispatch(ev); events::Audio().Dispatch(ev);
events::Ui().Dispatch(ev); events::Ui().Dispatch(ev);

@ -244,11 +244,19 @@ void Uninitialised::react(const system_fsm::BootComplete& ev) {
} }
void Standby::react(const PlayFile& ev) { void Standby::react(const PlayFile& ev) {
sFileSource->SetPath(ev.filename); sFileSource->SetPath(ev.filename, 10);
} }
void Playback::react(const PlayFile& ev) { void Playback::react(const PlayFile& ev) {
sFileSource->SetPath(ev.filename); sFileSource->SetPath(ev.filename, 15);
}
void Standby::react(const SeekFile& ev) {
sFileSource->SetPath(ev.filename, ev.offset);
}
void Playback::react(const SeekFile& ev) {
sFileSource->SetPath(ev.filename, ev.offset);
} }
void Standby::react(const internal::InputFileOpened& ev) { void Standby::react(const internal::InputFileOpened& ev) {

@ -11,8 +11,9 @@
namespace audio { namespace audio {
TaggedStream::TaggedStream(std::shared_ptr<database::TrackTags> t, TaggedStream::TaggedStream(std::shared_ptr<database::TrackTags> t,
std::unique_ptr<codecs::IStream> w) std::unique_ptr<codecs::IStream> w,
: codecs::IStream(w->type()), tags_(t), wrapped_(std::move(w)) {} uint32_t offset)
: codecs::IStream(w->type()), tags_(t), wrapped_(std::move(w)), offset_(offset) {}
auto TaggedStream::tags() -> std::shared_ptr<database::TrackTags> { auto TaggedStream::tags() -> std::shared_ptr<database::TrackTags> {
return tags_; return tags_;
@ -38,6 +39,10 @@ auto TaggedStream::Size() -> std::optional<int64_t> {
return wrapped_->Size(); return wrapped_->Size();
} }
auto TaggedStream::Offset() -> uint32_t {
return offset_;
}
auto TaggedStream::SetPreambleFinished() -> void { auto TaggedStream::SetPreambleFinished() -> void {
wrapped_->SetPreambleFinished(); wrapped_->SetPreambleFinished();
} }

@ -62,9 +62,9 @@ auto FatfsAudioInput::SetPath(std::optional<std::string> path) -> void {
} }
} }
auto FatfsAudioInput::SetPath(const std::string& path) -> void { auto FatfsAudioInput::SetPath(const std::string& path,uint32_t offset) -> void {
std::lock_guard<std::mutex> guard{new_stream_mutex_}; std::lock_guard<std::mutex> guard{new_stream_mutex_};
if (OpenFile(path)) { if (OpenFile(path, offset)) {
has_new_stream_ = true; has_new_stream_ = true;
has_new_stream_.notify_one(); has_new_stream_.notify_one();
} }
@ -103,7 +103,7 @@ auto FatfsAudioInput::NextStream() -> std::shared_ptr<TaggedStream> {
} }
} }
auto FatfsAudioInput::OpenFile(const std::string& path) -> bool { auto FatfsAudioInput::OpenFile(const std::string& path,uint32_t offset) -> bool {
ESP_LOGI(kTag, "opening file %s", path.c_str()); ESP_LOGI(kTag, "opening file %s", path.c_str());
auto tags = tag_parser_.ReadAndParseTags(path); auto tags = tag_parser_.ReadAndParseTags(path);
@ -136,7 +136,7 @@ auto FatfsAudioInput::OpenFile(const std::string& path) -> bool {
auto source = auto source =
std::make_unique<FatfsSource>(stream_type.value(), std::move(file)); std::make_unique<FatfsSource>(stream_type.value(), std::move(file));
new_stream_.reset(new TaggedStream(tags, std::move(source))); new_stream_.reset(new TaggedStream(tags, std::move(source), offset));
return true; return true;
} }

@ -24,7 +24,7 @@ namespace audio {
*/ */
class Timer { class Timer {
public: public:
Timer(std::shared_ptr<Track>, const codecs::ICodec::OutputFormat& format); Timer(std::shared_ptr<Track>, const codecs::ICodec::OutputFormat& format, uint32_t current_seconds = 0);
auto AddSamples(std::size_t) -> void; auto AddSamples(std::size_t) -> void;

@ -45,6 +45,11 @@ struct PlayFile : tinyfsm::Event {
std::string filename; std::string filename;
}; };
struct SeekFile : tinyfsm::Event {
std::string filename;
uint32_t offset;
};
struct StepUpVolume : tinyfsm::Event {}; struct StepUpVolume : tinyfsm::Event {};
struct StepDownVolume : tinyfsm::Event {}; struct StepDownVolume : tinyfsm::Event {};
struct SetVolume : tinyfsm::Event { struct SetVolume : tinyfsm::Event {

@ -57,6 +57,7 @@ class AudioState : public tinyfsm::Fsm<AudioState> {
virtual void react(const system_fsm::BluetoothEvent&); virtual void react(const system_fsm::BluetoothEvent&);
virtual void react(const PlayFile&) {} virtual void react(const PlayFile&) {}
virtual void react(const SeekFile&) {}
virtual void react(const QueueUpdate&) {} virtual void react(const QueueUpdate&) {}
virtual void react(const PlaybackUpdate&) {} virtual void react(const PlaybackUpdate&) {}
void react(const TogglePlayPause&); void react(const TogglePlayPause&);
@ -99,6 +100,7 @@ class Uninitialised : public AudioState {
class Standby : public AudioState { class Standby : public AudioState {
public: public:
void react(const PlayFile&) override; void react(const PlayFile&) override;
void react(const SeekFile&) override;
void react(const internal::InputFileOpened&) override; void react(const internal::InputFileOpened&) override;
void react(const QueueUpdate&) override; void react(const QueueUpdate&) override;
void react(const system_fsm::KeyLockChanged&) override; void react(const system_fsm::KeyLockChanged&) override;
@ -115,6 +117,7 @@ class Playback : public AudioState {
void react(const system_fsm::HasPhonesChanged&) override; void react(const system_fsm::HasPhonesChanged&) override;
void react(const PlayFile&) override; void react(const PlayFile&) override;
void react(const SeekFile&) override;
void react(const QueueUpdate&) override; void react(const QueueUpdate&) override;
void react(const PlaybackUpdate&) override; void react(const PlaybackUpdate&) override;

@ -16,7 +16,8 @@ namespace audio {
class TaggedStream : public codecs::IStream { class TaggedStream : public codecs::IStream {
public: public:
TaggedStream(std::shared_ptr<database::TrackTags>, TaggedStream(std::shared_ptr<database::TrackTags>,
std::unique_ptr<codecs::IStream> wrapped); std::unique_ptr<codecs::IStream> wrapped,
uint32_t offset = 0);
auto tags() -> std::shared_ptr<database::TrackTags>; auto tags() -> std::shared_ptr<database::TrackTags>;
@ -30,11 +31,14 @@ class TaggedStream : public codecs::IStream {
auto Size() -> std::optional<int64_t> override; auto Size() -> std::optional<int64_t> override;
auto Offset() -> uint32_t;
auto SetPreambleFinished() -> void override; auto SetPreambleFinished() -> void override;
private: private:
std::shared_ptr<database::TrackTags> tags_; std::shared_ptr<database::TrackTags> tags_;
std::unique_ptr<codecs::IStream> wrapped_; std::unique_ptr<codecs::IStream> wrapped_;
int32_t offset_;
}; };
class IAudioSource { class IAudioSource {

@ -39,7 +39,7 @@ class FatfsAudioInput : public IAudioSource {
* given file path. * given file path.
*/ */
auto SetPath(std::optional<std::string>) -> void; auto SetPath(std::optional<std::string>) -> void;
auto SetPath(const std::string&) -> void; auto SetPath(const std::string&,uint32_t offset = 0) -> void;
auto SetPath() -> void; auto SetPath() -> void;
auto HasNewStream() -> bool override; auto HasNewStream() -> bool override;
@ -49,7 +49,7 @@ class FatfsAudioInput : public IAudioSource {
FatfsAudioInput& operator=(const FatfsAudioInput&) = delete; FatfsAudioInput& operator=(const FatfsAudioInput&) = delete;
private: private:
auto OpenFile(const std::string& path) -> bool; auto OpenFile(const std::string& path,uint32_t offset) -> bool;
auto ContainerToStreamType(database::Container) auto ContainerToStreamType(database::Container)
-> std::optional<codecs::StreamType>; -> std::optional<codecs::StreamType>;

@ -117,7 +117,7 @@ class ICodec {
* Decodes metadata or headers from the given input stream, and returns the * Decodes metadata or headers from the given input stream, and returns the
* format for the samples that will be decoded from it. * format for the samples that will be decoded from it.
*/ */
virtual auto OpenStream(std::shared_ptr<IStream> input) virtual auto OpenStream(std::shared_ptr<IStream> input,uint32_t offset)
-> cpp::result<OutputFormat, Error> = 0; -> cpp::result<OutputFormat, Error> = 0;
struct OutputInfo { struct OutputInfo {

@ -26,7 +26,7 @@ class MadMp3Decoder : public ICodec {
MadMp3Decoder(); MadMp3Decoder();
~MadMp3Decoder(); ~MadMp3Decoder();
auto OpenStream(std::shared_ptr<IStream> input) auto OpenStream(std::shared_ptr<IStream> input,uint32_t offset)
-> cpp::result<OutputFormat, Error> override; -> cpp::result<OutputFormat, Error> override;
auto DecodeTo(cpp::span<sample::Sample> destination) auto DecodeTo(cpp::span<sample::Sample> destination)

@ -28,7 +28,7 @@ class MiniFlacDecoder : public ICodec {
MiniFlacDecoder(); MiniFlacDecoder();
~MiniFlacDecoder(); ~MiniFlacDecoder();
auto OpenStream(std::shared_ptr<IStream> input) auto OpenStream(std::shared_ptr<IStream> input,uint32_t offset)
-> cpp::result<OutputFormat, Error> override; -> cpp::result<OutputFormat, Error> override;
auto DecodeTo(cpp::span<sample::Sample> destination) auto DecodeTo(cpp::span<sample::Sample> destination)

@ -26,7 +26,7 @@ class XiphOpusDecoder : public ICodec {
XiphOpusDecoder(); XiphOpusDecoder();
~XiphOpusDecoder(); ~XiphOpusDecoder();
auto OpenStream(std::shared_ptr<IStream> input) auto OpenStream(std::shared_ptr<IStream> input,uint32_t offset)
-> cpp::result<OutputFormat, Error> override; -> cpp::result<OutputFormat, Error> override;
auto DecodeTo(cpp::span<sample::Sample> destination) auto DecodeTo(cpp::span<sample::Sample> destination)

@ -28,7 +28,7 @@ class TremorVorbisDecoder : public ICodec {
TremorVorbisDecoder(); TremorVorbisDecoder();
~TremorVorbisDecoder(); ~TremorVorbisDecoder();
auto OpenStream(std::shared_ptr<IStream> input) auto OpenStream(std::shared_ptr<IStream> input,uint32_t offset)
-> cpp::result<OutputFormat, Error> override; -> cpp::result<OutputFormat, Error> override;
auto DecodeTo(cpp::span<sample::Sample> destination) auto DecodeTo(cpp::span<sample::Sample> destination)

@ -31,7 +31,7 @@ class WavDecoder : public ICodec {
WavDecoder(); WavDecoder();
~WavDecoder(); ~WavDecoder();
auto OpenStream(std::shared_ptr<IStream> input) auto OpenStream(std::shared_ptr<IStream> input,uint32_t offset)
-> cpp::result<OutputFormat, Error> override; -> cpp::result<OutputFormat, Error> override;
auto DecodeTo(cpp::span<sample::Sample> destination) auto DecodeTo(cpp::span<sample::Sample> destination)

@ -58,7 +58,7 @@ auto MadMp3Decoder::GetBytesUsed() -> std::size_t {
} }
} }
auto MadMp3Decoder::OpenStream(std::shared_ptr<IStream> input) auto MadMp3Decoder::OpenStream(std::shared_ptr<IStream> input,uint32_t offset)
-> cpp::result<OutputFormat, ICodec::Error> { -> cpp::result<OutputFormat, ICodec::Error> {
input_ = input; input_ = input;

@ -42,7 +42,7 @@ MiniFlacDecoder::~MiniFlacDecoder() {
} }
} }
auto MiniFlacDecoder::OpenStream(std::shared_ptr<IStream> input) auto MiniFlacDecoder::OpenStream(std::shared_ptr<IStream> input,uint32_t offset)
-> cpp::result<OutputFormat, Error> { -> cpp::result<OutputFormat, Error> {
input_ = input; input_ = input;

@ -78,7 +78,7 @@ XiphOpusDecoder::~XiphOpusDecoder() {
} }
} }
auto XiphOpusDecoder::OpenStream(std::shared_ptr<IStream> input) auto XiphOpusDecoder::OpenStream(std::shared_ptr<IStream> input,uint32_t offset)
-> cpp::result<OutputFormat, Error> { -> cpp::result<OutputFormat, Error> {
input_ = input; input_ = input;

@ -84,7 +84,7 @@ TremorVorbisDecoder::~TremorVorbisDecoder() {
ov_clear(&vorbis_); ov_clear(&vorbis_);
} }
auto TremorVorbisDecoder::OpenStream(std::shared_ptr<IStream> input) auto TremorVorbisDecoder::OpenStream(std::shared_ptr<IStream> input,uint32_t offset)
-> cpp::result<OutputFormat, Error> { -> cpp::result<OutputFormat, Error> {
int res = ov_open_callbacks(input.get(), &vorbis_, NULL, 0, kCallbacks); int res = ov_open_callbacks(input.get(), &vorbis_, NULL, 0, kCallbacks);
if (res < 0) { if (res < 0) {

@ -84,7 +84,7 @@ WavDecoder::WavDecoder() : input_(), buffer_() {}
WavDecoder::~WavDecoder() {} WavDecoder::~WavDecoder() {}
auto WavDecoder::OpenStream(std::shared_ptr<IStream> input) auto WavDecoder::OpenStream(std::shared_ptr<IStream> input,uint32_t offset)
-> cpp::result<OutputFormat, Error> { -> cpp::result<OutputFormat, Error> {
input_ = input; input_ = input;
@ -199,8 +199,10 @@ auto WavDecoder::OpenStream(std::shared_ptr<IStream> input)
return cpp::fail(Error::kUnsupportedFormat); return cpp::fail(Error::kUnsupportedFormat);
} }
auto data_offset = offset * samples_per_second * bits_per_sample;
// Seek track to start of data // Seek track to start of data
input->SeekTo(data_chunk_index + 8, IStream::SeekFrom::kStartOfStream); input->SeekTo(data_chunk_index + 8 + data_offset, IStream::SeekFrom::kStartOfStream);
output_format_ = {.num_channels = (uint8_t)num_channels_, output_format_ = {.num_channels = (uint8_t)num_channels_,
.sample_rate_hz = samples_per_second, .sample_rate_hz = samples_per_second,

Loading…
Cancel
Save