diff options
| author | cooljqln <cooljqln@noreply.codeberg.org> | 2025-01-09 04:52:38 +0000 |
|---|---|---|
| committer | cooljqln <cooljqln@noreply.codeberg.org> | 2025-01-09 04:52:38 +0000 |
| commit | faf52c162f98fb78907ab7028e997ef3d316f393 (patch) | |
| tree | cd0631b047e8b09fbd61ea85ad1a67aa55929a25 /src/codecs | |
| parent | 829d033a448107f1bc610cf735ce9f7222de564b (diff) | |
| parent | faa62e0c60d51a9df88002a59825b427323259c0 (diff) | |
| download | tangara-fw-faf52c162f98fb78907ab7028e997ef3d316f393.tar.gz | |
Merge pull request 'Add bitrate info' (#172) from tjk/tangara-fw:bitrate into main
Reviewed-on: https://codeberg.org/cool-tech-zone/tangara-fw/pulls/172
Reviewed-by: cooljqln <cooljqln@noreply.codeberg.org>
Diffstat (limited to 'src/codecs')
| -rw-r--r-- | src/codecs/dr_flac.cpp | 7 | ||||
| -rw-r--r-- | src/codecs/include/codec.hpp | 1 | ||||
| -rw-r--r-- | src/codecs/include/mad.hpp | 2 | ||||
| -rw-r--r-- | src/codecs/mad.cpp | 23 | ||||
| -rw-r--r-- | src/codecs/native.cpp | 2 | ||||
| -rw-r--r-- | src/codecs/opus.cpp | 7 | ||||
| -rw-r--r-- | src/codecs/vorbis.cpp | 7 | ||||
| -rw-r--r-- | src/codecs/wav.cpp | 3 |
8 files changed, 44 insertions, 8 deletions
diff --git a/src/codecs/dr_flac.cpp b/src/codecs/dr_flac.cpp index 9341e938..939705ad 100644 --- a/src/codecs/dr_flac.cpp +++ b/src/codecs/dr_flac.cpp @@ -97,6 +97,13 @@ auto DrFlacDecoder::OpenStream(std::shared_ptr<IStream> input, uint32_t offset) .sample_rate_hz = static_cast<uint32_t>(flac_->sampleRate), .total_samples = flac_->totalPCMFrameCount * flac_->channels, }; + + if (input->Size() && format.total_samples) { + double sample_size = *(input->Size()) * 8.0 / *(format.total_samples); + format.bitrate_kbps = static_cast<uint32_t>( + flac_->sampleRate * flac_->channels * sample_size / 1024); + } + return format; } diff --git a/src/codecs/include/codec.hpp b/src/codecs/include/codec.hpp index 4d588a98..6ff7a267 100644 --- a/src/codecs/include/codec.hpp +++ b/src/codecs/include/codec.hpp @@ -106,6 +106,7 @@ class ICodec { uint8_t num_channels; uint32_t sample_rate_hz; std::optional<uint32_t> total_samples; + std::optional<uint32_t> bitrate_kbps; bool operator==(const OutputFormat&) const = default; }; diff --git a/src/codecs/include/mad.hpp b/src/codecs/include/mad.hpp index f45b5331..e28e32c8 100644 --- a/src/codecs/include/mad.hpp +++ b/src/codecs/include/mad.hpp @@ -36,7 +36,7 @@ class MadMp3Decoder : public ICodec { MadMp3Decoder& operator=(const MadMp3Decoder&) = delete; private: - auto SkipID3Tags(IStream& stream) -> void; + auto SkipID3Tags(IStream& stream) -> std::optional<uint32_t>; struct VbrInfo { uint32_t length; diff --git a/src/codecs/mad.cpp b/src/codecs/mad.cpp index af8b3ec1..d823d99d 100644 --- a/src/codecs/mad.cpp +++ b/src/codecs/mad.cpp @@ -63,7 +63,7 @@ auto MadMp3Decoder::OpenStream(std::shared_ptr<IStream> input, uint32_t offset) -> cpp::result<OutputFormat, ICodec::Error> { input_ = input; - SkipID3Tags(*input); + auto id3size = SkipID3Tags(*input); // To get the output format for MP3 streams, we simply need to decode the // first frame header. @@ -116,6 +116,14 @@ auto MadMp3Decoder::OpenStream(std::shared_ptr<IStream> input, uint32_t offset) output.total_samples = cbr_length * output.sample_rate_hz * channels; } + // header.bitrate is only for CBR, but we've calculated total samples for VBR + // and CBR, so we can use that to calculate sample size and therefore bitrate. + if (id3size && input->Size()) { + auto data_size = input->Size().value() - id3size.value(); + double sample_size = data_size * 8.0 / output.total_samples.value(); + output.bitrate_kbps = static_cast<uint32_t>(output.sample_rate_hz * channels * sample_size / 1024); + } + if (offset > 1 && cbr_length > 0) { // Constant bitrate seeking uint64_t skip_bytes = header.bitrate * (offset - 1) / 8; @@ -263,15 +271,15 @@ auto MadMp3Decoder::DecodeTo(std::span<sample::Sample> output) .is_stream_finished = is_eos_}; } -auto MadMp3Decoder::SkipID3Tags(IStream& stream) -> void { +auto MadMp3Decoder::SkipID3Tags(IStream& stream) -> std::optional<uint32_t> { // First check that the file actually does start with ID3 tags. std::array<std::byte, 3> magic_buf{}; if (stream.Read(magic_buf) != 3) { - return; + return {}; } if (std::memcmp(magic_buf.data(), "ID3", 3) != 0) { stream.SeekTo(0, IStream::SeekFrom::kStartOfStream); - return; + return {}; } // The size of the tags (*not* including the 10-byte header) is located 6 @@ -279,14 +287,17 @@ auto MadMp3Decoder::SkipID3Tags(IStream& stream) -> void { std::array<std::byte, 4> size_buf{}; stream.SeekTo(6, IStream::SeekFrom::kStartOfStream); if (stream.Read(size_buf) != 4) { - return; + return {}; } // Size is encoded with 7-bit ints for some reason. uint32_t tags_size = (static_cast<uint32_t>(size_buf[0]) << (7 * 3)) | (static_cast<uint32_t>(size_buf[1]) << (7 * 2)) | (static_cast<uint32_t>(size_buf[2]) << 7) | static_cast<uint32_t>(size_buf[3]); - stream.SeekTo(10 + tags_size, IStream::SeekFrom::kStartOfStream); + + auto skip_bytes = 10 + tags_size; + stream.SeekTo(skip_bytes, IStream::SeekFrom::kStartOfStream); + return skip_bytes; } /* diff --git a/src/codecs/native.cpp b/src/codecs/native.cpp index 124434e8..485694d1 100644 --- a/src/codecs/native.cpp +++ b/src/codecs/native.cpp @@ -30,6 +30,8 @@ auto NativeDecoder::OpenStream(std::shared_ptr<IStream> input, uint32_t offset) .num_channels = 1, .sample_rate_hz = 48000, .total_samples = {}, + // sample rate * channels * bits per sample / bits per kb + .bitrate_kbps = 48000 * 1 * 16 / 1024, }; } diff --git a/src/codecs/opus.cpp b/src/codecs/opus.cpp index b5e7c3fc..3b42516b 100644 --- a/src/codecs/opus.cpp +++ b/src/codecs/opus.cpp @@ -129,6 +129,12 @@ auto XiphOpusDecoder::OpenStream(std::shared_ptr<IStream> input, length = l * 2; } + auto b = op_bitrate(opus_, -1); + std::optional<uint32_t> bitrate_kbps; + if (b > 0) { + bitrate_kbps = b / 1024; + } + if (offset && op_pcm_seek(opus_, offset * 48000) != 0) { return cpp::fail(Error::kInternalError); } @@ -137,6 +143,7 @@ auto XiphOpusDecoder::OpenStream(std::shared_ptr<IStream> input, .num_channels = 2, .sample_rate_hz = 48000, .total_samples = length, + .bitrate_kbps = bitrate_kbps, }; } diff --git a/src/codecs/vorbis.cpp b/src/codecs/vorbis.cpp index ea33a2af..464aa4a2 100644 --- a/src/codecs/vorbis.cpp +++ b/src/codecs/vorbis.cpp @@ -118,6 +118,12 @@ auto TremorVorbisDecoder::OpenStream(std::shared_ptr<IStream> input, length = l * info->channels; } + auto b = ov_bitrate(vorbis_.get(), -1); + std::optional<uint32_t> bitrate_kbps; + if (b > 0) { + bitrate_kbps = b / 1024; + } + if (offset && ov_time_seek(vorbis_.get(), offset * 1000) != 0) { return cpp::fail(Error::kInternalError); } @@ -126,6 +132,7 @@ auto TremorVorbisDecoder::OpenStream(std::shared_ptr<IStream> input, .num_channels = static_cast<uint8_t>(info->channels), .sample_rate_hz = static_cast<uint32_t>(info->rate), .total_samples = length, + .bitrate_kbps = bitrate_kbps, }; } diff --git a/src/codecs/wav.cpp b/src/codecs/wav.cpp index 746f44ca..d80b7e48 100644 --- a/src/codecs/wav.cpp +++ b/src/codecs/wav.cpp @@ -216,7 +216,8 @@ auto WavDecoder::OpenStream(std::shared_ptr<IStream> input, uint32_t offset) output_format_ = {.num_channels = (uint8_t)num_channels_, .sample_rate_hz = samples_per_second, - .total_samples = number_of_samples}; + .total_samples = number_of_samples, + .bitrate_kbps = samples_per_second * num_channels_ * bytes_per_sample_ * 8 / 1024}; return output_format_; } |
