summaryrefslogtreecommitdiff
path: root/src/drivers/pcm_buffer.cpp
diff options
context:
space:
mode:
authorjacqueline <me@jacqueline.id.au>2024-07-05 10:12:55 +1000
committerjacqueline <me@jacqueline.id.au>2024-07-05 10:12:55 +1000
commitf42448d50123e376205df17bc295917e89d943f5 (patch)
tree194e94f12836867fffa3fa429e55f40b133bc801 /src/drivers/pcm_buffer.cpp
parent1b7fb84220222a447b18b760a4d8437587b46c2a (diff)
downloadtangara-fw-f42448d50123e376205df17bc295917e89d943f5.tar.gz
WIP start on accepting two streams in out audio output
Diffstat (limited to 'src/drivers/pcm_buffer.cpp')
-rw-r--r--src/drivers/pcm_buffer.cpp24
1 files changed, 19 insertions, 5 deletions
diff --git a/src/drivers/pcm_buffer.cpp b/src/drivers/pcm_buffer.cpp
index 3f4a0443..b619cefb 100644
--- a/src/drivers/pcm_buffer.cpp
+++ b/src/drivers/pcm_buffer.cpp
@@ -44,14 +44,15 @@ auto PcmBuffer::send(std::span<const int16_t> data) -> void {
sent_ += data.size();
}
-IRAM_ATTR auto PcmBuffer::receive(std::span<int16_t> dest, bool isr)
+IRAM_ATTR auto PcmBuffer::receive(std::span<int16_t> dest, bool mix, bool isr)
-> BaseType_t {
size_t first_read = 0, second_read = 0;
BaseType_t ret1 = false, ret2 = false;
- std::tie(first_read, ret1) = readSingle(dest, isr);
+ std::tie(first_read, ret1) = readSingle(dest, mix, isr);
if (first_read < dest.size()) {
- std::tie(second_read, ret2) = readSingle(dest.subspan(first_read), isr);
+ std::tie(second_read, ret2) =
+ readSingle(dest.subspan(first_read), mix, isr);
}
size_t total_read = first_read + second_read;
@@ -86,7 +87,9 @@ auto PcmBuffer::totalReceived() -> uint32_t {
return received_;
}
-IRAM_ATTR auto PcmBuffer::readSingle(std::span<int16_t> dest, bool isr)
+IRAM_ATTR auto PcmBuffer::readSingle(std::span<int16_t> dest,
+ bool mix,
+ bool isr)
-> std::pair<size_t, BaseType_t> {
BaseType_t ret;
size_t read_bytes = 0;
@@ -104,7 +107,18 @@ IRAM_ATTR auto PcmBuffer::readSingle(std::span<int16_t> dest, bool isr)
return {read_samples, ret};
}
- std::memcpy(dest.data(), data, read_bytes);
+ if (mix) {
+ for (size_t i = 0; i < read_samples; i++) {
+ // Sum the two samples in a 32 bit field so that the addition is always
+ // safe.
+ int32_t sum = static_cast<int32_t>(dest[i]) +
+ static_cast<int32_t>(reinterpret_cast<int16_t*>(data)[i]);
+ // Clip back into the range of a single sample.
+ dest[i] = std::clamp<int32_t>(sum, INT16_MIN, INT16_MAX);
+ }
+ } else {
+ std::memcpy(dest.data(), data, read_bytes);
+ }
if (isr) {
vRingbufferReturnItem(ringbuf_, data);