summaryrefslogtreecommitdiff
path: root/src/codecs/include
diff options
context:
space:
mode:
authorjacqueline <me@jacqueline.id.au>2023-08-08 20:25:42 +1000
committerjacqueline <me@jacqueline.id.au>2023-08-08 20:25:42 +1000
commite1181fbe59a835ea9c93d6e067e9757e8c522d3c (patch)
tree2fd61bb93713de8c2205b7b6d0a8c84c49832e93 /src/codecs/include
parentc3f40a8cc37114365ef3ec6f2888df64e5206b39 (diff)
parent592f231627843bc44ebaaa4506aec26da1f56499 (diff)
downloadtangara-fw-e1181fbe59a835ea9c93d6e067e9757e8c522d3c.tar.gz
Merge branch 'main' into opus
Diffstat (limited to 'src/codecs/include')
-rw-r--r--src/codecs/include/codec.hpp6
-rw-r--r--src/codecs/include/foxenflac.hpp3
-rw-r--r--src/codecs/include/mad.hpp3
-rw-r--r--src/codecs/include/sample.hpp65
4 files changed, 72 insertions, 5 deletions
diff --git a/src/codecs/include/codec.hpp b/src/codecs/include/codec.hpp
index e8be8f0a..32ebef69 100644
--- a/src/codecs/include/codec.hpp
+++ b/src/codecs/include/codec.hpp
@@ -17,6 +17,7 @@
#include <utility>
#include "result.hpp"
+#include "sample.hpp"
#include "span.hpp"
#include "types.hpp"
@@ -61,7 +62,6 @@ class ICodec {
struct OutputFormat {
uint8_t num_channels;
- uint8_t bits_per_sample;
uint32_t sample_rate_hz;
std::optional<uint32_t> duration_seconds;
@@ -76,7 +76,7 @@ class ICodec {
-> Result<OutputFormat> = 0;
struct OutputInfo {
- std::size_t bytes_written;
+ std::size_t samples_written;
bool is_finished_writing;
};
@@ -84,7 +84,7 @@ class ICodec {
* Writes PCM samples to the given output buffer.
*/
virtual auto ContinueStream(cpp::span<const std::byte> input,
- cpp::span<std::byte> output)
+ cpp::span<sample::Sample> output)
-> Result<OutputInfo> = 0;
virtual auto SeekStream(cpp::span<const std::byte> input,
diff --git a/src/codecs/include/foxenflac.hpp b/src/codecs/include/foxenflac.hpp
index cce1b762..abfa6d80 100644
--- a/src/codecs/include/foxenflac.hpp
+++ b/src/codecs/include/foxenflac.hpp
@@ -14,6 +14,7 @@
#include <utility>
#include "foxen/flac.h"
+#include "sample.hpp"
#include "span.hpp"
#include "codec.hpp"
@@ -26,7 +27,7 @@ class FoxenFlacDecoder : public ICodec {
~FoxenFlacDecoder();
auto BeginStream(cpp::span<const std::byte>) -> Result<OutputFormat> override;
- auto ContinueStream(cpp::span<const std::byte>, cpp::span<std::byte>)
+ auto ContinueStream(cpp::span<const std::byte>, cpp::span<sample::Sample>)
-> Result<OutputInfo> override;
auto SeekStream(cpp::span<const std::byte> input, std::size_t target_sample)
-> Result<void> override;
diff --git a/src/codecs/include/mad.hpp b/src/codecs/include/mad.hpp
index fbae560c..b81e4acb 100644
--- a/src/codecs/include/mad.hpp
+++ b/src/codecs/include/mad.hpp
@@ -13,6 +13,7 @@
#include <utility>
#include "mad.h"
+#include "sample.hpp"
#include "span.hpp"
#include "codec.hpp"
@@ -35,7 +36,7 @@ class MadMp3Decoder : public ICodec {
* Writes samples for the current frame.
*/
auto ContinueStream(cpp::span<const std::byte> input,
- cpp::span<std::byte> output)
+ cpp::span<sample::Sample> output)
-> Result<OutputInfo> override;
auto SeekStream(cpp::span<const std::byte> input, std::size_t target_sample)
diff --git a/src/codecs/include/sample.hpp b/src/codecs/include/sample.hpp
new file mode 100644
index 00000000..f8e08cdc
--- /dev/null
+++ b/src/codecs/include/sample.hpp
@@ -0,0 +1,65 @@
+#pragma once
+
+#include <stdint.h>
+
+#include <algorithm>
+
+#include <mad.h>
+
+namespace sample {
+
+// A signed, 32-bit PCM sample.
+typedef int32_t Sample;
+
+constexpr auto Clip(int64_t v) -> Sample {
+ if (v > INT32_MAX)
+ return INT32_MAX;
+ if (v < INT32_MIN)
+ return INT32_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);
+}
+
+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);
+}
+
+constexpr auto FromFloat(float src) -> Sample {
+ return std::clamp<float>(src, -1.0f, 1.0f) * static_cast<float>(INT32_MAX);
+}
+
+constexpr auto FromDouble(double src) -> Sample {
+ return std::clamp<double>(src, -1.0, 1.0) * static_cast<double>(INT32_MAX);
+}
+
+constexpr auto FromMad(mad_fixed_t src) -> Sample {
+ // Round the bottom bits.
+ src += (1L << (MAD_F_FRACBITS - 24));
+
+ // Clip the leftover bits to within range.
+ if (src >= MAD_F_ONE)
+ src = MAD_F_ONE - 1;
+ else if (src < -MAD_F_ONE)
+ src = -MAD_F_ONE;
+
+ // Quantize.
+ return FromSigned(src >> (MAD_F_FRACBITS + 1 - 24), 24);
+}
+
+constexpr auto ToSigned16Bit(Sample src) -> int16_t {
+ return src >> 16;
+}
+
+static constexpr float kFactor = 1.0f / static_cast<float>(INT32_MAX);
+
+constexpr auto ToFloat(Sample src) -> float {
+ return src * kFactor;
+}
+
+} // namespace sample