diff options
Diffstat (limited to 'src/codecs')
| -rw-r--r-- | src/codecs/foxenflac.cpp | 12 | ||||
| -rw-r--r-- | src/codecs/include/sample.hpp | 35 | ||||
| -rw-r--r-- | src/codecs/opus.cpp | 19 | ||||
| -rw-r--r-- | src/codecs/vorbis.cpp | 18 |
4 files changed, 36 insertions, 48 deletions
diff --git a/src/codecs/foxenflac.cpp b/src/codecs/foxenflac.cpp index cc110920..eef8225a 100644 --- a/src/codecs/foxenflac.cpp +++ b/src/codecs/foxenflac.cpp @@ -74,19 +74,25 @@ auto FoxenFlacDecoder::DecodeTo(cpp::span<sample::Sample> output) -> cpp::result<OutputInfo, Error> { bool is_eof = buffer_.Refill(input_.get()); - fx_flac_state_t state; - uint32_t samples_written = output.size(); + cpp::span<int32_t> output32{reinterpret_cast<int32_t*>(output.data()), + output.size() / 2}; + uint32_t samples_written = output32.size(); + fx_flac_state_t state; buffer_.ConsumeBytes([&](cpp::span<std::byte> buf) -> size_t { uint32_t bytes_read = buf.size_bytes(); state = fx_flac_process(flac_, reinterpret_cast<const uint8_t*>(buf.data()), - &bytes_read, output.data(), &samples_written); + &bytes_read, output32.data(), &samples_written); return bytes_read; }); if (state == FLAC_ERR) { return cpp::fail(Error::kMalformedData); } + for (size_t i = 0; i < samples_written; i++) { + output[i] = output32[i] >> 16; + } + return OutputInfo{.samples_written = samples_written, .is_stream_finished = samples_written == 0 && is_eof}; } diff --git a/src/codecs/include/sample.hpp b/src/codecs/include/sample.hpp index f8e08cdc..ea3a7ffc 100644 --- a/src/codecs/include/sample.hpp +++ b/src/codecs/include/sample.hpp @@ -9,38 +9,43 @@ namespace sample { // A signed, 32-bit PCM sample. -typedef int32_t Sample; +typedef int16_t Sample; constexpr auto Clip(int64_t v) -> Sample { - if (v > INT32_MAX) - return INT32_MAX; - if (v < INT32_MIN) - return INT32_MIN; + if (v > INT16_MAX) + return INT16_MAX; + if (v < INT16_MIN) + return INT16_MIN; return v; } constexpr auto FromSigned(int32_t src, uint_fast8_t bits) -> Sample { - // Left-align samples, effectively scaling them up to 32 bits. - return src << (sizeof(Sample) * 8 - bits); + if (bits > 16) { + // Left-align samples, effectively scaling them up to 32 bits. + return src << (sizeof(Sample) * 8 - bits); + } else if (bits < 16) { + return src << (bits - (sizeof(Sample) * 8)); + } + return src; } constexpr auto FromUnsigned(uint32_t src, uint_fast8_t bits) -> Sample { // Left-align, then substract the max value / 2 to make the sample centred // around zero. - return (src << (sizeof(uint32_t) * 8 - bits)) - (~0UL >> 1); + return (src << (sizeof(uint16_t) * 8 - bits)) - (~0UL >> 1); } constexpr auto FromFloat(float src) -> Sample { - return std::clamp<float>(src, -1.0f, 1.0f) * static_cast<float>(INT32_MAX); + return std::clamp<float>(src, -1.0f, 1.0f) * static_cast<float>(INT16_MAX); } constexpr auto FromDouble(double src) -> Sample { - return std::clamp<double>(src, -1.0, 1.0) * static_cast<double>(INT32_MAX); + return std::clamp<double>(src, -1.0, 1.0) * static_cast<double>(INT16_MAX); } constexpr auto FromMad(mad_fixed_t src) -> Sample { // Round the bottom bits. - src += (1L << (MAD_F_FRACBITS - 24)); + src += (1L << (MAD_F_FRACBITS - 16)); // Clip the leftover bits to within range. if (src >= MAD_F_ONE) @@ -49,14 +54,10 @@ constexpr auto FromMad(mad_fixed_t src) -> Sample { src = -MAD_F_ONE; // Quantize. - return FromSigned(src >> (MAD_F_FRACBITS + 1 - 24), 24); + return FromSigned(src >> (MAD_F_FRACBITS + 1 - 16), 16); } -constexpr auto ToSigned16Bit(Sample src) -> int16_t { - return src >> 16; -} - -static constexpr float kFactor = 1.0f / static_cast<float>(INT32_MAX); +static constexpr float kFactor = 1.0f / static_cast<float>(INT16_MAX); constexpr auto ToFloat(Sample src) -> float { return src * kFactor; diff --git a/src/codecs/opus.cpp b/src/codecs/opus.cpp index 70ec9e45..c0727c6b 100644 --- a/src/codecs/opus.cpp +++ b/src/codecs/opus.cpp @@ -122,35 +122,24 @@ auto XiphOpusDecoder::OpenStream(std::shared_ptr<IStream> input) return cpp::fail(Error::kMalformedData); } - num_channels_ = std::min<uint8_t>(2, op_channel_count(opus_, -1)); - return OutputFormat{ - .num_channels = num_channels_, + .num_channels = 2, .sample_rate_hz = 48000, }; } auto XiphOpusDecoder::DecodeTo(cpp::span<sample::Sample> output) -> cpp::result<OutputInfo, Error> { - cpp::span<int16_t> staging_buffer{ - reinterpret_cast<int16_t*>(output.subspan(output.size() / 2).data()), - output.size_bytes() / 2}; - - int samples_written = - op_read_stereo(opus_, staging_buffer.data(), staging_buffer.size()); + int samples_written = op_read_stereo(opus_, output.data(), output.size()); if (samples_written < 0) { ESP_LOGE(kTag, "read failed %i", samples_written); return cpp::fail(Error::kMalformedData); } - samples_written *= num_channels_; - for (int i = 0; i < samples_written; i++) { - output[i] = sample::FromSigned(staging_buffer[i], 16); - } - + samples_written *= 2; // Fixed to stereo return OutputInfo{ - .samples_written = static_cast<size_t>(samples_written / 2), + .samples_written = static_cast<size_t>(samples_written), .is_stream_finished = samples_written == 0, }; } diff --git a/src/codecs/vorbis.cpp b/src/codecs/vorbis.cpp index 6fa3256a..aa367e02 100644 --- a/src/codecs/vorbis.cpp +++ b/src/codecs/vorbis.cpp @@ -126,14 +126,9 @@ auto TremorVorbisDecoder::OpenStream(std::shared_ptr<IStream> input) auto TremorVorbisDecoder::DecodeTo(cpp::span<sample::Sample> output) -> cpp::result<OutputInfo, Error> { - cpp::span<int16_t> staging_buffer{ - reinterpret_cast<int16_t*>(output.subspan(output.size() / 2).data()), - output.size_bytes() / 2}; - - int bitstream; - long bytes_written = - ov_read(&vorbis_, reinterpret_cast<char*>(staging_buffer.data()), - staging_buffer.size_bytes(), &bitstream); + int bitstream = 0; + long bytes_written = ov_read(&vorbis_, reinterpret_cast<char*>(output.data()), + output.size_bytes(), &bitstream); if (bytes_written == OV_HOLE) { ESP_LOGE(kTag, "got OV_HOLE"); return cpp::fail(Error::kMalformedData); @@ -142,12 +137,9 @@ auto TremorVorbisDecoder::DecodeTo(cpp::span<sample::Sample> output) return cpp::fail(Error::kMalformedData); } - for (int i = 0; i < bytes_written / 2; i++) { - output[i] = sample::FromSigned(staging_buffer[i], 16); - } - return OutputInfo{ - .samples_written = static_cast<size_t>(bytes_written / 2), + .samples_written = + static_cast<size_t>(bytes_written / sizeof(sample::Sample)), .is_stream_finished = bytes_written == 0, }; } |
