Add duration for flacs

custom
jacqueline 2 years ago
parent 0a8d2fd12e
commit cdaa2ac97a
  1. 68
      src/audio/audio_task.cpp
  2. 19
      src/audio/include/audio_task.hpp
  3. 22
      src/codecs/foxenflac.cpp

@ -53,20 +53,23 @@ static const char* kTag = "audio_dec";
static constexpr std::size_t kSampleBufferSize = 16 * 1024;
Timer::Timer(StreamInfo::Pcm format)
: format_(format),
current_seconds_(0),
current_sample_in_second_(0),
total_duration_seconds_(0) {}
auto Timer::SetLengthSeconds(uint32_t len) -> void {
total_duration_seconds_ = len;
has_duration_ = true;
}
auto Timer::SetLengthBytes(uint32_t len) -> void {
total_duration_seconds_ = bytes_to_samples(len) / format_.sample_rate;
has_duration_ = true;
Timer::Timer(const StreamInfo::Pcm& format, const Duration& duration)
: format_(format), current_seconds_(0), current_sample_in_second_(0) {
switch (duration.src) {
case Duration::Source::kLibTags:
ESP_LOGI(kTag, "using duration from libtags");
total_duration_seconds_ = duration.duration;
break;
case Duration::Source::kCodec:
ESP_LOGI(kTag, "using duration from decoder");
total_duration_seconds_ = duration.duration;
break;
case Duration::Source::kFileSize:
ESP_LOGW(kTag, "calculating duration from filesize");
total_duration_seconds_ =
bytes_to_samples(duration.duration) / format_.sample_rate;
break;
}
}
auto Timer::AddBytes(std::size_t bytes) -> void {
@ -137,14 +140,6 @@ void AudioTask::Main() {
if (ForwardPcmStream(*pcm, stream.data())) {
stream.consume(stream.data().size_bytes());
}
if (!timer_->has_duration()) {
if (stream.info().total_length_seconds()) {
timer_->SetLengthSeconds(*stream.info().total_length_seconds());
} else {
timer_->SetLengthBytes(
stream.info().total_length_bytes().value_or(0));
}
}
return;
}
@ -235,16 +230,20 @@ auto AudioTask::BeginDecoding(InputStream& stream) -> bool {
.sample_rate = format.sample_rate_hz,
};
if (!ConfigureSink(new_format)) {
return false;
}
Duration duration;
if (format.duration_seconds) {
timer_->SetLengthSeconds(*format.duration_seconds);
duration.src = Duration::Source::kCodec;
duration.duration = *format.duration_seconds;
} else if (stream.info().total_length_seconds()) {
timer_->SetLengthSeconds(*stream.info().total_length_seconds());
duration.src = Duration::Source::kLibTags;
duration.duration = *stream.info().total_length_seconds();
} else {
timer_->SetLengthBytes(stream.info().total_length_bytes().value_or(0));
duration.src = Duration::Source::kFileSize;
duration.duration = *stream.info().total_length_bytes();
}
if (!ConfigureSink(new_format, duration)) {
return false;
}
return true;
@ -307,7 +306,11 @@ auto AudioTask::ForwardPcmStream(StreamInfo::Pcm& format,
cpp::span<const std::byte> samples) -> bool {
// First we need to reconfigure the sink for this sample format.
if (format != current_output_format_) {
if (!ConfigureSink(format)) {
Duration d{
.src = Duration::Source::kFileSize,
.duration = samples.size_bytes(),
};
if (!ConfigureSink(format, d)) {
return false;
}
}
@ -319,7 +322,8 @@ auto AudioTask::ForwardPcmStream(StreamInfo::Pcm& format,
return true;
}
auto AudioTask::ConfigureSink(const StreamInfo::Pcm& format) -> bool {
auto AudioTask::ConfigureSink(const StreamInfo::Pcm& format,
const Duration& duration) -> bool {
if (format != current_output_format_) {
// The new format is different to the old one. Wait for the sink to drain
// before continuing.
@ -337,7 +341,7 @@ auto AudioTask::ConfigureSink(const StreamInfo::Pcm& format) -> bool {
}
current_output_format_ = format;
timer_.reset(new Timer(format));
timer_.reset(new Timer(format, duration));
return true;
}

@ -18,15 +18,21 @@
namespace audio {
struct Duration {
enum class Source {
kLibTags,
kCodec,
kFileSize,
};
Source src;
uint32_t duration;
};
class Timer {
public:
explicit Timer(StreamInfo::Pcm);
auto SetLengthSeconds(uint32_t) -> void;
auto SetLengthBytes(uint32_t) -> void;
Timer(const StreamInfo::Pcm&, const Duration&);
auto AddBytes(std::size_t) -> void;
auto has_duration() const -> bool { return has_duration_; }
private:
auto bytes_to_samples(uint32_t) -> uint32_t;
@ -36,7 +42,6 @@ class Timer {
uint32_t current_seconds_;
uint32_t current_sample_in_second_;
bool has_duration_;
uint32_t total_duration_seconds_;
};
@ -57,7 +62,7 @@ class AudioTask {
auto ForwardPcmStream(StreamInfo::Pcm&, cpp::span<const std::byte>) -> bool;
auto ConfigureSink(const StreamInfo::Pcm&) -> bool;
auto ConfigureSink(const StreamInfo::Pcm&, const Duration&) -> bool;
IAudioSource* source_;
IAudioSink* sink_;

@ -6,6 +6,7 @@
#include "foxenflac.hpp"
#include <stdint.h>
#include <sys/_stdint.h>
#include <cstdlib>
@ -44,13 +45,20 @@ auto FoxenFlacDecoder::BeginStream(const cpp::span<const std::byte> input)
return {bytes_used, cpp::fail(Error::kMalformedData)};
}
return {bytes_used,
OutputFormat{
.num_channels = static_cast<uint8_t>(channels),
.bits_per_sample = 32, // libfoxenflac output is fixed-size.
.sample_rate_hz = static_cast<uint32_t>(fs),
.duration_seconds = {},
}};
OutputFormat format{
.num_channels = static_cast<uint8_t>(channels),
.bits_per_sample = 32, // libfoxenflac output is fixed-size.
.sample_rate_hz = static_cast<uint32_t>(fs),
.duration_seconds = {},
.bits_per_second = {},
};
uint64_t num_samples = fx_flac_get_streaminfo(flac_, FLAC_KEY_N_SAMPLES);
if (num_samples > 0) {
format.duration_seconds = num_samples / fs;
}
return {bytes_used, format};
}
auto FoxenFlacDecoder::ContinueStream(cpp::span<const std::byte> input,

Loading…
Cancel
Save