summaryrefslogtreecommitdiff
path: root/src/codecs
diff options
context:
space:
mode:
Diffstat (limited to 'src/codecs')
-rw-r--r--src/codecs/foxenflac.cpp12
-rw-r--r--src/codecs/include/sample.hpp35
-rw-r--r--src/codecs/opus.cpp19
-rw-r--r--src/codecs/vorbis.cpp18
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,
};
}