From 43fed076ad29e8aa8a14b5765e1d133aa9ff7cbb Mon Sep 17 00:00:00 2001 From: maciejmakowski2003 Date: Mon, 2 Feb 2026 16:21:51 +0100 Subject: [PATCH 01/30] refactor: audio array --- .../common/cpp/audioapi/utils/AudioArray.cpp | 229 +++++++++++++----- .../common/cpp/audioapi/utils/AudioArray.h | 76 ++++-- 2 files changed, 215 insertions(+), 90 deletions(-) diff --git a/packages/react-native-audio-api/common/cpp/audioapi/utils/AudioArray.cpp b/packages/react-native-audio-api/common/cpp/audioapi/utils/AudioArray.cpp index 0e321ed80..bc29aaf59 100644 --- a/packages/react-native-audio-api/common/cpp/audioapi/utils/AudioArray.cpp +++ b/packages/react-native-audio-api/common/cpp/audioapi/utils/AudioArray.cpp @@ -1,121 +1,218 @@ #include #include + #include +#include +#include -namespace audioapi { +#if defined(__ARM_NEON) +#include +#endif -AudioArray::AudioArray(size_t size) : data_(nullptr), size_(size) { - resize(size); -} - -AudioArray::AudioArray(const AudioArray &other) : data_(nullptr), size_(0) { - resize(other.size_); +namespace audioapi { - copy(&other); +AudioArray::AudioArray(size_t size): size_(size) { + if (size_ > 0) { + data_ = std::make_unique(size_); + zero(); + } } AudioArray::AudioArray(const float *data, size_t size) : size_(size) { - data_ = new float[size_]; - memcpy(data_, data, size_ * sizeof(float)); + if (size_ > 0) { + data_ = std::make_unique(size_); + std::memcpy(data_.get(), data, size_ * sizeof(float)); + } } -AudioArray::~AudioArray() { - if (data_) { - delete[] data_; - data_ = nullptr; - } +AudioArray::AudioArray(const AudioArray &other) : size_(other.size_) { + if (size_ > 0 && other.data_) { + data_ = std::make_unique(size_); + std::memcpy(data_.get(), other.data_.get(), size_ * sizeof(float)); + } } -size_t AudioArray::getSize() const { - return size_; +AudioArray::AudioArray(audioapi::AudioArray &&other) noexcept : data_(std::move(other.data_)), size_(other.size_) { + other.size_ = 0; } -float *AudioArray::getData() const { - return data_; -} +AudioArray &AudioArray::operator=(const audioapi::AudioArray &other) { + if (this != &other) { + if (size_ != other.size_) { + size_ = other.size_; + data_ = (size_ > 0) ? std::make_unique(size_) : nullptr; + } -float &AudioArray::operator[](size_t index) { - return data_[index]; -} + if (size_ > 0 && data_) { + std::memcpy(data_.get(), other.data_.get(), size_ * sizeof(float)); + } + } -const float &AudioArray::operator[](size_t index) const { - return data_[index]; + return *this; } -void AudioArray::normalize() { - float maxAbsValue = getMaxAbsValue(); - - if (maxAbsValue == 0.0f || maxAbsValue == 1.0f) { - return; - } +AudioArray &AudioArray::operator=(audioapi::AudioArray &&other) noexcept { + if (this != &other) { + data_ = std::move(other.data_); + size_ = other.size_; + other.size_ = 0; + } - dsp::multiplyByScalar(data_, 1.0f / maxAbsValue, data_, size_); + return *this; } void AudioArray::resize(size_t size) { - if (size == size_) { - if (!data_) { - data_ = new float[size]; - } - - zero(0, size); + if (size == size_ && data_ != nullptr) { + zero(); return; } - delete[] data_; size_ = size; - data_ = new float[size_]; + data_ = (size_ > 0) ? std::make_unique(size_) : nullptr; + if (data_ != nullptr) { + zero(); + } +} +void AudioArray::zero() noexcept { zero(0, size_); } -void AudioArray::scale(float value) { - dsp::multiplyByScalar(data_, value, data_, size_); +void AudioArray::zero(size_t start, size_t length) noexcept { + if (data_ == nullptr || length <= 0) { + return; + } + + memset(data_.get() + start, 0, length * sizeof(float)); } -float AudioArray::getMaxAbsValue() const { - return dsp::maximumMagnitude(data_, size_); +void AudioArray::sum(const AudioArray &source, float gain) { + sum(source, 0, 0, size_, gain); } -void AudioArray::zero() { - zero(0, size_); +void AudioArray::sum( + const AudioArray &source, + size_t sourceStart, + size_t destinationStart, + size_t length, + float gain) { + if (length == 0 || data_ == nullptr || source.data_ == nullptr) { + return; + } + + // Using restrict to inform the compiler that the source and destination do not overlap + float* __restrict dest = data_.get() + destinationStart; + const float* __restrict src = source.data_.get() + sourceStart; + + dsp::multiplyByScalarThenAddToOutput(src, gain, dest, length); } -void AudioArray::zero(size_t start, size_t length) { - memset(data_ + start, 0, length * sizeof(float)); +void AudioArray::multiply(const AudioArray &source) { + if (data_ == nullptr || source.data_ == nullptr) { + return; + } + + float* __restrict dest = data_.get(); + const float* __restrict src = source.data_.get(); + + dsp::multiply(src, dest, dest, size_); } -void AudioArray::sum(const AudioArray *source) { - sum(source, 0, 0, size_); +void AudioArray::multiplyByScalar(float value) { + if (data_ == nullptr) { + return; + } + + dsp::multiplyByScalar(data_.get(), value, data_.get(), size_); } -void AudioArray::sum(const AudioArray *source, size_t start, size_t length) { - sum(source, start, start, length); +void AudioArray::copy(const AudioArray &source) { + copy(source, 0, 0, size_); } -void AudioArray::sum( - const AudioArray *source, +void AudioArray::copy( + const AudioArray &source, size_t sourceStart, size_t destinationStart, size_t length) { - dsp::add( - data_ + destinationStart, source->getData() + sourceStart, data_ + destinationStart, length); + if (length == 0 || data_ == nullptr || source.data_ == nullptr) { + return; + } + + memcpy(data_.get() + destinationStart, source.data_.get() + sourceStart, length * sizeof(float)); } -void AudioArray::copy(const AudioArray *source) { - copy(source, 0, size_); +void AudioArray::reverse() { + if (data_ == nullptr && size_ > 1) { + return; + } + + std::reverse(begin(), end()); } -void AudioArray::copy(const AudioArray *source, size_t start, size_t length) { - copy(source, start, start, length); +void AudioArray::normalize() { + float maxAbsValue = getMaxAbsValue(); + + if (maxAbsValue == 0.0f || maxAbsValue == 1.0f) { + return; + } + + dsp::multiplyByScalar(data_.get(), 1.0f / maxAbsValue, data_.get(), size_); } -void AudioArray::copy( - const AudioArray *source, - size_t sourceStart, - size_t destinationStart, - size_t length) { - memcpy(data_ + destinationStart, source->getData() + sourceStart, length * sizeof(float)); +void AudioArray::scale(float value) { + if (data_ == nullptr) { + return; + } + + dsp::multiplyByScalar(data_.get(), value, data_.get(), size_); +} + +float AudioArray::getMaxAbsValue() const { + if (data_ == nullptr) { + return 0.0f; + } + + return dsp::maximumMagnitude(data_.get(), size_); +} + +float AudioArray::computeConvolution(const audioapi::AudioArray &kernel, size_t startIndex) const { + const auto kernelSize = kernel.size_; + + if (startIndex + kernelSize > size_ || !data_ || !kernel.data_) { + return 0.0f; + } + + const auto stateStart = data_.get() + startIndex; + const auto kernelStart = kernel.data_.get(); + + float sum = 0.0f; + size_t k = 0; + +#ifdef __ARM_NEON + float32x4_t vSum = vdupq_n_f32(0.0f); + + // process 4 samples at a time + for (; k <= kernelSize_ - 4; k += 4) { + float32x4_t vState = vld1q_f32(stateStart + k); + float32x4_t vKernel = vld1q_f32(kernelStart + k); + + // fused multiply-add: vSum += vState * vKernel + vSum = vmlaq_f32(vSum, vState, vKernel); + } + + // horizontal reduction: Sum the 4 lanes of vSum into a single float + sum += vgetq_lane_f32(vSum, 0); + sum += vgetq_lane_f32(vSum, 1); + sum += vgetq_lane_f32(vSum, 2); + sum += vgetq_lane_f32(vSum, 3); +#endif + + for (; k < kernelSize; ++k) { + sum += stateStart[k] * kernelStart[k]; + } + + return sum; } } // namespace audioapi diff --git a/packages/react-native-audio-api/common/cpp/audioapi/utils/AudioArray.h b/packages/react-native-audio-api/common/cpp/audioapi/utils/AudioArray.h index 9291f22ff..bf6743bad 100644 --- a/packages/react-native-audio-api/common/cpp/audioapi/utils/AudioArray.h +++ b/packages/react-native-audio-api/common/cpp/audioapi/utils/AudioArray.h @@ -10,40 +10,68 @@ namespace audioapi { class AudioArray { public: explicit AudioArray(size_t size); - AudioArray(const AudioArray &other); - - /// @brief Construct AudioArray from raw float data - /// @param data Pointer to the float data - /// @param size Number of float samples /// @note The data is copied, so it does not take ownership of the pointer AudioArray(const float *data, size_t size); - ~AudioArray(); + ~AudioArray() = default; - [[nodiscard]] size_t getSize() const; - [[nodiscard]] float *getData() const; + AudioArray(const AudioArray &other); + AudioArray(AudioArray &&other) noexcept; + AudioArray &operator=(const AudioArray &other); + AudioArray &operator=(AudioArray &&other) noexcept; - float &operator[](size_t index); - const float &operator[](size_t index) const; + [[nodiscard]] inline size_t getSize() const { + return size_; + } + + inline float &operator[](size_t index) { + return data_[index]; + } + inline const float &operator[](size_t index) const { + return data_[index]; + } + + [[nodiscard]] inline float *begin() noexcept { + return data_.get(); + } + [[nodiscard]] inline float *end() noexcept { + return data_.get() + size_; + } + + [[nodiscard]] inline const float *begin() const noexcept { + return data_.get(); + } + [[nodiscard]] inline const float *end() const noexcept { + return data_.get() + size_; + } - void normalize(); void resize(size_t size); - void scale(float value); - [[nodiscard]] float getMaxAbsValue() const; - void zero(); - void zero(size_t start, size_t length); + void zero() noexcept; + void zero(size_t start, size_t length) noexcept; + + void sum(const AudioArray &source, float gain = 1.0f); + void sum( + const AudioArray &source, + size_t sourceStart, + size_t destinationStart, + size_t length, + float gain = 1.0f); + + void multiply(const AudioArray &source); + void multiplyByScalar(float value); - void sum(const AudioArray *source); - void sum(const AudioArray *source, size_t start, size_t length); - void sum(const AudioArray *source, size_t sourceStart, size_t destinationStart, size_t length); + void copy(const AudioArray &source); + void copy(const AudioArray &source, size_t sourceStart, size_t destinationStart, size_t length); - void copy(const AudioArray *source); - void copy(const AudioArray *source, size_t start, size_t length); - void copy(const AudioArray *source, size_t sourceStart, size_t destinationStart, size_t length); + void reverse(); + void normalize(); + void scale(float value); + [[nodiscard]] float getMaxAbsValue() const; + [[nodiscard]] float computeConvolution(const AudioArray &kernel, size_t startIndex = 0) const; - protected: - float *data_; - size_t size_; + private: + std::unique_ptr data_ = nullptr; + size_t size_ = 0; }; } // namespace audioapi From 6ad3a2b16929802d83ff18b5ac9617241b2bf4d8 Mon Sep 17 00:00:00 2001 From: maciejmakowski2003 Date: Mon, 2 Feb 2026 16:23:32 +0100 Subject: [PATCH 02/30] feat: audio bus --- .../common/cpp/audioapi/utils/AudioBus.cpp | 393 +++++++----------- .../common/cpp/audioapi/utils/AudioBus.h | 60 +-- 2 files changed, 180 insertions(+), 273 deletions(-) diff --git a/packages/react-native-audio-api/common/cpp/audioapi/utils/AudioBus.cpp b/packages/react-native-audio-api/common/cpp/audioapi/utils/AudioBus.cpp index 5276b434b..ee14402fc 100644 --- a/packages/react-native-audio-api/common/cpp/audioapi/utils/AudioBus.cpp +++ b/packages/react-native-audio-api/common/cpp/audioapi/utils/AudioBus.cpp @@ -24,66 +24,63 @@ AudioBus::AudioBus(size_t size, int numberOfChannels, float sampleRate) createChannels(); } -AudioBus::AudioBus(const AudioBus &other) { - numberOfChannels_ = other.numberOfChannels_; - sampleRate_ = other.sampleRate_; - size_ = other.size_; - +AudioBus::AudioBus(const AudioBus &other): numberOfChannels_(other.numberOfChannels_), + sampleRate_(other.sampleRate_), + size_(other.size_) { createChannels(); for (int i = 0; i < numberOfChannels_; i += 1) { - channels_[i] = std::make_shared(*other.channels_[i]); + *channels_[i] = *other.channels_[i]; } } -AudioBus::AudioBus(AudioBus &&other) noexcept - : channels_(std::move(other.channels_)), - numberOfChannels_(other.numberOfChannels_), - sampleRate_(other.sampleRate_), - size_(other.size_) { - other.numberOfChannels_ = 0; - other.sampleRate_ = 0.0f; - other.size_ = 0; +AudioBus::AudioBus(audioapi::AudioBus &&other) noexcept : + channels_(std::move(other.channels_)), + numberOfChannels_(other.numberOfChannels_), + sampleRate_(other.sampleRate_), + size_(other.size_) { + other.numberOfChannels_ = 0; + other.sampleRate_ = 0.0f; + other.size_ = 0; } AudioBus &AudioBus::operator=(const AudioBus &other) { - if (this == &other) { - return *this; - } - - numberOfChannels_ = other.numberOfChannels_; - sampleRate_ = other.sampleRate_; - size_ = other.size_; + if (this != &other) { + if (numberOfChannels_ != other.numberOfChannels_ || size_ != other.size_) { + numberOfChannels_ = other.numberOfChannels_; + size_ = other.size_; + createChannels(); + } - createChannels(); + sampleRate_ = other.sampleRate_; - for (int i = 0; i < numberOfChannels_; i += 1) { - channels_[i] = std::make_shared(*other.channels_[i]); + for (int i = 0; i < numberOfChannels_; i += 1) { + *channels_[i] = *other.channels_[i]; + } } return *this; } -AudioBus::~AudioBus() { - channels_.clear(); +AudioBus &AudioBus::operator=(audioapi::AudioBus &&other) noexcept { + if (this != &other) { + channels_ = std::move(other.channels_); + + numberOfChannels_ = other.numberOfChannels_; + sampleRate_ = other.sampleRate_; + size_ = other.size_; + + other.numberOfChannels_ = 0; + other.sampleRate_ = 0.0f; + other.size_ = 0; + } + return *this; } /** * Public interfaces - getters */ -int AudioBus::getNumberOfChannels() const { - return numberOfChannels_; -} - -float AudioBus::getSampleRate() const { - return sampleRate_; -} - -size_t AudioBus::getSize() const { - return size_; -} - AudioArray *AudioBus::getChannel(int index) const { return channels_[index].get(); } @@ -162,14 +159,6 @@ std::shared_ptr AudioBus::getSharedChannel(int index) const { return channels_[index]; } -AudioArray &AudioBus::operator[](size_t index) { - return *channels_[index]; -} - -const AudioArray &AudioBus::operator[](size_t index) const { - return *channels_[index]; -} - /** * Public interfaces - audio processing and setters */ @@ -184,57 +173,21 @@ void AudioBus::zero(size_t start, size_t length) { } } -void AudioBus::normalize() { - float maxAbsValue = this->maxAbsValue(); - - if (maxAbsValue == 0.0f || maxAbsValue == 1.0f) { - return; - } - - float scale = 1.0f / maxAbsValue; - this->scale(scale); -} - -void AudioBus::scale(float value) { - for (auto &channel : channels_) { - channel->scale(value); - } -} - -float AudioBus::maxAbsValue() const { - float maxAbsValue = 1.0f; - - for (const auto &channel : channels_) { - float channelMaxAbsValue = channel->getMaxAbsValue(); - maxAbsValue = std::max(maxAbsValue, channelMaxAbsValue); - } - - return maxAbsValue; -} - -void AudioBus::sum(const AudioBus *source, ChannelInterpretation interpretation) { +void AudioBus::sum(const AudioBus& source, ChannelInterpretation interpretation) { sum(source, 0, 0, getSize(), interpretation); } void AudioBus::sum( - const AudioBus *source, - size_t start, - size_t length, - ChannelInterpretation interpretation) { - sum(source, start, start, length, interpretation); -} - -void AudioBus::sum( - const AudioBus *source, + const AudioBus& source, size_t sourceStart, size_t destinationStart, size_t length, ChannelInterpretation interpretation) { - if (source == this) { + if (&source == this) { return; } - int numberOfSourceChannels = source->getNumberOfChannels(); + int numberOfSourceChannels = source.getNumberOfChannels(); int numberOfChannels = getNumberOfChannels(); if (interpretation == ChannelInterpretation::DISCRETE) { @@ -255,31 +208,27 @@ void AudioBus::sum( } // Source and destination channel counts are the same. Just sum the channels. - for (int i = 0; i < numberOfChannels_; i += 1) { - getChannel(i)->sum(source->getChannel(i), sourceStart, destinationStart, length); + for (int i = 0; i < getNumberOfChannels(); i += 1) { + channels_[i]->sum(*source.channels_[i], sourceStart, destinationStart, length); } } -void AudioBus::copy(const AudioBus *source) { +void AudioBus::copy(const AudioBus& source) { copy(source, 0, 0, getSize()); } -void AudioBus::copy(const AudioBus *source, size_t start, size_t length) { - copy(source, start, start, length); -} - void AudioBus::copy( - const AudioBus *source, + const AudioBus& source, size_t sourceStart, size_t destinationStart, size_t length) { - if (source == this) { + if (&source == this) { return; } - if (source->getNumberOfChannels() == getNumberOfChannels()) { + if (source.getNumberOfChannels() == getNumberOfChannels()) { for (int i = 0; i < getNumberOfChannels(); i += 1) { - getChannel(i)->copy(source->getChannel(i), sourceStart, destinationStart, length); + channels_[i]->copy(*source.channels_[i], sourceStart, destinationStart, length); } return; @@ -290,15 +239,50 @@ void AudioBus::copy( sum(source, sourceStart, destinationStart, length); } +void AudioBus::normalize() { + float maxAbsValue = this->maxAbsValue(); + + if (maxAbsValue == 0.0f || maxAbsValue == 1.0f) { + return; + } + + float scale = 1.0f / maxAbsValue; + this->scale(scale); +} + +void AudioBus::scale(float value) { + for (auto &channel : channels_) { + channel->scale(value); + } +} + +float AudioBus::maxAbsValue() const { + float maxAbsValue = 1.0f; + + for (const auto &channel : channels_) { + float channelMaxAbsValue = channel->getMaxAbsValue(); + maxAbsValue = std::max(maxAbsValue, channelMaxAbsValue); + } + + return maxAbsValue; +} + /** * Internal tooling - channel initialization */ void AudioBus::createChannels() { - channels_ = std::vector>(numberOfChannels_); + if (channels_.size() != static_cast(numberOfChannels_)) { + channels_.clear(); + channels_.reserve(numberOfChannels_); - for (int i = 0; i < numberOfChannels_; i += 1) { - channels_[i] = std::make_shared(size_); + for (int i = 0; i < numberOfChannels_; i += 1) { + channels_.emplace_back(std::make_shared(size_)); + } + } else { + for (int i = 0; i < numberOfChannels_; i += 1) { + channels_[i]->resize(size_); + } } } @@ -307,65 +291,64 @@ void AudioBus::createChannels() { */ void AudioBus::discreteSum( - const AudioBus *source, + const AudioBus& source, size_t sourceStart, size_t destinationStart, size_t length) const { - int numberOfChannels = std::min(getNumberOfChannels(), source->getNumberOfChannels()); + int numberOfChannels = std::min(getNumberOfChannels(), source.getNumberOfChannels()); // In case of source > destination, we "down-mix" and drop the extra channels. // In case of source < destination, we "up-mix" as many channels as we have, // leaving the remaining channels untouched. for (int i = 0; i < numberOfChannels; i++) { - getChannel(i)->sum(source->getChannel(i), sourceStart, destinationStart, length); + channels_[i]->sum(*source.channels_[i], sourceStart, destinationStart, length); } } void AudioBus::sumByUpMixing( - const AudioBus *source, + const AudioBus& source, size_t sourceStart, size_t destinationStart, size_t length) { - int numberOfSourceChannels = source->getNumberOfChannels(); + int numberOfSourceChannels = source.getNumberOfChannels(); int numberOfChannels = getNumberOfChannels(); // Mono to stereo (1 -> 2, 4) if (numberOfSourceChannels == 1 && (numberOfChannels == 2 || numberOfChannels == 4)) { - AudioArray *sourceChannel = source->getChannelByType(ChannelMono); + AudioArray *sourceChannel = source.getChannelByType(ChannelMono); - getChannelByType(ChannelLeft)->sum(sourceChannel, sourceStart, destinationStart, length); - getChannelByType(ChannelRight)->sum(sourceChannel, sourceStart, destinationStart, length); + getChannelByType(ChannelLeft)->sum(*sourceChannel, sourceStart, destinationStart, length); + getChannelByType(ChannelRight)->sum(*sourceChannel, sourceStart, destinationStart, length); return; } // Mono to 5.1 (1 -> 6) if (numberOfSourceChannels == 1 && numberOfChannels == 6) { - AudioArray *sourceChannel = source->getChannel(0); + AudioArray *sourceChannel = source.getChannel(0); - getChannelByType(ChannelCenter)->sum(sourceChannel, sourceStart, destinationStart, length); + getChannelByType(ChannelCenter)->sum(*sourceChannel, sourceStart, destinationStart, length); return; } // Stereo 2 to stereo 4 or 5.1 (2 -> 4, 6) if (numberOfSourceChannels == 2 && (numberOfChannels == 4 || numberOfChannels == 6)) { getChannelByType(ChannelLeft) - ->sum(source->getChannelByType(ChannelLeft), sourceStart, destinationStart, length); + ->sum(*source.getChannelByType(ChannelLeft), sourceStart, destinationStart, length); getChannelByType(ChannelRight) - ->sum(source->getChannelByType(ChannelRight), sourceStart, destinationStart, length); + ->sum(*source.getChannelByType(ChannelRight), sourceStart, destinationStart, length); return; } // Stereo 4 to 5.1 (4 -> 6) if (numberOfSourceChannels == 4 && numberOfChannels == 6) { getChannelByType(ChannelLeft) - ->sum(source->getChannelByType(ChannelLeft), sourceStart, destinationStart, length); + ->sum(*source.getChannelByType(ChannelLeft), sourceStart, destinationStart, length); getChannelByType(ChannelRight) - ->sum(source->getChannelByType(ChannelRight), sourceStart, destinationStart, length); + ->sum(*source.getChannelByType(ChannelRight), sourceStart, destinationStart, length); getChannelByType(ChannelSurroundLeft) - ->sum(source->getChannelByType(ChannelSurroundLeft), sourceStart, destinationStart, length); + ->sum(*source.getChannelByType(ChannelSurroundLeft), sourceStart, destinationStart, length); getChannelByType(ChannelSurroundRight) - ->sum( - source->getChannelByType(ChannelSurroundRight), sourceStart, destinationStart, length); + ->sum(*source.getChannelByType(ChannelSurroundRight), sourceStart, destinationStart, length); return; } @@ -373,24 +356,19 @@ void AudioBus::sumByUpMixing( } void AudioBus::sumByDownMixing( - const AudioBus *source, + const AudioBus& source, size_t sourceStart, size_t destinationStart, size_t length) { - int numberOfSourceChannels = source->getNumberOfChannels(); + int numberOfSourceChannels = source.getNumberOfChannels(); int numberOfChannels = getNumberOfChannels(); // Stereo to mono (2 -> 1): output += 0.5 * (input.left + input.right). if (numberOfSourceChannels == 2 && numberOfChannels == 1) { - float *sourceLeft = source->getChannelByType(ChannelLeft)->getData(); - float *sourceRight = source->getChannelByType(ChannelRight)->getData(); + auto destinationData = getChannelByType(ChannelMono); - float *destinationData = getChannelByType(ChannelMono)->getData(); - - dsp::multiplyByScalarThenAddToOutput( - sourceLeft + sourceStart, 0.5f, destinationData + destinationStart, length); - dsp::multiplyByScalarThenAddToOutput( - sourceRight + sourceStart, 0.5f, destinationData + destinationStart, length); + destinationData->sum(*source.getChannelByType(ChannelLeft), sourceStart, destinationStart, length, 0.5f); + destinationData->sum(*source.getChannelByType(ChannelRight), sourceStart, destinationStart, length, 0.5f); return; } @@ -398,21 +376,12 @@ void AudioBus::sumByDownMixing( // output += 0.25 * (input.left + input.right + input.surroundLeft + // input.surroundRight) if (numberOfSourceChannels == 4 && numberOfChannels == 1) { - float *sourceLeft = source->getChannelByType(ChannelLeft)->getData(); - float *sourceRight = source->getChannelByType(ChannelRight)->getData(); - float *sourceSurroundLeft = source->getChannelByType(ChannelSurroundLeft)->getData(); - float *sourceSurroundRight = source->getChannelByType(ChannelSurroundRight)->getData(); - - float *destinationData = getChannelByType(ChannelMono)->getData(); - - dsp::multiplyByScalarThenAddToOutput( - sourceLeft + sourceStart, 0.25f, destinationData + destinationStart, length); - dsp::multiplyByScalarThenAddToOutput( - sourceRight + sourceStart, 0.25f, destinationData + destinationStart, length); - dsp::multiplyByScalarThenAddToOutput( - sourceSurroundLeft + sourceStart, 0.25f, destinationData + destinationStart, length); - dsp::multiplyByScalarThenAddToOutput( - sourceSurroundRight + sourceStart, 0.25f, destinationData + destinationStart, length); + auto destinationData = getChannelByType(ChannelMono); + + destinationData->sum(*source.getChannelByType(ChannelLeft), sourceStart, destinationStart, length, 0.25f); + destinationData->sum(*source.getChannelByType(ChannelRight), sourceStart, destinationStart, length, 0.25f); + destinationData->sum(*source.getChannelByType(ChannelSurroundLeft), sourceStart, destinationStart, length, 0.25f); + destinationData->sum(*source.getChannelByType(ChannelSurroundRight), sourceStart, destinationStart, length, 0.25f); return; } @@ -420,28 +389,13 @@ void AudioBus::sumByDownMixing( // output += sqrt(1/2) * (input.left + input.right) + input.center + 0.5 * // (input.surroundLeft + input.surroundRight) if (numberOfSourceChannels == 6 && numberOfChannels == 1) { - float *sourceLeft = source->getChannelByType(ChannelLeft)->getData(); - float *sourceRight = source->getChannelByType(ChannelRight)->getData(); - float *sourceCenter = source->getChannelByType(ChannelCenter)->getData(); - float *sourceSurroundLeft = source->getChannelByType(ChannelSurroundLeft)->getData(); - float *sourceSurroundRight = source->getChannelByType(ChannelSurroundRight)->getData(); - - float *destinationData = getChannelByType(ChannelMono)->getData(); - - dsp::multiplyByScalarThenAddToOutput( - sourceLeft + sourceStart, SQRT_HALF, destinationData + destinationStart, length); - dsp::multiplyByScalarThenAddToOutput( - sourceRight + sourceStart, SQRT_HALF, destinationData + destinationStart, length); - dsp::add( - sourceCenter + sourceStart, - destinationData + destinationStart, - destinationData + destinationStart, - length); - dsp::multiplyByScalarThenAddToOutput( - sourceSurroundLeft + sourceStart, 0.5f, destinationData + destinationStart, length); - dsp::multiplyByScalarThenAddToOutput( - sourceSurroundRight + sourceStart, 0.5f, destinationData + destinationStart, length); + auto destinationData = getChannelByType(ChannelMono); + destinationData->sum(*source.getChannelByType(ChannelLeft), sourceStart, destinationStart, length, SQRT_HALF); + destinationData->sum(*source.getChannelByType(ChannelRight), sourceStart, destinationStart, length, SQRT_HALF); + destinationData->sum(*source.getChannelByType(ChannelCenter), sourceStart, destinationStart, length); + destinationData->sum(*source.getChannelByType(ChannelSurroundLeft), sourceStart, destinationStart, length, 0.5f); + destinationData->sum(*source.getChannelByType(ChannelSurroundRight), sourceStart, destinationStart, length, 0.5f); return; } @@ -449,23 +403,14 @@ void AudioBus::sumByDownMixing( // output.left += 0.5 * (input.left + input.surroundLeft) // output.right += 0.5 * (input.right + input.surroundRight) if (numberOfSourceChannels == 4 && numberOfChannels == 2) { - float *sourceLeft = source->getChannelByType(ChannelLeft)->getData(); - float *sourceRight = source->getChannelByType(ChannelRight)->getData(); - float *sourceSurroundLeft = source->getChannelByType(ChannelSurroundLeft)->getData(); - float *sourceSurroundRight = source->getChannelByType(ChannelSurroundRight)->getData(); - - float *destinationLeft = getChannelByType(ChannelLeft)->getData(); - float *destinationRight = getChannelByType(ChannelRight)->getData(); - - dsp::multiplyByScalarThenAddToOutput( - sourceLeft + sourceStart, 0.5f, destinationLeft + destinationStart, length); - dsp::multiplyByScalarThenAddToOutput( - sourceSurroundLeft + sourceStart, 0.5f, destinationLeft + destinationStart, length); - - dsp::multiplyByScalarThenAddToOutput( - sourceRight + sourceStart, 0.5f, destinationRight + destinationStart, length); - dsp::multiplyByScalarThenAddToOutput( - sourceSurroundRight + sourceStart, 0.5f, destinationRight + destinationStart, length); + auto destinationLeft = getChannelByType(ChannelLeft); + auto destinationRight = getChannelByType(ChannelRight); + + destinationLeft->sum(*source.getChannelByType(ChannelLeft), sourceStart, destinationStart, length, 0.5f); + destinationLeft->sum(*source.getChannelByType(ChannelSurroundLeft), sourceStart, destinationStart, length, 0.5f); + + destinationRight->sum(*source.getChannelByType(ChannelRight), sourceStart, destinationStart, length, 0.5f); + destinationRight->sum(*source.getChannelByType(ChannelSurroundRight), sourceStart, destinationStart, length, 0.5f); return; } @@ -474,34 +419,16 @@ void AudioBus::sumByDownMixing( // output.right += input.right + sqrt(1/2) * (input.center + // input.surroundRight) if (numberOfSourceChannels == 6 && numberOfChannels == 2) { - float *sourceLeft = source->getChannelByType(ChannelLeft)->getData(); - float *sourceRight = source->getChannelByType(ChannelRight)->getData(); - float *sourceCenter = source->getChannelByType(ChannelCenter)->getData(); - float *sourceSurroundLeft = source->getChannelByType(ChannelSurroundLeft)->getData(); - float *sourceSurroundRight = source->getChannelByType(ChannelSurroundRight)->getData(); - - float *destinationLeft = getChannelByType(ChannelLeft)->getData(); - float *destinationRight = getChannelByType(ChannelRight)->getData(); - - dsp::add( - sourceLeft + sourceStart, - destinationLeft + destinationStart, - destinationLeft + destinationStart, - length); - dsp::multiplyByScalarThenAddToOutput( - sourceCenter + sourceStart, SQRT_HALF, destinationLeft + destinationStart, length); - dsp::multiplyByScalarThenAddToOutput( - sourceSurroundLeft + sourceStart, SQRT_HALF, destinationLeft + destinationStart, length); - - dsp::add( - sourceRight + sourceStart, - destinationRight + destinationStart, - destinationRight + destinationStart, - length); - dsp::multiplyByScalarThenAddToOutput( - sourceCenter + sourceStart, SQRT_HALF, destinationRight + destinationStart, length); - dsp::multiplyByScalarThenAddToOutput( - sourceSurroundRight + sourceStart, SQRT_HALF, destinationRight + destinationStart, length); + auto destinationLeft = getChannelByType(ChannelLeft); + auto destinationRight = getChannelByType(ChannelRight); + + destinationLeft->sum(*source.getChannelByType(ChannelLeft), sourceStart, destinationStart, length); + destinationLeft->sum(*source.getChannelByType(ChannelCenter), sourceStart, destinationStart, length, SQRT_HALF); + destinationLeft->sum(*source.getChannelByType(ChannelSurroundLeft), sourceStart, destinationStart, length, SQRT_HALF); + + destinationRight->sum(*source.getChannelByType(ChannelRight), sourceStart, destinationStart, length); + destinationRight->sum(*source.getChannelByType(ChannelCenter), sourceStart, destinationStart, length, SQRT_HALF); + destinationRight->sum(*source.getChannelByType(ChannelSurroundRight), sourceStart, destinationStart, length, SQRT_HALF); return; } @@ -511,43 +438,19 @@ void AudioBus::sumByDownMixing( // output.surroundLeft += input.surroundLeft // output.surroundRight += input.surroundRight if (numberOfSourceChannels == 6 && numberOfChannels == 4) { - float *sourceLeft = source->getChannelByType(ChannelLeft)->getData(); - float *sourceRight = source->getChannelByType(ChannelRight)->getData(); - float *sourceCenter = source->getChannelByType(ChannelCenter)->getData(); - float *sourceSurroundLeft = source->getChannelByType(ChannelSurroundLeft)->getData(); - float *sourceSurroundRight = source->getChannelByType(ChannelSurroundRight)->getData(); - - float *destinationLeft = getChannelByType(ChannelLeft)->getData(); - float *destinationRight = getChannelByType(ChannelRight)->getData(); - float *destinationSurroundLeft = getChannelByType(ChannelSurroundLeft)->getData(); - float *destinationSurroundRight = getChannelByType(ChannelSurroundRight)->getData(); - - dsp::add( - sourceLeft + sourceStart, - destinationLeft + destinationStart, - destinationLeft + destinationStart, - length); - dsp::multiplyByScalarThenAddToOutput( - sourceCenter, SQRT_HALF, destinationLeft + destinationStart, length); - - dsp::add( - sourceRight + sourceStart, - destinationRight + destinationStart, - destinationRight + destinationStart, - length); - dsp::multiplyByScalarThenAddToOutput( - sourceCenter, SQRT_HALF, destinationRight + destinationStart, length); - - dsp::add( - sourceSurroundLeft + sourceStart, - destinationSurroundLeft + destinationStart, - destinationSurroundLeft + destinationStart, - length); - dsp::add( - sourceSurroundRight + sourceStart, - destinationSurroundRight + destinationStart, - destinationSurroundRight + destinationStart, - length); + auto destinationLeft = getChannelByType(ChannelLeft); + auto destinationRight = getChannelByType(ChannelRight); + auto destinationSurroundLeft = getChannelByType(ChannelSurroundLeft); + auto destinationSurroundRight = getChannelByType(ChannelSurroundRight); + + destinationLeft->sum(*source.getChannelByType(ChannelLeft), sourceStart, destinationStart, length); + destinationLeft->sum(*source.getChannelByType(ChannelCenter), sourceStart, destinationStart, length, SQRT_HALF); + + destinationRight->sum(*source.getChannelByType(ChannelRight), sourceStart, destinationStart, length); + destinationRight->sum(*source.getChannelByType(ChannelCenter), sourceStart, destinationStart, length, SQRT_HALF); + + destinationSurroundLeft->sum(*source.getChannelByType(ChannelSurroundLeft), sourceStart, destinationStart, length); + destinationSurroundRight->sum(*source.getChannelByType(ChannelSurroundRight), sourceStart, destinationStart, length); return; } diff --git a/packages/react-native-audio-api/common/cpp/audioapi/utils/AudioBus.h b/packages/react-native-audio-api/common/cpp/audioapi/utils/AudioBus.h index ebcf34cf7..fa3d77a90 100644 --- a/packages/react-native-audio-api/common/cpp/audioapi/utils/AudioBus.h +++ b/packages/react-native-audio-api/common/cpp/audioapi/utils/AudioBus.h @@ -9,7 +9,6 @@ namespace audioapi { -class BaseAudioContext; class AudioArray; class AudioBus { @@ -29,62 +28,67 @@ class AudioBus { AudioBus(const AudioBus &other); AudioBus(AudioBus &&other) noexcept; AudioBus &operator=(const AudioBus &other); + AudioBus &operator=(AudioBus &&other) noexcept; + ~AudioBus() = default; + + [[nodiscard]] inline int getNumberOfChannels() const noexcept { + return numberOfChannels_; + } + [[nodiscard]] inline float getSampleRate() const noexcept { + return sampleRate_; + } + [[nodiscard]] inline size_t getSize() const noexcept { + return size_; + } - ~AudioBus(); - - [[nodiscard]] int getNumberOfChannels() const; - [[nodiscard]] float getSampleRate() const; - [[nodiscard]] size_t getSize() const; [[nodiscard]] AudioArray *getChannel(int index) const; [[nodiscard]] AudioArray *getChannelByType(int channelType) const; [[nodiscard]] std::shared_ptr getSharedChannel(int index) const; - AudioArray &operator[](size_t index); - const AudioArray &operator[](size_t index) const; - - void normalize(); - void scale(float value); - [[nodiscard]] float maxAbsValue() const; + AudioArray &operator[](size_t index) { + return *channels_[index]; + } + const AudioArray &operator[](size_t index) const { + return *channels_[index]; + } void zero(); void zero(size_t start, size_t length); void sum( - const AudioBus *source, - ChannelInterpretation interpretation = ChannelInterpretation::SPEAKERS); - void sum( - const AudioBus *source, - size_t start, - size_t length, + const AudioBus &source, ChannelInterpretation interpretation = ChannelInterpretation::SPEAKERS); void sum( - const AudioBus *source, + const AudioBus &source, size_t sourceStart, size_t destinationStart, size_t length, ChannelInterpretation interpretation = ChannelInterpretation::SPEAKERS); - void copy(const AudioBus *source); - void copy(const AudioBus *source, size_t start, size_t length); - void copy(const AudioBus *source, size_t sourceStart, size_t destinationStart, size_t length); + void copy(const AudioBus &source); + void copy(const AudioBus &source, size_t sourceStart, size_t destinationStart, size_t length); + + void normalize(); + void scale(float value); + [[nodiscard]] float maxAbsValue() const; private: std::vector> channels_; - int numberOfChannels_; - float sampleRate_; - size_t size_; + int numberOfChannels_ = 0; + float sampleRate_ = 0.0f; + size_t size_ = 0; void createChannels(); void discreteSum( - const AudioBus *source, + const AudioBus &source, size_t sourceStart, size_t destinationStart, size_t length) const; void - sumByUpMixing(const AudioBus *source, size_t sourceStart, size_t destinationStart, size_t length); + sumByUpMixing(const AudioBus &source, size_t sourceStart, size_t destinationStart, size_t length); void sumByDownMixing( - const AudioBus *source, + const AudioBus &source, size_t sourceStart, size_t destinationStart, size_t length); From f32a9f7f1c4b9c4f47f5203099685807d9b04b32 Mon Sep 17 00:00:00 2001 From: maciejmakowski2003 Date: Mon, 2 Feb 2026 16:30:16 +0100 Subject: [PATCH 03/30] chore: added docs for both utils --- .../common/cpp/audioapi/utils/AudioArray.h | 21 +++++++++++++++++++ .../common/cpp/audioapi/utils/AudioBus.h | 18 ++++++++++++++-- 2 files changed, 37 insertions(+), 2 deletions(-) diff --git a/packages/react-native-audio-api/common/cpp/audioapi/utils/AudioArray.h b/packages/react-native-audio-api/common/cpp/audioapi/utils/AudioArray.h index bf6743bad..11f8b7b58 100644 --- a/packages/react-native-audio-api/common/cpp/audioapi/utils/AudioArray.h +++ b/packages/react-native-audio-api/common/cpp/audioapi/utils/AudioArray.h @@ -7,9 +7,15 @@ namespace audioapi { +/// @brief AudioArray is a simple wrapper around a float array for audio data manipulation. +/// It provides various utility functions for audio processing. +/// @note AudioArray manages its own memory and provides copy and move semantics. +/// @note Not thread-safe. class AudioArray { public: explicit AudioArray(size_t size); + + /// @brief Constructs an AudioArray from existing data. /// @note The data is copied, so it does not take ownership of the pointer AudioArray(const float *data, size_t size); ~AudioArray() = default; @@ -49,7 +55,19 @@ class AudioArray { void zero() noexcept; void zero(size_t start, size_t length) noexcept; + /// @brief Sums the source AudioArray into this AudioArray with an optional gain. + /// @param source The source AudioArray to sum from. + /// @param gain The gain to apply to the source before summing. Default is 1.0f. + /// @note Assumes that source and this AudioArray are not the same. void sum(const AudioArray &source, float gain = 1.0f); + + /// @brief Sums the source AudioArray into this AudioArray with an optional gain. + /// @param source The source AudioArray to sum from. + /// @param sourceStart The starting index in the source AudioArray. + /// @param destinationStart The starting index in this AudioArray. + /// @param length The number of samples to sum. + /// @param gain The gain to apply to the source before summing. Default is 1.0f. + /// @note Assumes that source and this AudioArray are not the same. void sum( const AudioArray &source, size_t sourceStart, @@ -57,6 +75,9 @@ class AudioArray { size_t length, float gain = 1.0f); + /// @brief Multiplies this AudioArray by the source AudioArray element-wise. + /// @param source The source AudioArray to multiply with. + /// @note Assumes that source and this AudioArray are not the same. void multiply(const AudioArray &source); void multiplyByScalar(float value); diff --git a/packages/react-native-audio-api/common/cpp/audioapi/utils/AudioBus.h b/packages/react-native-audio-api/common/cpp/audioapi/utils/AudioBus.h index fa3d77a90..3e56682ce 100644 --- a/packages/react-native-audio-api/common/cpp/audioapi/utils/AudioBus.h +++ b/packages/react-native-audio-api/common/cpp/audioapi/utils/AudioBus.h @@ -41,8 +41,19 @@ class AudioBus { return size_; } + /// @brief Get the AudioArray for a specific channel index. + /// @param index The channel index. + /// @return Pointer to the AudioArray for the specified channel - not owning. [[nodiscard]] AudioArray *getChannel(int index) const; + + /// @brief Get the AudioArray for a specific channel type. + /// @param channelType The channel type (e.g., ChannelLeft, ChannelRight). + /// @return Pointer to the AudioArray for the specified channel type - not owning. [[nodiscard]] AudioArray *getChannelByType(int channelType) const; + + /// @brief Get a shared pointer to the AudioArray for a specific channel index. + /// @param index The channel index. + /// @return Shared pointer to the AudioArray for the specified channel - owning. [[nodiscard]] std::shared_ptr getSharedChannel(int index) const; AudioArray &operator[](size_t index) { @@ -85,8 +96,11 @@ class AudioBus { size_t sourceStart, size_t destinationStart, size_t length) const; - void - sumByUpMixing(const AudioBus &source, size_t sourceStart, size_t destinationStart, size_t length); + void sumByUpMixing( + const AudioBus &source, + size_t sourceStart, + size_t destinationStart, + size_t length); void sumByDownMixing( const AudioBus &source, size_t sourceStart, From 91503c4ca5d57bc9e16b01e1e05938702831cea0 Mon Sep 17 00:00:00 2001 From: maciejmakowski2003 Date: Mon, 2 Feb 2026 16:30:33 +0100 Subject: [PATCH 04/30] ci: lint --- .../common/cpp/audioapi/utils/AudioBus.h | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/packages/react-native-audio-api/common/cpp/audioapi/utils/AudioBus.h b/packages/react-native-audio-api/common/cpp/audioapi/utils/AudioBus.h index 3e56682ce..d7c2550df 100644 --- a/packages/react-native-audio-api/common/cpp/audioapi/utils/AudioBus.h +++ b/packages/react-native-audio-api/common/cpp/audioapi/utils/AudioBus.h @@ -96,11 +96,8 @@ class AudioBus { size_t sourceStart, size_t destinationStart, size_t length) const; - void sumByUpMixing( - const AudioBus &source, - size_t sourceStart, - size_t destinationStart, - size_t length); + void + sumByUpMixing(const AudioBus &source, size_t sourceStart, size_t destinationStart, size_t length); void sumByDownMixing( const AudioBus &source, size_t sourceStart, From 456b1395db7a90fb2f71260507eb3720a9f15d4a Mon Sep 17 00:00:00 2001 From: maciejmakowski2003 Date: Mon, 2 Feb 2026 17:48:33 +0100 Subject: [PATCH 05/30] refactor: audio array and fft --- .../common/cpp/audioapi/dsp/FFT.h | 11 ++++---- .../common/cpp/audioapi/utils/AudioArray.cpp | 14 ++++------ .../common/cpp/audioapi/utils/AudioArray.h | 27 +++++++++++++++++-- 3 files changed, 36 insertions(+), 16 deletions(-) diff --git a/packages/react-native-audio-api/common/cpp/audioapi/dsp/FFT.h b/packages/react-native-audio-api/common/cpp/audioapi/dsp/FFT.h index db9caf47c..751646ec4 100644 --- a/packages/react-native-audio-api/common/cpp/audioapi/dsp/FFT.h +++ b/packages/react-native-audio-api/common/cpp/audioapi/dsp/FFT.h @@ -2,6 +2,7 @@ #include #include +#include #include #include @@ -17,9 +18,9 @@ class FFT { ~FFT(); template - void doFFT(float *in, std::vector, Allocator> &out) { + void doFFT(const AudioArray& in, std::vector, Allocator> &out) { pffft_transform_ordered( - pffftSetup_, in, reinterpret_cast(&out[0]), work_, PFFFT_FORWARD); + pffftSetup_, in.begin(), reinterpret_cast(&out[0]), work_, PFFFT_FORWARD); // this is a possible place for bugs and mistakes // due to pffft implementation and how it stores results // keep this information in mind @@ -28,11 +29,11 @@ class FFT { } template - void doInverseFFT(std::vector, Allocator> &in, float *out) { + void doInverseFFT(std::vector, Allocator> &in, AudioArray& out) { pffft_transform_ordered( - pffftSetup_, reinterpret_cast(&in[0]), out, work_, PFFFT_BACKWARD); + pffftSetup_, reinterpret_cast(&in[0]), out.begin(), work_, PFFFT_BACKWARD); - dsp::multiplyByScalar(out, 1.0f / static_cast(size_), out, size_); + out.scale(1.0f / static_cast(size_)); } private: diff --git a/packages/react-native-audio-api/common/cpp/audioapi/utils/AudioArray.cpp b/packages/react-native-audio-api/common/cpp/audioapi/utils/AudioArray.cpp index bc29aaf59..b3cb6aa9b 100644 --- a/packages/react-native-audio-api/common/cpp/audioapi/utils/AudioArray.cpp +++ b/packages/react-native-audio-api/common/cpp/audioapi/utils/AudioArray.cpp @@ -108,6 +108,10 @@ void AudioArray::sum( } void AudioArray::multiply(const AudioArray &source) { + multiply(source, size_); +} + +void AudioArray::multiply(const audioapi::AudioArray &source, size_t length) { if (data_ == nullptr || source.data_ == nullptr) { return; } @@ -115,15 +119,7 @@ void AudioArray::multiply(const AudioArray &source) { float* __restrict dest = data_.get(); const float* __restrict src = source.data_.get(); - dsp::multiply(src, dest, dest, size_); -} - -void AudioArray::multiplyByScalar(float value) { - if (data_ == nullptr) { - return; - } - - dsp::multiplyByScalar(data_.get(), value, data_.get(), size_); + dsp::multiply(src, dest, dest, length); } void AudioArray::copy(const AudioArray &source) { diff --git a/packages/react-native-audio-api/common/cpp/audioapi/utils/AudioArray.h b/packages/react-native-audio-api/common/cpp/audioapi/utils/AudioArray.h index 11f8b7b58..f071172d3 100644 --- a/packages/react-native-audio-api/common/cpp/audioapi/utils/AudioArray.h +++ b/packages/react-native-audio-api/common/cpp/audioapi/utils/AudioArray.h @@ -4,6 +4,7 @@ #include #include #include +#include namespace audioapi { @@ -50,6 +51,21 @@ class AudioArray { return data_.get() + size_; } + [[nodiscard]] inline std::span span() noexcept { + return {data_.get(), size_}; + } + + [[nodiscard]] inline std::span span() const noexcept { + return {data_.get(), size_}; + } + + [[nodiscard]] inline std::span subSpan(size_t length, size_t offset = 0) { + if (offset + length > size_) { + throw std::out_of_range("AudioArray::subSpan - offset + length exceeds array size"); + } + return {data_.get() + offset, length}; + } + void resize(size_t size); void zero() noexcept; @@ -79,7 +95,14 @@ class AudioArray { /// @param source The source AudioArray to multiply with. /// @note Assumes that source and this AudioArray are not the same. void multiply(const AudioArray &source); - void multiplyByScalar(float value); + + /// @brief Multiplies this AudioArray by the source AudioArray element-wise. + /// @param source The source AudioArray to multiply with. + /// @param length The number of samples to multiply. + /// @note Assumes that source and this AudioArray are not the same. + void multiply( + const AudioArray &source, + size_t length); void copy(const AudioArray &source); void copy(const AudioArray &source, size_t sourceStart, size_t destinationStart, size_t length); @@ -90,7 +113,7 @@ class AudioArray { [[nodiscard]] float getMaxAbsValue() const; [[nodiscard]] float computeConvolution(const AudioArray &kernel, size_t startIndex = 0) const; - private: + protected: std::unique_ptr data_ = nullptr; size_t size_ = 0; }; From 8f439a6c88fef7970b3eb9abf51ed39b364cc517 Mon Sep 17 00:00:00 2001 From: maciejmakowski2003 Date: Tue, 3 Feb 2026 07:31:49 +0100 Subject: [PATCH 06/30] chore: requested changes --- .../common/cpp/audioapi/dsp/FFT.h | 4 ++-- .../common/cpp/audioapi/utils/AudioArray.h | 12 +++++------- .../common/cpp/audioapi/utils/AudioBus.h | 4 ++-- 3 files changed, 9 insertions(+), 11 deletions(-) diff --git a/packages/react-native-audio-api/common/cpp/audioapi/dsp/FFT.h b/packages/react-native-audio-api/common/cpp/audioapi/dsp/FFT.h index 751646ec4..c7308699f 100644 --- a/packages/react-native-audio-api/common/cpp/audioapi/dsp/FFT.h +++ b/packages/react-native-audio-api/common/cpp/audioapi/dsp/FFT.h @@ -18,7 +18,7 @@ class FFT { ~FFT(); template - void doFFT(const AudioArray& in, std::vector, Allocator> &out) { + void doFFT(const AudioArray &in, std::vector, Allocator> &out) { pffft_transform_ordered( pffftSetup_, in.begin(), reinterpret_cast(&out[0]), work_, PFFFT_FORWARD); // this is a possible place for bugs and mistakes @@ -29,7 +29,7 @@ class FFT { } template - void doInverseFFT(std::vector, Allocator> &in, AudioArray& out) { + void doInverseFFT(std::vector, Allocator> &in, AudioArray &out) { pffft_transform_ordered( pffftSetup_, reinterpret_cast(&in[0]), out.begin(), work_, PFFFT_BACKWARD); diff --git a/packages/react-native-audio-api/common/cpp/audioapi/utils/AudioArray.h b/packages/react-native-audio-api/common/cpp/audioapi/utils/AudioArray.h index f071172d3..e7f309ecd 100644 --- a/packages/react-native-audio-api/common/cpp/audioapi/utils/AudioArray.h +++ b/packages/react-native-audio-api/common/cpp/audioapi/utils/AudioArray.h @@ -26,14 +26,14 @@ class AudioArray { AudioArray &operator=(const AudioArray &other); AudioArray &operator=(AudioArray &&other) noexcept; - [[nodiscard]] inline size_t getSize() const { + [[nodiscard]] inline size_t getSize() const noexcept { return size_; } - inline float &operator[](size_t index) { + inline float &operator[](size_t index) noexcept { return data_[index]; } - inline const float &operator[](size_t index) const { + inline const float &operator[](size_t index) const noexcept { return data_[index]; } @@ -61,7 +61,7 @@ class AudioArray { [[nodiscard]] inline std::span subSpan(size_t length, size_t offset = 0) { if (offset + length > size_) { - throw std::out_of_range("AudioArray::subSpan - offset + length exceeds array size"); + throw std::out_of_range("AudioArray::subSpan - offset + length exceeds array size"); } return {data_.get() + offset, length}; } @@ -100,9 +100,7 @@ class AudioArray { /// @param source The source AudioArray to multiply with. /// @param length The number of samples to multiply. /// @note Assumes that source and this AudioArray are not the same. - void multiply( - const AudioArray &source, - size_t length); + void multiply(const AudioArray &source, size_t length); void copy(const AudioArray &source); void copy(const AudioArray &source, size_t sourceStart, size_t destinationStart, size_t length); diff --git a/packages/react-native-audio-api/common/cpp/audioapi/utils/AudioBus.h b/packages/react-native-audio-api/common/cpp/audioapi/utils/AudioBus.h index d7c2550df..243c900a8 100644 --- a/packages/react-native-audio-api/common/cpp/audioapi/utils/AudioBus.h +++ b/packages/react-native-audio-api/common/cpp/audioapi/utils/AudioBus.h @@ -51,9 +51,9 @@ class AudioBus { /// @return Pointer to the AudioArray for the specified channel type - not owning. [[nodiscard]] AudioArray *getChannelByType(int channelType) const; - /// @brief Get a shared pointer to the AudioArray for a specific channel index. + /// @brief Get a copy of shared pointer to the AudioArray for a specific channel index. /// @param index The channel index. - /// @return Shared pointer to the AudioArray for the specified channel - owning. + /// @return Copy of shared pointer to the AudioArray for the specified channel [[nodiscard]] std::shared_ptr getSharedChannel(int index) const; AudioArray &operator[](size_t index) { From e74317fe7e3e4bba5f240d271198d271dd74082d Mon Sep 17 00:00:00 2001 From: maciejmakowski2003 Date: Tue, 3 Feb 2026 09:14:29 +0100 Subject: [PATCH 07/30] refactor: next part for audio bus and audio array --- .../common/cpp/audioapi/utils/AudioArray.cpp | 15 +++++++++++++++ .../common/cpp/audioapi/utils/AudioArray.h | 8 ++++++++ .../common/cpp/audioapi/utils/AudioBus.cpp | 13 +++++++++++++ .../common/cpp/audioapi/utils/AudioBus.h | 1 + 4 files changed, 37 insertions(+) diff --git a/packages/react-native-audio-api/common/cpp/audioapi/utils/AudioArray.cpp b/packages/react-native-audio-api/common/cpp/audioapi/utils/AudioArray.cpp index b3cb6aa9b..ef738c773 100644 --- a/packages/react-native-audio-api/common/cpp/audioapi/utils/AudioArray.cpp +++ b/packages/react-native-audio-api/common/cpp/audioapi/utils/AudioArray.cpp @@ -138,6 +138,21 @@ void AudioArray::copy( memcpy(data_.get() + destinationStart, source.data_.get() + sourceStart, length * sizeof(float)); } +void AudioArray::copyReverse(const audioapi::AudioArray &source, size_t sourceStart, + size_t destinationStart, size_t length) { + if (length == 0 || data_ == nullptr || source.data_ == nullptr) { + return; + } + + auto dstView = this->subSpan(length, destinationStart); + auto srcView = source.span(); + const float* __restrict srcPtr = &srcView[sourceStart]; + + for (size_t i = 0; i < length; ++i) { + dstView[i] = srcPtr[-static_cast(i)]; + } +} + void AudioArray::reverse() { if (data_ == nullptr && size_ > 1) { return; diff --git a/packages/react-native-audio-api/common/cpp/audioapi/utils/AudioArray.h b/packages/react-native-audio-api/common/cpp/audioapi/utils/AudioArray.h index e7f309ecd..a456b9dbe 100644 --- a/packages/react-native-audio-api/common/cpp/audioapi/utils/AudioArray.h +++ b/packages/react-native-audio-api/common/cpp/audioapi/utils/AudioArray.h @@ -105,6 +105,14 @@ class AudioArray { void copy(const AudioArray &source); void copy(const AudioArray &source, size_t sourceStart, size_t destinationStart, size_t length); + /// @brief Copies data from the source AudioArray in reverse order into this AudioArray. + /// @param source The source AudioArray to copy from. + /// @param sourceStart The starting index in the source AudioArray. + /// @param destinationStart The starting index in this AudioArray. + /// @param length The number of samples to copy. + /// @note Assumes that source and this AudioArray are not the same. + void copyReverse(const AudioArray &source, size_t sourceStart, size_t destinationStart, size_t length); + void reverse(); void normalize(); void scale(float value); diff --git a/packages/react-native-audio-api/common/cpp/audioapi/utils/AudioBus.cpp b/packages/react-native-audio-api/common/cpp/audioapi/utils/AudioBus.cpp index ee14402fc..99c9e7327 100644 --- a/packages/react-native-audio-api/common/cpp/audioapi/utils/AudioBus.cpp +++ b/packages/react-native-audio-api/common/cpp/audioapi/utils/AudioBus.cpp @@ -34,6 +34,19 @@ AudioBus::AudioBus(const AudioBus &other): numberOfChannels_(other.numberOfChann } } +AudioBus::AudioBus(std::vector> channels, float sampleRate) + : channels_(std::move(channels)), + sampleRate_(sampleRate) { + + numberOfChannels_ = static_cast(channels_.size()); + + if (numberOfChannels_ > 0 && channels_[0] != nullptr) { + size_ = channels_[0]->getSize(); + } else { + size_ = 0; + } +} + AudioBus::AudioBus(audioapi::AudioBus &&other) noexcept : channels_(std::move(other.channels_)), numberOfChannels_(other.numberOfChannels_), diff --git a/packages/react-native-audio-api/common/cpp/audioapi/utils/AudioBus.h b/packages/react-native-audio-api/common/cpp/audioapi/utils/AudioBus.h index 243c900a8..497f04450 100644 --- a/packages/react-native-audio-api/common/cpp/audioapi/utils/AudioBus.h +++ b/packages/react-native-audio-api/common/cpp/audioapi/utils/AudioBus.h @@ -25,6 +25,7 @@ class AudioBus { explicit AudioBus() = default; explicit AudioBus(size_t size, int numberOfChannels, float sampleRate); + AudioBus(std::vector> channels, float sampleRate); AudioBus(const AudioBus &other); AudioBus(AudioBus &&other) noexcept; AudioBus &operator=(const AudioBus &other); From d1dede6569966e041217be6c83a9f2da045237e7 Mon Sep 17 00:00:00 2001 From: maciejmakowski2003 Date: Tue, 3 Feb 2026 11:36:26 +0100 Subject: [PATCH 08/30] refactor: wip --- .../docs/guides/create-your-own-effect.mdx | 8 +- .../basic/shared/MyProcessorNode.cpp | 11 +- .../templates/basic/shared/MyProcessorNode.h | 8 +- .../android/core/AndroidAudioRecorder.cpp | 7 +- .../android/core/AndroidAudioRecorder.h | 27 +- .../cpp/audioapi/android/core/AudioPlayer.cpp | 8 +- .../cpp/audioapi/android/core/AudioPlayer.h | 17 +- .../core/utils/AndroidRecorderCallback.cpp | 6 +- .../core/utils/AndroidRecorderCallback.h | 10 +- .../android/core/utils/AudioDecoder.cpp | 16 +- .../HostObjects/AudioParamHostObject.cpp | 4 +- .../effects/WaveShaperNodeHostObject.cpp | 9 +- .../inputs/AudioRecorderHostObject.cpp | 4 +- .../sources/AudioBufferHostObject.cpp | 13 +- .../sources/AudioBufferHostObject.h | 4 +- .../audioapi/HostObjects/utils/NodeOptions.h | 5 +- .../HostObjects/utils/NodeOptionsParser.h | 2 +- .../common/cpp/audioapi/core/AudioContext.cpp | 6 +- .../common/cpp/audioapi/core/AudioContext.h | 2 +- .../common/cpp/audioapi/core/AudioNode.cpp | 44 +-- .../common/cpp/audioapi/core/AudioNode.h | 21 +- .../common/cpp/audioapi/core/AudioParam.cpp | 28 +- .../common/cpp/audioapi/core/AudioParam.h | 20 +- .../cpp/audioapi/core/BaseAudioContext.cpp | 15 +- .../cpp/audioapi/core/BaseAudioContext.h | 2 +- .../cpp/audioapi/core/OfflineAudioContext.cpp | 20 +- .../cpp/audioapi/core/OfflineAudioContext.h | 2 +- .../audioapi/core/analysis/AnalyserNode.cpp | 44 +-- .../cpp/audioapi/core/analysis/AnalyserNode.h | 8 +- .../destinations/AudioDestinationNode.cpp | 8 +- .../core/destinations/AudioDestinationNode.h | 7 +- .../core/effects/BiquadFilterNode.cpp | 31 +- .../audioapi/core/effects/BiquadFilterNode.h | 6 +- .../audioapi/core/effects/ConvolverNode.cpp | 64 ++-- .../cpp/audioapi/core/effects/ConvolverNode.h | 16 +- .../cpp/audioapi/core/effects/DelayNode.cpp | 23 +- .../cpp/audioapi/core/effects/DelayNode.h | 10 +- .../cpp/audioapi/core/effects/GainNode.cpp | 14 +- .../cpp/audioapi/core/effects/GainNode.h | 6 +- .../audioapi/core/effects/IIRFilterNode.cpp | 37 ++- .../cpp/audioapi/core/effects/IIRFilterNode.h | 4 +- .../audioapi/core/effects/PeriodicWave.cpp | 52 ++-- .../cpp/audioapi/core/effects/PeriodicWave.h | 23 +- .../core/effects/StereoPannerNode.cpp | 57 ++-- .../audioapi/core/effects/StereoPannerNode.h | 6 +- .../audioapi/core/effects/WaveShaperNode.cpp | 16 +- .../audioapi/core/effects/WaveShaperNode.h | 14 +- .../cpp/audioapi/core/effects/WorkletNode.cpp | 18 +- .../cpp/audioapi/core/effects/WorkletNode.h | 16 +- .../core/effects/WorkletProcessingNode.cpp | 32 +- .../core/effects/WorkletProcessingNode.h | 14 +- .../cpp/audioapi/core/inputs/AudioRecorder.h | 2 +- .../cpp/audioapi/core/sources/AudioBuffer.cpp | 61 ---- .../cpp/audioapi/core/sources/AudioBuffer.h | 45 --- .../sources/AudioBufferBaseSourceNode.cpp | 10 +- .../core/sources/AudioBufferBaseSourceNode.h | 12 +- .../sources/AudioBufferQueueSourceNode.cpp | 34 +-- .../core/sources/AudioBufferQueueSourceNode.h | 12 +- .../core/sources/AudioBufferSourceNode.cpp | 46 ++- .../core/sources/AudioBufferSourceNode.h | 14 +- .../core/sources/AudioScheduledSourceNode.cpp | 11 +- .../core/sources/AudioScheduledSourceNode.h | 4 +- .../core/sources/ConstantSourceNode.cpp | 21 +- .../core/sources/ConstantSourceNode.h | 6 +- .../audioapi/core/sources/OscillatorNode.cpp | 50 +-- .../audioapi/core/sources/OscillatorNode.h | 6 +- .../core/sources/RecorderAdapterNode.cpp | 16 +- .../core/sources/RecorderAdapterNode.h | 14 +- .../audioapi/core/sources/StreamerNode.cpp | 40 ++- .../cpp/audioapi/core/sources/StreamerNode.h | 20 +- .../core/sources/WorkletSourceNode.cpp | 31 +- .../audioapi/core/sources/WorkletSourceNode.h | 14 +- .../audioapi/core/utils/AudioGraphManager.cpp | 6 +- .../audioapi/core/utils/AudioGraphManager.h | 4 +- .../core/utils/AudioParamEventQueue.h | 2 +- .../core/utils/AudioRecorderCallback.cpp | 18 +- .../core/utils/AudioRecorderCallback.h | 6 +- .../audioapi/core/utils/AudioStretcher.cpp | 17 +- .../cpp/audioapi/core/utils/AudioStretcher.h | 2 +- .../audioapi/core/utils/ParamChangeEvent.cpp | 20 -- ...aramChangeEvent.h => ParamChangeEvent.hpp} | 19 +- .../common/cpp/audioapi/dsp/AudioUtils.cpp | 27 -- .../common/cpp/audioapi/dsp/AudioUtils.h | 16 - .../common/cpp/audioapi/dsp/AudioUtils.hpp | 38 +++ .../common/cpp/audioapi/dsp/Convolver.cpp | 35 ++- .../common/cpp/audioapi/dsp/Convolver.h | 8 +- .../common/cpp/audioapi/dsp/Resampler.cpp | 74 +---- .../common/cpp/audioapi/dsp/Resampler.h | 18 +- .../common/cpp/audioapi/dsp/VectorMath.cpp | 2 +- .../common/cpp/audioapi/dsp/WaveShaper.cpp | 39 ++- .../common/cpp/audioapi/dsp/WaveShaper.h | 10 +- .../common/cpp/audioapi/dsp/Windows.cpp | 75 ----- .../common/cpp/audioapi/dsp/Windows.h | 96 ------ .../common/cpp/audioapi/dsp/Windows.hpp | 196 ++++++++++++ .../cpp/audioapi/jsi/AudioArrayBuffer.cpp | 13 - .../cpp/audioapi/jsi/AudioArrayBuffer.h | 34 --- .../audioapi/libs/ffmpeg/FFmpegDecoding.cpp | 84 ++--- .../cpp/audioapi/libs/ffmpeg/FFmpegDecoding.h | 12 +- .../libs/signalsmith-stretch/fft-pffft.h | 2 + .../common/cpp/audioapi/utils/AudioArray.cpp | 23 +- .../common/cpp/audioapi/utils/AudioArray.h | 6 +- .../cpp/audioapi/utils/AudioArrayBuffer.hpp | 48 +++ .../utils/{AudioBus.cpp => AudioBuffer.cpp} | 287 ++++++++++-------- .../utils/{AudioBus.h => AudioBuffer.h} | 49 +-- .../cpp/audioapi/utils/CircularAudioArray.cpp | 29 +- .../cpp/audioapi/utils/CircularAudioArray.h | 7 +- .../utils/CircularOverflowableAudioArray.cpp | 16 +- .../utils/CircularOverflowableAudioArray.h | 4 +- .../common/cpp/test/src/AudioParamTest.cpp | 11 +- .../cpp/test/src/AudioScheduledSourceTest.cpp | 8 +- .../cpp/test/src/ConstantSourceTest.cpp | 8 +- .../common/cpp/test/src/DelayTest.cpp | 21 +- .../common/cpp/test/src/GainTest.cpp | 19 +- .../common/cpp/test/src/StereoPannerTest.cpp | 34 +-- .../src/core/effects/WaveShaperNodeTest.cpp | 18 +- .../common/cpp/test/src/dsp/ResamplerTest.cpp | 15 +- .../ios/audioapi/ios/core/IOSAudioPlayer.h | 8 +- .../ios/audioapi/ios/core/IOSAudioPlayer.mm | 6 +- .../ios/audioapi/ios/core/IOSAudioRecorder.mm | 2 +- .../audioapi/ios/core/utils/AudioDecoder.mm | 9 +- .../ios/core/utils/IOSRecorderCallback.h | 2 +- .../ios/core/utils/IOSRecorderCallback.mm | 2 +- 122 files changed, 1357 insertions(+), 1462 deletions(-) delete mode 100644 packages/react-native-audio-api/common/cpp/audioapi/core/sources/AudioBuffer.cpp delete mode 100644 packages/react-native-audio-api/common/cpp/audioapi/core/sources/AudioBuffer.h delete mode 100644 packages/react-native-audio-api/common/cpp/audioapi/core/utils/ParamChangeEvent.cpp rename packages/react-native-audio-api/common/cpp/audioapi/core/utils/{ParamChangeEvent.h => ParamChangeEvent.hpp} (84%) delete mode 100644 packages/react-native-audio-api/common/cpp/audioapi/dsp/AudioUtils.cpp delete mode 100644 packages/react-native-audio-api/common/cpp/audioapi/dsp/AudioUtils.h create mode 100644 packages/react-native-audio-api/common/cpp/audioapi/dsp/AudioUtils.hpp delete mode 100644 packages/react-native-audio-api/common/cpp/audioapi/dsp/Windows.cpp delete mode 100644 packages/react-native-audio-api/common/cpp/audioapi/dsp/Windows.h create mode 100644 packages/react-native-audio-api/common/cpp/audioapi/dsp/Windows.hpp delete mode 100644 packages/react-native-audio-api/common/cpp/audioapi/jsi/AudioArrayBuffer.cpp delete mode 100644 packages/react-native-audio-api/common/cpp/audioapi/jsi/AudioArrayBuffer.h create mode 100644 packages/react-native-audio-api/common/cpp/audioapi/utils/AudioArrayBuffer.hpp rename packages/react-native-audio-api/common/cpp/audioapi/utils/{AudioBus.cpp => AudioBuffer.cpp} (58%) rename packages/react-native-audio-api/common/cpp/audioapi/utils/{AudioBus.h => AudioBuffer.h} (65%) diff --git a/packages/audiodocs/docs/guides/create-your-own-effect.mdx b/packages/audiodocs/docs/guides/create-your-own-effect.mdx index 9eb8ec8a2..85baaddf5 100644 --- a/packages/audiodocs/docs/guides/create-your-own-effect.mdx +++ b/packages/audiodocs/docs/guides/create-your-own-effect.mdx @@ -45,14 +45,14 @@ For the sake of a simplicity, we will use value as a raw `double` type, not wrap #include namespace audioapi { - class AudioBus; + class AudioBuffer; class MyProcessorNode : public AudioNode { public: explicit MyProcessorNode(BaseAudioContext *context); protected: - void processNode(const std::shared_ptr &bus, + void processNode(const std::shared_ptr &bus, int framesToProcess) override; // highlight-start @@ -69,7 +69,7 @@ namespace audioapi { ```cpp #include "MyProcessorNode.h" -#include +#include #include namespace audioapi { @@ -79,7 +79,7 @@ namespace audioapi { isInitialized_ = true; } - void MyProcessorNode::processNode(const std::shared_ptr &bus, + void MyProcessorNode::processNode(const std::shared_ptr &bus, int framesToProcess) { // highlight-start for (int channel = 0; channel < bus->getNumberOfChannels(); ++channel) { diff --git a/packages/custom-node-generator/templates/basic/shared/MyProcessorNode.cpp b/packages/custom-node-generator/templates/basic/shared/MyProcessorNode.cpp index 3aa07f407..b6c9c60cd 100644 --- a/packages/custom-node-generator/templates/basic/shared/MyProcessorNode.cpp +++ b/packages/custom-node-generator/templates/basic/shared/MyProcessorNode.cpp @@ -1,14 +1,15 @@ #include "MyProcessorNode.h" -#include +#include namespace audioapi { MyProcessorNode::MyProcessorNode(BaseAudioContext *context) : AudioNode(context) { - isInitialized_ = true; + isInitialized_ = true; } -std::shared_ptr MyProcessorNode::processNode(const std::shared_ptr &bus, - int framesToProcess) { - // put your processing logic here +std::shared_ptr +MyProcessorNode::processNode(const std::shared_ptr &bus, + int framesToProcess) { + // put your processing logic here } } // namespace audioapi diff --git a/packages/custom-node-generator/templates/basic/shared/MyProcessorNode.h b/packages/custom-node-generator/templates/basic/shared/MyProcessorNode.h index e065ff359..58cc43cc6 100644 --- a/packages/custom-node-generator/templates/basic/shared/MyProcessorNode.h +++ b/packages/custom-node-generator/templates/basic/shared/MyProcessorNode.h @@ -2,15 +2,15 @@ #include namespace audioapi { -class AudioBus; +class AudioBuffer; class MyProcessorNode : public AudioNode { public: explicit MyProcessorNode(BaseAudioContext *context); protected: - std::shared_ptr processNode(const std::shared_ptr &bus, - int framesToProcess) override; - + std::shared_ptr + processNode(const std::shared_ptr &bus, + int framesToProcess) override; }; } // namespace audioapi diff --git a/packages/react-native-audio-api/android/src/main/cpp/audioapi/android/core/AndroidAudioRecorder.cpp b/packages/react-native-audio-api/android/src/main/cpp/audioapi/android/core/AndroidAudioRecorder.cpp index 07d185a85..30bcc4bba 100644 --- a/packages/react-native-audio-api/android/src/main/cpp/audioapi/android/core/AndroidAudioRecorder.cpp +++ b/packages/react-native-audio-api/android/src/main/cpp/audioapi/android/core/AndroidAudioRecorder.cpp @@ -12,7 +12,7 @@ #include #include #include -#include +#include #include #include #include @@ -375,12 +375,13 @@ oboe::DataCallbackResult AndroidAudioRecorder::onAudioReady( if (isConnected()) { if (auto adapterLock = Locker::tryLock(adapterNodeMutex_)) { for (int channel = 0; channel < streamChannelCount_; ++channel) { + auto channelData = deinterleavingBuffer_->span(); for (int frame = 0; frame < numFrames; ++frame) { - deinterleavingBuffer_->getData()[frame] = + channelData[frame] = static_cast(audioData)[frame * streamChannelCount_ + channel]; } - adapterNode_->buff_[channel]->write(deinterleavingBuffer_->getData(), numFrames); + adapterNode_->buff_[channel]->write(*deinterleavingBuffer_, numFrames); } } } diff --git a/packages/react-native-audio-api/android/src/main/cpp/audioapi/android/core/AndroidAudioRecorder.h b/packages/react-native-audio-api/android/src/main/cpp/audioapi/android/core/AndroidAudioRecorder.h index 5c2ea8bbf..625fa91d9 100644 --- a/packages/react-native-audio-api/android/src/main/cpp/audioapi/android/core/AndroidAudioRecorder.h +++ b/packages/react-native-audio-api/android/src/main/cpp/audioapi/android/core/AndroidAudioRecorder.h @@ -1,18 +1,18 @@ #pragma once +#include #include +#include #include #include #include +#include #include #include -#include -#include -#include namespace audioapi { -class AudioBus; +class AudioBuffer; class AudioArray; class CircularAudioArray; class AudioFileProperties; @@ -22,14 +22,16 @@ class AudioEventHandlerRegistry; class AndroidAudioRecorder : public oboe::AudioStreamCallback, public AudioRecorder { public: - explicit AndroidAudioRecorder(const std::shared_ptr &audioEventHandlerRegistry); + explicit AndroidAudioRecorder( + const std::shared_ptr &audioEventHandlerRegistry); ~AndroidAudioRecorder() override; void cleanup(); Result start(const std::string &fileNameOverride) override; Result, std::string> stop() override; - Result enableFileOutput(std::shared_ptr properties) override; + Result enableFileOutput( + std::shared_ptr properties) override; void disableFileOutput() override; void pause() override; @@ -38,17 +40,18 @@ class AndroidAudioRecorder : public oboe::AudioStreamCallback, public AudioRecor bool isPaused() const override; bool isIdle() const override; - Result setOnAudioReadyCallback(float sampleRate, size_t bufferLength, int channelCount, uint64_t callbackId) - override; + Result setOnAudioReadyCallback( + float sampleRate, + size_t bufferLength, + int channelCount, + uint64_t callbackId) override; void clearOnAudioReadyCallback() override; void connect(const std::shared_ptr &node) override; void disconnect() override; - oboe::DataCallbackResult onAudioReady( - oboe::AudioStream *oboeStream, - void *audioData, - int32_t numFrames) override; + oboe::DataCallbackResult + onAudioReady(oboe::AudioStream *oboeStream, void *audioData, int32_t numFrames) override; void onErrorAfterClose(oboe::AudioStream *oboeStream, oboe::Result error) override; private: diff --git a/packages/react-native-audio-api/android/src/main/cpp/audioapi/android/core/AudioPlayer.cpp b/packages/react-native-audio-api/android/src/main/cpp/audioapi/android/core/AudioPlayer.cpp index e112c98a5..215f7f238 100644 --- a/packages/react-native-audio-api/android/src/main/cpp/audioapi/android/core/AudioPlayer.cpp +++ b/packages/react-native-audio-api/android/src/main/cpp/audioapi/android/core/AudioPlayer.cpp @@ -3,7 +3,7 @@ #include #include #include -#include +#include #include #include @@ -12,7 +12,7 @@ namespace audioapi { AudioPlayer::AudioPlayer( - const std::function, int)> &renderAudio, + const std::function, int)> &renderAudio, float sampleRate, int channelCount) : renderAudio_(renderAudio), @@ -42,7 +42,7 @@ bool AudioPlayer::openAudioStream() { return false; } - audioBus_ = std::make_shared(RENDER_QUANTUM_SIZE, channelCount_, sampleRate_); + audioBus_ = std::make_shared(RENDER_QUANTUM_SIZE, channelCount_, sampleRate_); return true; } @@ -119,7 +119,7 @@ AudioPlayer::onAudioReady(AudioStream *oboeStream, void *audioData, int32_t numF for (int i = 0; i < framesToProcess; i++) { for (int channel = 0; channel < channelCount_; channel++) { buffer[(processedFrames + i) * channelCount_ + channel] = - audioBus_->getChannel(channel)->getData()[i]; + (*audioBus_->getChannel(channel))[i]; } } diff --git a/packages/react-native-audio-api/android/src/main/cpp/audioapi/android/core/AudioPlayer.h b/packages/react-native-audio-api/android/src/main/cpp/audioapi/android/core/AudioPlayer.h index 2af28dde0..7fcc1796c 100644 --- a/packages/react-native-audio-api/android/src/main/cpp/audioapi/android/core/AudioPlayer.h +++ b/packages/react-native-audio-api/android/src/main/cpp/audioapi/android/core/AudioPlayer.h @@ -12,12 +12,12 @@ namespace audioapi { using namespace oboe; class AudioContext; -class AudioBus; +class AudioBuffer; class AudioPlayer : public AudioStreamDataCallback, AudioStreamErrorCallback { public: AudioPlayer( - const std::function, int)> &renderAudio, + const std::function, int)> &renderAudio, float sampleRate, int channelCount); @@ -34,18 +34,15 @@ class AudioPlayer : public AudioStreamDataCallback, AudioStreamErrorCallback { [[nodiscard]] bool isRunning() const; - DataCallbackResult onAudioReady( - AudioStream *oboeStream, - void *audioData, - int32_t numFrames) override; - - void onErrorAfterClose(AudioStream * /* audioStream */, Result /* error */) + DataCallbackResult onAudioReady(AudioStream *oboeStream, void *audioData, int32_t numFrames) override; + void onErrorAfterClose(AudioStream * /* audioStream */, Result /* error */) override; + private: - std::function, int)> renderAudio_; + std::function, int)> renderAudio_; std::shared_ptr mStream_; - std::shared_ptr audioBus_; + std::shared_ptr audioBus_; bool isInitialized_ = false; float sampleRate_; int channelCount_; diff --git a/packages/react-native-audio-api/android/src/main/cpp/audioapi/android/core/utils/AndroidRecorderCallback.cpp b/packages/react-native-audio-api/android/src/main/cpp/audioapi/android/core/utils/AndroidRecorderCallback.cpp index b354c7355..2b2573ff6 100644 --- a/packages/react-native-audio-api/android/src/main/cpp/audioapi/android/core/utils/AndroidRecorderCallback.cpp +++ b/packages/react-native-audio-api/android/src/main/cpp/audioapi/android/core/utils/AndroidRecorderCallback.cpp @@ -4,7 +4,7 @@ #include #include #include -#include +#include #include #include @@ -165,13 +165,13 @@ void AndroidRecorderCallback::deinterleaveAndPushAudioData(void *data, int numFr auto *inputData = static_cast(data); for (int channel = 0; channel < channelCount_; ++channel) { - float *channelData = deinterleavingArray_->getData(); + auto channelData = deinterleavingArray_->span(); for (int frame = 0; frame < numFrames; ++frame) { channelData[frame] = inputData[frame * channelCount_ + channel]; } - circularBus_[channel]->push_back(channelData, numFrames); + circularBus_[channel]->push_back(*deinterleavingArray_, numFrames); } } diff --git a/packages/react-native-audio-api/android/src/main/cpp/audioapi/android/core/utils/AndroidRecorderCallback.h b/packages/react-native-audio-api/android/src/main/cpp/audioapi/android/core/utils/AndroidRecorderCallback.h index 088bca2c5..1f573a65e 100644 --- a/packages/react-native-audio-api/android/src/main/cpp/audioapi/android/core/utils/AndroidRecorderCallback.h +++ b/packages/react-native-audio-api/android/src/main/cpp/audioapi/android/core/utils/AndroidRecorderCallback.h @@ -1,15 +1,14 @@ #pragma once - -#include #include +#include #include -#include #include +#include namespace audioapi { -class AudioBus; +class AudioBuffer; class AudioArray; class CircularAudioArray; class AudioEventHandlerRegistry; @@ -24,7 +23,8 @@ class AndroidRecorderCallback : public AudioRecorderCallback { uint64_t callbackId); ~AndroidRecorderCallback(); - Result prepare(float streamSampleRate, int streamChannelCount, size_t maxInputBufferLength); + Result + prepare(float streamSampleRate, int streamChannelCount, size_t maxInputBufferLength); void cleanup() override; void receiveAudioData(void *data, int numFrames); diff --git a/packages/react-native-audio-api/android/src/main/cpp/audioapi/android/core/utils/AudioDecoder.cpp b/packages/react-native-audio-api/android/src/main/cpp/audioapi/android/core/utils/AudioDecoder.cpp index da0c8ae6f..c27e69074 100644 --- a/packages/react-native-audio-api/android/src/main/cpp/audioapi/android/core/utils/AudioDecoder.cpp +++ b/packages/react-native-audio-api/android/src/main/cpp/audioapi/android/core/utils/AudioDecoder.cpp @@ -1,9 +1,8 @@ -#include #include #include #include #include -#include +#include #include #include @@ -54,15 +53,15 @@ std::shared_ptr AudioDecoder::makeAudioBufferFromFloatBuffer( } auto outputFrames = buffer.size() / outputChannels; - auto audioBus = std::make_shared(outputFrames, outputChannels, outputSampleRate); + auto audioBus = std::make_shared(outputFrames, outputChannels, outputSampleRate); for (int ch = 0; ch < outputChannels; ++ch) { - auto channelData = audioBus->getChannel(ch)->getData(); + auto channelData = audioBus->getChannel(ch)->span(); for (int i = 0; i < outputFrames; ++i) { channelData[i] = buffer[i * outputChannels + ch]; } } - return std::make_shared(audioBus); + return audioBus; } std::shared_ptr AudioDecoder::decodeWithFilePath( @@ -162,10 +161,11 @@ std::shared_ptr AudioDecoder::decodeWithPCMInBase64( const auto uint8Data = reinterpret_cast(decodedData.data()); size_t numFramesDecoded = decodedData.size() / (inputChannelCount * sizeof(int16_t)); - auto audioBus = std::make_shared(numFramesDecoded, inputChannelCount, inputSampleRate); + auto audioBus = + std::make_shared(numFramesDecoded, inputChannelCount, inputSampleRate); for (int ch = 0; ch < inputChannelCount; ++ch) { - auto channelData = audioBus->getChannel(ch)->getData(); + auto channelData = audioBus->getChannel(ch)->span(); for (size_t i = 0; i < numFramesDecoded; ++i) { size_t offset; @@ -180,7 +180,7 @@ std::shared_ptr AudioDecoder::decodeWithPCMInBase64( channelData[i] = uint8ToFloat(uint8Data[offset], uint8Data[offset + 1]); } } - return std::make_shared(audioBus); + return audioBus; } } // namespace audioapi diff --git a/packages/react-native-audio-api/common/cpp/audioapi/HostObjects/AudioParamHostObject.cpp b/packages/react-native-audio-api/common/cpp/audioapi/HostObjects/AudioParamHostObject.cpp index 45508e702..6d501e25d 100644 --- a/packages/react-native-audio-api/common/cpp/audioapi/HostObjects/AudioParamHostObject.cpp +++ b/packages/react-native-audio-api/common/cpp/audioapi/HostObjects/AudioParamHostObject.cpp @@ -1,6 +1,8 @@ #include #include +#include + #include #include @@ -80,7 +82,7 @@ JSI_HOST_FUNCTION_IMPL(AudioParamHostObject, setValueCurveAtTime) { args[0].getObject(runtime).getPropertyAsObject(runtime, "buffer").getArrayBuffer(runtime); auto rawValues = reinterpret_cast(arrayBuffer.data(runtime)); auto length = static_cast(arrayBuffer.size(runtime)); - auto values = std::make_unique>(rawValues, rawValues + length); + auto values = std::make_unique(rawValues, length); double startTime = args[1].getNumber(); double duration = args[2].getNumber(); diff --git a/packages/react-native-audio-api/common/cpp/audioapi/HostObjects/effects/WaveShaperNodeHostObject.cpp b/packages/react-native-audio-api/common/cpp/audioapi/HostObjects/effects/WaveShaperNodeHostObject.cpp index 1550e9b72..3a989cc25 100644 --- a/packages/react-native-audio-api/common/cpp/audioapi/HostObjects/effects/WaveShaperNodeHostObject.cpp +++ b/packages/react-native-audio-api/common/cpp/audioapi/HostObjects/effects/WaveShaperNodeHostObject.cpp @@ -3,7 +3,7 @@ #include #include #include -#include +#include #include #include @@ -37,8 +37,7 @@ JSI_PROPERTY_GETTER_IMPL(WaveShaperNodeHostObject, curve) { } // copy AudioArray holding curve data to avoid subsequent modifications - auto audioArray = std::make_shared(*curve); - auto audioArrayBuffer = std::make_shared(audioArray); + auto audioArrayBuffer = std::make_shared(*curve); auto arrayBuffer = jsi::ArrayBuffer(runtime, audioArrayBuffer); auto float32ArrayCtor = runtime.global().getPropertyAsFunction(runtime, "Float32Array"); @@ -58,14 +57,14 @@ JSI_HOST_FUNCTION_IMPL(WaveShaperNodeHostObject, setCurve) { auto waveShaperNode = std::static_pointer_cast(node_); if (args[0].isNull()) { - waveShaperNode->setCurve(std::shared_ptr(nullptr)); + waveShaperNode->setCurve(nullptr); return jsi::Value::undefined(); } auto arrayBuffer = args[0].getObject(runtime).getPropertyAsObject(runtime, "buffer").getArrayBuffer(runtime); - auto curve = std::make_shared( + auto curve = std::make_shared( reinterpret_cast(arrayBuffer.data(runtime)), static_cast(arrayBuffer.size(runtime) / sizeof(float))); diff --git a/packages/react-native-audio-api/common/cpp/audioapi/HostObjects/inputs/AudioRecorderHostObject.cpp b/packages/react-native-audio-api/common/cpp/audioapi/HostObjects/inputs/AudioRecorderHostObject.cpp index 10976563b..9ea3aeb0e 100644 --- a/packages/react-native-audio-api/common/cpp/audioapi/HostObjects/inputs/AudioRecorderHostObject.cpp +++ b/packages/react-native-audio-api/common/cpp/audioapi/HostObjects/inputs/AudioRecorderHostObject.cpp @@ -3,10 +3,10 @@ #include #include #include -#include #include -#include #include +#include +#include #ifdef ANDROID #include #else diff --git a/packages/react-native-audio-api/common/cpp/audioapi/HostObjects/sources/AudioBufferHostObject.cpp b/packages/react-native-audio-api/common/cpp/audioapi/HostObjects/sources/AudioBufferHostObject.cpp index 91a7c577a..cdaff96b0 100644 --- a/packages/react-native-audio-api/common/cpp/audioapi/HostObjects/sources/AudioBufferHostObject.cpp +++ b/packages/react-native-audio-api/common/cpp/audioapi/HostObjects/sources/AudioBufferHostObject.cpp @@ -1,7 +1,7 @@ #include -#include -#include +#include +#include #include #include @@ -30,7 +30,7 @@ JSI_PROPERTY_GETTER_IMPL(AudioBufferHostObject, sampleRate) { } JSI_PROPERTY_GETTER_IMPL(AudioBufferHostObject, length) { - return {static_cast(audioBuffer_->getLength())}; + return {static_cast(audioBuffer_->getSize())}; } JSI_PROPERTY_GETTER_IMPL(AudioBufferHostObject, duration) { @@ -43,8 +43,7 @@ JSI_PROPERTY_GETTER_IMPL(AudioBufferHostObject, numberOfChannels) { JSI_HOST_FUNCTION_IMPL(AudioBufferHostObject, getChannelData) { auto channel = static_cast(args[0].getNumber()); - auto audioArrayBuffer = - std::make_shared(audioBuffer_->bus_->getSharedChannel(channel)); + auto audioArrayBuffer = audioBuffer_->getSharedChannel(channel); auto arrayBuffer = jsi::ArrayBuffer(runtime, audioArrayBuffer); auto float32ArrayCtor = runtime.global().getPropertyAsFunction(runtime, "Float32Array"); @@ -63,7 +62,7 @@ JSI_HOST_FUNCTION_IMPL(AudioBufferHostObject, copyFromChannel) { auto channelNumber = static_cast(args[1].getNumber()); auto startInChannel = static_cast(args[2].getNumber()); - audioBuffer_->copyFromChannel(destination, length, channelNumber, startInChannel); + audioBuffer_->getChannel(channelNumber)->copyTo(destination, startInChannel, 0, length); return jsi::Value::undefined(); } @@ -76,7 +75,7 @@ JSI_HOST_FUNCTION_IMPL(AudioBufferHostObject, copyToChannel) { auto channelNumber = static_cast(args[1].getNumber()); auto startInChannel = static_cast(args[2].getNumber()); - audioBuffer_->copyToChannel(source, length, channelNumber, startInChannel); + audioBuffer_->getChannel(channelNumber)->copy(source, 0, startInChannel, length); return jsi::Value::undefined(); } diff --git a/packages/react-native-audio-api/common/cpp/audioapi/HostObjects/sources/AudioBufferHostObject.h b/packages/react-native-audio-api/common/cpp/audioapi/HostObjects/sources/AudioBufferHostObject.h index 7bd601004..09d440d55 100644 --- a/packages/react-native-audio-api/common/cpp/audioapi/HostObjects/sources/AudioBufferHostObject.h +++ b/packages/react-native-audio-api/common/cpp/audioapi/HostObjects/sources/AudioBufferHostObject.h @@ -1,7 +1,7 @@ #pragma once -#include #include +#include #include #include @@ -29,7 +29,7 @@ class AudioBufferHostObject : public JsiHostObject { } [[nodiscard]] inline size_t getSizeInBytes() const { - return audioBuffer_->getLength() * audioBuffer_->getNumberOfChannels() * sizeof(float); + return audioBuffer_->getSize() * audioBuffer_->getNumberOfChannels() * sizeof(float); } JSI_PROPERTY_GETTER_DECL(sampleRate); diff --git a/packages/react-native-audio-api/common/cpp/audioapi/HostObjects/utils/NodeOptions.h b/packages/react-native-audio-api/common/cpp/audioapi/HostObjects/utils/NodeOptions.h index b3fcd250c..e6d7cf68a 100644 --- a/packages/react-native-audio-api/common/cpp/audioapi/HostObjects/utils/NodeOptions.h +++ b/packages/react-native-audio-api/common/cpp/audioapi/HostObjects/utils/NodeOptions.h @@ -6,13 +6,14 @@ #include #include -#include #include #include #include #include #include #include +#include +#include namespace audioapi { struct AudioNodeOptions { @@ -104,7 +105,7 @@ struct IIRFilterOptions : AudioNodeOptions { }; struct WaveShaperOptions : AudioNodeOptions { - std::shared_ptr curve; + std::shared_ptr curve; OverSampleType oversample; }; diff --git a/packages/react-native-audio-api/common/cpp/audioapi/HostObjects/utils/NodeOptionsParser.h b/packages/react-native-audio-api/common/cpp/audioapi/HostObjects/utils/NodeOptionsParser.h index ede0e4a94..0810d684e 100644 --- a/packages/react-native-audio-api/common/cpp/audioapi/HostObjects/utils/NodeOptionsParser.h +++ b/packages/react-native-audio-api/common/cpp/audioapi/HostObjects/utils/NodeOptionsParser.h @@ -253,7 +253,7 @@ WaveShaperOptions parseWaveShaperOptions(jsi::Runtime &runtime, const jsi::Objec if (optionsObject.hasProperty(runtime, "buffer")) { auto arrayBuffer = optionsObject.getPropertyAsObject(runtime, "buffer").getArrayBuffer(runtime); - options.curve = std::make_shared( + options.curve = std::make_shared( reinterpret_cast(arrayBuffer.data(runtime)), static_cast(arrayBuffer.size(runtime) / sizeof(float))); } diff --git a/packages/react-native-audio-api/common/cpp/audioapi/core/AudioContext.cpp b/packages/react-native-audio-api/common/cpp/audioapi/core/AudioContext.cpp index 7e90d9a36..853f5633c 100644 --- a/packages/react-native-audio-api/common/cpp/audioapi/core/AudioContext.cpp +++ b/packages/react-native-audio-api/common/cpp/audioapi/core/AudioContext.cpp @@ -16,7 +16,7 @@ AudioContext::AudioContext( const std::shared_ptr &audioEventHandlerRegistry, const RuntimeRegistry &runtimeRegistry) : BaseAudioContext(sampleRate, audioEventHandlerRegistry, runtimeRegistry), - isInitialized_(false) {} + isInitialized_(false) {} AudioContext::~AudioContext() { if (getState() != ContextState::CLOSED) { @@ -90,8 +90,8 @@ bool AudioContext::start() { return false; } -std::function, int)> AudioContext::renderAudio() { - return [this](const std::shared_ptr &data, int frames) { +std::function, int)> AudioContext::renderAudio() { + return [this](const std::shared_ptr &data, int frames) { destination_->renderAudio(data, frames); }; } diff --git a/packages/react-native-audio-api/common/cpp/audioapi/core/AudioContext.h b/packages/react-native-audio-api/common/cpp/audioapi/core/AudioContext.h index c1eced267..967b38426 100644 --- a/packages/react-native-audio-api/common/cpp/audioapi/core/AudioContext.h +++ b/packages/react-native-audio-api/common/cpp/audioapi/core/AudioContext.h @@ -37,7 +37,7 @@ class AudioContext : public BaseAudioContext { bool isDriverRunning() const override; - std::function, int)> renderAudio(); + std::function, int)> renderAudio(); }; } // namespace audioapi diff --git a/packages/react-native-audio-api/common/cpp/audioapi/core/AudioNode.cpp b/packages/react-native-audio-api/common/cpp/audioapi/core/AudioNode.cpp index e8cd1503e..8997adb39 100644 --- a/packages/react-native-audio-api/common/cpp/audioapi/core/AudioNode.cpp +++ b/packages/react-native-audio-api/common/cpp/audioapi/core/AudioNode.cpp @@ -4,16 +4,16 @@ #include #include #include -#include +#include #include #include #include namespace audioapi { -AudioNode::AudioNode(const std::shared_ptr& context) : context_(context) { +AudioNode::AudioNode(const std::shared_ptr &context) : context_(context) { audioBus_ = - std::make_shared(RENDER_QUANTUM_SIZE, channelCount_, context->getSampleRate()); + std::make_shared(RENDER_QUANTUM_SIZE, channelCount_, context->getSampleRate()); } AudioNode::AudioNode( @@ -24,7 +24,7 @@ AudioNode::AudioNode( channelCountMode_(options.channelCountMode), channelInterpretation_(options.channelInterpretation) { audioBus_ = - std::make_shared(RENDER_QUANTUM_SIZE, channelCount_, context->getSampleRate()); + std::make_shared(RENDER_QUANTUM_SIZE, channelCount_, context->getSampleRate()); } AudioNode::~AudioNode() { @@ -55,36 +55,36 @@ ChannelInterpretation AudioNode::getChannelInterpretation() const { void AudioNode::connect(const std::shared_ptr &node) { if (std::shared_ptr context = context_.lock()) { - context->getGraphManager()->addPendingNodeConnection( - shared_from_this(), node, AudioGraphManager::ConnectionType::CONNECT); + context->getGraphManager()->addPendingNodeConnection( + shared_from_this(), node, AudioGraphManager::ConnectionType::CONNECT); } } void AudioNode::connect(const std::shared_ptr ¶m) { if (std::shared_ptr context = context_.lock()) { - context->getGraphManager()->addPendingParamConnection( - shared_from_this(), param, AudioGraphManager::ConnectionType::CONNECT); + context->getGraphManager()->addPendingParamConnection( + shared_from_this(), param, AudioGraphManager::ConnectionType::CONNECT); } } void AudioNode::disconnect() { if (std::shared_ptr context = context_.lock()) { - context->getGraphManager()->addPendingNodeConnection( - shared_from_this(), nullptr, AudioGraphManager::ConnectionType::DISCONNECT_ALL); + context->getGraphManager()->addPendingNodeConnection( + shared_from_this(), nullptr, AudioGraphManager::ConnectionType::DISCONNECT_ALL); } } void AudioNode::disconnect(const std::shared_ptr &node) { if (std::shared_ptr context = context_.lock()) { - context->getGraphManager()->addPendingNodeConnection( - shared_from_this(), node, AudioGraphManager::ConnectionType::DISCONNECT); + context->getGraphManager()->addPendingNodeConnection( + shared_from_this(), node, AudioGraphManager::ConnectionType::DISCONNECT); } } void AudioNode::disconnect(const std::shared_ptr ¶m) { if (std::shared_ptr context = context_.lock()) { - context->getGraphManager()->addPendingParamConnection( - shared_from_this(), param, AudioGraphManager::ConnectionType::DISCONNECT); + context->getGraphManager()->addPendingParamConnection( + shared_from_this(), param, AudioGraphManager::ConnectionType::DISCONNECT); } } @@ -120,8 +120,8 @@ void AudioNode::disable() { } } -std::shared_ptr AudioNode::processAudio( - const std::shared_ptr &outputBus, +std::shared_ptr AudioNode::processAudio( + const std::shared_ptr &outputBus, int framesToProcess, bool checkIsAlreadyProcessed) { if (!isInitialized_) { @@ -166,8 +166,8 @@ bool AudioNode::isAlreadyProcessed() { return true; } -std::shared_ptr AudioNode::processInputs( - const std::shared_ptr &outputBus, +std::shared_ptr AudioNode::processInputs( + const std::shared_ptr &outputBus, int framesToProcess, bool checkIsAlreadyProcessed) { auto processingBus = audioBus_; @@ -194,8 +194,8 @@ std::shared_ptr AudioNode::processInputs( return processingBus; } -std::shared_ptr AudioNode::applyChannelCountMode( - const std::shared_ptr &processingBus) { +std::shared_ptr AudioNode::applyChannelCountMode( + const std::shared_ptr &processingBus) { // If the channelCountMode is EXPLICIT, the node should output the number of // channels specified by the channelCount. if (channelCountMode_ == ChannelCountMode::EXPLICIT) { @@ -212,11 +212,11 @@ std::shared_ptr AudioNode::applyChannelCountMode( return processingBus; } -void AudioNode::mixInputsBuses(const std::shared_ptr &processingBus) { +void AudioNode::mixInputsBuses(const std::shared_ptr &processingBus) { assert(processingBus != nullptr); for (auto it = inputBuses_.begin(), end = inputBuses_.end(); it != end; ++it) { - processingBus->sum(it->get(), channelInterpretation_); + processingBus->sum(**it, channelInterpretation_); } inputBuses_.clear(); diff --git a/packages/react-native-audio-api/common/cpp/audioapi/core/AudioNode.h b/packages/react-native-audio-api/common/cpp/audioapi/core/AudioNode.h index 8a52f15c3..319108b1c 100644 --- a/packages/react-native-audio-api/common/cpp/audioapi/core/AudioNode.h +++ b/packages/react-native-audio-api/common/cpp/audioapi/core/AudioNode.h @@ -13,7 +13,7 @@ namespace audioapi { -class AudioBus; +class AudioBuffer; class BaseAudioContext; class AudioParam; struct AudioNodeOptions; @@ -36,8 +36,8 @@ class AudioNode : public std::enable_shared_from_this { void disconnect(); void disconnect(const std::shared_ptr &node); void disconnect(const std::shared_ptr ¶m); - virtual std::shared_ptr processAudio( - const std::shared_ptr &outputBus, + virtual std::shared_ptr processAudio( + const std::shared_ptr &outputBus, int framesToProcess, bool checkIsAlreadyProcessed); @@ -53,7 +53,7 @@ class AudioNode : public std::enable_shared_from_this { friend class DelayNodeHostObject; std::weak_ptr context_; - std::shared_ptr audioBus_; + std::shared_ptr audioBus_; int numberOfInputs_ = 1; int numberOfOutputs_ = 1; @@ -73,17 +73,18 @@ class AudioNode : public std::enable_shared_from_this { std::size_t lastRenderedFrame_{SIZE_MAX}; private: - std::vector> inputBuses_ = {}; + std::vector> inputBuses_ = {}; - virtual std::shared_ptr processInputs( - const std::shared_ptr &outputBus, + virtual std::shared_ptr processInputs( + const std::shared_ptr &outputBus, int framesToProcess, bool checkIsAlreadyProcessed); - virtual std::shared_ptr processNode(const std::shared_ptr &, int) = 0; + virtual std::shared_ptr processNode(const std::shared_ptr &, int) = 0; bool isAlreadyProcessed(); - std::shared_ptr applyChannelCountMode(const std::shared_ptr &processingBus); - void mixInputsBuses(const std::shared_ptr &processingBus); + std::shared_ptr applyChannelCountMode( + const std::shared_ptr &processingBus); + void mixInputsBuses(const std::shared_ptr &processingBus); void connectNode(const std::shared_ptr &node); void disconnectNode(const std::shared_ptr &node); diff --git a/packages/react-native-audio-api/common/cpp/audioapi/core/AudioParam.cpp b/packages/react-native-audio-api/common/cpp/audioapi/core/AudioParam.cpp index c0873dbe8..87b134fef 100644 --- a/packages/react-native-audio-api/common/cpp/audioapi/core/AudioParam.cpp +++ b/packages/react-native-audio-api/common/cpp/audioapi/core/AudioParam.cpp @@ -1,6 +1,6 @@ #include #include -#include +#include #include #include #include @@ -12,7 +12,7 @@ AudioParam::AudioParam( float defaultValue, float minValue, float maxValue, - const std::shared_ptr& context) + const std::shared_ptr &context) : context_(context), value_(defaultValue), defaultValue_(defaultValue), @@ -24,7 +24,7 @@ AudioParam::AudioParam( endTime_(0), startValue_(defaultValue), endValue_(defaultValue), - audioBus_(std::make_shared(RENDER_QUANTUM_SIZE, 1, context->getSampleRate())) { + audioBus_(std::make_shared(RENDER_QUANTUM_SIZE, 1, context->getSampleRate())) { inputBuses_.reserve(4); inputNodes_.reserve(4); // Default calculation function just returns the static value @@ -174,7 +174,7 @@ void AudioParam::setTargetAtTime(float target, double startTime, double timeCons } void AudioParam::setValueCurveAtTime( - const std::shared_ptr>& values, + const std::shared_ptr &values, size_t length, double startTime, double duration) { @@ -197,7 +197,7 @@ void AudioParam::setValueCurveAtTime( // Calculate interpolation factor between adjacent array elements auto factor = static_cast( (time - startTime) * static_cast(length - 1) / (endTime - startTime) - k); - return dsp::linearInterpolate(values->data(), k, k + 1, factor); + return dsp::linearInterpolate(values->span(), k, k + 1, factor); } return endValue; @@ -207,7 +207,7 @@ void AudioParam::setValueCurveAtTime( startTime, startTime + duration, param.getQueueEndValue(), - values->at(length - 1), + values->span()[length - 1], std::move(calculateValue), ParamChangeEventType::SET_VALUE_CURVE)); }; @@ -242,8 +242,8 @@ void AudioParam::removeInputNode(AudioNode *node) { } } -std::shared_ptr AudioParam::calculateInputs( - const std::shared_ptr &processingBus, +std::shared_ptr AudioParam::calculateInputs( + const std::shared_ptr &processingBus, int framesToProcess) { processingBus->zero(); if (inputNodes_.empty()) { @@ -254,7 +254,7 @@ std::shared_ptr AudioParam::calculateInputs( return processingBus; } -std::shared_ptr AudioParam::processARateParam(int framesToProcess, double time) { +std::shared_ptr AudioParam::processARateParam(int framesToProcess, double time) { processScheduledEvents(); auto processingBus = calculateInputs(audioBus_, framesToProcess); @@ -262,7 +262,7 @@ std::shared_ptr AudioParam::processARateParam(int framesToProcess, dou if (context == nullptr) return processingBus; float sampleRate = context->getSampleRate(); - float *busData = processingBus->getChannel(0)->getData(); + auto busData = processingBus->getChannel(0)->span(); float timeCache = time; float timeStep = 1.0f / sampleRate; float sample = 0.0f; @@ -281,11 +281,11 @@ float AudioParam::processKRateParam(int framesToProcess, double time) { auto processingBus = calculateInputs(audioBus_, framesToProcess); // Return block-rate parameter value plus first sample of input modulation - return processingBus->getChannel(0)->getData()[0] + getValueAtTime(time); + return processingBus->getChannel(0)->span()[0] + getValueAtTime(time); } void AudioParam::processInputs( - const std::shared_ptr &outputBus, + const std::shared_ptr &outputBus, int framesToProcess, bool checkIsAlreadyProcessed) { for (auto it = inputNodes_.begin(), end = inputNodes_.end(); it != end; ++it) { @@ -302,12 +302,12 @@ void AudioParam::processInputs( } } -void AudioParam::mixInputsBuses(const std::shared_ptr &processingBus) { +void AudioParam::mixInputsBuses(const std::shared_ptr &processingBus) { assert(processingBus != nullptr); // Sum all input buses into the processing bus for (auto it = inputBuses_.begin(), end = inputBuses_.end(); it != end; ++it) { - processingBus->sum(it->get(), ChannelInterpretation::SPEAKERS); + processingBus->sum(**it, ChannelInterpretation::SPEAKERS); } // Clear for next processing cycle diff --git a/packages/react-native-audio-api/common/cpp/audioapi/core/AudioParam.h b/packages/react-native-audio-api/common/cpp/audioapi/core/AudioParam.h index 0f53b8a7e..165a48809 100644 --- a/packages/react-native-audio-api/common/cpp/audioapi/core/AudioParam.h +++ b/packages/react-native-audio-api/common/cpp/audioapi/core/AudioParam.h @@ -3,8 +3,8 @@ #include #include #include -#include -#include +#include +#include #include #include @@ -65,7 +65,7 @@ class AudioParam { // JS-Thread only void setValueCurveAtTime( - const std::shared_ptr> &values, + const std::shared_ptr &values, size_t length, double startTime, double duration); @@ -86,7 +86,7 @@ class AudioParam { void removeInputNode(AudioNode *node); // Audio-Thread only - std::shared_ptr processARateParam(int framesToProcess, double time); + std::shared_ptr processARateParam(int framesToProcess, double time); // Audio-Thread only float processKRateParam(int framesToProcess, double time); @@ -111,8 +111,8 @@ class AudioParam { // Input modulation system std::vector inputNodes_; - std::shared_ptr audioBus_; - std::vector> inputBuses_; + std::shared_ptr audioBus_; + std::vector> inputBuses_; /// @brief Get the end time of the parameter queue. /// @return The end time of the parameter queue or last endTime_ if queue is empty. @@ -145,12 +145,12 @@ class AudioParam { } float getValueAtTime(double time); void processInputs( - const std::shared_ptr &outputBus, + const std::shared_ptr &outputBus, int framesToProcess, bool checkIsAlreadyProcessed); - void mixInputsBuses(const std::shared_ptr &processingBus); - std::shared_ptr calculateInputs( - const std::shared_ptr &processingBus, + void mixInputsBuses(const std::shared_ptr &processingBus); + std::shared_ptr calculateInputs( + const std::shared_ptr &processingBus, int framesToProcess); }; diff --git a/packages/react-native-audio-api/common/cpp/audioapi/core/BaseAudioContext.cpp b/packages/react-native-audio-api/common/cpp/audioapi/core/BaseAudioContext.cpp index 78b8888cf..8ec251296 100644 --- a/packages/react-native-audio-api/common/cpp/audioapi/core/BaseAudioContext.cpp +++ b/packages/react-native-audio-api/common/cpp/audioapi/core/BaseAudioContext.cpp @@ -11,7 +11,6 @@ #include #include #include -#include #include #include #include @@ -26,7 +25,7 @@ #include #include #include -#include +#include #include #include #include @@ -78,7 +77,7 @@ std::shared_ptr BaseAudioContext::getDestination() const { } void BaseAudioContext::setState(audioapi::ContextState state) { - state_.store(state, std::memory_order_release); + state_.store(state, std::memory_order_release); } std::shared_ptr BaseAudioContext::createWorkletSourceNode( @@ -122,7 +121,8 @@ std::shared_ptr BaseAudioContext::createRecorderAdapter() { return recorderAdapter; } -std::shared_ptr BaseAudioContext::createOscillator(const OscillatorOptions &options) { +std::shared_ptr BaseAudioContext::createOscillator( + const OscillatorOptions &options) { auto oscillator = std::make_shared(shared_from_this(), options); graphManager_->addSourceNode(oscillator); return oscillator; @@ -192,7 +192,7 @@ std::shared_ptr BaseAudioContext::createBufferQueueS } std::shared_ptr BaseAudioContext::createBuffer(const AudioBufferOptions &options) { - return std::make_shared(options); + return std::make_shared(options.length, options.numberOfChannels, options.sampleRate); } std::shared_ptr BaseAudioContext::createPeriodicWave( @@ -214,7 +214,8 @@ std::shared_ptr BaseAudioContext::createConvolver(const Convolver return convolver; } -std::shared_ptr BaseAudioContext::createWaveShaper(const WaveShaperOptions &options) { +std::shared_ptr BaseAudioContext::createWaveShaper( + const WaveShaperOptions &options) { auto waveShaper = std::make_shared(shared_from_this(), options); graphManager_->addProcessingNode(waveShaper); return waveShaper; @@ -261,7 +262,7 @@ std::shared_ptr BaseAudioContext::getAudioEventHandl } const RuntimeRegistry &BaseAudioContext::getRuntimeRegistry() const { - return runtimeRegistry_; + return runtimeRegistry_; } } // namespace audioapi diff --git a/packages/react-native-audio-api/common/cpp/audioapi/core/BaseAudioContext.h b/packages/react-native-audio-api/common/cpp/audioapi/core/BaseAudioContext.h index a684eda13..bcbc837a4 100644 --- a/packages/react-native-audio-api/common/cpp/audioapi/core/BaseAudioContext.h +++ b/packages/react-native-audio-api/common/cpp/audioapi/core/BaseAudioContext.h @@ -16,7 +16,7 @@ namespace audioapi { -class AudioBus; +class AudioBuffer; class GainNode; class DelayNode; class AudioBuffer; diff --git a/packages/react-native-audio-api/common/cpp/audioapi/core/OfflineAudioContext.cpp b/packages/react-native-audio-api/common/cpp/audioapi/core/OfflineAudioContext.cpp index 0b771c973..9b2b15f7a 100644 --- a/packages/react-native-audio-api/common/cpp/audioapi/core/OfflineAudioContext.cpp +++ b/packages/react-native-audio-api/common/cpp/audioapi/core/OfflineAudioContext.cpp @@ -2,12 +2,11 @@ #include #include -#include #include #include #include #include -#include +#include #include #include @@ -28,10 +27,10 @@ OfflineAudioContext::OfflineAudioContext( length_(length), numberOfChannels_(numberOfChannels), currentSampleFrame_(0), - resultBus_(std::make_shared(length, numberOfChannels, sampleRate)) {} + resultBus_(std::make_shared(length, numberOfChannels, sampleRate)) {} OfflineAudioContext::~OfflineAudioContext() { - getGraphManager()->cleanup(); + getGraphManager()->cleanup(); } void OfflineAudioContext::resume() { @@ -65,7 +64,8 @@ void OfflineAudioContext::renderAudio() { setState(ContextState::RUNNING); std::thread([this]() { - auto audioBus = std::make_shared(RENDER_QUANTUM_SIZE, numberOfChannels_, getSampleRate()); + auto audioBus = + std::make_shared(RENDER_QUANTUM_SIZE, numberOfChannels_, getSampleRate()); while (currentSampleFrame_ < length_) { Locker locker(mutex_); @@ -74,12 +74,7 @@ void OfflineAudioContext::renderAudio() { destination_->renderAudio(audioBus, framesToProcess); - for (int i = 0; i < framesToProcess; i++) { - for (int channel = 0; channel < numberOfChannels_; channel += 1) { - resultBus_->getChannel(channel)->getData()[currentSampleFrame_ + i] = - audioBus->getChannel(channel)->getData()[i]; - } - } + resultBus_->copy(*audioBus, currentSampleFrame_, 0, framesToProcess); currentSampleFrame_ += framesToProcess; @@ -96,8 +91,7 @@ void OfflineAudioContext::renderAudio() { } // Rendering completed - auto buffer = std::make_shared(resultBus_); - resultCallback_(buffer); + resultCallback_(resultBus_); }).detach(); } diff --git a/packages/react-native-audio-api/common/cpp/audioapi/core/OfflineAudioContext.h b/packages/react-native-audio-api/common/cpp/audioapi/core/OfflineAudioContext.h index a33fd384a..e3c16e015 100644 --- a/packages/react-native-audio-api/common/cpp/audioapi/core/OfflineAudioContext.h +++ b/packages/react-native-audio-api/common/cpp/audioapi/core/OfflineAudioContext.h @@ -38,7 +38,7 @@ class OfflineAudioContext : public BaseAudioContext { int numberOfChannels_; size_t currentSampleFrame_; - std::shared_ptr resultBus_; + std::shared_ptr resultBus_; void renderAudio(); diff --git a/packages/react-native-audio-api/common/cpp/audioapi/core/analysis/AnalyserNode.cpp b/packages/react-native-audio-api/common/cpp/audioapi/core/analysis/AnalyserNode.cpp index f0396a522..70c9ae50d 100644 --- a/packages/react-native-audio-api/common/cpp/audioapi/core/analysis/AnalyserNode.cpp +++ b/packages/react-native-audio-api/common/cpp/audioapi/core/analysis/AnalyserNode.cpp @@ -1,11 +1,11 @@ #include #include #include -#include +#include #include -#include +#include #include -#include +#include #include #include @@ -25,7 +25,7 @@ AnalyserNode::AnalyserNode( smoothingTimeConstant_(options.smoothingTimeConstant), windowType_(WindowType::BLACKMAN), inputBuffer_(std::make_unique(MAX_FFT_SIZE * 2)), - downMixBus_(std::make_unique(RENDER_QUANTUM_SIZE, 1, context->getSampleRate())), + downMixBus_(std::make_unique(RENDER_QUANTUM_SIZE, 1, context->getSampleRate())), tempBuffer_(std::make_unique(fftSize_)), fft_(std::make_unique(fftSize_)), complexData_(std::vector>(fftSize_)), @@ -91,13 +91,14 @@ void AnalyserNode::getFloatFrequencyData(float *data, int length) { doFFTAnalysis(); length = std::min(static_cast(magnitudeBuffer_->getSize()), length); - dsp::linearToDecibels(magnitudeBuffer_->getData(), data, length); + // TODO + // dsp::linearToDecibels(magnitudeBuffer_->getData(), data, length); } void AnalyserNode::getByteFrequencyData(uint8_t *data, int length) { doFFTAnalysis(); - auto magnitudeBufferData = magnitudeBuffer_->getData(); + auto magnitudeBufferData = magnitudeBuffer_->span(); length = std::min(static_cast(magnitudeBuffer_->getSize()), length); const auto rangeScaleFactor = @@ -121,18 +122,19 @@ void AnalyserNode::getByteFrequencyData(uint8_t *data, int length) { void AnalyserNode::getFloatTimeDomainData(float *data, int length) { auto size = std::min(fftSize_, length); - inputBuffer_->pop_back(data, size, std::max(0, fftSize_ - size), true); +// TODO +// inputBuffer_->pop_back(data, size, std::max(0, fftSize_ - size), true); } void AnalyserNode::getByteTimeDomainData(uint8_t *data, int length) { auto size = std::min(fftSize_, length); - inputBuffer_->pop_back(tempBuffer_->getData(), fftSize_, std::max(0, fftSize_ - size), true); + inputBuffer_->pop_back(*tempBuffer_, fftSize_, std::max(0, fftSize_ - size), true); - for (int i = 0; i < size; i++) { - auto value = tempBuffer_->getData()[i]; + auto values = tempBuffer_->span(); - float scaledValue = 128 * (value + 1); + for (int i = 0; i < size; i++) { + float scaledValue = 128 * (values[i] + 1); if (scaledValue < 0) { scaledValue = 0; @@ -145,16 +147,16 @@ void AnalyserNode::getByteTimeDomainData(uint8_t *data, int length) { } } -std::shared_ptr AnalyserNode::processNode( - const std::shared_ptr &processingBus, +std::shared_ptr AnalyserNode::processNode( + const std::shared_ptr &processingBus, int framesToProcess) { // Analyser should behave like a sniffer node, it should not modify the // processingBus but instead copy the data to its own input buffer. // Down mix the input bus to mono - downMixBus_->copy(processingBus.get()); + downMixBus_->copy(*processingBus); // Copy the down mixed bus to the input buffer (circular buffer) - inputBuffer_->push_back(downMixBus_->getChannel(0)->getData(), framesToProcess, true); + inputBuffer_->push_back(*downMixBus_->getChannel(0), framesToProcess, true); shouldDoFFTAnalysis_ = true; @@ -170,18 +172,18 @@ void AnalyserNode::doFFTAnalysis() { // We want to copy last fftSize_ elements added to the input buffer to apply // the window. - inputBuffer_->pop_back(tempBuffer_->getData(), fftSize_, 0, true); + inputBuffer_->pop_back(*tempBuffer_, fftSize_, 0, true); - dsp::multiply(tempBuffer_->getData(), windowData_->getData(), tempBuffer_->getData(), fftSize_); + tempBuffer_->multiply(*windowData_, fftSize_); // do fft analysis - get frequency domain data - fft_->doFFT(tempBuffer_->getData(), complexData_); + fft_->doFFT(*tempBuffer_, complexData_); // Zero out nquist component complexData_[0] = std::complex(complexData_[0].real(), 0); const float magnitudeScale = 1.0f / static_cast(fftSize_); - auto magnitudeBufferData = magnitudeBuffer_->getData(); + auto magnitudeBufferData = magnitudeBuffer_->span(); for (int i = 0; i < magnitudeBuffer_->getSize(); i++) { auto scalarMagnitude = std::abs(complexData_[i]) * magnitudeScale; @@ -203,10 +205,10 @@ void AnalyserNode::setWindowData(AnalyserNode::WindowType type, int size) { switch (windowType_) { case WindowType::BLACKMAN: - dsp::Blackman().apply(windowData_->getData(), static_cast(windowData_->getSize())); + dsp::Blackman().apply(windowData_->span()); break; case WindowType::HANN: - dsp::Hann().apply(windowData_->getData(), static_cast(windowData_->getSize())); + dsp::Hann().apply(windowData_->span()); break; } } diff --git a/packages/react-native-audio-api/common/cpp/audioapi/core/analysis/AnalyserNode.h b/packages/react-native-audio-api/common/cpp/audioapi/core/analysis/AnalyserNode.h index b5e22822f..3ef915803 100644 --- a/packages/react-native-audio-api/common/cpp/audioapi/core/analysis/AnalyserNode.h +++ b/packages/react-native-audio-api/common/cpp/audioapi/core/analysis/AnalyserNode.h @@ -12,7 +12,7 @@ namespace audioapi { -class AudioBus; +class AudioBuffer; class AudioArray; class CircularAudioArray; struct AnalyserOptions; @@ -43,8 +43,8 @@ class AnalyserNode : public AudioNode { void getByteTimeDomainData(uint8_t *data, int length); protected: - std::shared_ptr processNode( - const std::shared_ptr &processingBus, + std::shared_ptr processNode( + const std::shared_ptr &processingBus, int framesToProcess) override; private: @@ -57,7 +57,7 @@ class AnalyserNode : public AudioNode { std::shared_ptr windowData_; std::unique_ptr inputBuffer_; - std::unique_ptr downMixBus_; + std::unique_ptr downMixBus_; std::unique_ptr tempBuffer_; std::unique_ptr fft_; diff --git a/packages/react-native-audio-api/common/cpp/audioapi/core/destinations/AudioDestinationNode.cpp b/packages/react-native-audio-api/common/cpp/audioapi/core/destinations/AudioDestinationNode.cpp index 9133f688a..87fc96461 100644 --- a/packages/react-native-audio-api/common/cpp/audioapi/core/destinations/AudioDestinationNode.cpp +++ b/packages/react-native-audio-api/common/cpp/audioapi/core/destinations/AudioDestinationNode.cpp @@ -2,7 +2,7 @@ #include #include #include -#include +#include #include namespace audioapi { @@ -28,14 +28,14 @@ double AudioDestinationNode::getCurrentTime() const { } void AudioDestinationNode::renderAudio( - const std::shared_ptr &destinationBus, + const std::shared_ptr &destinationBus, int numFrames) { if (numFrames < 0 || !destinationBus || !isInitialized_) { return; } if (std::shared_ptr context = context_.lock()) { - context->getGraphManager()->preProcessGraph(); + context->getGraphManager()->preProcessGraph(); } destinationBus->zero(); @@ -43,7 +43,7 @@ void AudioDestinationNode::renderAudio( auto processedBus = processAudio(destinationBus, numFrames, true); if (processedBus && processedBus != destinationBus) { - destinationBus->copy(processedBus.get()); + destinationBus->copy(*processedBus); } destinationBus->normalize(); diff --git a/packages/react-native-audio-api/common/cpp/audioapi/core/destinations/AudioDestinationNode.h b/packages/react-native-audio-api/common/cpp/audioapi/core/destinations/AudioDestinationNode.h index 94b8e3bba..478e979d8 100644 --- a/packages/react-native-audio-api/common/cpp/audioapi/core/destinations/AudioDestinationNode.h +++ b/packages/react-native-audio-api/common/cpp/audioapi/core/destinations/AudioDestinationNode.h @@ -10,7 +10,7 @@ namespace audioapi { -class AudioBus; +class AudioBuffer; class BaseAudioContext; class AudioDestinationNode : public AudioNode { @@ -20,12 +20,13 @@ class AudioDestinationNode : public AudioNode { std::size_t getCurrentSampleFrame() const; double getCurrentTime() const; - void renderAudio(const std::shared_ptr &audioData, int numFrames); + void renderAudio(const std::shared_ptr &audioData, int numFrames); protected: // DestinationNode is triggered by AudioContext using renderAudio // processNode function is not necessary and is never called. - std::shared_ptr processNode(const std::shared_ptr &processingBus, int) final { + std::shared_ptr processNode(const std::shared_ptr &processingBus, int) + final { return processingBus; }; diff --git a/packages/react-native-audio-api/common/cpp/audioapi/core/effects/BiquadFilterNode.cpp b/packages/react-native-audio-api/common/cpp/audioapi/core/effects/BiquadFilterNode.cpp index d7da37744..0e4248ba2 100644 --- a/packages/react-native-audio-api/common/cpp/audioapi/core/effects/BiquadFilterNode.cpp +++ b/packages/react-native-audio-api/common/cpp/audioapi/core/effects/BiquadFilterNode.cpp @@ -30,7 +30,7 @@ #include #include #include -#include +#include #include #include @@ -39,9 +39,12 @@ namespace audioapi { -BiquadFilterNode::BiquadFilterNode(const std::shared_ptr& context, const BiquadFilterOptions &options) : AudioNode(context, options) { - frequencyParam_ = - std::make_shared(options.frequency, 0.0f, context->getNyquistFrequency(), context); +BiquadFilterNode::BiquadFilterNode( + const std::shared_ptr &context, + const BiquadFilterOptions &options) + : AudioNode(context, options) { + frequencyParam_ = std::make_shared( + options.frequency, 0.0f, context->getNyquistFrequency(), context); detuneParam_ = std::make_shared( options.detune, -1200 * LOG2_MOST_POSITIVE_SINGLE_FLOAT, @@ -383,8 +386,8 @@ void BiquadFilterNode::applyFilter() { } } -std::shared_ptr BiquadFilterNode::processNode( - const std::shared_ptr &processingBus, +std::shared_ptr BiquadFilterNode::processNode( + const std::shared_ptr &processingBus, int framesToProcess) { int numChannels = processingBus->getNumberOfChannels(); @@ -400,24 +403,30 @@ std::shared_ptr BiquadFilterNode::processNode( float x1, x2, y1, y2; for (int c = 0; c < numChannels; ++c) { - auto channelData = processingBus->getChannel(c)->getData(); + auto channel = processingBus->getChannel(c)->subSpan(framesToProcess); x1 = x1_[c]; x2 = x2_[c]; y1 = y1_[c]; y2 = y2_[c]; - for (int i = 0; i < framesToProcess; ++i) { - float input = channelData[i]; - float output = b0 * input + b1 * x1 + b2 * x2 - a1 * y1 - a2 * y2; + for (float &sample : channel) { + auto input = sample; + auto output = b0 * input + b1 * x1 + b2 * x2 - a1 * y1 - a2 * y2; - channelData[i] = output; + // Avoid denormalized numbers + if (std::abs(output) < 1e-15f) { + output = 0.0f; + } + + sample = output; x2 = x1; x1 = input; y2 = y1; y1 = output; } + x1_[c] = x1; x2_[c] = x2; y1_[c] = y1; diff --git a/packages/react-native-audio-api/common/cpp/audioapi/core/effects/BiquadFilterNode.h b/packages/react-native-audio-api/common/cpp/audioapi/core/effects/BiquadFilterNode.h index 38f140c3e..287e4ca53 100644 --- a/packages/react-native-audio-api/common/cpp/audioapi/core/effects/BiquadFilterNode.h +++ b/packages/react-native-audio-api/common/cpp/audioapi/core/effects/BiquadFilterNode.h @@ -45,7 +45,7 @@ namespace audioapi { -class AudioBus; +class AudioBuffer; struct BiquadFilterOptions; class BiquadFilterNode : public AudioNode { @@ -72,8 +72,8 @@ class BiquadFilterNode : public AudioNode { size_t length); protected: - std::shared_ptr processNode( - const std::shared_ptr &processingBus, + std::shared_ptr processNode( + const std::shared_ptr &processingBus, int framesToProcess) override; private: diff --git a/packages/react-native-audio-api/common/cpp/audioapi/core/effects/ConvolverNode.cpp b/packages/react-native-audio-api/common/cpp/audioapi/core/effects/ConvolverNode.cpp index 35077afdd..f107e8041 100644 --- a/packages/react-native-audio-api/common/cpp/audioapi/core/effects/ConvolverNode.cpp +++ b/packages/react-native-audio-api/common/cpp/audioapi/core/effects/ConvolverNode.cpp @@ -1,18 +1,20 @@ #include #include #include -#include #include -#include +#include #include #include +#include #include #include #include #include namespace audioapi { -ConvolverNode::ConvolverNode(const std::shared_ptr& context, const ConvolverOptions &options) +ConvolverNode::ConvolverNode( + const std::shared_ptr &context, + const ConvolverOptions &options) : AudioNode(context, options), gainCalibrationSampleRate_(context->getSampleRate()), remainingSegments_(0), @@ -25,7 +27,7 @@ ConvolverNode::ConvolverNode(const std::shared_ptr& context, c internalBuffer_(nullptr) { setBuffer(options.bus); audioBus_ = - std::make_shared(RENDER_QUANTUM_SIZE, channelCount_, context->getSampleRate()); + std::make_shared(RENDER_QUANTUM_SIZE, channelCount_, context->getSampleRate()); requiresTailProcessing_ = true; isInitialized_ = true; } @@ -58,20 +60,18 @@ void ConvolverNode::setBuffer(const std::shared_ptr &buffer) { convolvers_.clear(); for (int i = 0; i < buffer->getNumberOfChannels(); ++i) { convolvers_.emplace_back(); - AudioArray channelData(buffer->getLength()); - memcpy(channelData.getData(), buffer->getChannelData(i), buffer->getLength() * sizeof(float)); - convolvers_.back().init(RENDER_QUANTUM_SIZE, channelData, buffer->getLength()); + AudioArray channelData(*buffer->getChannel(i)); + convolvers_.back().init(RENDER_QUANTUM_SIZE, channelData, buffer->getSize()); } if (buffer->getNumberOfChannels() == 1) { // add one more convolver, because right now input is always stereo convolvers_.emplace_back(); - AudioArray channelData(buffer->getLength()); - memcpy(channelData.getData(), buffer->getChannelData(0), buffer->getLength() * sizeof(float)); - convolvers_.back().init(RENDER_QUANTUM_SIZE, channelData, buffer->getLength()); + AudioArray channelData(*buffer->getChannel(0)); + convolvers_.back().init(RENDER_QUANTUM_SIZE, channelData, buffer->getSize()); } - internalBuffer_ = - std::make_shared(RENDER_QUANTUM_SIZE * 2, channelCount_, buffer->getSampleRate()); - intermediateBus_ = std::make_shared( + internalBuffer_ = std::make_shared( + RENDER_QUANTUM_SIZE * 2, channelCount_, buffer->getSampleRate()); + intermediateBus_ = std::make_shared( RENDER_QUANTUM_SIZE, convolvers_.size(), buffer->getSampleRate()); internalBufferIndex_ = 0; } @@ -85,8 +85,8 @@ void ConvolverNode::onInputDisabled() { } } -std::shared_ptr ConvolverNode::processInputs( - const std::shared_ptr &outputBus, +std::shared_ptr ConvolverNode::processInputs( + const std::shared_ptr &outputBus, int framesToProcess, bool checkIsAlreadyProcessed) { if (internalBufferIndex_ < framesToProcess) { @@ -97,8 +97,8 @@ std::shared_ptr ConvolverNode::processInputs( // processing pipeline: processingBus -> intermediateBus_ -> audioBus_ (mixing // with intermediateBus_) -std::shared_ptr ConvolverNode::processNode( - const std::shared_ptr &processingBus, +std::shared_ptr ConvolverNode::processNode( + const std::shared_ptr &processingBus, int framesToProcess) { if (signalledToStop_) { if (remainingSegments_ > 0) { @@ -112,30 +112,23 @@ std::shared_ptr ConvolverNode::processNode( } if (internalBufferIndex_ < framesToProcess) { performConvolution(processingBus); // result returned to intermediateBus_ - audioBus_->sum(intermediateBus_.get()); + audioBus_->sum(*intermediateBus_); - internalBuffer_->copy(audioBus_.get(), 0, internalBufferIndex_, RENDER_QUANTUM_SIZE); + internalBuffer_->copy(*audioBus_, 0, internalBufferIndex_, RENDER_QUANTUM_SIZE); internalBufferIndex_ += RENDER_QUANTUM_SIZE; } audioBus_->zero(); - audioBus_->copy(internalBuffer_.get(), 0, 0, framesToProcess); + audioBus_->copy(*internalBuffer_, 0, 0, framesToProcess); int remainingFrames = internalBufferIndex_ - framesToProcess; if (remainingFrames > 0) { for (int i = 0; i < internalBuffer_->getNumberOfChannels(); ++i) { - memmove( - internalBuffer_->getChannel(i)->getData(), - internalBuffer_->getChannel(i)->getData() + framesToProcess, - remainingFrames * sizeof(float)); + internalBuffer_->copy(*internalBuffer_, framesToProcess, 0, remainingFrames); } } internalBufferIndex_ -= framesToProcess; for (int i = 0; i < audioBus_->getNumberOfChannels(); ++i) { - dsp::multiplyByScalar( - audioBus_->getChannel(i)->getData(), - scaleFactor_, - audioBus_->getChannel(i)->getData(), - framesToProcess); + audioBus_->getChannel(i)->scale(scaleFactor_); } return audioBus_; @@ -143,13 +136,13 @@ std::shared_ptr ConvolverNode::processNode( void ConvolverNode::calculateNormalizationScale() { int numberOfChannels = buffer_->getNumberOfChannels(); - int length = buffer_->getLength(); + auto length = buffer_->getSize(); float power = 0; for (int channel = 0; channel < numberOfChannels; ++channel) { float channelPower = 0; - auto channelData = buffer_->getChannelData(channel); + auto channelData = buffer_->getChannel(channel)->span(); for (int i = 0; i < length; ++i) { float sample = channelData[i]; channelPower += sample * sample; @@ -166,12 +159,11 @@ void ConvolverNode::calculateNormalizationScale() { scaleFactor_ *= gainCalibrationSampleRate_ / buffer_->getSampleRate(); } -void ConvolverNode::performConvolution(const std::shared_ptr &processingBus) { +void ConvolverNode::performConvolution(const std::shared_ptr &processingBus) { if (processingBus->getNumberOfChannels() == 1) { for (int i = 0; i < convolvers_.size(); ++i) { threadPool_->schedule([&, i] { - convolvers_[i].process( - processingBus->getChannel(0)->getData(), intermediateBus_->getChannel(i)->getData()); + convolvers_[i].process(*processingBus->getChannel(0), *intermediateBus_->getChannel(i)); }); } } else if (processingBus->getNumberOfChannels() == 2) { @@ -187,8 +179,8 @@ void ConvolverNode::performConvolution(const std::shared_ptr &processi for (int i = 0; i < convolvers_.size(); ++i) { threadPool_->schedule([this, i, inputChannelMap, outputChannelMap, &processingBus] { convolvers_[i].process( - processingBus->getChannel(inputChannelMap[i])->getData(), - intermediateBus_->getChannel(outputChannelMap[i])->getData()); + *processingBus->getChannel(inputChannelMap[i]), + *intermediateBus_->getChannel(outputChannelMap[i])); }); } } diff --git a/packages/react-native-audio-api/common/cpp/audioapi/core/effects/ConvolverNode.h b/packages/react-native-audio-api/common/cpp/audioapi/core/effects/ConvolverNode.h index 5a705787e..33054f524 100644 --- a/packages/react-native-audio-api/common/cpp/audioapi/core/effects/ConvolverNode.h +++ b/packages/react-native-audio-api/common/cpp/audioapi/core/effects/ConvolverNode.h @@ -15,7 +15,7 @@ static constexpr double MIN_IR_POWER = 0.000125; namespace audioapi { -class AudioBus; +class AudioBuffer; class AudioBuffer; struct ConvolverOptions; @@ -31,13 +31,13 @@ class ConvolverNode : public AudioNode { void setBuffer(const std::shared_ptr &buffer); protected: - std::shared_ptr processNode( - const std::shared_ptr &processingBus, + std::shared_ptr processNode( + const std::shared_ptr &processingBus, int framesToProcess) override; private: - std::shared_ptr processInputs( - const std::shared_ptr &outputBus, + std::shared_ptr processInputs( + const std::shared_ptr &outputBus, int framesToProcess, bool checkIsAlreadyProcessed) override; void onInputDisabled() override; @@ -47,18 +47,18 @@ class ConvolverNode : public AudioNode { bool normalize_; bool signalledToStop_; float scaleFactor_; - std::shared_ptr intermediateBus_; + std::shared_ptr intermediateBus_; // impulse response buffer std::shared_ptr buffer_; // buffer to hold internal processed data - std::shared_ptr internalBuffer_; + std::shared_ptr internalBuffer_; // vectors of convolvers, one per channel std::vector convolvers_; std::shared_ptr threadPool_; void calculateNormalizationScale(); - void performConvolution(const std::shared_ptr &processingBus); + void performConvolution(const std::shared_ptr &processingBus); }; } // namespace audioapi diff --git a/packages/react-native-audio-api/common/cpp/audioapi/core/effects/DelayNode.cpp b/packages/react-native-audio-api/common/cpp/audioapi/core/effects/DelayNode.cpp index 04a4dd886..019a15dd2 100644 --- a/packages/react-native-audio-api/common/cpp/audioapi/core/effects/DelayNode.cpp +++ b/packages/react-native-audio-api/common/cpp/audioapi/core/effects/DelayNode.cpp @@ -3,16 +3,17 @@ #include #include #include -#include +#include #include namespace audioapi { -DelayNode::DelayNode(const std::shared_ptr& context, const DelayOptions &options) +DelayNode::DelayNode(const std::shared_ptr &context, const DelayOptions &options) : AudioNode(context, options), - delayTimeParam_(std::make_shared(options.delayTime, 0, options.maxDelayTime, context)), + delayTimeParam_( + std::make_shared(options.delayTime, 0, options.maxDelayTime, context)), delayBuffer_( - std::make_shared( + std::make_shared( static_cast( options.maxDelayTime * context->getSampleRate() + 1), // +1 to enable delayTime equal to maxDelayTime @@ -39,7 +40,7 @@ void DelayNode::onInputDisabled() { } void DelayNode::delayBufferOperation( - const std::shared_ptr &processingBus, + const std::shared_ptr &processingBus, int framesToProcess, size_t &operationStartingIndex, DelayNode::BufferAction action) { @@ -51,10 +52,10 @@ void DelayNode::delayBufferOperation( if (action == BufferAction::WRITE) { delayBuffer_->sum( - processingBus.get(), processingBusStartIndex, operationStartingIndex, framesToEnd); + *processingBus, processingBusStartIndex, operationStartingIndex, framesToEnd); } else { // READ processingBus->sum( - delayBuffer_.get(), operationStartingIndex, processingBusStartIndex, framesToEnd); + *delayBuffer_, operationStartingIndex, processingBusStartIndex, framesToEnd); } operationStartingIndex = 0; @@ -64,11 +65,11 @@ void DelayNode::delayBufferOperation( if (action == BufferAction::WRITE) { delayBuffer_->sum( - processingBus.get(), processingBusStartIndex, operationStartingIndex, framesToProcess); + *processingBus, processingBusStartIndex, operationStartingIndex, framesToProcess); processingBus->zero(); } else { // READ processingBus->sum( - delayBuffer_.get(), operationStartingIndex, processingBusStartIndex, framesToProcess); + *delayBuffer_, operationStartingIndex, processingBusStartIndex, framesToProcess); delayBuffer_->zero(operationStartingIndex, framesToProcess); } @@ -79,8 +80,8 @@ void DelayNode::delayBufferOperation( // processing is split into two parts // 1. writing to delay buffer (mixing if needed) from processing bus // 2. reading from delay buffer to processing bus (mixing if needed) with delay -std::shared_ptr DelayNode::processNode( - const std::shared_ptr &processingBus, +std::shared_ptr DelayNode::processNode( + const std::shared_ptr &processingBus, int framesToProcess) { // handling tail processing if (signalledToStop_) { diff --git a/packages/react-native-audio-api/common/cpp/audioapi/core/effects/DelayNode.h b/packages/react-native-audio-api/common/cpp/audioapi/core/effects/DelayNode.h index 0d280e0fd..a44a77007 100644 --- a/packages/react-native-audio-api/common/cpp/audioapi/core/effects/DelayNode.h +++ b/packages/react-native-audio-api/common/cpp/audioapi/core/effects/DelayNode.h @@ -8,7 +8,7 @@ namespace audioapi { -class AudioBus; +class AudioBuffer; struct DelayOptions; class DelayNode : public AudioNode { @@ -18,20 +18,20 @@ class DelayNode : public AudioNode { [[nodiscard]] std::shared_ptr getDelayTimeParam() const; protected: - std::shared_ptr processNode( - const std::shared_ptr &processingBus, + std::shared_ptr processNode( + const std::shared_ptr &processingBus, int framesToProcess) override; private: void onInputDisabled() override; enum class BufferAction { READ, WRITE }; void delayBufferOperation( - const std::shared_ptr &processingBus, + const std::shared_ptr &processingBus, int framesToProcess, size_t &operationStartingIndex, BufferAction action); std::shared_ptr delayTimeParam_; - std::shared_ptr delayBuffer_; + std::shared_ptr delayBuffer_; size_t readIndex_ = 0; bool signalledToStop_ = false; int remainingFrames_ = 0; diff --git a/packages/react-native-audio-api/common/cpp/audioapi/core/effects/GainNode.cpp b/packages/react-native-audio-api/common/cpp/audioapi/core/effects/GainNode.cpp index 57da13581..e538a1187 100644 --- a/packages/react-native-audio-api/common/cpp/audioapi/core/effects/GainNode.cpp +++ b/packages/react-native-audio-api/common/cpp/audioapi/core/effects/GainNode.cpp @@ -3,7 +3,7 @@ #include #include #include -#include +#include #include namespace audioapi { @@ -23,8 +23,8 @@ std::shared_ptr GainNode::getGainParam() const { return gainParam_; } -std::shared_ptr GainNode::processNode( - const std::shared_ptr &processingBus, +std::shared_ptr GainNode::processNode( + const std::shared_ptr &processingBus, int framesToProcess) { std::shared_ptr context = context_.lock(); if (context == nullptr) @@ -32,11 +32,9 @@ std::shared_ptr GainNode::processNode( double time = context->getCurrentTime(); auto gainParamValues = gainParam_->processARateParam(framesToProcess, time); for (int i = 0; i < processingBus->getNumberOfChannels(); i += 1) { - dsp::multiply( - processingBus->getChannel(i)->getData(), - gainParamValues->getChannel(0)->getData(), - processingBus->getChannel(i)->getData(), - framesToProcess); + auto channel = processingBus->getChannel(i); + auto gainValues = gainParamValues->getChannel(0); + channel->multiply(*gainValues, framesToProcess); } return processingBus; diff --git a/packages/react-native-audio-api/common/cpp/audioapi/core/effects/GainNode.h b/packages/react-native-audio-api/common/cpp/audioapi/core/effects/GainNode.h index b224f8f55..928d5a5fc 100644 --- a/packages/react-native-audio-api/common/cpp/audioapi/core/effects/GainNode.h +++ b/packages/react-native-audio-api/common/cpp/audioapi/core/effects/GainNode.h @@ -7,7 +7,7 @@ namespace audioapi { -class AudioBus; +class AudioBuffer; struct GainOptions; class GainNode : public AudioNode { @@ -17,8 +17,8 @@ class GainNode : public AudioNode { [[nodiscard]] std::shared_ptr getGainParam() const; protected: - std::shared_ptr processNode( - const std::shared_ptr &processingBus, + std::shared_ptr processNode( + const std::shared_ptr &processingBus, int framesToProcess) override; private: diff --git a/packages/react-native-audio-api/common/cpp/audioapi/core/effects/IIRFilterNode.cpp b/packages/react-native-audio-api/common/cpp/audioapi/core/effects/IIRFilterNode.cpp index 467098bf1..a1a160850 100644 --- a/packages/react-native-audio-api/common/cpp/audioapi/core/effects/IIRFilterNode.cpp +++ b/packages/react-native-audio-api/common/cpp/audioapi/core/effects/IIRFilterNode.cpp @@ -28,7 +28,7 @@ #include #include #include -#include +#include #include #include #include @@ -39,9 +39,7 @@ namespace audioapi { IIRFilterNode::IIRFilterNode( const std::shared_ptr &context, const IIRFilterOptions &options) - : AudioNode(context, options), - feedforward_(std::move(options.feedforward)), - feedback_(std::move(options.feedback)) { + : AudioNode(context, options), feedforward_(options.feedforward), feedback_(options.feedback) { int maxChannels = MAX_CHANNEL_COUNT; xBuffers_.resize(maxChannels); @@ -123,8 +121,8 @@ void IIRFilterNode::getFrequencyResponse( // TODO: tail -std::shared_ptr IIRFilterNode::processNode( - const std::shared_ptr &processingBus, +std::shared_ptr IIRFilterNode::processNode( + const std::shared_ptr &processingBus, int framesToProcess) { int numChannels = processingBus->getNumberOfChannels(); @@ -135,31 +133,38 @@ std::shared_ptr IIRFilterNode::processNode( int mask = bufferLength - 1; for (int c = 0; c < numChannels; ++c) { - auto channelData = processingBus->getChannel(c)->getData(); + auto channel = processingBus->getChannel(c)->subSpan(0, framesToProcess); + auto &x = xBuffers_[c]; auto &y = yBuffers_[c]; size_t bufferIndex = bufferIndices[c]; - for (int n = 0; n < framesToProcess; ++n) { - float yn = feedforward_[0] * channelData[n]; + for (float &sample : channel) { + const float x_n = sample; + float y_n = feedforward_[0] * sample; for (int k = 1; k < minLength; ++k) { int m = (bufferIndex - k) & mask; - yn = std::fma(feedforward_[k], x[m], yn); - yn = std::fma(-feedback_[k], y[m], yn); + y_n = std::fma(feedforward_[k], x[m], y_n); + y_n = std::fma(-feedback_[k], y[m], y_n); } for (int k = minLength; k < feedforwardLength; ++k) { - yn = std::fma(feedforward_[k], x[(bufferIndex - k) & mask], yn); + y_n = std::fma(feedforward_[k], x[(bufferIndex - k) & mask], y_n); } for (int k = minLength; k < feedbackLength; ++k) { - yn = std::fma(-feedback_[k], y[(bufferIndex - k) & (bufferLength - 1)], yn); + y_n = std::fma(-feedback_[k], y[(bufferIndex - k) & (bufferLength - 1)], y_n); + } + + // Avoid denormalized numbers + if (std::abs(y_n) < 1e-15f) { + y_n = 0.0f; } - channelData[n] = yn; + sample = y_n; - x[bufferIndex] = channelData[n]; - y[bufferIndex] = yn; + x[bufferIndex] = x_n; + y[bufferIndex] = y_n; bufferIndex = (bufferIndex + 1) & (bufferLength - 1); } diff --git a/packages/react-native-audio-api/common/cpp/audioapi/core/effects/IIRFilterNode.h b/packages/react-native-audio-api/common/cpp/audioapi/core/effects/IIRFilterNode.h index 4ac80bf8b..8d6b44937 100644 --- a/packages/react-native-audio-api/common/cpp/audioapi/core/effects/IIRFilterNode.h +++ b/packages/react-native-audio-api/common/cpp/audioapi/core/effects/IIRFilterNode.h @@ -49,8 +49,8 @@ class IIRFilterNode : public AudioNode { size_t length); protected: - std::shared_ptr processNode( - const std::shared_ptr &processingBus, + std::shared_ptr processNode( + const std::shared_ptr &processingBus, int framesToProcess) override; private: diff --git a/packages/react-native-audio-api/common/cpp/audioapi/core/effects/PeriodicWave.cpp b/packages/react-native-audio-api/common/cpp/audioapi/core/effects/PeriodicWave.cpp index 07bbcd86e..423c21789 100644 --- a/packages/react-native-audio-api/common/cpp/audioapi/core/effects/PeriodicWave.cpp +++ b/packages/react-native-audio-api/common/cpp/audioapi/core/effects/PeriodicWave.cpp @@ -47,7 +47,8 @@ PeriodicWave::PeriodicWave(float sampleRate, bool disableNormalization) lowestFundamentalFrequency_ = static_cast(nyquistFrequency) / static_cast(getMaxNumberOfPartials()); scale_ = static_cast(getPeriodicWaveSize()) / static_cast(sampleRate_); - bandLimitedTables_ = new float *[numberOfRanges_]; + bandLimitedTables_ = + std::make_unique(getPeriodicWaveSize(), numberOfRanges_, sampleRate_); fft_ = std::make_unique(getPeriodicWaveSize()); } @@ -69,14 +70,6 @@ PeriodicWave::PeriodicWave( createBandLimitedTables(complexData, length); } -PeriodicWave::~PeriodicWave() { - for (int i = 0; i < numberOfRanges_; i++) { - delete[] bandLimitedTables_[i]; - } - delete[] bandLimitedTables_; - bandLimitedTables_ = nullptr; -} - int PeriodicWave::getPeriodicWaveSize() const { if (sampleRate_ <= 24000) { return 2048; @@ -94,13 +87,10 @@ float PeriodicWave::getScale() const { } float PeriodicWave::getSample(float fundamentalFrequency, float phase, float phaseIncrement) { - float *lowerWaveData = nullptr; - float *higherWaveData = nullptr; + WaveTableSource source = getWaveDataForFundamentalFrequency(fundamentalFrequency); - auto interpolationFactor = - getWaveDataForFundamentalFrequency(fundamentalFrequency, lowerWaveData, higherWaveData); - - return doInterpolation(phase, phaseIncrement, interpolationFactor, lowerWaveData, higherWaveData); + return doInterpolation( + phase, phaseIncrement, source.interpolationFactor, *source.lower, *source.higher); } int PeriodicWave::getMaxNumberOfPartials() const { @@ -217,31 +207,24 @@ void PeriodicWave::createBandLimitedTables( // Zero out the DC and nquist components. complexFFTData[0] = {0.0f, 0.0f}; - bandLimitedTables_[rangeIndex] = new float[fftSize]; + auto channel = bandLimitedTables_->getChannel(rangeIndex); // Perform the inverse FFT to get the time domain representation of the // band-limited waveform. - fft_->doInverseFFT(complexFFTData, bandLimitedTables_[rangeIndex]); + fft_->doInverseFFT(complexFFTData, *channel); if (!disableNormalization_ && rangeIndex == 0) { - float maxValue = dsp::maximumMagnitude(bandLimitedTables_[rangeIndex], fftSize); + float maxValue = channel->getMaxAbsValue(); if (maxValue != 0) { normalizationFactor = 1.0f / maxValue; } } - dsp::multiplyByScalar( - bandLimitedTables_[rangeIndex], - normalizationFactor, - bandLimitedTables_[rangeIndex], - fftSize); + channel->scale(normalizationFactor); } } -float PeriodicWave::getWaveDataForFundamentalFrequency( - float fundamentalFrequency, - float *&lowerWaveData, - float *&higherWaveData) { +WaveTableSource PeriodicWave::getWaveDataForFundamentalFrequency(float fundamentalFrequency) const { // negative frequencies are allowed and will be treated as positive. fundamentalFrequency = std::fabs(fundamentalFrequency); @@ -260,19 +243,19 @@ float PeriodicWave::getWaveDataForFundamentalFrequency( lowerRangeIndex < numberOfRanges_ - 1 ? lowerRangeIndex + 1 : lowerRangeIndex; // get the wave data for the lower and higher range index. - lowerWaveData = bandLimitedTables_[lowerRangeIndex]; - higherWaveData = bandLimitedTables_[higherRangeIndex]; - // calculate the interpolation factor between the lower and higher range data. - return pitchRange - static_cast(lowerRangeIndex); + return { + bandLimitedTables_->getChannel(lowerRangeIndex), + bandLimitedTables_->getChannel(higherRangeIndex), + pitchRange - static_cast(lowerRangeIndex)}; } float PeriodicWave::doInterpolation( float phase, float phaseIncrement, float waveTableInterpolationFactor, - const float *lowerWaveData, - const float *higherWaveData) const { + const AudioArray &lowerWaveData, + const AudioArray &higherWaveData) const { float lowerWaveDataSample = 0; float higherWaveDataSample = 0; @@ -336,7 +319,6 @@ float PeriodicWave::doInterpolation( } } - return (1 - waveTableInterpolationFactor) * higherWaveDataSample + - waveTableInterpolationFactor * lowerWaveDataSample; + return std::lerp(higherWaveDataSample, lowerWaveDataSample, waveTableInterpolationFactor); } } // namespace audioapi diff --git a/packages/react-native-audio-api/common/cpp/audioapi/core/effects/PeriodicWave.h b/packages/react-native-audio-api/common/cpp/audioapi/core/effects/PeriodicWave.h index e04b83dae..d39cb1e15 100644 --- a/packages/react-native-audio-api/common/cpp/audioapi/core/effects/PeriodicWave.h +++ b/packages/react-native-audio-api/common/cpp/audioapi/core/effects/PeriodicWave.h @@ -30,6 +30,7 @@ #include #include +#include #include #include @@ -38,6 +39,13 @@ #include namespace audioapi { + +struct WaveTableSource { + const AudioArray *lower; + const AudioArray *higher; + float interpolationFactor; +}; + class PeriodicWave { public: explicit PeriodicWave(float sampleRate, OscillatorType type, bool disableNormalization); @@ -46,7 +54,6 @@ class PeriodicWave { const std::vector> &complexData, int length, bool disableNormalization); - ~PeriodicWave(); [[nodiscard]] int getPeriodicWaveSize() const; [[nodiscard]] float getScale() const; @@ -81,21 +88,18 @@ class PeriodicWave { // This function returns the interpolation factor between the lower and higher // range data and sets the lower and higher wave data for the given // fundamental frequency. - float getWaveDataForFundamentalFrequency( - float fundamentalFrequency, - float *&lowerWaveData, - float *&higherWaveData); + WaveTableSource getWaveDataForFundamentalFrequency(float fundamentalFrequency) const; // This function performs interpolation between the lower and higher range // data based on the interpolation factor and current buffer index. Type of // interpolation is determined by the phase increment. Returns the // interpolated sample. - float doInterpolation( + [[nodiscard]] float doInterpolation( float bufferIndex, float phaseIncrement, float waveTableInterpolationFactor, - const float *lowerWaveData, - const float *higherWaveData) const; + const AudioArray &lowerWaveData, + const AudioArray &higherWaveData) const; // determines the time resolution of the waveform. float sampleRate_; @@ -108,8 +112,7 @@ class PeriodicWave { // rate. float scale_; // array of band-limited waveforms. - float **bandLimitedTables_; - // + std::unique_ptr bandLimitedTables_; std::unique_ptr fft_; // if true, the waveTable is not normalized. bool disableNormalization_; diff --git a/packages/react-native-audio-api/common/cpp/audioapi/core/effects/StereoPannerNode.cpp b/packages/react-native-audio-api/common/cpp/audioapi/core/effects/StereoPannerNode.cpp index ca6b0ad47..be31dd231 100644 --- a/packages/react-native-audio-api/common/cpp/audioapi/core/effects/StereoPannerNode.cpp +++ b/packages/react-native-audio-api/common/cpp/audioapi/core/effects/StereoPannerNode.cpp @@ -3,7 +3,7 @@ #include #include #include -#include +#include #include // https://webaudio.github.io/web-audio-api/#stereopanner-algorithm @@ -22,8 +22,8 @@ std::shared_ptr StereoPannerNode::getPanParam() const { return panParam_; } -std::shared_ptr StereoPannerNode::processNode( - const std::shared_ptr &processingBus, +std::shared_ptr StereoPannerNode::processNode( + const std::shared_ptr &processingBus, int framesToProcess) { std::shared_ptr context = context_.lock(); if (context == nullptr) @@ -31,46 +31,43 @@ std::shared_ptr StereoPannerNode::processNode( double time = context->getCurrentTime(); double deltaTime = 1.0 / context->getSampleRate(); - auto *inputLeft = processingBus->getChannelByType(AudioBus::ChannelLeft); - auto panParamValues = - panParam_->processARateParam(framesToProcess, time)->getChannel(0)->getData(); + auto panParamValues = panParam_->processARateParam(framesToProcess, time)->getChannel(0)->span(); - auto *outputLeft = audioBus_->getChannelByType(AudioBus::ChannelLeft); - auto *outputRight = audioBus_->getChannelByType(AudioBus::ChannelRight); + auto outputLeft = audioBus_->getChannelByType(AudioBuffer::ChannelLeft)->span(); + auto outputRight = audioBus_->getChannelByType(AudioBuffer::ChannelRight)->span(); // Input is mono if (processingBus->getNumberOfChannels() == 1) { - for (int i = 0; i < framesToProcess; i++) { - auto pan = std::clamp(panParamValues[i], -1.0f, 1.0f); - auto x = (pan + 1) / 2; - - auto gainL = static_cast(cos(x * PI / 2)); - auto gainR = static_cast(sin(x * PI / 2)); + auto inputLeft = processingBus->getChannelByType(AudioBuffer::ChannelMono)->span(); - float input = (*inputLeft)[i]; + for (int i = 0; i < framesToProcess; i++) { + const auto pan = std::clamp(panParamValues[i], -1.0f, 1.0f); + const auto x = (pan + 1) / 2; + const auto angle = x * (PI / 2); + const float input = inputLeft[i]; - (*outputLeft)[i] = input * gainL; - (*outputRight)[i] = input * gainR; + outputLeft[i] = input * std::cos(angle); + outputRight[i] = input * std::sin(angle); time += deltaTime; } } else { // Input is stereo - auto *inputRight = processingBus->getChannelByType(AudioBus::ChannelRight); - for (int i = 0; i < framesToProcess; i++) { - auto pan = std::clamp(panParamValues[i], -1.0f, 1.0f); - auto x = (pan <= 0 ? pan + 1 : pan); - - auto gainL = static_cast(cos(x * PI / 2)); - auto gainR = static_cast(sin(x * PI / 2)); + auto inputLeft = processingBus->getChannelByType(AudioBuffer::ChannelMono)->span(); + auto inputRight = processingBus->getChannelByType(AudioBuffer::ChannelRight)->span(); - float inputL = (*inputLeft)[i]; - float inputR = (*inputRight)[i]; + for (int i = 0; i < framesToProcess; i++) { + const auto pan = std::clamp(panParamValues[i], -1.0f, 1.0f); + const auto x = (pan <= 0 ? pan + 1 : pan); + const auto gainL = static_cast(cos(x * PI / 2)); + const auto gainR = static_cast(sin(x * PI / 2)); + const float inputL = inputLeft[i]; + const float inputR = inputRight[i]; if (pan <= 0) { - (*outputLeft)[i] = inputL + inputR * gainL; - (*outputRight)[i] = inputR * gainR; + outputLeft[i] = inputL + inputR * gainL; + outputRight[i] = inputR * gainR; } else { - (*outputLeft)[i] = inputL * gainL; - (*outputRight)[i] = inputR + inputL * gainR; + outputLeft[i] = inputL * gainL; + outputRight[i] = inputR + inputL * gainR; } time += deltaTime; diff --git a/packages/react-native-audio-api/common/cpp/audioapi/core/effects/StereoPannerNode.h b/packages/react-native-audio-api/common/cpp/audioapi/core/effects/StereoPannerNode.h index 6f79ecb52..da99cbe13 100644 --- a/packages/react-native-audio-api/common/cpp/audioapi/core/effects/StereoPannerNode.h +++ b/packages/react-native-audio-api/common/cpp/audioapi/core/effects/StereoPannerNode.h @@ -9,7 +9,7 @@ namespace audioapi { -class AudioBus; +class AudioBuffer; struct StereoPannerOptions; class StereoPannerNode : public AudioNode { @@ -21,8 +21,8 @@ class StereoPannerNode : public AudioNode { [[nodiscard]] std::shared_ptr getPanParam() const; protected: - std::shared_ptr processNode( - const std::shared_ptr &processingBus, + std::shared_ptr processNode( + const std::shared_ptr &processingBus, int framesToProcess) override; private: diff --git a/packages/react-native-audio-api/common/cpp/audioapi/core/effects/WaveShaperNode.cpp b/packages/react-native-audio-api/common/cpp/audioapi/core/effects/WaveShaperNode.cpp index e16198b4b..70bc34cec 100644 --- a/packages/react-native-audio-api/common/cpp/audioapi/core/effects/WaveShaperNode.cpp +++ b/packages/react-native-audio-api/common/cpp/audioapi/core/effects/WaveShaperNode.cpp @@ -2,8 +2,8 @@ #include #include #include -#include -#include +#include +#include #include #include @@ -39,12 +39,12 @@ void WaveShaperNode::setOversample(OverSampleType type) { } } -std::shared_ptr WaveShaperNode::getCurve() const { +std::shared_ptr WaveShaperNode::getCurve() const { std::scoped_lock lock(mutex_); return curve_; } -void WaveShaperNode::setCurve(const std::shared_ptr &curve) { +void WaveShaperNode::setCurve(const std::shared_ptr &curve) { std::scoped_lock lock(mutex_); curve_ = curve; @@ -53,8 +53,8 @@ void WaveShaperNode::setCurve(const std::shared_ptr &curve) { } } -std::shared_ptr WaveShaperNode::processNode( - const std::shared_ptr &processingBus, +std::shared_ptr WaveShaperNode::processNode( + const std::shared_ptr &processingBus, int framesToProcess) { if (!isInitialized_) { return processingBus; @@ -71,9 +71,9 @@ std::shared_ptr WaveShaperNode::processNode( } for (int channel = 0; channel < processingBus->getNumberOfChannels(); channel++) { - auto channelData = processingBus->getSharedChannel(channel); + auto channelData = processingBus->getChannel(channel); - waveShapers_[channel]->process(channelData, framesToProcess); + waveShapers_[channel]->process(*channelData, framesToProcess); } return processingBus; diff --git a/packages/react-native-audio-api/common/cpp/audioapi/core/effects/WaveShaperNode.h b/packages/react-native-audio-api/common/cpp/audioapi/core/effects/WaveShaperNode.h index d1620e02a..759b706fb 100644 --- a/packages/react-native-audio-api/common/cpp/audioapi/core/effects/WaveShaperNode.h +++ b/packages/react-native-audio-api/common/cpp/audioapi/core/effects/WaveShaperNode.h @@ -14,8 +14,8 @@ namespace audioapi { -class AudioBus; -class AudioArray; +class AudioBuffer; +class AudioArrayBuffer; struct WaveShaperOptions; class WaveShaperNode : public AudioNode { @@ -25,19 +25,19 @@ class WaveShaperNode : public AudioNode { const WaveShaperOptions &options); [[nodiscard]] OverSampleType getOversample() const; - [[nodiscard]] std::shared_ptr getCurve() const; + [[nodiscard]] std::shared_ptr getCurve() const; void setOversample(OverSampleType); - void setCurve(const std::shared_ptr &curve); + void setCurve(const std::shared_ptr &curve); protected: - std::shared_ptr processNode( - const std::shared_ptr &processingBus, + std::shared_ptr processNode( + const std::shared_ptr &processingBus, int framesToProcess) override; private: std::atomic oversample_; - std::shared_ptr curve_{}; + std::shared_ptr curve_; mutable std::mutex mutex_; std::vector> waveShapers_{}; diff --git a/packages/react-native-audio-api/common/cpp/audioapi/core/effects/WorkletNode.cpp b/packages/react-native-audio-api/common/cpp/audioapi/core/effects/WorkletNode.cpp index 1a76ea72e..befb84c23 100644 --- a/packages/react-native-audio-api/common/cpp/audioapi/core/effects/WorkletNode.cpp +++ b/packages/react-native-audio-api/common/cpp/audioapi/core/effects/WorkletNode.cpp @@ -7,21 +7,22 @@ namespace audioapi { WorkletNode::WorkletNode( - std::shared_ptr context, + const std::shared_ptr &context, size_t bufferLength, size_t inputChannelCount, WorkletsRunner &&runtime) : AudioNode(context), workletRunner_(std::move(runtime)), - bus_(std::make_shared(bufferLength, inputChannelCount, context->getSampleRate())), + bus_( + std::make_shared(bufferLength, inputChannelCount, context->getSampleRate())), bufferLength_(bufferLength), inputChannelCount_(inputChannelCount), curBuffIndex_(0) { isInitialized_ = true; } -std::shared_ptr WorkletNode::processNode( - const std::shared_ptr &processingBus, +std::shared_ptr WorkletNode::processNode( + const std::shared_ptr &processingBus, int framesToProcess) { size_t processed = 0; size_t channelCount_ = @@ -34,7 +35,7 @@ std::shared_ptr WorkletNode::processNode( /// here we copy /// to [curBuffIndex_, curBuffIndex_ + shouldProcess] /// from [processed, processed + shouldProcess] - bus_->copy(processingBus.get(), processed, curBuffIndex_, shouldProcess); + bus_->copy(*processingBus, processed, curBuffIndex_, shouldProcess); processed += shouldProcess; curBuffIndex_ += shouldProcess; @@ -48,10 +49,9 @@ std::shared_ptr WorkletNode::processNode( workletRunner_.executeOnRuntimeSync([this, channelCount_](jsi::Runtime &uiRuntimeRaw) { /// Arguments preparation auto jsArray = jsi::Array(uiRuntimeRaw, channelCount_); - for (size_t ch = 0; ch < channelCount_; ch++) { - auto audioArray = std::make_shared(bufferLength_); - audioArray->copy(bus_->getChannel(ch)); - auto sharedAudioArray = std::make_shared(audioArray); + for (int ch = 0; ch < channelCount_; ch++) { + auto sharedAudioArray = std::make_shared(bufferLength_); + sharedAudioArray->copy(*bus_->getChannel(ch)); auto sharedAudioArraySize = sharedAudioArray->size(); auto arrayBuffer = jsi::ArrayBuffer(uiRuntimeRaw, std::move(sharedAudioArray)); arrayBuffer.setExternalMemoryPressure(uiRuntimeRaw, sharedAudioArraySize); diff --git a/packages/react-native-audio-api/common/cpp/audioapi/core/effects/WorkletNode.h b/packages/react-native-audio-api/common/cpp/audioapi/core/effects/WorkletNode.h index a830acb7e..f42bd6f3b 100644 --- a/packages/react-native-audio-api/common/cpp/audioapi/core/effects/WorkletNode.h +++ b/packages/react-native-audio-api/common/cpp/audioapi/core/effects/WorkletNode.h @@ -3,9 +3,9 @@ #include #include #include -#include #include -#include +#include +#include #include #include @@ -24,8 +24,8 @@ class WorkletNode : public AudioNode { : AudioNode(context) {} protected: - std::shared_ptr processNode( - const std::shared_ptr &processingBus, + std::shared_ptr processNode( + const std::shared_ptr &processingBus, int framesToProcess) override { return processingBus; } @@ -37,7 +37,7 @@ using namespace facebook; class WorkletNode : public AudioNode { public: explicit WorkletNode( - std::shared_ptr context, + const std::shared_ptr &context, size_t bufferLength, size_t inputChannelCount, WorkletsRunner &&workletRunner); @@ -45,13 +45,13 @@ class WorkletNode : public AudioNode { ~WorkletNode() override = default; protected: - std::shared_ptr processNode( - const std::shared_ptr &processingBus, + std::shared_ptr processNode( + const std::shared_ptr &processingBus, int framesToProcess) override; private: WorkletsRunner workletRunner_; - std::shared_ptr bus_; + std::shared_ptr bus_; /// @brief Length of the byte buffer that will be passed to the AudioArrayBuffer size_t bufferLength_; diff --git a/packages/react-native-audio-api/common/cpp/audioapi/core/effects/WorkletProcessingNode.cpp b/packages/react-native-audio-api/common/cpp/audioapi/core/effects/WorkletProcessingNode.cpp index e385f7b89..cc3f12b1d 100644 --- a/packages/react-native-audio-api/common/cpp/audioapi/core/effects/WorkletProcessingNode.cpp +++ b/packages/react-native-audio-api/common/cpp/audioapi/core/effects/WorkletProcessingNode.cpp @@ -6,7 +6,7 @@ namespace audioapi { WorkletProcessingNode::WorkletProcessingNode( - std::shared_ptr context, + const std::shared_ptr &context, WorkletsRunner &&workletRunner) : AudioNode(context), workletRunner_(std::move(workletRunner)) { // Pre-allocate buffers for max 128 frames and 2 channels (stereo) @@ -15,29 +15,22 @@ WorkletProcessingNode::WorkletProcessingNode( outputBuffsHandles_.resize(maxChannelCount); for (size_t i = 0; i < maxChannelCount; ++i) { - auto inputAudioArray = std::make_shared(RENDER_QUANTUM_SIZE); - inputBuffsHandles_[i] = std::make_shared(inputAudioArray); - - auto outputAudioArray = std::make_shared(RENDER_QUANTUM_SIZE); - outputBuffsHandles_[i] = std::make_shared(outputAudioArray); + inputBuffsHandles_[i] = std::make_shared(RENDER_QUANTUM_SIZE); + outputBuffsHandles_[i] = std::make_shared(RENDER_QUANTUM_SIZE); } isInitialized_ = true; } -std::shared_ptr WorkletProcessingNode::processNode( - const std::shared_ptr &processingBus, +std::shared_ptr WorkletProcessingNode::processNode( + const std::shared_ptr &processingBus, int framesToProcess) { size_t channelCount = std::min( static_cast(2), // Fixed to stereo for now static_cast(processingBus->getNumberOfChannels())); // Copy input data to pre-allocated input buffers - for (size_t ch = 0; ch < channelCount; ch++) { - auto channelData = processingBus->getChannel(ch)->getData(); - std::memcpy( - /* dest */ inputBuffsHandles_[ch]->data(), - /* src */ reinterpret_cast(channelData), - /* size */ framesToProcess * sizeof(float)); + for (int ch = 0; ch < channelCount; ch++) { + inputBuffsHandles_[ch]->copy(*processingBus->getChannel(ch), 0, 0, framesToProcess); } // Execute the worklet @@ -71,18 +64,15 @@ std::shared_ptr WorkletProcessingNode::processNode( }); // Copy processed output data back to the processing bus or zero on failure - for (size_t ch = 0; ch < channelCount; ch++) { - auto channelData = processingBus->getChannel(ch)->getData(); + for (int ch = 0; ch < channelCount; ch++) { + auto channelData = processingBus->getChannel(ch); if (result.has_value()) { // Copy processed output data - std::memcpy( - /* dest */ reinterpret_cast(channelData), - /* src */ outputBuffsHandles_[ch]->data(), - /* size */ framesToProcess * sizeof(float)); + channelData->copy(*inputBuffsHandles_[ch], 0, 0, framesToProcess); } else { // Zero the output on worklet execution failure - std::memset(channelData, 0, framesToProcess * sizeof(float)); + channelData->zero(0, framesToProcess); } } diff --git a/packages/react-native-audio-api/common/cpp/audioapi/core/effects/WorkletProcessingNode.h b/packages/react-native-audio-api/common/cpp/audioapi/core/effects/WorkletProcessingNode.h index b302e81bc..5fe43bb8d 100644 --- a/packages/react-native-audio-api/common/cpp/audioapi/core/effects/WorkletProcessingNode.h +++ b/packages/react-native-audio-api/common/cpp/audioapi/core/effects/WorkletProcessingNode.h @@ -3,9 +3,9 @@ #include #include #include -#include #include -#include +#include +#include #include #include @@ -22,8 +22,8 @@ class WorkletProcessingNode : public AudioNode { : AudioNode(context) {} protected: - std::shared_ptr processNode( - const std::shared_ptr &processingBus, + std::shared_ptr processNode( + const std::shared_ptr &processingBus, int framesToProcess) override { return processingBus; } @@ -35,12 +35,12 @@ using namespace facebook; class WorkletProcessingNode : public AudioNode { public: explicit WorkletProcessingNode( - std::shared_ptr context, + const std::shared_ptr &context, WorkletsRunner &&workletRunner); protected: - std::shared_ptr processNode( - const std::shared_ptr &processingBus, + std::shared_ptr processNode( + const std::shared_ptr &processingBus, int framesToProcess) override; private: diff --git a/packages/react-native-audio-api/common/cpp/audioapi/core/inputs/AudioRecorder.h b/packages/react-native-audio-api/common/cpp/audioapi/core/inputs/AudioRecorder.h index b0f1fb89c..c2b196765 100644 --- a/packages/react-native-audio-api/common/cpp/audioapi/core/inputs/AudioRecorder.h +++ b/packages/react-native-audio-api/common/cpp/audioapi/core/inputs/AudioRecorder.h @@ -9,7 +9,7 @@ namespace audioapi { -class AudioBus; +class AudioBuffer; class AudioFileWriter; class CircularAudioArray; class RecorderAdapterNode; diff --git a/packages/react-native-audio-api/common/cpp/audioapi/core/sources/AudioBuffer.cpp b/packages/react-native-audio-api/common/cpp/audioapi/core/sources/AudioBuffer.cpp deleted file mode 100644 index 528ca7703..000000000 --- a/packages/react-native-audio-api/common/cpp/audioapi/core/sources/AudioBuffer.cpp +++ /dev/null @@ -1,61 +0,0 @@ -#include -#include -#include -#include - -#include -#include -#include - -namespace audioapi { - -AudioBuffer::AudioBuffer(const AudioBufferOptions &options) - : bus_(std::make_shared(options.length, options.numberOfChannels, options.sampleRate)) {} - -AudioBuffer::AudioBuffer(std::shared_ptr bus) { - bus_ = std::move(bus); -} - -size_t AudioBuffer::getLength() const { - return bus_->getSize(); -} - -int AudioBuffer::getNumberOfChannels() const { - return bus_->getNumberOfChannels(); -} - -float AudioBuffer::getSampleRate() const { - return bus_->getSampleRate(); -} - -double AudioBuffer::getDuration() const { - return static_cast(getLength()) / getSampleRate(); -} - -float *AudioBuffer::getChannelData(int channel) const { - return bus_->getChannel(channel)->getData(); -} - -void AudioBuffer::copyFromChannel( - float *destination, - size_t destinationLength, - int channelNumber, - size_t startInChannel) const { - memcpy( - destination, - bus_->getChannel(channelNumber)->getData() + startInChannel, - std::min(destinationLength, getLength() - startInChannel) * sizeof(float)); -} - -void AudioBuffer::copyToChannel( - const float *source, - size_t sourceLength, - int channelNumber, - size_t startInChannel) { - memcpy( - bus_->getChannel(channelNumber)->getData() + startInChannel, - source, - std::min(sourceLength, getLength() - startInChannel) * sizeof(float)); -} - -} // namespace audioapi diff --git a/packages/react-native-audio-api/common/cpp/audioapi/core/sources/AudioBuffer.h b/packages/react-native-audio-api/common/cpp/audioapi/core/sources/AudioBuffer.h deleted file mode 100644 index 6d0b157a9..000000000 --- a/packages/react-native-audio-api/common/cpp/audioapi/core/sources/AudioBuffer.h +++ /dev/null @@ -1,45 +0,0 @@ -#pragma once - -#include -#include -#include -#include -#include -#include - -namespace audioapi { - -class AudioBus; -struct AudioBufferOptions; - -/// AudioBuffer is not thread-safe. -/// Due to that fact it should be copied when passing between threads. -class AudioBuffer { - public: - explicit AudioBuffer(const AudioBufferOptions &options); - explicit AudioBuffer(std::shared_ptr bus); - - [[nodiscard]] size_t getLength() const; - [[nodiscard]] float getSampleRate() const; - [[nodiscard]] double getDuration() const; - - [[nodiscard]] int getNumberOfChannels() const; - [[nodiscard]] float *getChannelData(int channel) const; - - void copyFromChannel( - float *destination, - size_t destinationLength, - int channelNumber, - size_t startInChannel) const; - void - copyToChannel(const float *source, size_t sourceLength, int channelNumber, size_t startInChannel); - - private: - friend class AudioBufferSourceNode; - friend class AudioBufferQueueSourceNode; - friend class AudioBufferHostObject; - - std::shared_ptr bus_; -}; - -} // namespace audioapi diff --git a/packages/react-native-audio-api/common/cpp/audioapi/core/sources/AudioBufferBaseSourceNode.cpp b/packages/react-native-audio-api/common/cpp/audioapi/core/sources/AudioBufferBaseSourceNode.cpp index f73a4b3c7..38d038fb7 100644 --- a/packages/react-native-audio-api/common/cpp/audioapi/core/sources/AudioBufferBaseSourceNode.cpp +++ b/packages/react-native-audio-api/common/cpp/audioapi/core/sources/AudioBufferBaseSourceNode.cpp @@ -5,7 +5,7 @@ #include #include #include -#include +#include #include #include #include @@ -24,8 +24,8 @@ AudioBufferBaseSourceNode::AudioBufferBaseSourceNode( playbackRateParam_ = std::make_shared( options.playbackRate, MOST_NEGATIVE_SINGLE_FLOAT, MOST_POSITIVE_SINGLE_FLOAT, context); - playbackRateBus_ = - std::make_shared(RENDER_QUANTUM_SIZE * 3, channelCount_, context->getSampleRate()); + playbackRateBus_ = std::make_shared( + RENDER_QUANTUM_SIZE * 3, channelCount_, context->getSampleRate()); stretch_ = std::make_shared>(); } @@ -99,7 +99,7 @@ void AudioBufferBaseSourceNode::sendOnPositionChangedEvent() { } void AudioBufferBaseSourceNode::processWithPitchCorrection( - const std::shared_ptr &processingBus, + const std::shared_ptr &processingBus, int framesToProcess) { size_t startOffset = 0; size_t offsetLength = 0; @@ -145,7 +145,7 @@ void AudioBufferBaseSourceNode::processWithPitchCorrection( } void AudioBufferBaseSourceNode::processWithoutPitchCorrection( - const std::shared_ptr &processingBus, + const std::shared_ptr &processingBus, int framesToProcess) { size_t startOffset = 0; size_t offsetLength = 0; diff --git a/packages/react-native-audio-api/common/cpp/audioapi/core/sources/AudioBufferBaseSourceNode.h b/packages/react-native-audio-api/common/cpp/audioapi/core/sources/AudioBufferBaseSourceNode.h index d44a4c702..87b3e4cf0 100644 --- a/packages/react-native-audio-api/common/cpp/audioapi/core/sources/AudioBufferBaseSourceNode.h +++ b/packages/react-native-audio-api/common/cpp/audioapi/core/sources/AudioBufferBaseSourceNode.h @@ -9,7 +9,7 @@ namespace audioapi { -class AudioBus; +class AudioBuffer; class AudioParam; struct BaseAudioBufferSourceOptions; @@ -36,7 +36,7 @@ class AudioBufferBaseSourceNode : public AudioScheduledSourceNode { // pitch correction std::shared_ptr> stretch_; - std::shared_ptr playbackRateBus_; + std::shared_ptr playbackRateBus_; // k-rate params std::shared_ptr detuneParam_; @@ -55,22 +55,22 @@ class AudioBufferBaseSourceNode : public AudioScheduledSourceNode { void sendOnPositionChangedEvent(); void processWithPitchCorrection( - const std::shared_ptr &processingBus, + const std::shared_ptr &processingBus, int framesToProcess); void processWithoutPitchCorrection( - const std::shared_ptr &processingBus, + const std::shared_ptr &processingBus, int framesToProcess); float getComputedPlaybackRateValue(int framesToProcess, double time); virtual void processWithoutInterpolation( - const std::shared_ptr &processingBus, + const std::shared_ptr &processingBus, size_t startOffset, size_t offsetLength, float playbackRate) = 0; virtual void processWithInterpolation( - const std::shared_ptr &processingBus, + const std::shared_ptr &processingBus, size_t startOffset, size_t offsetLength, float playbackRate) = 0; diff --git a/packages/react-native-audio-api/common/cpp/audioapi/core/sources/AudioBufferQueueSourceNode.cpp b/packages/react-native-audio-api/common/cpp/audioapi/core/sources/AudioBufferQueueSourceNode.cpp index c845dd40e..956a99ac0 100644 --- a/packages/react-native-audio-api/common/cpp/audioapi/core/sources/AudioBufferQueueSourceNode.cpp +++ b/packages/react-native-audio-api/common/cpp/audioapi/core/sources/AudioBufferQueueSourceNode.cpp @@ -4,10 +4,10 @@ #include #include #include -#include +#include #include #include -#include +#include #include #include @@ -35,7 +35,7 @@ AudioBufferQueueSourceNode::AudioBufferQueueSourceNode( extraTailFrames, static_cast(channelCount_), context->getSampleRate()); tailBuffer_ = std::make_shared(audioBufferOptions); - tailBuffer_->bus_->zero(); + tailBuffer_->zero(); } isInitialized_ = true; @@ -137,8 +137,8 @@ void AudioBufferQueueSourceNode::setOnBufferEndedCallbackId(uint64_t callbackId) } } -std::shared_ptr AudioBufferQueueSourceNode::processNode( - const std::shared_ptr &processingBus, +std::shared_ptr AudioBufferQueueSourceNode::processNode( + const std::shared_ptr &processingBus, int framesToProcess) { if (auto locker = Locker::tryLock(getBufferLock())) { // no audio data to fill, zero the output and return. @@ -187,7 +187,7 @@ void AudioBufferQueueSourceNode::sendOnBufferEndedEvent(size_t bufferId, bool is */ void AudioBufferQueueSourceNode::processWithoutInterpolation( - const std::shared_ptr &processingBus, + const std::shared_ptr &processingBus, size_t startOffset, size_t offsetLength, float playbackRate) { @@ -201,22 +201,22 @@ void AudioBufferQueueSourceNode::processWithoutInterpolation( size_t framesLeft = offsetLength; while (framesLeft > 0) { - size_t framesToEnd = buffer->getLength() - readIndex; + size_t framesToEnd = buffer->getSize() - readIndex; size_t framesToCopy = std::min(framesToEnd, framesLeft); framesToCopy = framesToCopy > 0 ? framesToCopy : 0; assert(readIndex >= 0); assert(writeIndex >= 0); - assert(readIndex + framesToCopy <= buffer->getLength()); + assert(readIndex + framesToCopy <= buffer->getSize()); assert(writeIndex + framesToCopy <= processingBus->getSize()); - processingBus->copy(buffer->bus_.get(), readIndex, writeIndex, framesToCopy); + processingBus->copy(*buffer, readIndex, writeIndex, framesToCopy); writeIndex += framesToCopy; readIndex += framesToCopy; framesLeft -= framesToCopy; - if (readIndex >= buffer->getLength()) { + if (readIndex >= buffer->getSize()) { playedBuffersDuration_ += buffer->getDuration(); buffers_.pop(); @@ -248,7 +248,7 @@ void AudioBufferQueueSourceNode::processWithoutInterpolation( } void AudioBufferQueueSourceNode::processWithInterpolation( - const std::shared_ptr &processingBus, + const std::shared_ptr &processingBus, size_t startOffset, size_t offsetLength, float playbackRate) { @@ -267,7 +267,7 @@ void AudioBufferQueueSourceNode::processWithInterpolation( bool crossBufferInterpolation = false; std::shared_ptr nextBuffer = nullptr; - if (nextReadIndex >= buffer->getLength()) { + if (nextReadIndex >= buffer->getSize()) { if (buffers_.size() > 1) { auto tempQueue = buffers_; tempQueue.pop(); @@ -280,11 +280,11 @@ void AudioBufferQueueSourceNode::processWithInterpolation( } for (int i = 0; i < processingBus->getNumberOfChannels(); i += 1) { - float *destination = processingBus->getChannel(i)->getData(); - const float *currentSource = buffer->bus_->getChannel(i)->getData(); + const auto destination = processingBus->getChannel(i)->span(); + const auto currentSource = buffer->getChannel(i)->span(); if (crossBufferInterpolation) { - const float *nextSource = nextBuffer->bus_->getChannel(i)->getData(); + const auto nextSource = nextBuffer->getChannel(i)->span(); float currentSample = currentSource[readIndex]; float nextSample = nextSource[nextReadIndex]; destination[writeIndex] = currentSample + factor * (nextSample - currentSample); @@ -299,7 +299,7 @@ void AudioBufferQueueSourceNode::processWithInterpolation( vReadIndex_ += std::abs(playbackRate); framesLeft -= 1; - if (vReadIndex_ >= static_cast(buffer->getLength())) { + if (vReadIndex_ >= static_cast(buffer->getSize())) { playedBuffersDuration_ += buffer->getDuration(); buffers_.pop(); @@ -311,7 +311,7 @@ void AudioBufferQueueSourceNode::processWithInterpolation( break; } - vReadIndex_ = vReadIndex_ - buffer->getLength(); + vReadIndex_ = vReadIndex_ - buffer->getSize(); data = buffers_.front(); bufferId = data.first; buffer = data.second; diff --git a/packages/react-native-audio-api/common/cpp/audioapi/core/sources/AudioBufferQueueSourceNode.h b/packages/react-native-audio-api/common/cpp/audioapi/core/sources/AudioBufferQueueSourceNode.h index 6e017018b..12714c44d 100644 --- a/packages/react-native-audio-api/common/cpp/audioapi/core/sources/AudioBufferQueueSourceNode.h +++ b/packages/react-native-audio-api/common/cpp/audioapi/core/sources/AudioBufferQueueSourceNode.h @@ -1,8 +1,8 @@ #pragma once -#include #include #include +#include #include #include @@ -12,7 +12,7 @@ namespace audioapi { -class AudioBus; +class AudioBuffer; class AudioParam; struct BaseAudioBufferSourceOptions; @@ -37,8 +37,8 @@ class AudioBufferQueueSourceNode : public AudioBufferBaseSourceNode { void setOnBufferEndedCallbackId(uint64_t callbackId); protected: - std::shared_ptr processNode( - const std::shared_ptr &processingBus, + std::shared_ptr processNode( + const std::shared_ptr &processingBus, int framesToProcess) override; double getCurrentPosition() const override; @@ -59,13 +59,13 @@ class AudioBufferQueueSourceNode : public AudioBufferBaseSourceNode { std::atomic onBufferEndedCallbackId_ = 0; // 0 means no callback void processWithoutInterpolation( - const std::shared_ptr &processingBus, + const std::shared_ptr &processingBus, size_t startOffset, size_t offsetLength, float playbackRate) override; void processWithInterpolation( - const std::shared_ptr &processingBus, + const std::shared_ptr &processingBus, size_t startOffset, size_t offsetLength, float playbackRate) override; diff --git a/packages/react-native-audio-api/common/cpp/audioapi/core/sources/AudioBufferSourceNode.cpp b/packages/react-native-audio-api/common/cpp/audioapi/core/sources/AudioBufferSourceNode.cpp index 06764ece4..ce42ba036 100644 --- a/packages/react-native-audio-api/common/cpp/audioapi/core/sources/AudioBufferSourceNode.cpp +++ b/packages/react-native-audio-api/common/cpp/audioapi/core/sources/AudioBufferSourceNode.cpp @@ -4,10 +4,10 @@ #include #include #include -#include +#include #include #include -#include +#include #include #include @@ -22,7 +22,7 @@ AudioBufferSourceNode::AudioBufferSourceNode( loopStart_(options.loopStart), loopEnd_(options.loopEnd) { buffer_ = std::shared_ptr(options.buffer); - alignedBus_ = std::shared_ptr(nullptr); + alignedBus_ = std::shared_ptr(nullptr); isInitialized_ = true; } @@ -81,7 +81,7 @@ void AudioBufferSourceNode::setBuffer(const std::shared_ptr &buffer if (buffer == nullptr || context == nullptr) { buffer_ = std::shared_ptr(nullptr); - alignedBus_ = std::shared_ptr(nullptr); + alignedBus_ = std::shared_ptr(nullptr); loopEnd_ = 0; return; } @@ -94,19 +94,19 @@ void AudioBufferSourceNode::setBuffer(const std::shared_ptr &buffer if (pitchCorrection_) { int extraTailFrames = static_cast((getInputLatency() + getOutputLatency()) * context->getSampleRate()); - size_t totalSize = buffer_->getLength() + extraTailFrames; + size_t totalSize = buffer_->getSize() + extraTailFrames; - alignedBus_ = std::make_shared(totalSize, channelCount_, buffer_->getSampleRate()); - alignedBus_->copy(buffer_->bus_.get(), 0, 0, buffer_->getLength()); + alignedBus_ = std::make_shared(totalSize, channelCount_, buffer_->getSampleRate()); + alignedBus_->copy(*buffer_); - alignedBus_->zero(buffer_->getLength(), extraTailFrames); + alignedBus_->zero(buffer_->getSize(), extraTailFrames); } else { - alignedBus_ = std::make_shared(*buffer_->bus_); + alignedBus_ = std::make_shared(*buffer_); } audioBus_ = - std::make_shared(RENDER_QUANTUM_SIZE, channelCount_, context->getSampleRate()); - playbackRateBus_ = - std::make_shared(RENDER_QUANTUM_SIZE * 3, channelCount_, context->getSampleRate()); + std::make_shared(RENDER_QUANTUM_SIZE, channelCount_, context->getSampleRate()); + playbackRateBus_ = std::make_shared( + RENDER_QUANTUM_SIZE * 3, channelCount_, context->getSampleRate()); loopEnd_ = buffer_->getDuration(); } @@ -145,8 +145,8 @@ void AudioBufferSourceNode::setOnLoopEndedCallbackId(uint64_t callbackId) { } } -std::shared_ptr AudioBufferSourceNode::processNode( - const std::shared_ptr &processingBus, +std::shared_ptr AudioBufferSourceNode::processNode( + const std::shared_ptr &processingBus, int framesToProcess) { if (auto locker = Locker::tryLock(getBufferLock())) { // No audio data to fill, zero the output and return. @@ -186,7 +186,7 @@ void AudioBufferSourceNode::sendOnLoopEndedEvent() { */ void AudioBufferSourceNode::processWithoutInterpolation( - const std::shared_ptr &processingBus, + const std::shared_ptr &processingBus, size_t startOffset, size_t offsetLength, float playbackRate) { @@ -228,13 +228,11 @@ void AudioBufferSourceNode::processWithoutInterpolation( // Direction is forward, we can normally copy the data if (direction == 1) { - processingBus->copy(alignedBus_.get(), readIndex, writeIndex, framesToCopy); + processingBus->copy(*alignedBus_, readIndex, writeIndex, framesToCopy); } else { - for (int i = 0; i < framesToCopy; i += 1) { - for (int j = 0; j < processingBus->getNumberOfChannels(); j += 1) { - (*processingBus->getChannel(j))[writeIndex + i] = - (*alignedBus_->getChannel(j))[readIndex - i]; - } + for (int ch = 0; ch < processingBus->getNumberOfChannels(); ch += 1) { + processingBus->getChannel(ch)->copyReverse( + *alignedBus_->getChannel(ch), readIndex, writeIndex, framesToCopy); } } @@ -262,7 +260,7 @@ void AudioBufferSourceNode::processWithoutInterpolation( } void AudioBufferSourceNode::processWithInterpolation( - const std::shared_ptr &processingBus, + const std::shared_ptr &processingBus, size_t startOffset, size_t offsetLength, float playbackRate) { @@ -301,8 +299,8 @@ void AudioBufferSourceNode::processWithInterpolation( } for (int i = 0; i < processingBus->getNumberOfChannels(); i += 1) { - float *destination = processingBus->getChannel(i)->getData(); - const float *source = alignedBus_->getChannel(i)->getData(); + auto destination = processingBus->getChannel(i)->span(); + const auto source = alignedBus_->getChannel(i)->span(); destination[writeIndex] = dsp::linearInterpolate(source, readIndex, nextReadIndex, factor); } diff --git a/packages/react-native-audio-api/common/cpp/audioapi/core/sources/AudioBufferSourceNode.h b/packages/react-native-audio-api/common/cpp/audioapi/core/sources/AudioBufferSourceNode.h index 806d513c9..a47f49620 100644 --- a/packages/react-native-audio-api/common/cpp/audioapi/core/sources/AudioBufferSourceNode.h +++ b/packages/react-native-audio-api/common/cpp/audioapi/core/sources/AudioBufferSourceNode.h @@ -1,8 +1,8 @@ #pragma once -#include #include #include +#include #include #include @@ -11,7 +11,7 @@ namespace audioapi { -class AudioBus; +class AudioBuffer; class AudioParam; struct AudioBufferSourceOptions; @@ -41,8 +41,8 @@ class AudioBufferSourceNode : public AudioBufferBaseSourceNode { void setOnLoopEndedCallbackId(uint64_t callbackId); protected: - std::shared_ptr processNode( - const std::shared_ptr &processingBus, + std::shared_ptr processNode( + const std::shared_ptr &processingBus, int framesToProcess) override; double getCurrentPosition() const override; @@ -55,19 +55,19 @@ class AudioBufferSourceNode : public AudioBufferBaseSourceNode { // User provided buffer std::shared_ptr buffer_; - std::shared_ptr alignedBus_; + std::shared_ptr alignedBus_; std::atomic onLoopEndedCallbackId_ = 0; // 0 means no callback void sendOnLoopEndedEvent(); void processWithoutInterpolation( - const std::shared_ptr &processingBus, + const std::shared_ptr &processingBus, size_t startOffset, size_t offsetLength, float playbackRate) override; void processWithInterpolation( - const std::shared_ptr &processingBus, + const std::shared_ptr &processingBus, size_t startOffset, size_t offsetLength, float playbackRate) override; diff --git a/packages/react-native-audio-api/common/cpp/audioapi/core/sources/AudioScheduledSourceNode.cpp b/packages/react-native-audio-api/common/cpp/audioapi/core/sources/AudioScheduledSourceNode.cpp index 5a419463e..a2ee963cf 100644 --- a/packages/react-native-audio-api/common/cpp/audioapi/core/sources/AudioScheduledSourceNode.cpp +++ b/packages/react-native-audio-api/common/cpp/audioapi/core/sources/AudioScheduledSourceNode.cpp @@ -1,10 +1,10 @@ #include #include #include -#include +#include #include #include -#include +#include #if !RN_AUDIO_API_TEST #include @@ -16,7 +16,7 @@ namespace audioapi { -AudioScheduledSourceNode::AudioScheduledSourceNode(std::shared_ptr context) +AudioScheduledSourceNode::AudioScheduledSourceNode(const std::shared_ptr &context) : AudioNode(context), startTime_(-1.0), stopTime_(-1.0), @@ -71,7 +71,7 @@ void AudioScheduledSourceNode::setOnEndedCallbackId(const uint64_t callbackId) { } void AudioScheduledSourceNode::updatePlaybackInfo( - const std::shared_ptr &processingBus, + const std::shared_ptr &processingBus, int framesToProcess, size_t &startOffset, size_t &nonSilentFramesToProcess, @@ -167,7 +167,8 @@ void AudioScheduledSourceNode::disable() { auto onEndedCallbackId = onEndedCallbackId_.load(std::memory_order_acquire); if (onEndedCallbackId != 0) { - audioEventHandlerRegistry_->invokeHandlerWithEventBody(AudioEvent::ENDED, onEndedCallbackId, {}); + audioEventHandlerRegistry_->invokeHandlerWithEventBody( + AudioEvent::ENDED, onEndedCallbackId, {}); } } diff --git a/packages/react-native-audio-api/common/cpp/audioapi/core/sources/AudioScheduledSourceNode.h b/packages/react-native-audio-api/common/cpp/audioapi/core/sources/AudioScheduledSourceNode.h index 8717c2825..7f9f0f277 100644 --- a/packages/react-native-audio-api/common/cpp/audioapi/core/sources/AudioScheduledSourceNode.h +++ b/packages/react-native-audio-api/common/cpp/audioapi/core/sources/AudioScheduledSourceNode.h @@ -26,7 +26,7 @@ class AudioScheduledSourceNode : public AudioNode { // STOP_SCHEDULED: The node is scheduled to stop at a specific time, but is still playing. // FINISHED: The node has finished playing. enum class PlaybackState { UNSCHEDULED, SCHEDULED, PLAYING, STOP_SCHEDULED, FINISHED }; - explicit AudioScheduledSourceNode(std::shared_ptr context); + explicit AudioScheduledSourceNode(const std::shared_ptr &context); virtual void start(double when); virtual void stop(double when); @@ -51,7 +51,7 @@ class AudioScheduledSourceNode : public AudioNode { std::shared_ptr audioEventHandlerRegistry_; void updatePlaybackInfo( - const std::shared_ptr &processingBus, + const std::shared_ptr &processingBus, int framesToProcess, size_t &startOffset, size_t &nonSilentFramesToProcess, diff --git a/packages/react-native-audio-api/common/cpp/audioapi/core/sources/ConstantSourceNode.cpp b/packages/react-native-audio-api/common/cpp/audioapi/core/sources/ConstantSourceNode.cpp index 23292ad39..48a9ad884 100644 --- a/packages/react-native-audio-api/common/cpp/audioapi/core/sources/ConstantSourceNode.cpp +++ b/packages/react-native-audio-api/common/cpp/audioapi/core/sources/ConstantSourceNode.cpp @@ -1,9 +1,9 @@ #include #include #include -#include +#include #include -#include +#include #include namespace audioapi { @@ -20,8 +20,8 @@ std::shared_ptr ConstantSourceNode::getOffsetParam() const { return offsetParam_; } -std::shared_ptr ConstantSourceNode::processNode( - const std::shared_ptr &processingBus, +std::shared_ptr ConstantSourceNode::processNode( + const std::shared_ptr &processingBus, int framesToProcess) { size_t startOffset = 0; size_t offsetLength = 0; @@ -44,16 +44,13 @@ std::shared_ptr ConstantSourceNode::processNode( processingBus->zero(); return processingBus; } - auto offsetBus = offsetParam_->processARateParam(framesToProcess, context->getCurrentTime()); - auto offsetChannelData = offsetBus->getChannel(0)->getData(); - for (int channel = 0; channel < processingBus->getNumberOfChannels(); ++channel) { - auto outputChannelData = processingBus->getChannel(channel)->getData(); + auto offsetChannel = + offsetParam_->processARateParam(framesToProcess, context->getCurrentTime())->getChannel(0); - std::copy( - offsetChannelData + startOffset, - offsetChannelData + startOffset + offsetLength, - outputChannelData + startOffset); + for (int channel = 0; channel < processingBus->getNumberOfChannels(); ++channel) { + processingBus->getChannel(channel)->copy( + *offsetChannel, startOffset, startOffset, offsetLength); } if (isStopScheduled()) { diff --git a/packages/react-native-audio-api/common/cpp/audioapi/core/sources/ConstantSourceNode.h b/packages/react-native-audio-api/common/cpp/audioapi/core/sources/ConstantSourceNode.h index 8b83ad762..61a099055 100644 --- a/packages/react-native-audio-api/common/cpp/audioapi/core/sources/ConstantSourceNode.h +++ b/packages/react-native-audio-api/common/cpp/audioapi/core/sources/ConstantSourceNode.h @@ -9,7 +9,7 @@ namespace audioapi { -class AudioBus; +class AudioBuffer; struct ConstantSourceOptions; class ConstantSourceNode : public AudioScheduledSourceNode { @@ -21,8 +21,8 @@ class ConstantSourceNode : public AudioScheduledSourceNode { [[nodiscard]] std::shared_ptr getOffsetParam() const; protected: - std::shared_ptr processNode( - const std::shared_ptr &processingBus, + std::shared_ptr processNode( + const std::shared_ptr &processingBus, int framesToProcess) override; private: diff --git a/packages/react-native-audio-api/common/cpp/audioapi/core/sources/OscillatorNode.cpp b/packages/react-native-audio-api/common/cpp/audioapi/core/sources/OscillatorNode.cpp index 36b3e5349..82a13db30 100644 --- a/packages/react-native-audio-api/common/cpp/audioapi/core/sources/OscillatorNode.cpp +++ b/packages/react-native-audio-api/common/cpp/audioapi/core/sources/OscillatorNode.cpp @@ -1,9 +1,9 @@ #include #include #include -#include +#include #include -#include +#include #include #include @@ -27,7 +27,7 @@ OscillatorNode::OscillatorNode( periodicWave_ = context->getBasicWaveForm(type_); } - audioBus_ = std::make_shared(RENDER_QUANTUM_SIZE, 1, context->getSampleRate()); + audioBus_ = std::make_shared(RENDER_QUANTUM_SIZE, 1, context->getSampleRate()); isInitialized_ = true; } @@ -56,8 +56,8 @@ void OscillatorNode::setPeriodicWave(const std::shared_ptr &period type_ = OscillatorType::CUSTOM; } -std::shared_ptr OscillatorNode::processNode( - const std::shared_ptr &processingBus, +std::shared_ptr OscillatorNode::processNode( + const std::shared_ptr &processingBus, int framesToProcess) { size_t startOffset = 0; size_t offsetLength = 0; @@ -83,25 +83,41 @@ std::shared_ptr OscillatorNode::processNode( auto time = context->getCurrentTime() + static_cast(startOffset) * 1.0 / context->getSampleRate(); - auto detuneParamValues = detuneParam_->processARateParam(framesToProcess, time); - auto frequencyParamValues = frequencyParam_->processARateParam(framesToProcess, time); + auto detuneSpan = detuneParam_->processARateParam(framesToProcess, time)->getChannel(0)->span(); + auto freqSpan = frequencyParam_->processARateParam(framesToProcess, time)->getChannel(0)->span(); - for (size_t i = startOffset; i < offsetLength; i += 1) { - auto detuneRatio = std::pow(2.0f, detuneParamValues->getChannel(0)->getData()[i] / 1200.0f); - auto detunedFrequency = frequencyParamValues->getChannel(0)->getData()[i] * detuneRatio; - auto phaseIncrement = detunedFrequency * periodicWave_->getScale(); + const auto tableSize = static_cast(periodicWave_->getPeriodicWaveSize()); + const auto tableScale = periodicWave_->getScale(); + const auto numChannels = processingBus->getNumberOfChannels(); - float sample = periodicWave_->getSample(detunedFrequency, phase_, phaseIncrement); + auto finalPhase = phase_; - for (int j = 0; j < processingBus->getNumberOfChannels(); j += 1) { - (*processingBus->getChannel(j))[i] = sample; + for (int ch = 0; ch < numChannels; ch += 1) { + auto channelSpan = processingBus->getChannel(ch)->span(); + float currentPhase = phase_; + + for (size_t i = startOffset; i < offsetLength; i += 1) { + auto detuneRatio = detuneSpan[i] == 0 ? 1.0f : std::pow(2.0f, detuneSpan[i] / 1200.0f); + auto detunedFrequency = freqSpan[i] * detuneRatio; + auto phaseIncrement = detunedFrequency * tableScale; + + channelSpan[i] = periodicWave_->getSample(detunedFrequency, currentPhase, phaseIncrement); + + currentPhase += phaseIncrement; + + if (currentPhase >= tableSize) { + currentPhase -= tableSize; + } else if (currentPhase < 0.0f) { + currentPhase += tableSize; + } } - phase_ += phaseIncrement; - phase_ -= floor(phase_ / static_cast(periodicWave_->getPeriodicWaveSize())) * - static_cast(periodicWave_->getPeriodicWaveSize()); + if (ch == 0) { + finalPhase = currentPhase; + } } + phase_ = finalPhase; handleStopScheduled(); return processingBus; diff --git a/packages/react-native-audio-api/common/cpp/audioapi/core/sources/OscillatorNode.h b/packages/react-native-audio-api/common/cpp/audioapi/core/sources/OscillatorNode.h index cfd0908a2..1805a6204 100644 --- a/packages/react-native-audio-api/common/cpp/audioapi/core/sources/OscillatorNode.h +++ b/packages/react-native-audio-api/common/cpp/audioapi/core/sources/OscillatorNode.h @@ -12,7 +12,7 @@ namespace audioapi { -class AudioBus; +class AudioBuffer; struct OscillatorOptions; class OscillatorNode : public AudioScheduledSourceNode { @@ -28,8 +28,8 @@ class OscillatorNode : public AudioScheduledSourceNode { void setPeriodicWave(const std::shared_ptr &periodicWave); protected: - std::shared_ptr processNode( - const std::shared_ptr &processingBus, + std::shared_ptr processNode( + const std::shared_ptr &processingBus, int framesToProcess) override; private: diff --git a/packages/react-native-audio-api/common/cpp/audioapi/core/sources/RecorderAdapterNode.cpp b/packages/react-native-audio-api/common/cpp/audioapi/core/sources/RecorderAdapterNode.cpp index a94ad3423..8cf50cd7e 100644 --- a/packages/react-native-audio-api/common/cpp/audioapi/core/sources/RecorderAdapterNode.cpp +++ b/packages/react-native-audio-api/common/cpp/audioapi/core/sources/RecorderAdapterNode.cpp @@ -3,13 +3,13 @@ #include #include #include -#include +#include #include #include namespace audioapi { -RecorderAdapterNode::RecorderAdapterNode(std::shared_ptr context) +RecorderAdapterNode::RecorderAdapterNode(const std::shared_ptr &context) : AudioNode(context) { // It should be marked as initialized only after it is connected to the // recorder. Internall buffer size is based on the recorder's buffer length. @@ -33,7 +33,7 @@ void RecorderAdapterNode::init(size_t bufferSize, int channelCount) { // This assumes that the sample rate is the same in audio context and recorder. // (recorder is not enforcing any sample rate on the system*). This means that only // channel mixing might be required. To do so, we create an output bus with - // the desired channel count and will take advantage of the AudioBus sum method. + // the desired channel count and will take advantage of the AudioBuffer sum method. // // * any allocations required by the recorder (including this method) are during recording start // or after, which means that audio context has already setup the system in 99% of sane cases. @@ -42,7 +42,7 @@ void RecorderAdapterNode::init(size_t bufferSize, int channelCount) { // context output and not enforcing anything on the system output/input configuration. // A lot of words for a couple of lines of implementation :shrug: adapterOutputBus_ = - std::make_shared(RENDER_QUANTUM_SIZE, channelCount_, context->getSampleRate()); + std::make_shared(RENDER_QUANTUM_SIZE, channelCount_, context->getSampleRate()); isInitialized_ = true; } @@ -52,8 +52,8 @@ void RecorderAdapterNode::cleanup() { adapterOutputBus_.reset(); } -std::shared_ptr RecorderAdapterNode::processNode( - const std::shared_ptr &processingBus, +std::shared_ptr RecorderAdapterNode::processNode( + const std::shared_ptr &processingBus, int framesToProcess) { if (!isInitialized_) { processingBus->zero(); @@ -62,7 +62,7 @@ std::shared_ptr RecorderAdapterNode::processNode( readFrames(framesToProcess); - processingBus->sum(adapterOutputBus_.get(), ChannelInterpretation::SPEAKERS); + processingBus->sum(*adapterOutputBus_, ChannelInterpretation::SPEAKERS); return processingBus; } @@ -70,7 +70,7 @@ void RecorderAdapterNode::readFrames(const size_t framesToRead) { adapterOutputBus_->zero(); for (size_t channel = 0; channel < channelCount_; ++channel) { - buff_[channel]->read(adapterOutputBus_->getChannel(channel)->getData(), framesToRead); + buff_[channel]->read(*adapterOutputBus_->getChannel(channel), framesToRead); } } diff --git a/packages/react-native-audio-api/common/cpp/audioapi/core/sources/RecorderAdapterNode.h b/packages/react-native-audio-api/common/cpp/audioapi/core/sources/RecorderAdapterNode.h index 46f2aa541..8c2dcbaf1 100644 --- a/packages/react-native-audio-api/common/cpp/audioapi/core/sources/RecorderAdapterNode.h +++ b/packages/react-native-audio-api/common/cpp/audioapi/core/sources/RecorderAdapterNode.h @@ -10,7 +10,7 @@ namespace audioapi { -class AudioBus; +class AudioBuffer; /// @brief RecorderAdapterNode is an AudioNode which adapts push Recorder into pull graph. /// It uses RingBuffer to store audio data and AudioParam to provide audio data in pull mode. @@ -19,7 +19,7 @@ class AudioBus; /// @note it will push silence if it is not connected to any Recorder class RecorderAdapterNode : public AudioNode { public: - explicit RecorderAdapterNode(std::shared_ptr context); + explicit RecorderAdapterNode(const std::shared_ptr &context); /// @brief Initialize the RecorderAdapterNode with a buffer size and channel count. /// @note This method should be called ONLY ONCE when the buffer size is known. @@ -28,15 +28,15 @@ class RecorderAdapterNode : public AudioNode { void init(size_t bufferSize, int channelCount); void cleanup(); - int channelCount_; - // TODO: CircularOverflowableAudioBus + int channelCount_{}; + // TODO: CircularOverflowableAudioBuffer std::vector> buff_; protected: - std::shared_ptr processNode( - const std::shared_ptr &processingBus, + std::shared_ptr processNode( + const std::shared_ptr &processingBus, int framesToProcess) override; - std::shared_ptr adapterOutputBus_; + std::shared_ptr adapterOutputBus_; private: /// @brief Read audio frames from the recorder's internal circular buffer into output buss. diff --git a/packages/react-native-audio-api/common/cpp/audioapi/core/sources/StreamerNode.cpp b/packages/react-native-audio-api/common/cpp/audioapi/core/sources/StreamerNode.cpp index 1b6c8a212..99a252d7c 100644 --- a/packages/react-native-audio-api/common/cpp/audioapi/core/sources/StreamerNode.cpp +++ b/packages/react-native-audio-api/common/cpp/audioapi/core/sources/StreamerNode.cpp @@ -14,12 +14,13 @@ #include #include #include -#include +#include #include #include #include #include #include +#include namespace audioapi { #if !RN_AUDIO_API_FFMPEG_DISABLED @@ -36,6 +37,7 @@ StreamerNode::StreamerNode( swrCtx_(nullptr), resampledData_(nullptr), bufferedBus_(nullptr), + bufferedBusSize_(0), audio_stream_index_(-1), maxResampledSamples_(0), processedSamples_(0) {} @@ -89,7 +91,7 @@ bool StreamerNode::initialize(const std::string &input_url) { channelCount_ = codecpar_->ch_layout.nb_channels; audioBus_ = - std::make_shared(RENDER_QUANTUM_SIZE, channelCount_, context->getSampleRate()); + std::make_shared(RENDER_QUANTUM_SIZE, channelCount_, context->getSampleRate()); auto [sender, receiver] = channels::spsc::channel< StreamingData, @@ -106,8 +108,8 @@ bool StreamerNode::initialize(const std::string &input_url) { #endif // RN_AUDIO_API_FFMPEG_DISABLED } -std::shared_ptr StreamerNode::processNode( - const std::shared_ptr &processingBus, +std::shared_ptr StreamerNode::processNode( + const std::shared_ptr &processingBus, int framesToProcess) { #if !RN_AUDIO_API_FFMPEG_DISABLED size_t startOffset = 0; @@ -135,19 +137,14 @@ std::shared_ptr StreamerNode::processNode( int alreadyProcessed = 0; if (bufferRemaining < framesToProcess) { if (bufferedBus_ != nullptr) { - for (int ch = 0; ch < processingBus->getNumberOfChannels(); ch++) { - memcpy( - processingBus->getChannel(ch)->getData(), - bufferedBus_->getChannel(ch)->getData() + processedSamples_, - bufferRemaining * sizeof(float)); - } + processingBus->copy(*bufferedBus_, processedSamples_, 0, bufferRemaining); framesToProcess -= bufferRemaining; alreadyProcessed += bufferRemaining; } StreamingData data; auto res = receiver_.try_receive(data); if (res == channels::spsc::ResponseStatus::SUCCESS) { - bufferedBus_ = std::make_shared(std::move(data.bus)); + bufferedBus_ = std::make_shared(std::move(data.bus)); bufferedBusSize_ = data.size; processedSamples_ = 0; } else { @@ -155,12 +152,7 @@ std::shared_ptr StreamerNode::processNode( } } if (bufferedBus_ != nullptr) { - for (int ch = 0; ch < processingBus->getNumberOfChannels(); ch++) { - memcpy( - processingBus->getChannel(ch)->getData() + alreadyProcessed, - bufferedBus_->getChannel(ch)->getData() + processedSamples_, - framesToProcess * sizeof(float)); - } + processingBus->copy(*bufferedBus_, processedSamples_, alreadyProcessed, framesToProcess); processedSamples_ += framesToProcess; } #endif // RN_AUDIO_API_FFMPEG_DISABLED @@ -230,7 +222,7 @@ void StreamerNode::streamAudio() { bool StreamerNode::processFrameWithResampler( AVFrame *frame, - std::shared_ptr context) { + const std::shared_ptr &context) { // Check if we need to reallocate the resampled buffer int out_samples = swr_get_out_samples(swrCtx_, frame->nb_samples); if (out_samples > maxResampledSamples_) { @@ -267,16 +259,18 @@ bool StreamerNode::processFrameWithResampler( if (this->isFinished()) { return true; } - auto bus = AudioBus( - static_cast(converted_samples), + + AudioBuffer buffer = AudioBuffer( + converted_samples, codecCtx_->ch_layout.nb_channels, context->getSampleRate()); + for (int ch = 0; ch < codecCtx_->ch_layout.nb_channels; ch++) { auto *src = reinterpret_cast(resampledData_[ch]); - float *dst = bus.getChannel(ch)->getData(); - memcpy(dst, src, converted_samples * sizeof(float)); + buffer.getChannel(ch)->copy(src, 0, 0, converted_samples); } - StreamingData data{std::move(bus), static_cast(converted_samples)}; + + StreamingData data{std::move(buffer), static_cast(converted_samples)}; sender_.send(std::move(data)); return true; } diff --git a/packages/react-native-audio-api/common/cpp/audioapi/core/sources/StreamerNode.h b/packages/react-native-audio-api/common/cpp/audioapi/core/sources/StreamerNode.h index 7ca9928a7..9700bc565 100644 --- a/packages/react-native-audio-api/common/cpp/audioapi/core/sources/StreamerNode.h +++ b/packages/react-native-audio-api/common/cpp/audioapi/core/sources/StreamerNode.h @@ -11,7 +11,7 @@ #pragma once #include -#include +#include #if !RN_AUDIO_API_FFMPEG_DISABLED extern "C" { @@ -40,10 +40,10 @@ static constexpr bool VERBOSE = false; static constexpr int CHANNEL_CAPACITY = 32; struct StreamingData { - audioapi::AudioBus bus; + audioapi::AudioBuffer bus; size_t size; StreamingData() = default; - StreamingData(audioapi::AudioBus b, size_t s) : bus(b), size(s) {} + StreamingData(audioapi::AudioBuffer b, size_t s) : bus(b), size(s) {} StreamingData(const StreamingData &data) : bus(data.bus), size(data.size) {} StreamingData(StreamingData &&data) noexcept : bus(std::move(data.bus)), size(data.size) {} StreamingData &operator=(const StreamingData &data) { @@ -58,7 +58,7 @@ struct StreamingData { namespace audioapi { -class AudioBus; +class AudioBuffer; struct StreamerOptions; class StreamerNode : public AudioScheduledSourceNode { @@ -82,8 +82,8 @@ class StreamerNode : public AudioScheduledSourceNode { } protected: - std::shared_ptr processNode( - const std::shared_ptr &processingBus, + std::shared_ptr processNode( + const std::shared_ptr &processingBus, int framesToProcess) override; private: @@ -97,9 +97,9 @@ class StreamerNode : public AudioScheduledSourceNode { SwrContext *swrCtx_; uint8_t **resampledData_; // weird ffmpeg way of using raw byte pointers for resampled data - std::shared_ptr bufferedBus_; // audio bus for buffering hls frames - size_t bufferedBusSize_; // size of currently buffered bus - int audio_stream_index_; // index of the audio stream channel in the input + std::shared_ptr bufferedBus_; // audio bus for buffering hls frames + size_t bufferedBusSize_; // size of currently buffered bus + int audio_stream_index_; // index of the audio stream channel in the input int maxResampledSamples_; size_t processedSamples_; @@ -128,7 +128,7 @@ class StreamerNode : public AudioScheduledSourceNode { * @param frame The AVFrame to resample * @return true if successful, false otherwise */ - bool processFrameWithResampler(AVFrame *frame, std::shared_ptr context); + bool processFrameWithResampler(AVFrame *frame, const std::shared_ptr &context); /** * @brief Thread function to continuously read and process audio frames diff --git a/packages/react-native-audio-api/common/cpp/audioapi/core/sources/WorkletSourceNode.cpp b/packages/react-native-audio-api/common/cpp/audioapi/core/sources/WorkletSourceNode.cpp index a243742a2..5fdad711c 100644 --- a/packages/react-native-audio-api/common/cpp/audioapi/core/sources/WorkletSourceNode.cpp +++ b/packages/react-native-audio-api/common/cpp/audioapi/core/sources/WorkletSourceNode.cpp @@ -6,7 +6,7 @@ namespace audioapi { WorkletSourceNode::WorkletSourceNode( - std::shared_ptr context, + const std::shared_ptr &context, WorkletsRunner &&workletRunner) : AudioScheduledSourceNode(context), workletRunner_(std::move(workletRunner)) { isInitialized_ = true; @@ -15,13 +15,12 @@ WorkletSourceNode::WorkletSourceNode( size_t outputChannelCount = this->getChannelCount(); outputBuffsHandles_.resize(outputChannelCount); for (size_t i = 0; i < outputChannelCount; ++i) { - auto audioArray = std::make_shared(RENDER_QUANTUM_SIZE); - outputBuffsHandles_[i] = std::make_shared(audioArray); + outputBuffsHandles_[i] = std::make_shared(RENDER_QUANTUM_SIZE); } } -std::shared_ptr WorkletSourceNode::processNode( - const std::shared_ptr &processingBus, +std::shared_ptr WorkletSourceNode::processNode( + const std::shared_ptr &processingBus, int framesToProcess) { if (isUnscheduled() || isFinished() || !isEnabled()) { processingBus->zero(); @@ -36,7 +35,13 @@ std::shared_ptr WorkletSourceNode::processNode( processingBus->zero(); return processingBus; } - updatePlaybackInfo(processingBus, framesToProcess, startOffset, nonSilentFramesToProcess, context->getSampleRate(), context->getCurrentSampleFrame()); + updatePlaybackInfo( + processingBus, + framesToProcess, + startOffset, + nonSilentFramesToProcess, + context->getSampleRate(), + context->getCurrentSampleFrame()); if (nonSilentFramesToProcess == 0) { processingBus->zero(); @@ -46,7 +51,8 @@ std::shared_ptr WorkletSourceNode::processNode( size_t outputChannelCount = processingBus->getNumberOfChannels(); auto result = workletRunner_.executeOnRuntimeSync( - [this, nonSilentFramesToProcess, startOffset, time = context->getCurrentTime()](jsi::Runtime &rt) { + [this, nonSilentFramesToProcess, startOffset, time = context->getCurrentTime()]( + jsi::Runtime &rt) { auto jsiArray = jsi::Array(rt, this->outputBuffsHandles_.size()); for (size_t i = 0; i < this->outputBuffsHandles_.size(); ++i) { auto arrayBuffer = jsi::ArrayBuffer(rt, this->outputBuffsHandles_[i]); @@ -70,13 +76,10 @@ std::shared_ptr WorkletSourceNode::processNode( return processingBus; } - // Copy the processed data back to the AudioBus - for (size_t i = 0; i < outputChannelCount; ++i) { - float *channelData = processingBus->getChannel(i)->getData(); - memcpy( - channelData + startOffset, - outputBuffsHandles_[i]->data(), - nonSilentFramesToProcess * sizeof(float)); + // Copy the processed data back to the AudioBuffer + for (int i = 0; i < outputChannelCount; ++i) { + processingBus->getChannel(i)->copy( + *outputBuffsHandles_[i], 0, startOffset, nonSilentFramesToProcess); } handleStopScheduled(); diff --git a/packages/react-native-audio-api/common/cpp/audioapi/core/sources/WorkletSourceNode.h b/packages/react-native-audio-api/common/cpp/audioapi/core/sources/WorkletSourceNode.h index ce7e01515..93b098767 100644 --- a/packages/react-native-audio-api/common/cpp/audioapi/core/sources/WorkletSourceNode.h +++ b/packages/react-native-audio-api/common/cpp/audioapi/core/sources/WorkletSourceNode.h @@ -3,9 +3,9 @@ #include #include #include -#include #include -#include +#include +#include #include #include @@ -22,8 +22,8 @@ class WorkletSourceNode : public AudioScheduledSourceNode { : AudioScheduledSourceNode(context) {} protected: - std::shared_ptr processNode( - const std::shared_ptr &processingBus, + std::shared_ptr processNode( + const std::shared_ptr &processingBus, int framesToProcess) override { return processingBus; } @@ -33,12 +33,12 @@ class WorkletSourceNode : public AudioScheduledSourceNode { class WorkletSourceNode : public AudioScheduledSourceNode { public: explicit WorkletSourceNode( - std::shared_ptr context, + const std::shared_ptr &context, WorkletsRunner &&workletRunner); protected: - std::shared_ptr processNode( - const std::shared_ptr &processingBus, + std::shared_ptr processNode( + const std::shared_ptr &processingBus, int framesToProcess) override; private: diff --git a/packages/react-native-audio-api/common/cpp/audioapi/core/utils/AudioGraphManager.cpp b/packages/react-native-audio-api/common/cpp/audioapi/core/utils/AudioGraphManager.cpp index eb02e3b6b..f5bc89fcb 100644 --- a/packages/react-native-audio-api/common/cpp/audioapi/core/utils/AudioGraphManager.cpp +++ b/packages/react-native-audio-api/common/cpp/audioapi/core/utils/AudioGraphManager.cpp @@ -1,22 +1,22 @@ #include #include -#include #include #include #include #include #include +#include #include #include #include namespace audioapi { -AudioGraphManager::Event::Event(Event &&other) { +AudioGraphManager::Event::Event(Event &&other) noexcept { *this = std::move(other); } -AudioGraphManager::Event &AudioGraphManager::Event::operator=(Event &&other) { +AudioGraphManager::Event &AudioGraphManager::Event::operator=(Event &&other) noexcept { if (this != &other) { // Clean up current resources this->~Event(); diff --git a/packages/react-native-audio-api/common/cpp/audioapi/core/utils/AudioGraphManager.h b/packages/react-native-audio-api/common/cpp/audioapi/core/utils/AudioGraphManager.h index 60f5f1f5f..2017ce49d 100644 --- a/packages/react-native-audio-api/common/cpp/audioapi/core/utils/AudioGraphManager.h +++ b/packages/react-native-audio-api/common/cpp/audioapi/core/utils/AudioGraphManager.h @@ -55,8 +55,8 @@ class AudioGraphManager { EventPayloadType payloadType; EventPayload payload; - Event(Event &&other); - Event &operator=(Event &&other); + Event(Event &&other) noexcept; + Event &operator=(Event &&other) noexcept; Event() : type(ConnectionType::CONNECT), payloadType(EventPayloadType::NODES), payload() {} ~Event(); }; diff --git a/packages/react-native-audio-api/common/cpp/audioapi/core/utils/AudioParamEventQueue.h b/packages/react-native-audio-api/common/cpp/audioapi/core/utils/AudioParamEventQueue.h index e69514210..37abe6ef8 100644 --- a/packages/react-native-audio-api/common/cpp/audioapi/core/utils/AudioParamEventQueue.h +++ b/packages/react-native-audio-api/common/cpp/audioapi/core/utils/AudioParamEventQueue.h @@ -1,7 +1,7 @@ #pragma once #include -#include +#include #include namespace audioapi { diff --git a/packages/react-native-audio-api/common/cpp/audioapi/core/utils/AudioRecorderCallback.cpp b/packages/react-native-audio-api/common/cpp/audioapi/core/utils/AudioRecorderCallback.cpp index b7d467140..4de47a7a3 100644 --- a/packages/react-native-audio-api/common/cpp/audioapi/core/utils/AudioRecorderCallback.cpp +++ b/packages/react-native-audio-api/common/cpp/audioapi/core/utils/AudioRecorderCallback.cpp @@ -4,7 +4,7 @@ #include #include #include -#include +#include #include #include @@ -56,27 +56,26 @@ void AudioRecorderCallback::emitAudioData(bool flush) { } while (circularBus_[0]->getNumberOfAvailableFrames() >= sizeLimit) { - auto bus = std::make_shared(sizeLimit, channelCount_, sampleRate_); + auto bus = std::make_shared(sizeLimit, channelCount_, sampleRate_); for (int i = 0; i < channelCount_; ++i) { - auto *outputChannel = bus->getChannel(i)->getData(); - circularBus_[i]->pop_front(outputChannel, sizeLimit); + circularBus_[i]->pop_front(*bus->getChannel(i), sizeLimit); } invokeCallback(bus, static_cast(sizeLimit)); } } -void AudioRecorderCallback::invokeCallback(const std::shared_ptr &bus, int numFrames) { - auto audioBuffer = std::make_shared(bus); - auto audioBufferHostObject = std::make_shared(audioBuffer); +void AudioRecorderCallback::invokeCallback(const std::shared_ptr &bus, int numFrames) { + auto audioBufferHostObject = std::make_shared(bus); std::unordered_map eventPayload = {}; eventPayload.insert({"buffer", audioBufferHostObject}); eventPayload.insert({"numFrames", numFrames}); if (audioEventHandlerRegistry_) { - audioEventHandlerRegistry_->invokeHandlerWithEventBody(AudioEvent::AUDIO_READY, callbackId_, eventPayload); + audioEventHandlerRegistry_->invokeHandlerWithEventBody( + AudioEvent::AUDIO_READY, callbackId_, eventPayload); } } @@ -98,7 +97,8 @@ void AudioRecorderCallback::invokeOnErrorCallback(const std::string &message) { } std::unordered_map eventPayload = {{"message", message}}; - audioEventHandlerRegistry_->invokeHandlerWithEventBody(AudioEvent::RECORDER_ERROR, callbackId, eventPayload); + audioEventHandlerRegistry_->invokeHandlerWithEventBody( + AudioEvent::RECORDER_ERROR, callbackId, eventPayload); } } // namespace audioapi diff --git a/packages/react-native-audio-api/common/cpp/audioapi/core/utils/AudioRecorderCallback.h b/packages/react-native-audio-api/common/cpp/audioapi/core/utils/AudioRecorderCallback.h index d35da9683..0d3d7656a 100644 --- a/packages/react-native-audio-api/common/cpp/audioapi/core/utils/AudioRecorderCallback.h +++ b/packages/react-native-audio-api/common/cpp/audioapi/core/utils/AudioRecorderCallback.h @@ -8,7 +8,7 @@ namespace audioapi { -class AudioBus; +class AudioBuffer; class AudioArray; class CircularAudioArray; class AudioEventHandlerRegistry; @@ -26,7 +26,7 @@ class AudioRecorderCallback { virtual void cleanup() = 0; void emitAudioData(bool flush = false); - void invokeCallback(const std::shared_ptr &bus, int numFrames); + void invokeCallback(const std::shared_ptr &bus, int numFrames); void setOnErrorCallback(uint64_t callbackId); void clearOnErrorCallback(); @@ -45,7 +45,7 @@ class AudioRecorderCallback { std::shared_ptr audioEventHandlerRegistry_; - // TODO: CircularAudioBus + // TODO: CircularAudioBuffer std::vector> circularBus_; }; diff --git a/packages/react-native-audio-api/common/cpp/audioapi/core/utils/AudioStretcher.cpp b/packages/react-native-audio-api/common/cpp/audioapi/core/utils/AudioStretcher.cpp index 3c84ebc50..1f650575e 100644 --- a/packages/react-native-audio-api/common/cpp/audioapi/core/utils/AudioStretcher.cpp +++ b/packages/react-native-audio-api/common/cpp/audioapi/core/utils/AudioStretcher.cpp @@ -1,9 +1,8 @@ -#include #include #include #include #include -#include +#include #include #include #include @@ -12,12 +11,12 @@ namespace audioapi { std::vector AudioStretcher::castToInt16Buffer(AudioBuffer &buffer) { const size_t numChannels = buffer.getNumberOfChannels(); - const size_t numFrames = buffer.getLength(); + const size_t numFrames = buffer.getSize(); std::vector int16Buffer(numFrames * numChannels); - for (size_t ch = 0; ch < numChannels; ++ch) { - const float *channelData = buffer.getChannelData(ch); + for (int ch = 0; ch < numChannels; ++ch) { + auto channelData = buffer.getChannel(ch)->span(); for (size_t i = 0; i < numFrames; ++i) { int16Buffer[i * numChannels + ch] = floatToInt16(channelData[i]); } @@ -31,7 +30,7 @@ std::shared_ptr AudioStretcher::changePlaybackSpeed( float playbackSpeed) { const float sampleRate = buffer.getSampleRate(); const size_t outputChannels = buffer.getNumberOfChannels(); - const size_t numFrames = buffer.getLength(); + const size_t numFrames = buffer.getSize(); if (playbackSpeed == 1.0f) { return std::make_shared(buffer); @@ -60,16 +59,16 @@ std::shared_ptr AudioStretcher::changePlaybackSpeed( stretchedBuffer.resize(outputFrames * outputChannels); stretch_deinit(stretcher); - auto audioBus = std::make_shared(outputFrames, outputChannels, sampleRate); + auto audioBus = std::make_shared(outputFrames, outputChannels, sampleRate); for (int ch = 0; ch < outputChannels; ++ch) { - auto channelData = audioBus->getChannel(ch)->getData(); + auto channelData = audioBus->getChannel(ch)->span(); for (int i = 0; i < outputFrames; ++i) { channelData[i] = int16ToFloat(stretchedBuffer[i * outputChannels + ch]); } } - return std::make_shared(audioBus); + return audioBus; } } // namespace audioapi diff --git a/packages/react-native-audio-api/common/cpp/audioapi/core/utils/AudioStretcher.h b/packages/react-native-audio-api/common/cpp/audioapi/core/utils/AudioStretcher.h index 2fbff057e..94d7894c6 100644 --- a/packages/react-native-audio-api/common/cpp/audioapi/core/utils/AudioStretcher.h +++ b/packages/react-native-audio-api/common/cpp/audioapi/core/utils/AudioStretcher.h @@ -5,7 +5,7 @@ namespace audioapi { -class AudioBus; +class AudioBuffer; class AudioBuffer; class AudioStretcher { diff --git a/packages/react-native-audio-api/common/cpp/audioapi/core/utils/ParamChangeEvent.cpp b/packages/react-native-audio-api/common/cpp/audioapi/core/utils/ParamChangeEvent.cpp deleted file mode 100644 index 32612d66c..000000000 --- a/packages/react-native-audio-api/common/cpp/audioapi/core/utils/ParamChangeEvent.cpp +++ /dev/null @@ -1,20 +0,0 @@ -#include -#include - -namespace audioapi { - -ParamChangeEvent::ParamChangeEvent( - double startTime, - double endTime, - float startValue, - float endValue, - std::function &&calculateValue, - ParamChangeEventType type) - : startTime_(startTime), - endTime_(endTime), - calculateValue_(std::move(calculateValue)), - startValue_(startValue), - endValue_(endValue), - type_(type) {} - -} // namespace audioapi diff --git a/packages/react-native-audio-api/common/cpp/audioapi/core/utils/ParamChangeEvent.h b/packages/react-native-audio-api/common/cpp/audioapi/core/utils/ParamChangeEvent.hpp similarity index 84% rename from packages/react-native-audio-api/common/cpp/audioapi/core/utils/ParamChangeEvent.h rename to packages/react-native-audio-api/common/cpp/audioapi/core/utils/ParamChangeEvent.hpp index afe93f0f1..506109959 100644 --- a/packages/react-native-audio-api/common/cpp/audioapi/core/utils/ParamChangeEvent.h +++ b/packages/react-native-audio-api/common/cpp/audioapi/core/utils/ParamChangeEvent.hpp @@ -17,18 +17,25 @@ class ParamChangeEvent { float startValue, float endValue, std::function &&calculateValue, - ParamChangeEventType type); + ParamChangeEventType type) + : startTime_(startTime), + endTime_(endTime), + calculateValue_(std::move(calculateValue)), + startValue_(startValue), + endValue_(endValue), + type_(type) {} ParamChangeEvent(const ParamChangeEvent &other) = delete; ParamChangeEvent &operator=(const ParamChangeEvent &other) = delete; - explicit ParamChangeEvent(ParamChangeEvent &&other) noexcept + ParamChangeEvent(ParamChangeEvent &&other) noexcept : startTime_(other.startTime_), endTime_(other.endTime_), calculateValue_(std::move(other.calculateValue_)), startValue_(other.startValue_), endValue_(other.endValue_), type_(other.type_) {} + ParamChangeEvent &operator=(ParamChangeEvent &&other) noexcept { if (this != &other) { startTime_ = other.startTime_; @@ -72,11 +79,11 @@ class ParamChangeEvent { } private: - double startTime_; - double endTime_; + double startTime_ = 0.0; + double endTime_ = 0.0; std::function calculateValue_; - float startValue_; - float endValue_; + float startValue_ = 0.0f; + float endValue_ = 0.0f; ParamChangeEventType type_; }; diff --git a/packages/react-native-audio-api/common/cpp/audioapi/dsp/AudioUtils.cpp b/packages/react-native-audio-api/common/cpp/audioapi/dsp/AudioUtils.cpp deleted file mode 100644 index cdfc33d63..000000000 --- a/packages/react-native-audio-api/common/cpp/audioapi/dsp/AudioUtils.cpp +++ /dev/null @@ -1,27 +0,0 @@ -#include - -namespace audioapi::dsp { -size_t timeToSampleFrame(double time, float sampleRate) { - return static_cast(time * sampleRate); -} - -double sampleFrameToTime(int sampleFrame, float sampleRate) { - return static_cast(sampleFrame) / sampleRate; -} - -float linearInterpolate(const float *source, size_t firstIndex, size_t secondIndex, float factor) { - if (firstIndex == secondIndex && firstIndex >= 1) { - return source[firstIndex] + factor * (source[firstIndex] - source[firstIndex - 1]); - } - - return source[firstIndex] + factor * (source[secondIndex] - source[firstIndex]); -} - -float linearToDecibels(float value) { - return 20 * log10f(value); -} - -float decibelsToLinear(float value) { - return pow(10, value / 20); -} -} // namespace audioapi::dsp \ No newline at end of file diff --git a/packages/react-native-audio-api/common/cpp/audioapi/dsp/AudioUtils.h b/packages/react-native-audio-api/common/cpp/audioapi/dsp/AudioUtils.h deleted file mode 100644 index f636021a9..000000000 --- a/packages/react-native-audio-api/common/cpp/audioapi/dsp/AudioUtils.h +++ /dev/null @@ -1,16 +0,0 @@ -#pragma once - -#include -#include -#include - -namespace audioapi::dsp { - -size_t timeToSampleFrame(double time, float sampleRate); -double sampleFrameToTime(int sampleFrame, float sampleRate); - -float linearInterpolate(const float *source, size_t firstIndex, size_t secondIndex, float factor); - -float linearToDecibels(float value); -float decibelsToLinear(float value); -} // namespace audioapi::dsp diff --git a/packages/react-native-audio-api/common/cpp/audioapi/dsp/AudioUtils.hpp b/packages/react-native-audio-api/common/cpp/audioapi/dsp/AudioUtils.hpp new file mode 100644 index 000000000..41bc36e42 --- /dev/null +++ b/packages/react-native-audio-api/common/cpp/audioapi/dsp/AudioUtils.hpp @@ -0,0 +1,38 @@ +#pragma once + +#include +#include +#include +#include + +namespace audioapi::dsp { + +[[nodiscard]] inline size_t timeToSampleFrame(double time, float sampleRate) { + return static_cast(time * sampleRate); +} + +[[nodiscard]] inline double sampleFrameToTime(int sampleFrame, float sampleRate) { + return static_cast(sampleFrame) / sampleRate; +} + +[[nodiscard]] inline float linearInterpolate( + std::span source, + size_t firstIndex, + size_t secondIndex, + float factor) { + + if (firstIndex == secondIndex && firstIndex >= 1) { + return source[firstIndex] + factor * (source[firstIndex] - source[firstIndex - 1]); + } + + return std::lerp(source[firstIndex], source[secondIndex], factor); +} + +[[nodiscard]] inline float linearToDecibels(float value) { + return 20 * log10f(value); +} + +[[nodiscard]] inline float decibelsToLinear(float value) { + return static_cast(pow(10, value / 20)); +} +} // namespace audioapi::dsp diff --git a/packages/react-native-audio-api/common/cpp/audioapi/dsp/Convolver.cpp b/packages/react-native-audio-api/common/cpp/audioapi/dsp/Convolver.cpp index 812cbe34c..5d23ef200 100644 --- a/packages/react-native-audio-api/common/cpp/audioapi/dsp/Convolver.cpp +++ b/packages/react-native-audio-api/common/cpp/audioapi/dsp/Convolver.cpp @@ -5,10 +5,10 @@ #include #endif -#include #include #include #include +#include #include #include #include @@ -17,17 +17,16 @@ namespace audioapi { Convolver::Convolver() - : _blockSize(0), + : _trueSegmentCount(0), + _blockSize(0), _segSize(0), _segCount(0), _fftComplexSize(0), _segments(), _segmentsIR(), - _fftBuffer(0), _fft(nullptr), _preMultiplied(), - _current(0), - _inputBuffer(0) {} + _current(0) {} void Convolver::reset() { _blockSize = 0; @@ -39,8 +38,8 @@ void Convolver::reset() { _segments.clear(); _segmentsIR.clear(); _preMultiplied.clear(); - _fftBuffer.zero(); - _inputBuffer.zero(); + _fftBuffer->zero(); + _inputBuffer->zero(); } bool Convolver::init(size_t blockSize, const audioapi::AudioArray &ir, size_t irLen) { @@ -71,7 +70,7 @@ bool Convolver::init(size_t blockSize, const audioapi::AudioArray &ir, size_t ir // complex-conjugate symmetricity _fftComplexSize = _segSize / 2 + 1; _fft = std::make_shared(static_cast(_segSize)); - _fftBuffer.resize(_segSize); + _fftBuffer = std::make_unique(_segSize); // segments preparation for (int i = 0; i < _segCount; ++i) { @@ -86,18 +85,18 @@ bool Convolver::init(size_t blockSize, const audioapi::AudioArray &ir, size_t ir const size_t samplesToCopy = std::min(_blockSize, remainingSamples); if (samplesToCopy > 0) { - memcpy(_fftBuffer.getData(), ir.getData() + i * _blockSize, samplesToCopy * sizeof(float)); + _fftBuffer->copy(ir, i * _blockSize, 0, samplesToCopy); } // Each sub filter is zero-padded to length 2B and transformed using a // 2B-point real-to-complex FFT. - memset(_fftBuffer.getData() + _blockSize, 0, _blockSize * sizeof(float)); - _fft->doFFT(_fftBuffer.getData(), segment); + _fftBuffer->zero(_blockSize, _blockSize); + _fft->doFFT(*_fftBuffer, segment); segment.at(0).imag(0.0f); // ensure DC component is real _segmentsIR.push_back(segment); } _preMultiplied = aligned_vec_complex(_fftComplexSize); - _inputBuffer.resize(_segSize); + _inputBuffer = std::make_unique(_segSize); _current = 0; return true; @@ -165,12 +164,12 @@ void pairwise_complex_multiply_fast( #endif } -void Convolver::process(float *data, float *outputData) { +void Convolver::process(const AudioArray &input, AudioArray &output) { // The input buffer acts as a 2B-point sliding window of the input signal. // With each new input block, the right half of the input buffer is shifted // to the left and the new block is stored in the right half. - memmove(_inputBuffer.getData(), _inputBuffer.getData() + _blockSize, _blockSize * sizeof(float)); - memcpy(_inputBuffer.getData() + _blockSize, data, _blockSize * sizeof(float)); + _inputBuffer->copy(*_inputBuffer, _blockSize, 0, _blockSize); + _inputBuffer->copy(input, 0, _blockSize, _blockSize); // All contents (DFT spectra) in the FDL are shifted up by one slot. _current = (_current > 0) ? _current - 1 : _segCount - 1; @@ -178,7 +177,7 @@ void Convolver::process(float *data, float *outputData) { // resulting in B+1 complex-conjugate symmetric DFT coefficients. The // result is stored in the first FDL slot. // _current marks first FDL slot, which is the current input block. - _fft->doFFT(_inputBuffer.getData(), _segments[_current]); + _fft->doFFT(*_inputBuffer, _segments[_current]); _segments[_current][0].imag(0.0f); // ensure DC component is real // The P sub filter spectra are pairwisely multiplied with the input spectra @@ -194,8 +193,8 @@ void Convolver::process(float *data, float *outputData) { // Of the accumulated spectral convolutions, an 2B-point complex-to-real // IFFT is computed. From the resulting 2B samples, the left half is // discarded and the right half is returned as the next output block. - _fft->doInverseFFT(_preMultiplied, _fftBuffer.getData()); + _fft->doInverseFFT(_preMultiplied, *_fftBuffer); - memcpy(outputData, _fftBuffer.getData() + _blockSize, _blockSize * sizeof(float)); + output.copy(*_fftBuffer, _blockSize, 0, _blockSize); } } // namespace audioapi diff --git a/packages/react-native-audio-api/common/cpp/audioapi/dsp/Convolver.h b/packages/react-native-audio-api/common/cpp/audioapi/dsp/Convolver.h index a356bf840..8d7b966cb 100644 --- a/packages/react-native-audio-api/common/cpp/audioapi/dsp/Convolver.h +++ b/packages/react-native-audio-api/common/cpp/audioapi/dsp/Convolver.h @@ -19,9 +19,9 @@ class Convolver { public: Convolver(); bool init(size_t blockSize, const AudioArray &ir, size_t irLen); - void process(float *inputData, float *outputData); + void process(const AudioArray &input, AudioArray &output); void reset(); - inline size_t getSegCount() const { + [[nodiscard]] inline size_t getSegCount() const { return _trueSegmentCount; } @@ -33,11 +33,11 @@ class Convolver { size_t _fftComplexSize; std::vector _segments; std::vector _segmentsIR; - AudioArray _fftBuffer; + std::unique_ptr _fftBuffer; std::shared_ptr _fft; aligned_vec_complex _preMultiplied; size_t _current; - AudioArray _inputBuffer; + std::unique_ptr _inputBuffer; friend void pairwise_complex_multiply_fast( const aligned_vec_complex &ir, diff --git a/packages/react-native-audio-api/common/cpp/audioapi/dsp/Resampler.cpp b/packages/react-native-audio-api/common/cpp/audioapi/dsp/Resampler.cpp index c90f9bc9d..80a262f18 100644 --- a/packages/react-native-audio-api/common/cpp/audioapi/dsp/Resampler.cpp +++ b/packages/react-native-audio-api/common/cpp/audioapi/dsp/Resampler.cpp @@ -44,7 +44,7 @@ namespace audioapi { Resampler::Resampler(int maxBlockSize, int kernelSize): kernelSize_(kernelSize), kernel_(std::make_shared(kernelSize)), - stateBuffer_(std::make_shared(2 * maxBlockSize)) { + stateBuffer_(std::make_unique(2 * maxBlockSize)) { stateBuffer_->zero(); } @@ -58,35 +58,6 @@ float Resampler::computeBlackmanWindow(double x) const { return static_cast(a0 - a1 * std::cos(2.0 * PI * n) + a2 * std::cos(4.0 * PI * n)); } -float Resampler::computeConvolution(const float *stateStart, const float *kernelStart) const { - float sum = 0.0f; - int k = 0; - -#ifdef __ARM_NEON - float32x4_t vSum = vdupq_n_f32(0.0f); - - // process 4 samples at a time - for (; k <= kernelSize_ - 4; k += 4) { - float32x4_t vState = vld1q_f32(stateStart + k); - float32x4_t vKernel = vld1q_f32(kernelStart + k); - - // fused multiply-add: vSum += vState * vKernel - vSum = vmlaq_f32(vSum, vState, vKernel); - } - - // horizontal reduction: Sum the 4 lanes of vSum into a single float - sum += vgetq_lane_f32(vSum, 0); - sum += vgetq_lane_f32(vSum, 1); - sum += vgetq_lane_f32(vSum, 2); - sum += vgetq_lane_f32(vSum, 3); -#endif - for (; k < kernelSize_; ++k) { - sum += stateStart[k] * kernelStart[k]; - } - - return sum; -} - void Resampler::reset() { if (stateBuffer_) { stateBuffer_->zero(); @@ -98,7 +69,6 @@ UpSampler::UpSampler(int maxBlockSize, int kernelSize) : Resampler(maxBlockSize, } void UpSampler::initializeKernel() { - auto kData = kernel_->getData(); int halfSize = kernelSize_ / 2; double subSampleOffset = -0.5; @@ -111,39 +81,33 @@ void UpSampler::initializeKernel() { double sinc = (std::abs(x) < 1e-9) ? 1.0 : std::sin(x * PI) / (x * PI); // apply window in order smooth out the edges, because sinc extends to infinity in both directions - kData[i] = static_cast(sinc * computeBlackmanWindow(i - subSampleOffset)); + (*kernel_)[i] = static_cast(sinc * computeBlackmanWindow(i - subSampleOffset)); } // reverse kernel to match convolution implementation - std::reverse(kData, kData + kernelSize_); + kernel_->reverse(); } int UpSampler::process( - const std::shared_ptr &input, - const std::shared_ptr &output, + AudioArray& input, + AudioArray& output, int framesToProcess) { - - const float *inputData = input->getData(); - float *outputData = output->getData(); - float *state = stateBuffer_->getData(); - const float *kernel = kernel_->getData(); - // copy new input [ HISTORY | NEW DATA ] - std::memcpy(state + kernelSize_, inputData, framesToProcess * sizeof(float)); + stateBuffer_->copy(input, 0, kernelSize_, framesToProcess); int halfKernel = kernelSize_ / 2; for (int i = 0; i < framesToProcess; ++i) { // direct copy for even samples with half kernel latency compensation - outputData[2 * i] = state[kernelSize_ + i - halfKernel]; + output[2 * i] = (*stateBuffer_)[kernelSize_ + i - halfKernel]; // convolution for odd samples // symmetric Linear Phase filter has latency of half kernel size - outputData[2 * i + 1] = computeConvolution(&state[i + 1], kernel); + output[2 * i + 1] = stateBuffer_->computeConvolution(*kernel_, i + 1); } // move new data to history [ NEW DATA | EMPTY ] - std::memmove(state, state + framesToProcess, kernelSize_ * sizeof(float)); + stateBuffer_->copy(*stateBuffer_, framesToProcess, 0, kernelSize_); return framesToProcess * 2; } @@ -153,7 +117,6 @@ DownSampler::DownSampler(int maxBlockSize, int kernelSize) : Resampler(maxBlockS } void DownSampler::initializeKernel() { - auto kData = kernel_->getData(); int halfSize = kernelSize_ / 2; for (int i = 0; i < kernelSize_; ++i) { @@ -166,34 +129,29 @@ void DownSampler::initializeKernel() { sinc *= 0.5; // apply window in order smooth out the edges, because sinc extends to infinity in both directions - kData[i] = static_cast(sinc * computeBlackmanWindow(i)); + (*kernel_)[i] = static_cast(sinc * computeBlackmanWindow(i)); } // reverse kernel to match convolution implementation - std::reverse(kData, kData + kernelSize_); + kernel_->reverse(); } int DownSampler::process( - const std::shared_ptr &input, - const std::shared_ptr &output, + AudioArray& input, + AudioArray& output, int framesToProcess) { - const float *inputData = input->getData(); - float *outputData = output->getData(); - float *state = stateBuffer_->getData(); - const float *kernel = kernel_->getData(); - // copy new input [ HISTORY | NEW DATA ] - std::memcpy(state + kernelSize_, inputData, framesToProcess * sizeof(float)); + stateBuffer_->copy(input, 0, kernelSize_, framesToProcess); auto outputCount = framesToProcess / 2; for (int i = 0; i < outputCount; ++i) { // convolution for downsampled samples - outputData[i] = computeConvolution(&state[2 * i + 1], kernel); + output[i] = stateBuffer_->computeConvolution(*kernel_, 2 * i + 1); } // move new data to history [ NEW DATA | EMPTY ] - std::memmove(state, state + framesToProcess, kernelSize_ * sizeof(float)); + stateBuffer_->copy(*stateBuffer_, framesToProcess, 0, kernelSize_); return outputCount; } diff --git a/packages/react-native-audio-api/common/cpp/audioapi/dsp/Resampler.h b/packages/react-native-audio-api/common/cpp/audioapi/dsp/Resampler.h index 4a99f9f45..08b748f0c 100644 --- a/packages/react-native-audio-api/common/cpp/audioapi/dsp/Resampler.h +++ b/packages/react-native-audio-api/common/cpp/audioapi/dsp/Resampler.h @@ -16,22 +16,18 @@ class Resampler { Resampler(int maxBlockSize, int kernelSize); virtual ~Resampler() = default; - virtual int process( - const std::shared_ptr &input, - const std::shared_ptr &output, - int framesToProcess) = 0; + virtual int process(AudioArray &input, AudioArray &output, int framesToProcess) = 0; void reset(); protected: [[nodiscard]] float computeBlackmanWindow(double x) const; - float computeConvolution(const float *stateStart, const float *kernelStart) const; virtual void initializeKernel() = 0; int kernelSize_; std::shared_ptr kernel_; // [ HISTORY | NEW DATA ] - std::shared_ptr stateBuffer_; + std::unique_ptr stateBuffer_; }; class UpSampler : public Resampler { @@ -39,10 +35,7 @@ class UpSampler : public Resampler { UpSampler(int maxBlockSize, int kernelSize); // N -> 2N - int process( - const std::shared_ptr &input, - const std::shared_ptr &output, - int framesToProcess) override; + int process(AudioArray &input, AudioArray &output, int framesToProcess) override; protected: void initializeKernel() final; @@ -53,10 +46,7 @@ class DownSampler : public Resampler { DownSampler(int maxBlockSize, int kernelSize); // N -> N / 2 - int process( - const std::shared_ptr &input, - const std::shared_ptr &output, - int framesToProcess) override; + int process(AudioArray &input, AudioArray &output, int framesToProcess) override; protected: void initializeKernel() final; diff --git a/packages/react-native-audio-api/common/cpp/audioapi/dsp/VectorMath.cpp b/packages/react-native-audio-api/common/cpp/audioapi/dsp/VectorMath.cpp index 4e0ffd3fa..379dd3dfd 100644 --- a/packages/react-native-audio-api/common/cpp/audioapi/dsp/VectorMath.cpp +++ b/packages/react-native-audio-api/common/cpp/audioapi/dsp/VectorMath.cpp @@ -23,7 +23,7 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#include +#include #include #include diff --git a/packages/react-native-audio-api/common/cpp/audioapi/dsp/WaveShaper.cpp b/packages/react-native-audio-api/common/cpp/audioapi/dsp/WaveShaper.cpp index 9ee3c7207..cd846c2ae 100644 --- a/packages/react-native-audio-api/common/cpp/audioapi/dsp/WaveShaper.cpp +++ b/packages/react-native-audio-api/common/cpp/audioapi/dsp/WaveShaper.cpp @@ -2,7 +2,7 @@ #include #include #include -#include +#include #include #include @@ -46,7 +46,7 @@ void WaveShaper::setOversample(OverSampleType type) { } } -void WaveShaper::process(const std::shared_ptr &channelData, int framesToProcess) { +void WaveShaper::process(AudioArray &channelData, int framesToProcess) { if (curve_ == nullptr) { return; } @@ -66,40 +66,39 @@ void WaveShaper::process(const std::shared_ptr &channelData, int fra } // based on https://webaudio.github.io/web-audio-api/#WaveShaperNode -void WaveShaper::processNone(const std::shared_ptr &channelData, int framesToProcess) { - auto curveArray = curve_->getData(); +void WaveShaper::processNone(AudioArray &channelData, int framesToProcess) { auto curveSize = curve_->getSize(); - auto data = channelData->getData(); - for (int i = 0; i < framesToProcess; i++) { - float v = (static_cast(curveSize) - 1) * 0.5f * (data[i] + 1.0f); + float v = (static_cast(curveSize) - 1) * 0.5f * (channelData[i] + 1.0f); if (v <= 0) { - data[i] = curveArray[0]; + channelData[i] = (*curve_)[0]; } else if (v >= static_cast(curveSize) - 1) { - data[i] = curveArray[curveSize - 1]; + channelData[i] = (*curve_)[curveSize - 1]; } else { auto k = std::floor(v); auto f = v - k; auto kIndex = static_cast(k); - data[i] = (1 - f) * curveArray[kIndex] + f * curveArray[kIndex + 1]; + channelData[i] = (1 - f) * (*curve_)[kIndex] + f * (*curve_)[kIndex + 1]; } } } -void WaveShaper::process2x(const std::shared_ptr &channelData, int framesToProcess) { - auto outputFrames = upSampler_->process(channelData, tempBuffer2x_, framesToProcess); - processNone(tempBuffer2x_, outputFrames); - downSampler_->process(tempBuffer2x_, channelData, outputFrames); +void WaveShaper::process2x(AudioArray &channelData, int framesToProcess) { + auto outputFrames = upSampler_->process(channelData, *tempBuffer2x_, framesToProcess); + processNone(*tempBuffer2x_, outputFrames); + downSampler_->process(*tempBuffer2x_, channelData, outputFrames); } -void WaveShaper::process4x(const std::shared_ptr &channelData, int framesToProcess) { - auto upSamplerOutputFrames = upSampler_->process(channelData, tempBuffer2x_, framesToProcess); - auto upSampler2OutputFrames = upSampler2_->process(tempBuffer2x_, tempBuffer4x_, upSamplerOutputFrames); - processNone(tempBuffer4x_, upSampler2OutputFrames); - auto downSampler2OutputFrames = downSampler2_->process(tempBuffer4x_, tempBuffer2x_, upSampler2OutputFrames); - downSampler_->process(tempBuffer2x_, channelData, downSampler2OutputFrames); +void WaveShaper::process4x(AudioArray &channelData, int framesToProcess) { + auto upSamplerOutputFrames = upSampler_->process(channelData, *tempBuffer2x_, framesToProcess); + auto upSampler2OutputFrames = + upSampler2_->process(*tempBuffer2x_, *tempBuffer4x_, upSamplerOutputFrames); + processNone(*tempBuffer4x_, upSampler2OutputFrames); + auto downSampler2OutputFrames = + downSampler2_->process(*tempBuffer4x_, *tempBuffer2x_, upSampler2OutputFrames); + downSampler_->process(*tempBuffer2x_, channelData, downSampler2OutputFrames); } } // namespace audioapi diff --git a/packages/react-native-audio-api/common/cpp/audioapi/dsp/WaveShaper.h b/packages/react-native-audio-api/common/cpp/audioapi/dsp/WaveShaper.h index fd5a04b44..9db0bffd5 100644 --- a/packages/react-native-audio-api/common/cpp/audioapi/dsp/WaveShaper.h +++ b/packages/react-native-audio-api/common/cpp/audioapi/dsp/WaveShaper.h @@ -11,14 +11,14 @@ namespace audioapi { -class AudioBus; +class AudioBuffer; class AudioArray; class WaveShaper { public: explicit WaveShaper(const std::shared_ptr &curve); - void process(const std::shared_ptr &channelData, int framesToProcess); + void process(AudioArray &channelData, int framesToProcess); void setCurve(const std::shared_ptr &curve); void setOversample(OverSampleType type); @@ -38,9 +38,9 @@ class WaveShaper { std::shared_ptr tempBuffer2x_; std::shared_ptr tempBuffer4x_; - void processNone(const std::shared_ptr &channelData, int framesToProcess); - void process2x(const std::shared_ptr &channelData, int framesToProcess); - void process4x(const std::shared_ptr &channelData, int framesToProcess); + void processNone(AudioArray &channelData, int framesToProcess); + void process2x(AudioArray &channelData, int framesToProcess); + void process4x(AudioArray &channelData, int framesToProcess); }; } // namespace audioapi diff --git a/packages/react-native-audio-api/common/cpp/audioapi/dsp/Windows.cpp b/packages/react-native-audio-api/common/cpp/audioapi/dsp/Windows.cpp deleted file mode 100644 index 79f7948ec..000000000 --- a/packages/react-native-audio-api/common/cpp/audioapi/dsp/Windows.cpp +++ /dev/null @@ -1,75 +0,0 @@ -#include -#include -#include - -namespace audioapi::dsp { - -void WindowFunction::forcePerfectReconstruction(float *data, int windowLength, int interval) { - for (int i = 0; i < interval; ++i) { - float sum2 = 0; - - for (int index = i; index < windowLength; index += interval) { - sum2 += data[index] * data[index]; - } - - float factor = 1 / std::sqrt(sum2); - - for (int index = i; index < windowLength; index += interval) { - data[index] *= factor; - } - } -} - -void Hann::apply(float *data, int size) const { - for (int i = 0; i < size; ++i) { - auto x = static_cast(i) / static_cast(size - 1); - auto window = 0.5f - 0.5f * cos(2 * PI * x); - data[i] = window * amplitude_; - } -} - -void Blackman::apply(float *data, int size) const { - for (int i = 0; i < size; ++i) { - auto x = static_cast(i) / static_cast(size - 1); - auto window = 0.42f - 0.5f * cos(2 * PI * x) + 0.08f * cos(4 * PI * x); - data[i] = window * amplitude_; - } -} - -void Kaiser::apply(float *data, int size) const { - for (int i = 0; i < size; ++i) { - auto r = static_cast(2 * i + 1) / static_cast(size) - 1.0f; - auto arg = std::sqrt(1 - r * r); - data[i] = bessel0(beta_ * arg) * invB0_ * amplitude_; - } -} - -float Kaiser::bandwidthToBeta(float bandwidth, bool heuristicOptimal) { - if (heuristicOptimal) { // Heuristic based on numerical search - return bandwidth + 8.0f / (bandwidth + 3.0f) * (bandwidth + 3.0f) + - 0.25f * std::max(3.0f - bandwidth, 0.0f); - } - - bandwidth = std::max(bandwidth, 2.0f); - auto alpha = std::sqrt(bandwidth * bandwidth * 0.25f - 1.0f); - return alpha * PI; -} - -void ApproximateConfinedGaussian::apply(float *data, int size) const { - auto offsetScale = getGaussian(1.0f) / (getGaussian(3.0f) + getGaussian(-1.0f)); - auto norm = 1 / (getGaussian(1.0f) - 2 * offsetScale * getGaussian(2.0f)); - for (int i = 0; i < size; ++i) { - auto r = static_cast(2 * i + 1) / static_cast(size) - 1.0f; - data[i] = norm * (getGaussian(r) - offsetScale * (getGaussian(r - 2) + getGaussian(r + 2))); - } -} - -float ApproximateConfinedGaussian::bandwidthToSigma(float bandwidth) { - return 0.3f / std::sqrt(bandwidth); -} - -float ApproximateConfinedGaussian::getGaussian(float x) const { - return std::exp(-x * x * gaussianFactor_); -} - -} // namespace audioapi::dsp diff --git a/packages/react-native-audio-api/common/cpp/audioapi/dsp/Windows.h b/packages/react-native-audio-api/common/cpp/audioapi/dsp/Windows.h deleted file mode 100644 index 8108e18a3..000000000 --- a/packages/react-native-audio-api/common/cpp/audioapi/dsp/Windows.h +++ /dev/null @@ -1,96 +0,0 @@ -#pragma once - -#include - -namespace audioapi::dsp { - -// https://en.wikipedia.org/wiki/Window_function -// https://personalpages.hs-kempten.de/~vollratj/InEl/pdf/Window%20function%20-%20Wikipedia.pdf -class WindowFunction { - public: - explicit WindowFunction(float amplitude = 1.0f) : amplitude_(amplitude) {} - - virtual void apply(float *data, int size) const = 0; - // forces STFT perfect-reconstruction (WOLA) on an existing window, for a given STFT interval. - static void forcePerfectReconstruction(float *data, int windowLength, int interval); - - protected: - // 1/L = amplitude - float amplitude_; -}; - -//https://en.wikipedia.org/wiki/Hann_function -// https://www.sciencedirect.com/topics/engineering/hanning-window -// https://docs.scipy.org/doc//scipy-1.2.3/reference/generated/scipy.signal.windows.hann.html#scipy.signal.windows.hann -class Hann : public WindowFunction { - public: - explicit Hann(float amplitude = 1.0f) : WindowFunction(amplitude) {} - - void apply(float *data, int size) const override; -}; - -// https://www.sciencedirect.com/topics/engineering/blackman-window -// https://docs.scipy.org/doc//scipy-1.2.3/reference/generated/scipy.signal.windows.blackman.html#scipy.signal.windows.blackman -class Blackman : public WindowFunction { - public: - explicit Blackman(float amplitude = 1.0f) : WindowFunction(amplitude) {} - - void apply(float *data, int size) const override; -}; - -// https://en.wikipedia.org/wiki/Kaiser_window -class Kaiser : public WindowFunction { - public: - explicit Kaiser(float beta, float amplitude = 1.0f) - : WindowFunction(amplitude), beta_(beta), invB0_(1.0f / bessel0(beta)) {} - - static Kaiser - withBandwidth(float bandwidth, bool heuristicOptimal = false, float amplitude = 1.0f) { - return Kaiser(bandwidthToBeta(bandwidth, heuristicOptimal), amplitude); - } - - void apply(float *data, int size) const override; - - private: - // beta = pi * alpha - // invB0 = 1 / I0(beta) - float beta_; - float invB0_; - - // https://en.wikipedia.org/wiki/Bessel_function#Modified_Bessel_functions:_I%CE%B1,_K%CE%B1 - static inline float bessel0(float x) { - const double significanceLimit = 1e-4; - auto result = 0.0f; - auto term = 1.0f; - auto m = 1.0f; - while (term > significanceLimit) { - result += term; - ++m; - term *= (x * x) / (4 * m * m); - } - - return result; - } - static float bandwidthToBeta(float bandwidth, bool heuristicOptimal = false); -}; - -// https://www.recordingblogs.com/wiki/gaussian-window -class ApproximateConfinedGaussian : public WindowFunction { - public: - explicit ApproximateConfinedGaussian(float sigma, float amplitude = 1.0f) - : WindowFunction(amplitude), gaussianFactor_(0.0625f / (sigma * sigma)) {} - - static ApproximateConfinedGaussian withBandwidth(float bandwidth, float amplitude = 1.0f) { - return ApproximateConfinedGaussian(bandwidthToSigma(bandwidth), amplitude); - } - - void apply(float *data, int size) const override; - - private: - float gaussianFactor_; - - static float bandwidthToSigma(float bandwidth); - - [[nodiscard]] float getGaussian(float x) const; -}; -} // namespace audioapi::dsp diff --git a/packages/react-native-audio-api/common/cpp/audioapi/dsp/Windows.hpp b/packages/react-native-audio-api/common/cpp/audioapi/dsp/Windows.hpp new file mode 100644 index 000000000..7c66985dc --- /dev/null +++ b/packages/react-native-audio-api/common/cpp/audioapi/dsp/Windows.hpp @@ -0,0 +1,196 @@ +#pragma once + +#include +#include +#include + +namespace audioapi::dsp { + +// https://en.wikipedia.org/wiki/Window_function +// https://personalpages.hs-kempten.de/~vollratj/InEl/pdf/Window%20function%20-%20Wikipedia.pdf +class WindowFunction { + public: + explicit WindowFunction(float amplitude = 1.0f) : amplitude_(amplitude) {} + + virtual void apply(std::span data) const noexcept = 0; + // forces STFT perfect-reconstruction (WOLA) on an existing window, for a given STFT interval. + static void forcePerfectReconstruction(std::span data, int interval) { + int windowLength = static_cast(data.size()); + + for (int i = 0; i < interval; ++i) { + float sum2 = 0; + + for (int index = i; index < windowLength; index += interval) { + sum2 += data[index] * data[index]; + } + + float factor = 1 / std::sqrt(sum2); + + for (int index = i; index < windowLength; index += interval) { + data[index] *= factor; + } + } + } + + protected: + // 1/L = amplitude + float amplitude_; +}; + +//https://en.wikipedia.org/wiki/Hann_function +// https://www.sciencedirect.com/topics/engineering/hanning-window +// https://docs.scipy.org/doc//scipy-1.2.3/reference/generated/scipy.signal.windows.hann.html#scipy.signal.windows.hann +class Hann : public WindowFunction { + public: + explicit Hann(float amplitude = 1.0f) : WindowFunction(amplitude) {} + + void apply(std::span data) const noexcept override { + const size_t size = data.size(); + if (size < 2) { + return; + } + + const float invSizeMinusOne = 1.0f / static_cast(size - 1); + const float constantPart = 2.0f * std::numbers::pi_v * invSizeMinusOne; + + for (size_t i = 0; i < size; ++i) { + float window = 0.5f * (1.0f - std::cos(constantPart * i)); + data[i] = window * amplitude_; + } + } +}; + +// https://www.sciencedirect.com/topics/engineering/blackman-window +// https://docs.scipy.org/doc//scipy-1.2.3/reference/generated/scipy.signal.windows.blackman.html#scipy.signal.windows.blackman +class Blackman : public WindowFunction { + public: + explicit Blackman(float amplitude = 1.0f) : WindowFunction(amplitude) {} + + void apply(std::span data) const noexcept override { + const size_t size = data.size(); + if (size < 2) { + return; + } + + const float invSizeMinusOne = 1.0f / static_cast(size - 1); + const float alpha = 2.0f * std::numbers::pi_v * invSizeMinusOne; + + for (size_t i = 0; i < size; ++i) { + const float phase = alpha * i; + // 4*PI*x is just 2 * (2*PI*x) + const float window = 0.42f - 0.50f * std::cos(phase) + 0.08f * std::cos(2.0f * phase); + data[i] = window * amplitude_; + } + } +}; + +// https://en.wikipedia.org/wiki/Kaiser_window +class Kaiser : public WindowFunction { + public: + explicit Kaiser(float beta, float amplitude = 1.0f) + : WindowFunction(amplitude), beta_(beta), invB0_(1.0f / bessel0(beta)) {} + + static Kaiser + withBandwidth(float bandwidth, bool heuristicOptimal = false, float amplitude = 1.0f) { + return Kaiser(bandwidthToBeta(bandwidth, heuristicOptimal), amplitude); + } + + void apply(std::span data) const noexcept override { + const size_t size = data.size(); + if (size == 0) { + return; + } + + const float invSize = 1.0f / static_cast(size); + const float commonScale = invB0_ * amplitude_; + + for (size_t i = 0; i < size; ++i) { + // Optimized 'r' calculation: (2i+1)/size - 1 + const float r = (static_cast(2 * i + 1) * invSize) - 1.0f; + const float arg = std::sqrt(std::max(0.0f, 1.0f - r * r)); + + data[i] = bessel0(beta_ * arg) * commonScale; + } + } + + private: + // beta = pi * alpha + // invB0 = 1 / I0(beta) + float beta_; + float invB0_; + + // https://en.wikipedia.org/wiki/Bessel_function#Modified_Bessel_functions:_I%CE%B1,_K%CE%B1 + static inline float bessel0(float x) { + const double significanceLimit = 1e-4; + auto result = 0.0f; + auto term = 1.0f; + auto m = 1.0f; + while (term > significanceLimit) { + result += term; + ++m; + term *= (x * x) / (4 * m * m); + } + + return result; + } + inline static float bandwidthToBeta(float bandwidth, bool heuristicOptimal = false) { + if (heuristicOptimal) { // Heuristic based on numerical search + return bandwidth + 8.0f / (bandwidth + 3.0f) * (bandwidth + 3.0f) + + 0.25f * std::max(3.0f - bandwidth, 0.0f); + } + + bandwidth = std::max(bandwidth, 2.0f); + auto alpha = std::sqrt(bandwidth * bandwidth * 0.25f - 1.0f); + return alpha * PI; + } +}; + +// https://www.recordingblogs.com/wiki/gaussian-window +class ApproximateConfinedGaussian : public WindowFunction { + public: + explicit ApproximateConfinedGaussian(float sigma, float amplitude = 1.0f) + : WindowFunction(amplitude), gaussianFactor_(0.0625f / (sigma * sigma)) {} + + static ApproximateConfinedGaussian withBandwidth(float bandwidth, float amplitude = 1.0f) { + return ApproximateConfinedGaussian(bandwidthToSigma(bandwidth), amplitude); + } + + void apply(std::span data) const noexcept override { + const size_t size = data.size(); + if (size == 0) + return; + + const float g1 = getGaussian(1.0f); + const float g3 = getGaussian(3.0f); + const float g_1 = getGaussian(-1.0f); + const float g2 = getGaussian(2.0f); + + const float offsetScale = g1 / (g3 + g_1); + const float norm = 1.0f / (g1 - 2.0f * offsetScale * g2); + + const float invSize = 1.0f / static_cast(size); + const float totalAmplitude = norm * amplitude_; + + for (size_t i = 0; i < size; ++i) { + const float r = (static_cast(2 * i + 1) * invSize) - 1.0f; + + const float gR = getGaussian(r); + const float gRMinus2 = getGaussian(r - 2.0f); + const float gRPlus2 = getGaussian(r + 2.0f); + + data[i] = totalAmplitude * (gR - offsetScale * (gRMinus2 + gRPlus2)); + } + } + + private: + float gaussianFactor_; + + inline static float bandwidthToSigma(float bandwidth) noexcept { + return 0.3f / std::sqrt(bandwidth); + } + + [[nodiscard]] inline float getGaussian(float x) const noexcept { + return std::exp(-x * x * gaussianFactor_); + } +}; +} // namespace audioapi::dsp diff --git a/packages/react-native-audio-api/common/cpp/audioapi/jsi/AudioArrayBuffer.cpp b/packages/react-native-audio-api/common/cpp/audioapi/jsi/AudioArrayBuffer.cpp deleted file mode 100644 index 59bf02153..000000000 --- a/packages/react-native-audio-api/common/cpp/audioapi/jsi/AudioArrayBuffer.cpp +++ /dev/null @@ -1,13 +0,0 @@ -#include - -namespace audioapi { - -size_t AudioArrayBuffer::size() const { - return audioArray_->getSize() * sizeof(float); -} - -uint8_t *AudioArrayBuffer::data() { - return reinterpret_cast(audioArray_->getData()); -} - -} // namespace audioapi diff --git a/packages/react-native-audio-api/common/cpp/audioapi/jsi/AudioArrayBuffer.h b/packages/react-native-audio-api/common/cpp/audioapi/jsi/AudioArrayBuffer.h deleted file mode 100644 index 6469ae13a..000000000 --- a/packages/react-native-audio-api/common/cpp/audioapi/jsi/AudioArrayBuffer.h +++ /dev/null @@ -1,34 +0,0 @@ -#pragma once - -#include -#include - -#include -#include - -namespace audioapi { - -using namespace facebook; - -class AudioArrayBuffer : public jsi::MutableBuffer { - public: - explicit AudioArrayBuffer(const std::shared_ptr &audioArray) - : audioArray_(audioArray) {} - ~AudioArrayBuffer() override = default; - - AudioArrayBuffer(AudioArrayBuffer &&other) noexcept : audioArray_(std::move(other.audioArray_)) { - other.audioArray_ = nullptr; - } - - AudioArrayBuffer(const AudioArrayBuffer &) = delete; - AudioArrayBuffer &operator=(const AudioArrayBuffer &) = delete; - AudioArrayBuffer &operator=(AudioArrayBuffer &&other) = delete; - - [[nodiscard]] size_t size() const override; - uint8_t *data() override; - - private: - std::shared_ptr audioArray_; -}; - -} // namespace audioapi diff --git a/packages/react-native-audio-api/common/cpp/audioapi/libs/ffmpeg/FFmpegDecoding.cpp b/packages/react-native-audio-api/common/cpp/audioapi/libs/ffmpeg/FFmpegDecoding.cpp index 32c10d691..1773bab53 100644 --- a/packages/react-native-audio-api/common/cpp/audioapi/libs/ffmpeg/FFmpegDecoding.cpp +++ b/packages/react-native-audio-api/common/cpp/audioapi/libs/ffmpeg/FFmpegDecoding.cpp @@ -8,12 +8,12 @@ * FFmpeg, you must comply with the terms of the LGPL for FFmpeg itself. */ -#include +#include #if !RN_AUDIO_API_FFMPEG_DISABLED #include #endif // RN_AUDIO_API_FFMPEG_DISABLED #include -#include +#include #include namespace audioapi::ffmpegdecoder { @@ -25,8 +25,7 @@ int read_packet(void *opaque, uint8_t *buf, int buf_size) { return AVERROR_EOF; } - int bytes_to_read = - std::min(buf_size, static_cast(ctx->size - ctx->pos)); + int bytes_to_read = std::min(buf_size, static_cast(ctx->size - ctx->pos)); memcpy(buf, ctx->data + ctx->pos, bytes_to_read); ctx->pos += bytes_to_read; @@ -91,13 +90,9 @@ void convertFrameToBuffer( if (converted_samples > 0) { const size_t current_size = buffer.size(); - const size_t new_samples = - static_cast(converted_samples) * output_channel_count; + const size_t new_samples = static_cast(converted_samples) * output_channel_count; buffer.resize(current_size + new_samples); - memcpy( - buffer.data() + current_size, - resampled_data[0], - new_samples * sizeof(float)); + memcpy(buffer.data() + current_size, resampled_data[0], new_samples * sizeof(float)); framesRead += converted_samples; } } @@ -206,8 +201,7 @@ inline int findAudioStreamIndex(AVFormatContext *fmt_ctx) { bool setupDecoderContext( AVFormatContext *fmt_ctx, int &audio_stream_index, - std::unique_ptr> - &codec_ctx) { + std::unique_ptr> &codec_ctx) { audio_stream_index = findAudioStreamIndex(fmt_ctx); if (audio_stream_index == -1) { return false; @@ -241,37 +235,30 @@ std::shared_ptr decodeAudioFrames( int audio_stream_index, int sample_rate) { size_t framesRead = 0; - int output_sample_rate = - (sample_rate > 0) ? sample_rate : codec_ctx->sample_rate; + int output_sample_rate = (sample_rate > 0) ? sample_rate : codec_ctx->sample_rate; int output_channel_count = codec_ctx->ch_layout.nb_channels; std::vector decoded_buffer = readAllPcmFrames( - fmt_ctx, - codec_ctx, - output_sample_rate, - output_channel_count, - audio_stream_index, - framesRead); + fmt_ctx, codec_ctx, output_sample_rate, output_channel_count, audio_stream_index, framesRead); if (framesRead == 0 || decoded_buffer.empty()) { return nullptr; } auto outputFrames = decoded_buffer.size() / output_channel_count; - auto audioBus = std::make_shared( - outputFrames, output_channel_count, output_sample_rate); + auto audioBus = + std::make_shared(outputFrames, output_channel_count, output_sample_rate); for (int ch = 0; ch < output_channel_count; ++ch) { - auto channelData = audioBus->getChannel(ch)->getData(); + auto channelData = audioBus->getChannel(ch)->span(); for (int i = 0; i < outputFrames; ++i) { channelData[i] = decoded_buffer[i * output_channel_count + ch]; } } - return std::make_shared(audioBus); + return audioBus; } -std::shared_ptr -decodeWithMemoryBlock(const void *data, size_t size, int sample_rate) { +std::shared_ptr decodeWithMemoryBlock(const void *data, size_t size, int sample_rate) { if (data == nullptr || size == 0) { return nullptr; } @@ -284,17 +271,9 @@ decodeWithMemoryBlock(const void *data, size_t size, int sample_rate) { return nullptr; } - auto avio_ctx = - std::unique_ptr>( - avio_alloc_context( - io_buffer, - buffer_size, - 0, - &io_ctx, - read_packet, - nullptr, - seek_packet), - [](AVIOContext *ctx) { avio_context_free(&ctx); }); + auto avio_ctx = std::unique_ptr>( + avio_alloc_context(io_buffer, buffer_size, 0, &io_ctx, read_packet, nullptr, seek_packet), + [](AVIOContext *ctx) { avio_context_free(&ctx); }); if (avio_ctx == nullptr) { return nullptr; } @@ -310,29 +289,24 @@ decodeWithMemoryBlock(const void *data, size_t size, int sample_rate) { return nullptr; } - auto fmt_ctx = - std::unique_ptr( - raw_fmt_ctx, &avformat_free_context); + auto fmt_ctx = std::unique_ptr( + raw_fmt_ctx, &avformat_free_context); if (avformat_find_stream_info(fmt_ctx.get(), nullptr) < 0) { return nullptr; } - auto codec_ctx = - std::unique_ptr>( - nullptr, [](AVCodecContext *ctx) { avcodec_free_context(&ctx); }); + auto codec_ctx = std::unique_ptr>( + nullptr, [](AVCodecContext *ctx) { avcodec_free_context(&ctx); }); int audio_stream_index = -1; if (!setupDecoderContext(fmt_ctx.get(), audio_stream_index, codec_ctx)) { return nullptr; } - return decodeAudioFrames( - fmt_ctx.get(), codec_ctx.get(), audio_stream_index, sample_rate); + return decodeAudioFrames(fmt_ctx.get(), codec_ctx.get(), audio_stream_index, sample_rate); } -std::shared_ptr decodeWithFilePath( - const std::string &path, - int sample_rate) { +std::shared_ptr decodeWithFilePath(const std::string &path, int sample_rate) { if (path.empty()) { return nullptr; } @@ -341,25 +315,21 @@ std::shared_ptr decodeWithFilePath( if (avformat_open_input(&raw_fmt_ctx, path.c_str(), nullptr, nullptr) < 0) return nullptr; - auto fmt_ctx = - std::unique_ptr>( - raw_fmt_ctx, - [](AVFormatContext *ctx) { avformat_close_input(&ctx); }); + auto fmt_ctx = std::unique_ptr>( + raw_fmt_ctx, [](AVFormatContext *ctx) { avformat_close_input(&ctx); }); if (avformat_find_stream_info(fmt_ctx.get(), nullptr) < 0) { return nullptr; } - auto codec_ctx = - std::unique_ptr>( - nullptr, [](AVCodecContext *ctx) { avcodec_free_context(&ctx); }); + auto codec_ctx = std::unique_ptr>( + nullptr, [](AVCodecContext *ctx) { avcodec_free_context(&ctx); }); int audio_stream_index = -1; if (!setupDecoderContext(fmt_ctx.get(), audio_stream_index, codec_ctx)) { return nullptr; } - return decodeAudioFrames( - fmt_ctx.get(), codec_ctx.get(), audio_stream_index, sample_rate); + return decodeAudioFrames(fmt_ctx.get(), codec_ctx.get(), audio_stream_index, sample_rate); } } // namespace audioapi::ffmpegdecoder diff --git a/packages/react-native-audio-api/common/cpp/audioapi/libs/ffmpeg/FFmpegDecoding.h b/packages/react-native-audio-api/common/cpp/audioapi/libs/ffmpeg/FFmpegDecoding.h index f00047d7f..63b813f01 100644 --- a/packages/react-native-audio-api/common/cpp/audioapi/libs/ffmpeg/FFmpegDecoding.h +++ b/packages/react-native-audio-api/common/cpp/audioapi/libs/ffmpeg/FFmpegDecoding.h @@ -8,7 +8,7 @@ * FFmpeg, you must comply with the terms of the LGPL for FFmpeg itself. */ -#include +#include #include #include #include @@ -57,19 +57,15 @@ void convertFrameToBuffer( bool setupDecoderContext( AVFormatContext *fmt_ctx, int &audio_stream_index, - std::unique_ptr - &codec_ctx); + std::unique_ptr &codec_ctx); std::shared_ptr decodeAudioFrames( AVFormatContext *fmt_ctx, AVCodecContext *codec_ctx, int audio_stream_index, int sample_rate); -std::shared_ptr -decodeWithMemoryBlock(const void *data, size_t size, int sample_rate); +std::shared_ptr decodeWithMemoryBlock(const void *data, size_t size, int sample_rate); -std::shared_ptr decodeWithFilePath( - const std::string &path, - int sample_rate); +std::shared_ptr decodeWithFilePath(const std::string &path, int sample_rate); } // namespace audioapi::ffmpegdecoder diff --git a/packages/react-native-audio-api/common/cpp/audioapi/libs/signalsmith-stretch/fft-pffft.h b/packages/react-native-audio-api/common/cpp/audioapi/libs/signalsmith-stretch/fft-pffft.h index 1c687a8c9..8206de121 100644 --- a/packages/react-native-audio-api/common/cpp/audioapi/libs/signalsmith-stretch/fft-pffft.h +++ b/packages/react-native-audio-api/common/cpp/audioapi/libs/signalsmith-stretch/fft-pffft.h @@ -1,6 +1,8 @@ #ifndef SIGNALSMITH_LINEAR_PLATFORM_FFT_PFFFT_H #define SIGNALSMITH_LINEAR_PLATFORM_FFT_PFFFT_H +#include + #if defined(__has_include) && !__has_include("pffft/pffft.h") # include #else diff --git a/packages/react-native-audio-api/common/cpp/audioapi/utils/AudioArray.cpp b/packages/react-native-audio-api/common/cpp/audioapi/utils/AudioArray.cpp index ef738c773..af555c1bb 100644 --- a/packages/react-native-audio-api/common/cpp/audioapi/utils/AudioArray.cpp +++ b/packages/react-native-audio-api/common/cpp/audioapi/utils/AudioArray.cpp @@ -21,6 +21,7 @@ AudioArray::AudioArray(size_t size): size_(size) { AudioArray::AudioArray(const float *data, size_t size) : size_(size) { if (size_ > 0) { data_ = std::make_unique(size_); + copy(data, 0, 0, size_); std::memcpy(data_.get(), data, size_ * sizeof(float)); } } @@ -135,7 +136,7 @@ void AudioArray::copy( return; } - memcpy(data_.get() + destinationStart, source.data_.get() + sourceStart, length * sizeof(float)); + copy(source.data_.get(), sourceStart, destinationStart, length); } void AudioArray::copyReverse(const audioapi::AudioArray &source, size_t sourceStart, @@ -153,6 +154,24 @@ void AudioArray::copyReverse(const audioapi::AudioArray &source, size_t sourceSt } } +void AudioArray::copy(const float *source, size_t sourceStart, size_t destinationStart, + size_t length) { + if (length == 0 || data_ == nullptr || source == nullptr) { + return; + } + + memcpy(data_.get() + destinationStart, source + sourceStart, length * sizeof(float)); +} + +void AudioArray::copyTo(float *destination, size_t sourceStart, size_t destinationStart, + size_t length) const { + if (length == 0 || data_ == nullptr || destination == nullptr) { + return; + } + + memcpy(destination + destinationStart, data_.get() + sourceStart, length * sizeof(float)); +} + void AudioArray::reverse() { if (data_ == nullptr && size_ > 1) { return; @@ -204,7 +223,7 @@ float AudioArray::computeConvolution(const audioapi::AudioArray &kernel, size_t float32x4_t vSum = vdupq_n_f32(0.0f); // process 4 samples at a time - for (; k <= kernelSize_ - 4; k += 4) { + for (; k <= kernelSize - 4; k += 4) { float32x4_t vState = vld1q_f32(stateStart + k); float32x4_t vKernel = vld1q_f32(kernelStart + k); diff --git a/packages/react-native-audio-api/common/cpp/audioapi/utils/AudioArray.h b/packages/react-native-audio-api/common/cpp/audioapi/utils/AudioArray.h index a456b9dbe..85af5c272 100644 --- a/packages/react-native-audio-api/common/cpp/audioapi/utils/AudioArray.h +++ b/packages/react-native-audio-api/common/cpp/audioapi/utils/AudioArray.h @@ -111,7 +111,11 @@ class AudioArray { /// @param destinationStart The starting index in this AudioArray. /// @param length The number of samples to copy. /// @note Assumes that source and this AudioArray are not the same. - void copyReverse(const AudioArray &source, size_t sourceStart, size_t destinationStart, size_t length); + void + copyReverse(const AudioArray &source, size_t sourceStart, size_t destinationStart, size_t length); + + void copy(const float *source, size_t sourceStart, size_t destinationStart, size_t length); + void copyTo(float *destination, size_t sourceStart, size_t destinationStart, size_t length) const; void reverse(); void normalize(); diff --git a/packages/react-native-audio-api/common/cpp/audioapi/utils/AudioArrayBuffer.hpp b/packages/react-native-audio-api/common/cpp/audioapi/utils/AudioArrayBuffer.hpp new file mode 100644 index 000000000..e72b7c9ac --- /dev/null +++ b/packages/react-native-audio-api/common/cpp/audioapi/utils/AudioArrayBuffer.hpp @@ -0,0 +1,48 @@ +#pragma once + +#include +#include +#include + +#if !RN_AUDIO_API_TEST +#include + +namespace audioapi { + +using namespace facebook; + +class AudioArrayBuffer : public jsi::MutableBuffer, public AudioArray { + public: + explicit AudioArrayBuffer(size_t size) : AudioArray(size) {}; + AudioArrayBuffer(const float *data, size_t size) : AudioArray(data, size) {}; + + [[nodiscard]] size_t size() const override { + return size_ * sizeof(float); + } + uint8_t *data() override { + return reinterpret_cast(data_.get()); + } +}; + +} // namespace audioapi + +#else + +namespace audioapi { + +class AudioArrayBuffer : public AudioArray { + public: + explicit AudioArrayBuffer(size_t size) : AudioArray(size) {}; + AudioArrayBuffer(const float *data, size_t size) : AudioArray(data, size) {}; + + [[nodiscard]] size_t size() const { + return size_ * sizeof(float); + } + uint8_t *data() { + return reinterpret_cast(data_.get()); + } +}; + +} // namespace audioapi + +#endif diff --git a/packages/react-native-audio-api/common/cpp/audioapi/utils/AudioBus.cpp b/packages/react-native-audio-api/common/cpp/audioapi/utils/AudioBuffer.cpp similarity index 58% rename from packages/react-native-audio-api/common/cpp/audioapi/utils/AudioBus.cpp rename to packages/react-native-audio-api/common/cpp/audioapi/utils/AudioBuffer.cpp index 99c9e7327..99531b4e6 100644 --- a/packages/react-native-audio-api/common/cpp/audioapi/utils/AudioBus.cpp +++ b/packages/react-native-audio-api/common/cpp/audioapi/utils/AudioBuffer.cpp @@ -1,7 +1,9 @@ #include #include #include -#include +#include +#include +#include #include #include #include @@ -19,14 +21,18 @@ namespace audioapi { * Public interfaces - memory management */ -AudioBus::AudioBus(size_t size, int numberOfChannels, float sampleRate) +AudioBuffer::AudioBuffer(size_t size, int numberOfChannels, float sampleRate) : numberOfChannels_(numberOfChannels), sampleRate_(sampleRate), size_(size) { createChannels(); } -AudioBus::AudioBus(const AudioBus &other): numberOfChannels_(other.numberOfChannels_), - sampleRate_(other.sampleRate_), - size_(other.size_) { +AudioBuffer::AudioBuffer(const audioapi::AudioBufferOptions &options) + : AudioBuffer(options.length, options.numberOfChannels, options.sampleRate) {} + +AudioBuffer::AudioBuffer(const AudioBuffer &other) + : numberOfChannels_(other.numberOfChannels_), + sampleRate_(other.sampleRate_), + size_(other.size_) { createChannels(); for (int i = 0; i < numberOfChannels_; i += 1) { @@ -34,71 +40,58 @@ AudioBus::AudioBus(const AudioBus &other): numberOfChannels_(other.numberOfChann } } -AudioBus::AudioBus(std::vector> channels, float sampleRate) - : channels_(std::move(channels)), - sampleRate_(sampleRate) { - - numberOfChannels_ = static_cast(channels_.size()); - - if (numberOfChannels_ > 0 && channels_[0] != nullptr) { - size_ = channels_[0]->getSize(); - } else { - size_ = 0; - } -} - -AudioBus::AudioBus(audioapi::AudioBus &&other) noexcept : - channels_(std::move(other.channels_)), - numberOfChannels_(other.numberOfChannels_), - sampleRate_(other.sampleRate_), - size_(other.size_) { - other.numberOfChannels_ = 0; - other.sampleRate_ = 0.0f; - other.size_ = 0; +AudioBuffer::AudioBuffer(audioapi::AudioBuffer &&other) noexcept + : channels_(std::move(other.channels_)), + numberOfChannels_(other.numberOfChannels_), + sampleRate_(other.sampleRate_), + size_(other.size_) { + other.numberOfChannels_ = 0; + other.sampleRate_ = 0.0f; + other.size_ = 0; } -AudioBus &AudioBus::operator=(const AudioBus &other) { +AudioBuffer &AudioBuffer::operator=(const AudioBuffer &other) { if (this != &other) { - if (numberOfChannels_ != other.numberOfChannels_ || size_ != other.size_) { - numberOfChannels_ = other.numberOfChannels_; - size_ = other.size_; - createChannels(); - } + if (numberOfChannels_ != other.numberOfChannels_ || size_ != other.size_) { + numberOfChannels_ = other.numberOfChannels_; + size_ = other.size_; + createChannels(); + } - sampleRate_ = other.sampleRate_; + sampleRate_ = other.sampleRate_; - for (int i = 0; i < numberOfChannels_; i += 1) { - *channels_[i] = *other.channels_[i]; - } + for (int i = 0; i < numberOfChannels_; i += 1) { + *channels_[i] = *other.channels_[i]; + } } return *this; } -AudioBus &AudioBus::operator=(audioapi::AudioBus &&other) noexcept { - if (this != &other) { - channels_ = std::move(other.channels_); +AudioBuffer &AudioBuffer::operator=(audioapi::AudioBuffer &&other) noexcept { + if (this != &other) { + channels_ = std::move(other.channels_); - numberOfChannels_ = other.numberOfChannels_; - sampleRate_ = other.sampleRate_; - size_ = other.size_; + numberOfChannels_ = other.numberOfChannels_; + sampleRate_ = other.sampleRate_; + size_ = other.size_; - other.numberOfChannels_ = 0; - other.sampleRate_ = 0.0f; - other.size_ = 0; - } - return *this; + other.numberOfChannels_ = 0; + other.sampleRate_ = 0.0f; + other.size_ = 0; + } + return *this; } /** * Public interfaces - getters */ -AudioArray *AudioBus::getChannel(int index) const { +AudioArray *AudioBuffer::getChannel(int index) const { return channels_[index].get(); } -AudioArray *AudioBus::getChannelByType(int channelType) const { +AudioArray *AudioBuffer::getChannelByType(int channelType) const { switch (getNumberOfChannels()) { case 1: // mono if (channelType == ChannelMono) { @@ -168,7 +161,7 @@ AudioArray *AudioBus::getChannelByType(int channelType) const { } } -std::shared_ptr AudioBus::getSharedChannel(int index) const { +std::shared_ptr AudioBuffer::getSharedChannel(int index) const { return channels_[index]; } @@ -176,22 +169,22 @@ std::shared_ptr AudioBus::getSharedChannel(int index) const { * Public interfaces - audio processing and setters */ -void AudioBus::zero() { +void AudioBuffer::zero() { zero(0, getSize()); } -void AudioBus::zero(size_t start, size_t length) { +void AudioBuffer::zero(size_t start, size_t length) { for (auto it = channels_.begin(); it != channels_.end(); it += 1) { it->get()->zero(start, length); } } -void AudioBus::sum(const AudioBus& source, ChannelInterpretation interpretation) { +void AudioBuffer::sum(const AudioBuffer &source, ChannelInterpretation interpretation) { sum(source, 0, 0, getSize(), interpretation); } -void AudioBus::sum( - const AudioBus& source, +void AudioBuffer::sum( + const AudioBuffer &source, size_t sourceStart, size_t destinationStart, size_t length, @@ -226,12 +219,12 @@ void AudioBus::sum( } } -void AudioBus::copy(const AudioBus& source) { +void AudioBuffer::copy(const AudioBuffer &source) { copy(source, 0, 0, getSize()); } -void AudioBus::copy( - const AudioBus& source, +void AudioBuffer::copy( + const AudioBuffer &source, size_t sourceStart, size_t destinationStart, size_t length) { @@ -252,50 +245,50 @@ void AudioBus::copy( sum(source, sourceStart, destinationStart, length); } -void AudioBus::normalize() { - float maxAbsValue = this->maxAbsValue(); +void AudioBuffer::normalize() { + float maxAbsValue = this->maxAbsValue(); - if (maxAbsValue == 0.0f || maxAbsValue == 1.0f) { - return; - } + if (maxAbsValue == 0.0f || maxAbsValue == 1.0f) { + return; + } - float scale = 1.0f / maxAbsValue; - this->scale(scale); + float scale = 1.0f / maxAbsValue; + this->scale(scale); } -void AudioBus::scale(float value) { - for (auto &channel : channels_) { - channel->scale(value); - } +void AudioBuffer::scale(float value) { + for (auto &channel : channels_) { + channel->scale(value); + } } -float AudioBus::maxAbsValue() const { - float maxAbsValue = 1.0f; +float AudioBuffer::maxAbsValue() const { + float maxAbsValue = 1.0f; - for (const auto &channel : channels_) { - float channelMaxAbsValue = channel->getMaxAbsValue(); - maxAbsValue = std::max(maxAbsValue, channelMaxAbsValue); - } + for (const auto &channel : channels_) { + float channelMaxAbsValue = channel->getMaxAbsValue(); + maxAbsValue = std::max(maxAbsValue, channelMaxAbsValue); + } - return maxAbsValue; + return maxAbsValue; } /** * Internal tooling - channel initialization */ -void AudioBus::createChannels() { +void AudioBuffer::createChannels() { if (channels_.size() != static_cast(numberOfChannels_)) { - channels_.clear(); - channels_.reserve(numberOfChannels_); + channels_.clear(); + channels_.reserve(numberOfChannels_); - for (int i = 0; i < numberOfChannels_; i += 1) { - channels_.emplace_back(std::make_shared(size_)); - } + for (int i = 0; i < numberOfChannels_; i += 1) { + channels_.emplace_back(std::make_shared(size_)); + } } else { - for (int i = 0; i < numberOfChannels_; i += 1) { - channels_[i]->resize(size_); - } + for (int i = 0; i < numberOfChannels_; i += 1) { + channels_[i]->resize(size_); + } } } @@ -303,8 +296,8 @@ void AudioBus::createChannels() { * Internal tooling - channel summing */ -void AudioBus::discreteSum( - const AudioBus& source, +void AudioBuffer::discreteSum( + const AudioBuffer &source, size_t sourceStart, size_t destinationStart, size_t length) const { @@ -318,8 +311,8 @@ void AudioBus::discreteSum( } } -void AudioBus::sumByUpMixing( - const AudioBus& source, +void AudioBuffer::sumByUpMixing( + const AudioBuffer &source, size_t sourceStart, size_t destinationStart, size_t length) { @@ -361,15 +354,16 @@ void AudioBus::sumByUpMixing( getChannelByType(ChannelSurroundLeft) ->sum(*source.getChannelByType(ChannelSurroundLeft), sourceStart, destinationStart, length); getChannelByType(ChannelSurroundRight) - ->sum(*source.getChannelByType(ChannelSurroundRight), sourceStart, destinationStart, length); + ->sum( + *source.getChannelByType(ChannelSurroundRight), sourceStart, destinationStart, length); return; } discreteSum(source, sourceStart, destinationStart, length); } -void AudioBus::sumByDownMixing( - const AudioBus& source, +void AudioBuffer::sumByDownMixing( + const AudioBuffer &source, size_t sourceStart, size_t destinationStart, size_t length) { @@ -380,8 +374,10 @@ void AudioBus::sumByDownMixing( if (numberOfSourceChannels == 2 && numberOfChannels == 1) { auto destinationData = getChannelByType(ChannelMono); - destinationData->sum(*source.getChannelByType(ChannelLeft), sourceStart, destinationStart, length, 0.5f); - destinationData->sum(*source.getChannelByType(ChannelRight), sourceStart, destinationStart, length, 0.5f); + destinationData->sum( + *source.getChannelByType(ChannelLeft), sourceStart, destinationStart, length, 0.5f); + destinationData->sum( + *source.getChannelByType(ChannelRight), sourceStart, destinationStart, length, 0.5f); return; } @@ -391,10 +387,22 @@ void AudioBus::sumByDownMixing( if (numberOfSourceChannels == 4 && numberOfChannels == 1) { auto destinationData = getChannelByType(ChannelMono); - destinationData->sum(*source.getChannelByType(ChannelLeft), sourceStart, destinationStart, length, 0.25f); - destinationData->sum(*source.getChannelByType(ChannelRight), sourceStart, destinationStart, length, 0.25f); - destinationData->sum(*source.getChannelByType(ChannelSurroundLeft), sourceStart, destinationStart, length, 0.25f); - destinationData->sum(*source.getChannelByType(ChannelSurroundRight), sourceStart, destinationStart, length, 0.25f); + destinationData->sum( + *source.getChannelByType(ChannelLeft), sourceStart, destinationStart, length, 0.25f); + destinationData->sum( + *source.getChannelByType(ChannelRight), sourceStart, destinationStart, length, 0.25f); + destinationData->sum( + *source.getChannelByType(ChannelSurroundLeft), + sourceStart, + destinationStart, + length, + 0.25f); + destinationData->sum( + *source.getChannelByType(ChannelSurroundRight), + sourceStart, + destinationStart, + length, + 0.25f); return; } @@ -404,11 +412,20 @@ void AudioBus::sumByDownMixing( if (numberOfSourceChannels == 6 && numberOfChannels == 1) { auto destinationData = getChannelByType(ChannelMono); - destinationData->sum(*source.getChannelByType(ChannelLeft), sourceStart, destinationStart, length, SQRT_HALF); - destinationData->sum(*source.getChannelByType(ChannelRight), sourceStart, destinationStart, length, SQRT_HALF); - destinationData->sum(*source.getChannelByType(ChannelCenter), sourceStart, destinationStart, length); - destinationData->sum(*source.getChannelByType(ChannelSurroundLeft), sourceStart, destinationStart, length, 0.5f); - destinationData->sum(*source.getChannelByType(ChannelSurroundRight), sourceStart, destinationStart, length, 0.5f); + destinationData->sum( + *source.getChannelByType(ChannelLeft), sourceStart, destinationStart, length, SQRT_HALF); + destinationData->sum( + *source.getChannelByType(ChannelRight), sourceStart, destinationStart, length, SQRT_HALF); + destinationData->sum( + *source.getChannelByType(ChannelCenter), sourceStart, destinationStart, length); + destinationData->sum( + *source.getChannelByType(ChannelSurroundLeft), sourceStart, destinationStart, length, 0.5f); + destinationData->sum( + *source.getChannelByType(ChannelSurroundRight), + sourceStart, + destinationStart, + length, + 0.5f); return; } @@ -419,11 +436,19 @@ void AudioBus::sumByDownMixing( auto destinationLeft = getChannelByType(ChannelLeft); auto destinationRight = getChannelByType(ChannelRight); - destinationLeft->sum(*source.getChannelByType(ChannelLeft), sourceStart, destinationStart, length, 0.5f); - destinationLeft->sum(*source.getChannelByType(ChannelSurroundLeft), sourceStart, destinationStart, length, 0.5f); - - destinationRight->sum(*source.getChannelByType(ChannelRight), sourceStart, destinationStart, length, 0.5f); - destinationRight->sum(*source.getChannelByType(ChannelSurroundRight), sourceStart, destinationStart, length, 0.5f); + destinationLeft->sum( + *source.getChannelByType(ChannelLeft), sourceStart, destinationStart, length, 0.5f); + destinationLeft->sum( + *source.getChannelByType(ChannelSurroundLeft), sourceStart, destinationStart, length, 0.5f); + + destinationRight->sum( + *source.getChannelByType(ChannelRight), sourceStart, destinationStart, length, 0.5f); + destinationRight->sum( + *source.getChannelByType(ChannelSurroundRight), + sourceStart, + destinationStart, + length, + 0.5f); return; } @@ -435,13 +460,27 @@ void AudioBus::sumByDownMixing( auto destinationLeft = getChannelByType(ChannelLeft); auto destinationRight = getChannelByType(ChannelRight); - destinationLeft->sum(*source.getChannelByType(ChannelLeft), sourceStart, destinationStart, length); - destinationLeft->sum(*source.getChannelByType(ChannelCenter), sourceStart, destinationStart, length, SQRT_HALF); - destinationLeft->sum(*source.getChannelByType(ChannelSurroundLeft), sourceStart, destinationStart, length, SQRT_HALF); - - destinationRight->sum(*source.getChannelByType(ChannelRight), sourceStart, destinationStart, length); - destinationRight->sum(*source.getChannelByType(ChannelCenter), sourceStart, destinationStart, length, SQRT_HALF); - destinationRight->sum(*source.getChannelByType(ChannelSurroundRight), sourceStart, destinationStart, length, SQRT_HALF); + destinationLeft->sum( + *source.getChannelByType(ChannelLeft), sourceStart, destinationStart, length); + destinationLeft->sum( + *source.getChannelByType(ChannelCenter), sourceStart, destinationStart, length, SQRT_HALF); + destinationLeft->sum( + *source.getChannelByType(ChannelSurroundLeft), + sourceStart, + destinationStart, + length, + SQRT_HALF); + + destinationRight->sum( + *source.getChannelByType(ChannelRight), sourceStart, destinationStart, length); + destinationRight->sum( + *source.getChannelByType(ChannelCenter), sourceStart, destinationStart, length, SQRT_HALF); + destinationRight->sum( + *source.getChannelByType(ChannelSurroundRight), + sourceStart, + destinationStart, + length, + SQRT_HALF); return; } @@ -456,14 +495,20 @@ void AudioBus::sumByDownMixing( auto destinationSurroundLeft = getChannelByType(ChannelSurroundLeft); auto destinationSurroundRight = getChannelByType(ChannelSurroundRight); - destinationLeft->sum(*source.getChannelByType(ChannelLeft), sourceStart, destinationStart, length); - destinationLeft->sum(*source.getChannelByType(ChannelCenter), sourceStart, destinationStart, length, SQRT_HALF); + destinationLeft->sum( + *source.getChannelByType(ChannelLeft), sourceStart, destinationStart, length); + destinationLeft->sum( + *source.getChannelByType(ChannelCenter), sourceStart, destinationStart, length, SQRT_HALF); - destinationRight->sum(*source.getChannelByType(ChannelRight), sourceStart, destinationStart, length); - destinationRight->sum(*source.getChannelByType(ChannelCenter), sourceStart, destinationStart, length, SQRT_HALF); + destinationRight->sum( + *source.getChannelByType(ChannelRight), sourceStart, destinationStart, length); + destinationRight->sum( + *source.getChannelByType(ChannelCenter), sourceStart, destinationStart, length, SQRT_HALF); - destinationSurroundLeft->sum(*source.getChannelByType(ChannelSurroundLeft), sourceStart, destinationStart, length); - destinationSurroundRight->sum(*source.getChannelByType(ChannelSurroundRight), sourceStart, destinationStart, length); + destinationSurroundLeft->sum( + *source.getChannelByType(ChannelSurroundLeft), sourceStart, destinationStart, length); + destinationSurroundRight->sum( + *source.getChannelByType(ChannelSurroundRight), sourceStart, destinationStart, length); return; } diff --git a/packages/react-native-audio-api/common/cpp/audioapi/utils/AudioBus.h b/packages/react-native-audio-api/common/cpp/audioapi/utils/AudioBuffer.h similarity index 65% rename from packages/react-native-audio-api/common/cpp/audioapi/utils/AudioBus.h rename to packages/react-native-audio-api/common/cpp/audioapi/utils/AudioBuffer.h index 497f04450..9803d5a47 100644 --- a/packages/react-native-audio-api/common/cpp/audioapi/utils/AudioBus.h +++ b/packages/react-native-audio-api/common/cpp/audioapi/utils/AudioBuffer.h @@ -1,6 +1,8 @@ #pragma once #include +#include +#include #include #include @@ -9,9 +11,9 @@ namespace audioapi { -class AudioArray; +struct AudioBufferOptions; -class AudioBus { +class AudioBuffer { public: enum { ChannelMono = 0, @@ -23,14 +25,14 @@ class AudioBus { ChannelSurroundRight = 5, }; - explicit AudioBus() = default; - explicit AudioBus(size_t size, int numberOfChannels, float sampleRate); - AudioBus(std::vector> channels, float sampleRate); - AudioBus(const AudioBus &other); - AudioBus(AudioBus &&other) noexcept; - AudioBus &operator=(const AudioBus &other); - AudioBus &operator=(AudioBus &&other) noexcept; - ~AudioBus() = default; + explicit AudioBuffer() = default; + explicit AudioBuffer(size_t size, int numberOfChannels, float sampleRate); + explicit AudioBuffer(const AudioBufferOptions &options); + AudioBuffer(const AudioBuffer &other); + AudioBuffer(AudioBuffer &&other) noexcept; + AudioBuffer &operator=(const AudioBuffer &other); + AudioBuffer &operator=(AudioBuffer &&other) noexcept; + ~AudioBuffer() = default; [[nodiscard]] inline int getNumberOfChannels() const noexcept { return numberOfChannels_; @@ -42,6 +44,10 @@ class AudioBus { return size_; } + [[nodiscard]] double getDuration() const noexcept { + return static_cast(size_) / getSampleRate(); + } + /// @brief Get the AudioArray for a specific channel index. /// @param index The channel index. /// @return Pointer to the AudioArray for the specified channel - not owning. @@ -55,7 +61,7 @@ class AudioBus { /// @brief Get a copy of shared pointer to the AudioArray for a specific channel index. /// @param index The channel index. /// @return Copy of shared pointer to the AudioArray for the specified channel - [[nodiscard]] std::shared_ptr getSharedChannel(int index) const; + [[nodiscard]] std::shared_ptr getSharedChannel(int index) const; AudioArray &operator[](size_t index) { return *channels_[index]; @@ -68,24 +74,24 @@ class AudioBus { void zero(size_t start, size_t length); void sum( - const AudioBus &source, + const AudioBuffer &source, ChannelInterpretation interpretation = ChannelInterpretation::SPEAKERS); void sum( - const AudioBus &source, + const AudioBuffer &source, size_t sourceStart, size_t destinationStart, size_t length, ChannelInterpretation interpretation = ChannelInterpretation::SPEAKERS); - void copy(const AudioBus &source); - void copy(const AudioBus &source, size_t sourceStart, size_t destinationStart, size_t length); + void copy(const AudioBuffer &source); + void copy(const AudioBuffer &source, size_t sourceStart, size_t destinationStart, size_t length); void normalize(); void scale(float value); [[nodiscard]] float maxAbsValue() const; private: - std::vector> channels_; + std::vector> channels_; int numberOfChannels_ = 0; float sampleRate_ = 0.0f; @@ -93,14 +99,17 @@ class AudioBus { void createChannels(); void discreteSum( - const AudioBus &source, + const AudioBuffer &source, size_t sourceStart, size_t destinationStart, size_t length) const; - void - sumByUpMixing(const AudioBus &source, size_t sourceStart, size_t destinationStart, size_t length); + void sumByUpMixing( + const AudioBuffer &source, + size_t sourceStart, + size_t destinationStart, + size_t length); void sumByDownMixing( - const AudioBus &source, + const AudioBuffer &source, size_t sourceStart, size_t destinationStart, size_t length); diff --git a/packages/react-native-audio-api/common/cpp/audioapi/utils/CircularAudioArray.cpp b/packages/react-native-audio-api/common/cpp/audioapi/utils/CircularAudioArray.cpp index 142cd9819..14848094a 100644 --- a/packages/react-native-audio-api/common/cpp/audioapi/utils/CircularAudioArray.cpp +++ b/packages/react-native-audio-api/common/cpp/audioapi/utils/CircularAudioArray.cpp @@ -1,10 +1,12 @@ #include +#include + namespace audioapi { CircularAudioArray::CircularAudioArray(size_t size) : AudioArray(size) {} -void CircularAudioArray::push_back(const float *data, size_t size, bool skipAvailableSpaceCheck) { +void CircularAudioArray::push_back(const AudioArray & data, size_t size, bool skipAvailableSpaceCheck) { if (size > size_) { throw std::overflow_error("size exceeds CircularAudioArray size_"); } @@ -15,16 +17,17 @@ void CircularAudioArray::push_back(const float *data, size_t size, bool skipAvai if (vWriteIndex_ + size > size_) { auto partSize = size_ - vWriteIndex_; - memcpy(data_ + vWriteIndex_, data, partSize * sizeof(float)); - memcpy(data_, data + partSize, (size - partSize) * sizeof(float)); + + copy(data, 0, vWriteIndex_, partSize); + copy(data, partSize, 0, size - partSize); } else { - memcpy(data_ + vWriteIndex_, data, size * sizeof(float)); + copy(data, 0, vWriteIndex_, size); } vWriteIndex_ = vWriteIndex_ + size > size_ ? vWriteIndex_ + size - size_ : vWriteIndex_ + size; } -void CircularAudioArray::pop_front(float *data, size_t size, bool skipAvailableDataCheck) { +void CircularAudioArray::pop_front(AudioArray &data, size_t size, bool skipAvailableDataCheck) { if (size > size_) { throw std::overflow_error("size exceeds CircularAudioArray size_"); } @@ -35,17 +38,17 @@ void CircularAudioArray::pop_front(float *data, size_t size, bool skipAvailableD if (vReadIndex_ + size > size_) { auto partSize = size_ - vReadIndex_; - memcpy(data, data_ + vReadIndex_, partSize * sizeof(float)); - memcpy(data + partSize, data_, (size - partSize) * sizeof(float)); + data.copy(*this, vReadIndex_, 0, partSize); + data.copy(*this, 0, partSize, size - partSize); } else { - memcpy(data, data_ + vReadIndex_, size * sizeof(float)); + data.copy(*this, vReadIndex_, 0, size); } vReadIndex_ = vReadIndex_ + size > size_ ? vReadIndex_ + size - size_ : vReadIndex_ + size; } void CircularAudioArray::pop_back( - float *data, + AudioArray &data, size_t size, size_t offset, bool skipAvailableDataCheck) { @@ -58,13 +61,13 @@ void CircularAudioArray::pop_back( } if (vWriteIndex_ <= offset) { - memcpy(data, data_ + size_ - (offset - vWriteIndex_) - size, size * sizeof(float)); + data.copy(*this, size_ - (offset - vWriteIndex_) - size, 0, size); } else if (vWriteIndex_ <= size + offset) { auto partSize = size + offset - vWriteIndex_; - memcpy(data, data_ + size_ - partSize, partSize * sizeof(float)); - memcpy(data + partSize, data_, (size - partSize) * sizeof(float)); + data.copy(*this, size_ - partSize, 0, partSize); + data.copy(*this, 0, partSize, size - partSize); } else { - memcpy(data, data_ + vWriteIndex_ - size - offset, size * sizeof(float)); + data.copy(*this, vWriteIndex_ - size - offset, 0, size); } vReadIndex_ = vWriteIndex_ - offset < 0 ? size + vWriteIndex_ - offset : vWriteIndex_ - offset; diff --git a/packages/react-native-audio-api/common/cpp/audioapi/utils/CircularAudioArray.h b/packages/react-native-audio-api/common/cpp/audioapi/utils/CircularAudioArray.h index f0df81b75..999af4fce 100644 --- a/packages/react-native-audio-api/common/cpp/audioapi/utils/CircularAudioArray.h +++ b/packages/react-native-audio-api/common/cpp/audioapi/utils/CircularAudioArray.h @@ -11,9 +11,10 @@ class CircularAudioArray : public AudioArray { CircularAudioArray(const CircularAudioArray &other) = default; ~CircularAudioArray() = default; - void push_back(const float *data, size_t size, bool skipAvailableSpaceCheck = false); - void pop_front(float *data, size_t size, bool skipAvailableDataCheck = false); - void pop_back(float *data, size_t size, size_t offset = 0, bool skipAvailableDataCheck = false); + void push_back(const AudioArray &data, size_t size, bool skipAvailableSpaceCheck = false); + void pop_front(AudioArray &data, size_t size, bool skipAvailableDataCheck = false); + void + pop_back(AudioArray &data, size_t size, size_t offset = 0, bool skipAvailableDataCheck = false); [[nodiscard]] size_t getNumberOfAvailableFrames() const; diff --git a/packages/react-native-audio-api/common/cpp/audioapi/utils/CircularOverflowableAudioArray.cpp b/packages/react-native-audio-api/common/cpp/audioapi/utils/CircularOverflowableAudioArray.cpp index 86acde67c..66b6c852a 100644 --- a/packages/react-native-audio-api/common/cpp/audioapi/utils/CircularOverflowableAudioArray.cpp +++ b/packages/react-native-audio-api/common/cpp/audioapi/utils/CircularOverflowableAudioArray.cpp @@ -8,7 +8,7 @@ CircularOverflowableAudioArray::CircularOverflowableAudioArray(size_t size) noex std::is_nothrow_constructible::value) : AudioArray(size) {} -void CircularOverflowableAudioArray::write(const float *data, const size_t size) { +void CircularOverflowableAudioArray::write(const AudioArray &data, const size_t size) { size_t writeIndex = vWriteIndex_.load(std::memory_order_relaxed); if (size > size_) { @@ -25,25 +25,25 @@ void CircularOverflowableAudioArray::write(const float *data, const size_t size) size_t partSize = size_ - writeIndex; if (size > partSize) { - std::memcpy(data_ + writeIndex, data, partSize * sizeof(float)); - std::memcpy(data_, data + partSize, (size - partSize) * sizeof(float)); + copy(data, 0, writeIndex, partSize); + copy(data, partSize, 0, size - partSize); } else { - std::memcpy(data_ + writeIndex, data, size * sizeof(float)); + copy(data, 0, writeIndex, size); } vWriteIndex_.store((writeIndex + size) % size_, std::memory_order_relaxed); } -size_t CircularOverflowableAudioArray::read(float *output, size_t size) const { +size_t CircularOverflowableAudioArray::read(AudioArray &data, size_t size) const { readLock_.lock(); size_t availableSpace = getAvailableSpace(); size_t readSize = std::min(size, availableSpace); size_t partSize = size_ - vReadIndex_; if (readSize > partSize) { - std::memcpy(output, data_ + vReadIndex_, partSize * sizeof(float)); - std::memcpy(output + partSize, data_, (readSize - partSize) * sizeof(float)); + data.copy(*this, vReadIndex_, 0, partSize); + data.copy(*this, 0, partSize, readSize - partSize); } else { - std::memcpy(output, data_ + vReadIndex_, readSize * sizeof(float)); + data.copy(*this, vReadIndex_, 0, readSize); } vReadIndex_ = (vReadIndex_ + readSize) % size_; readLock_.unlock(); diff --git a/packages/react-native-audio-api/common/cpp/audioapi/utils/CircularOverflowableAudioArray.h b/packages/react-native-audio-api/common/cpp/audioapi/utils/CircularOverflowableAudioArray.h index 601da5610..b4889857b 100644 --- a/packages/react-native-audio-api/common/cpp/audioapi/utils/CircularOverflowableAudioArray.h +++ b/packages/react-native-audio-api/common/cpp/audioapi/utils/CircularOverflowableAudioArray.h @@ -23,13 +23,13 @@ class CircularOverflowableAudioArray : public AudioArray { /// @note Might wait for read operation to finish if it is in progress. It ignores writes that exceed the buffer size. /// @param data Pointer to the input buffer. /// @param size Number of frames to write. - void write(const float *data, size_t size); + void write(const AudioArray &data, size_t size); /// @brief Reads data from the circular buffer. /// @param output Pointer to the output buffer. /// @param size Number of frames to read. /// @return The number of frames actually read. - size_t read(float *output, size_t size) const; + size_t read(AudioArray &data, size_t size) const; private: std::atomic vWriteIndex_ = {0}; diff --git a/packages/react-native-audio-api/common/cpp/test/src/AudioParamTest.cpp b/packages/react-native-audio-api/common/cpp/test/src/AudioParamTest.cpp index 7d8cbae23..75efa552a 100644 --- a/packages/react-native-audio-api/common/cpp/test/src/AudioParamTest.cpp +++ b/packages/react-native-audio-api/common/cpp/test/src/AudioParamTest.cpp @@ -121,8 +121,15 @@ TEST_F(AudioParamTest, SetTargetAtTime) { TEST_F(AudioParamTest, SetValueCurveAtTime) { auto param = AudioParam(0.0, 0.0, 1.0, context); param.setValue(0.5); - auto curve = std::make_shared>(std::vector{0.1, 0.4, 0.2, 0.8, 0.5}); - param.setValueCurveAtTime(curve, curve->size(), 0.1, 0.2); + auto curve = std::make_shared(5); + auto curveSpan = curve ->span(); + curveSpan[0] = 0.1f; + curveSpan[1] = 0.4f; + curveSpan[2] = 0.2f; + curveSpan[3] = 0.8f; + curveSpan[4] = 0.5f; + + param.setValueCurveAtTime(curve, curve->getSize(), 0.1, 0.2); // 5 elements over 0.2s => each element is 0.04s apart float value = param.processKRateParam(1, 0.05); diff --git a/packages/react-native-audio-api/common/cpp/test/src/AudioScheduledSourceTest.cpp b/packages/react-native-audio-api/common/cpp/test/src/AudioScheduledSourceTest.cpp index ec2df8519..8c09eaa14 100644 --- a/packages/react-native-audio-api/common/cpp/test/src/AudioScheduledSourceTest.cpp +++ b/packages/react-native-audio-api/common/cpp/test/src/AudioScheduledSourceTest.cpp @@ -2,7 +2,7 @@ #include #include #include -#include +#include #include #include #include @@ -33,7 +33,7 @@ class TestableAudioScheduledSourceNode : public AudioScheduledSourceNode { } void updatePlaybackInfo( - const std::shared_ptr &processingBus, + const std::shared_ptr &processingBus, int framesToProcess, size_t &startOffset, size_t &nonSilentFramesToProcess, @@ -48,7 +48,7 @@ class TestableAudioScheduledSourceNode : public AudioScheduledSourceNode { currentSampleFrame); } - std::shared_ptr processNode(const std::shared_ptr &, int) override { + std::shared_ptr processNode(const std::shared_ptr &, int) override { return nullptr; } @@ -60,7 +60,7 @@ class TestableAudioScheduledSourceNode : public AudioScheduledSourceNode { if (std::shared_ptr context = context_.lock()) { size_t startOffset = 0; size_t nonSilentFramesToProcess = 0; - auto processingBus = std::make_shared(128, 2, static_cast(SAMPLE_RATE)); + auto processingBus = std::make_shared(128, 2, static_cast(SAMPLE_RATE)); updatePlaybackInfo( processingBus, frames, diff --git a/packages/react-native-audio-api/common/cpp/test/src/ConstantSourceTest.cpp b/packages/react-native-audio-api/common/cpp/test/src/ConstantSourceTest.cpp index 4bac9678f..85e7b4ad4 100644 --- a/packages/react-native-audio-api/common/cpp/test/src/ConstantSourceTest.cpp +++ b/packages/react-native-audio-api/common/cpp/test/src/ConstantSourceTest.cpp @@ -3,7 +3,7 @@ #include #include #include -#include +#include #include #include #include @@ -33,8 +33,8 @@ class TestableConstantSourceNode : public ConstantSourceNode { getOffsetParam()->setValue(value); } - std::shared_ptr processNode( - const std::shared_ptr &processingBus, + std::shared_ptr processNode( + const std::shared_ptr &processingBus, int framesToProcess) override { return ConstantSourceNode::processNode(processingBus, framesToProcess); } @@ -48,7 +48,7 @@ TEST_F(ConstantSourceTest, ConstantSourceCanBeCreated) { TEST_F(ConstantSourceTest, ConstantSourceOutputsConstantValue) { static constexpr int FRAMES_TO_PROCESS = 4; - auto bus = std::make_shared(FRAMES_TO_PROCESS, 1, sampleRate); + auto bus = std::make_shared(FRAMES_TO_PROCESS, 1, sampleRate); auto constantSource = TestableConstantSourceNode(context); // constantSource.start(context->getCurrentTime()); // auto resultBus = constantSource.processNode(bus, FRAMES_TO_PROCESS); diff --git a/packages/react-native-audio-api/common/cpp/test/src/DelayTest.cpp b/packages/react-native-audio-api/common/cpp/test/src/DelayTest.cpp index 80f57b80c..3ea5f2b54 100644 --- a/packages/react-native-audio-api/common/cpp/test/src/DelayTest.cpp +++ b/packages/react-native-audio-api/common/cpp/test/src/DelayTest.cpp @@ -3,7 +3,7 @@ #include #include #include -#include +#include #include #include #include @@ -26,14 +26,15 @@ class DelayTest : public ::testing::Test { class TestableDelayNode : public DelayNode { public: - explicit TestableDelayNode(std::shared_ptr context, const DelayOptions& options) : DelayNode(context, options) {} + explicit TestableDelayNode(std::shared_ptr context, const DelayOptions &options) + : DelayNode(context, options) {} void setDelayTimeParam(float value) { getDelayTimeParam()->setValue(value); } - std::shared_ptr processNode( - const std::shared_ptr &processingBus, + std::shared_ptr processNode( + const std::shared_ptr &processingBus, int framesToProcess) override { return DelayNode::processNode(processingBus, framesToProcess); } @@ -52,9 +53,9 @@ TEST_F(DelayTest, DelayWithZeroDelayOutputsInputSignal) { auto delayNode = TestableDelayNode(context, options); delayNode.setDelayTimeParam(DELAY_TIME); - auto bus = std::make_shared(FRAMES_TO_PROCESS, 1, sampleRate); + auto bus = std::make_shared(FRAMES_TO_PROCESS, 1, sampleRate); for (size_t i = 0; i < bus->getSize(); ++i) { - bus->getChannel(0)->getData()[i] = i + 1; + (*bus->getChannel(0))[i] = i + 1; } auto resultBus = delayNode.processNode(bus, FRAMES_TO_PROCESS); @@ -71,9 +72,9 @@ TEST_F(DelayTest, DelayAppliesTimeShiftCorrectly) { auto delayNode = TestableDelayNode(context, options); delayNode.setDelayTimeParam(DELAY_TIME); - auto bus = std::make_shared(FRAMES_TO_PROCESS, 1, sampleRate); + auto bus = std::make_shared(FRAMES_TO_PROCESS, 1, sampleRate); for (size_t i = 0; i < bus->getSize(); ++i) { - bus->getChannel(0)->getData()[i] = i + 1; + (*bus->getChannel(0))[i] = i + 1; } auto resultBus = delayNode.processNode(bus, FRAMES_TO_PROCESS); @@ -97,9 +98,9 @@ TEST_F(DelayTest, DelayHandlesTailCorrectly) { auto delayNode = TestableDelayNode(context, options); delayNode.setDelayTimeParam(DELAY_TIME); - auto bus = std::make_shared(FRAMES_TO_PROCESS, 1, sampleRate); + auto bus = std::make_shared(FRAMES_TO_PROCESS, 1, sampleRate); for (size_t i = 0; i < bus->getSize(); ++i) { - bus->getChannel(0)->getData()[i] = i + 1; + (*bus->getChannel(0))[i] = i + 1; } delayNode.processNode(bus, FRAMES_TO_PROCESS); diff --git a/packages/react-native-audio-api/common/cpp/test/src/GainTest.cpp b/packages/react-native-audio-api/common/cpp/test/src/GainTest.cpp index e34870fb6..1accf6785 100644 --- a/packages/react-native-audio-api/common/cpp/test/src/GainTest.cpp +++ b/packages/react-native-audio-api/common/cpp/test/src/GainTest.cpp @@ -3,7 +3,7 @@ #include #include #include -#include +#include #include #include #include @@ -26,14 +26,15 @@ class GainTest : public ::testing::Test { class TestableGainNode : public GainNode { public: - explicit TestableGainNode(std::shared_ptr context) : GainNode(context, GainOptions()) {} + explicit TestableGainNode(std::shared_ptr context) + : GainNode(context, GainOptions()) {} void setGainParam(float value) { getGainParam()->setValue(value); } - std::shared_ptr processNode( - const std::shared_ptr &processingBus, + std::shared_ptr processNode( + const std::shared_ptr &processingBus, int framesToProcess) override { return GainNode::processNode(processingBus, framesToProcess); } @@ -50,9 +51,9 @@ TEST_F(GainTest, GainModulatesVolumeCorrectly) { auto gainNode = TestableGainNode(context); gainNode.setGainParam(GAIN_VALUE); - auto bus = std::make_shared(FRAMES_TO_PROCESS, 1, sampleRate); + auto bus = std::make_shared(FRAMES_TO_PROCESS, 1, sampleRate); for (size_t i = 0; i < bus->getSize(); ++i) { - bus->getChannel(0)->getData()[i] = i + 1; + (*bus->getChannel(0))[i] = i + 1; } auto resultBus = gainNode.processNode(bus, FRAMES_TO_PROCESS); @@ -67,10 +68,10 @@ TEST_F(GainTest, GainModulatesVolumeCorrectlyMultiChannel) { auto gainNode = TestableGainNode(context); gainNode.setGainParam(GAIN_VALUE); - auto bus = std::make_shared(FRAMES_TO_PROCESS, 2, sampleRate); + auto bus = std::make_shared(FRAMES_TO_PROCESS, 2, sampleRate); for (size_t i = 0; i < bus->getSize(); ++i) { - bus->getChannel(0)->getData()[i] = i + 1; - bus->getChannel(1)->getData()[i] = -i - 1; + (*bus->getChannel(0))[i] = i + 1; + (*bus->getChannel(1))[i] = -i - 1; } auto resultBus = gainNode.processNode(bus, FRAMES_TO_PROCESS); diff --git a/packages/react-native-audio-api/common/cpp/test/src/StereoPannerTest.cpp b/packages/react-native-audio-api/common/cpp/test/src/StereoPannerTest.cpp index 68ce23c55..18d935e9f 100644 --- a/packages/react-native-audio-api/common/cpp/test/src/StereoPannerTest.cpp +++ b/packages/react-native-audio-api/common/cpp/test/src/StereoPannerTest.cpp @@ -3,7 +3,7 @@ #include #include #include -#include +#include #include #include #include @@ -33,8 +33,8 @@ class TestableStereoPannerNode : public StereoPannerNode { getPanParam()->setValue(value); } - std::shared_ptr processNode( - const std::shared_ptr &processingBus, + std::shared_ptr processNode( + const std::shared_ptr &processingBus, int framesToProcess) override { return StereoPannerNode::processNode(processingBus, framesToProcess); } @@ -51,9 +51,9 @@ TEST_F(StereoPannerTest, PanModulatesInputMonoCorrectly) { auto panNode = TestableStereoPannerNode(context); panNode.setPanParam(PAN_VALUE); - auto bus = std::make_shared(FRAMES_TO_PROCESS, 1, sampleRate); + auto bus = std::make_shared(FRAMES_TO_PROCESS, 1, sampleRate); for (size_t i = 0; i < bus->getSize(); ++i) { - (*bus->getChannelByType(AudioBus::ChannelLeft))[i] = i + 1; + (*bus->getChannelByType(AudioBuffer::ChannelLeft))[i] = i + 1; } auto resultBus = panNode.processNode(bus, FRAMES_TO_PROCESS); @@ -62,11 +62,11 @@ TEST_F(StereoPannerTest, PanModulatesInputMonoCorrectly) { // gainR = sin(x * (Ï€ / 2)) = sin(0.75 * (Ï€ / 2)) = 0.9238795325112867 for (size_t i = 0; i < FRAMES_TO_PROCESS; ++i) { EXPECT_NEAR( - (*resultBus->getChannelByType(AudioBus::ChannelLeft))[i], + (*resultBus->getChannelByType(AudioBuffer::ChannelLeft))[i], (i + 1) * 0.38268343236508984, 1e-4); EXPECT_NEAR( - (*resultBus->getChannelByType(AudioBus::ChannelRight))[i], + (*resultBus->getChannelByType(AudioBuffer::ChannelRight))[i], (i + 1) * 0.9238795325112867, 1e-4); } @@ -78,10 +78,10 @@ TEST_F(StereoPannerTest, PanModulatesInputStereoCorrectlyWithNegativePan) { auto panNode = TestableStereoPannerNode(context); panNode.setPanParam(PAN_VALUE); - auto bus = std::make_shared(FRAMES_TO_PROCESS, 2, sampleRate); + auto bus = std::make_shared(FRAMES_TO_PROCESS, 2, sampleRate); for (size_t i = 0; i < bus->getSize(); ++i) { - (*bus->getChannelByType(AudioBus::ChannelLeft))[i] = i + 1; - (*bus->getChannelByType(AudioBus::ChannelRight))[i] = i + 1; + (*bus->getChannelByType(AudioBuffer::ChannelLeft))[i] = i + 1; + (*bus->getChannelByType(AudioBuffer::ChannelRight))[i] = i + 1; } auto resultBus = panNode.processNode(bus, FRAMES_TO_PROCESS); @@ -90,11 +90,11 @@ TEST_F(StereoPannerTest, PanModulatesInputStereoCorrectlyWithNegativePan) { // gainR = sin(x * (Ï€ / 2)) = sin(0.5 * (Ï€ / 2)) = 0.7071067811865476 for (size_t i = 0; i < FRAMES_TO_PROCESS; ++i) { EXPECT_NEAR( - (*resultBus->getChannelByType(AudioBus::ChannelLeft))[i], + (*resultBus->getChannelByType(AudioBuffer::ChannelLeft))[i], (i + 1) + (i + 1) * 0.7071067811865476, 1e-4); EXPECT_NEAR( - (*resultBus->getChannelByType(AudioBus::ChannelRight))[i], + (*resultBus->getChannelByType(AudioBuffer::ChannelRight))[i], (i + 1) * 0.7071067811865476, 1e-4); } @@ -106,10 +106,10 @@ TEST_F(StereoPannerTest, PanModulatesInputStereoCorrectlyWithPositivePan) { auto panNode = TestableStereoPannerNode(context); panNode.setPanParam(PAN_VALUE); - auto bus = std::make_shared(FRAMES_TO_PROCESS, 2, sampleRate); + auto bus = std::make_shared(FRAMES_TO_PROCESS, 2, sampleRate); for (size_t i = 0; i < bus->getSize(); ++i) { - (*bus->getChannelByType(AudioBus::ChannelLeft))[i] = i + 1; - (*bus->getChannelByType(AudioBus::ChannelRight))[i] = i + 1; + (*bus->getChannelByType(AudioBuffer::ChannelLeft))[i] = i + 1; + (*bus->getChannelByType(AudioBuffer::ChannelRight))[i] = i + 1; } auto resultBus = panNode.processNode(bus, FRAMES_TO_PROCESS); @@ -118,11 +118,11 @@ TEST_F(StereoPannerTest, PanModulatesInputStereoCorrectlyWithPositivePan) { // gainR = sin(x * (Ï€ / 2)) = sin(0.75 * (Ï€ / 2)) = 0.9238795325112867 for (size_t i = 0; i < FRAMES_TO_PROCESS; ++i) { EXPECT_NEAR( - (*resultBus->getChannelByType(AudioBus::ChannelLeft))[i], + (*resultBus->getChannelByType(AudioBuffer::ChannelLeft))[i], (i + 1) * 0.38268343236508984, 1e-4); EXPECT_NEAR( - (*resultBus->getChannelByType(AudioBus::ChannelRight))[i], + (*resultBus->getChannelByType(AudioBuffer::ChannelRight))[i], (i + 1) + (i + 1) * 0.9238795325112867, 1e-4); } diff --git a/packages/react-native-audio-api/common/cpp/test/src/core/effects/WaveShaperNodeTest.cpp b/packages/react-native-audio-api/common/cpp/test/src/core/effects/WaveShaperNodeTest.cpp index 679b4f76e..6ae4eb87d 100644 --- a/packages/react-native-audio-api/common/cpp/test/src/core/effects/WaveShaperNodeTest.cpp +++ b/packages/react-native-audio-api/common/cpp/test/src/core/effects/WaveShaperNodeTest.cpp @@ -1,10 +1,10 @@ #include #include #include -#include #include +#include #include -#include +#include #include #include #include @@ -29,14 +29,14 @@ class TestableWaveShaperNode : public WaveShaperNode { explicit TestableWaveShaperNode(std::shared_ptr context) : WaveShaperNode(context, WaveShaperOptions()) { testCurve_ = std::make_shared(3); - auto data = testCurve_->getData(); + auto data = testCurve_->span(); data[0] = -2.0f; data[1] = 0.0f; data[2] = 2.0f; } - std::shared_ptr processNode( - const std::shared_ptr &processingBus, + std::shared_ptr processNode( + const std::shared_ptr &processingBus, int framesToProcess) override { return WaveShaperNode::processNode(processingBus, framesToProcess); } @@ -61,14 +61,14 @@ TEST_F(WaveShaperNodeTest, NoneOverSamplingProcessesCorrectly) { waveShaper->setOversample(OverSampleType::OVERSAMPLE_NONE); waveShaper->setCurve(waveShaper->testCurve_); - auto bus = std::make_shared(FRAMES_TO_PROCESS, 1, sampleRate); + auto bus = std::make_shared(FRAMES_TO_PROCESS, 1, sampleRate); for (size_t i = 0; i < bus->getSize(); ++i) { - bus->getChannel(0)->getData()[i] = -1.0f + i * 0.5f; + (*bus->getChannel(0))[i] = -1.0f + i * 0.5f; } auto resultBus = waveShaper->processNode(bus, FRAMES_TO_PROCESS); - auto curveData = waveShaper->testCurve_->getData(); - auto resultData = resultBus->getChannel(0)->getData(); + auto curveData = waveShaper->testCurve_->span(); + auto resultData = resultBus->getChannel(0)->span(); EXPECT_FLOAT_EQ(resultData[0], curveData[0]); EXPECT_FLOAT_EQ(resultData[1], -1.0f); diff --git a/packages/react-native-audio-api/common/cpp/test/src/dsp/ResamplerTest.cpp b/packages/react-native-audio-api/common/cpp/test/src/dsp/ResamplerTest.cpp index f62fc9824..21e868148 100644 --- a/packages/react-native-audio-api/common/cpp/test/src/dsp/ResamplerTest.cpp +++ b/packages/react-native-audio-api/common/cpp/test/src/dsp/ResamplerTest.cpp @@ -1,16 +1,16 @@ +#include #include #include #include -#include -#include +#include #include #include using namespace audioapi; class ResamplerTest : public ::testing::Test { - protected: - static constexpr int KERNEL_SIZE = RENDER_QUANTUM_SIZE; + protected: + static constexpr int KERNEL_SIZE = RENDER_QUANTUM_SIZE; }; class TestableUpSampler : public UpSampler { @@ -39,7 +39,8 @@ TEST_F(ResamplerTest, UpSamplerCanBeCreated) { } TEST_F(ResamplerTest, DownSamplerCanBeCreated) { - auto downSampler = std::make_unique(RENDER_QUANTUM_SIZE * 2, RENDER_QUANTUM_SIZE * 2); + auto downSampler = + std::make_unique(RENDER_QUANTUM_SIZE * 2, RENDER_QUANTUM_SIZE * 2); ASSERT_NE(downSampler, nullptr); } @@ -109,8 +110,8 @@ TEST_F(ResamplerTest, UpDownSamplingProcess) { int upSamplerOutputFrames; int downSamplerOutputFrames; - EXPECT_NO_THROW(upSamplerOutputFrames = upSampler->process(inputArray, outputArray, 4)); - EXPECT_NO_THROW(downSamplerOutputFrames = downSampler->process(outputArray, inputArray, 8)); + EXPECT_NO_THROW(upSamplerOutputFrames = upSampler->process(*inputArray, *outputArray, 4)); + EXPECT_NO_THROW(downSamplerOutputFrames = downSampler->process(*outputArray, *inputArray, 8)); EXPECT_EQ(upSamplerOutputFrames, 8); EXPECT_EQ(downSamplerOutputFrames, 4); diff --git a/packages/react-native-audio-api/ios/audioapi/ios/core/IOSAudioPlayer.h b/packages/react-native-audio-api/ios/audioapi/ios/core/IOSAudioPlayer.h index 21e858888..c11e9b7fd 100644 --- a/packages/react-native-audio-api/ios/audioapi/ios/core/IOSAudioPlayer.h +++ b/packages/react-native-audio-api/ios/audioapi/ios/core/IOSAudioPlayer.h @@ -10,13 +10,13 @@ typedef struct objc_object NativeAudioPlayer; namespace audioapi { -class AudioBus; +class AudioBuffer; class AudioContext; class IOSAudioPlayer { public: IOSAudioPlayer( - const std::function, int)> &renderAudio, + const std::function, int)> &renderAudio, float sampleRate, int channelCount); ~IOSAudioPlayer(); @@ -30,9 +30,9 @@ class IOSAudioPlayer { bool isRunning() const; protected: - std::shared_ptr audioBus_; + std::shared_ptr audioBus_; NativeAudioPlayer *audioPlayer_; - std::function, int)> renderAudio_; + std::function, int)> renderAudio_; int channelCount_; std::atomic isRunning_; }; diff --git a/packages/react-native-audio-api/ios/audioapi/ios/core/IOSAudioPlayer.mm b/packages/react-native-audio-api/ios/audioapi/ios/core/IOSAudioPlayer.mm index 0b2609a1f..1c33c8ed0 100644 --- a/packages/react-native-audio-api/ios/audioapi/ios/core/IOSAudioPlayer.mm +++ b/packages/react-native-audio-api/ios/audioapi/ios/core/IOSAudioPlayer.mm @@ -5,12 +5,12 @@ #include #include #include -#include +#include namespace audioapi { IOSAudioPlayer::IOSAudioPlayer( - const std::function, int)> &renderAudio, + const std::function, int)> &renderAudio, float sampleRate, int channelCount) : renderAudio_(renderAudio), channelCount_(channelCount), audioBus_(0), isRunning_(false) @@ -42,7 +42,7 @@ sampleRate:sampleRate channelCount:channelCount_]; - audioBus_ = std::make_shared(RENDER_QUANTUM_SIZE, channelCount_, sampleRate); + audioBus_ = std::make_shared(RENDER_QUANTUM_SIZE, channelCount_, sampleRate); } IOSAudioPlayer::~IOSAudioPlayer() diff --git a/packages/react-native-audio-api/ios/audioapi/ios/core/IOSAudioRecorder.mm b/packages/react-native-audio-api/ios/audioapi/ios/core/IOSAudioRecorder.mm index ac6229b1b..9e6168fcb 100644 --- a/packages/react-native-audio-api/ios/audioapi/ios/core/IOSAudioRecorder.mm +++ b/packages/react-native-audio-api/ios/audioapi/ios/core/IOSAudioRecorder.mm @@ -16,7 +16,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/packages/react-native-audio-api/ios/audioapi/ios/core/utils/AudioDecoder.mm b/packages/react-native-audio-api/ios/audioapi/ios/core/utils/AudioDecoder.mm index 3b2b4b8d4..62b7a7914 100644 --- a/packages/react-native-audio-api/ios/audioapi/ios/core/utils/AudioDecoder.mm +++ b/packages/react-native-audio-api/ios/audioapi/ios/core/utils/AudioDecoder.mm @@ -2,16 +2,16 @@ #include #include -#include #include #include #include #include +#include #if !RN_AUDIO_API_FFMPEG_DISABLED #include #endif // RN_AUDIO_API_FFMPEG_DISABLED #include -#include +#include namespace audioapi { @@ -51,7 +51,7 @@ } auto outputFrames = buffer.size() / outputChannels; - auto audioBus = std::make_shared(outputFrames, outputChannels, outputSampleRate); + auto audioBus = std::make_shared(outputFrames, outputChannels, outputSampleRate); for (int ch = 0; ch < outputChannels; ++ch) { auto channelData = audioBus->getChannel(ch)->getData(); @@ -152,7 +152,8 @@ const auto uint8Data = reinterpret_cast(decodedData.data()); size_t numFramesDecoded = decodedData.size() / (inputChannelCount * sizeof(int16_t)); - auto audioBus = std::make_shared(numFramesDecoded, inputChannelCount, inputSampleRate); + auto audioBus = + std::make_shared(numFramesDecoded, inputChannelCount, inputSampleRate); for (int ch = 0; ch < inputChannelCount; ++ch) { auto channelData = audioBus->getChannel(ch)->getData(); diff --git a/packages/react-native-audio-api/ios/audioapi/ios/core/utils/IOSRecorderCallback.h b/packages/react-native-audio-api/ios/audioapi/ios/core/utils/IOSRecorderCallback.h index 2c35ddeec..3409d6961 100644 --- a/packages/react-native-audio-api/ios/audioapi/ios/core/utils/IOSRecorderCallback.h +++ b/packages/react-native-audio-api/ios/audioapi/ios/core/utils/IOSRecorderCallback.h @@ -13,7 +13,7 @@ typedef struct objc_object AVAudioConverter; namespace audioapi { -class AudioBus; +class AudioBuffer; class CircularAudioArray; class AudioEventHandlerRegistry; diff --git a/packages/react-native-audio-api/ios/audioapi/ios/core/utils/IOSRecorderCallback.mm b/packages/react-native-audio-api/ios/audioapi/ios/core/utils/IOSRecorderCallback.mm index 3293f8f20..d7c951aa3 100644 --- a/packages/react-native-audio-api/ios/audioapi/ios/core/utils/IOSRecorderCallback.mm +++ b/packages/react-native-audio-api/ios/audioapi/ios/core/utils/IOSRecorderCallback.mm @@ -7,7 +7,7 @@ #include #include #include -#include +#include #include #include #include From 55bb04b4dfd3ad4076494150841d7a32bdcee284 Mon Sep 17 00:00:00 2001 From: maciejmakowski2003 Date: Tue, 3 Feb 2026 15:33:16 +0100 Subject: [PATCH 09/30] fix: a few fixes --- .../HostObjects/sources/AudioBufferHostObject.cpp | 4 ++-- .../common/cpp/audioapi/core/OfflineAudioContext.cpp | 2 +- .../cpp/audioapi/core/sources/AudioBufferSourceNode.cpp | 2 +- .../common/cpp/audioapi/dsp/Convolver.cpp | 8 ++++++-- .../ios/audioapi/ios/core/IOSAudioPlayer.mm | 5 ++--- .../ios/audioapi/ios/core/IOSAudioRecorder.mm | 3 ++- .../ios/audioapi/ios/core/utils/AudioDecoder.mm | 8 ++++---- .../ios/audioapi/ios/core/utils/IOSRecorderCallback.mm | 6 ++++-- 8 files changed, 22 insertions(+), 16 deletions(-) diff --git a/packages/react-native-audio-api/common/cpp/audioapi/HostObjects/sources/AudioBufferHostObject.cpp b/packages/react-native-audio-api/common/cpp/audioapi/HostObjects/sources/AudioBufferHostObject.cpp index cdaff96b0..1ac1d28af 100644 --- a/packages/react-native-audio-api/common/cpp/audioapi/HostObjects/sources/AudioBufferHostObject.cpp +++ b/packages/react-native-audio-api/common/cpp/audioapi/HostObjects/sources/AudioBufferHostObject.cpp @@ -58,7 +58,7 @@ JSI_HOST_FUNCTION_IMPL(AudioBufferHostObject, copyFromChannel) { auto arrayBuffer = args[0].getObject(runtime).getPropertyAsObject(runtime, "buffer").getArrayBuffer(runtime); auto destination = reinterpret_cast(arrayBuffer.data(runtime)); - auto length = static_cast(arrayBuffer.size(runtime)); + auto length = arrayBuffer.size(runtime) / sizeof(float); auto channelNumber = static_cast(args[1].getNumber()); auto startInChannel = static_cast(args[2].getNumber()); @@ -71,7 +71,7 @@ JSI_HOST_FUNCTION_IMPL(AudioBufferHostObject, copyToChannel) { auto arrayBuffer = args[0].getObject(runtime).getPropertyAsObject(runtime, "buffer").getArrayBuffer(runtime); auto source = reinterpret_cast(arrayBuffer.data(runtime)); - auto length = static_cast(arrayBuffer.size(runtime)); + auto length = arrayBuffer.size(runtime) / sizeof(float); auto channelNumber = static_cast(args[1].getNumber()); auto startInChannel = static_cast(args[2].getNumber()); diff --git a/packages/react-native-audio-api/common/cpp/audioapi/core/OfflineAudioContext.cpp b/packages/react-native-audio-api/common/cpp/audioapi/core/OfflineAudioContext.cpp index 9b2b15f7a..79cb330cf 100644 --- a/packages/react-native-audio-api/common/cpp/audioapi/core/OfflineAudioContext.cpp +++ b/packages/react-native-audio-api/common/cpp/audioapi/core/OfflineAudioContext.cpp @@ -74,7 +74,7 @@ void OfflineAudioContext::renderAudio() { destination_->renderAudio(audioBus, framesToProcess); - resultBus_->copy(*audioBus, currentSampleFrame_, 0, framesToProcess); + resultBus_->copy(*audioBus, 0, currentSampleFrame_, framesToProcess); currentSampleFrame_ += framesToProcess; diff --git a/packages/react-native-audio-api/common/cpp/audioapi/core/sources/AudioBufferSourceNode.cpp b/packages/react-native-audio-api/common/cpp/audioapi/core/sources/AudioBufferSourceNode.cpp index ce42ba036..591698447 100644 --- a/packages/react-native-audio-api/common/cpp/audioapi/core/sources/AudioBufferSourceNode.cpp +++ b/packages/react-native-audio-api/common/cpp/audioapi/core/sources/AudioBufferSourceNode.cpp @@ -97,7 +97,7 @@ void AudioBufferSourceNode::setBuffer(const std::shared_ptr &buffer size_t totalSize = buffer_->getSize() + extraTailFrames; alignedBus_ = std::make_shared(totalSize, channelCount_, buffer_->getSampleRate()); - alignedBus_->copy(*buffer_); + alignedBus_->copy(*buffer_, 0, 0, buffer_->getSize()); alignedBus_->zero(buffer_->getSize(), extraTailFrames); } else { diff --git a/packages/react-native-audio-api/common/cpp/audioapi/dsp/Convolver.cpp b/packages/react-native-audio-api/common/cpp/audioapi/dsp/Convolver.cpp index 5d23ef200..29a619251 100644 --- a/packages/react-native-audio-api/common/cpp/audioapi/dsp/Convolver.cpp +++ b/packages/react-native-audio-api/common/cpp/audioapi/dsp/Convolver.cpp @@ -38,8 +38,12 @@ void Convolver::reset() { _segments.clear(); _segmentsIR.clear(); _preMultiplied.clear(); - _fftBuffer->zero(); - _inputBuffer->zero(); + if (_fftBuffer) { + _fftBuffer->zero(); + } + if (_inputBuffer) { + _inputBuffer->zero(); + } } bool Convolver::init(size_t blockSize, const audioapi::AudioArray &ir, size_t irLen) { diff --git a/packages/react-native-audio-api/ios/audioapi/ios/core/IOSAudioPlayer.mm b/packages/react-native-audio-api/ios/audioapi/ios/core/IOSAudioPlayer.mm index 1c33c8ed0..e86575440 100644 --- a/packages/react-native-audio-api/ios/audioapi/ios/core/IOSAudioPlayer.mm +++ b/packages/react-native-audio-api/ios/audioapi/ios/core/IOSAudioPlayer.mm @@ -29,9 +29,8 @@ for (int channel = 0; channel < channelCount_; channel += 1) { float *outputChannel = (float *)outputData->mBuffers[channel].mData; - auto *inputChannel = audioBus_->getChannel(channel)->getData(); - - memcpy(outputChannel + processedFrames, inputChannel, framesToProcess * sizeof(float)); + + audioBus_->getChannel(channel)->copyTo(outputChannel, 0, processedFrames, framesToProcess); } processedFrames += framesToProcess; diff --git a/packages/react-native-audio-api/ios/audioapi/ios/core/IOSAudioRecorder.mm b/packages/react-native-audio-api/ios/audioapi/ios/core/IOSAudioRecorder.mm index 9e6168fcb..70e6d2408 100644 --- a/packages/react-native-audio-api/ios/audioapi/ios/core/IOSAudioRecorder.mm +++ b/packages/react-native-audio-api/ios/audioapi/ios/core/IOSAudioRecorder.mm @@ -53,7 +53,8 @@ for (size_t channel = 0; channel < adapterNode_->channelCount_; ++channel) { float *channelData = (float *)inputBuffer->mBuffers[channel].mData; - adapterNode_->buff_[channel]->write(channelData, numFrames); + // TODO +// adapterNode_->buff_[channel]->write(channelData, numFrames); } } } diff --git a/packages/react-native-audio-api/ios/audioapi/ios/core/utils/AudioDecoder.mm b/packages/react-native-audio-api/ios/audioapi/ios/core/utils/AudioDecoder.mm index 62b7a7914..3d2df2fb5 100644 --- a/packages/react-native-audio-api/ios/audioapi/ios/core/utils/AudioDecoder.mm +++ b/packages/react-native-audio-api/ios/audioapi/ios/core/utils/AudioDecoder.mm @@ -54,13 +54,13 @@ auto audioBus = std::make_shared(outputFrames, outputChannels, outputSampleRate); for (int ch = 0; ch < outputChannels; ++ch) { - auto channelData = audioBus->getChannel(ch)->getData(); + auto channelData = audioBus->getChannel(ch)->span(); for (int i = 0; i < outputFrames; ++i) { channelData[i] = buffer[i * outputChannels + ch]; } } - return std::make_shared(audioBus); + return audioBus; } std::shared_ptr AudioDecoder::decodeWithFilePath( @@ -156,7 +156,7 @@ std::make_shared(numFramesDecoded, inputChannelCount, inputSampleRate); for (int ch = 0; ch < inputChannelCount; ++ch) { - auto channelData = audioBus->getChannel(ch)->getData(); + auto channelData = audioBus->getChannel(ch)->span(); for (size_t i = 0; i < numFramesDecoded; ++i) { size_t offset; @@ -171,7 +171,7 @@ channelData[i] = uint8ToFloat(uint8Data[offset], uint8Data[offset + 1]); } } - return std::make_shared(audioBus); + return audioBus; } } // namespace audioapi diff --git a/packages/react-native-audio-api/ios/audioapi/ios/core/utils/IOSRecorderCallback.mm b/packages/react-native-audio-api/ios/audioapi/ios/core/utils/IOSRecorderCallback.mm index 12d7b1d5a..bfb43be57 100644 --- a/packages/react-native-audio-api/ios/audioapi/ios/core/utils/IOSRecorderCallback.mm +++ b/packages/react-native-audio-api/ios/audioapi/ios/core/utils/IOSRecorderCallback.mm @@ -150,7 +150,8 @@ // Directly write to circular buffer for (int i = 0; i < channelCount_; ++i) { auto *inputChannel = static_cast(inputBuffer->mBuffers[i].mData); - circularBus_[i]->push_back(inputChannel, numFrames); + // TODO +// circularBus_[i]->push_back(inputChannel, numFrames); } if (circularBus_[0]->getNumberOfAvailableFrames() >= bufferLength_) { @@ -197,7 +198,8 @@ for (int i = 0; i < channelCount_; ++i) { auto *inputChannel = static_cast(converterOutputBuffer_.audioBufferList->mBuffers[i].mData); - circularBus_[i]->push_back(inputChannel, outputFrameCount); + // TODO + //circularBus_[i]->push_back(inputChannel, outputFrameCount); } if (circularBus_[0]->getNumberOfAvailableFrames() >= bufferLength_) { From e3b937c4167f66612c88338aad27c9144448dcdd Mon Sep 17 00:00:00 2001 From: maciejmakowski2003 Date: Tue, 3 Feb 2026 15:33:57 +0100 Subject: [PATCH 10/30] fix: lint --- .../ios/audioapi/ios/core/IOSAudioPlayer.mm | 2 +- .../ios/audioapi/ios/core/IOSAudioRecorder.mm | 2 +- .../ios/audioapi/ios/core/utils/IOSRecorderCallback.mm | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/react-native-audio-api/ios/audioapi/ios/core/IOSAudioPlayer.mm b/packages/react-native-audio-api/ios/audioapi/ios/core/IOSAudioPlayer.mm index e86575440..4d1d61b05 100644 --- a/packages/react-native-audio-api/ios/audioapi/ios/core/IOSAudioPlayer.mm +++ b/packages/react-native-audio-api/ios/audioapi/ios/core/IOSAudioPlayer.mm @@ -29,7 +29,7 @@ for (int channel = 0; channel < channelCount_; channel += 1) { float *outputChannel = (float *)outputData->mBuffers[channel].mData; - + audioBus_->getChannel(channel)->copyTo(outputChannel, 0, processedFrames, framesToProcess); } diff --git a/packages/react-native-audio-api/ios/audioapi/ios/core/IOSAudioRecorder.mm b/packages/react-native-audio-api/ios/audioapi/ios/core/IOSAudioRecorder.mm index 70e6d2408..d71f68ca2 100644 --- a/packages/react-native-audio-api/ios/audioapi/ios/core/IOSAudioRecorder.mm +++ b/packages/react-native-audio-api/ios/audioapi/ios/core/IOSAudioRecorder.mm @@ -54,7 +54,7 @@ float *channelData = (float *)inputBuffer->mBuffers[channel].mData; // TODO -// adapterNode_->buff_[channel]->write(channelData, numFrames); + // adapterNode_->buff_[channel]->write(channelData, numFrames); } } } diff --git a/packages/react-native-audio-api/ios/audioapi/ios/core/utils/IOSRecorderCallback.mm b/packages/react-native-audio-api/ios/audioapi/ios/core/utils/IOSRecorderCallback.mm index bfb43be57..d8ad00655 100644 --- a/packages/react-native-audio-api/ios/audioapi/ios/core/utils/IOSRecorderCallback.mm +++ b/packages/react-native-audio-api/ios/audioapi/ios/core/utils/IOSRecorderCallback.mm @@ -151,7 +151,7 @@ for (int i = 0; i < channelCount_; ++i) { auto *inputChannel = static_cast(inputBuffer->mBuffers[i].mData); // TODO -// circularBus_[i]->push_back(inputChannel, numFrames); + // circularBus_[i]->push_back(inputChannel, numFrames); } if (circularBus_[0]->getNumberOfAvailableFrames() >= bufferLength_) { From 83e8fdde9dff27e31f9aa4144492e515803a3250 Mon Sep 17 00:00:00 2001 From: maciejmakowski2003 Date: Tue, 3 Feb 2026 16:17:35 +0100 Subject: [PATCH 11/30] fix: fixed tests --- .../common/cpp/test/src/core/effects/WaveShaperNodeTest.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/react-native-audio-api/common/cpp/test/src/core/effects/WaveShaperNodeTest.cpp b/packages/react-native-audio-api/common/cpp/test/src/core/effects/WaveShaperNodeTest.cpp index 6ae4eb87d..474e953d0 100644 --- a/packages/react-native-audio-api/common/cpp/test/src/core/effects/WaveShaperNodeTest.cpp +++ b/packages/react-native-audio-api/common/cpp/test/src/core/effects/WaveShaperNodeTest.cpp @@ -3,7 +3,7 @@ #include #include #include -#include +#include #include #include #include @@ -28,7 +28,7 @@ class TestableWaveShaperNode : public WaveShaperNode { public: explicit TestableWaveShaperNode(std::shared_ptr context) : WaveShaperNode(context, WaveShaperOptions()) { - testCurve_ = std::make_shared(3); + testCurve_ = std::make_shared(3); auto data = testCurve_->span(); data[0] = -2.0f; data[1] = 0.0f; @@ -41,7 +41,7 @@ class TestableWaveShaperNode : public WaveShaperNode { return WaveShaperNode::processNode(processingBus, framesToProcess); } - std::shared_ptr testCurve_; + std::shared_ptr testCurve_; }; TEST_F(WaveShaperNodeTest, WaveShaperNodeCanBeCreated) { From 122b9e0b042e02fc7123f5eabd2b45f7893cbc42 Mon Sep 17 00:00:00 2001 From: maciejmakowski2003 Date: Wed, 4 Feb 2026 07:34:05 +0100 Subject: [PATCH 12/30] fix: todos --- .../android/core/AndroidAudioRecorder.cpp | 27 +++++++++---------- .../android/core/AndroidAudioRecorder.h | 3 --- .../core/utils/AndroidRecorderCallback.h | 2 -- .../cpp/audioapi/core/inputs/AudioRecorder.h | 4 +++ .../core/utils/AudioRecorderCallback.h | 2 ++ .../common/cpp/audioapi/utils/AudioArray.cpp | 7 +++-- .../common/cpp/audioapi/utils/AudioArray.h | 1 + .../ios/audioapi/ios/core/IOSAudioRecorder.h | 1 + .../ios/audioapi/ios/core/IOSAudioRecorder.mm | 26 +++++++++++------- .../ios/core/utils/IOSRecorderCallback.mm | 20 +++++++++++--- 10 files changed, 56 insertions(+), 37 deletions(-) diff --git a/packages/react-native-audio-api/android/src/main/cpp/audioapi/android/core/AndroidAudioRecorder.cpp b/packages/react-native-audio-api/android/src/main/cpp/audioapi/android/core/AndroidAudioRecorder.cpp index 30bcc4bba..fad36c5c2 100644 --- a/packages/react-native-audio-api/android/src/main/cpp/audioapi/android/core/AndroidAudioRecorder.cpp +++ b/packages/react-native-audio-api/android/src/main/cpp/audioapi/android/core/AndroidAudioRecorder.cpp @@ -28,8 +28,7 @@ AndroidAudioRecorder::AndroidAudioRecorder( const std::shared_ptr &audioEventHandlerRegistry) : AudioRecorder(audioEventHandlerRegistry), streamSampleRate_(0.0), - streamChannelCount_(0), - streamMaxBufferSizeInFrames_(0) {} + streamChannelCount_(0) {} /// @brief Destructor ensures that the audio stream and each output type are closed and flushed up remaining data. /// TODO: Possibly locks here are not necessary, but we might have an issue with oboe having raw pointer to the @@ -91,7 +90,7 @@ Result AndroidAudioRecorder::openAudioStream() { streamSampleRate_ = static_cast(mStream_->getSampleRate()); streamChannelCount_ = mStream_->getChannelCount(); - streamMaxBufferSizeInFrames_ = mStream_->getBufferSizeInFrames(); + maxBufferSizeInFrames_ = mStream_->getBufferSizeInFrames(); return Result::Ok(None); } @@ -126,7 +125,7 @@ Result AndroidAudioRecorder::start(const std::string & ->openFile( streamSampleRate_, streamChannelCount_, - streamMaxBufferSizeInFrames_, + maxBufferSizeInFrames_, fileNameOverride); if (!fileResult.is_ok()) { @@ -139,12 +138,12 @@ Result AndroidAudioRecorder::start(const std::string & if (usesCallback()) { std::static_pointer_cast(dataCallback_) - ->prepare(streamSampleRate_, streamChannelCount_, streamMaxBufferSizeInFrames_); + ->prepare(streamSampleRate_, streamChannelCount_, maxBufferSizeInFrames_); } if (isConnected()) { - deinterleavingBuffer_ = std::make_shared(streamMaxBufferSizeInFrames_); - adapterNode_->init(streamMaxBufferSizeInFrames_, streamChannelCount_); + deinterleavingArray_ = std::make_shared(maxBufferSizeInFrames_); + adapterNode_->init(maxBufferSizeInFrames_, streamChannelCount_); } auto result = mStream_->requestStart(); @@ -233,7 +232,7 @@ Result AndroidAudioRecorder::enableFileOutput( if (!isIdle()) { auto fileResult = std::static_pointer_cast(fileWriter_) - ->openFile(streamSampleRate_, streamChannelCount_, streamMaxBufferSizeInFrames_, ""); + ->openFile(streamSampleRate_, streamChannelCount_, maxBufferSizeInFrames_, ""); if (!fileResult.is_ok()) { return Result::Err( @@ -298,7 +297,7 @@ Result AndroidAudioRecorder::setOnAudioReadyCallback( if (!isIdle()) { std::static_pointer_cast(dataCallback_) - ->prepare(streamSampleRate_, streamChannelCount_, streamMaxBufferSizeInFrames_); + ->prepare(streamSampleRate_, streamChannelCount_, maxBufferSizeInFrames_); } callbackOutputEnabled_.store(true, std::memory_order_release); @@ -324,8 +323,8 @@ void AndroidAudioRecorder::connect(const std::shared_ptr &n adapterNode_ = node; if (!isIdle()) { - deinterleavingBuffer_ = std::make_shared(streamMaxBufferSizeInFrames_); - adapterNode_->init(streamMaxBufferSizeInFrames_, streamChannelCount_); + deinterleavingArray_ = std::make_shared(maxBufferSizeInFrames_); + adapterNode_->init(maxBufferSizeInFrames_, streamChannelCount_); } isConnected_.store(true, std::memory_order_release); @@ -337,7 +336,7 @@ void AndroidAudioRecorder::connect(const std::shared_ptr &n void AndroidAudioRecorder::disconnect() { std::scoped_lock adapterLock(adapterNodeMutex_); isConnected_.store(false, std::memory_order_release); - deinterleavingBuffer_ = nullptr; + deinterleavingArray_ = nullptr; adapterNode_ = nullptr; } @@ -375,13 +374,13 @@ oboe::DataCallbackResult AndroidAudioRecorder::onAudioReady( if (isConnected()) { if (auto adapterLock = Locker::tryLock(adapterNodeMutex_)) { for (int channel = 0; channel < streamChannelCount_; ++channel) { - auto channelData = deinterleavingBuffer_->span(); + auto channelData = deinterleavingArray_->span(); for (int frame = 0; frame < numFrames; ++frame) { channelData[frame] = static_cast(audioData)[frame * streamChannelCount_ + channel]; } - adapterNode_->buff_[channel]->write(*deinterleavingBuffer_, numFrames); + adapterNode_->buff_[channel]->write(*deinterleavingArray_, numFrames); } } } diff --git a/packages/react-native-audio-api/android/src/main/cpp/audioapi/android/core/AndroidAudioRecorder.h b/packages/react-native-audio-api/android/src/main/cpp/audioapi/android/core/AndroidAudioRecorder.h index 625fa91d9..7a242c479 100644 --- a/packages/react-native-audio-api/android/src/main/cpp/audioapi/android/core/AndroidAudioRecorder.h +++ b/packages/react-native-audio-api/android/src/main/cpp/audioapi/android/core/AndroidAudioRecorder.h @@ -55,11 +55,8 @@ class AndroidAudioRecorder : public oboe::AudioStreamCallback, public AudioRecor void onErrorAfterClose(oboe::AudioStream *oboeStream, oboe::Result error) override; private: - std::shared_ptr deinterleavingBuffer_; - float streamSampleRate_; int32_t streamChannelCount_; - int32_t streamMaxBufferSizeInFrames_; facebook::jni::global_ref nativeAudioRecorder_; diff --git a/packages/react-native-audio-api/android/src/main/cpp/audioapi/android/core/utils/AndroidRecorderCallback.h b/packages/react-native-audio-api/android/src/main/cpp/audioapi/android/core/utils/AndroidRecorderCallback.h index a20a4eb47..614967462 100644 --- a/packages/react-native-audio-api/android/src/main/cpp/audioapi/android/core/utils/AndroidRecorderCallback.h +++ b/packages/react-native-audio-api/android/src/main/cpp/audioapi/android/core/utils/AndroidRecorderCallback.h @@ -44,8 +44,6 @@ class AndroidRecorderCallback : public AudioRecorderCallback { ma_uint64 processingBufferLength_{0}; std::unique_ptr converter_{nullptr}; - std::shared_ptr deinterleavingArray_; - void deinterleaveAndPushAudioData(void *data, int numFrames); private: diff --git a/packages/react-native-audio-api/common/cpp/audioapi/core/inputs/AudioRecorder.h b/packages/react-native-audio-api/common/cpp/audioapi/core/inputs/AudioRecorder.h index c2b196765..7c379fe3c 100644 --- a/packages/react-native-audio-api/common/cpp/audioapi/core/inputs/AudioRecorder.h +++ b/packages/react-native-audio-api/common/cpp/audioapi/core/inputs/AudioRecorder.h @@ -1,6 +1,7 @@ #pragma once #include +#include #include #include #include @@ -65,6 +66,9 @@ class AudioRecorder { std::atomic fileOutputEnabled_{false}; std::atomic callbackOutputEnabled_{false}; + std::shared_ptr deinterleavingArray_; + size_t maxBufferSizeInFrames_ = 0; + std::mutex callbackMutex_; std::mutex fileWriterMutex_; std::mutex errorCallbackMutex_; diff --git a/packages/react-native-audio-api/common/cpp/audioapi/core/utils/AudioRecorderCallback.h b/packages/react-native-audio-api/common/cpp/audioapi/core/utils/AudioRecorderCallback.h index 74346aaef..d93e478e6 100644 --- a/packages/react-native-audio-api/common/cpp/audioapi/core/utils/AudioRecorderCallback.h +++ b/packages/react-native-audio-api/common/cpp/audioapi/core/utils/AudioRecorderCallback.h @@ -43,6 +43,8 @@ class AudioRecorderCallback { uint64_t callbackId_; size_t ringBufferSize_; + std::shared_ptr deinterleavingArray_; + std::atomic errorCallbackId_{0}; std::shared_ptr audioEventHandlerRegistry_; diff --git a/packages/react-native-audio-api/common/cpp/audioapi/utils/AudioArray.cpp b/packages/react-native-audio-api/common/cpp/audioapi/utils/AudioArray.cpp index af555c1bb..41713ff9e 100644 --- a/packages/react-native-audio-api/common/cpp/audioapi/utils/AudioArray.cpp +++ b/packages/react-native-audio-api/common/cpp/audioapi/utils/AudioArray.cpp @@ -22,7 +22,6 @@ AudioArray::AudioArray(const float *data, size_t size) : size_(size) { if (size_ > 0) { data_ = std::make_unique(size_); copy(data, 0, 0, size_); - std::memcpy(data_.get(), data, size_ * sizeof(float)); } } @@ -173,9 +172,9 @@ void AudioArray::copyTo(float *destination, size_t sourceStart, size_t destinati } void AudioArray::reverse() { - if (data_ == nullptr && size_ > 1) { - return; - } + if (data_ == nullptr && size_ > 1) { + return; + } std::reverse(begin(), end()); } diff --git a/packages/react-native-audio-api/common/cpp/audioapi/utils/AudioArray.h b/packages/react-native-audio-api/common/cpp/audioapi/utils/AudioArray.h index 85af5c272..fe7b26794 100644 --- a/packages/react-native-audio-api/common/cpp/audioapi/utils/AudioArray.h +++ b/packages/react-native-audio-api/common/cpp/audioapi/utils/AudioArray.h @@ -63,6 +63,7 @@ class AudioArray { if (offset + length > size_) { throw std::out_of_range("AudioArray::subSpan - offset + length exceeds array size"); } + return {data_.get() + offset, length}; } diff --git a/packages/react-native-audio-api/ios/audioapi/ios/core/IOSAudioRecorder.h b/packages/react-native-audio-api/ios/audioapi/ios/core/IOSAudioRecorder.h index 9137b9405..fc7174bb9 100644 --- a/packages/react-native-audio-api/ios/audioapi/ios/core/IOSAudioRecorder.h +++ b/packages/react-native-audio-api/ios/audioapi/ios/core/IOSAudioRecorder.h @@ -11,6 +11,7 @@ typedef struct objc_object NativeAudioRecorder; #include #include +#include #include diff --git a/packages/react-native-audio-api/ios/audioapi/ios/core/IOSAudioRecorder.mm b/packages/react-native-audio-api/ios/audioapi/ios/core/IOSAudioRecorder.mm index d71f68ca2..ad7227a5c 100644 --- a/packages/react-native-audio-api/ios/audioapi/ios/core/IOSAudioRecorder.mm +++ b/packages/react-native-audio-api/ios/audioapi/ios/core/IOSAudioRecorder.mm @@ -51,10 +51,14 @@ if (isConnected()) { if (auto lock = Locker::tryLock(adapterNodeMutex_)) { for (size_t channel = 0; channel < adapterNode_->channelCount_; ++channel) { - float *channelData = (float *)inputBuffer->mBuffers[channel].mData; - - // TODO - // adapterNode_->buff_[channel]->write(channelData, numFrames); + float *data = (float *)inputBuffer->mBuffers[channel].mData; + auto channelData = deinterleavingArray_->span(); + + for (int frame = 0; frame < numFrames; ++frame) { + channelData[frame] = data[frame]; + } + + adapterNode_->buff_[channel]->write(*deinterleavingArray_, numFrames); } } } @@ -100,12 +104,12 @@ [AudioEngine.sharedInstance stopIfNecessary]; // Estimate the maximum input buffer lengths that can be expected from the sink node - size_t maxInputBufferLength = [nativeRecorder_ getBufferSize]; + maxBufferSizeInFrames_ = [nativeRecorder_ getBufferSize]; auto inputFormat = [nativeRecorder_ getInputFormat]; if (usesFileOutput()) { auto fileResult = std::static_pointer_cast(fileWriter_) - ->openFile(inputFormat, maxInputBufferLength, fileNameOverride); + ->openFile(inputFormat, maxBufferSizeInFrames_, fileNameOverride); if (fileResult.is_err()) { return Result::Err( @@ -117,7 +121,7 @@ if (usesCallback()) { auto callbackResult = std::static_pointer_cast(dataCallback_) - ->prepare(inputFormat, maxInputBufferLength); + ->prepare(inputFormat, maxBufferSizeInFrames_); if (callbackResult.is_err()) { return Result::Err( @@ -126,8 +130,9 @@ } if (isConnected()) { + deinterleavingArray_ = std::make_shared(maxBufferSizeInFrames_); // TODO: pass sample rate, in case conversion is necessary - adapterNode_->init(maxInputBufferLength, inputFormat.channelCount); + adapterNode_->init(maxBufferSizeInFrames_, inputFormat.channelCount); } [nativeRecorder_ start]; @@ -227,8 +232,8 @@ adapterNode_ = node; if (!isIdle()) { - adapterNode_->init( - [nativeRecorder_ getBufferSize], [nativeRecorder_ getInputFormat].channelCount); + deinterleavingArray_ = std::make_shared(maxBufferSizeInFrames_); + adapterNode_->init(maxBufferSizeInFrames_, [nativeRecorder_ getInputFormat].channelCount); } isConnected_.store(true, std::memory_order_release); @@ -240,6 +245,7 @@ void IOSAudioRecorder::disconnect() { std::scoped_lock lock(adapterNodeMutex_); + deinterleavingArray_ = nullptr; adapterNode_ = nullptr; isConnected_.store(false, std::memory_order_release); } diff --git a/packages/react-native-audio-api/ios/audioapi/ios/core/utils/IOSRecorderCallback.mm b/packages/react-native-audio-api/ios/audioapi/ios/core/utils/IOSRecorderCallback.mm index d8ad00655..f0d3393a4 100644 --- a/packages/react-native-audio-api/ios/audioapi/ios/core/utils/IOSRecorderCallback.mm +++ b/packages/react-native-audio-api/ios/audioapi/ios/core/utils/IOSRecorderCallback.mm @@ -71,6 +71,8 @@ converterOutputBufferSize_ = std::max( (double)maxInputBufferLength, sampleRate_ / bufferFormat.sampleRate * maxInputBufferLength); + + deinterleavingArray_ = std::make_shared(converterOutputBufferSize_); callbackFormat_ = [[AVAudioFormat alloc] initWithCommonFormat:AVAudioPCMFormatFloat32 sampleRate:sampleRate_ @@ -150,8 +152,13 @@ // Directly write to circular buffer for (int i = 0; i < channelCount_; ++i) { auto *inputChannel = static_cast(inputBuffer->mBuffers[i].mData); - // TODO - // circularBus_[i]->push_back(inputChannel, numFrames); + auto channelData = deinterleavingArray_->span(); + + for (int frame = 0; frame < numFrames; ++frame) { + channelData[frame] = inputChannel[frame]; + } + + circularBus_[i]->push_back(*deinterleavingArray_, numFrames); } if (circularBus_[0]->getNumberOfAvailableFrames() >= bufferLength_) { @@ -198,8 +205,13 @@ for (int i = 0; i < channelCount_; ++i) { auto *inputChannel = static_cast(converterOutputBuffer_.audioBufferList->mBuffers[i].mData); - // TODO - //circularBus_[i]->push_back(inputChannel, outputFrameCount); + auto channelData = deinterleavingArray_->span(); + + for (int frame = 0; frame < numFrames; ++frame) { + channelData[frame] = inputChannel[frame]; + } + + circularBus_[i]->push_back(*deinterleavingArray_, outputFrameCount); } if (circularBus_[0]->getNumberOfAvailableFrames() >= bufferLength_) { From a87f2f7e97f17249b1524bfc1aad3327afeed330 Mon Sep 17 00:00:00 2001 From: maciejmakowski2003 Date: Wed, 4 Feb 2026 08:30:13 +0100 Subject: [PATCH 13/30] refactor: nits --- .../android/core/AndroidAudioRecorder.cpp | 14 ++-- .../audioapi/core/analysis/AnalyserNode.cpp | 44 +++++----- .../cpp/audioapi/core/analysis/AnalyserNode.h | 6 +- .../cpp/audioapi/core/inputs/AudioRecorder.h | 2 +- .../common/cpp/audioapi/dsp/VectorMath.cpp | 33 ++++++-- .../common/cpp/audioapi/dsp/VectorMath.h | 5 +- .../common/cpp/audioapi/utils/AudioArray.cpp | 83 ++++--------------- .../utils/CircularOverflowableAudioArray.h | 4 +- .../ios/audioapi/ios/core/IOSAudioRecorder.h | 2 +- .../ios/audioapi/ios/core/IOSAudioRecorder.mm | 8 +- .../ios/core/utils/IOSRecorderCallback.mm | 17 +--- 11 files changed, 87 insertions(+), 131 deletions(-) diff --git a/packages/react-native-audio-api/android/src/main/cpp/audioapi/android/core/AndroidAudioRecorder.cpp b/packages/react-native-audio-api/android/src/main/cpp/audioapi/android/core/AndroidAudioRecorder.cpp index fad36c5c2..37e9eb528 100644 --- a/packages/react-native-audio-api/android/src/main/cpp/audioapi/android/core/AndroidAudioRecorder.cpp +++ b/packages/react-native-audio-api/android/src/main/cpp/audioapi/android/core/AndroidAudioRecorder.cpp @@ -26,9 +26,7 @@ namespace audioapi { AndroidAudioRecorder::AndroidAudioRecorder( const std::shared_ptr &audioEventHandlerRegistry) - : AudioRecorder(audioEventHandlerRegistry), - streamSampleRate_(0.0), - streamChannelCount_(0) {} + : AudioRecorder(audioEventHandlerRegistry), streamSampleRate_(0.0), streamChannelCount_(0) {} /// @brief Destructor ensures that the audio stream and each output type are closed and flushed up remaining data. /// TODO: Possibly locks here are not necessary, but we might have an issue with oboe having raw pointer to the @@ -121,12 +119,10 @@ Result AndroidAudioRecorder::start(const std::string & } if (usesFileOutput()) { - auto fileResult = std::static_pointer_cast(fileWriter_) - ->openFile( - streamSampleRate_, - streamChannelCount_, - maxBufferSizeInFrames_, - fileNameOverride); + auto fileResult = + std::static_pointer_cast(fileWriter_) + ->openFile( + streamSampleRate_, streamChannelCount_, maxBufferSizeInFrames_, fileNameOverride); if (!fileResult.is_ok()) { return Result::Err( diff --git a/packages/react-native-audio-api/common/cpp/audioapi/core/analysis/AnalyserNode.cpp b/packages/react-native-audio-api/common/cpp/audioapi/core/analysis/AnalyserNode.cpp index 70c9ae50d..b1ae3b6c3 100644 --- a/packages/react-native-audio-api/common/cpp/audioapi/core/analysis/AnalyserNode.cpp +++ b/packages/react-native-audio-api/common/cpp/audioapi/core/analysis/AnalyserNode.cpp @@ -24,12 +24,12 @@ AnalyserNode::AnalyserNode( maxDecibels_(options.maxDecibels), smoothingTimeConstant_(options.smoothingTimeConstant), windowType_(WindowType::BLACKMAN), - inputBuffer_(std::make_unique(MAX_FFT_SIZE * 2)), + inputArray_(std::make_unique(MAX_FFT_SIZE * 2)), downMixBus_(std::make_unique(RENDER_QUANTUM_SIZE, 1, context->getSampleRate())), - tempBuffer_(std::make_unique(fftSize_)), + tempArray_(std::make_unique(fftSize_)), fft_(std::make_unique(fftSize_)), complexData_(std::vector>(fftSize_)), - magnitudeBuffer_(std::make_unique(fftSize_ / 2)) { + magnitudeArray_(std::make_unique(fftSize_ / 2)) { setWindowData(windowType_, fftSize_); isInitialized_ = true; } @@ -66,8 +66,8 @@ void AnalyserNode::setFftSize(int fftSize) { fftSize_ = fftSize; fft_ = std::make_unique(fftSize_); complexData_ = std::vector>(fftSize_); - magnitudeBuffer_ = std::make_unique(fftSize_ / 2); - tempBuffer_ = std::make_unique(fftSize_); + magnitudeArray_ = std::make_unique(fftSize_ / 2); + tempArray_ = std::make_unique(fftSize_); setWindowData(windowType_, fftSize_); } @@ -90,16 +90,19 @@ void AnalyserNode::setWindowType(AnalyserNode::WindowType type) { void AnalyserNode::getFloatFrequencyData(float *data, int length) { doFFTAnalysis(); - length = std::min(static_cast(magnitudeBuffer_->getSize()), length); - // TODO - // dsp::linearToDecibels(magnitudeBuffer_->getData(), data, length); + length = std::min(static_cast(magnitudeArray_->getSize()), length); + auto magnitudeSpan = magnitudeArray_->span(); + + for (int i = 0; i < length; i++) { + data[i] = dsp::linearToDecibels(magnitudeSpan[i]); + } } void AnalyserNode::getByteFrequencyData(uint8_t *data, int length) { doFFTAnalysis(); - auto magnitudeBufferData = magnitudeBuffer_->span(); - length = std::min(static_cast(magnitudeBuffer_->getSize()), length); + auto magnitudeBufferData = magnitudeArray_->span(); + length = std::min(static_cast(magnitudeArray_->getSize()), length); const auto rangeScaleFactor = maxDecibels_ == minDecibels_ ? 1 : 1 / (maxDecibels_ - minDecibels_); @@ -122,16 +125,17 @@ void AnalyserNode::getByteFrequencyData(uint8_t *data, int length) { void AnalyserNode::getFloatTimeDomainData(float *data, int length) { auto size = std::min(fftSize_, length); -// TODO -// inputBuffer_->pop_back(data, size, std::max(0, fftSize_ - size), true); + + inputArray_->pop_back(*tempArray_, size, std::max(0, fftSize_ - size), true); + tempArray_->copyTo(data, 0, 0, size); } void AnalyserNode::getByteTimeDomainData(uint8_t *data, int length) { auto size = std::min(fftSize_, length); - inputBuffer_->pop_back(*tempBuffer_, fftSize_, std::max(0, fftSize_ - size), true); + inputArray_->pop_back(*tempArray_, size, std::max(0, fftSize_ - size), true); - auto values = tempBuffer_->span(); + auto values = tempArray_->span(); for (int i = 0; i < size; i++) { float scaledValue = 128 * (values[i] + 1); @@ -156,7 +160,7 @@ std::shared_ptr AnalyserNode::processNode( // Down mix the input bus to mono downMixBus_->copy(*processingBus); // Copy the down mixed bus to the input buffer (circular buffer) - inputBuffer_->push_back(*downMixBus_->getChannel(0), framesToProcess, true); + inputArray_->push_back(*downMixBus_->getChannel(0), framesToProcess, true); shouldDoFFTAnalysis_ = true; @@ -172,20 +176,20 @@ void AnalyserNode::doFFTAnalysis() { // We want to copy last fftSize_ elements added to the input buffer to apply // the window. - inputBuffer_->pop_back(*tempBuffer_, fftSize_, 0, true); + inputArray_->pop_back(*tempArray_, fftSize_, 0, true); - tempBuffer_->multiply(*windowData_, fftSize_); + tempArray_->multiply(*windowData_, fftSize_); // do fft analysis - get frequency domain data - fft_->doFFT(*tempBuffer_, complexData_); + fft_->doFFT(*tempArray_, complexData_); // Zero out nquist component complexData_[0] = std::complex(complexData_[0].real(), 0); const float magnitudeScale = 1.0f / static_cast(fftSize_); - auto magnitudeBufferData = magnitudeBuffer_->span(); + auto magnitudeBufferData = magnitudeArray_->span(); - for (int i = 0; i < magnitudeBuffer_->getSize(); i++) { + for (int i = 0; i < magnitudeArray_->getSize(); i++) { auto scalarMagnitude = std::abs(complexData_[i]) * magnitudeScale; magnitudeBufferData[i] = static_cast( smoothingTimeConstant_ * magnitudeBufferData[i] + diff --git a/packages/react-native-audio-api/common/cpp/audioapi/core/analysis/AnalyserNode.h b/packages/react-native-audio-api/common/cpp/audioapi/core/analysis/AnalyserNode.h index 3ef915803..0dea5b123 100644 --- a/packages/react-native-audio-api/common/cpp/audioapi/core/analysis/AnalyserNode.h +++ b/packages/react-native-audio-api/common/cpp/audioapi/core/analysis/AnalyserNode.h @@ -56,13 +56,13 @@ class AnalyserNode : public AudioNode { WindowType windowType_; std::shared_ptr windowData_; - std::unique_ptr inputBuffer_; + std::unique_ptr inputArray_; std::unique_ptr downMixBus_; - std::unique_ptr tempBuffer_; + std::unique_ptr tempArray_; std::unique_ptr fft_; std::vector> complexData_; - std::unique_ptr magnitudeBuffer_; + std::unique_ptr magnitudeArray_; bool shouldDoFFTAnalysis_{true}; void doFFTAnalysis(); diff --git a/packages/react-native-audio-api/common/cpp/audioapi/core/inputs/AudioRecorder.h b/packages/react-native-audio-api/common/cpp/audioapi/core/inputs/AudioRecorder.h index 7c379fe3c..7df5cf075 100644 --- a/packages/react-native-audio-api/common/cpp/audioapi/core/inputs/AudioRecorder.h +++ b/packages/react-native-audio-api/common/cpp/audioapi/core/inputs/AudioRecorder.h @@ -1,7 +1,7 @@ #pragma once -#include #include +#include #include #include #include diff --git a/packages/react-native-audio-api/common/cpp/audioapi/dsp/VectorMath.cpp b/packages/react-native-audio-api/common/cpp/audioapi/dsp/VectorMath.cpp index 379dd3dfd..4cadc42be 100644 --- a/packages/react-native-audio-api/common/cpp/audioapi/dsp/VectorMath.cpp +++ b/packages/react-native-audio-api/common/cpp/audioapi/dsp/VectorMath.cpp @@ -656,13 +656,32 @@ void multiplyByScalarThenAddToOutput( #endif -void linearToDecibels( - const float *inputVector, - float *outputVector, - size_t numberOfElementsToProcess) { - for (int i = 0; i < numberOfElementsToProcess; i++) { - outputVector[i] = dsp::linearToDecibels(inputVector[i]); +float computeConvolution(const float *state, const float *kernel, size_t kernelSize) { + float sum = 0.0f; + int k = 0; + +#ifdef HAVE_ARM_NEON_INTRINSICS + float32x4_t vSum = vdupq_n_f32(0.0f); + + // process 4 samples at a time + for (; k <= kernelSize - 4; k += 4) { + float32x4_t vState = vld1q_f32(state + k); + float32x4_t vKernel = vld1q_f32(kernel + k); + + // fused multiply-add: vSum += vState * vKernel + vSum = vmlaq_f32(vSum, vState, vKernel); } -} + // horizontal reduction: Sum the 4 lanes of vSum into a single float + sum += vgetq_lane_f32(vSum, 0); + sum += vgetq_lane_f32(vSum, 1); + sum += vgetq_lane_f32(vSum, 2); + sum += vgetq_lane_f32(vSum, 3); +#endif + for (; k < kernelSize; ++k) { + sum += state[k] * kernel[k]; + } + + return sum; +} } // namespace audioapi::dsp diff --git a/packages/react-native-audio-api/common/cpp/audioapi/dsp/VectorMath.h b/packages/react-native-audio-api/common/cpp/audioapi/dsp/VectorMath.h index 0451ee125..fd11dfaa1 100644 --- a/packages/react-native-audio-api/common/cpp/audioapi/dsp/VectorMath.h +++ b/packages/react-native-audio-api/common/cpp/audioapi/dsp/VectorMath.h @@ -69,9 +69,6 @@ void multiply( // Finds the maximum magnitude of a float vector. float maximumMagnitude(const float *inputVector, size_t numberOfElementsToProcess); -void linearToDecibels( - const float *inputVector, - float *outputVector, - size_t numberOfElementsToProcess); +float computeConvolution(const float *state, const float *kernel, size_t kernelSize); } // namespace audioapi::dsp diff --git a/packages/react-native-audio-api/common/cpp/audioapi/utils/AudioArray.cpp b/packages/react-native-audio-api/common/cpp/audioapi/utils/AudioArray.cpp index 41713ff9e..69efaf367 100644 --- a/packages/react-native-audio-api/common/cpp/audioapi/utils/AudioArray.cpp +++ b/packages/react-native-audio-api/common/cpp/audioapi/utils/AudioArray.cpp @@ -5,10 +5,6 @@ #include #include -#if defined(__ARM_NEON) -#include -#endif - namespace audioapi { AudioArray::AudioArray(size_t size): size_(size) { @@ -79,10 +75,6 @@ void AudioArray::zero() noexcept { } void AudioArray::zero(size_t start, size_t length) noexcept { - if (data_ == nullptr || length <= 0) { - return; - } - memset(data_.get() + start, 0, length * sizeof(float)); } @@ -96,9 +88,9 @@ void AudioArray::sum( size_t destinationStart, size_t length, float gain) { - if (length == 0 || data_ == nullptr || source.data_ == nullptr) { - return; - } + if (size_ - destinationStart < length || source.size_ - sourceStart < length) { + throw std::out_of_range("Not enough data to sum two vectors."); + } // Using restrict to inform the compiler that the source and destination do not overlap float* __restrict dest = data_.get() + destinationStart; @@ -112,8 +104,8 @@ void AudioArray::multiply(const AudioArray &source) { } void AudioArray::multiply(const audioapi::AudioArray &source, size_t length) { - if (data_ == nullptr || source.data_ == nullptr) { - return; + if (size_ < length || source.size_ < length) { + throw std::out_of_range("Not enough data to perform vector multiplication."); } float* __restrict dest = data_.get(); @@ -131,17 +123,17 @@ void AudioArray::copy( size_t sourceStart, size_t destinationStart, size_t length) { - if (length == 0 || data_ == nullptr || source.data_ == nullptr) { - return; - } + if (source.size_ - sourceStart < length) { + throw std::out_of_range("Not enough data to copy from source."); + } copy(source.data_.get(), sourceStart, destinationStart, length); } void AudioArray::copyReverse(const audioapi::AudioArray &source, size_t sourceStart, size_t destinationStart, size_t length) { - if (length == 0 || data_ == nullptr || source.data_ == nullptr) { - return; + if (size_ - destinationStart < length || source.size_ - sourceStart < length) { + throw std::out_of_range("Not enough space to copy to destination or from source."); } auto dstView = this->subSpan(length, destinationStart); @@ -155,8 +147,8 @@ void AudioArray::copyReverse(const audioapi::AudioArray &source, size_t sourceSt void AudioArray::copy(const float *source, size_t sourceStart, size_t destinationStart, size_t length) { - if (length == 0 || data_ == nullptr || source == nullptr) { - return; + if (size_ - destinationStart < length) { + throw std::out_of_range("Not enough space to copy to destination."); } memcpy(data_.get() + destinationStart, source + sourceStart, length * sizeof(float)); @@ -164,15 +156,15 @@ void AudioArray::copy(const float *source, size_t sourceStart, size_t destinatio void AudioArray::copyTo(float *destination, size_t sourceStart, size_t destinationStart, size_t length) const { - if (length == 0 || data_ == nullptr || destination == nullptr) { - return; + if (size_ - sourceStart < length) { + throw std::out_of_range("Not enough data to copy from source."); } memcpy(destination + destinationStart, data_.get() + sourceStart, length * sizeof(float)); } void AudioArray::reverse() { - if (data_ == nullptr && size_ > 1) { + if (size_ > 1) { return; } @@ -190,58 +182,19 @@ void AudioArray::normalize() { } void AudioArray::scale(float value) { - if (data_ == nullptr) { - return; - } - dsp::multiplyByScalar(data_.get(), value, data_.get(), size_); } float AudioArray::getMaxAbsValue() const { - if (data_ == nullptr) { - return 0.0f; - } - return dsp::maximumMagnitude(data_.get(), size_); } float AudioArray::computeConvolution(const audioapi::AudioArray &kernel, size_t startIndex) const { - const auto kernelSize = kernel.size_; - - if (startIndex + kernelSize > size_ || !data_ || !kernel.data_) { - return 0.0f; - } - - const auto stateStart = data_.get() + startIndex; - const auto kernelStart = kernel.data_.get(); - - float sum = 0.0f; - size_t k = 0; - -#ifdef __ARM_NEON - float32x4_t vSum = vdupq_n_f32(0.0f); - - // process 4 samples at a time - for (; k <= kernelSize - 4; k += 4) { - float32x4_t vState = vld1q_f32(stateStart + k); - float32x4_t vKernel = vld1q_f32(kernelStart + k); - - // fused multiply-add: vSum += vState * vKernel - vSum = vmlaq_f32(vSum, vState, vKernel); - } - - // horizontal reduction: Sum the 4 lanes of vSum into a single float - sum += vgetq_lane_f32(vSum, 0); - sum += vgetq_lane_f32(vSum, 1); - sum += vgetq_lane_f32(vSum, 2); - sum += vgetq_lane_f32(vSum, 3); -#endif - - for (; k < kernelSize; ++k) { - sum += stateStart[k] * kernelStart[k]; + if (kernel.size_ > size_ - startIndex) { + throw std::out_of_range("Kernal size exceeds available data for convolution."); } - return sum; + return dsp::computeConvolution(data_.get() + startIndex, kernel.data_.get(), kernel.size_); } } // namespace audioapi diff --git a/packages/react-native-audio-api/common/cpp/audioapi/utils/CircularOverflowableAudioArray.h b/packages/react-native-audio-api/common/cpp/audioapi/utils/CircularOverflowableAudioArray.h index b4889857b..588c72d4e 100644 --- a/packages/react-native-audio-api/common/cpp/audioapi/utils/CircularOverflowableAudioArray.h +++ b/packages/react-native-audio-api/common/cpp/audioapi/utils/CircularOverflowableAudioArray.h @@ -21,12 +21,12 @@ class CircularOverflowableAudioArray : public AudioArray { /// @brief Writes data to the circular buffer. /// @note Might wait for read operation to finish if it is in progress. It ignores writes that exceed the buffer size. - /// @param data Pointer to the input buffer. + /// @param data Reference to input AudioArray. /// @param size Number of frames to write. void write(const AudioArray &data, size_t size); /// @brief Reads data from the circular buffer. - /// @param output Pointer to the output buffer. + /// @param output Reference to output AudioArray. /// @param size Number of frames to read. /// @return The number of frames actually read. size_t read(AudioArray &data, size_t size) const; diff --git a/packages/react-native-audio-api/ios/audioapi/ios/core/IOSAudioRecorder.h b/packages/react-native-audio-api/ios/audioapi/ios/core/IOSAudioRecorder.h index fc7174bb9..ed356c18e 100644 --- a/packages/react-native-audio-api/ios/audioapi/ios/core/IOSAudioRecorder.h +++ b/packages/react-native-audio-api/ios/audioapi/ios/core/IOSAudioRecorder.h @@ -10,8 +10,8 @@ typedef struct objc_object NativeAudioRecorder; #endif // __OBJC__ #include -#include #include +#include #include diff --git a/packages/react-native-audio-api/ios/audioapi/ios/core/IOSAudioRecorder.mm b/packages/react-native-audio-api/ios/audioapi/ios/core/IOSAudioRecorder.mm index ad7227a5c..e77ceb39c 100644 --- a/packages/react-native-audio-api/ios/audioapi/ios/core/IOSAudioRecorder.mm +++ b/packages/react-native-audio-api/ios/audioapi/ios/core/IOSAudioRecorder.mm @@ -52,12 +52,8 @@ if (auto lock = Locker::tryLock(adapterNodeMutex_)) { for (size_t channel = 0; channel < adapterNode_->channelCount_; ++channel) { float *data = (float *)inputBuffer->mBuffers[channel].mData; - auto channelData = deinterleavingArray_->span(); - - for (int frame = 0; frame < numFrames; ++frame) { - channelData[frame] = data[frame]; - } - + + deinterleavingArray_->copy(data, 0, 0, numFrames); adapterNode_->buff_[channel]->write(*deinterleavingArray_, numFrames); } } diff --git a/packages/react-native-audio-api/ios/audioapi/ios/core/utils/IOSRecorderCallback.mm b/packages/react-native-audio-api/ios/audioapi/ios/core/utils/IOSRecorderCallback.mm index f0d3393a4..b4ef82b2c 100644 --- a/packages/react-native-audio-api/ios/audioapi/ios/core/utils/IOSRecorderCallback.mm +++ b/packages/react-native-audio-api/ios/audioapi/ios/core/utils/IOSRecorderCallback.mm @@ -71,7 +71,7 @@ converterOutputBufferSize_ = std::max( (double)maxInputBufferLength, sampleRate_ / bufferFormat.sampleRate * maxInputBufferLength); - + deinterleavingArray_ = std::make_shared(converterOutputBufferSize_); callbackFormat_ = [[AVAudioFormat alloc] initWithCommonFormat:AVAudioPCMFormatFloat32 @@ -152,12 +152,8 @@ // Directly write to circular buffer for (int i = 0; i < channelCount_; ++i) { auto *inputChannel = static_cast(inputBuffer->mBuffers[i].mData); - auto channelData = deinterleavingArray_->span(); - for (int frame = 0; frame < numFrames; ++frame) { - channelData[frame] = inputChannel[frame]; - } - + deinterleavingArray_->copy(inputChannel, 0, 0, numFrames); circularBus_[i]->push_back(*deinterleavingArray_, numFrames); } @@ -203,14 +199,9 @@ } for (int i = 0; i < channelCount_; ++i) { - auto *inputChannel = - static_cast(converterOutputBuffer_.audioBufferList->mBuffers[i].mData); - auto channelData = deinterleavingArray_->span(); + auto *data = static_cast(converterOutputBuffer_.audioBufferList->mBuffers[i].mData); - for (int frame = 0; frame < numFrames; ++frame) { - channelData[frame] = inputChannel[frame]; - } - + deinterleavingArray_->copy(data, 0, 0, outputFrameCount); circularBus_[i]->push_back(*deinterleavingArray_, outputFrameCount); } From 58471e4b7a42142f9c72679de847e6ce9a469150 Mon Sep 17 00:00:00 2001 From: maciejmakowski2003 Date: Wed, 4 Feb 2026 08:38:32 +0100 Subject: [PATCH 14/30] fix: nitpick --- .../common/cpp/audioapi/utils/AudioArray.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/react-native-audio-api/common/cpp/audioapi/utils/AudioArray.cpp b/packages/react-native-audio-api/common/cpp/audioapi/utils/AudioArray.cpp index 69efaf367..04b3a17bb 100644 --- a/packages/react-native-audio-api/common/cpp/audioapi/utils/AudioArray.cpp +++ b/packages/react-native-audio-api/common/cpp/audioapi/utils/AudioArray.cpp @@ -164,7 +164,7 @@ void AudioArray::copyTo(float *destination, size_t sourceStart, size_t destinati } void AudioArray::reverse() { - if (size_ > 1) { + if (size_ <= 1) { return; } From 1b51ce674a5601f76169896ada2db7f3f7e3a7c0 Mon Sep 17 00:00:00 2001 From: maciejmakowski2003 Date: Wed, 4 Feb 2026 12:37:42 +0100 Subject: [PATCH 15/30] refactor: added copyWithin - memmove to audio array --- .../common/cpp/audioapi/utils/AudioArray.cpp | 8 ++++ .../common/cpp/audioapi/utils/AudioArray.h | 39 ++++++++++++++++--- 2 files changed, 42 insertions(+), 5 deletions(-) diff --git a/packages/react-native-audio-api/common/cpp/audioapi/utils/AudioArray.cpp b/packages/react-native-audio-api/common/cpp/audioapi/utils/AudioArray.cpp index 04b3a17bb..8c938e311 100644 --- a/packages/react-native-audio-api/common/cpp/audioapi/utils/AudioArray.cpp +++ b/packages/react-native-audio-api/common/cpp/audioapi/utils/AudioArray.cpp @@ -163,6 +163,14 @@ void AudioArray::copyTo(float *destination, size_t sourceStart, size_t destinati memcpy(destination + destinationStart, data_.get() + sourceStart, length * sizeof(float)); } +void AudioArray::copyWithin(size_t sourceStart, size_t destinationStart, size_t length) { + if (size_ - sourceStart < length || size_ - destinationStart < length) { + throw std::out_of_range("Not enough space for moving data or data to move."); + } + + memmove(data_.get() + destinationStart, data_.get() + sourceStart, length); +} + void AudioArray::reverse() { if (size_ <= 1) { return; diff --git a/packages/react-native-audio-api/common/cpp/audioapi/utils/AudioArray.h b/packages/react-native-audio-api/common/cpp/audioapi/utils/AudioArray.h index fe7b26794..4c324de87 100644 --- a/packages/react-native-audio-api/common/cpp/audioapi/utils/AudioArray.h +++ b/packages/react-native-audio-api/common/cpp/audioapi/utils/AudioArray.h @@ -75,7 +75,7 @@ class AudioArray { /// @brief Sums the source AudioArray into this AudioArray with an optional gain. /// @param source The source AudioArray to sum from. /// @param gain The gain to apply to the source before summing. Default is 1.0f. - /// @note Assumes that source and this AudioArray are not the same. + /// @note Assumes that source and this are located in two distinct, non-overlapping memory locations. void sum(const AudioArray &source, float gain = 1.0f); /// @brief Sums the source AudioArray into this AudioArray with an optional gain. @@ -84,7 +84,7 @@ class AudioArray { /// @param destinationStart The starting index in this AudioArray. /// @param length The number of samples to sum. /// @param gain The gain to apply to the source before summing. Default is 1.0f. - /// @note Assumes that source and this AudioArray are not the same. + /// @note Assumes that source and this are located in two distinct, non-overlapping memory locations. void sum( const AudioArray &source, size_t sourceStart, @@ -94,16 +94,26 @@ class AudioArray { /// @brief Multiplies this AudioArray by the source AudioArray element-wise. /// @param source The source AudioArray to multiply with. - /// @note Assumes that source and this AudioArray are not the same. + /// @note Assumes that source and this are located in two distinct, non-overlapping memory locations. void multiply(const AudioArray &source); /// @brief Multiplies this AudioArray by the source AudioArray element-wise. /// @param source The source AudioArray to multiply with. /// @param length The number of samples to multiply. - /// @note Assumes that source and this AudioArray are not the same. + /// @note Assumes that source and this are located in two distinct, non-overlapping memory locations. void multiply(const AudioArray &source, size_t length); + /// @brief Copies source AudioArray into this AudioArray + /// @param source The source AudioArray to copy. + /// @note Assumes that source and this are located in two distinct, non-overlapping memory locations. void copy(const AudioArray &source); + + /// @brief Copies source AudioArray into this AudioArray + /// @param source The source AudioArray to copy. + /// @param sourceStart The starting index in the source AudioArray. + /// @param destinationStart The starting index in this AudioArray. + /// @param length The number of samples to copy. + /// @note Assumes that source and this are located in two distinct, non-overlapping memory locations. void copy(const AudioArray &source, size_t sourceStart, size_t destinationStart, size_t length); /// @brief Copies data from the source AudioArray in reverse order into this AudioArray. @@ -111,13 +121,32 @@ class AudioArray { /// @param sourceStart The starting index in the source AudioArray. /// @param destinationStart The starting index in this AudioArray. /// @param length The number of samples to copy. - /// @note Assumes that source and this AudioArray are not the same. + /// @note Assumes that source and this are located in two distinct, non-overlapping memory locations. void copyReverse(const AudioArray &source, size_t sourceStart, size_t destinationStart, size_t length); + /// @brief Copies data from a raw float pointer into this AudioArray. + /// @param source The source float pointer to copy from. + /// @param sourceStart The starting index in the source float pointer. + /// @param destinationStart The starting index in this AudioArray. + /// @param length The number of samples to copy. + /// @note Assumes that source and this are located in two distinct, non-overlapping memory locations. void copy(const float *source, size_t sourceStart, size_t destinationStart, size_t length); + + /// @brief Copies data to a raw float pointer from this AudioArray. + /// @param destination The destination float pointer to copy to. + /// @param sourceStart The starting index in the this AudioArray. + /// @param destinationStart The starting index in the destination float pointer. + /// @param length The number of samples to copy. + /// @note Assumes that destination and this are located in two distinct, non-overlapping memory locations. void copyTo(float *destination, size_t sourceStart, size_t destinationStart, size_t length) const; + /// @brief Moves data inside this AudioArray. + /// @param sourceStart The starting index in the source float pointer. + /// @param destinationStart The starting index of memory. + /// @param length The number of samples to copy. + void copyWithin(size_t sourceStart, size_t destinationStart, size_t length); + void reverse(); void normalize(); void scale(float value); From 8127fa219a00b16b22a8b22fec8898f6ae5705dc Mon Sep 17 00:00:00 2001 From: maciejmakowski2003 Date: Wed, 4 Feb 2026 13:03:36 +0100 Subject: [PATCH 16/30] fix: memmove --- .../audioapi/core/effects/ConvolverNode.cpp | 5 +- .../common/cpp/audioapi/dsp/Convolver.cpp | 2 +- .../common/cpp/audioapi/dsp/Resampler.cpp | 4 +- .../common/cpp/audioapi/utils/AudioArray.cpp | 160 ++++++++++-------- .../common/cpp/audioapi/utils/AudioArray.h | 6 +- 5 files changed, 94 insertions(+), 83 deletions(-) diff --git a/packages/react-native-audio-api/common/cpp/audioapi/core/effects/ConvolverNode.cpp b/packages/react-native-audio-api/common/cpp/audioapi/core/effects/ConvolverNode.cpp index f107e8041..2a026ccb5 100644 --- a/packages/react-native-audio-api/common/cpp/audioapi/core/effects/ConvolverNode.cpp +++ b/packages/react-native-audio-api/common/cpp/audioapi/core/effects/ConvolverNode.cpp @@ -121,10 +121,11 @@ std::shared_ptr ConvolverNode::processNode( audioBus_->copy(*internalBuffer_, 0, 0, framesToProcess); int remainingFrames = internalBufferIndex_ - framesToProcess; if (remainingFrames > 0) { - for (int i = 0; i < internalBuffer_->getNumberOfChannels(); ++i) { - internalBuffer_->copy(*internalBuffer_, framesToProcess, 0, remainingFrames); + for (int ch = 0; ch < internalBuffer_->getNumberOfChannels(); ++ch) { + internalBuffer_->getChannel(ch)->copyWithin(framesToProcess, 0, remainingFrames); } } + internalBufferIndex_ -= framesToProcess; for (int i = 0; i < audioBus_->getNumberOfChannels(); ++i) { diff --git a/packages/react-native-audio-api/common/cpp/audioapi/dsp/Convolver.cpp b/packages/react-native-audio-api/common/cpp/audioapi/dsp/Convolver.cpp index 29a619251..ca73e4d5a 100644 --- a/packages/react-native-audio-api/common/cpp/audioapi/dsp/Convolver.cpp +++ b/packages/react-native-audio-api/common/cpp/audioapi/dsp/Convolver.cpp @@ -172,7 +172,7 @@ void Convolver::process(const AudioArray &input, AudioArray &output) { // The input buffer acts as a 2B-point sliding window of the input signal. // With each new input block, the right half of the input buffer is shifted // to the left and the new block is stored in the right half. - _inputBuffer->copy(*_inputBuffer, _blockSize, 0, _blockSize); + _inputBuffer->copyWithin(_blockSize, 0, _blockSize); _inputBuffer->copy(input, 0, _blockSize, _blockSize); // All contents (DFT spectra) in the FDL are shifted up by one slot. diff --git a/packages/react-native-audio-api/common/cpp/audioapi/dsp/Resampler.cpp b/packages/react-native-audio-api/common/cpp/audioapi/dsp/Resampler.cpp index 80a262f18..278f51474 100644 --- a/packages/react-native-audio-api/common/cpp/audioapi/dsp/Resampler.cpp +++ b/packages/react-native-audio-api/common/cpp/audioapi/dsp/Resampler.cpp @@ -107,7 +107,7 @@ int UpSampler::process( } // move new data to history [ NEW DATA | EMPTY ] - stateBuffer_->copy(*stateBuffer_, framesToProcess, 0, kernelSize_); + stateBuffer_->copyWithin(framesToProcess, 0, kernelSize_); return framesToProcess * 2; } @@ -151,7 +151,7 @@ int DownSampler::process( } // move new data to history [ NEW DATA | EMPTY ] - stateBuffer_->copy(*stateBuffer_, framesToProcess, 0, kernelSize_); + stateBuffer_->copyWithin(framesToProcess, 0, kernelSize_); return outputCount; } diff --git a/packages/react-native-audio-api/common/cpp/audioapi/utils/AudioArray.cpp b/packages/react-native-audio-api/common/cpp/audioapi/utils/AudioArray.cpp index 8c938e311..ac7bc1c76 100644 --- a/packages/react-native-audio-api/common/cpp/audioapi/utils/AudioArray.cpp +++ b/packages/react-native-audio-api/common/cpp/audioapi/utils/AudioArray.cpp @@ -2,59 +2,60 @@ #include #include -#include #include +#include namespace audioapi { -AudioArray::AudioArray(size_t size): size_(size) { - if (size_ > 0) { - data_ = std::make_unique(size_); - zero(); - } +AudioArray::AudioArray(size_t size) : size_(size) { + if (size_ > 0) { + data_ = std::make_unique(size_); + zero(); + } } AudioArray::AudioArray(const float *data, size_t size) : size_(size) { - if (size_ > 0) { - data_ = std::make_unique(size_); - copy(data, 0, 0, size_); - } + if (size_ > 0) { + data_ = std::make_unique(size_); + copy(data, 0, 0, size_); + } } AudioArray::AudioArray(const AudioArray &other) : size_(other.size_) { - if (size_ > 0 && other.data_) { - data_ = std::make_unique(size_); - std::memcpy(data_.get(), other.data_.get(), size_ * sizeof(float)); - } + if (size_ > 0 && other.data_) { + data_ = std::make_unique(size_); + std::memcpy(data_.get(), other.data_.get(), size_ * sizeof(float)); + } } -AudioArray::AudioArray(audioapi::AudioArray &&other) noexcept : data_(std::move(other.data_)), size_(other.size_) { +AudioArray::AudioArray(audioapi::AudioArray &&other) noexcept + : data_(std::move(other.data_)), size_(other.size_) { other.size_ = 0; } AudioArray &AudioArray::operator=(const audioapi::AudioArray &other) { - if (this != &other) { - if (size_ != other.size_) { - size_ = other.size_; - data_ = (size_ > 0) ? std::make_unique(size_) : nullptr; - } + if (this != &other) { + if (size_ != other.size_) { + size_ = other.size_; + data_ = (size_ > 0) ? std::make_unique(size_) : nullptr; + } - if (size_ > 0 && data_) { + if (size_ > 0 && data_) { std::memcpy(data_.get(), other.data_.get(), size_ * sizeof(float)); - } } + } - return *this; + return *this; } AudioArray &AudioArray::operator=(audioapi::AudioArray &&other) noexcept { - if (this != &other) { - data_ = std::move(other.data_); - size_ = other.size_; - other.size_ = 0; - } + if (this != &other) { + data_ = std::move(other.data_); + size_ = other.size_; + other.size_ = 0; + } - return *this; + return *this; } void AudioArray::resize(size_t size) { @@ -88,13 +89,13 @@ void AudioArray::sum( size_t destinationStart, size_t length, float gain) { - if (size_ - destinationStart < length || source.size_ - sourceStart < length) { - throw std::out_of_range("Not enough data to sum two vectors."); - } + if (size_ - destinationStart < length || source.size_ - sourceStart < length) { + throw std::out_of_range("Not enough data to sum two vectors."); + } // Using restrict to inform the compiler that the source and destination do not overlap - float* __restrict dest = data_.get() + destinationStart; - const float* __restrict src = source.data_.get() + sourceStart; + float *__restrict dest = data_.get() + destinationStart; + const float *__restrict src = source.data_.get() + sourceStart; dsp::multiplyByScalarThenAddToOutput(src, gain, dest, length); } @@ -108,8 +109,8 @@ void AudioArray::multiply(const audioapi::AudioArray &source, size_t length) { throw std::out_of_range("Not enough data to perform vector multiplication."); } - float* __restrict dest = data_.get(); - const float* __restrict src = source.data_.get(); + float *__restrict dest = data_.get(); + const float *__restrict src = source.data_.get(); dsp::multiply(src, dest, dest, length); } @@ -130,79 +131,88 @@ void AudioArray::copy( copy(source.data_.get(), sourceStart, destinationStart, length); } -void AudioArray::copyReverse(const audioapi::AudioArray &source, size_t sourceStart, - size_t destinationStart, size_t length) { - if (size_ - destinationStart < length || source.size_ - sourceStart < length) { - throw std::out_of_range("Not enough space to copy to destination or from source."); - } +void AudioArray::copyReverse( + const audioapi::AudioArray &source, + size_t sourceStart, + size_t destinationStart, + size_t length) { + if (size_ - destinationStart < length || source.size_ - sourceStart < length) { + throw std::out_of_range("Not enough space to copy to destination or from source."); + } - auto dstView = this->subSpan(length, destinationStart); - auto srcView = source.span(); - const float* __restrict srcPtr = &srcView[sourceStart]; + auto dstView = this->subSpan(length, destinationStart); + auto srcView = source.span(); + const float *__restrict srcPtr = &srcView[sourceStart]; - for (size_t i = 0; i < length; ++i) { - dstView[i] = srcPtr[-static_cast(i)]; - } + for (size_t i = 0; i < length; ++i) { + dstView[i] = srcPtr[-static_cast(i)]; + } } -void AudioArray::copy(const float *source, size_t sourceStart, size_t destinationStart, - size_t length) { - if (size_ - destinationStart < length) { - throw std::out_of_range("Not enough space to copy to destination."); - } +void AudioArray::copy( + const float *source, + size_t sourceStart, + size_t destinationStart, + size_t length) { + if (size_ - destinationStart < length) { + throw std::out_of_range("Not enough space to copy to destination."); + } - memcpy(data_.get() + destinationStart, source + sourceStart, length * sizeof(float)); + memcpy(data_.get() + destinationStart, source + sourceStart, length * sizeof(float)); } -void AudioArray::copyTo(float *destination, size_t sourceStart, size_t destinationStart, - size_t length) const { - if (size_ - sourceStart < length) { - throw std::out_of_range("Not enough data to copy from source."); - } +void AudioArray::copyTo( + float *destination, + size_t sourceStart, + size_t destinationStart, + size_t length) const { + if (size_ - sourceStart < length) { + throw std::out_of_range("Not enough data to copy from source."); + } - memcpy(destination + destinationStart, data_.get() + sourceStart, length * sizeof(float)); + memcpy(destination + destinationStart, data_.get() + sourceStart, length * sizeof(float)); } void AudioArray::copyWithin(size_t sourceStart, size_t destinationStart, size_t length) { - if (size_ - sourceStart < length || size_ - destinationStart < length) { - throw std::out_of_range("Not enough space for moving data or data to move."); - } + if (size_ - sourceStart < length || size_ - destinationStart < length) { + throw std::out_of_range("Not enough space for moving data or data to move."); + } - memmove(data_.get() + destinationStart, data_.get() + sourceStart, length); + memmove(data_.get() + destinationStart, data_.get() + sourceStart, length * sizeof(float)); } void AudioArray::reverse() { if (size_ <= 1) { - return; + return; } std::reverse(begin(), end()); } void AudioArray::normalize() { - float maxAbsValue = getMaxAbsValue(); + float maxAbsValue = getMaxAbsValue(); - if (maxAbsValue == 0.0f || maxAbsValue == 1.0f) { - return; - } + if (maxAbsValue == 0.0f || maxAbsValue == 1.0f) { + return; + } - dsp::multiplyByScalar(data_.get(), 1.0f / maxAbsValue, data_.get(), size_); + dsp::multiplyByScalar(data_.get(), 1.0f / maxAbsValue, data_.get(), size_); } void AudioArray::scale(float value) { - dsp::multiplyByScalar(data_.get(), value, data_.get(), size_); + dsp::multiplyByScalar(data_.get(), value, data_.get(), size_); } float AudioArray::getMaxAbsValue() const { - return dsp::maximumMagnitude(data_.get(), size_); + return dsp::maximumMagnitude(data_.get(), size_); } float AudioArray::computeConvolution(const audioapi::AudioArray &kernel, size_t startIndex) const { - if (kernel.size_ > size_ - startIndex) { - throw std::out_of_range("Kernal size exceeds available data for convolution."); - } + if (kernel.size_ > size_ - startIndex) { + throw std::out_of_range("Kernal size exceeds available data for convolution."); + } - return dsp::computeConvolution(data_.get() + startIndex, kernel.data_.get(), kernel.size_); + return dsp::computeConvolution(data_.get() + startIndex, kernel.data_.get(), kernel.size_); } } // namespace audioapi diff --git a/packages/react-native-audio-api/common/cpp/audioapi/utils/AudioArray.h b/packages/react-native-audio-api/common/cpp/audioapi/utils/AudioArray.h index 4c324de87..77fc4cba3 100644 --- a/packages/react-native-audio-api/common/cpp/audioapi/utils/AudioArray.h +++ b/packages/react-native-audio-api/common/cpp/audioapi/utils/AudioArray.h @@ -141,9 +141,9 @@ class AudioArray { /// @note Assumes that destination and this are located in two distinct, non-overlapping memory locations. void copyTo(float *destination, size_t sourceStart, size_t destinationStart, size_t length) const; - /// @brief Moves data inside this AudioArray. - /// @param sourceStart The starting index in the source float pointer. - /// @param destinationStart The starting index of memory. + /// @brief Copies a sub-section of the array to another location within itself. + /// @param sourceStart The index where the data to be copied begins. + /// @param destinationStart The index where the data should be placed. /// @param length The number of samples to copy. void copyWithin(size_t sourceStart, size_t destinationStart, size_t length); From 2b01ac345608c40d7132ae9cb37ace3000b0d285 Mon Sep 17 00:00:00 2001 From: maciejmakowski2003 Date: Wed, 4 Feb 2026 13:53:20 +0100 Subject: [PATCH 17/30] chore: updated custom processor template --- .../docs/guides/create-your-own-effect.mdx | 28 ++++++++----------- .../basic/shared/MyProcessorNode.cpp | 5 ++-- .../templates/basic/shared/MyProcessorNode.h | 4 +-- 3 files changed, 17 insertions(+), 20 deletions(-) diff --git a/packages/audiodocs/docs/guides/create-your-own-effect.mdx b/packages/audiodocs/docs/guides/create-your-own-effect.mdx index 85baaddf5..de1e07882 100644 --- a/packages/audiodocs/docs/guides/create-your-own-effect.mdx +++ b/packages/audiodocs/docs/guides/create-your-own-effect.mdx @@ -45,21 +45,17 @@ For the sake of a simplicity, we will use value as a raw `double` type, not wrap #include namespace audioapi { - class AudioBuffer; +class AudioBuffer; - class MyProcessorNode : public AudioNode { - public: - explicit MyProcessorNode(BaseAudioContext *context); - - protected: - void processNode(const std::shared_ptr &bus, - int framesToProcess) override; +class MyProcessorNode : public AudioNode { +public: + explicit MyProcessorNode(const std::shared_ptr &context, ); - // highlight-start - private: - double gain; // value responsible for gain value - // highlight-end - }; +protected: + std::shared_ptr + processNode(const std::shared_ptr &buffer, + int framesToProcess) override; +}; } // namespace audioapi ``` @@ -73,16 +69,16 @@ namespace audioapi { #include namespace audioapi { - MyProcessorNode::MyProcessorNode(BaseAudioContext *context) + MyProcessorNode::MyProcessorNode(const std::shared_ptr &context) //highlight-next-line : AudioNode(context), gain(0.5) { isInitialized_ = true; } - void MyProcessorNode::processNode(const std::shared_ptr &bus, + void MyProcessorNode::processNode(const std::shared_ptr &buffer, int framesToProcess) { // highlight-start - for (int channel = 0; channel < bus->getNumberOfChannels(); ++channel) { + for (int channel = 0; channel < buffer->getNumberOfChannels(); ++channel) { auto *audioArray = bus->getChannel(channel); for (size_t i = 0; i < framesToProcess; ++i) { // Apply gain to each sample in the audio array diff --git a/packages/custom-node-generator/templates/basic/shared/MyProcessorNode.cpp b/packages/custom-node-generator/templates/basic/shared/MyProcessorNode.cpp index b6c9c60cd..b1ffb9581 100644 --- a/packages/custom-node-generator/templates/basic/shared/MyProcessorNode.cpp +++ b/packages/custom-node-generator/templates/basic/shared/MyProcessorNode.cpp @@ -2,13 +2,14 @@ #include namespace audioapi { -MyProcessorNode::MyProcessorNode(BaseAudioContext *context) +MyProcessorNode::MyProcessorNode( + const std::shared_ptr &context, ) : AudioNode(context) { isInitialized_ = true; } std::shared_ptr -MyProcessorNode::processNode(const std::shared_ptr &bus, +MyProcessorNode::processNode(const std::shared_ptr &buffer, int framesToProcess) { // put your processing logic here } diff --git a/packages/custom-node-generator/templates/basic/shared/MyProcessorNode.h b/packages/custom-node-generator/templates/basic/shared/MyProcessorNode.h index 58cc43cc6..250321092 100644 --- a/packages/custom-node-generator/templates/basic/shared/MyProcessorNode.h +++ b/packages/custom-node-generator/templates/basic/shared/MyProcessorNode.h @@ -6,11 +6,11 @@ class AudioBuffer; class MyProcessorNode : public AudioNode { public: - explicit MyProcessorNode(BaseAudioContext *context); + explicit MyProcessorNode(const std::shared_ptr &context, ); protected: std::shared_ptr - processNode(const std::shared_ptr &bus, + processNode(const std::shared_ptr &buffer, int framesToProcess) override; }; } // namespace audioapi From dd2bf6ba4ae59cadba8ce0104e04678c6ef0a6bb Mon Sep 17 00:00:00 2001 From: maciejmakowski2003 Date: Wed, 4 Feb 2026 20:00:51 +0100 Subject: [PATCH 18/30] refactor: optimized interleaveTo function --- .../cpp/audioapi/android/core/AudioPlayer.cpp | 16 ++-- .../cpp/audioapi/android/core/AudioPlayer.h | 2 +- .../common/cpp/audioapi/dsp/VectorMath.cpp | 75 ++++++++++++++++++- .../common/cpp/audioapi/dsp/VectorMath.h | 6 ++ .../common/cpp/audioapi/utils/AudioBuffer.cpp | 33 ++++++++ .../common/cpp/audioapi/utils/AudioBuffer.h | 9 +++ 6 files changed, 128 insertions(+), 13 deletions(-) diff --git a/packages/react-native-audio-api/android/src/main/cpp/audioapi/android/core/AudioPlayer.cpp b/packages/react-native-audio-api/android/src/main/cpp/audioapi/android/core/AudioPlayer.cpp index 215f7f238..6e3bd1692 100644 --- a/packages/react-native-audio-api/android/src/main/cpp/audioapi/android/core/AudioPlayer.cpp +++ b/packages/react-native-audio-api/android/src/main/cpp/audioapi/android/core/AudioPlayer.cpp @@ -42,7 +42,7 @@ bool AudioPlayer::openAudioStream() { return false; } - audioBus_ = std::make_shared(RENDER_QUANTUM_SIZE, channelCount_, sampleRate_); + buffer_ = std::make_shared(RENDER_QUANTUM_SIZE, channelCount_, sampleRate_); return true; } @@ -108,21 +108,17 @@ AudioPlayer::onAudioReady(AudioStream *oboeStream, void *audioData, int32_t numF int processedFrames = 0; while (processedFrames < numFrames) { - int framesToProcess = std::min(numFrames - processedFrames, RENDER_QUANTUM_SIZE); + auto framesToProcess = std::min(numFrames - processedFrames, RENDER_QUANTUM_SIZE); if (isRunning_.load(std::memory_order_acquire)) { - renderAudio_(audioBus_, framesToProcess); + renderAudio_(buffer_, framesToProcess); } else { - audioBus_->zero(); + buffer_->zero(); } - for (int i = 0; i < framesToProcess; i++) { - for (int channel = 0; channel < channelCount_; channel++) { - buffer[(processedFrames + i) * channelCount_ + channel] = - (*audioBus_->getChannel(channel))[i]; - } - } + float *destination = buffer + (processedFrames * channelCount_); + buffer_->interleaveTo(destination, framesToProcess); processedFrames += framesToProcess; } diff --git a/packages/react-native-audio-api/android/src/main/cpp/audioapi/android/core/AudioPlayer.h b/packages/react-native-audio-api/android/src/main/cpp/audioapi/android/core/AudioPlayer.h index 7fcc1796c..c453382a5 100644 --- a/packages/react-native-audio-api/android/src/main/cpp/audioapi/android/core/AudioPlayer.h +++ b/packages/react-native-audio-api/android/src/main/cpp/audioapi/android/core/AudioPlayer.h @@ -42,7 +42,7 @@ class AudioPlayer : public AudioStreamDataCallback, AudioStreamErrorCallback { private: std::function, int)> renderAudio_; std::shared_ptr mStream_; - std::shared_ptr audioBus_; + std::shared_ptr buffer_; bool isInitialized_ = false; float sampleRate_; int channelCount_; diff --git a/packages/react-native-audio-api/common/cpp/audioapi/dsp/VectorMath.cpp b/packages/react-native-audio-api/common/cpp/audioapi/dsp/VectorMath.cpp index 4cadc42be..18bdeab4c 100644 --- a/packages/react-native-audio-api/common/cpp/audioapi/dsp/VectorMath.cpp +++ b/packages/react-native-audio-api/common/cpp/audioapi/dsp/VectorMath.cpp @@ -97,6 +97,22 @@ void multiplyByScalarThenAddToOutput( vDSP_vsma(inputVector, 1, &scalar, outputVector, 1, outputVector, 1, numberOfElementsToProcess); } +float computeConvolution(const float *state, const float *kernel, size_t kernelSize) { + float result = 0.0f; + vDSP_conv(state, 1, kernel, 1, &result, 1, 1, kernelSize); + return result; +} + +void interleaveStereo( + const float* __restrict inputLeft, + const float* __restrict inputRight, + float* __restrict outputInterleaved, + size_t numberOfFrames) { + float zero = 0.0f; + vDSP_vsadd(inputLeft, 1, &zero, outputInterleaved, 2, numberOfFrames); + vDSP_vsadd(inputRight, 1, &zero, outputInterleaved + 1, 2, numberOfFrames); +} + #else #if defined(HAVE_X86_SSE2) @@ -654,8 +670,6 @@ void multiplyByScalarThenAddToOutput( } } -#endif - float computeConvolution(const float *state, const float *kernel, size_t kernelSize) { float sum = 0.0f; int k = 0; @@ -684,4 +698,61 @@ float computeConvolution(const float *state, const float *kernel, size_t kernelS return sum; } + +void interleaveStereo( + const float * __restrict inputLeft, + const float * __restrict inputRight, + float * __restrict outputInterleaved, + size_t numberOfFrames) { + + size_t n = numberOfFrames; + +#if defined(HAVE_ARM_NEON_INTRINSICS) + // process 4 frames (8 samples) at a time + size_t group = n / 4; + while (group--) { + // load contiguous planar data + float32x4_t vL = vld1q_f32(inputLeft); + float32x4_t vR = vld1q_f32(inputRight); + + // vst2q_f32 takes two registers and interleaves them during the store: + float32x4x2_t vOut = { vL, vR }; + vst2q_f32(outputInterleaved, vOut); + + inputLeft += 4; + inputRight += 4; + outputInterleaved += 8; + } + n %= 4; +#elif defined(HAVE_X86_SSE2) + // process 4 frames (8 samples) at a time + size_t group = n / 4; + while (group--) { + __m128 vL = _mm_loadu_ps(inputLeft); + __m128 vR = _mm_loadu_ps(inputRight); + + // unpack low: Interleaves first two elements of each register + __m128 vLow = _mm_unpacklo_ps(vL, vR); + + // unpack high: Interleaves last two elements of each register + __m128 vHigh = _mm_unpackhi_ps(vL, vR); + + _mm_storeu_ps(outputInterleaved, vLow); + _mm_storeu_ps(outputInterleaved + 4, vHigh); + + inputLeft += 4; + inputRight += 4; + outputInterleaved += 8; + } + n %= 4; +#endif + + while (n--) { + *outputInterleaved++ = *inputLeft++; + *outputInterleaved++ = *inputRight++; + } +} + +#endif + } // namespace audioapi::dsp diff --git a/packages/react-native-audio-api/common/cpp/audioapi/dsp/VectorMath.h b/packages/react-native-audio-api/common/cpp/audioapi/dsp/VectorMath.h index fd11dfaa1..c66f46f9b 100644 --- a/packages/react-native-audio-api/common/cpp/audioapi/dsp/VectorMath.h +++ b/packages/react-native-audio-api/common/cpp/audioapi/dsp/VectorMath.h @@ -71,4 +71,10 @@ float maximumMagnitude(const float *inputVector, size_t numberOfElementsToProces float computeConvolution(const float *state, const float *kernel, size_t kernelSize); +void interleaveStereo( + const float *inputLeft, + const float *inputRight, + float *outputInterleaved, + size_t numberOfFrames); + } // namespace audioapi::dsp diff --git a/packages/react-native-audio-api/common/cpp/audioapi/utils/AudioBuffer.cpp b/packages/react-native-audio-api/common/cpp/audioapi/utils/AudioBuffer.cpp index 99531b4e6..9d0a9f18d 100644 --- a/packages/react-native-audio-api/common/cpp/audioapi/utils/AudioBuffer.cpp +++ b/packages/react-native-audio-api/common/cpp/audioapi/utils/AudioBuffer.cpp @@ -4,6 +4,7 @@ #include #include #include + #include #include #include @@ -245,6 +246,38 @@ void AudioBuffer::copy( sum(source, sourceStart, destinationStart, length); } +void AudioBuffer::interleaveTo(float *destination, size_t frames) const { + if (frames == 0) { + return; + } + + if (numberOfChannels_ == 1) { + channels_[0]->copyTo(destination, 0, 0, frames); + return; + } + + if (numberOfChannels_ == 2) { + dsp::interleaveStereo(channels_[0]->begin(), channels_[1]->begin(), destination, frames); + return; + } + + float* channelsPtrs[MAX_CHANNEL_COUNT]; + for (int i = 0; i < numberOfChannels_; ++i) { + channelsPtrs[i] = channels_[i]->begin(); + } + + constexpr size_t kBlockSize = 64; + for (size_t blockStart = 0; blockStart < frames; blockStart += kBlockSize) { + size_t blockEnd = std::min(blockStart + kBlockSize, frames); + for (size_t i = blockStart; i < blockEnd; ++i) { + float* frameDest = destination + (i * numberOfChannels_); + for (int ch = 0; ch < numberOfChannels_; ++ch) { + frameDest[ch] = channelsPtrs[ch][i]; + } + } + } +} + void AudioBuffer::normalize() { float maxAbsValue = this->maxAbsValue(); diff --git a/packages/react-native-audio-api/common/cpp/audioapi/utils/AudioBuffer.h b/packages/react-native-audio-api/common/cpp/audioapi/utils/AudioBuffer.h index 9803d5a47..660ff7135 100644 --- a/packages/react-native-audio-api/common/cpp/audioapi/utils/AudioBuffer.h +++ b/packages/react-native-audio-api/common/cpp/audioapi/utils/AudioBuffer.h @@ -86,6 +86,15 @@ class AudioBuffer { void copy(const AudioBuffer &source); void copy(const AudioBuffer &source, size_t sourceStart, size_t destinationStart, size_t length); + /// @brief Interleave audio data from this AudioBuffer into a destination buffer. + /// @param destination Pointer to the destination buffer where interleaved audio data will be written. + /// @param frames Number of frames to interleave into the destination buffer. + /// @note The destination buffer should have enough space to hold the interleaved data + /// according to the number of channels in this AudioBuffer. + /// Example of interleaved data for stereo (2 channels): + /// [L0, R0, L1, R1, L2, R2, ...] + void interleaveTo(float *destination, size_t frames) const; + void normalize(); void scale(float value); [[nodiscard]] float maxAbsValue() const; From 40d3ce7da0d6e9fad4aa375282503b1e029d1a3a Mon Sep 17 00:00:00 2001 From: maciejmakowski2003 Date: Wed, 4 Feb 2026 20:09:11 +0100 Subject: [PATCH 19/30] refactor: renaming --- .../docs/guides/create-your-own-effect.mdx | 5 +++ .../android/core/AndroidAudioRecorder.cpp | 10 +++--- .../core/utils/AndroidRecorderCallback.cpp | 6 ++-- .../audioapi/core/analysis/AnalyserNode.cpp | 8 ++--- .../cpp/audioapi/core/analysis/AnalyserNode.h | 2 +- .../core/destinations/AudioDestinationNode.h | 7 ++-- .../core/effects/BiquadFilterNode.cpp | 8 ++--- .../audioapi/core/effects/BiquadFilterNode.h | 2 +- .../audioapi/core/effects/ConvolverNode.cpp | 30 ++++++++-------- .../cpp/audioapi/core/effects/ConvolverNode.h | 6 ++-- .../cpp/audioapi/core/effects/DelayNode.cpp | 36 +++++++++---------- .../cpp/audioapi/core/effects/DelayNode.h | 4 +-- .../cpp/audioapi/core/effects/GainNode.cpp | 3 +- .../audioapi/core/effects/IIRFilterNode.cpp | 2 +- .../cpp/audioapi/core/inputs/AudioRecorder.h | 2 +- .../core/utils/AudioRecorderCallback.h | 2 +- .../common/cpp/audioapi/utils/AudioArray.cpp | 36 +++++++++---------- .../common/cpp/audioapi/utils/AudioArray.h | 16 ++++----- .../ios/audioapi/ios/core/IOSAudioRecorder.mm | 10 +++--- .../ios/core/utils/IOSRecorderCallback.mm | 10 +++--- 20 files changed, 106 insertions(+), 99 deletions(-) diff --git a/packages/audiodocs/docs/guides/create-your-own-effect.mdx b/packages/audiodocs/docs/guides/create-your-own-effect.mdx index de1e07882..e195c92f2 100644 --- a/packages/audiodocs/docs/guides/create-your-own-effect.mdx +++ b/packages/audiodocs/docs/guides/create-your-own-effect.mdx @@ -55,6 +55,11 @@ protected: std::shared_ptr processNode(const std::shared_ptr &buffer, int framesToProcess) override; + +// highlight-start +private: + double gain; // value responsible for gain value +// highlight-end }; } // namespace audioapi ``` diff --git a/packages/react-native-audio-api/android/src/main/cpp/audioapi/android/core/AndroidAudioRecorder.cpp b/packages/react-native-audio-api/android/src/main/cpp/audioapi/android/core/AndroidAudioRecorder.cpp index 37e9eb528..77eee6ccf 100644 --- a/packages/react-native-audio-api/android/src/main/cpp/audioapi/android/core/AndroidAudioRecorder.cpp +++ b/packages/react-native-audio-api/android/src/main/cpp/audioapi/android/core/AndroidAudioRecorder.cpp @@ -138,7 +138,7 @@ Result AndroidAudioRecorder::start(const std::string & } if (isConnected()) { - deinterleavingArray_ = std::make_shared(maxBufferSizeInFrames_); + tempArray_ = std::make_shared(maxBufferSizeInFrames_); adapterNode_->init(maxBufferSizeInFrames_, streamChannelCount_); } @@ -319,7 +319,7 @@ void AndroidAudioRecorder::connect(const std::shared_ptr &n adapterNode_ = node; if (!isIdle()) { - deinterleavingArray_ = std::make_shared(maxBufferSizeInFrames_); + tempArray_ = std::make_shared(maxBufferSizeInFrames_); adapterNode_->init(maxBufferSizeInFrames_, streamChannelCount_); } @@ -332,7 +332,7 @@ void AndroidAudioRecorder::connect(const std::shared_ptr &n void AndroidAudioRecorder::disconnect() { std::scoped_lock adapterLock(adapterNodeMutex_); isConnected_.store(false, std::memory_order_release); - deinterleavingArray_ = nullptr; + tempArray_ = nullptr; adapterNode_ = nullptr; } @@ -370,13 +370,13 @@ oboe::DataCallbackResult AndroidAudioRecorder::onAudioReady( if (isConnected()) { if (auto adapterLock = Locker::tryLock(adapterNodeMutex_)) { for (int channel = 0; channel < streamChannelCount_; ++channel) { - auto channelData = deinterleavingArray_->span(); + auto channelData = tempArray_->span(); for (int frame = 0; frame < numFrames; ++frame) { channelData[frame] = static_cast(audioData)[frame * streamChannelCount_ + channel]; } - adapterNode_->buff_[channel]->write(*deinterleavingArray_, numFrames); + adapterNode_->buff_[channel]->write(*tempArray_, numFrames); } } } diff --git a/packages/react-native-audio-api/android/src/main/cpp/audioapi/android/core/utils/AndroidRecorderCallback.cpp b/packages/react-native-audio-api/android/src/main/cpp/audioapi/android/core/utils/AndroidRecorderCallback.cpp index fab40cf20..c27f3a431 100644 --- a/packages/react-native-audio-api/android/src/main/cpp/audioapi/android/core/utils/AndroidRecorderCallback.cpp +++ b/packages/react-native-audio-api/android/src/main/cpp/audioapi/android/core/utils/AndroidRecorderCallback.cpp @@ -96,7 +96,7 @@ Result AndroidRecorderCallback::prepare( processingBufferLength_ = std::max(processingBufferLength_, (ma_uint64)maxInputBufferLength_); - deinterleavingArray_ = std::make_shared(processingBufferLength_); + tempArray_ = std::make_shared(processingBufferLength_); processingBuffer_ = ma_malloc( processingBufferLength_ * channelCount_ * ma_get_bytes_per_sample(ma_format_f32), nullptr); @@ -152,13 +152,13 @@ void AndroidRecorderCallback::deinterleaveAndPushAudioData(void *data, int numFr auto *inputData = static_cast(data); for (int channel = 0; channel < channelCount_; ++channel) { - auto channelData = deinterleavingArray_->span(); + auto channelData = tempArray_->span(); for (int frame = 0; frame < numFrames; ++frame) { channelData[frame] = inputData[frame * channelCount_ + channel]; } - circularBus_[channel]->push_back(*deinterleavingArray_, numFrames); + circularBus_[channel]->push_back(*tempArray_, numFrames); } } diff --git a/packages/react-native-audio-api/common/cpp/audioapi/core/analysis/AnalyserNode.cpp b/packages/react-native-audio-api/common/cpp/audioapi/core/analysis/AnalyserNode.cpp index b1ae3b6c3..5cd6dd660 100644 --- a/packages/react-native-audio-api/common/cpp/audioapi/core/analysis/AnalyserNode.cpp +++ b/packages/react-native-audio-api/common/cpp/audioapi/core/analysis/AnalyserNode.cpp @@ -152,19 +152,19 @@ void AnalyserNode::getByteTimeDomainData(uint8_t *data, int length) { } std::shared_ptr AnalyserNode::processNode( - const std::shared_ptr &processingBus, + const std::shared_ptr &processingBuffer, int framesToProcess) { // Analyser should behave like a sniffer node, it should not modify the - // processingBus but instead copy the data to its own input buffer. + // processingBuffer but instead copy the data to its own input buffer. // Down mix the input bus to mono - downMixBus_->copy(*processingBus); + downMixBus_->copy(*processingBuffer); // Copy the down mixed bus to the input buffer (circular buffer) inputArray_->push_back(*downMixBus_->getChannel(0), framesToProcess, true); shouldDoFFTAnalysis_ = true; - return processingBus; + return processingBuffer; } void AnalyserNode::doFFTAnalysis() { diff --git a/packages/react-native-audio-api/common/cpp/audioapi/core/analysis/AnalyserNode.h b/packages/react-native-audio-api/common/cpp/audioapi/core/analysis/AnalyserNode.h index 0dea5b123..62afdbb84 100644 --- a/packages/react-native-audio-api/common/cpp/audioapi/core/analysis/AnalyserNode.h +++ b/packages/react-native-audio-api/common/cpp/audioapi/core/analysis/AnalyserNode.h @@ -44,7 +44,7 @@ class AnalyserNode : public AudioNode { protected: std::shared_ptr processNode( - const std::shared_ptr &processingBus, + const std::shared_ptr &processingBuffer, int framesToProcess) override; private: diff --git a/packages/react-native-audio-api/common/cpp/audioapi/core/destinations/AudioDestinationNode.h b/packages/react-native-audio-api/common/cpp/audioapi/core/destinations/AudioDestinationNode.h index 478e979d8..2e6e7350a 100644 --- a/packages/react-native-audio-api/common/cpp/audioapi/core/destinations/AudioDestinationNode.h +++ b/packages/react-native-audio-api/common/cpp/audioapi/core/destinations/AudioDestinationNode.h @@ -25,9 +25,10 @@ class AudioDestinationNode : public AudioNode { protected: // DestinationNode is triggered by AudioContext using renderAudio // processNode function is not necessary and is never called. - std::shared_ptr processNode(const std::shared_ptr &processingBus, int) - final { - return processingBus; + std::shared_ptr processNode( + const std::shared_ptr &processingBuffer, + int) final { + return processingBuffer; }; private: diff --git a/packages/react-native-audio-api/common/cpp/audioapi/core/effects/BiquadFilterNode.cpp b/packages/react-native-audio-api/common/cpp/audioapi/core/effects/BiquadFilterNode.cpp index 0e4248ba2..7c0998b5a 100644 --- a/packages/react-native-audio-api/common/cpp/audioapi/core/effects/BiquadFilterNode.cpp +++ b/packages/react-native-audio-api/common/cpp/audioapi/core/effects/BiquadFilterNode.cpp @@ -387,9 +387,9 @@ void BiquadFilterNode::applyFilter() { } std::shared_ptr BiquadFilterNode::processNode( - const std::shared_ptr &processingBus, + const std::shared_ptr &processingBuffer, int framesToProcess) { - int numChannels = processingBus->getNumberOfChannels(); + int numChannels = processingBuffer->getNumberOfChannels(); applyFilter(); @@ -403,7 +403,7 @@ std::shared_ptr BiquadFilterNode::processNode( float x1, x2, y1, y2; for (int c = 0; c < numChannels; ++c) { - auto channel = processingBus->getChannel(c)->subSpan(framesToProcess); + auto channel = processingBuffer->getChannel(c)->subSpan(framesToProcess); x1 = x1_[c]; x2 = x2_[c]; @@ -433,7 +433,7 @@ std::shared_ptr BiquadFilterNode::processNode( y2_[c] = y2; } - return processingBus; + return processingBuffer; } } // namespace audioapi diff --git a/packages/react-native-audio-api/common/cpp/audioapi/core/effects/BiquadFilterNode.h b/packages/react-native-audio-api/common/cpp/audioapi/core/effects/BiquadFilterNode.h index 287e4ca53..3763f9c2e 100644 --- a/packages/react-native-audio-api/common/cpp/audioapi/core/effects/BiquadFilterNode.h +++ b/packages/react-native-audio-api/common/cpp/audioapi/core/effects/BiquadFilterNode.h @@ -73,7 +73,7 @@ class BiquadFilterNode : public AudioNode { protected: std::shared_ptr processNode( - const std::shared_ptr &processingBus, + const std::shared_ptr &processingBuffer, int framesToProcess) override; private: diff --git a/packages/react-native-audio-api/common/cpp/audioapi/core/effects/ConvolverNode.cpp b/packages/react-native-audio-api/common/cpp/audioapi/core/effects/ConvolverNode.cpp index 2a026ccb5..1b72d49f4 100644 --- a/packages/react-native-audio-api/common/cpp/audioapi/core/effects/ConvolverNode.cpp +++ b/packages/react-native-audio-api/common/cpp/audioapi/core/effects/ConvolverNode.cpp @@ -22,7 +22,7 @@ ConvolverNode::ConvolverNode( normalize_(!options.disableNormalization), signalledToStop_(false), scaleFactor_(1.0f), - intermediateBus_(nullptr), + intermediateBuffer_(nullptr), buffer_(nullptr), internalBuffer_(nullptr) { setBuffer(options.bus); @@ -71,7 +71,7 @@ void ConvolverNode::setBuffer(const std::shared_ptr &buffer) { } internalBuffer_ = std::make_shared( RENDER_QUANTUM_SIZE * 2, channelCount_, buffer->getSampleRate()); - intermediateBus_ = std::make_shared( + intermediateBuffer_ = std::make_shared( RENDER_QUANTUM_SIZE, convolvers_.size(), buffer->getSampleRate()); internalBufferIndex_ = 0; } @@ -95,10 +95,10 @@ std::shared_ptr ConvolverNode::processInputs( return AudioNode::processInputs(outputBus, 0, false); } -// processing pipeline: processingBus -> intermediateBus_ -> audioBus_ (mixing -// with intermediateBus_) +// processing pipeline: processingBuffer -> intermediateBuffer_ -> audioBus_ (mixing +// with intermediateBuffer_) std::shared_ptr ConvolverNode::processNode( - const std::shared_ptr &processingBus, + const std::shared_ptr &processingBuffer, int framesToProcess) { if (signalledToStop_) { if (remainingSegments_ > 0) { @@ -107,12 +107,12 @@ std::shared_ptr ConvolverNode::processNode( disable(); signalledToStop_ = false; internalBufferIndex_ = 0; - return processingBus; + return processingBuffer; } } if (internalBufferIndex_ < framesToProcess) { - performConvolution(processingBus); // result returned to intermediateBus_ - audioBus_->sum(*intermediateBus_); + performConvolution(processingBuffer); // result returned to intermediateBuffer_ + audioBus_->sum(*intermediateBuffer_); internalBuffer_->copy(*audioBus_, 0, internalBufferIndex_, RENDER_QUANTUM_SIZE); internalBufferIndex_ += RENDER_QUANTUM_SIZE; @@ -160,14 +160,14 @@ void ConvolverNode::calculateNormalizationScale() { scaleFactor_ *= gainCalibrationSampleRate_ / buffer_->getSampleRate(); } -void ConvolverNode::performConvolution(const std::shared_ptr &processingBus) { - if (processingBus->getNumberOfChannels() == 1) { +void ConvolverNode::performConvolution(const std::shared_ptr &processingBuffer) { + if (processingBuffer->getNumberOfChannels() == 1) { for (int i = 0; i < convolvers_.size(); ++i) { threadPool_->schedule([&, i] { - convolvers_[i].process(*processingBus->getChannel(0), *intermediateBus_->getChannel(i)); + convolvers_[i].process(*processingBuffer->getChannel(0), *intermediateBuffer_->getChannel(i)); }); } - } else if (processingBus->getNumberOfChannels() == 2) { + } else if (processingBuffer->getNumberOfChannels() == 2) { std::vector inputChannelMap; std::vector outputChannelMap; if (convolvers_.size() == 2) { @@ -178,10 +178,10 @@ void ConvolverNode::performConvolution(const std::shared_ptr &proce outputChannelMap = {0, 3, 2, 1}; } for (int i = 0; i < convolvers_.size(); ++i) { - threadPool_->schedule([this, i, inputChannelMap, outputChannelMap, &processingBus] { + threadPool_->schedule([this, i, inputChannelMap, outputChannelMap, &processingBuffer] { convolvers_[i].process( - *processingBus->getChannel(inputChannelMap[i]), - *intermediateBus_->getChannel(outputChannelMap[i])); + *processingBuffer->getChannel(inputChannelMap[i]), + *intermediateBuffer_->getChannel(outputChannelMap[i])); }); } } diff --git a/packages/react-native-audio-api/common/cpp/audioapi/core/effects/ConvolverNode.h b/packages/react-native-audio-api/common/cpp/audioapi/core/effects/ConvolverNode.h index 33054f524..00b05b78f 100644 --- a/packages/react-native-audio-api/common/cpp/audioapi/core/effects/ConvolverNode.h +++ b/packages/react-native-audio-api/common/cpp/audioapi/core/effects/ConvolverNode.h @@ -32,7 +32,7 @@ class ConvolverNode : public AudioNode { protected: std::shared_ptr processNode( - const std::shared_ptr &processingBus, + const std::shared_ptr &processingBuffer, int framesToProcess) override; private: @@ -47,7 +47,7 @@ class ConvolverNode : public AudioNode { bool normalize_; bool signalledToStop_; float scaleFactor_; - std::shared_ptr intermediateBus_; + std::shared_ptr intermediateBuffer_; // impulse response buffer std::shared_ptr buffer_; @@ -58,7 +58,7 @@ class ConvolverNode : public AudioNode { std::shared_ptr threadPool_; void calculateNormalizationScale(); - void performConvolution(const std::shared_ptr &processingBus); + void performConvolution(const std::shared_ptr &processingBuffer); }; } // namespace audioapi diff --git a/packages/react-native-audio-api/common/cpp/audioapi/core/effects/DelayNode.cpp b/packages/react-native-audio-api/common/cpp/audioapi/core/effects/DelayNode.cpp index 019a15dd2..817a41239 100644 --- a/packages/react-native-audio-api/common/cpp/audioapi/core/effects/DelayNode.cpp +++ b/packages/react-native-audio-api/common/cpp/audioapi/core/effects/DelayNode.cpp @@ -40,11 +40,11 @@ void DelayNode::onInputDisabled() { } void DelayNode::delayBufferOperation( - const std::shared_ptr &processingBus, + const std::shared_ptr &processingBuffer, int framesToProcess, size_t &operationStartingIndex, DelayNode::BufferAction action) { - size_t processingBusStartIndex = 0; + size_t processingBufferStartIndex = 0; // handle buffer wrap around if (operationStartingIndex + framesToProcess > delayBuffer_->getSize()) { @@ -52,24 +52,24 @@ void DelayNode::delayBufferOperation( if (action == BufferAction::WRITE) { delayBuffer_->sum( - *processingBus, processingBusStartIndex, operationStartingIndex, framesToEnd); + *processingBuffer, processingBufferStartIndex, operationStartingIndex, framesToEnd); } else { // READ - processingBus->sum( - *delayBuffer_, operationStartingIndex, processingBusStartIndex, framesToEnd); + processingBuffer->sum( + *delayBuffer_, operationStartingIndex, processingBufferStartIndex, framesToEnd); } operationStartingIndex = 0; - processingBusStartIndex += framesToEnd; + processingBufferStartIndex += framesToEnd; framesToProcess -= framesToEnd; } if (action == BufferAction::WRITE) { delayBuffer_->sum( - *processingBus, processingBusStartIndex, operationStartingIndex, framesToProcess); - processingBus->zero(); + *processingBuffer, processingBufferStartIndex, operationStartingIndex, framesToProcess); + processingBuffer->zero(); } else { // READ - processingBus->sum( - *delayBuffer_, operationStartingIndex, processingBusStartIndex, framesToProcess); + processingBuffer->sum( + *delayBuffer_, operationStartingIndex, processingBufferStartIndex, framesToProcess); delayBuffer_->zero(operationStartingIndex, framesToProcess); } @@ -81,32 +81,32 @@ void DelayNode::delayBufferOperation( // 1. writing to delay buffer (mixing if needed) from processing bus // 2. reading from delay buffer to processing bus (mixing if needed) with delay std::shared_ptr DelayNode::processNode( - const std::shared_ptr &processingBus, + const std::shared_ptr &processingBuffer, int framesToProcess) { // handling tail processing if (signalledToStop_) { if (remainingFrames_ <= 0) { disable(); signalledToStop_ = false; - return processingBus; + return processingBuffer; } - delayBufferOperation(processingBus, framesToProcess, readIndex_, DelayNode::BufferAction::READ); + delayBufferOperation(processingBuffer, framesToProcess, readIndex_, DelayNode::BufferAction::READ); remainingFrames_ -= framesToProcess; - return processingBus; + return processingBuffer; } // normal processing std::shared_ptr context = context_.lock(); if (context == nullptr) - return processingBus; + return processingBuffer; auto delayTime = delayTimeParam_->processKRateParam(framesToProcess, context->getCurrentTime()); size_t writeIndex = static_cast(readIndex_ + delayTime * context->getSampleRate()) % delayBuffer_->getSize(); - delayBufferOperation(processingBus, framesToProcess, writeIndex, DelayNode::BufferAction::WRITE); - delayBufferOperation(processingBus, framesToProcess, readIndex_, DelayNode::BufferAction::READ); + delayBufferOperation(processingBuffer, framesToProcess, writeIndex, DelayNode::BufferAction::WRITE); + delayBufferOperation(processingBuffer, framesToProcess, readIndex_, DelayNode::BufferAction::READ); - return processingBus; + return processingBuffer; } } // namespace audioapi diff --git a/packages/react-native-audio-api/common/cpp/audioapi/core/effects/DelayNode.h b/packages/react-native-audio-api/common/cpp/audioapi/core/effects/DelayNode.h index a44a77007..eb6f74cd2 100644 --- a/packages/react-native-audio-api/common/cpp/audioapi/core/effects/DelayNode.h +++ b/packages/react-native-audio-api/common/cpp/audioapi/core/effects/DelayNode.h @@ -19,14 +19,14 @@ class DelayNode : public AudioNode { protected: std::shared_ptr processNode( - const std::shared_ptr &processingBus, + const std::shared_ptr &processingBuffer, int framesToProcess) override; private: void onInputDisabled() override; enum class BufferAction { READ, WRITE }; void delayBufferOperation( - const std::shared_ptr &processingBus, + const std::shared_ptr &processingBuffer, int framesToProcess, size_t &operationStartingIndex, BufferAction action); diff --git a/packages/react-native-audio-api/common/cpp/audioapi/core/effects/GainNode.cpp b/packages/react-native-audio-api/common/cpp/audioapi/core/effects/GainNode.cpp index e538a1187..3213cfdc0 100644 --- a/packages/react-native-audio-api/common/cpp/audioapi/core/effects/GainNode.cpp +++ b/packages/react-native-audio-api/common/cpp/audioapi/core/effects/GainNode.cpp @@ -31,9 +31,10 @@ std::shared_ptr GainNode::processNode( return processingBus; double time = context->getCurrentTime(); auto gainParamValues = gainParam_->processARateParam(framesToProcess, time); + auto gainValues = gainParamValues->getChannel(0); + for (int i = 0; i < processingBus->getNumberOfChannels(); i += 1) { auto channel = processingBus->getChannel(i); - auto gainValues = gainParamValues->getChannel(0); channel->multiply(*gainValues, framesToProcess); } diff --git a/packages/react-native-audio-api/common/cpp/audioapi/core/effects/IIRFilterNode.cpp b/packages/react-native-audio-api/common/cpp/audioapi/core/effects/IIRFilterNode.cpp index a1a160850..28aeb7f08 100644 --- a/packages/react-native-audio-api/common/cpp/audioapi/core/effects/IIRFilterNode.cpp +++ b/packages/react-native-audio-api/common/cpp/audioapi/core/effects/IIRFilterNode.cpp @@ -133,7 +133,7 @@ std::shared_ptr IIRFilterNode::processNode( int mask = bufferLength - 1; for (int c = 0; c < numChannels; ++c) { - auto channel = processingBus->getChannel(c)->subSpan(0, framesToProcess); + auto channel = processingBus->getChannel(c)->subSpan(framesToProcess); auto &x = xBuffers_[c]; auto &y = yBuffers_[c]; diff --git a/packages/react-native-audio-api/common/cpp/audioapi/core/inputs/AudioRecorder.h b/packages/react-native-audio-api/common/cpp/audioapi/core/inputs/AudioRecorder.h index 7df5cf075..72bca381d 100644 --- a/packages/react-native-audio-api/common/cpp/audioapi/core/inputs/AudioRecorder.h +++ b/packages/react-native-audio-api/common/cpp/audioapi/core/inputs/AudioRecorder.h @@ -66,7 +66,7 @@ class AudioRecorder { std::atomic fileOutputEnabled_{false}; std::atomic callbackOutputEnabled_{false}; - std::shared_ptr deinterleavingArray_; + std::shared_ptr tempArray_; size_t maxBufferSizeInFrames_ = 0; std::mutex callbackMutex_; diff --git a/packages/react-native-audio-api/common/cpp/audioapi/core/utils/AudioRecorderCallback.h b/packages/react-native-audio-api/common/cpp/audioapi/core/utils/AudioRecorderCallback.h index d93e478e6..4ffed6bae 100644 --- a/packages/react-native-audio-api/common/cpp/audioapi/core/utils/AudioRecorderCallback.h +++ b/packages/react-native-audio-api/common/cpp/audioapi/core/utils/AudioRecorderCallback.h @@ -43,7 +43,7 @@ class AudioRecorderCallback { uint64_t callbackId_; size_t ringBufferSize_; - std::shared_ptr deinterleavingArray_; + std::shared_ptr tempArray_; std::atomic errorCallbackId_{0}; diff --git a/packages/react-native-audio-api/common/cpp/audioapi/utils/AudioArray.cpp b/packages/react-native-audio-api/common/cpp/audioapi/utils/AudioArray.cpp index ac7bc1c76..8923acab8 100644 --- a/packages/react-native-audio-api/common/cpp/audioapi/utils/AudioArray.cpp +++ b/packages/react-native-audio-api/common/cpp/audioapi/utils/AudioArray.cpp @@ -131,24 +131,6 @@ void AudioArray::copy( copy(source.data_.get(), sourceStart, destinationStart, length); } -void AudioArray::copyReverse( - const audioapi::AudioArray &source, - size_t sourceStart, - size_t destinationStart, - size_t length) { - if (size_ - destinationStart < length || source.size_ - sourceStart < length) { - throw std::out_of_range("Not enough space to copy to destination or from source."); - } - - auto dstView = this->subSpan(length, destinationStart); - auto srcView = source.span(); - const float *__restrict srcPtr = &srcView[sourceStart]; - - for (size_t i = 0; i < length; ++i) { - dstView[i] = srcPtr[-static_cast(i)]; - } -} - void AudioArray::copy( const float *source, size_t sourceStart, @@ -161,6 +143,24 @@ void AudioArray::copy( memcpy(data_.get() + destinationStart, source + sourceStart, length * sizeof(float)); } +void AudioArray::copyReverse( + const audioapi::AudioArray &source, + size_t sourceStart, + size_t destinationStart, + size_t length) { + if (size_ - destinationStart < length || source.size_ - sourceStart < length) { + throw std::out_of_range("Not enough space to copy to destination or from source."); + } + + auto dstView = this->subSpan(length, destinationStart); + auto srcView = source.span(); + const float *__restrict srcPtr = &srcView[sourceStart]; + + for (size_t i = 0; i < length; ++i) { + dstView[i] = srcPtr[-static_cast(i)]; + } +} + void AudioArray::copyTo( float *destination, size_t sourceStart, diff --git a/packages/react-native-audio-api/common/cpp/audioapi/utils/AudioArray.h b/packages/react-native-audio-api/common/cpp/audioapi/utils/AudioArray.h index 77fc4cba3..e2fbbed67 100644 --- a/packages/react-native-audio-api/common/cpp/audioapi/utils/AudioArray.h +++ b/packages/react-native-audio-api/common/cpp/audioapi/utils/AudioArray.h @@ -116,6 +116,14 @@ class AudioArray { /// @note Assumes that source and this are located in two distinct, non-overlapping memory locations. void copy(const AudioArray &source, size_t sourceStart, size_t destinationStart, size_t length); + /// @brief Copies data from a raw float pointer into this AudioArray. + /// @param source The source float pointer to copy from. + /// @param sourceStart The starting index in the source float pointer. + /// @param destinationStart The starting index in this AudioArray. + /// @param length The number of samples to copy. + /// @note Assumes that source and this are located in two distinct, non-overlapping memory locations. + void copy(const float *source, size_t sourceStart, size_t destinationStart, size_t length); + /// @brief Copies data from the source AudioArray in reverse order into this AudioArray. /// @param source The source AudioArray to copy from. /// @param sourceStart The starting index in the source AudioArray. @@ -125,14 +133,6 @@ class AudioArray { void copyReverse(const AudioArray &source, size_t sourceStart, size_t destinationStart, size_t length); - /// @brief Copies data from a raw float pointer into this AudioArray. - /// @param source The source float pointer to copy from. - /// @param sourceStart The starting index in the source float pointer. - /// @param destinationStart The starting index in this AudioArray. - /// @param length The number of samples to copy. - /// @note Assumes that source and this are located in two distinct, non-overlapping memory locations. - void copy(const float *source, size_t sourceStart, size_t destinationStart, size_t length); - /// @brief Copies data to a raw float pointer from this AudioArray. /// @param destination The destination float pointer to copy to. /// @param sourceStart The starting index in the this AudioArray. diff --git a/packages/react-native-audio-api/ios/audioapi/ios/core/IOSAudioRecorder.mm b/packages/react-native-audio-api/ios/audioapi/ios/core/IOSAudioRecorder.mm index e77ceb39c..2436e4cfa 100644 --- a/packages/react-native-audio-api/ios/audioapi/ios/core/IOSAudioRecorder.mm +++ b/packages/react-native-audio-api/ios/audioapi/ios/core/IOSAudioRecorder.mm @@ -53,8 +53,8 @@ for (size_t channel = 0; channel < adapterNode_->channelCount_; ++channel) { float *data = (float *)inputBuffer->mBuffers[channel].mData; - deinterleavingArray_->copy(data, 0, 0, numFrames); - adapterNode_->buff_[channel]->write(*deinterleavingArray_, numFrames); + tempArray_->copy(data, 0, 0, numFrames); + adapterNode_->buff_[channel]->write(*tempArray_, numFrames); } } } @@ -126,7 +126,7 @@ } if (isConnected()) { - deinterleavingArray_ = std::make_shared(maxBufferSizeInFrames_); + tempArray_ = std::make_shared(maxBufferSizeInFrames_); // TODO: pass sample rate, in case conversion is necessary adapterNode_->init(maxBufferSizeInFrames_, inputFormat.channelCount); } @@ -228,7 +228,7 @@ adapterNode_ = node; if (!isIdle()) { - deinterleavingArray_ = std::make_shared(maxBufferSizeInFrames_); + tempArray_ = std::make_shared(maxBufferSizeInFrames_); adapterNode_->init(maxBufferSizeInFrames_, [nativeRecorder_ getInputFormat].channelCount); } @@ -241,7 +241,7 @@ void IOSAudioRecorder::disconnect() { std::scoped_lock lock(adapterNodeMutex_); - deinterleavingArray_ = nullptr; + tempArray_ = nullptr; adapterNode_ = nullptr; isConnected_.store(false, std::memory_order_release); } diff --git a/packages/react-native-audio-api/ios/audioapi/ios/core/utils/IOSRecorderCallback.mm b/packages/react-native-audio-api/ios/audioapi/ios/core/utils/IOSRecorderCallback.mm index b4ef82b2c..2fa64d692 100644 --- a/packages/react-native-audio-api/ios/audioapi/ios/core/utils/IOSRecorderCallback.mm +++ b/packages/react-native-audio-api/ios/audioapi/ios/core/utils/IOSRecorderCallback.mm @@ -72,7 +72,7 @@ converterOutputBufferSize_ = std::max( (double)maxInputBufferLength, sampleRate_ / bufferFormat.sampleRate * maxInputBufferLength); - deinterleavingArray_ = std::make_shared(converterOutputBufferSize_); + tempArray_ = std::make_shared(converterOutputBufferSize_); callbackFormat_ = [[AVAudioFormat alloc] initWithCommonFormat:AVAudioPCMFormatFloat32 sampleRate:sampleRate_ @@ -153,8 +153,8 @@ for (int i = 0; i < channelCount_; ++i) { auto *inputChannel = static_cast(inputBuffer->mBuffers[i].mData); - deinterleavingArray_->copy(inputChannel, 0, 0, numFrames); - circularBus_[i]->push_back(*deinterleavingArray_, numFrames); + tempArray_->copy(inputChannel, 0, 0, numFrames); + circularBus_[i]->push_back(*tempArray_, numFrames); } if (circularBus_[0]->getNumberOfAvailableFrames() >= bufferLength_) { @@ -201,8 +201,8 @@ for (int i = 0; i < channelCount_; ++i) { auto *data = static_cast(converterOutputBuffer_.audioBufferList->mBuffers[i].mData); - deinterleavingArray_->copy(data, 0, 0, outputFrameCount); - circularBus_[i]->push_back(*deinterleavingArray_, outputFrameCount); + tempArray_->copy(data, 0, 0, outputFrameCount); + circularBus_[i]->push_back(*tempArray_, outputFrameCount); } if (circularBus_[0]->getNumberOfAvailableFrames() >= bufferLength_) { From 770376766b314de45350726cf64d3f7a68daebe4 Mon Sep 17 00:00:00 2001 From: maciejmakowski2003 Date: Wed, 4 Feb 2026 20:14:01 +0100 Subject: [PATCH 20/30] refactor: renaming --- .../common/cpp/audioapi/core/AudioNode.cpp | 30 +++++++-------- .../common/cpp/audioapi/core/AudioNode.h | 4 +- .../common/cpp/audioapi/core/AudioParam.cpp | 32 ++++++++-------- .../common/cpp/audioapi/core/AudioParam.h | 4 +- .../cpp/audioapi/core/effects/GainNode.cpp | 10 ++--- .../cpp/audioapi/core/effects/GainNode.h | 2 +- .../audioapi/core/effects/IIRFilterNode.cpp | 8 ++-- .../cpp/audioapi/core/effects/IIRFilterNode.h | 2 +- .../core/effects/StereoPannerNode.cpp | 12 +++--- .../audioapi/core/effects/StereoPannerNode.h | 2 +- .../audioapi/core/effects/WaveShaperNode.cpp | 14 +++---- .../audioapi/core/effects/WaveShaperNode.h | 2 +- .../cpp/audioapi/core/effects/WorkletNode.cpp | 8 ++-- .../cpp/audioapi/core/effects/WorkletNode.h | 6 +-- .../core/effects/WorkletProcessingNode.cpp | 10 ++--- .../core/effects/WorkletProcessingNode.h | 6 +-- .../sources/AudioBufferBaseSourceNode.cpp | 20 +++++----- .../core/sources/AudioBufferBaseSourceNode.h | 8 ++-- .../sources/AudioBufferQueueSourceNode.cpp | 30 +++++++-------- .../core/sources/AudioBufferQueueSourceNode.h | 6 +-- .../core/sources/AudioBufferSourceNode.cpp | 38 +++++++++---------- .../core/sources/AudioBufferSourceNode.h | 6 +-- .../core/sources/AudioScheduledSourceNode.cpp | 8 ++-- .../core/sources/AudioScheduledSourceNode.h | 2 +- .../core/sources/ConstantSourceNode.cpp | 18 ++++----- .../core/sources/ConstantSourceNode.h | 2 +- .../audioapi/core/sources/OscillatorNode.cpp | 18 ++++----- .../audioapi/core/sources/OscillatorNode.h | 2 +- .../core/sources/RecorderAdapterNode.cpp | 10 ++--- .../core/sources/RecorderAdapterNode.h | 2 +- .../audioapi/core/sources/StreamerNode.cpp | 24 ++++++------ .../cpp/audioapi/core/sources/StreamerNode.h | 2 +- .../core/sources/WorkletSourceNode.cpp | 26 ++++++------- .../audioapi/core/sources/WorkletSourceNode.h | 6 +-- .../cpp/test/src/AudioScheduledSourceTest.cpp | 11 +++--- .../cpp/test/src/ConstantSourceTest.cpp | 4 +- .../common/cpp/test/src/DelayTest.cpp | 4 +- .../common/cpp/test/src/GainTest.cpp | 4 +- .../common/cpp/test/src/StereoPannerTest.cpp | 4 +- .../src/core/effects/WaveShaperNodeTest.cpp | 4 +- 40 files changed, 205 insertions(+), 206 deletions(-) diff --git a/packages/react-native-audio-api/common/cpp/audioapi/core/AudioNode.cpp b/packages/react-native-audio-api/common/cpp/audioapi/core/AudioNode.cpp index 8997adb39..95aae1923 100644 --- a/packages/react-native-audio-api/common/cpp/audioapi/core/AudioNode.cpp +++ b/packages/react-native-audio-api/common/cpp/audioapi/core/AudioNode.cpp @@ -133,18 +133,18 @@ std::shared_ptr AudioNode::processAudio( } // Process inputs and return the bus with the most channels. - auto processingBus = processInputs(outputBus, framesToProcess, checkIsAlreadyProcessed); + auto processingBuffer = processInputs(outputBus, framesToProcess, checkIsAlreadyProcessed); // Apply channel count mode. - processingBus = applyChannelCountMode(processingBus); + processingBuffer = applyChannelCountMode(processingBuffer); // Mix all input buses into the processing bus. - mixInputsBuses(processingBus); + mixInputsBuses(processingBuffer); - assert(processingBus != nullptr); + assert(processingBuffer != nullptr); // Finally, process the node itself. - return processNode(processingBus, framesToProcess); + return processNode(processingBuffer, framesToProcess); } bool AudioNode::isAlreadyProcessed() { @@ -170,8 +170,8 @@ std::shared_ptr AudioNode::processInputs( const std::shared_ptr &outputBus, int framesToProcess, bool checkIsAlreadyProcessed) { - auto processingBus = audioBus_; - processingBus->zero(); + auto processingBuffer = audioBus_; + processingBuffer->zero(); int maxNumberOfChannels = 0; for (auto it = inputNodes_.begin(), end = inputNodes_.end(); it != end; ++it) { @@ -187,15 +187,15 @@ std::shared_ptr AudioNode::processInputs( if (maxNumberOfChannels < inputBus->getNumberOfChannels()) { maxNumberOfChannels = inputBus->getNumberOfChannels(); - processingBus = inputBus; + processingBuffer = inputBus; } } - return processingBus; + return processingBuffer; } std::shared_ptr AudioNode::applyChannelCountMode( - const std::shared_ptr &processingBus) { + const std::shared_ptr &processingBuffer) { // If the channelCountMode is EXPLICIT, the node should output the number of // channels specified by the channelCount. if (channelCountMode_ == ChannelCountMode::EXPLICIT) { @@ -205,18 +205,18 @@ std::shared_ptr AudioNode::applyChannelCountMode( // If the channelCountMode is CLAMPED_MAX, the node should output the maximum // number of channels clamped to channelCount. if (channelCountMode_ == ChannelCountMode::CLAMPED_MAX && - processingBus->getNumberOfChannels() >= channelCount_) { + processingBuffer->getNumberOfChannels() >= channelCount_) { return audioBus_; } - return processingBus; + return processingBuffer; } -void AudioNode::mixInputsBuses(const std::shared_ptr &processingBus) { - assert(processingBus != nullptr); +void AudioNode::mixInputsBuses(const std::shared_ptr &processingBuffer) { + assert(processingBuffer != nullptr); for (auto it = inputBuses_.begin(), end = inputBuses_.end(); it != end; ++it) { - processingBus->sum(**it, channelInterpretation_); + processingBuffer->sum(**it, channelInterpretation_); } inputBuses_.clear(); diff --git a/packages/react-native-audio-api/common/cpp/audioapi/core/AudioNode.h b/packages/react-native-audio-api/common/cpp/audioapi/core/AudioNode.h index 319108b1c..91e4ab675 100644 --- a/packages/react-native-audio-api/common/cpp/audioapi/core/AudioNode.h +++ b/packages/react-native-audio-api/common/cpp/audioapi/core/AudioNode.h @@ -83,8 +83,8 @@ class AudioNode : public std::enable_shared_from_this { bool isAlreadyProcessed(); std::shared_ptr applyChannelCountMode( - const std::shared_ptr &processingBus); - void mixInputsBuses(const std::shared_ptr &processingBus); + const std::shared_ptr &processingBuffer); + void mixInputsBuses(const std::shared_ptr &processingBuffer); void connectNode(const std::shared_ptr &node); void disconnectNode(const std::shared_ptr &node); diff --git a/packages/react-native-audio-api/common/cpp/audioapi/core/AudioParam.cpp b/packages/react-native-audio-api/common/cpp/audioapi/core/AudioParam.cpp index 87b134fef..737e4507f 100644 --- a/packages/react-native-audio-api/common/cpp/audioapi/core/AudioParam.cpp +++ b/packages/react-native-audio-api/common/cpp/audioapi/core/AudioParam.cpp @@ -243,26 +243,26 @@ void AudioParam::removeInputNode(AudioNode *node) { } std::shared_ptr AudioParam::calculateInputs( - const std::shared_ptr &processingBus, + const std::shared_ptr &processingBuffer, int framesToProcess) { - processingBus->zero(); + processingBuffer->zero(); if (inputNodes_.empty()) { - return processingBus; + return processingBuffer; } - processInputs(processingBus, framesToProcess, true); - mixInputsBuses(processingBus); - return processingBus; + processInputs(processingBuffer, framesToProcess, true); + mixInputsBuses(processingBuffer); + return processingBuffer; } std::shared_ptr AudioParam::processARateParam(int framesToProcess, double time) { processScheduledEvents(); - auto processingBus = calculateInputs(audioBus_, framesToProcess); + auto processingBuffer = calculateInputs(audioBus_, framesToProcess); std::shared_ptr context = context_.lock(); if (context == nullptr) - return processingBus; + return processingBuffer; float sampleRate = context->getSampleRate(); - auto busData = processingBus->getChannel(0)->span(); + auto busData = processingBuffer->getChannel(0)->span(); float timeCache = time; float timeStep = 1.0f / sampleRate; float sample = 0.0f; @@ -272,16 +272,16 @@ std::shared_ptr AudioParam::processARateParam(int framesToProcess, sample = getValueAtTime(timeCache); busData[i] += sample; } - // processingBus is a mono bus containing per-sample parameter values - return processingBus; + // processingBuffer is a mono bus containing per-sample parameter values + return processingBuffer; } float AudioParam::processKRateParam(int framesToProcess, double time) { processScheduledEvents(); - auto processingBus = calculateInputs(audioBus_, framesToProcess); + auto processingBuffer = calculateInputs(audioBus_, framesToProcess); // Return block-rate parameter value plus first sample of input modulation - return processingBus->getChannel(0)->span()[0] + getValueAtTime(time); + return processingBuffer->getChannel(0)->span()[0] + getValueAtTime(time); } void AudioParam::processInputs( @@ -302,12 +302,12 @@ void AudioParam::processInputs( } } -void AudioParam::mixInputsBuses(const std::shared_ptr &processingBus) { - assert(processingBus != nullptr); +void AudioParam::mixInputsBuses(const std::shared_ptr &processingBuffer) { + assert(processingBuffer != nullptr); // Sum all input buses into the processing bus for (auto it = inputBuses_.begin(), end = inputBuses_.end(); it != end; ++it) { - processingBus->sum(**it, ChannelInterpretation::SPEAKERS); + processingBuffer->sum(**it, ChannelInterpretation::SPEAKERS); } // Clear for next processing cycle diff --git a/packages/react-native-audio-api/common/cpp/audioapi/core/AudioParam.h b/packages/react-native-audio-api/common/cpp/audioapi/core/AudioParam.h index 165a48809..ed7f6fb66 100644 --- a/packages/react-native-audio-api/common/cpp/audioapi/core/AudioParam.h +++ b/packages/react-native-audio-api/common/cpp/audioapi/core/AudioParam.h @@ -148,9 +148,9 @@ class AudioParam { const std::shared_ptr &outputBus, int framesToProcess, bool checkIsAlreadyProcessed); - void mixInputsBuses(const std::shared_ptr &processingBus); + void mixInputsBuses(const std::shared_ptr &processingBuffer); std::shared_ptr calculateInputs( - const std::shared_ptr &processingBus, + const std::shared_ptr &processingBuffer, int framesToProcess); }; diff --git a/packages/react-native-audio-api/common/cpp/audioapi/core/effects/GainNode.cpp b/packages/react-native-audio-api/common/cpp/audioapi/core/effects/GainNode.cpp index 3213cfdc0..9334b768a 100644 --- a/packages/react-native-audio-api/common/cpp/audioapi/core/effects/GainNode.cpp +++ b/packages/react-native-audio-api/common/cpp/audioapi/core/effects/GainNode.cpp @@ -24,21 +24,21 @@ std::shared_ptr GainNode::getGainParam() const { } std::shared_ptr GainNode::processNode( - const std::shared_ptr &processingBus, + const std::shared_ptr &processingBuffer, int framesToProcess) { std::shared_ptr context = context_.lock(); if (context == nullptr) - return processingBus; + return processingBuffer; double time = context->getCurrentTime(); auto gainParamValues = gainParam_->processARateParam(framesToProcess, time); auto gainValues = gainParamValues->getChannel(0); - for (int i = 0; i < processingBus->getNumberOfChannels(); i += 1) { - auto channel = processingBus->getChannel(i); + for (int i = 0; i < processingBuffer->getNumberOfChannels(); i += 1) { + auto channel = processingBuffer->getChannel(i); channel->multiply(*gainValues, framesToProcess); } - return processingBus; + return processingBuffer; } } // namespace audioapi diff --git a/packages/react-native-audio-api/common/cpp/audioapi/core/effects/GainNode.h b/packages/react-native-audio-api/common/cpp/audioapi/core/effects/GainNode.h index 928d5a5fc..86b18cc77 100644 --- a/packages/react-native-audio-api/common/cpp/audioapi/core/effects/GainNode.h +++ b/packages/react-native-audio-api/common/cpp/audioapi/core/effects/GainNode.h @@ -18,7 +18,7 @@ class GainNode : public AudioNode { protected: std::shared_ptr processNode( - const std::shared_ptr &processingBus, + const std::shared_ptr &processingBuffer, int framesToProcess) override; private: diff --git a/packages/react-native-audio-api/common/cpp/audioapi/core/effects/IIRFilterNode.cpp b/packages/react-native-audio-api/common/cpp/audioapi/core/effects/IIRFilterNode.cpp index 28aeb7f08..83ec8607b 100644 --- a/packages/react-native-audio-api/common/cpp/audioapi/core/effects/IIRFilterNode.cpp +++ b/packages/react-native-audio-api/common/cpp/audioapi/core/effects/IIRFilterNode.cpp @@ -122,9 +122,9 @@ void IIRFilterNode::getFrequencyResponse( // TODO: tail std::shared_ptr IIRFilterNode::processNode( - const std::shared_ptr &processingBus, + const std::shared_ptr &processingBuffer, int framesToProcess) { - int numChannels = processingBus->getNumberOfChannels(); + int numChannels = processingBuffer->getNumberOfChannels(); size_t feedforwardLength = feedforward_.size(); size_t feedbackLength = feedback_.size(); @@ -133,7 +133,7 @@ std::shared_ptr IIRFilterNode::processNode( int mask = bufferLength - 1; for (int c = 0; c < numChannels; ++c) { - auto channel = processingBus->getChannel(c)->subSpan(framesToProcess); + auto channel = processingBuffer->getChannel(c)->subSpan(framesToProcess); auto &x = xBuffers_[c]; auto &y = yBuffers_[c]; @@ -170,7 +170,7 @@ std::shared_ptr IIRFilterNode::processNode( } bufferIndices[c] = bufferIndex; } - return processingBus; + return processingBuffer; } } // namespace audioapi diff --git a/packages/react-native-audio-api/common/cpp/audioapi/core/effects/IIRFilterNode.h b/packages/react-native-audio-api/common/cpp/audioapi/core/effects/IIRFilterNode.h index 8d6b44937..28ebcef9d 100644 --- a/packages/react-native-audio-api/common/cpp/audioapi/core/effects/IIRFilterNode.h +++ b/packages/react-native-audio-api/common/cpp/audioapi/core/effects/IIRFilterNode.h @@ -50,7 +50,7 @@ class IIRFilterNode : public AudioNode { protected: std::shared_ptr processNode( - const std::shared_ptr &processingBus, + const std::shared_ptr &processingBuffer, int framesToProcess) override; private: diff --git a/packages/react-native-audio-api/common/cpp/audioapi/core/effects/StereoPannerNode.cpp b/packages/react-native-audio-api/common/cpp/audioapi/core/effects/StereoPannerNode.cpp index be31dd231..8accf2e4d 100644 --- a/packages/react-native-audio-api/common/cpp/audioapi/core/effects/StereoPannerNode.cpp +++ b/packages/react-native-audio-api/common/cpp/audioapi/core/effects/StereoPannerNode.cpp @@ -23,11 +23,11 @@ std::shared_ptr StereoPannerNode::getPanParam() const { } std::shared_ptr StereoPannerNode::processNode( - const std::shared_ptr &processingBus, + const std::shared_ptr &processingBuffer, int framesToProcess) { std::shared_ptr context = context_.lock(); if (context == nullptr) - return processingBus; + return processingBuffer; double time = context->getCurrentTime(); double deltaTime = 1.0 / context->getSampleRate(); @@ -37,8 +37,8 @@ std::shared_ptr StereoPannerNode::processNode( auto outputRight = audioBus_->getChannelByType(AudioBuffer::ChannelRight)->span(); // Input is mono - if (processingBus->getNumberOfChannels() == 1) { - auto inputLeft = processingBus->getChannelByType(AudioBuffer::ChannelMono)->span(); + if (processingBuffer->getNumberOfChannels() == 1) { + auto inputLeft = processingBuffer->getChannelByType(AudioBuffer::ChannelMono)->span(); for (int i = 0; i < framesToProcess; i++) { const auto pan = std::clamp(panParamValues[i], -1.0f, 1.0f); @@ -51,8 +51,8 @@ std::shared_ptr StereoPannerNode::processNode( time += deltaTime; } } else { // Input is stereo - auto inputLeft = processingBus->getChannelByType(AudioBuffer::ChannelMono)->span(); - auto inputRight = processingBus->getChannelByType(AudioBuffer::ChannelRight)->span(); + auto inputLeft = processingBuffer->getChannelByType(AudioBuffer::ChannelMono)->span(); + auto inputRight = processingBuffer->getChannelByType(AudioBuffer::ChannelRight)->span(); for (int i = 0; i < framesToProcess; i++) { const auto pan = std::clamp(panParamValues[i], -1.0f, 1.0f); diff --git a/packages/react-native-audio-api/common/cpp/audioapi/core/effects/StereoPannerNode.h b/packages/react-native-audio-api/common/cpp/audioapi/core/effects/StereoPannerNode.h index da99cbe13..064a9e91b 100644 --- a/packages/react-native-audio-api/common/cpp/audioapi/core/effects/StereoPannerNode.h +++ b/packages/react-native-audio-api/common/cpp/audioapi/core/effects/StereoPannerNode.h @@ -22,7 +22,7 @@ class StereoPannerNode : public AudioNode { protected: std::shared_ptr processNode( - const std::shared_ptr &processingBus, + const std::shared_ptr &processingBuffer, int framesToProcess) override; private: diff --git a/packages/react-native-audio-api/common/cpp/audioapi/core/effects/WaveShaperNode.cpp b/packages/react-native-audio-api/common/cpp/audioapi/core/effects/WaveShaperNode.cpp index 70bc34cec..c010d70c2 100644 --- a/packages/react-native-audio-api/common/cpp/audioapi/core/effects/WaveShaperNode.cpp +++ b/packages/react-native-audio-api/common/cpp/audioapi/core/effects/WaveShaperNode.cpp @@ -54,29 +54,29 @@ void WaveShaperNode::setCurve(const std::shared_ptr &curve) { } std::shared_ptr WaveShaperNode::processNode( - const std::shared_ptr &processingBus, + const std::shared_ptr &processingBuffer, int framesToProcess) { if (!isInitialized_) { - return processingBus; + return processingBuffer; } std::unique_lock lock(mutex_, std::try_to_lock); if (!lock.owns_lock()) { - return processingBus; + return processingBuffer; } if (curve_ == nullptr) { - return processingBus; + return processingBuffer; } - for (int channel = 0; channel < processingBus->getNumberOfChannels(); channel++) { - auto channelData = processingBus->getChannel(channel); + for (int channel = 0; channel < processingBuffer->getNumberOfChannels(); channel++) { + auto channelData = processingBuffer->getChannel(channel); waveShapers_[channel]->process(*channelData, framesToProcess); } - return processingBus; + return processingBuffer; } } // namespace audioapi diff --git a/packages/react-native-audio-api/common/cpp/audioapi/core/effects/WaveShaperNode.h b/packages/react-native-audio-api/common/cpp/audioapi/core/effects/WaveShaperNode.h index 759b706fb..18a3f96a2 100644 --- a/packages/react-native-audio-api/common/cpp/audioapi/core/effects/WaveShaperNode.h +++ b/packages/react-native-audio-api/common/cpp/audioapi/core/effects/WaveShaperNode.h @@ -32,7 +32,7 @@ class WaveShaperNode : public AudioNode { protected: std::shared_ptr processNode( - const std::shared_ptr &processingBus, + const std::shared_ptr &processingBuffer, int framesToProcess) override; private: diff --git a/packages/react-native-audio-api/common/cpp/audioapi/core/effects/WorkletNode.cpp b/packages/react-native-audio-api/common/cpp/audioapi/core/effects/WorkletNode.cpp index befb84c23..fcce0f364 100644 --- a/packages/react-native-audio-api/common/cpp/audioapi/core/effects/WorkletNode.cpp +++ b/packages/react-native-audio-api/common/cpp/audioapi/core/effects/WorkletNode.cpp @@ -22,11 +22,11 @@ WorkletNode::WorkletNode( } std::shared_ptr WorkletNode::processNode( - const std::shared_ptr &processingBus, + const std::shared_ptr &processingBuffer, int framesToProcess) { size_t processed = 0; size_t channelCount_ = - std::min(inputChannelCount_, static_cast(processingBus->getNumberOfChannels())); + std::min(inputChannelCount_, static_cast(processingBuffer->getNumberOfChannels())); while (processed < framesToProcess) { size_t framesToWorkletInvoke = bufferLength_ - curBuffIndex_; size_t needsToProcess = framesToProcess - processed; @@ -35,7 +35,7 @@ std::shared_ptr WorkletNode::processNode( /// here we copy /// to [curBuffIndex_, curBuffIndex_ + shouldProcess] /// from [processed, processed + shouldProcess] - bus_->copy(*processingBus, processed, curBuffIndex_, shouldProcess); + bus_->copy(*processingBuffer, processed, curBuffIndex_, shouldProcess); processed += shouldProcess; curBuffIndex_ += shouldProcess; @@ -68,7 +68,7 @@ std::shared_ptr WorkletNode::processNode( }); } - return processingBus; + return processingBuffer; } } // namespace audioapi diff --git a/packages/react-native-audio-api/common/cpp/audioapi/core/effects/WorkletNode.h b/packages/react-native-audio-api/common/cpp/audioapi/core/effects/WorkletNode.h index f42bd6f3b..9a1afb11f 100644 --- a/packages/react-native-audio-api/common/cpp/audioapi/core/effects/WorkletNode.h +++ b/packages/react-native-audio-api/common/cpp/audioapi/core/effects/WorkletNode.h @@ -25,9 +25,9 @@ class WorkletNode : public AudioNode { protected: std::shared_ptr processNode( - const std::shared_ptr &processingBus, + const std::shared_ptr &processingBuffer, int framesToProcess) override { - return processingBus; + return processingBuffer; } }; #else @@ -46,7 +46,7 @@ class WorkletNode : public AudioNode { protected: std::shared_ptr processNode( - const std::shared_ptr &processingBus, + const std::shared_ptr &processingBuffer, int framesToProcess) override; private: diff --git a/packages/react-native-audio-api/common/cpp/audioapi/core/effects/WorkletProcessingNode.cpp b/packages/react-native-audio-api/common/cpp/audioapi/core/effects/WorkletProcessingNode.cpp index cc3f12b1d..9768bc6c5 100644 --- a/packages/react-native-audio-api/common/cpp/audioapi/core/effects/WorkletProcessingNode.cpp +++ b/packages/react-native-audio-api/common/cpp/audioapi/core/effects/WorkletProcessingNode.cpp @@ -22,15 +22,15 @@ WorkletProcessingNode::WorkletProcessingNode( } std::shared_ptr WorkletProcessingNode::processNode( - const std::shared_ptr &processingBus, + const std::shared_ptr &processingBuffer, int framesToProcess) { size_t channelCount = std::min( static_cast(2), // Fixed to stereo for now - static_cast(processingBus->getNumberOfChannels())); + static_cast(processingBuffer->getNumberOfChannels())); // Copy input data to pre-allocated input buffers for (int ch = 0; ch < channelCount; ch++) { - inputBuffsHandles_[ch]->copy(*processingBus->getChannel(ch), 0, 0, framesToProcess); + inputBuffsHandles_[ch]->copy(*processingBuffer->getChannel(ch), 0, 0, framesToProcess); } // Execute the worklet @@ -65,7 +65,7 @@ std::shared_ptr WorkletProcessingNode::processNode( // Copy processed output data back to the processing bus or zero on failure for (int ch = 0; ch < channelCount; ch++) { - auto channelData = processingBus->getChannel(ch); + auto channelData = processingBuffer->getChannel(ch); if (result.has_value()) { // Copy processed output data @@ -76,7 +76,7 @@ std::shared_ptr WorkletProcessingNode::processNode( } } - return processingBus; + return processingBuffer; } } // namespace audioapi diff --git a/packages/react-native-audio-api/common/cpp/audioapi/core/effects/WorkletProcessingNode.h b/packages/react-native-audio-api/common/cpp/audioapi/core/effects/WorkletProcessingNode.h index 5fe43bb8d..42e8ec72b 100644 --- a/packages/react-native-audio-api/common/cpp/audioapi/core/effects/WorkletProcessingNode.h +++ b/packages/react-native-audio-api/common/cpp/audioapi/core/effects/WorkletProcessingNode.h @@ -23,9 +23,9 @@ class WorkletProcessingNode : public AudioNode { protected: std::shared_ptr processNode( - const std::shared_ptr &processingBus, + const std::shared_ptr &processingBuffer, int framesToProcess) override { - return processingBus; + return processingBuffer; } }; #else @@ -40,7 +40,7 @@ class WorkletProcessingNode : public AudioNode { protected: std::shared_ptr processNode( - const std::shared_ptr &processingBus, + const std::shared_ptr &processingBuffer, int framesToProcess) override; private: diff --git a/packages/react-native-audio-api/common/cpp/audioapi/core/sources/AudioBufferBaseSourceNode.cpp b/packages/react-native-audio-api/common/cpp/audioapi/core/sources/AudioBufferBaseSourceNode.cpp index 38d038fb7..059c5a74b 100644 --- a/packages/react-native-audio-api/common/cpp/audioapi/core/sources/AudioBufferBaseSourceNode.cpp +++ b/packages/react-native-audio-api/common/cpp/audioapi/core/sources/AudioBufferBaseSourceNode.cpp @@ -99,14 +99,14 @@ void AudioBufferBaseSourceNode::sendOnPositionChangedEvent() { } void AudioBufferBaseSourceNode::processWithPitchCorrection( - const std::shared_ptr &processingBus, + const std::shared_ptr &processingBuffer, int framesToProcess) { size_t startOffset = 0; size_t offsetLength = 0; std::shared_ptr context = context_.lock(); if (context == nullptr) { - processingBus->zero(); + processingBuffer->zero(); return; } auto time = context->getCurrentTime(); @@ -128,14 +128,14 @@ void AudioBufferBaseSourceNode::processWithPitchCorrection( context->getCurrentSampleFrame()); if (playbackRate == 0.0f || (!isPlaying() && !isStopScheduled())) { - processingBus->zero(); + processingBuffer->zero(); return; } processWithoutInterpolation(playbackRateBus_, startOffset, offsetLength, playbackRate); stretch_->process( - playbackRateBus_.get()[0], framesNeededToStretch, processingBus.get()[0], framesToProcess); + playbackRateBus_.get()[0], framesNeededToStretch, processingBuffer.get()[0], framesToProcess); if (detune != 0.0f) { stretch_->setTransposeSemitones(detune); @@ -145,20 +145,20 @@ void AudioBufferBaseSourceNode::processWithPitchCorrection( } void AudioBufferBaseSourceNode::processWithoutPitchCorrection( - const std::shared_ptr &processingBus, + const std::shared_ptr &processingBuffer, int framesToProcess) { size_t startOffset = 0; size_t offsetLength = 0; std::shared_ptr context = context_.lock(); if (context == nullptr) { - processingBus->zero(); + processingBuffer->zero(); return; } auto computedPlaybackRate = getComputedPlaybackRateValue(framesToProcess, context->getCurrentTime()); updatePlaybackInfo( - processingBus, + processingBuffer, framesToProcess, startOffset, offsetLength, @@ -166,14 +166,14 @@ void AudioBufferBaseSourceNode::processWithoutPitchCorrection( context->getCurrentSampleFrame()); if (computedPlaybackRate == 0.0f || (!isPlaying() && !isStopScheduled())) { - processingBus->zero(); + processingBuffer->zero(); return; } if (std::fabs(computedPlaybackRate) == 1.0) { - processWithoutInterpolation(processingBus, startOffset, offsetLength, computedPlaybackRate); + processWithoutInterpolation(processingBuffer, startOffset, offsetLength, computedPlaybackRate); } else { - processWithInterpolation(processingBus, startOffset, offsetLength, computedPlaybackRate); + processWithInterpolation(processingBuffer, startOffset, offsetLength, computedPlaybackRate); } sendOnPositionChangedEvent(); diff --git a/packages/react-native-audio-api/common/cpp/audioapi/core/sources/AudioBufferBaseSourceNode.h b/packages/react-native-audio-api/common/cpp/audioapi/core/sources/AudioBufferBaseSourceNode.h index 87b3e4cf0..4969cba4c 100644 --- a/packages/react-native-audio-api/common/cpp/audioapi/core/sources/AudioBufferBaseSourceNode.h +++ b/packages/react-native-audio-api/common/cpp/audioapi/core/sources/AudioBufferBaseSourceNode.h @@ -55,22 +55,22 @@ class AudioBufferBaseSourceNode : public AudioScheduledSourceNode { void sendOnPositionChangedEvent(); void processWithPitchCorrection( - const std::shared_ptr &processingBus, + const std::shared_ptr &processingBuffer, int framesToProcess); void processWithoutPitchCorrection( - const std::shared_ptr &processingBus, + const std::shared_ptr &processingBuffer, int framesToProcess); float getComputedPlaybackRateValue(int framesToProcess, double time); virtual void processWithoutInterpolation( - const std::shared_ptr &processingBus, + const std::shared_ptr &processingBuffer, size_t startOffset, size_t offsetLength, float playbackRate) = 0; virtual void processWithInterpolation( - const std::shared_ptr &processingBus, + const std::shared_ptr &processingBuffer, size_t startOffset, size_t offsetLength, float playbackRate) = 0; diff --git a/packages/react-native-audio-api/common/cpp/audioapi/core/sources/AudioBufferQueueSourceNode.cpp b/packages/react-native-audio-api/common/cpp/audioapi/core/sources/AudioBufferQueueSourceNode.cpp index 956a99ac0..eac330254 100644 --- a/packages/react-native-audio-api/common/cpp/audioapi/core/sources/AudioBufferQueueSourceNode.cpp +++ b/packages/react-native-audio-api/common/cpp/audioapi/core/sources/AudioBufferQueueSourceNode.cpp @@ -138,27 +138,27 @@ void AudioBufferQueueSourceNode::setOnBufferEndedCallbackId(uint64_t callbackId) } std::shared_ptr AudioBufferQueueSourceNode::processNode( - const std::shared_ptr &processingBus, + const std::shared_ptr &processingBuffer, int framesToProcess) { if (auto locker = Locker::tryLock(getBufferLock())) { // no audio data to fill, zero the output and return. if (buffers_.empty()) { - processingBus->zero(); - return processingBus; + processingBuffer->zero(); + return processingBuffer; } if (!pitchCorrection_) { - processWithoutPitchCorrection(processingBus, framesToProcess); + processWithoutPitchCorrection(processingBuffer, framesToProcess); } else { - processWithPitchCorrection(processingBus, framesToProcess); + processWithPitchCorrection(processingBuffer, framesToProcess); } handleStopScheduled(); } else { - processingBus->zero(); + processingBuffer->zero(); } - return processingBus; + return processingBuffer; } double AudioBufferQueueSourceNode::getCurrentPosition() const { @@ -187,7 +187,7 @@ void AudioBufferQueueSourceNode::sendOnBufferEndedEvent(size_t bufferId, bool is */ void AudioBufferQueueSourceNode::processWithoutInterpolation( - const std::shared_ptr &processingBus, + const std::shared_ptr &processingBuffer, size_t startOffset, size_t offsetLength, float playbackRate) { @@ -208,9 +208,9 @@ void AudioBufferQueueSourceNode::processWithoutInterpolation( assert(readIndex >= 0); assert(writeIndex >= 0); assert(readIndex + framesToCopy <= buffer->getSize()); - assert(writeIndex + framesToCopy <= processingBus->getSize()); + assert(writeIndex + framesToCopy <= processingBuffer->getSize()); - processingBus->copy(*buffer, readIndex, writeIndex, framesToCopy); + processingBuffer->copy(*buffer, readIndex, writeIndex, framesToCopy); writeIndex += framesToCopy; readIndex += framesToCopy; @@ -229,7 +229,7 @@ void AudioBufferQueueSourceNode::processWithoutInterpolation( buffers_.emplace(bufferId, tailBuffer_); addExtraTailFrames_ = false; } else { - processingBus->zero(writeIndex, framesLeft); + processingBuffer->zero(writeIndex, framesLeft); readIndex = 0; break; @@ -248,7 +248,7 @@ void AudioBufferQueueSourceNode::processWithoutInterpolation( } void AudioBufferQueueSourceNode::processWithInterpolation( - const std::shared_ptr &processingBus, + const std::shared_ptr &processingBuffer, size_t startOffset, size_t offsetLength, float playbackRate) { @@ -279,8 +279,8 @@ void AudioBufferQueueSourceNode::processWithInterpolation( } } - for (int i = 0; i < processingBus->getNumberOfChannels(); i += 1) { - const auto destination = processingBus->getChannel(i)->span(); + for (int i = 0; i < processingBuffer->getNumberOfChannels(); i += 1) { + const auto destination = processingBuffer->getChannel(i)->span(); const auto currentSource = buffer->getChannel(i)->span(); if (crossBufferInterpolation) { @@ -306,7 +306,7 @@ void AudioBufferQueueSourceNode::processWithInterpolation( sendOnBufferEndedEvent(bufferId, buffers_.empty()); if (buffers_.empty()) { - processingBus->zero(writeIndex, framesLeft); + processingBuffer->zero(writeIndex, framesLeft); vReadIndex_ = 0.0; break; } diff --git a/packages/react-native-audio-api/common/cpp/audioapi/core/sources/AudioBufferQueueSourceNode.h b/packages/react-native-audio-api/common/cpp/audioapi/core/sources/AudioBufferQueueSourceNode.h index 12714c44d..7ab344fef 100644 --- a/packages/react-native-audio-api/common/cpp/audioapi/core/sources/AudioBufferQueueSourceNode.h +++ b/packages/react-native-audio-api/common/cpp/audioapi/core/sources/AudioBufferQueueSourceNode.h @@ -38,7 +38,7 @@ class AudioBufferQueueSourceNode : public AudioBufferBaseSourceNode { protected: std::shared_ptr processNode( - const std::shared_ptr &processingBus, + const std::shared_ptr &processingBuffer, int framesToProcess) override; double getCurrentPosition() const override; @@ -59,13 +59,13 @@ class AudioBufferQueueSourceNode : public AudioBufferBaseSourceNode { std::atomic onBufferEndedCallbackId_ = 0; // 0 means no callback void processWithoutInterpolation( - const std::shared_ptr &processingBus, + const std::shared_ptr &processingBuffer, size_t startOffset, size_t offsetLength, float playbackRate) override; void processWithInterpolation( - const std::shared_ptr &processingBus, + const std::shared_ptr &processingBuffer, size_t startOffset, size_t offsetLength, float playbackRate) override; diff --git a/packages/react-native-audio-api/common/cpp/audioapi/core/sources/AudioBufferSourceNode.cpp b/packages/react-native-audio-api/common/cpp/audioapi/core/sources/AudioBufferSourceNode.cpp index 591698447..d27729fad 100644 --- a/packages/react-native-audio-api/common/cpp/audioapi/core/sources/AudioBufferSourceNode.cpp +++ b/packages/react-native-audio-api/common/cpp/audioapi/core/sources/AudioBufferSourceNode.cpp @@ -146,27 +146,27 @@ void AudioBufferSourceNode::setOnLoopEndedCallbackId(uint64_t callbackId) { } std::shared_ptr AudioBufferSourceNode::processNode( - const std::shared_ptr &processingBus, + const std::shared_ptr &processingBuffer, int framesToProcess) { if (auto locker = Locker::tryLock(getBufferLock())) { // No audio data to fill, zero the output and return. if (!alignedBus_) { - processingBus->zero(); - return processingBus; + processingBuffer->zero(); + return processingBuffer; } if (!pitchCorrection_) { - processWithoutPitchCorrection(processingBus, framesToProcess); + processWithoutPitchCorrection(processingBuffer, framesToProcess); } else { - processWithPitchCorrection(processingBus, framesToProcess); + processWithPitchCorrection(processingBuffer, framesToProcess); } handleStopScheduled(); } else { - processingBus->zero(); + processingBuffer->zero(); } - return processingBus; + return processingBuffer; } double AudioBufferSourceNode::getCurrentPosition() const { @@ -186,7 +186,7 @@ void AudioBufferSourceNode::sendOnLoopEndedEvent() { */ void AudioBufferSourceNode::processWithoutInterpolation( - const std::shared_ptr &processingBus, + const std::shared_ptr &processingBuffer, size_t startOffset, size_t offsetLength, float playbackRate) { @@ -201,7 +201,7 @@ void AudioBufferSourceNode::processWithoutInterpolation( frameStart = static_cast(getVirtualStartFrame(context->getSampleRate())); frameEnd = static_cast(getVirtualEndFrame(context->getSampleRate())); } else { - processingBus->zero(); + processingBuffer->zero(); return; } size_t frameDelta = frameEnd - frameStart; @@ -224,14 +224,14 @@ void AudioBufferSourceNode::processWithoutInterpolation( assert(readIndex >= 0); assert(writeIndex >= 0); assert(readIndex + framesToCopy <= alignedBus_->getSize()); - assert(writeIndex + framesToCopy <= processingBus->getSize()); + assert(writeIndex + framesToCopy <= processingBuffer->getSize()); // Direction is forward, we can normally copy the data if (direction == 1) { - processingBus->copy(*alignedBus_, readIndex, writeIndex, framesToCopy); + processingBuffer->copy(*alignedBus_, readIndex, writeIndex, framesToCopy); } else { - for (int ch = 0; ch < processingBus->getNumberOfChannels(); ch += 1) { - processingBus->getChannel(ch)->copyReverse( + for (int ch = 0; ch < processingBuffer->getNumberOfChannels(); ch += 1) { + processingBuffer->getChannel(ch)->copyReverse( *alignedBus_->getChannel(ch), readIndex, writeIndex, framesToCopy); } } @@ -246,7 +246,7 @@ void AudioBufferSourceNode::processWithoutInterpolation( readIndex -= direction * frameDelta; if (!loop_) { - processingBus->zero(writeIndex, framesLeft); + processingBuffer->zero(writeIndex, framesLeft); playbackState_ = PlaybackState::STOP_SCHEDULED; break; } @@ -260,7 +260,7 @@ void AudioBufferSourceNode::processWithoutInterpolation( } void AudioBufferSourceNode::processWithInterpolation( - const std::shared_ptr &processingBus, + const std::shared_ptr &processingBuffer, size_t startOffset, size_t offsetLength, float playbackRate) { @@ -274,7 +274,7 @@ void AudioBufferSourceNode::processWithInterpolation( vFrameStart = getVirtualStartFrame(context->getSampleRate()); vFrameEnd = getVirtualEndFrame(context->getSampleRate()); } else { - processingBus->zero(); + processingBuffer->zero(); return; } auto vFrameDelta = vFrameEnd - vFrameStart; @@ -298,8 +298,8 @@ void AudioBufferSourceNode::processWithInterpolation( nextReadIndex = loop_ ? frameStart : readIndex; } - for (int i = 0; i < processingBus->getNumberOfChannels(); i += 1) { - auto destination = processingBus->getChannel(i)->span(); + for (int i = 0; i < processingBuffer->getNumberOfChannels(); i += 1) { + auto destination = processingBuffer->getChannel(i)->span(); const auto source = alignedBus_->getChannel(i)->span(); destination[writeIndex] = dsp::linearInterpolate(source, readIndex, nextReadIndex, factor); @@ -313,7 +313,7 @@ void AudioBufferSourceNode::processWithInterpolation( vReadIndex_ -= static_cast(direction) * vFrameDelta; if (!loop_) { - processingBus->zero(writeIndex, framesLeft); + processingBuffer->zero(writeIndex, framesLeft); playbackState_ = PlaybackState::STOP_SCHEDULED; break; } diff --git a/packages/react-native-audio-api/common/cpp/audioapi/core/sources/AudioBufferSourceNode.h b/packages/react-native-audio-api/common/cpp/audioapi/core/sources/AudioBufferSourceNode.h index a47f49620..0667ad9d2 100644 --- a/packages/react-native-audio-api/common/cpp/audioapi/core/sources/AudioBufferSourceNode.h +++ b/packages/react-native-audio-api/common/cpp/audioapi/core/sources/AudioBufferSourceNode.h @@ -42,7 +42,7 @@ class AudioBufferSourceNode : public AudioBufferBaseSourceNode { protected: std::shared_ptr processNode( - const std::shared_ptr &processingBus, + const std::shared_ptr &processingBuffer, int framesToProcess) override; double getCurrentPosition() const override; @@ -61,13 +61,13 @@ class AudioBufferSourceNode : public AudioBufferBaseSourceNode { void sendOnLoopEndedEvent(); void processWithoutInterpolation( - const std::shared_ptr &processingBus, + const std::shared_ptr &processingBuffer, size_t startOffset, size_t offsetLength, float playbackRate) override; void processWithInterpolation( - const std::shared_ptr &processingBus, + const std::shared_ptr &processingBuffer, size_t startOffset, size_t offsetLength, float playbackRate) override; diff --git a/packages/react-native-audio-api/common/cpp/audioapi/core/sources/AudioScheduledSourceNode.cpp b/packages/react-native-audio-api/common/cpp/audioapi/core/sources/AudioScheduledSourceNode.cpp index a2ee963cf..cfce6e393 100644 --- a/packages/react-native-audio-api/common/cpp/audioapi/core/sources/AudioScheduledSourceNode.cpp +++ b/packages/react-native-audio-api/common/cpp/audioapi/core/sources/AudioScheduledSourceNode.cpp @@ -71,7 +71,7 @@ void AudioScheduledSourceNode::setOnEndedCallbackId(const uint64_t callbackId) { } void AudioScheduledSourceNode::updatePlaybackInfo( - const std::shared_ptr &processingBus, + const std::shared_ptr &processingBuffer, int framesToProcess, size_t &startOffset, size_t &nonSilentFramesToProcess, @@ -118,10 +118,10 @@ void AudioScheduledSourceNode::updatePlaybackInfo( // stop will happen in the same render quantum if (stopFrame <= lastFrame && stopFrame >= firstFrame) { playbackState_ = PlaybackState::STOP_SCHEDULED; - processingBus->zero(stopFrame - firstFrame, lastFrame - stopFrame); + processingBuffer->zero(stopFrame - firstFrame, lastFrame - stopFrame); } - processingBus->zero(0, startOffset); + processingBuffer->zero(0, startOffset); return; } @@ -137,7 +137,7 @@ void AudioScheduledSourceNode::updatePlaybackInfo( assert(startOffset <= framesToProcess); assert(nonSilentFramesToProcess <= framesToProcess); - processingBus->zero(stopFrame - firstFrame, lastFrame - stopFrame); + processingBuffer->zero(stopFrame - firstFrame, lastFrame - stopFrame); return; } diff --git a/packages/react-native-audio-api/common/cpp/audioapi/core/sources/AudioScheduledSourceNode.h b/packages/react-native-audio-api/common/cpp/audioapi/core/sources/AudioScheduledSourceNode.h index 7f9f0f277..eba765c40 100644 --- a/packages/react-native-audio-api/common/cpp/audioapi/core/sources/AudioScheduledSourceNode.h +++ b/packages/react-native-audio-api/common/cpp/audioapi/core/sources/AudioScheduledSourceNode.h @@ -51,7 +51,7 @@ class AudioScheduledSourceNode : public AudioNode { std::shared_ptr audioEventHandlerRegistry_; void updatePlaybackInfo( - const std::shared_ptr &processingBus, + const std::shared_ptr &processingBuffer, int framesToProcess, size_t &startOffset, size_t &nonSilentFramesToProcess, diff --git a/packages/react-native-audio-api/common/cpp/audioapi/core/sources/ConstantSourceNode.cpp b/packages/react-native-audio-api/common/cpp/audioapi/core/sources/ConstantSourceNode.cpp index 48a9ad884..ca728f201 100644 --- a/packages/react-native-audio-api/common/cpp/audioapi/core/sources/ConstantSourceNode.cpp +++ b/packages/react-native-audio-api/common/cpp/audioapi/core/sources/ConstantSourceNode.cpp @@ -21,19 +21,19 @@ std::shared_ptr ConstantSourceNode::getOffsetParam() const { } std::shared_ptr ConstantSourceNode::processNode( - const std::shared_ptr &processingBus, + const std::shared_ptr &processingBuffer, int framesToProcess) { size_t startOffset = 0; size_t offsetLength = 0; std::shared_ptr context = context_.lock(); if (context == nullptr) { - processingBus->zero(); - return processingBus; + processingBuffer->zero(); + return processingBuffer; } updatePlaybackInfo( - processingBus, + processingBuffer, framesToProcess, startOffset, offsetLength, @@ -41,15 +41,15 @@ std::shared_ptr ConstantSourceNode::processNode( context->getCurrentSampleFrame()); if (!isPlaying() && !isStopScheduled()) { - processingBus->zero(); - return processingBus; + processingBuffer->zero(); + return processingBuffer; } auto offsetChannel = offsetParam_->processARateParam(framesToProcess, context->getCurrentTime())->getChannel(0); - for (int channel = 0; channel < processingBus->getNumberOfChannels(); ++channel) { - processingBus->getChannel(channel)->copy( + for (int channel = 0; channel < processingBuffer->getNumberOfChannels(); ++channel) { + processingBuffer->getChannel(channel)->copy( *offsetChannel, startOffset, startOffset, offsetLength); } @@ -57,6 +57,6 @@ std::shared_ptr ConstantSourceNode::processNode( handleStopScheduled(); } - return processingBus; + return processingBuffer; } } // namespace audioapi diff --git a/packages/react-native-audio-api/common/cpp/audioapi/core/sources/ConstantSourceNode.h b/packages/react-native-audio-api/common/cpp/audioapi/core/sources/ConstantSourceNode.h index 61a099055..214fba989 100644 --- a/packages/react-native-audio-api/common/cpp/audioapi/core/sources/ConstantSourceNode.h +++ b/packages/react-native-audio-api/common/cpp/audioapi/core/sources/ConstantSourceNode.h @@ -22,7 +22,7 @@ class ConstantSourceNode : public AudioScheduledSourceNode { protected: std::shared_ptr processNode( - const std::shared_ptr &processingBus, + const std::shared_ptr &processingBuffer, int framesToProcess) override; private: diff --git a/packages/react-native-audio-api/common/cpp/audioapi/core/sources/OscillatorNode.cpp b/packages/react-native-audio-api/common/cpp/audioapi/core/sources/OscillatorNode.cpp index 82a13db30..e9340f7f5 100644 --- a/packages/react-native-audio-api/common/cpp/audioapi/core/sources/OscillatorNode.cpp +++ b/packages/react-native-audio-api/common/cpp/audioapi/core/sources/OscillatorNode.cpp @@ -57,19 +57,19 @@ void OscillatorNode::setPeriodicWave(const std::shared_ptr &period } std::shared_ptr OscillatorNode::processNode( - const std::shared_ptr &processingBus, + const std::shared_ptr &processingBuffer, int framesToProcess) { size_t startOffset = 0; size_t offsetLength = 0; std::shared_ptr context = context_.lock(); if (context == nullptr) { - processingBus->zero(); - return processingBus; + processingBuffer->zero(); + return processingBuffer; } updatePlaybackInfo( - processingBus, + processingBuffer, framesToProcess, startOffset, offsetLength, @@ -77,8 +77,8 @@ std::shared_ptr OscillatorNode::processNode( context->getCurrentSampleFrame()); if (!isPlaying() && !isStopScheduled()) { - processingBus->zero(); - return processingBus; + processingBuffer->zero(); + return processingBuffer; } auto time = @@ -88,12 +88,12 @@ std::shared_ptr OscillatorNode::processNode( const auto tableSize = static_cast(periodicWave_->getPeriodicWaveSize()); const auto tableScale = periodicWave_->getScale(); - const auto numChannels = processingBus->getNumberOfChannels(); + const auto numChannels = processingBuffer->getNumberOfChannels(); auto finalPhase = phase_; for (int ch = 0; ch < numChannels; ch += 1) { - auto channelSpan = processingBus->getChannel(ch)->span(); + auto channelSpan = processingBuffer->getChannel(ch)->span(); float currentPhase = phase_; for (size_t i = startOffset; i < offsetLength; i += 1) { @@ -120,7 +120,7 @@ std::shared_ptr OscillatorNode::processNode( phase_ = finalPhase; handleStopScheduled(); - return processingBus; + return processingBuffer; } } // namespace audioapi diff --git a/packages/react-native-audio-api/common/cpp/audioapi/core/sources/OscillatorNode.h b/packages/react-native-audio-api/common/cpp/audioapi/core/sources/OscillatorNode.h index 1805a6204..c76fe956f 100644 --- a/packages/react-native-audio-api/common/cpp/audioapi/core/sources/OscillatorNode.h +++ b/packages/react-native-audio-api/common/cpp/audioapi/core/sources/OscillatorNode.h @@ -29,7 +29,7 @@ class OscillatorNode : public AudioScheduledSourceNode { protected: std::shared_ptr processNode( - const std::shared_ptr &processingBus, + const std::shared_ptr &processingBuffer, int framesToProcess) override; private: diff --git a/packages/react-native-audio-api/common/cpp/audioapi/core/sources/RecorderAdapterNode.cpp b/packages/react-native-audio-api/common/cpp/audioapi/core/sources/RecorderAdapterNode.cpp index 8cf50cd7e..096f20b40 100644 --- a/packages/react-native-audio-api/common/cpp/audioapi/core/sources/RecorderAdapterNode.cpp +++ b/packages/react-native-audio-api/common/cpp/audioapi/core/sources/RecorderAdapterNode.cpp @@ -53,17 +53,17 @@ void RecorderAdapterNode::cleanup() { } std::shared_ptr RecorderAdapterNode::processNode( - const std::shared_ptr &processingBus, + const std::shared_ptr &processingBuffer, int framesToProcess) { if (!isInitialized_) { - processingBus->zero(); - return processingBus; + processingBuffer->zero(); + return processingBuffer; } readFrames(framesToProcess); - processingBus->sum(*adapterOutputBus_, ChannelInterpretation::SPEAKERS); - return processingBus; + processingBuffer->sum(*adapterOutputBus_, ChannelInterpretation::SPEAKERS); + return processingBuffer; } void RecorderAdapterNode::readFrames(const size_t framesToRead) { diff --git a/packages/react-native-audio-api/common/cpp/audioapi/core/sources/RecorderAdapterNode.h b/packages/react-native-audio-api/common/cpp/audioapi/core/sources/RecorderAdapterNode.h index 8c2dcbaf1..a3d5aba8f 100644 --- a/packages/react-native-audio-api/common/cpp/audioapi/core/sources/RecorderAdapterNode.h +++ b/packages/react-native-audio-api/common/cpp/audioapi/core/sources/RecorderAdapterNode.h @@ -34,7 +34,7 @@ class RecorderAdapterNode : public AudioNode { protected: std::shared_ptr processNode( - const std::shared_ptr &processingBus, + const std::shared_ptr &processingBuffer, int framesToProcess) override; std::shared_ptr adapterOutputBus_; diff --git a/packages/react-native-audio-api/common/cpp/audioapi/core/sources/StreamerNode.cpp b/packages/react-native-audio-api/common/cpp/audioapi/core/sources/StreamerNode.cpp index 784a8f0e2..f57af1e59 100644 --- a/packages/react-native-audio-api/common/cpp/audioapi/core/sources/StreamerNode.cpp +++ b/packages/react-native-audio-api/common/cpp/audioapi/core/sources/StreamerNode.cpp @@ -109,18 +109,18 @@ bool StreamerNode::initialize(const std::string &input_url) { } std::shared_ptr StreamerNode::processNode( - const std::shared_ptr &processingBus, + const std::shared_ptr &processingBuffer, int framesToProcess) { #if !RN_AUDIO_API_FFMPEG_DISABLED size_t startOffset = 0; size_t offsetLength = 0; std::shared_ptr context = context_.lock(); if (context == nullptr) { - processingBus->zero(); - return processingBus; + processingBuffer->zero(); + return processingBuffer; } updatePlaybackInfo( - processingBus, + processingBuffer, framesToProcess, startOffset, offsetLength, @@ -129,15 +129,15 @@ std::shared_ptr StreamerNode::processNode( isNodeFinished_.store(isFinished(), std::memory_order_release); if (!isPlaying() && !isStopScheduled()) { - processingBus->zero(); - return processingBus; + processingBuffer->zero(); + return processingBuffer; } int bufferRemaining = bufferedBusSize_ - processedSamples_; int alreadyProcessed = 0; if (bufferRemaining < framesToProcess) { if (bufferedBus_ != nullptr) { - processingBus->copy(*bufferedBus_, processedSamples_, 0, bufferRemaining); + processingBuffer->copy(*bufferedBus_, processedSamples_, 0, bufferRemaining); framesToProcess -= bufferRemaining; alreadyProcessed += bufferRemaining; } @@ -152,12 +152,12 @@ std::shared_ptr StreamerNode::processNode( } } if (bufferedBus_ != nullptr) { - processingBus->copy(*bufferedBus_, processedSamples_, alreadyProcessed, framesToProcess); + processingBuffer->copy(*bufferedBus_, processedSamples_, alreadyProcessed, framesToProcess); processedSamples_ += framesToProcess; } #endif // RN_AUDIO_API_FFMPEG_DISABLED - return processingBus; + return processingBuffer; } #if !RN_AUDIO_API_FFMPEG_DISABLED @@ -260,10 +260,8 @@ bool StreamerNode::processFrameWithResampler( return true; } - AudioBuffer buffer = AudioBuffer( - converted_samples, - codecCtx_->ch_layout.nb_channels, - context->getSampleRate()); + AudioBuffer buffer = + AudioBuffer(converted_samples, codecCtx_->ch_layout.nb_channels, context->getSampleRate()); for (int ch = 0; ch < codecCtx_->ch_layout.nb_channels; ch++) { auto *src = reinterpret_cast(resampledData_[ch]); diff --git a/packages/react-native-audio-api/common/cpp/audioapi/core/sources/StreamerNode.h b/packages/react-native-audio-api/common/cpp/audioapi/core/sources/StreamerNode.h index c2f8ce7d2..3c360d21d 100644 --- a/packages/react-native-audio-api/common/cpp/audioapi/core/sources/StreamerNode.h +++ b/packages/react-native-audio-api/common/cpp/audioapi/core/sources/StreamerNode.h @@ -83,7 +83,7 @@ class StreamerNode : public AudioScheduledSourceNode { protected: std::shared_ptr processNode( - const std::shared_ptr &processingBus, + const std::shared_ptr &processingBuffer, int framesToProcess) override; private: diff --git a/packages/react-native-audio-api/common/cpp/audioapi/core/sources/WorkletSourceNode.cpp b/packages/react-native-audio-api/common/cpp/audioapi/core/sources/WorkletSourceNode.cpp index 5fdad711c..8637ee776 100644 --- a/packages/react-native-audio-api/common/cpp/audioapi/core/sources/WorkletSourceNode.cpp +++ b/packages/react-native-audio-api/common/cpp/audioapi/core/sources/WorkletSourceNode.cpp @@ -20,11 +20,11 @@ WorkletSourceNode::WorkletSourceNode( } std::shared_ptr WorkletSourceNode::processNode( - const std::shared_ptr &processingBus, + const std::shared_ptr &processingBuffer, int framesToProcess) { if (isUnscheduled() || isFinished() || !isEnabled()) { - processingBus->zero(); - return processingBus; + processingBuffer->zero(); + return processingBuffer; } size_t startOffset = 0; @@ -32,11 +32,11 @@ std::shared_ptr WorkletSourceNode::processNode( std::shared_ptr context = context_.lock(); if (context == nullptr) { - processingBus->zero(); - return processingBus; + processingBuffer->zero(); + return processingBuffer; } updatePlaybackInfo( - processingBus, + processingBuffer, framesToProcess, startOffset, nonSilentFramesToProcess, @@ -44,11 +44,11 @@ std::shared_ptr WorkletSourceNode::processNode( context->getCurrentSampleFrame()); if (nonSilentFramesToProcess == 0) { - processingBus->zero(); - return processingBus; + processingBuffer->zero(); + return processingBuffer; } - size_t outputChannelCount = processingBus->getNumberOfChannels(); + size_t outputChannelCount = processingBuffer->getNumberOfChannels(); auto result = workletRunner_.executeOnRuntimeSync( [this, nonSilentFramesToProcess, startOffset, time = context->getCurrentTime()]( @@ -72,19 +72,19 @@ std::shared_ptr WorkletSourceNode::processNode( // If the worklet execution failed, zero the output // It might happen if the runtime is not available if (!result.has_value()) { - processingBus->zero(); - return processingBus; + processingBuffer->zero(); + return processingBuffer; } // Copy the processed data back to the AudioBuffer for (int i = 0; i < outputChannelCount; ++i) { - processingBus->getChannel(i)->copy( + processingBuffer->getChannel(i)->copy( *outputBuffsHandles_[i], 0, startOffset, nonSilentFramesToProcess); } handleStopScheduled(); - return processingBus; + return processingBuffer; } } // namespace audioapi diff --git a/packages/react-native-audio-api/common/cpp/audioapi/core/sources/WorkletSourceNode.h b/packages/react-native-audio-api/common/cpp/audioapi/core/sources/WorkletSourceNode.h index 93b098767..9596f6822 100644 --- a/packages/react-native-audio-api/common/cpp/audioapi/core/sources/WorkletSourceNode.h +++ b/packages/react-native-audio-api/common/cpp/audioapi/core/sources/WorkletSourceNode.h @@ -23,9 +23,9 @@ class WorkletSourceNode : public AudioScheduledSourceNode { protected: std::shared_ptr processNode( - const std::shared_ptr &processingBus, + const std::shared_ptr &processingBuffer, int framesToProcess) override { - return processingBus; + return processingBuffer; } }; #else @@ -38,7 +38,7 @@ class WorkletSourceNode : public AudioScheduledSourceNode { protected: std::shared_ptr processNode( - const std::shared_ptr &processingBus, + const std::shared_ptr &processingBuffer, int framesToProcess) override; private: diff --git a/packages/react-native-audio-api/common/cpp/test/src/AudioScheduledSourceTest.cpp b/packages/react-native-audio-api/common/cpp/test/src/AudioScheduledSourceTest.cpp index 8c09eaa14..f8ce75501 100644 --- a/packages/react-native-audio-api/common/cpp/test/src/AudioScheduledSourceTest.cpp +++ b/packages/react-native-audio-api/common/cpp/test/src/AudioScheduledSourceTest.cpp @@ -33,14 +33,14 @@ class TestableAudioScheduledSourceNode : public AudioScheduledSourceNode { } void updatePlaybackInfo( - const std::shared_ptr &processingBus, + const std::shared_ptr &processingBuffer, int framesToProcess, size_t &startOffset, size_t &nonSilentFramesToProcess, float sampleRate, size_t currentSampleFrame) { AudioScheduledSourceNode::updatePlaybackInfo( - processingBus, + processingBuffer, framesToProcess, startOffset, nonSilentFramesToProcess, @@ -60,15 +60,16 @@ class TestableAudioScheduledSourceNode : public AudioScheduledSourceNode { if (std::shared_ptr context = context_.lock()) { size_t startOffset = 0; size_t nonSilentFramesToProcess = 0; - auto processingBus = std::make_shared(128, 2, static_cast(SAMPLE_RATE)); + auto processingBuffer = + std::make_shared(128, 2, static_cast(SAMPLE_RATE)); updatePlaybackInfo( - processingBus, + processingBuffer, frames, startOffset, nonSilentFramesToProcess, context->getSampleRate(), context->getCurrentSampleFrame()); - context->getDestination()->renderAudio(processingBus, frames); + context->getDestination()->renderAudio(processingBuffer, frames); } } }; diff --git a/packages/react-native-audio-api/common/cpp/test/src/ConstantSourceTest.cpp b/packages/react-native-audio-api/common/cpp/test/src/ConstantSourceTest.cpp index 85e7b4ad4..90ad1ce32 100644 --- a/packages/react-native-audio-api/common/cpp/test/src/ConstantSourceTest.cpp +++ b/packages/react-native-audio-api/common/cpp/test/src/ConstantSourceTest.cpp @@ -34,9 +34,9 @@ class TestableConstantSourceNode : public ConstantSourceNode { } std::shared_ptr processNode( - const std::shared_ptr &processingBus, + const std::shared_ptr &processingBuffer, int framesToProcess) override { - return ConstantSourceNode::processNode(processingBus, framesToProcess); + return ConstantSourceNode::processNode(processingBuffer, framesToProcess); } }; diff --git a/packages/react-native-audio-api/common/cpp/test/src/DelayTest.cpp b/packages/react-native-audio-api/common/cpp/test/src/DelayTest.cpp index 3ea5f2b54..2da57a8c2 100644 --- a/packages/react-native-audio-api/common/cpp/test/src/DelayTest.cpp +++ b/packages/react-native-audio-api/common/cpp/test/src/DelayTest.cpp @@ -34,9 +34,9 @@ class TestableDelayNode : public DelayNode { } std::shared_ptr processNode( - const std::shared_ptr &processingBus, + const std::shared_ptr &processingBuffer, int framesToProcess) override { - return DelayNode::processNode(processingBus, framesToProcess); + return DelayNode::processNode(processingBuffer, framesToProcess); } }; diff --git a/packages/react-native-audio-api/common/cpp/test/src/GainTest.cpp b/packages/react-native-audio-api/common/cpp/test/src/GainTest.cpp index 1accf6785..2303795f5 100644 --- a/packages/react-native-audio-api/common/cpp/test/src/GainTest.cpp +++ b/packages/react-native-audio-api/common/cpp/test/src/GainTest.cpp @@ -34,9 +34,9 @@ class TestableGainNode : public GainNode { } std::shared_ptr processNode( - const std::shared_ptr &processingBus, + const std::shared_ptr &processingBuffer, int framesToProcess) override { - return GainNode::processNode(processingBus, framesToProcess); + return GainNode::processNode(processingBuffer, framesToProcess); } }; diff --git a/packages/react-native-audio-api/common/cpp/test/src/StereoPannerTest.cpp b/packages/react-native-audio-api/common/cpp/test/src/StereoPannerTest.cpp index 18d935e9f..6bdc2160e 100644 --- a/packages/react-native-audio-api/common/cpp/test/src/StereoPannerTest.cpp +++ b/packages/react-native-audio-api/common/cpp/test/src/StereoPannerTest.cpp @@ -34,9 +34,9 @@ class TestableStereoPannerNode : public StereoPannerNode { } std::shared_ptr processNode( - const std::shared_ptr &processingBus, + const std::shared_ptr &processingBuffer, int framesToProcess) override { - return StereoPannerNode::processNode(processingBus, framesToProcess); + return StereoPannerNode::processNode(processingBuffer, framesToProcess); } }; diff --git a/packages/react-native-audio-api/common/cpp/test/src/core/effects/WaveShaperNodeTest.cpp b/packages/react-native-audio-api/common/cpp/test/src/core/effects/WaveShaperNodeTest.cpp index 474e953d0..f0d52d2ce 100644 --- a/packages/react-native-audio-api/common/cpp/test/src/core/effects/WaveShaperNodeTest.cpp +++ b/packages/react-native-audio-api/common/cpp/test/src/core/effects/WaveShaperNodeTest.cpp @@ -36,9 +36,9 @@ class TestableWaveShaperNode : public WaveShaperNode { } std::shared_ptr processNode( - const std::shared_ptr &processingBus, + const std::shared_ptr &processingBuffer, int framesToProcess) override { - return WaveShaperNode::processNode(processingBus, framesToProcess); + return WaveShaperNode::processNode(processingBuffer, framesToProcess); } std::shared_ptr testCurve_; From a39e9553b668875ff543d90cdc8a229ead97b07e Mon Sep 17 00:00:00 2001 From: maciejmakowski2003 Date: Wed, 4 Feb 2026 20:36:48 +0100 Subject: [PATCH 21/30] refactor: renaming --- .../android/core/utils/AudioDecoder.cpp | 13 +++---- .../BaseAudioContextHostObject.cpp | 9 ++--- .../audioapi/HostObjects/utils/NodeOptions.h | 2 +- .../HostObjects/utils/NodeOptionsParser.h | 2 +- .../common/cpp/audioapi/core/AudioNode.cpp | 16 ++++----- .../common/cpp/audioapi/core/AudioNode.h | 2 +- .../common/cpp/audioapi/core/AudioParam.cpp | 17 ++++----- .../common/cpp/audioapi/core/AudioParam.h | 2 +- .../cpp/audioapi/core/OfflineAudioContext.cpp | 6 ++-- .../audioapi/core/analysis/AnalyserNode.cpp | 6 ++-- .../audioapi/core/effects/ConvolverNode.cpp | 23 ++++++------ .../cpp/audioapi/core/effects/DelayNode.cpp | 13 ++++--- .../core/effects/StereoPannerNode.cpp | 6 ++-- .../cpp/audioapi/core/effects/WorkletNode.cpp | 8 ++--- .../cpp/audioapi/core/effects/WorkletNode.h | 2 +- .../core/effects/WorkletProcessingNode.cpp | 2 +- .../core/sources/AudioBufferSourceNode.cpp | 2 +- .../audioapi/core/sources/OscillatorNode.cpp | 2 +- .../core/sources/RecorderAdapterNode.cpp | 2 +- .../core/sources/RecorderAdapterNode.h | 2 +- .../audioapi/core/sources/StreamerNode.cpp | 6 ++-- .../cpp/audioapi/core/sources/StreamerNode.h | 16 ++++----- .../core/utils/AudioRecorderCallback.cpp | 12 ++++--- .../core/utils/AudioRecorderCallback.h | 2 +- .../audioapi/core/utils/AudioStretcher.cpp | 6 ++-- .../audioapi/libs/ffmpeg/FFmpegDecoding.cpp | 6 ++-- .../common/cpp/audioapi/utils/AudioBuffer.cpp | 36 +++++++++---------- .../cpp/audioapi/utils/CircularAudioArray.cpp | 1 - .../cpp/test/src/ConstantSourceTest.cpp | 6 ++-- .../common/cpp/test/src/DelayTest.cpp | 30 ++++++++-------- .../common/cpp/test/src/GainTest.cpp | 18 +++++----- .../common/cpp/test/src/StereoPannerTest.cpp | 28 +++++++-------- .../src/core/effects/WaveShaperNodeTest.cpp | 8 ++--- .../ios/audioapi/ios/core/IOSAudioPlayer.h | 2 +- .../ios/audioapi/ios/core/IOSAudioPlayer.mm | 15 ++++---- .../ios/audioapi/ios/core/IOSAudioRecorder.h | 1 - .../audioapi/ios/core/utils/AudioDecoder.mm | 12 +++---- 37 files changed, 174 insertions(+), 168 deletions(-) diff --git a/packages/react-native-audio-api/android/src/main/cpp/audioapi/android/core/utils/AudioDecoder.cpp b/packages/react-native-audio-api/android/src/main/cpp/audioapi/android/core/utils/AudioDecoder.cpp index c27e69074..c08e4ba30 100644 --- a/packages/react-native-audio-api/android/src/main/cpp/audioapi/android/core/utils/AudioDecoder.cpp +++ b/packages/react-native-audio-api/android/src/main/cpp/audioapi/android/core/utils/AudioDecoder.cpp @@ -53,15 +53,16 @@ std::shared_ptr AudioDecoder::makeAudioBufferFromFloatBuffer( } auto outputFrames = buffer.size() / outputChannels; - auto audioBus = std::make_shared(outputFrames, outputChannels, outputSampleRate); + auto audioBuffer = std::make_shared(outputFrames, outputChannels, outputSampleRate); for (int ch = 0; ch < outputChannels; ++ch) { - auto channelData = audioBus->getChannel(ch)->span(); + auto channelData = audioBuffer->getChannel(ch)->span(); for (int i = 0; i < outputFrames; ++i) { channelData[i] = buffer[i * outputChannels + ch]; } } - return audioBus; + + return audioBuffer; } std::shared_ptr AudioDecoder::decodeWithFilePath( @@ -161,11 +162,11 @@ std::shared_ptr AudioDecoder::decodeWithPCMInBase64( const auto uint8Data = reinterpret_cast(decodedData.data()); size_t numFramesDecoded = decodedData.size() / (inputChannelCount * sizeof(int16_t)); - auto audioBus = + auto audioBuffer = std::make_shared(numFramesDecoded, inputChannelCount, inputSampleRate); for (int ch = 0; ch < inputChannelCount; ++ch) { - auto channelData = audioBus->getChannel(ch)->span(); + auto channelData = audioBuffer->getChannel(ch)->span(); for (size_t i = 0; i < numFramesDecoded; ++i) { size_t offset; @@ -180,7 +181,7 @@ std::shared_ptr AudioDecoder::decodeWithPCMInBase64( channelData[i] = uint8ToFloat(uint8Data[offset], uint8Data[offset + 1]); } } - return audioBus; + return audioBuffer; } } // namespace audioapi diff --git a/packages/react-native-audio-api/common/cpp/audioapi/HostObjects/BaseAudioContextHostObject.cpp b/packages/react-native-audio-api/common/cpp/audioapi/HostObjects/BaseAudioContextHostObject.cpp index aa9978d2a..4bf7dd070 100644 --- a/packages/react-native-audio-api/common/cpp/audioapi/HostObjects/BaseAudioContextHostObject.cpp +++ b/packages/react-native-audio-api/common/cpp/audioapi/HostObjects/BaseAudioContextHostObject.cpp @@ -1,6 +1,4 @@ #include -#include -#include #include #include #include @@ -11,6 +9,8 @@ #include #include #include +#include +#include #include #include #include @@ -78,7 +78,8 @@ JSI_PROPERTY_GETTER_IMPL(BaseAudioContextHostObject, destination) { } JSI_PROPERTY_GETTER_IMPL(BaseAudioContextHostObject, state) { - return jsi::String::createFromUtf8(runtime, js_enum_parser::contextStateToString(context_->getState())); + return jsi::String::createFromUtf8( + runtime, js_enum_parser::contextStateToString(context_->getState())); } JSI_PROPERTY_GETTER_IMPL(BaseAudioContextHostObject, sampleRate) { @@ -309,7 +310,7 @@ JSI_HOST_FUNCTION_IMPL(BaseAudioContextHostObject, createConvolver) { const auto convolverOptions = audioapi::option_parser::parseConvolverOptions(runtime, options); auto convolverHostObject = std::make_shared(context_, convolverOptions); auto jsiObject = jsi::Object::createFromHostObject(runtime, convolverHostObject); - if (convolverOptions.bus != nullptr) { + if (convolverOptions.buffer != nullptr) { auto bufferHostObject = options.getProperty(runtime, "buffer") .getObject(runtime) .asHostObject(runtime); diff --git a/packages/react-native-audio-api/common/cpp/audioapi/HostObjects/utils/NodeOptions.h b/packages/react-native-audio-api/common/cpp/audioapi/HostObjects/utils/NodeOptions.h index e6d7cf68a..17a3a2bda 100644 --- a/packages/react-native-audio-api/common/cpp/audioapi/HostObjects/utils/NodeOptions.h +++ b/packages/react-native-audio-api/common/cpp/audioapi/HostObjects/utils/NodeOptions.h @@ -31,7 +31,7 @@ struct StereoPannerOptions : AudioNodeOptions { }; struct ConvolverOptions : AudioNodeOptions { - std::shared_ptr bus; + std::shared_ptr buffer; bool disableNormalization; }; diff --git a/packages/react-native-audio-api/common/cpp/audioapi/HostObjects/utils/NodeOptionsParser.h b/packages/react-native-audio-api/common/cpp/audioapi/HostObjects/utils/NodeOptionsParser.h index 0810d684e..595a13b8b 100644 --- a/packages/react-native-audio-api/common/cpp/audioapi/HostObjects/utils/NodeOptionsParser.h +++ b/packages/react-native-audio-api/common/cpp/audioapi/HostObjects/utils/NodeOptionsParser.h @@ -63,7 +63,7 @@ ConvolverOptions parseConvolverOptions(jsi::Runtime &runtime, const jsi::Object auto bufferHostObject = optionsObject.getProperty(runtime, "buffer") .getObject(runtime) .asHostObject(runtime); - options.bus = bufferHostObject->audioBuffer_; + options.buffer = bufferHostObject->audioBuffer_; } return options; } diff --git a/packages/react-native-audio-api/common/cpp/audioapi/core/AudioNode.cpp b/packages/react-native-audio-api/common/cpp/audioapi/core/AudioNode.cpp index 95aae1923..f0cc01e1c 100644 --- a/packages/react-native-audio-api/common/cpp/audioapi/core/AudioNode.cpp +++ b/packages/react-native-audio-api/common/cpp/audioapi/core/AudioNode.cpp @@ -12,7 +12,7 @@ namespace audioapi { AudioNode::AudioNode(const std::shared_ptr &context) : context_(context) { - audioBus_ = + audioBuffer_ = std::make_shared(RENDER_QUANTUM_SIZE, channelCount_, context->getSampleRate()); } @@ -23,7 +23,7 @@ AudioNode::AudioNode( channelCount_(options.channelCount), channelCountMode_(options.channelCountMode), channelInterpretation_(options.channelInterpretation) { - audioBus_ = + audioBuffer_ = std::make_shared(RENDER_QUANTUM_SIZE, channelCount_, context->getSampleRate()); } @@ -129,16 +129,16 @@ std::shared_ptr AudioNode::processAudio( } if (checkIsAlreadyProcessed && isAlreadyProcessed()) { - return audioBus_; + return audioBuffer_; } - // Process inputs and return the bus with the most channels. + // Process inputs and return the buffer with the most channels. auto processingBuffer = processInputs(outputBus, framesToProcess, checkIsAlreadyProcessed); // Apply channel count mode. processingBuffer = applyChannelCountMode(processingBuffer); - // Mix all input buses into the processing bus. + // Mix all input buffers into the processing buffer. mixInputsBuses(processingBuffer); assert(processingBuffer != nullptr); @@ -170,7 +170,7 @@ std::shared_ptr AudioNode::processInputs( const std::shared_ptr &outputBus, int framesToProcess, bool checkIsAlreadyProcessed) { - auto processingBuffer = audioBus_; + auto processingBuffer = audioBuffer_; processingBuffer->zero(); int maxNumberOfChannels = 0; @@ -199,14 +199,14 @@ std::shared_ptr AudioNode::applyChannelCountMode( // If the channelCountMode is EXPLICIT, the node should output the number of // channels specified by the channelCount. if (channelCountMode_ == ChannelCountMode::EXPLICIT) { - return audioBus_; + return audioBuffer_; } // If the channelCountMode is CLAMPED_MAX, the node should output the maximum // number of channels clamped to channelCount. if (channelCountMode_ == ChannelCountMode::CLAMPED_MAX && processingBuffer->getNumberOfChannels() >= channelCount_) { - return audioBus_; + return audioBuffer_; } return processingBuffer; diff --git a/packages/react-native-audio-api/common/cpp/audioapi/core/AudioNode.h b/packages/react-native-audio-api/common/cpp/audioapi/core/AudioNode.h index 91e4ab675..37578ff8c 100644 --- a/packages/react-native-audio-api/common/cpp/audioapi/core/AudioNode.h +++ b/packages/react-native-audio-api/common/cpp/audioapi/core/AudioNode.h @@ -53,7 +53,7 @@ class AudioNode : public std::enable_shared_from_this { friend class DelayNodeHostObject; std::weak_ptr context_; - std::shared_ptr audioBus_; + std::shared_ptr audioBuffer_; int numberOfInputs_ = 1; int numberOfOutputs_ = 1; diff --git a/packages/react-native-audio-api/common/cpp/audioapi/core/AudioParam.cpp b/packages/react-native-audio-api/common/cpp/audioapi/core/AudioParam.cpp index 737e4507f..a2af0c5b5 100644 --- a/packages/react-native-audio-api/common/cpp/audioapi/core/AudioParam.cpp +++ b/packages/react-native-audio-api/common/cpp/audioapi/core/AudioParam.cpp @@ -24,7 +24,8 @@ AudioParam::AudioParam( endTime_(0), startValue_(defaultValue), endValue_(defaultValue), - audioBus_(std::make_shared(RENDER_QUANTUM_SIZE, 1, context->getSampleRate())) { + audioBuffer_( + std::make_shared(RENDER_QUANTUM_SIZE, 1, context->getSampleRate())) { inputBuses_.reserve(4); inputNodes_.reserve(4); // Default calculation function just returns the static value @@ -256,13 +257,13 @@ std::shared_ptr AudioParam::calculateInputs( std::shared_ptr AudioParam::processARateParam(int framesToProcess, double time) { processScheduledEvents(); - auto processingBuffer = calculateInputs(audioBus_, framesToProcess); + auto processingBuffer = calculateInputs(audioBuffer_, framesToProcess); std::shared_ptr context = context_.lock(); if (context == nullptr) return processingBuffer; float sampleRate = context->getSampleRate(); - auto busData = processingBuffer->getChannel(0)->span(); + auto bufferData = processingBuffer->getChannel(0)->span(); float timeCache = time; float timeStep = 1.0f / sampleRate; float sample = 0.0f; @@ -270,15 +271,15 @@ std::shared_ptr AudioParam::processARateParam(int framesToProcess, // Add automated parameter value to each sample for (size_t i = 0; i < framesToProcess; i++, timeCache += timeStep) { sample = getValueAtTime(timeCache); - busData[i] += sample; + bufferData[i] += sample; } - // processingBuffer is a mono bus containing per-sample parameter values + // processingBuffer is a mono buffer containing per-sample parameter values return processingBuffer; } float AudioParam::processKRateParam(int framesToProcess, double time) { processScheduledEvents(); - auto processingBuffer = calculateInputs(audioBus_, framesToProcess); + auto processingBuffer = calculateInputs(audioBuffer_, framesToProcess); // Return block-rate parameter value plus first sample of input modulation return processingBuffer->getChannel(0)->span()[0] + getValueAtTime(time); @@ -296,7 +297,7 @@ void AudioParam::processInputs( continue; } - // Process this input node and store its output bus + // Process this input node and store its output buffer auto inputBus = inputNode->processAudio(outputBus, framesToProcess, checkIsAlreadyProcessed); inputBuses_.emplace_back(inputBus); } @@ -305,7 +306,7 @@ void AudioParam::processInputs( void AudioParam::mixInputsBuses(const std::shared_ptr &processingBuffer) { assert(processingBuffer != nullptr); - // Sum all input buses into the processing bus + // Sum all input buffers into the processing buffer for (auto it = inputBuses_.begin(), end = inputBuses_.end(); it != end; ++it) { processingBuffer->sum(**it, ChannelInterpretation::SPEAKERS); } diff --git a/packages/react-native-audio-api/common/cpp/audioapi/core/AudioParam.h b/packages/react-native-audio-api/common/cpp/audioapi/core/AudioParam.h index ed7f6fb66..37eb209d2 100644 --- a/packages/react-native-audio-api/common/cpp/audioapi/core/AudioParam.h +++ b/packages/react-native-audio-api/common/cpp/audioapi/core/AudioParam.h @@ -111,7 +111,7 @@ class AudioParam { // Input modulation system std::vector inputNodes_; - std::shared_ptr audioBus_; + std::shared_ptr audioBuffer_; std::vector> inputBuses_; /// @brief Get the end time of the parameter queue. diff --git a/packages/react-native-audio-api/common/cpp/audioapi/core/OfflineAudioContext.cpp b/packages/react-native-audio-api/common/cpp/audioapi/core/OfflineAudioContext.cpp index 79cb330cf..f8d20a6db 100644 --- a/packages/react-native-audio-api/common/cpp/audioapi/core/OfflineAudioContext.cpp +++ b/packages/react-native-audio-api/common/cpp/audioapi/core/OfflineAudioContext.cpp @@ -64,7 +64,7 @@ void OfflineAudioContext::renderAudio() { setState(ContextState::RUNNING); std::thread([this]() { - auto audioBus = + auto audioBuffer = std::make_shared(RENDER_QUANTUM_SIZE, numberOfChannels_, getSampleRate()); while (currentSampleFrame_ < length_) { @@ -72,9 +72,9 @@ void OfflineAudioContext::renderAudio() { int framesToProcess = std::min(static_cast(length_ - currentSampleFrame_), RENDER_QUANTUM_SIZE); - destination_->renderAudio(audioBus, framesToProcess); + destination_->renderAudio(audioBuffer, framesToProcess); - resultBus_->copy(*audioBus, 0, currentSampleFrame_, framesToProcess); + resultBus_->copy(*audioBuffer, 0, currentSampleFrame_, framesToProcess); currentSampleFrame_ += framesToProcess; diff --git a/packages/react-native-audio-api/common/cpp/audioapi/core/analysis/AnalyserNode.cpp b/packages/react-native-audio-api/common/cpp/audioapi/core/analysis/AnalyserNode.cpp index 5cd6dd660..99d07d7e2 100644 --- a/packages/react-native-audio-api/common/cpp/audioapi/core/analysis/AnalyserNode.cpp +++ b/packages/react-native-audio-api/common/cpp/audioapi/core/analysis/AnalyserNode.cpp @@ -94,7 +94,7 @@ void AnalyserNode::getFloatFrequencyData(float *data, int length) { auto magnitudeSpan = magnitudeArray_->span(); for (int i = 0; i < length; i++) { - data[i] = dsp::linearToDecibels(magnitudeSpan[i]); + data[i] = dsp::linearToDecibels(magnitudeSpan[i]); } } @@ -157,9 +157,9 @@ std::shared_ptr AnalyserNode::processNode( // Analyser should behave like a sniffer node, it should not modify the // processingBuffer but instead copy the data to its own input buffer. - // Down mix the input bus to mono + // Down mix the input buffer to mono downMixBus_->copy(*processingBuffer); - // Copy the down mixed bus to the input buffer (circular buffer) + // Copy the down mixed buffer to the input buffer (circular buffer) inputArray_->push_back(*downMixBus_->getChannel(0), framesToProcess, true); shouldDoFFTAnalysis_ = true; diff --git a/packages/react-native-audio-api/common/cpp/audioapi/core/effects/ConvolverNode.cpp b/packages/react-native-audio-api/common/cpp/audioapi/core/effects/ConvolverNode.cpp index 1b72d49f4..1deff6a10 100644 --- a/packages/react-native-audio-api/common/cpp/audioapi/core/effects/ConvolverNode.cpp +++ b/packages/react-native-audio-api/common/cpp/audioapi/core/effects/ConvolverNode.cpp @@ -25,8 +25,8 @@ ConvolverNode::ConvolverNode( intermediateBuffer_(nullptr), buffer_(nullptr), internalBuffer_(nullptr) { - setBuffer(options.bus); - audioBus_ = + setBuffer(options.buffer); + audioBuffer_ = std::make_shared(RENDER_QUANTUM_SIZE, channelCount_, context->getSampleRate()); requiresTailProcessing_ = true; isInitialized_ = true; @@ -95,7 +95,7 @@ std::shared_ptr ConvolverNode::processInputs( return AudioNode::processInputs(outputBus, 0, false); } -// processing pipeline: processingBuffer -> intermediateBuffer_ -> audioBus_ (mixing +// processing pipeline: processingBuffer -> intermediateBuffer_ -> audioBuffer_ (mixing // with intermediateBuffer_) std::shared_ptr ConvolverNode::processNode( const std::shared_ptr &processingBuffer, @@ -112,13 +112,13 @@ std::shared_ptr ConvolverNode::processNode( } if (internalBufferIndex_ < framesToProcess) { performConvolution(processingBuffer); // result returned to intermediateBuffer_ - audioBus_->sum(*intermediateBuffer_); + audioBuffer_->sum(*intermediateBuffer_); - internalBuffer_->copy(*audioBus_, 0, internalBufferIndex_, RENDER_QUANTUM_SIZE); + internalBuffer_->copy(*audioBuffer_, 0, internalBufferIndex_, RENDER_QUANTUM_SIZE); internalBufferIndex_ += RENDER_QUANTUM_SIZE; } - audioBus_->zero(); - audioBus_->copy(*internalBuffer_, 0, 0, framesToProcess); + audioBuffer_->zero(); + audioBuffer_->copy(*internalBuffer_, 0, 0, framesToProcess); int remainingFrames = internalBufferIndex_ - framesToProcess; if (remainingFrames > 0) { for (int ch = 0; ch < internalBuffer_->getNumberOfChannels(); ++ch) { @@ -128,11 +128,11 @@ std::shared_ptr ConvolverNode::processNode( internalBufferIndex_ -= framesToProcess; - for (int i = 0; i < audioBus_->getNumberOfChannels(); ++i) { - audioBus_->getChannel(i)->scale(scaleFactor_); + for (int i = 0; i < audioBuffer_->getNumberOfChannels(); ++i) { + audioBuffer_->getChannel(i)->scale(scaleFactor_); } - return audioBus_; + return audioBuffer_; } void ConvolverNode::calculateNormalizationScale() { @@ -164,7 +164,8 @@ void ConvolverNode::performConvolution(const std::shared_ptr &proce if (processingBuffer->getNumberOfChannels() == 1) { for (int i = 0; i < convolvers_.size(); ++i) { threadPool_->schedule([&, i] { - convolvers_[i].process(*processingBuffer->getChannel(0), *intermediateBuffer_->getChannel(i)); + convolvers_[i].process( + *processingBuffer->getChannel(0), *intermediateBuffer_->getChannel(i)); }); } } else if (processingBuffer->getNumberOfChannels() == 2) { diff --git a/packages/react-native-audio-api/common/cpp/audioapi/core/effects/DelayNode.cpp b/packages/react-native-audio-api/common/cpp/audioapi/core/effects/DelayNode.cpp index 817a41239..f2b287446 100644 --- a/packages/react-native-audio-api/common/cpp/audioapi/core/effects/DelayNode.cpp +++ b/packages/react-native-audio-api/common/cpp/audioapi/core/effects/DelayNode.cpp @@ -78,8 +78,8 @@ void DelayNode::delayBufferOperation( // delay buffer always has channelCount_ channels // processing is split into two parts -// 1. writing to delay buffer (mixing if needed) from processing bus -// 2. reading from delay buffer to processing bus (mixing if needed) with delay +// 1. writing to delay buffer (mixing if needed) from processing buffer +// 2. reading from delay buffer to processing buffer (mixing if needed) with delay std::shared_ptr DelayNode::processNode( const std::shared_ptr &processingBuffer, int framesToProcess) { @@ -91,7 +91,8 @@ std::shared_ptr DelayNode::processNode( return processingBuffer; } - delayBufferOperation(processingBuffer, framesToProcess, readIndex_, DelayNode::BufferAction::READ); + delayBufferOperation( + processingBuffer, framesToProcess, readIndex_, DelayNode::BufferAction::READ); remainingFrames_ -= framesToProcess; return processingBuffer; } @@ -103,8 +104,10 @@ std::shared_ptr DelayNode::processNode( auto delayTime = delayTimeParam_->processKRateParam(framesToProcess, context->getCurrentTime()); size_t writeIndex = static_cast(readIndex_ + delayTime * context->getSampleRate()) % delayBuffer_->getSize(); - delayBufferOperation(processingBuffer, framesToProcess, writeIndex, DelayNode::BufferAction::WRITE); - delayBufferOperation(processingBuffer, framesToProcess, readIndex_, DelayNode::BufferAction::READ); + delayBufferOperation( + processingBuffer, framesToProcess, writeIndex, DelayNode::BufferAction::WRITE); + delayBufferOperation( + processingBuffer, framesToProcess, readIndex_, DelayNode::BufferAction::READ); return processingBuffer; } diff --git a/packages/react-native-audio-api/common/cpp/audioapi/core/effects/StereoPannerNode.cpp b/packages/react-native-audio-api/common/cpp/audioapi/core/effects/StereoPannerNode.cpp index 8accf2e4d..879a6ea0b 100644 --- a/packages/react-native-audio-api/common/cpp/audioapi/core/effects/StereoPannerNode.cpp +++ b/packages/react-native-audio-api/common/cpp/audioapi/core/effects/StereoPannerNode.cpp @@ -33,8 +33,8 @@ std::shared_ptr StereoPannerNode::processNode( auto panParamValues = panParam_->processARateParam(framesToProcess, time)->getChannel(0)->span(); - auto outputLeft = audioBus_->getChannelByType(AudioBuffer::ChannelLeft)->span(); - auto outputRight = audioBus_->getChannelByType(AudioBuffer::ChannelRight)->span(); + auto outputLeft = audioBuffer_->getChannelByType(AudioBuffer::ChannelLeft)->span(); + auto outputRight = audioBuffer_->getChannelByType(AudioBuffer::ChannelRight)->span(); // Input is mono if (processingBuffer->getNumberOfChannels() == 1) { @@ -74,7 +74,7 @@ std::shared_ptr StereoPannerNode::processNode( } } - return audioBus_; + return audioBuffer_; } } // namespace audioapi diff --git a/packages/react-native-audio-api/common/cpp/audioapi/core/effects/WorkletNode.cpp b/packages/react-native-audio-api/common/cpp/audioapi/core/effects/WorkletNode.cpp index fcce0f364..4cbdb79e8 100644 --- a/packages/react-native-audio-api/common/cpp/audioapi/core/effects/WorkletNode.cpp +++ b/packages/react-native-audio-api/common/cpp/audioapi/core/effects/WorkletNode.cpp @@ -13,7 +13,7 @@ WorkletNode::WorkletNode( WorkletsRunner &&runtime) : AudioNode(context), workletRunner_(std::move(runtime)), - bus_( + buffer_( std::make_shared(bufferLength, inputChannelCount, context->getSampleRate())), bufferLength_(bufferLength), inputChannelCount_(inputChannelCount), @@ -35,7 +35,7 @@ std::shared_ptr WorkletNode::processNode( /// here we copy /// to [curBuffIndex_, curBuffIndex_ + shouldProcess] /// from [processed, processed + shouldProcess] - bus_->copy(*processingBuffer, processed, curBuffIndex_, shouldProcess); + buffer_->copy(*processingBuffer, processed, curBuffIndex_, shouldProcess); processed += shouldProcess; curBuffIndex_ += shouldProcess; @@ -51,14 +51,14 @@ std::shared_ptr WorkletNode::processNode( auto jsArray = jsi::Array(uiRuntimeRaw, channelCount_); for (int ch = 0; ch < channelCount_; ch++) { auto sharedAudioArray = std::make_shared(bufferLength_); - sharedAudioArray->copy(*bus_->getChannel(ch)); + sharedAudioArray->copy(*buffer_->getChannel(ch)); auto sharedAudioArraySize = sharedAudioArray->size(); auto arrayBuffer = jsi::ArrayBuffer(uiRuntimeRaw, std::move(sharedAudioArray)); arrayBuffer.setExternalMemoryPressure(uiRuntimeRaw, sharedAudioArraySize); jsArray.setValueAtIndex(uiRuntimeRaw, ch, std::move(arrayBuffer)); } - bus_->zero(); + buffer_->zero(); /// Call the worklet workletRunner_.callUnsafe( diff --git a/packages/react-native-audio-api/common/cpp/audioapi/core/effects/WorkletNode.h b/packages/react-native-audio-api/common/cpp/audioapi/core/effects/WorkletNode.h index 9a1afb11f..0523f99fd 100644 --- a/packages/react-native-audio-api/common/cpp/audioapi/core/effects/WorkletNode.h +++ b/packages/react-native-audio-api/common/cpp/audioapi/core/effects/WorkletNode.h @@ -51,7 +51,7 @@ class WorkletNode : public AudioNode { private: WorkletsRunner workletRunner_; - std::shared_ptr bus_; + std::shared_ptr buffer_; /// @brief Length of the byte buffer that will be passed to the AudioArrayBuffer size_t bufferLength_; diff --git a/packages/react-native-audio-api/common/cpp/audioapi/core/effects/WorkletProcessingNode.cpp b/packages/react-native-audio-api/common/cpp/audioapi/core/effects/WorkletProcessingNode.cpp index 9768bc6c5..7aa0ca58e 100644 --- a/packages/react-native-audio-api/common/cpp/audioapi/core/effects/WorkletProcessingNode.cpp +++ b/packages/react-native-audio-api/common/cpp/audioapi/core/effects/WorkletProcessingNode.cpp @@ -63,7 +63,7 @@ std::shared_ptr WorkletProcessingNode::processNode( jsi::Value(rt, time)); }); - // Copy processed output data back to the processing bus or zero on failure + // Copy processed output data back to the processing buffer or zero on failure for (int ch = 0; ch < channelCount; ch++) { auto channelData = processingBuffer->getChannel(ch); diff --git a/packages/react-native-audio-api/common/cpp/audioapi/core/sources/AudioBufferSourceNode.cpp b/packages/react-native-audio-api/common/cpp/audioapi/core/sources/AudioBufferSourceNode.cpp index d27729fad..ddb17bc1c 100644 --- a/packages/react-native-audio-api/common/cpp/audioapi/core/sources/AudioBufferSourceNode.cpp +++ b/packages/react-native-audio-api/common/cpp/audioapi/core/sources/AudioBufferSourceNode.cpp @@ -103,7 +103,7 @@ void AudioBufferSourceNode::setBuffer(const std::shared_ptr &buffer } else { alignedBus_ = std::make_shared(*buffer_); } - audioBus_ = + audioBuffer_ = std::make_shared(RENDER_QUANTUM_SIZE, channelCount_, context->getSampleRate()); playbackRateBus_ = std::make_shared( RENDER_QUANTUM_SIZE * 3, channelCount_, context->getSampleRate()); diff --git a/packages/react-native-audio-api/common/cpp/audioapi/core/sources/OscillatorNode.cpp b/packages/react-native-audio-api/common/cpp/audioapi/core/sources/OscillatorNode.cpp index e9340f7f5..cfab566fc 100644 --- a/packages/react-native-audio-api/common/cpp/audioapi/core/sources/OscillatorNode.cpp +++ b/packages/react-native-audio-api/common/cpp/audioapi/core/sources/OscillatorNode.cpp @@ -27,7 +27,7 @@ OscillatorNode::OscillatorNode( periodicWave_ = context->getBasicWaveForm(type_); } - audioBus_ = std::make_shared(RENDER_QUANTUM_SIZE, 1, context->getSampleRate()); + audioBuffer_ = std::make_shared(RENDER_QUANTUM_SIZE, 1, context->getSampleRate()); isInitialized_ = true; } diff --git a/packages/react-native-audio-api/common/cpp/audioapi/core/sources/RecorderAdapterNode.cpp b/packages/react-native-audio-api/common/cpp/audioapi/core/sources/RecorderAdapterNode.cpp index 096f20b40..73bac391d 100644 --- a/packages/react-native-audio-api/common/cpp/audioapi/core/sources/RecorderAdapterNode.cpp +++ b/packages/react-native-audio-api/common/cpp/audioapi/core/sources/RecorderAdapterNode.cpp @@ -32,7 +32,7 @@ void RecorderAdapterNode::init(size_t bufferSize, int channelCount) { // This assumes that the sample rate is the same in audio context and recorder. // (recorder is not enforcing any sample rate on the system*). This means that only - // channel mixing might be required. To do so, we create an output bus with + // channel mixing might be required. To do so, we create an output buffer with // the desired channel count and will take advantage of the AudioBuffer sum method. // // * any allocations required by the recorder (including this method) are during recording start diff --git a/packages/react-native-audio-api/common/cpp/audioapi/core/sources/RecorderAdapterNode.h b/packages/react-native-audio-api/common/cpp/audioapi/core/sources/RecorderAdapterNode.h index a3d5aba8f..6d98e90a2 100644 --- a/packages/react-native-audio-api/common/cpp/audioapi/core/sources/RecorderAdapterNode.h +++ b/packages/react-native-audio-api/common/cpp/audioapi/core/sources/RecorderAdapterNode.h @@ -39,7 +39,7 @@ class RecorderAdapterNode : public AudioNode { std::shared_ptr adapterOutputBus_; private: - /// @brief Read audio frames from the recorder's internal circular buffer into output buss. + /// @brief Read audio frames from the recorder's internal circular buffer into output buffers. /// @note If `framesToRead` is greater than the number of available frames, it will fill empty space with silence. /// @param framesToRead Number of frames to read. void readFrames(size_t framesToRead); diff --git a/packages/react-native-audio-api/common/cpp/audioapi/core/sources/StreamerNode.cpp b/packages/react-native-audio-api/common/cpp/audioapi/core/sources/StreamerNode.cpp index f57af1e59..b48ee9e38 100644 --- a/packages/react-native-audio-api/common/cpp/audioapi/core/sources/StreamerNode.cpp +++ b/packages/react-native-audio-api/common/cpp/audioapi/core/sources/StreamerNode.cpp @@ -12,7 +12,6 @@ #include #include #include -#include #include #include #include @@ -20,7 +19,6 @@ #include #include #include -#include namespace audioapi { #if !RN_AUDIO_API_FFMPEG_DISABLED @@ -90,7 +88,7 @@ bool StreamerNode::initialize(const std::string &input_url) { } channelCount_ = codecpar_->ch_layout.nb_channels; - audioBus_ = + audioBuffer_ = std::make_shared(RENDER_QUANTUM_SIZE, channelCount_, context->getSampleRate()); auto [sender, receiver] = channels::spsc::channel< @@ -144,7 +142,7 @@ std::shared_ptr StreamerNode::processNode( StreamingData data; auto res = receiver_.try_receive(data); if (res == channels::spsc::ResponseStatus::SUCCESS) { - bufferedBus_ = std::make_shared(std::move(data.bus)); + bufferedBus_ = std::make_shared(std::move(data.buffer)); bufferedBusSize_ = data.size; processedSamples_ = 0; } else { diff --git a/packages/react-native-audio-api/common/cpp/audioapi/core/sources/StreamerNode.h b/packages/react-native-audio-api/common/cpp/audioapi/core/sources/StreamerNode.h index 3c360d21d..70b48a268 100644 --- a/packages/react-native-audio-api/common/cpp/audioapi/core/sources/StreamerNode.h +++ b/packages/react-native-audio-api/common/cpp/audioapi/core/sources/StreamerNode.h @@ -40,17 +40,17 @@ inline constexpr auto VERBOSE = false; inline constexpr auto CHANNEL_CAPACITY = 32; struct StreamingData { - audioapi::AudioBuffer bus; + audioapi::AudioBuffer buffer; size_t size; StreamingData() = default; - StreamingData(audioapi::AudioBuffer b, size_t s) : bus(b), size(s) {} - StreamingData(const StreamingData &data) : bus(data.bus), size(data.size) {} - StreamingData(StreamingData &&data) noexcept : bus(std::move(data.bus)), size(data.size) {} + StreamingData(audioapi::AudioBuffer b, size_t s) : buffer(b), size(s) {} + StreamingData(const StreamingData &data) : buffer(data.buffer), size(data.size) {} + StreamingData(StreamingData &&data) noexcept : buffer(std::move(data.buffer)), size(data.size) {} StreamingData &operator=(const StreamingData &data) { if (this == &data) { return *this; } - bus = data.bus; + buffer = data.buffer; size = data.size; return *this; } @@ -97,8 +97,8 @@ class StreamerNode : public AudioScheduledSourceNode { SwrContext *swrCtx_; uint8_t **resampledData_; // weird ffmpeg way of using raw byte pointers for resampled data - std::shared_ptr bufferedBus_; // audio bus for buffering hls frames - size_t bufferedBusSize_; // size of currently buffered bus + std::shared_ptr bufferedBus_; // audio buffer for buffering hls frames + size_t bufferedBusSize_; // size of currently buffered buffer int audio_stream_index_; // index of the audio stream channel in the input int maxResampledSamples_; size_t processedSamples_; @@ -133,7 +133,7 @@ class StreamerNode : public AudioScheduledSourceNode { /** * @brief Thread function to continuously read and process audio frames * @details This function runs in a separate thread to avoid blocking the main audio processing thread - * @note It will read frames from the input stream, resample them, and store them in the buffered bus + * @note It will read frames from the input stream, resample them, and store them in the buffered buffer * @note The thread will stop when streamFlag is set to false */ void streamAudio(); diff --git a/packages/react-native-audio-api/common/cpp/audioapi/core/utils/AudioRecorderCallback.cpp b/packages/react-native-audio-api/common/cpp/audioapi/core/utils/AudioRecorderCallback.cpp index 4de47a7a3..fd9e41ea8 100644 --- a/packages/react-native-audio-api/common/cpp/audioapi/core/utils/AudioRecorderCallback.cpp +++ b/packages/react-native-audio-api/common/cpp/audioapi/core/utils/AudioRecorderCallback.cpp @@ -56,18 +56,20 @@ void AudioRecorderCallback::emitAudioData(bool flush) { } while (circularBus_[0]->getNumberOfAvailableFrames() >= sizeLimit) { - auto bus = std::make_shared(sizeLimit, channelCount_, sampleRate_); + auto buffer = std::make_shared(sizeLimit, channelCount_, sampleRate_); for (int i = 0; i < channelCount_; ++i) { - circularBus_[i]->pop_front(*bus->getChannel(i), sizeLimit); + circularBus_[i]->pop_front(*buffer->getChannel(i), sizeLimit); } - invokeCallback(bus, static_cast(sizeLimit)); + invokeCallback(buffer, static_cast(sizeLimit)); } } -void AudioRecorderCallback::invokeCallback(const std::shared_ptr &bus, int numFrames) { - auto audioBufferHostObject = std::make_shared(bus); +void AudioRecorderCallback::invokeCallback( + const std::shared_ptr &buffer, + int numFrames) { + auto audioBufferHostObject = std::make_shared(buffer); std::unordered_map eventPayload = {}; eventPayload.insert({"buffer", audioBufferHostObject}); diff --git a/packages/react-native-audio-api/common/cpp/audioapi/core/utils/AudioRecorderCallback.h b/packages/react-native-audio-api/common/cpp/audioapi/core/utils/AudioRecorderCallback.h index 4ffed6bae..3b5746791 100644 --- a/packages/react-native-audio-api/common/cpp/audioapi/core/utils/AudioRecorderCallback.h +++ b/packages/react-native-audio-api/common/cpp/audioapi/core/utils/AudioRecorderCallback.h @@ -28,7 +28,7 @@ class AudioRecorderCallback { virtual void cleanup() = 0; void emitAudioData(bool flush = false); - void invokeCallback(const std::shared_ptr &bus, int numFrames); + void invokeCallback(const std::shared_ptr &buffer, int numFrames); void setOnErrorCallback(uint64_t callbackId); void clearOnErrorCallback(); diff --git a/packages/react-native-audio-api/common/cpp/audioapi/core/utils/AudioStretcher.cpp b/packages/react-native-audio-api/common/cpp/audioapi/core/utils/AudioStretcher.cpp index 1f650575e..647787c28 100644 --- a/packages/react-native-audio-api/common/cpp/audioapi/core/utils/AudioStretcher.cpp +++ b/packages/react-native-audio-api/common/cpp/audioapi/core/utils/AudioStretcher.cpp @@ -59,16 +59,16 @@ std::shared_ptr AudioStretcher::changePlaybackSpeed( stretchedBuffer.resize(outputFrames * outputChannels); stretch_deinit(stretcher); - auto audioBus = std::make_shared(outputFrames, outputChannels, sampleRate); + auto audioBuffer = std::make_shared(outputFrames, outputChannels, sampleRate); for (int ch = 0; ch < outputChannels; ++ch) { - auto channelData = audioBus->getChannel(ch)->span(); + auto channelData = audioBuffer->getChannel(ch)->span(); for (int i = 0; i < outputFrames; ++i) { channelData[i] = int16ToFloat(stretchedBuffer[i * outputChannels + ch]); } } - return audioBus; + return audioBuffer; } } // namespace audioapi diff --git a/packages/react-native-audio-api/common/cpp/audioapi/libs/ffmpeg/FFmpegDecoding.cpp b/packages/react-native-audio-api/common/cpp/audioapi/libs/ffmpeg/FFmpegDecoding.cpp index 1773bab53..7cca55feb 100644 --- a/packages/react-native-audio-api/common/cpp/audioapi/libs/ffmpeg/FFmpegDecoding.cpp +++ b/packages/react-native-audio-api/common/cpp/audioapi/libs/ffmpeg/FFmpegDecoding.cpp @@ -246,16 +246,16 @@ std::shared_ptr decodeAudioFrames( } auto outputFrames = decoded_buffer.size() / output_channel_count; - auto audioBus = + auto audioBuffer = std::make_shared(outputFrames, output_channel_count, output_sample_rate); for (int ch = 0; ch < output_channel_count; ++ch) { - auto channelData = audioBus->getChannel(ch)->span(); + auto channelData = audioBuffer->getChannel(ch)->span(); for (int i = 0; i < outputFrames; ++i) { channelData[i] = decoded_buffer[i * output_channel_count + ch]; } } - return audioBus; + return audioBuffer; } std::shared_ptr decodeWithMemoryBlock(const void *data, size_t size, int sample_rate) { diff --git a/packages/react-native-audio-api/common/cpp/audioapi/utils/AudioBuffer.cpp b/packages/react-native-audio-api/common/cpp/audioapi/utils/AudioBuffer.cpp index 9d0a9f18d..835d3b237 100644 --- a/packages/react-native-audio-api/common/cpp/audioapi/utils/AudioBuffer.cpp +++ b/packages/react-native-audio-api/common/cpp/audioapi/utils/AudioBuffer.cpp @@ -1,9 +1,9 @@ +#include #include #include #include #include #include -#include #include #include @@ -202,13 +202,13 @@ void AudioBuffer::sum( return; } - // Source channel count is smaller than current bus, we need to up-mix. + // Source channel count is smaller than current buffer, we need to up-mix. if (numberOfSourceChannels < numberOfChannels) { sumByUpMixing(source, sourceStart, destinationStart, length); return; } - // Source channel count is larger than current bus, we need to down-mix. + // Source channel count is larger than current buffer, we need to down-mix. if (numberOfSourceChannels > numberOfChannels) { sumByDownMixing(source, sourceStart, destinationStart, length); return; @@ -257,25 +257,25 @@ void AudioBuffer::interleaveTo(float *destination, size_t frames) const { } if (numberOfChannels_ == 2) { - dsp::interleaveStereo(channels_[0]->begin(), channels_[1]->begin(), destination, frames); - return; + dsp::interleaveStereo(channels_[0]->begin(), channels_[1]->begin(), destination, frames); + return; } - float* channelsPtrs[MAX_CHANNEL_COUNT]; - for (int i = 0; i < numberOfChannels_; ++i) { - channelsPtrs[i] = channels_[i]->begin(); - } + float *channelsPtrs[MAX_CHANNEL_COUNT]; + for (int i = 0; i < numberOfChannels_; ++i) { + channelsPtrs[i] = channels_[i]->begin(); + } - constexpr size_t kBlockSize = 64; - for (size_t blockStart = 0; blockStart < frames; blockStart += kBlockSize) { - size_t blockEnd = std::min(blockStart + kBlockSize, frames); - for (size_t i = blockStart; i < blockEnd; ++i) { - float* frameDest = destination + (i * numberOfChannels_); - for (int ch = 0; ch < numberOfChannels_; ++ch) { - frameDest[ch] = channelsPtrs[ch][i]; - } - } + constexpr size_t kBlockSize = 64; + for (size_t blockStart = 0; blockStart < frames; blockStart += kBlockSize) { + size_t blockEnd = std::min(blockStart + kBlockSize, frames); + for (size_t i = blockStart; i < blockEnd; ++i) { + float *frameDest = destination + (i * numberOfChannels_); + for (int ch = 0; ch < numberOfChannels_; ++ch) { + frameDest[ch] = channelsPtrs[ch][i]; + } } + } } void AudioBuffer::normalize() { diff --git a/packages/react-native-audio-api/common/cpp/audioapi/utils/CircularAudioArray.cpp b/packages/react-native-audio-api/common/cpp/audioapi/utils/CircularAudioArray.cpp index 14848094a..a0433bfc6 100644 --- a/packages/react-native-audio-api/common/cpp/audioapi/utils/CircularAudioArray.cpp +++ b/packages/react-native-audio-api/common/cpp/audioapi/utils/CircularAudioArray.cpp @@ -17,7 +17,6 @@ void CircularAudioArray::push_back(const AudioArray & data, size_t size, bool sk if (vWriteIndex_ + size > size_) { auto partSize = size_ - vWriteIndex_; - copy(data, 0, vWriteIndex_, partSize); copy(data, partSize, 0, size - partSize); } else { diff --git a/packages/react-native-audio-api/common/cpp/test/src/ConstantSourceTest.cpp b/packages/react-native-audio-api/common/cpp/test/src/ConstantSourceTest.cpp index 90ad1ce32..b85140e14 100644 --- a/packages/react-native-audio-api/common/cpp/test/src/ConstantSourceTest.cpp +++ b/packages/react-native-audio-api/common/cpp/test/src/ConstantSourceTest.cpp @@ -48,17 +48,17 @@ TEST_F(ConstantSourceTest, ConstantSourceCanBeCreated) { TEST_F(ConstantSourceTest, ConstantSourceOutputsConstantValue) { static constexpr int FRAMES_TO_PROCESS = 4; - auto bus = std::make_shared(FRAMES_TO_PROCESS, 1, sampleRate); + auto buffer = std::make_shared(FRAMES_TO_PROCESS, 1, sampleRate); auto constantSource = TestableConstantSourceNode(context); // constantSource.start(context->getCurrentTime()); - // auto resultBus = constantSource.processNode(bus, FRAMES_TO_PROCESS); + // auto resultBus = constantSource.processNode(buffer, FRAMES_TO_PROCESS); // for (int i = 0; i < FRAMES_TO_PROCESS; ++i) { // EXPECT_FLOAT_EQ((*resultBus->getChannel(0))[i], 1.0f); // } // constantSource.setOffsetParam(0.5f); - // resultBus = constantSource.processNode(bus, FRAMES_TO_PROCESS); + // resultBus = constantSource.processNode(buffer, FRAMES_TO_PROCESS); // for (int i = 0; i < FRAMES_TO_PROCESS; ++i) { // EXPECT_FLOAT_EQ((*resultBus->getChannel(0))[i], 0.5f); // } diff --git a/packages/react-native-audio-api/common/cpp/test/src/DelayTest.cpp b/packages/react-native-audio-api/common/cpp/test/src/DelayTest.cpp index 2da57a8c2..8b89667e5 100644 --- a/packages/react-native-audio-api/common/cpp/test/src/DelayTest.cpp +++ b/packages/react-native-audio-api/common/cpp/test/src/DelayTest.cpp @@ -53,12 +53,12 @@ TEST_F(DelayTest, DelayWithZeroDelayOutputsInputSignal) { auto delayNode = TestableDelayNode(context, options); delayNode.setDelayTimeParam(DELAY_TIME); - auto bus = std::make_shared(FRAMES_TO_PROCESS, 1, sampleRate); - for (size_t i = 0; i < bus->getSize(); ++i) { - (*bus->getChannel(0))[i] = i + 1; + auto buffer = std::make_shared(FRAMES_TO_PROCESS, 1, sampleRate); + for (size_t i = 0; i < buffer->getSize(); ++i) { + (*buffer->getChannel(0))[i] = i + 1; } - auto resultBus = delayNode.processNode(bus, FRAMES_TO_PROCESS); + auto resultBus = delayNode.processNode(buffer, FRAMES_TO_PROCESS); for (size_t i = 0; i < FRAMES_TO_PROCESS; ++i) { EXPECT_FLOAT_EQ((*resultBus->getChannel(0))[i], static_cast(i + 1)); } @@ -72,12 +72,12 @@ TEST_F(DelayTest, DelayAppliesTimeShiftCorrectly) { auto delayNode = TestableDelayNode(context, options); delayNode.setDelayTimeParam(DELAY_TIME); - auto bus = std::make_shared(FRAMES_TO_PROCESS, 1, sampleRate); - for (size_t i = 0; i < bus->getSize(); ++i) { - (*bus->getChannel(0))[i] = i + 1; + auto buffer = std::make_shared(FRAMES_TO_PROCESS, 1, sampleRate); + for (size_t i = 0; i < buffer->getSize(); ++i) { + (*buffer->getChannel(0))[i] = i + 1; } - auto resultBus = delayNode.processNode(bus, FRAMES_TO_PROCESS); + auto resultBus = delayNode.processNode(buffer, FRAMES_TO_PROCESS); for (size_t i = 0; i < FRAMES_TO_PROCESS; ++i) { if (i < FRAMES_TO_PROCESS / 2) { // First 64 samples should be zero due to delay EXPECT_FLOAT_EQ((*resultBus->getChannel(0))[i], 0.0f); @@ -85,7 +85,7 @@ TEST_F(DelayTest, DelayAppliesTimeShiftCorrectly) { EXPECT_FLOAT_EQ( (*resultBus->getChannel(0))[i], static_cast( - i + 1 - FRAMES_TO_PROCESS / 2)); // Last 64 samples should be 1st part of bus + i + 1 - FRAMES_TO_PROCESS / 2)); // Last 64 samples should be 1st part of buffer } } } @@ -98,15 +98,15 @@ TEST_F(DelayTest, DelayHandlesTailCorrectly) { auto delayNode = TestableDelayNode(context, options); delayNode.setDelayTimeParam(DELAY_TIME); - auto bus = std::make_shared(FRAMES_TO_PROCESS, 1, sampleRate); - for (size_t i = 0; i < bus->getSize(); ++i) { - (*bus->getChannel(0))[i] = i + 1; + auto buffer = std::make_shared(FRAMES_TO_PROCESS, 1, sampleRate); + for (size_t i = 0; i < buffer->getSize(); ++i) { + (*buffer->getChannel(0))[i] = i + 1; } - delayNode.processNode(bus, FRAMES_TO_PROCESS); - auto resultBus = delayNode.processNode(bus, FRAMES_TO_PROCESS); + delayNode.processNode(buffer, FRAMES_TO_PROCESS); + auto resultBus = delayNode.processNode(buffer, FRAMES_TO_PROCESS); for (size_t i = 0; i < FRAMES_TO_PROCESS; ++i) { - if (i < FRAMES_TO_PROCESS / 2) { // First 64 samples should be 2nd part of bus + if (i < FRAMES_TO_PROCESS / 2) { // First 64 samples should be 2nd part of buffer EXPECT_FLOAT_EQ( (*resultBus->getChannel(0))[i], static_cast(i + 1 + FRAMES_TO_PROCESS / 2)); } else { diff --git a/packages/react-native-audio-api/common/cpp/test/src/GainTest.cpp b/packages/react-native-audio-api/common/cpp/test/src/GainTest.cpp index 2303795f5..036675869 100644 --- a/packages/react-native-audio-api/common/cpp/test/src/GainTest.cpp +++ b/packages/react-native-audio-api/common/cpp/test/src/GainTest.cpp @@ -51,12 +51,12 @@ TEST_F(GainTest, GainModulatesVolumeCorrectly) { auto gainNode = TestableGainNode(context); gainNode.setGainParam(GAIN_VALUE); - auto bus = std::make_shared(FRAMES_TO_PROCESS, 1, sampleRate); - for (size_t i = 0; i < bus->getSize(); ++i) { - (*bus->getChannel(0))[i] = i + 1; + auto buffer = std::make_shared(FRAMES_TO_PROCESS, 1, sampleRate); + for (size_t i = 0; i < buffer->getSize(); ++i) { + (*buffer->getChannel(0))[i] = i + 1; } - auto resultBus = gainNode.processNode(bus, FRAMES_TO_PROCESS); + auto resultBus = gainNode.processNode(buffer, FRAMES_TO_PROCESS); for (size_t i = 0; i < FRAMES_TO_PROCESS; ++i) { EXPECT_FLOAT_EQ((*resultBus->getChannel(0))[i], (i + 1) * GAIN_VALUE); } @@ -68,13 +68,13 @@ TEST_F(GainTest, GainModulatesVolumeCorrectlyMultiChannel) { auto gainNode = TestableGainNode(context); gainNode.setGainParam(GAIN_VALUE); - auto bus = std::make_shared(FRAMES_TO_PROCESS, 2, sampleRate); - for (size_t i = 0; i < bus->getSize(); ++i) { - (*bus->getChannel(0))[i] = i + 1; - (*bus->getChannel(1))[i] = -i - 1; + auto buffer = std::make_shared(FRAMES_TO_PROCESS, 2, sampleRate); + for (size_t i = 0; i < buffer->getSize(); ++i) { + (*buffer->getChannel(0))[i] = i + 1; + (*buffer->getChannel(1))[i] = -i - 1; } - auto resultBus = gainNode.processNode(bus, FRAMES_TO_PROCESS); + auto resultBus = gainNode.processNode(buffer, FRAMES_TO_PROCESS); for (size_t i = 0; i < FRAMES_TO_PROCESS; ++i) { EXPECT_FLOAT_EQ((*resultBus->getChannel(0))[i], (i + 1) * GAIN_VALUE); EXPECT_FLOAT_EQ((*resultBus->getChannel(1))[i], (-i - 1) * GAIN_VALUE); diff --git a/packages/react-native-audio-api/common/cpp/test/src/StereoPannerTest.cpp b/packages/react-native-audio-api/common/cpp/test/src/StereoPannerTest.cpp index 6bdc2160e..d0f597631 100644 --- a/packages/react-native-audio-api/common/cpp/test/src/StereoPannerTest.cpp +++ b/packages/react-native-audio-api/common/cpp/test/src/StereoPannerTest.cpp @@ -51,12 +51,12 @@ TEST_F(StereoPannerTest, PanModulatesInputMonoCorrectly) { auto panNode = TestableStereoPannerNode(context); panNode.setPanParam(PAN_VALUE); - auto bus = std::make_shared(FRAMES_TO_PROCESS, 1, sampleRate); - for (size_t i = 0; i < bus->getSize(); ++i) { - (*bus->getChannelByType(AudioBuffer::ChannelLeft))[i] = i + 1; + auto buffer = std::make_shared(FRAMES_TO_PROCESS, 1, sampleRate); + for (size_t i = 0; i < buffer->getSize(); ++i) { + (*buffer->getChannelByType(AudioBuffer::ChannelLeft))[i] = i + 1; } - auto resultBus = panNode.processNode(bus, FRAMES_TO_PROCESS); + auto resultBus = panNode.processNode(buffer, FRAMES_TO_PROCESS); // x = (0.5 + 1) / 2 = 0.75 // gainL = cos(x * (Ï€ / 2)) = cos(0.75 * (Ï€ / 2)) = 0.38268343236508984 // gainR = sin(x * (Ï€ / 2)) = sin(0.75 * (Ï€ / 2)) = 0.9238795325112867 @@ -78,13 +78,13 @@ TEST_F(StereoPannerTest, PanModulatesInputStereoCorrectlyWithNegativePan) { auto panNode = TestableStereoPannerNode(context); panNode.setPanParam(PAN_VALUE); - auto bus = std::make_shared(FRAMES_TO_PROCESS, 2, sampleRate); - for (size_t i = 0; i < bus->getSize(); ++i) { - (*bus->getChannelByType(AudioBuffer::ChannelLeft))[i] = i + 1; - (*bus->getChannelByType(AudioBuffer::ChannelRight))[i] = i + 1; + auto buffer = std::make_shared(FRAMES_TO_PROCESS, 2, sampleRate); + for (size_t i = 0; i < buffer->getSize(); ++i) { + (*buffer->getChannelByType(AudioBuffer::ChannelLeft))[i] = i + 1; + (*buffer->getChannelByType(AudioBuffer::ChannelRight))[i] = i + 1; } - auto resultBus = panNode.processNode(bus, FRAMES_TO_PROCESS); + auto resultBus = panNode.processNode(buffer, FRAMES_TO_PROCESS); // x = -0.5 + 1 = 0.5 // gainL = cos(x * (Ï€ / 2)) = cos(0.5 * (Ï€ / 2)) = 0.7071067811865476 // gainR = sin(x * (Ï€ / 2)) = sin(0.5 * (Ï€ / 2)) = 0.7071067811865476 @@ -106,13 +106,13 @@ TEST_F(StereoPannerTest, PanModulatesInputStereoCorrectlyWithPositivePan) { auto panNode = TestableStereoPannerNode(context); panNode.setPanParam(PAN_VALUE); - auto bus = std::make_shared(FRAMES_TO_PROCESS, 2, sampleRate); - for (size_t i = 0; i < bus->getSize(); ++i) { - (*bus->getChannelByType(AudioBuffer::ChannelLeft))[i] = i + 1; - (*bus->getChannelByType(AudioBuffer::ChannelRight))[i] = i + 1; + auto buffer = std::make_shared(FRAMES_TO_PROCESS, 2, sampleRate); + for (size_t i = 0; i < buffer->getSize(); ++i) { + (*buffer->getChannelByType(AudioBuffer::ChannelLeft))[i] = i + 1; + (*buffer->getChannelByType(AudioBuffer::ChannelRight))[i] = i + 1; } - auto resultBus = panNode.processNode(bus, FRAMES_TO_PROCESS); + auto resultBus = panNode.processNode(buffer, FRAMES_TO_PROCESS); // x = 0.75 // gainL = cos(x * (Ï€ / 2)) = cos(0.75 * (Ï€ / 2)) = 0.38268343236508984 // gainR = sin(x * (Ï€ / 2)) = sin(0.75 * (Ï€ / 2)) = 0.9238795325112867 diff --git a/packages/react-native-audio-api/common/cpp/test/src/core/effects/WaveShaperNodeTest.cpp b/packages/react-native-audio-api/common/cpp/test/src/core/effects/WaveShaperNodeTest.cpp index f0d52d2ce..9dac1b694 100644 --- a/packages/react-native-audio-api/common/cpp/test/src/core/effects/WaveShaperNodeTest.cpp +++ b/packages/react-native-audio-api/common/cpp/test/src/core/effects/WaveShaperNodeTest.cpp @@ -61,12 +61,12 @@ TEST_F(WaveShaperNodeTest, NoneOverSamplingProcessesCorrectly) { waveShaper->setOversample(OverSampleType::OVERSAMPLE_NONE); waveShaper->setCurve(waveShaper->testCurve_); - auto bus = std::make_shared(FRAMES_TO_PROCESS, 1, sampleRate); - for (size_t i = 0; i < bus->getSize(); ++i) { - (*bus->getChannel(0))[i] = -1.0f + i * 0.5f; + auto buffer = std::make_shared(FRAMES_TO_PROCESS, 1, sampleRate); + for (size_t i = 0; i < buffer->getSize(); ++i) { + (*buffer->getChannel(0))[i] = -1.0f + i * 0.5f; } - auto resultBus = waveShaper->processNode(bus, FRAMES_TO_PROCESS); + auto resultBus = waveShaper->processNode(buffer, FRAMES_TO_PROCESS); auto curveData = waveShaper->testCurve_->span(); auto resultData = resultBus->getChannel(0)->span(); diff --git a/packages/react-native-audio-api/ios/audioapi/ios/core/IOSAudioPlayer.h b/packages/react-native-audio-api/ios/audioapi/ios/core/IOSAudioPlayer.h index c11e9b7fd..bf4643abf 100644 --- a/packages/react-native-audio-api/ios/audioapi/ios/core/IOSAudioPlayer.h +++ b/packages/react-native-audio-api/ios/audioapi/ios/core/IOSAudioPlayer.h @@ -30,7 +30,7 @@ class IOSAudioPlayer { bool isRunning() const; protected: - std::shared_ptr audioBus_; + std::shared_ptr audioBuffer_; NativeAudioPlayer *audioPlayer_; std::function, int)> renderAudio_; int channelCount_; diff --git a/packages/react-native-audio-api/ios/audioapi/ios/core/IOSAudioPlayer.mm b/packages/react-native-audio-api/ios/audioapi/ios/core/IOSAudioPlayer.mm index 4d1d61b05..f9d05810a 100644 --- a/packages/react-native-audio-api/ios/audioapi/ios/core/IOSAudioPlayer.mm +++ b/packages/react-native-audio-api/ios/audioapi/ios/core/IOSAudioPlayer.mm @@ -13,7 +13,7 @@ const std::function, int)> &renderAudio, float sampleRate, int channelCount) - : renderAudio_(renderAudio), channelCount_(channelCount), audioBus_(0), isRunning_(false) + : renderAudio_(renderAudio), channelCount_(channelCount), audioBuffer_(0), isRunning_(false) { RenderAudioBlock renderAudioBlock = ^(AudioBufferList *outputData, int numFrames) { int processedFrames = 0; @@ -22,15 +22,16 @@ int framesToProcess = std::min(numFrames - processedFrames, RENDER_QUANTUM_SIZE); if (isRunning_.load(std::memory_order_acquire)) { - renderAudio_(audioBus_, framesToProcess); + renderAudio_(audioBuffer_, framesToProcess); } else { - audioBus_->zero(); + audioBuffer_->zero(); } for (int channel = 0; channel < channelCount_; channel += 1) { float *outputChannel = (float *)outputData->mBuffers[channel].mData; - audioBus_->getChannel(channel)->copyTo(outputChannel, 0, processedFrames, framesToProcess); + audioBuffer_->getChannel(channel)->copyTo( + outputChannel, 0, processedFrames, framesToProcess); } processedFrames += framesToProcess; @@ -41,7 +42,7 @@ sampleRate:sampleRate channelCount:channelCount_]; - audioBus_ = std::make_shared(RENDER_QUANTUM_SIZE, channelCount_, sampleRate); + audioBuffer_ = std::make_shared(RENDER_QUANTUM_SIZE, channelCount_, sampleRate); } IOSAudioPlayer::~IOSAudioPlayer() @@ -96,8 +97,8 @@ stop(); [audioPlayer_ cleanup]; - if (audioBus_) { - audioBus_ = nullptr; + if (audioBuffer_) { + audioBuffer_ = nullptr; } } diff --git a/packages/react-native-audio-api/ios/audioapi/ios/core/IOSAudioRecorder.h b/packages/react-native-audio-api/ios/audioapi/ios/core/IOSAudioRecorder.h index ed356c18e..9137b9405 100644 --- a/packages/react-native-audio-api/ios/audioapi/ios/core/IOSAudioRecorder.h +++ b/packages/react-native-audio-api/ios/audioapi/ios/core/IOSAudioRecorder.h @@ -10,7 +10,6 @@ typedef struct objc_object NativeAudioRecorder; #endif // __OBJC__ #include -#include #include #include diff --git a/packages/react-native-audio-api/ios/audioapi/ios/core/utils/AudioDecoder.mm b/packages/react-native-audio-api/ios/audioapi/ios/core/utils/AudioDecoder.mm index 3d2df2fb5..2995256bc 100644 --- a/packages/react-native-audio-api/ios/audioapi/ios/core/utils/AudioDecoder.mm +++ b/packages/react-native-audio-api/ios/audioapi/ios/core/utils/AudioDecoder.mm @@ -51,16 +51,16 @@ } auto outputFrames = buffer.size() / outputChannels; - auto audioBus = std::make_shared(outputFrames, outputChannels, outputSampleRate); + auto audioBuffer = std::make_shared(outputFrames, outputChannels, outputSampleRate); for (int ch = 0; ch < outputChannels; ++ch) { - auto channelData = audioBus->getChannel(ch)->span(); + auto channelData = audioBuffer->getChannel(ch)->span(); for (int i = 0; i < outputFrames; ++i) { channelData[i] = buffer[i * outputChannels + ch]; } } - return audioBus; + return audioBuffer; } std::shared_ptr AudioDecoder::decodeWithFilePath( @@ -152,11 +152,11 @@ const auto uint8Data = reinterpret_cast(decodedData.data()); size_t numFramesDecoded = decodedData.size() / (inputChannelCount * sizeof(int16_t)); - auto audioBus = + auto audioBuffer = std::make_shared(numFramesDecoded, inputChannelCount, inputSampleRate); for (int ch = 0; ch < inputChannelCount; ++ch) { - auto channelData = audioBus->getChannel(ch)->span(); + auto channelData = audioBuffer->getChannel(ch)->span(); for (size_t i = 0; i < numFramesDecoded; ++i) { size_t offset; @@ -171,7 +171,7 @@ channelData[i] = uint8ToFloat(uint8Data[offset], uint8Data[offset + 1]); } } - return audioBus; + return audioBuffer; } } // namespace audioapi From f9a3ac2a4c2f777126c6bd4e9fad58ae9584da86 Mon Sep 17 00:00:00 2001 From: maciejmakowski2003 Date: Wed, 4 Feb 2026 20:42:21 +0100 Subject: [PATCH 22/30] refactor: doxygen for AudioBuffer --- .../common/cpp/audioapi/utils/AudioBuffer.h | 27 +++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/packages/react-native-audio-api/common/cpp/audioapi/utils/AudioBuffer.h b/packages/react-native-audio-api/common/cpp/audioapi/utils/AudioBuffer.h index 660ff7135..6bdfae9bd 100644 --- a/packages/react-native-audio-api/common/cpp/audioapi/utils/AudioBuffer.h +++ b/packages/react-native-audio-api/common/cpp/audioapi/utils/AudioBuffer.h @@ -73,9 +73,23 @@ class AudioBuffer { void zero(); void zero(size_t start, size_t length); + /// @brief Sums audio data from a source AudioBuffer into this AudioBuffer. + /// @param source The source AudioBuffer to sum from. + /// @param interpretation The channel interpretation to use for summing (default is SPEAKERS). + /// @note Handles up-mixing and down-mixing based on the number of channels in both buffers. + /// Assumes that source and this are located in two distinct, non-overlapping memory locations. void sum( const AudioBuffer &source, ChannelInterpretation interpretation = ChannelInterpretation::SPEAKERS); + + /// @brief Sums audio data from a source AudioBuffer into this AudioBuffer. + /// @param source The source AudioBuffer to sum from. + /// @param sourceStart The starting index in the source AudioBuffer. + /// @param destinationStart The starting index in this AudioBuffer. + /// @param length The number of samples to sum. + /// @param interpretation The channel interpretation to use for summing (default is SPEAKERS). + /// @note Handles up-mixing and down-mixing based on the number of channels in both buffers. + /// Assumes that source and this are located in two distinct, non-overlapping memory locations. void sum( const AudioBuffer &source, size_t sourceStart, @@ -83,7 +97,19 @@ class AudioBuffer { size_t length, ChannelInterpretation interpretation = ChannelInterpretation::SPEAKERS); + /// @brief Copies audio data from a source AudioBuffer into this AudioBuffer. + /// @param source The source AudioBuffer to copy from. + /// @note Handles up-mixing and down-mixing based on the number of channels in both buffers. + /// Assumes that source and this are located in two distinct, non-overlapping memory locations. void copy(const AudioBuffer &source); + + /// @brief Copies audio data from a source AudioBuffer into this AudioBuffer. + /// @param source The source AudioBuffer to copy from. + /// @param sourceStart The starting index in the source AudioBuffer. + /// @param destinationStart The starting index in this AudioBuffer. + /// @param length The number of samples to copy. + /// @note Handles up-mixing and down-mixing based on the number of channels in both buffers. + /// Assumes that source and this are located in two distinct, non-overlapping memory locations. void copy(const AudioBuffer &source, size_t sourceStart, size_t destinationStart, size_t length); /// @brief Interleave audio data from this AudioBuffer into a destination buffer. @@ -93,6 +119,7 @@ class AudioBuffer { /// according to the number of channels in this AudioBuffer. /// Example of interleaved data for stereo (2 channels): /// [L0, R0, L1, R1, L2, R2, ...] + /// Assumes that this and destination are located in two distinct, non-overlapping memory locations. void interleaveTo(float *destination, size_t frames) const; void normalize(); From a92bbf98d94b56289be9a564ea7f569ecb4828fb Mon Sep 17 00:00:00 2001 From: maciejmakowski2003 Date: Thu, 5 Feb 2026 08:45:20 +0100 Subject: [PATCH 23/30] refactor: deinterleave audio data using AudioBuffer method --- .../android/core/utils/AudioDecoder.cpp | 7 +-- .../common/cpp/audioapi/dsp/VectorMath.cpp | 62 +++++++++++++++++++ .../common/cpp/audioapi/dsp/VectorMath.h | 6 ++ .../common/cpp/audioapi/utils/AudioBuffer.cpp | 55 ++++++++++------ .../common/cpp/audioapi/utils/AudioBuffer.h | 9 +++ .../audioapi/ios/core/utils/AudioDecoder.mm | 7 +-- 6 files changed, 114 insertions(+), 32 deletions(-) diff --git a/packages/react-native-audio-api/android/src/main/cpp/audioapi/android/core/utils/AudioDecoder.cpp b/packages/react-native-audio-api/android/src/main/cpp/audioapi/android/core/utils/AudioDecoder.cpp index c08e4ba30..4fa157d2a 100644 --- a/packages/react-native-audio-api/android/src/main/cpp/audioapi/android/core/utils/AudioDecoder.cpp +++ b/packages/react-native-audio-api/android/src/main/cpp/audioapi/android/core/utils/AudioDecoder.cpp @@ -55,12 +55,7 @@ std::shared_ptr AudioDecoder::makeAudioBufferFromFloatBuffer( auto outputFrames = buffer.size() / outputChannels; auto audioBuffer = std::make_shared(outputFrames, outputChannels, outputSampleRate); - for (int ch = 0; ch < outputChannels; ++ch) { - auto channelData = audioBuffer->getChannel(ch)->span(); - for (int i = 0; i < outputFrames; ++i) { - channelData[i] = buffer[i * outputChannels + ch]; - } - } + audioBuffer->deinterleaveFrom(buffer.data(), outputFrames); return audioBuffer; } diff --git a/packages/react-native-audio-api/common/cpp/audioapi/dsp/VectorMath.cpp b/packages/react-native-audio-api/common/cpp/audioapi/dsp/VectorMath.cpp index 18bdeab4c..d965bafc6 100644 --- a/packages/react-native-audio-api/common/cpp/audioapi/dsp/VectorMath.cpp +++ b/packages/react-native-audio-api/common/cpp/audioapi/dsp/VectorMath.cpp @@ -103,6 +103,16 @@ float computeConvolution(const float *state, const float *kernel, size_t kernelS return result; } +void deinterleaveStereo( + const float * __restrict inputInterleaved, + float * __restrict outputLeft, + float * __restrict outputRight, + size_t numberOfFrames) { + float zero = 0.0f; + vDSP_vsadd(inputInterleaved, 2, &zero, outputLeft, 1, numberOfFrames); + vDSP_vsadd(inputInterleaved + 1, 2, &zero, outputRight, 1, numberOfFrames); +} + void interleaveStereo( const float* __restrict inputLeft, const float* __restrict inputRight, @@ -699,6 +709,58 @@ float computeConvolution(const float *state, const float *kernel, size_t kernelS return sum; } +void deinterleaveStereo( + const float * __restrict inputInterleaved, + float * __restrict outputLeft, + float * __restrict outputRight, + size_t numberOfFrames) { + + size_t n = numberOfFrames; + +#if defined(HAVE_ARM_NEON_INTRINSICS) + // process 4 frames (8 samples) at a time using NEON + size_t group = n / 4; + while (group--) { + // vld2q_f32 deinterleaves L and R into separate registers in one hardware op + float32x4x2_t v = vld2q_f32(inputInterleaved); + vst1q_f32(outputLeft, v.val[0]); + vst1q_f32(outputRight, v.val[1]); + + inputInterleaved += 8; + outputLeft += 4; + outputRight += 4; + } + n %= 4; +#elif defined(HAVE_X86_SSE2) + // process 4 frames (8 samples) at a time using SSE + size_t group = n / 4; + while (group--) { + // load two 128-bit registers (8 floats total) + __m128 s0 = _mm_loadu_ps(inputInterleaved); + __m128 s1 = _mm_loadu_ps(inputInterleaved + 4); + + // use shuffle to group the Left samples and Right samples + // mask 0x88 (2,0,2,0) picks indices 0 and 2 from both s0 and s1 + // mask 0xDD (3,1,3,1) picks indices 1 and 3 from both s0 and s1 + __m128 left_v = _mm_shuffle_ps(s0, s1, _MM_SHUFFLE(2, 0, 2, 0)); + __m128 right_v = _mm_shuffle_ps(s0, s1, _MM_SHUFFLE(3, 1, 3, 1)); + + _mm_storeu_ps(outputLeft, left_v); + _mm_storeu_ps(outputRight, right_v); + + inputInterleaved += 8; + outputLeft += 4; + outputRight += 4; + } + n %= 4; +#endif + + while (n--) { + *outputLeft++ = *inputInterleaved++; + *outputRight++ = *inputInterleaved++; + } +} + void interleaveStereo( const float * __restrict inputLeft, const float * __restrict inputRight, diff --git a/packages/react-native-audio-api/common/cpp/audioapi/dsp/VectorMath.h b/packages/react-native-audio-api/common/cpp/audioapi/dsp/VectorMath.h index c66f46f9b..cbbfedabb 100644 --- a/packages/react-native-audio-api/common/cpp/audioapi/dsp/VectorMath.h +++ b/packages/react-native-audio-api/common/cpp/audioapi/dsp/VectorMath.h @@ -77,4 +77,10 @@ void interleaveStereo( float *outputInterleaved, size_t numberOfFrames); +void deinterleaveStereo( + const float *inputInterleaved, + float *outputLeft, + float *outputRight, + size_t numberOfFrames); + } // namespace audioapi::dsp diff --git a/packages/react-native-audio-api/common/cpp/audioapi/utils/AudioBuffer.cpp b/packages/react-native-audio-api/common/cpp/audioapi/utils/AudioBuffer.cpp index 835d3b237..2555ac601 100644 --- a/packages/react-native-audio-api/common/cpp/audioapi/utils/AudioBuffer.cpp +++ b/packages/react-native-audio-api/common/cpp/audioapi/utils/AudioBuffer.cpp @@ -14,13 +14,10 @@ // source: // https://github.com/WebKit/WebKit/blob/main/Source/WebCore/platform/audio/AudioBus.cpp -const float SQRT_HALF = sqrtf(0.5f); - namespace audioapi { -/** - * Public interfaces - memory management - */ +const float SQRT_HALF = sqrtf(0.5f); +constexpr int BLOCK_SIZE = 64; AudioBuffer::AudioBuffer(size_t size, int numberOfChannels, float sampleRate) : numberOfChannels_(numberOfChannels), sampleRate_(sampleRate), size_(size) { @@ -84,10 +81,6 @@ AudioBuffer &AudioBuffer::operator=(audioapi::AudioBuffer &&other) noexcept { return *this; } -/** - * Public interfaces - getters - */ - AudioArray *AudioBuffer::getChannel(int index) const { return channels_[index].get(); } @@ -166,10 +159,6 @@ std::shared_ptr AudioBuffer::getSharedChannel(int index) const return channels_[index]; } -/** - * Public interfaces - audio processing and setters - */ - void AudioBuffer::zero() { zero(0, getSize()); } @@ -246,6 +235,37 @@ void AudioBuffer::copy( sum(source, sourceStart, destinationStart, length); } +void AudioBuffer::deinterleaveFrom(const float *source, size_t frames) { + if (frames == 0) { + return; + } + + if (numberOfChannels_ == 1) { + channels_[0]->copy(source, 0, 0, frames); + return; + } + + if (numberOfChannels_ == 2) { + dsp::deinterleaveStereo(source, channels_[0]->begin(), channels_[1]->begin(), frames); + return; + } + + float *channelsPtrs[MAX_CHANNEL_COUNT]; + for (int i = 0; i < numberOfChannels_; ++i) { + channelsPtrs[i] = channels_[i]->begin(); + } + + for (size_t blockStart = 0; blockStart < frames; blockStart += BLOCK_SIZE) { + size_t blockEnd = std::min(blockStart + BLOCK_SIZE, frames); + for (size_t i = blockStart; i < blockEnd; ++i) { + const float *frameSource = source + (i * numberOfChannels_); + for (int ch = 0; ch < numberOfChannels_; ++ch) { + channelsPtrs[ch][i] = frameSource[ch]; + } + } + } +} + void AudioBuffer::interleaveTo(float *destination, size_t frames) const { if (frames == 0) { return; @@ -266,9 +286,8 @@ void AudioBuffer::interleaveTo(float *destination, size_t frames) const { channelsPtrs[i] = channels_[i]->begin(); } - constexpr size_t kBlockSize = 64; - for (size_t blockStart = 0; blockStart < frames; blockStart += kBlockSize) { - size_t blockEnd = std::min(blockStart + kBlockSize, frames); + for (size_t blockStart = 0; blockStart < frames; blockStart += BLOCK_SIZE) { + size_t blockEnd = std::min(blockStart + BLOCK_SIZE, frames); for (size_t i = blockStart; i < blockEnd; ++i) { float *frameDest = destination + (i * numberOfChannels_); for (int ch = 0; ch < numberOfChannels_; ++ch) { @@ -325,10 +344,6 @@ void AudioBuffer::createChannels() { } } -/** - * Internal tooling - channel summing - */ - void AudioBuffer::discreteSum( const AudioBuffer &source, size_t sourceStart, diff --git a/packages/react-native-audio-api/common/cpp/audioapi/utils/AudioBuffer.h b/packages/react-native-audio-api/common/cpp/audioapi/utils/AudioBuffer.h index 6bdfae9bd..5e77f957a 100644 --- a/packages/react-native-audio-api/common/cpp/audioapi/utils/AudioBuffer.h +++ b/packages/react-native-audio-api/common/cpp/audioapi/utils/AudioBuffer.h @@ -112,6 +112,15 @@ class AudioBuffer { /// Assumes that source and this are located in two distinct, non-overlapping memory locations. void copy(const AudioBuffer &source, size_t sourceStart, size_t destinationStart, size_t length); + /// @brief Deinterleave audio data from a source buffer into this AudioBuffer. + /// @param source Pointer to the source buffer containing interleaved audio data. + /// @param frames Number of frames to deinterleave from the source buffer. + /// @note The source buffer should contain interleaved audio data according to the number of channels in this AudioBuffer. + /// Example of interleaved data for stereo (2 channels): + /// [L0, R0, L1, R1, L2, R2, ...] + /// Assumes that source and this are located in two distinct, non-overlapping memory locations. + void deinterleaveFrom(const float *source, size_t frames); + /// @brief Interleave audio data from this AudioBuffer into a destination buffer. /// @param destination Pointer to the destination buffer where interleaved audio data will be written. /// @param frames Number of frames to interleave into the destination buffer. diff --git a/packages/react-native-audio-api/ios/audioapi/ios/core/utils/AudioDecoder.mm b/packages/react-native-audio-api/ios/audioapi/ios/core/utils/AudioDecoder.mm index 2995256bc..8e54daa16 100644 --- a/packages/react-native-audio-api/ios/audioapi/ios/core/utils/AudioDecoder.mm +++ b/packages/react-native-audio-api/ios/audioapi/ios/core/utils/AudioDecoder.mm @@ -53,12 +53,7 @@ auto outputFrames = buffer.size() / outputChannels; auto audioBuffer = std::make_shared(outputFrames, outputChannels, outputSampleRate); - for (int ch = 0; ch < outputChannels; ++ch) { - auto channelData = audioBuffer->getChannel(ch)->span(); - for (int i = 0; i < outputFrames; ++i) { - channelData[i] = buffer[i * outputChannels + ch]; - } - } + audioBuffer->deinterleaveFrom(buffer.data(), outputFrames); return audioBuffer; } From 49537d004b1172be636ffb41a162a63f90fdacf5 Mon Sep 17 00:00:00 2001 From: maciejmakowski2003 Date: Thu, 5 Feb 2026 08:46:35 +0100 Subject: [PATCH 24/30] refactor: broader support for circular data structures operations and deinterleaving --- .../android/core/AndroidAudioRecorder.cpp | 48 +++---- .../android/core/AndroidAudioRecorder.h | 3 + .../core/utils/AndroidRecorderCallback.cpp | 14 +-- .../core/utils/AndroidRecorderCallback.h | 2 + .../audioapi/core/analysis/AnalyserNode.cpp | 3 +- .../cpp/audioapi/core/inputs/AudioRecorder.h | 3 - .../core/utils/AudioRecorderCallback.h | 2 - .../cpp/audioapi/utils/CircularAudioArray.cpp | 119 ++++++++++-------- .../cpp/audioapi/utils/CircularAudioArray.h | 5 + .../utils/CircularOverflowableAudioArray.cpp | 80 ++++++------ .../utils/CircularOverflowableAudioArray.h | 14 ++- .../ios/audioapi/ios/core/IOSAudioRecorder.mm | 17 ++- .../ios/core/utils/IOSRecorderCallback.mm | 12 +- 13 files changed, 175 insertions(+), 147 deletions(-) diff --git a/packages/react-native-audio-api/android/src/main/cpp/audioapi/android/core/AndroidAudioRecorder.cpp b/packages/react-native-audio-api/android/src/main/cpp/audioapi/android/core/AndroidAudioRecorder.cpp index 77eee6ccf..3c589c345 100644 --- a/packages/react-native-audio-api/android/src/main/cpp/audioapi/android/core/AndroidAudioRecorder.cpp +++ b/packages/react-native-audio-api/android/src/main/cpp/audioapi/android/core/AndroidAudioRecorder.cpp @@ -26,7 +26,10 @@ namespace audioapi { AndroidAudioRecorder::AndroidAudioRecorder( const std::shared_ptr &audioEventHandlerRegistry) - : AudioRecorder(audioEventHandlerRegistry), streamSampleRate_(0.0), streamChannelCount_(0) {} + : AudioRecorder(audioEventHandlerRegistry), + streamSampleRate_(0.0), + streamChannelCount_(0), + streamMaxBufferSizeInFrames_(0) {} /// @brief Destructor ensures that the audio stream and each output type are closed and flushed up remaining data. /// TODO: Possibly locks here are not necessary, but we might have an issue with oboe having raw pointer to the @@ -88,7 +91,7 @@ Result AndroidAudioRecorder::openAudioStream() { streamSampleRate_ = static_cast(mStream_->getSampleRate()); streamChannelCount_ = mStream_->getChannelCount(); - maxBufferSizeInFrames_ = mStream_->getBufferSizeInFrames(); + streamMaxBufferSizeInFrames_ = mStream_->getBufferSizeInFrames(); return Result::Ok(None); } @@ -119,10 +122,12 @@ Result AndroidAudioRecorder::start(const std::string & } if (usesFileOutput()) { - auto fileResult = - std::static_pointer_cast(fileWriter_) - ->openFile( - streamSampleRate_, streamChannelCount_, maxBufferSizeInFrames_, fileNameOverride); + auto fileResult = std::static_pointer_cast(fileWriter_) + ->openFile( + streamSampleRate_, + streamChannelCount_, + streamMaxBufferSizeInFrames_, + fileNameOverride); if (!fileResult.is_ok()) { return Result::Err( @@ -134,12 +139,13 @@ Result AndroidAudioRecorder::start(const std::string & if (usesCallback()) { std::static_pointer_cast(dataCallback_) - ->prepare(streamSampleRate_, streamChannelCount_, maxBufferSizeInFrames_); + ->prepare(streamSampleRate_, streamChannelCount_, streamMaxBufferSizeInFrames_); } if (isConnected()) { - tempArray_ = std::make_shared(maxBufferSizeInFrames_); - adapterNode_->init(maxBufferSizeInFrames_, streamChannelCount_); + deinterleavingBuffer_ = std::make_shared( + streamMaxBufferSizeInFrames_, streamChannelCount_, streamSampleRate_); + adapterNode_->init(streamMaxBufferSizeInFrames_, streamChannelCount_); } auto result = mStream_->requestStart(); @@ -228,7 +234,7 @@ Result AndroidAudioRecorder::enableFileOutput( if (!isIdle()) { auto fileResult = std::static_pointer_cast(fileWriter_) - ->openFile(streamSampleRate_, streamChannelCount_, maxBufferSizeInFrames_, ""); + ->openFile(streamSampleRate_, streamChannelCount_, streamMaxBufferSizeInFrames_, ""); if (!fileResult.is_ok()) { return Result::Err( @@ -293,7 +299,7 @@ Result AndroidAudioRecorder::setOnAudioReadyCallback( if (!isIdle()) { std::static_pointer_cast(dataCallback_) - ->prepare(streamSampleRate_, streamChannelCount_, maxBufferSizeInFrames_); + ->prepare(streamSampleRate_, streamChannelCount_, streamMaxBufferSizeInFrames_); } callbackOutputEnabled_.store(true, std::memory_order_release); @@ -319,8 +325,9 @@ void AndroidAudioRecorder::connect(const std::shared_ptr &n adapterNode_ = node; if (!isIdle()) { - tempArray_ = std::make_shared(maxBufferSizeInFrames_); - adapterNode_->init(maxBufferSizeInFrames_, streamChannelCount_); + deinterleavingBuffer_ = std::make_shared( + streamMaxBufferSizeInFrames_, streamChannelCount_, streamSampleRate_); + adapterNode_->init(streamMaxBufferSizeInFrames_, streamChannelCount_); } isConnected_.store(true, std::memory_order_release); @@ -332,7 +339,7 @@ void AndroidAudioRecorder::connect(const std::shared_ptr &n void AndroidAudioRecorder::disconnect() { std::scoped_lock adapterLock(adapterNodeMutex_); isConnected_.store(false, std::memory_order_release); - tempArray_ = nullptr; + deinterleavingBuffer_ = nullptr; adapterNode_ = nullptr; } @@ -369,14 +376,11 @@ oboe::DataCallbackResult AndroidAudioRecorder::onAudioReady( if (isConnected()) { if (auto adapterLock = Locker::tryLock(adapterNodeMutex_)) { - for (int channel = 0; channel < streamChannelCount_; ++channel) { - auto channelData = tempArray_->span(); - for (int frame = 0; frame < numFrames; ++frame) { - channelData[frame] = - static_cast(audioData)[frame * streamChannelCount_ + channel]; - } - - adapterNode_->buff_[channel]->write(*tempArray_, numFrames); + auto const data = static_cast(audioData); + deinterleavingBuffer_->deinterleaveFrom(data, numFrames); + + for (int ch = 0; ch < streamChannelCount_; ++ch) { + adapterNode_->buff_[ch]->write(*deinterleavingBuffer_->getChannel(ch), numFrames); } } } diff --git a/packages/react-native-audio-api/android/src/main/cpp/audioapi/android/core/AndroidAudioRecorder.h b/packages/react-native-audio-api/android/src/main/cpp/audioapi/android/core/AndroidAudioRecorder.h index 7a242c479..05602cb10 100644 --- a/packages/react-native-audio-api/android/src/main/cpp/audioapi/android/core/AndroidAudioRecorder.h +++ b/packages/react-native-audio-api/android/src/main/cpp/audioapi/android/core/AndroidAudioRecorder.h @@ -55,8 +55,11 @@ class AndroidAudioRecorder : public oboe::AudioStreamCallback, public AudioRecor void onErrorAfterClose(oboe::AudioStream *oboeStream, oboe::Result error) override; private: + std::shared_ptr deinterleavingBuffer_; + float streamSampleRate_; int32_t streamChannelCount_; + int32_t streamMaxBufferSizeInFrames_; facebook::jni::global_ref nativeAudioRecorder_; diff --git a/packages/react-native-audio-api/android/src/main/cpp/audioapi/android/core/utils/AndroidRecorderCallback.cpp b/packages/react-native-audio-api/android/src/main/cpp/audioapi/android/core/utils/AndroidRecorderCallback.cpp index c27f3a431..bccc4dde7 100644 --- a/packages/react-native-audio-api/android/src/main/cpp/audioapi/android/core/utils/AndroidRecorderCallback.cpp +++ b/packages/react-native-audio-api/android/src/main/cpp/audioapi/android/core/utils/AndroidRecorderCallback.cpp @@ -96,7 +96,8 @@ Result AndroidRecorderCallback::prepare( processingBufferLength_ = std::max(processingBufferLength_, (ma_uint64)maxInputBufferLength_); - tempArray_ = std::make_shared(processingBufferLength_); + deinterleavingBuffer_ = + std::make_shared(processingBufferLength_, channelCount_, sampleRate_); processingBuffer_ = ma_malloc( processingBufferLength_ * channelCount_ * ma_get_bytes_per_sample(ma_format_f32), nullptr); @@ -150,15 +151,10 @@ void AndroidRecorderCallback::receiveAudioData(void *data, int numFrames) { /// @param numFrames Number of frames in the audio data. void AndroidRecorderCallback::deinterleaveAndPushAudioData(void *data, int numFrames) { auto *inputData = static_cast(data); + deinterleavingBuffer_->deinterleaveFrom(inputData, numFrames); - for (int channel = 0; channel < channelCount_; ++channel) { - auto channelData = tempArray_->span(); - - for (int frame = 0; frame < numFrames; ++frame) { - channelData[frame] = inputData[frame * channelCount_ + channel]; - } - - circularBus_[channel]->push_back(*tempArray_, numFrames); + for (int ch = 0; ch < channelCount_; ++ch) { + circularBus_[ch]->push_back(*deinterleavingBuffer_->getChannel(ch), numFrames); } } diff --git a/packages/react-native-audio-api/android/src/main/cpp/audioapi/android/core/utils/AndroidRecorderCallback.h b/packages/react-native-audio-api/android/src/main/cpp/audioapi/android/core/utils/AndroidRecorderCallback.h index 614967462..51c9633d0 100644 --- a/packages/react-native-audio-api/android/src/main/cpp/audioapi/android/core/utils/AndroidRecorderCallback.h +++ b/packages/react-native-audio-api/android/src/main/cpp/audioapi/android/core/utils/AndroidRecorderCallback.h @@ -44,6 +44,8 @@ class AndroidRecorderCallback : public AudioRecorderCallback { ma_uint64 processingBufferLength_{0}; std::unique_ptr converter_{nullptr}; + std::shared_ptr deinterleavingBuffer_; + void deinterleaveAndPushAudioData(void *data, int numFrames); private: diff --git a/packages/react-native-audio-api/common/cpp/audioapi/core/analysis/AnalyserNode.cpp b/packages/react-native-audio-api/common/cpp/audioapi/core/analysis/AnalyserNode.cpp index 99d07d7e2..014f8ab80 100644 --- a/packages/react-native-audio-api/common/cpp/audioapi/core/analysis/AnalyserNode.cpp +++ b/packages/react-native-audio-api/common/cpp/audioapi/core/analysis/AnalyserNode.cpp @@ -126,8 +126,7 @@ void AnalyserNode::getByteFrequencyData(uint8_t *data, int length) { void AnalyserNode::getFloatTimeDomainData(float *data, int length) { auto size = std::min(fftSize_, length); - inputArray_->pop_back(*tempArray_, size, std::max(0, fftSize_ - size), true); - tempArray_->copyTo(data, 0, 0, size); + inputArray_->pop_back(data, size, std::max(0, fftSize_ - size), true); } void AnalyserNode::getByteTimeDomainData(uint8_t *data, int length) { diff --git a/packages/react-native-audio-api/common/cpp/audioapi/core/inputs/AudioRecorder.h b/packages/react-native-audio-api/common/cpp/audioapi/core/inputs/AudioRecorder.h index 72bca381d..3c117c9a1 100644 --- a/packages/react-native-audio-api/common/cpp/audioapi/core/inputs/AudioRecorder.h +++ b/packages/react-native-audio-api/common/cpp/audioapi/core/inputs/AudioRecorder.h @@ -66,9 +66,6 @@ class AudioRecorder { std::atomic fileOutputEnabled_{false}; std::atomic callbackOutputEnabled_{false}; - std::shared_ptr tempArray_; - size_t maxBufferSizeInFrames_ = 0; - std::mutex callbackMutex_; std::mutex fileWriterMutex_; std::mutex errorCallbackMutex_; diff --git a/packages/react-native-audio-api/common/cpp/audioapi/core/utils/AudioRecorderCallback.h b/packages/react-native-audio-api/common/cpp/audioapi/core/utils/AudioRecorderCallback.h index 3b5746791..fb2141cd7 100644 --- a/packages/react-native-audio-api/common/cpp/audioapi/core/utils/AudioRecorderCallback.h +++ b/packages/react-native-audio-api/common/cpp/audioapi/core/utils/AudioRecorderCallback.h @@ -43,8 +43,6 @@ class AudioRecorderCallback { uint64_t callbackId_; size_t ringBufferSize_; - std::shared_ptr tempArray_; - std::atomic errorCallbackId_{0}; std::shared_ptr audioEventHandlerRegistry_; diff --git a/packages/react-native-audio-api/common/cpp/audioapi/utils/CircularAudioArray.cpp b/packages/react-native-audio-api/common/cpp/audioapi/utils/CircularAudioArray.cpp index a0433bfc6..a09faa09d 100644 --- a/packages/react-native-audio-api/common/cpp/audioapi/utils/CircularAudioArray.cpp +++ b/packages/react-native-audio-api/common/cpp/audioapi/utils/CircularAudioArray.cpp @@ -7,43 +7,51 @@ namespace audioapi { CircularAudioArray::CircularAudioArray(size_t size) : AudioArray(size) {} void CircularAudioArray::push_back(const AudioArray & data, size_t size, bool skipAvailableSpaceCheck) { - if (size > size_) { - throw std::overflow_error("size exceeds CircularAudioArray size_"); - } - - if (size > getAvailableSpace() && !skipAvailableSpaceCheck) { - throw std::overflow_error("not enough space in CircularAudioArray"); - } - - if (vWriteIndex_ + size > size_) { - auto partSize = size_ - vWriteIndex_; - copy(data, 0, vWriteIndex_, partSize); - copy(data, partSize, 0, size - partSize); - } else { - copy(data, 0, vWriteIndex_, size); - } - - vWriteIndex_ = vWriteIndex_ + size > size_ ? vWriteIndex_ + size - size_ : vWriteIndex_ + size; + push_back(data.begin(), size, skipAvailableSpaceCheck); +} + +void CircularAudioArray::push_back(const float *data, size_t size, bool skipAvailableSpaceCheck) { + if (size > size_) { + throw std::overflow_error("size exceeds CircularAudioArray size_"); + } + + if (size > getAvailableSpace() && !skipAvailableSpaceCheck) { + throw std::overflow_error("not enough space in CircularAudioArray"); + } + + if (vWriteIndex_ + size > size_) { + auto partSize = size_ - vWriteIndex_; + copy(data, 0, vWriteIndex_, partSize); + copy(data, partSize, 0, size - partSize); + } else { + copy(data, 0, vWriteIndex_, size); + } + + vWriteIndex_ = vWriteIndex_ + size > size_ ? vWriteIndex_ + size - size_ : vWriteIndex_ + size; } void CircularAudioArray::pop_front(AudioArray &data, size_t size, bool skipAvailableDataCheck) { - if (size > size_) { - throw std::overflow_error("size exceeds CircularAudioArray size_"); - } - - if (size > getNumberOfAvailableFrames() && !skipAvailableDataCheck) { - throw std::overflow_error("not enough data in CircularAudioArray"); - } - - if (vReadIndex_ + size > size_) { - auto partSize = size_ - vReadIndex_; - data.copy(*this, vReadIndex_, 0, partSize); - data.copy(*this, 0, partSize, size - partSize); - } else { - data.copy(*this, vReadIndex_, 0, size); - } - - vReadIndex_ = vReadIndex_ + size > size_ ? vReadIndex_ + size - size_ : vReadIndex_ + size; + pop_front(data.begin(), size, skipAvailableDataCheck); +} + +void CircularAudioArray::pop_front(float *data, size_t size, bool skipAvailableDataCheck) { + if (size > size_) { + throw std::overflow_error("size exceeds CircularAudioArray size_"); + } + + if (size > getNumberOfAvailableFrames() && !skipAvailableDataCheck) { + throw std::overflow_error("not enough data in CircularAudioArray"); + } + + if (vReadIndex_ + size > size_) { + auto partSize = size_ - vReadIndex_; + copyTo(data, vReadIndex_, 0, partSize); + copyTo(data, 0, partSize, size - partSize); + } else { + copyTo(data, vReadIndex_, 0, size); + } + + vReadIndex_ = vReadIndex_ + size > size_ ? vReadIndex_ + size - size_ : vReadIndex_ + size; } void CircularAudioArray::pop_back( @@ -51,25 +59,30 @@ void CircularAudioArray::pop_back( size_t size, size_t offset, bool skipAvailableDataCheck) { - if (size > size_) { - throw std::overflow_error("size exceeds CircularAudioArray size_"); - } - - if (size + offset > getNumberOfAvailableFrames() && !skipAvailableDataCheck) { - throw std::overflow_error("not enough data in CircularAudioArray"); - } - - if (vWriteIndex_ <= offset) { - data.copy(*this, size_ - (offset - vWriteIndex_) - size, 0, size); - } else if (vWriteIndex_ <= size + offset) { - auto partSize = size + offset - vWriteIndex_; - data.copy(*this, size_ - partSize, 0, partSize); - data.copy(*this, 0, partSize, size - partSize); - } else { - data.copy(*this, vWriteIndex_ - size - offset, 0, size); - } - - vReadIndex_ = vWriteIndex_ - offset < 0 ? size + vWriteIndex_ - offset : vWriteIndex_ - offset; + pop_back(data.begin(), size, offset, skipAvailableDataCheck); +} + +void CircularAudioArray::pop_back(float *data, size_t size, size_t offset, + bool skipAvailableDataCheck) { + if (size > size_) { + throw std::overflow_error("size exceeds CircularAudioArray size_"); + } + + if (size + offset > getNumberOfAvailableFrames() && !skipAvailableDataCheck) { + throw std::overflow_error("not enough data in CircularAudioArray"); + } + + if (vWriteIndex_ <= offset) { + copyTo(data, size_ - (offset - vWriteIndex_) - size, 0, size); + } else if (vWriteIndex_ <= size + offset) { + auto partSize = size + offset - vWriteIndex_; + copyTo(data, size_ - partSize, 0, partSize); + copyTo(data, 0, partSize, size - partSize); + } else { + copyTo(data, vWriteIndex_ - size - offset, 0, size); + } + + vReadIndex_ = vWriteIndex_ - offset < 0 ? size + vWriteIndex_ - offset : vWriteIndex_ - offset; } size_t CircularAudioArray::getNumberOfAvailableFrames() const { diff --git a/packages/react-native-audio-api/common/cpp/audioapi/utils/CircularAudioArray.h b/packages/react-native-audio-api/common/cpp/audioapi/utils/CircularAudioArray.h index 999af4fce..757ed2098 100644 --- a/packages/react-native-audio-api/common/cpp/audioapi/utils/CircularAudioArray.h +++ b/packages/react-native-audio-api/common/cpp/audioapi/utils/CircularAudioArray.h @@ -12,9 +12,14 @@ class CircularAudioArray : public AudioArray { ~CircularAudioArray() = default; void push_back(const AudioArray &data, size_t size, bool skipAvailableSpaceCheck = false); + void push_back(const float *data, size_t size, bool skipAvailableSpaceCheck = false); + void pop_front(AudioArray &data, size_t size, bool skipAvailableDataCheck = false); + void pop_front(float *data, size_t size, bool skipAvailableDataCheck = false); + void pop_back(AudioArray &data, size_t size, size_t offset = 0, bool skipAvailableDataCheck = false); + void pop_back(float *data, size_t size, size_t offset = 0, bool skipAvailableDataCheck = false); [[nodiscard]] size_t getNumberOfAvailableFrames() const; diff --git a/packages/react-native-audio-api/common/cpp/audioapi/utils/CircularOverflowableAudioArray.cpp b/packages/react-native-audio-api/common/cpp/audioapi/utils/CircularOverflowableAudioArray.cpp index 66b6c852a..eab7f11e5 100644 --- a/packages/react-native-audio-api/common/cpp/audioapi/utils/CircularOverflowableAudioArray.cpp +++ b/packages/react-native-audio-api/common/cpp/audioapi/utils/CircularOverflowableAudioArray.cpp @@ -9,45 +9,53 @@ CircularOverflowableAudioArray::CircularOverflowableAudioArray(size_t size) noex : AudioArray(size) {} void CircularOverflowableAudioArray::write(const AudioArray &data, const size_t size) { - size_t writeIndex = vWriteIndex_.load(std::memory_order_relaxed); - - if (size > size_) { - return; // Ignore write if size exceeds buffer size - } - - /// Advances the read index if there is not enough space - readLock_.lock(); - size_t availableSpace = (size_ + vReadIndex_ - writeIndex - 1) % size_; - if (size > availableSpace) { - vReadIndex_ = (writeIndex + size + 1) % size_; - } - readLock_.unlock(); - - size_t partSize = size_ - writeIndex; - if (size > partSize) { - copy(data, 0, writeIndex, partSize); - copy(data, partSize, 0, size - partSize); - } else { - copy(data, 0, writeIndex, size); - } - vWriteIndex_.store((writeIndex + size) % size_, std::memory_order_relaxed); + write(data.begin(), size); +} + +void CircularOverflowableAudioArray::write(const float *data, size_t size) { + size_t writeIndex = vWriteIndex_.load(std::memory_order_relaxed); + + if (size > size_) { + return; // Ignore write if size exceeds buffer size + } + + /// Advances the read index if there is not enough space + readLock_.lock(); + size_t availableSpace = (size_ + vReadIndex_ - writeIndex - 1) % size_; + if (size > availableSpace) { + vReadIndex_ = (writeIndex + size + 1) % size_; + } + readLock_.unlock(); + + size_t partSize = size_ - writeIndex; + if (size > partSize) { + copy(data, 0, writeIndex, partSize); + copy(data, partSize, 0, size - partSize); + } else { + copy(data, 0, writeIndex, size); + } + vWriteIndex_.store((writeIndex + size) % size_, std::memory_order_relaxed); } size_t CircularOverflowableAudioArray::read(AudioArray &data, size_t size) const { - readLock_.lock(); - size_t availableSpace = getAvailableSpace(); - size_t readSize = std::min(size, availableSpace); - - size_t partSize = size_ - vReadIndex_; - if (readSize > partSize) { - data.copy(*this, vReadIndex_, 0, partSize); - data.copy(*this, 0, partSize, readSize - partSize); - } else { - data.copy(*this, vReadIndex_, 0, readSize); - } - vReadIndex_ = (vReadIndex_ + readSize) % size_; - readLock_.unlock(); - return readSize; + return read(data.begin(), size); +} + +size_t CircularOverflowableAudioArray::read(float *data, size_t size) const { + readLock_.lock(); + size_t availableSpace = getAvailableSpace(); + size_t readSize = std::min(size, availableSpace); + + size_t partSize = size_ - vReadIndex_; + if (readSize > partSize) { + copyTo(data, vReadIndex_, 0, partSize); + copyTo(data, 0, partSize, readSize - partSize); + } else { + copyTo(data, vReadIndex_, 0, readSize); + } + vReadIndex_ = (vReadIndex_ + readSize) % size_; + readLock_.unlock(); + return readSize; } size_t CircularOverflowableAudioArray::getAvailableSpace() const { diff --git a/packages/react-native-audio-api/common/cpp/audioapi/utils/CircularOverflowableAudioArray.h b/packages/react-native-audio-api/common/cpp/audioapi/utils/CircularOverflowableAudioArray.h index 588c72d4e..449100423 100644 --- a/packages/react-native-audio-api/common/cpp/audioapi/utils/CircularOverflowableAudioArray.h +++ b/packages/react-native-audio-api/common/cpp/audioapi/utils/CircularOverflowableAudioArray.h @@ -25,12 +25,24 @@ class CircularOverflowableAudioArray : public AudioArray { /// @param size Number of frames to write. void write(const AudioArray &data, size_t size); + /// @brief Writes data to the circular buffer. + /// @note Might wait for read operation to finish if it is in progress. It ignores writes that exceed the buffer size. + /// @param data Pointer to the input buffer. + /// @param size Number of frames to write. + void write(const float *data, size_t size); + /// @brief Reads data from the circular buffer. - /// @param output Reference to output AudioArray. + /// @param data Reference to output AudioArray. /// @param size Number of frames to read. /// @return The number of frames actually read. size_t read(AudioArray &data, size_t size) const; + /// @brief Reads data from the circular buffer. + /// @param data Pointer to the output buffer. + /// @param size Number of frames to read. + /// @return The number of frames actually read. + size_t read(float *data, size_t size) const; + private: std::atomic vWriteIndex_ = {0}; mutable size_t vReadIndex_ = 0; // it is only used after acquiring readLock_ diff --git a/packages/react-native-audio-api/ios/audioapi/ios/core/IOSAudioRecorder.mm b/packages/react-native-audio-api/ios/audioapi/ios/core/IOSAudioRecorder.mm index 2436e4cfa..74c339c9a 100644 --- a/packages/react-native-audio-api/ios/audioapi/ios/core/IOSAudioRecorder.mm +++ b/packages/react-native-audio-api/ios/audioapi/ios/core/IOSAudioRecorder.mm @@ -53,8 +53,7 @@ for (size_t channel = 0; channel < adapterNode_->channelCount_; ++channel) { float *data = (float *)inputBuffer->mBuffers[channel].mData; - tempArray_->copy(data, 0, 0, numFrames); - adapterNode_->buff_[channel]->write(*tempArray_, numFrames); + adapterNode_->buff_[channel]->write(data, numFrames); } } } @@ -100,12 +99,12 @@ [AudioEngine.sharedInstance stopIfNecessary]; // Estimate the maximum input buffer lengths that can be expected from the sink node - maxBufferSizeInFrames_ = [nativeRecorder_ getBufferSize]; + size_t maxInputBufferLength = [nativeRecorder_ getBufferSize]; auto inputFormat = [nativeRecorder_ getInputFormat]; if (usesFileOutput()) { auto fileResult = std::static_pointer_cast(fileWriter_) - ->openFile(inputFormat, maxBufferSizeInFrames_, fileNameOverride); + ->openFile(inputFormat, maxInputBufferLength, fileNameOverride); if (fileResult.is_err()) { return Result::Err( @@ -117,7 +116,7 @@ if (usesCallback()) { auto callbackResult = std::static_pointer_cast(dataCallback_) - ->prepare(inputFormat, maxBufferSizeInFrames_); + ->prepare(inputFormat, maxInputBufferLength); if (callbackResult.is_err()) { return Result::Err( @@ -126,9 +125,8 @@ } if (isConnected()) { - tempArray_ = std::make_shared(maxBufferSizeInFrames_); // TODO: pass sample rate, in case conversion is necessary - adapterNode_->init(maxBufferSizeInFrames_, inputFormat.channelCount); + adapterNode_->init(maxInputBufferLength, inputFormat.channelCount); } [nativeRecorder_ start]; @@ -228,8 +226,8 @@ adapterNode_ = node; if (!isIdle()) { - tempArray_ = std::make_shared(maxBufferSizeInFrames_); - adapterNode_->init(maxBufferSizeInFrames_, [nativeRecorder_ getInputFormat].channelCount); + adapterNode_->init( + [nativeRecorder_ getBufferSize], [nativeRecorder_ getInputFormat].channelCount); } isConnected_.store(true, std::memory_order_release); @@ -241,7 +239,6 @@ void IOSAudioRecorder::disconnect() { std::scoped_lock lock(adapterNodeMutex_); - tempArray_ = nullptr; adapterNode_ = nullptr; isConnected_.store(false, std::memory_order_release); } diff --git a/packages/react-native-audio-api/ios/audioapi/ios/core/utils/IOSRecorderCallback.mm b/packages/react-native-audio-api/ios/audioapi/ios/core/utils/IOSRecorderCallback.mm index 2fa64d692..d922fb74c 100644 --- a/packages/react-native-audio-api/ios/audioapi/ios/core/utils/IOSRecorderCallback.mm +++ b/packages/react-native-audio-api/ios/audioapi/ios/core/utils/IOSRecorderCallback.mm @@ -72,8 +72,6 @@ converterOutputBufferSize_ = std::max( (double)maxInputBufferLength, sampleRate_ / bufferFormat.sampleRate * maxInputBufferLength); - tempArray_ = std::make_shared(converterOutputBufferSize_); - callbackFormat_ = [[AVAudioFormat alloc] initWithCommonFormat:AVAudioPCMFormatFloat32 sampleRate:sampleRate_ channels:channelCount_ @@ -151,10 +149,8 @@ !bufferFormat_.isInterleaved) { // Directly write to circular buffer for (int i = 0; i < channelCount_; ++i) { - auto *inputChannel = static_cast(inputBuffer->mBuffers[i].mData); - - tempArray_->copy(inputChannel, 0, 0, numFrames); - circularBus_[i]->push_back(*tempArray_, numFrames); + auto *data = static_cast(inputBuffer->mBuffers[i].mData); + circularBus_[i]->push_back(data, numFrames); } if (circularBus_[0]->getNumberOfAvailableFrames() >= bufferLength_) { @@ -200,9 +196,7 @@ for (int i = 0; i < channelCount_; ++i) { auto *data = static_cast(converterOutputBuffer_.audioBufferList->mBuffers[i].mData); - - tempArray_->copy(data, 0, 0, outputFrameCount); - circularBus_[i]->push_back(*tempArray_, outputFrameCount); + circularBus_[i]->push_back(data, outputFrameCount); } if (circularBus_[0]->getNumberOfAvailableFrames() >= bufferLength_) { From 7a13612e143fa28e98ea67ecd377ead1ae3765c0 Mon Sep 17 00:00:00 2001 From: maciejmakowski2003 Date: Thu, 5 Feb 2026 17:42:52 +0100 Subject: [PATCH 25/30] chore: requuested changes from code review --- .../android/core/AndroidAudioRecorder.cpp | 2 +- .../core/utils/AndroidRecorderCallback.cpp | 2 +- .../android/core/utils/AudioDecoder.cpp | 2 +- .../common/cpp/audioapi/core/AudioNode.h | 2 +- .../audioapi/core/effects/ConvolverNode.cpp | 6 +- .../cpp/audioapi/core/effects/GainNode.cpp | 2 +- .../audioapi/core/effects/WaveShaperNode.cpp | 4 +- .../cpp/audioapi/core/effects/WorkletNode.cpp | 2 +- .../core/effects/WorkletProcessingNode.cpp | 4 +- .../cpp/audioapi/core/inputs/AudioRecorder.h | 1 - .../sources/AudioBufferBaseSourceNode.cpp | 10 +-- .../core/sources/AudioBufferBaseSourceNode.h | 2 +- .../sources/AudioBufferQueueSourceNode.cpp | 2 +- .../core/sources/AudioBufferSourceNode.cpp | 42 +++++----- .../core/sources/AudioBufferSourceNode.h | 2 +- .../core/sources/ConstantSourceNode.cpp | 2 +- .../audioapi/core/sources/OscillatorNode.cpp | 2 +- .../core/sources/RecorderAdapterNode.cpp | 10 +-- .../core/sources/RecorderAdapterNode.h | 2 +- .../audioapi/core/sources/StreamerNode.cpp | 22 +++--- .../cpp/audioapi/core/sources/StreamerNode.h | 6 +- .../core/sources/WorkletSourceNode.cpp | 2 +- .../audioapi/core/utils/AudioStretcher.cpp | 4 +- .../common/cpp/audioapi/dsp/AudioUtils.hpp | 3 +- .../common/cpp/audioapi/dsp/Resampler.cpp | 2 +- .../audioapi/libs/ffmpeg/FFmpegDecoding.cpp | 2 +- .../common/cpp/audioapi/utils/AudioArray.cpp | 31 +++----- .../common/cpp/audioapi/utils/AudioArray.h | 22 +++--- .../common/cpp/audioapi/utils/AudioBuffer.cpp | 78 +++++++++---------- .../common/cpp/audioapi/utils/AudioBuffer.h | 19 ++--- .../ios/audioapi/ios/core/IOSAudioPlayer.mm | 2 +- .../audioapi/ios/core/utils/AudioDecoder.mm | 2 +- .../ios/core/utils/IOSRecorderCallback.mm | 8 +- 33 files changed, 144 insertions(+), 160 deletions(-) diff --git a/packages/react-native-audio-api/android/src/main/cpp/audioapi/android/core/AndroidAudioRecorder.cpp b/packages/react-native-audio-api/android/src/main/cpp/audioapi/android/core/AndroidAudioRecorder.cpp index 3c589c345..6be58a7f5 100644 --- a/packages/react-native-audio-api/android/src/main/cpp/audioapi/android/core/AndroidAudioRecorder.cpp +++ b/packages/react-native-audio-api/android/src/main/cpp/audioapi/android/core/AndroidAudioRecorder.cpp @@ -379,7 +379,7 @@ oboe::DataCallbackResult AndroidAudioRecorder::onAudioReady( auto const data = static_cast(audioData); deinterleavingBuffer_->deinterleaveFrom(data, numFrames); - for (int ch = 0; ch < streamChannelCount_; ++ch) { + for (size_t ch = 0; ch < streamChannelCount_; ++ch) { adapterNode_->buff_[ch]->write(*deinterleavingBuffer_->getChannel(ch), numFrames); } } diff --git a/packages/react-native-audio-api/android/src/main/cpp/audioapi/android/core/utils/AndroidRecorderCallback.cpp b/packages/react-native-audio-api/android/src/main/cpp/audioapi/android/core/utils/AndroidRecorderCallback.cpp index bccc4dde7..5f102f381 100644 --- a/packages/react-native-audio-api/android/src/main/cpp/audioapi/android/core/utils/AndroidRecorderCallback.cpp +++ b/packages/react-native-audio-api/android/src/main/cpp/audioapi/android/core/utils/AndroidRecorderCallback.cpp @@ -153,7 +153,7 @@ void AndroidRecorderCallback::deinterleaveAndPushAudioData(void *data, int numFr auto *inputData = static_cast(data); deinterleavingBuffer_->deinterleaveFrom(inputData, numFrames); - for (int ch = 0; ch < channelCount_; ++ch) { + for (size_t ch = 0; ch < channelCount_; ++ch) { circularBus_[ch]->push_back(*deinterleavingBuffer_->getChannel(ch), numFrames); } } diff --git a/packages/react-native-audio-api/android/src/main/cpp/audioapi/android/core/utils/AudioDecoder.cpp b/packages/react-native-audio-api/android/src/main/cpp/audioapi/android/core/utils/AudioDecoder.cpp index 4fa157d2a..d7b3dd04a 100644 --- a/packages/react-native-audio-api/android/src/main/cpp/audioapi/android/core/utils/AudioDecoder.cpp +++ b/packages/react-native-audio-api/android/src/main/cpp/audioapi/android/core/utils/AudioDecoder.cpp @@ -160,7 +160,7 @@ std::shared_ptr AudioDecoder::decodeWithPCMInBase64( auto audioBuffer = std::make_shared(numFramesDecoded, inputChannelCount, inputSampleRate); - for (int ch = 0; ch < inputChannelCount; ++ch) { + for (size_t ch = 0; ch < inputChannelCount; ++ch) { auto channelData = audioBuffer->getChannel(ch)->span(); for (size_t i = 0; i < numFramesDecoded; ++i) { diff --git a/packages/react-native-audio-api/common/cpp/audioapi/core/AudioNode.h b/packages/react-native-audio-api/common/cpp/audioapi/core/AudioNode.h index 37578ff8c..df6aa6134 100644 --- a/packages/react-native-audio-api/common/cpp/audioapi/core/AudioNode.h +++ b/packages/react-native-audio-api/common/cpp/audioapi/core/AudioNode.h @@ -57,7 +57,7 @@ class AudioNode : public std::enable_shared_from_this { int numberOfInputs_ = 1; int numberOfOutputs_ = 1; - int channelCount_ = 2; + size_t channelCount_ = 2; ChannelCountMode channelCountMode_ = ChannelCountMode::MAX; ChannelInterpretation channelInterpretation_ = ChannelInterpretation::SPEAKERS; diff --git a/packages/react-native-audio-api/common/cpp/audioapi/core/effects/ConvolverNode.cpp b/packages/react-native-audio-api/common/cpp/audioapi/core/effects/ConvolverNode.cpp index 1deff6a10..0522619b8 100644 --- a/packages/react-native-audio-api/common/cpp/audioapi/core/effects/ConvolverNode.cpp +++ b/packages/react-native-audio-api/common/cpp/audioapi/core/effects/ConvolverNode.cpp @@ -58,7 +58,7 @@ void ConvolverNode::setBuffer(const std::shared_ptr &buffer) { calculateNormalizationScale(); threadPool_ = std::make_shared(4); convolvers_.clear(); - for (int i = 0; i < buffer->getNumberOfChannels(); ++i) { + for (size_t i = 0; i < buffer->getNumberOfChannels(); ++i) { convolvers_.emplace_back(); AudioArray channelData(*buffer->getChannel(i)); convolvers_.back().init(RENDER_QUANTUM_SIZE, channelData, buffer->getSize()); @@ -121,7 +121,7 @@ std::shared_ptr ConvolverNode::processNode( audioBuffer_->copy(*internalBuffer_, 0, 0, framesToProcess); int remainingFrames = internalBufferIndex_ - framesToProcess; if (remainingFrames > 0) { - for (int ch = 0; ch < internalBuffer_->getNumberOfChannels(); ++ch) { + for (size_t ch = 0; ch < internalBuffer_->getNumberOfChannels(); ++ch) { internalBuffer_->getChannel(ch)->copyWithin(framesToProcess, 0, remainingFrames); } } @@ -141,7 +141,7 @@ void ConvolverNode::calculateNormalizationScale() { float power = 0; - for (int channel = 0; channel < numberOfChannels; ++channel) { + for (size_t channel = 0; channel < numberOfChannels; ++channel) { float channelPower = 0; auto channelData = buffer_->getChannel(channel)->span(); for (int i = 0; i < length; ++i) { diff --git a/packages/react-native-audio-api/common/cpp/audioapi/core/effects/GainNode.cpp b/packages/react-native-audio-api/common/cpp/audioapi/core/effects/GainNode.cpp index 9334b768a..86fd99dec 100644 --- a/packages/react-native-audio-api/common/cpp/audioapi/core/effects/GainNode.cpp +++ b/packages/react-native-audio-api/common/cpp/audioapi/core/effects/GainNode.cpp @@ -33,7 +33,7 @@ std::shared_ptr GainNode::processNode( auto gainParamValues = gainParam_->processARateParam(framesToProcess, time); auto gainValues = gainParamValues->getChannel(0); - for (int i = 0; i < processingBuffer->getNumberOfChannels(); i += 1) { + for (size_t i = 0; i < processingBuffer->getNumberOfChannels(); i++) { auto channel = processingBuffer->getChannel(i); channel->multiply(*gainValues, framesToProcess); } diff --git a/packages/react-native-audio-api/common/cpp/audioapi/core/effects/WaveShaperNode.cpp b/packages/react-native-audio-api/common/cpp/audioapi/core/effects/WaveShaperNode.cpp index c010d70c2..49e9ef44d 100644 --- a/packages/react-native-audio-api/common/cpp/audioapi/core/effects/WaveShaperNode.cpp +++ b/packages/react-native-audio-api/common/cpp/audioapi/core/effects/WaveShaperNode.cpp @@ -17,7 +17,7 @@ WaveShaperNode::WaveShaperNode( : AudioNode(context, options), oversample_(options.oversample) { waveShapers_.reserve(6); - for (int i = 0; i < channelCount_; i++) { + for (size_t i = 0; i < channelCount_; i++) { waveShapers_.emplace_back(std::make_unique(nullptr)); } setCurve(options.curve); @@ -70,7 +70,7 @@ std::shared_ptr WaveShaperNode::processNode( return processingBuffer; } - for (int channel = 0; channel < processingBuffer->getNumberOfChannels(); channel++) { + for (size_t channel = 0; channel < processingBuffer->getNumberOfChannels(); channel++) { auto channelData = processingBuffer->getChannel(channel); waveShapers_[channel]->process(*channelData, framesToProcess); diff --git a/packages/react-native-audio-api/common/cpp/audioapi/core/effects/WorkletNode.cpp b/packages/react-native-audio-api/common/cpp/audioapi/core/effects/WorkletNode.cpp index 4cbdb79e8..cac5c720a 100644 --- a/packages/react-native-audio-api/common/cpp/audioapi/core/effects/WorkletNode.cpp +++ b/packages/react-native-audio-api/common/cpp/audioapi/core/effects/WorkletNode.cpp @@ -49,7 +49,7 @@ std::shared_ptr WorkletNode::processNode( workletRunner_.executeOnRuntimeSync([this, channelCount_](jsi::Runtime &uiRuntimeRaw) { /// Arguments preparation auto jsArray = jsi::Array(uiRuntimeRaw, channelCount_); - for (int ch = 0; ch < channelCount_; ch++) { + for (size_t ch = 0; ch < channelCount_; ch++) { auto sharedAudioArray = std::make_shared(bufferLength_); sharedAudioArray->copy(*buffer_->getChannel(ch)); auto sharedAudioArraySize = sharedAudioArray->size(); diff --git a/packages/react-native-audio-api/common/cpp/audioapi/core/effects/WorkletProcessingNode.cpp b/packages/react-native-audio-api/common/cpp/audioapi/core/effects/WorkletProcessingNode.cpp index 7aa0ca58e..f1bb4c642 100644 --- a/packages/react-native-audio-api/common/cpp/audioapi/core/effects/WorkletProcessingNode.cpp +++ b/packages/react-native-audio-api/common/cpp/audioapi/core/effects/WorkletProcessingNode.cpp @@ -29,7 +29,7 @@ std::shared_ptr WorkletProcessingNode::processNode( static_cast(processingBuffer->getNumberOfChannels())); // Copy input data to pre-allocated input buffers - for (int ch = 0; ch < channelCount; ch++) { + for (size_t ch = 0; ch < channelCount; ch++) { inputBuffsHandles_[ch]->copy(*processingBuffer->getChannel(ch), 0, 0, framesToProcess); } @@ -64,7 +64,7 @@ std::shared_ptr WorkletProcessingNode::processNode( }); // Copy processed output data back to the processing buffer or zero on failure - for (int ch = 0; ch < channelCount; ch++) { + for (size_t ch = 0; ch < channelCount; ch++) { auto channelData = processingBuffer->getChannel(ch); if (result.has_value()) { diff --git a/packages/react-native-audio-api/common/cpp/audioapi/core/inputs/AudioRecorder.h b/packages/react-native-audio-api/common/cpp/audioapi/core/inputs/AudioRecorder.h index 3c117c9a1..c2b196765 100644 --- a/packages/react-native-audio-api/common/cpp/audioapi/core/inputs/AudioRecorder.h +++ b/packages/react-native-audio-api/common/cpp/audioapi/core/inputs/AudioRecorder.h @@ -1,6 +1,5 @@ #pragma once -#include #include #include #include diff --git a/packages/react-native-audio-api/common/cpp/audioapi/core/sources/AudioBufferBaseSourceNode.cpp b/packages/react-native-audio-api/common/cpp/audioapi/core/sources/AudioBufferBaseSourceNode.cpp index 059c5a74b..ae421e033 100644 --- a/packages/react-native-audio-api/common/cpp/audioapi/core/sources/AudioBufferBaseSourceNode.cpp +++ b/packages/react-native-audio-api/common/cpp/audioapi/core/sources/AudioBufferBaseSourceNode.cpp @@ -24,7 +24,7 @@ AudioBufferBaseSourceNode::AudioBufferBaseSourceNode( playbackRateParam_ = std::make_shared( options.playbackRate, MOST_NEGATIVE_SINGLE_FLOAT, MOST_POSITIVE_SINGLE_FLOAT, context); - playbackRateBus_ = std::make_shared( + playbackRateBuffer_ = std::make_shared( RENDER_QUANTUM_SIZE * 3, channelCount_, context->getSampleRate()); stretch_ = std::make_shared>(); @@ -115,12 +115,12 @@ void AudioBufferBaseSourceNode::processWithPitchCorrection( auto detune = std::clamp(detuneParam_->processKRateParam(framesToProcess, time) / 100.0f, -12.0f, 12.0f); - playbackRateBus_->zero(); + playbackRateBuffer_->zero(); auto framesNeededToStretch = static_cast(playbackRate * static_cast(framesToProcess)); updatePlaybackInfo( - playbackRateBus_, + playbackRateBuffer_, framesNeededToStretch, startOffset, offsetLength, @@ -132,10 +132,10 @@ void AudioBufferBaseSourceNode::processWithPitchCorrection( return; } - processWithoutInterpolation(playbackRateBus_, startOffset, offsetLength, playbackRate); + processWithoutInterpolation(playbackRateBuffer_, startOffset, offsetLength, playbackRate); stretch_->process( - playbackRateBus_.get()[0], framesNeededToStretch, processingBuffer.get()[0], framesToProcess); + playbackRateBuffer_.get()[0], framesNeededToStretch, processingBuffer.get()[0], framesToProcess); if (detune != 0.0f) { stretch_->setTransposeSemitones(detune); diff --git a/packages/react-native-audio-api/common/cpp/audioapi/core/sources/AudioBufferBaseSourceNode.h b/packages/react-native-audio-api/common/cpp/audioapi/core/sources/AudioBufferBaseSourceNode.h index 4969cba4c..139594fdb 100644 --- a/packages/react-native-audio-api/common/cpp/audioapi/core/sources/AudioBufferBaseSourceNode.h +++ b/packages/react-native-audio-api/common/cpp/audioapi/core/sources/AudioBufferBaseSourceNode.h @@ -36,7 +36,7 @@ class AudioBufferBaseSourceNode : public AudioScheduledSourceNode { // pitch correction std::shared_ptr> stretch_; - std::shared_ptr playbackRateBus_; + std::shared_ptr playbackRateBuffer_; // k-rate params std::shared_ptr detuneParam_; diff --git a/packages/react-native-audio-api/common/cpp/audioapi/core/sources/AudioBufferQueueSourceNode.cpp b/packages/react-native-audio-api/common/cpp/audioapi/core/sources/AudioBufferQueueSourceNode.cpp index eac330254..c1d2844a6 100644 --- a/packages/react-native-audio-api/common/cpp/audioapi/core/sources/AudioBufferQueueSourceNode.cpp +++ b/packages/react-native-audio-api/common/cpp/audioapi/core/sources/AudioBufferQueueSourceNode.cpp @@ -279,7 +279,7 @@ void AudioBufferQueueSourceNode::processWithInterpolation( } } - for (int i = 0; i < processingBuffer->getNumberOfChannels(); i += 1) { + for (size_t i = 0; i < processingBuffer->getNumberOfChannels(); i += 1) { const auto destination = processingBuffer->getChannel(i)->span(); const auto currentSource = buffer->getChannel(i)->span(); diff --git a/packages/react-native-audio-api/common/cpp/audioapi/core/sources/AudioBufferSourceNode.cpp b/packages/react-native-audio-api/common/cpp/audioapi/core/sources/AudioBufferSourceNode.cpp index ddb17bc1c..f782fcd82 100644 --- a/packages/react-native-audio-api/common/cpp/audioapi/core/sources/AudioBufferSourceNode.cpp +++ b/packages/react-native-audio-api/common/cpp/audioapi/core/sources/AudioBufferSourceNode.cpp @@ -22,7 +22,7 @@ AudioBufferSourceNode::AudioBufferSourceNode( loopStart_(options.loopStart), loopEnd_(options.loopEnd) { buffer_ = std::shared_ptr(options.buffer); - alignedBus_ = std::shared_ptr(nullptr); + alignedBuffer_ = std::shared_ptr(nullptr); isInitialized_ = true; } @@ -31,7 +31,7 @@ AudioBufferSourceNode::~AudioBufferSourceNode() { Locker locker(getBufferLock()); buffer_.reset(); - alignedBus_.reset(); + alignedBuffer_.reset(); } bool AudioBufferSourceNode::getLoop() const { @@ -81,7 +81,7 @@ void AudioBufferSourceNode::setBuffer(const std::shared_ptr &buffer if (buffer == nullptr || context == nullptr) { buffer_ = std::shared_ptr(nullptr); - alignedBus_ = std::shared_ptr(nullptr); + alignedBuffer_ = std::shared_ptr(nullptr); loopEnd_ = 0; return; } @@ -89,23 +89,23 @@ void AudioBufferSourceNode::setBuffer(const std::shared_ptr &buffer buffer_ = buffer; channelCount_ = buffer_->getNumberOfChannels(); - stretch_->presetDefault(channelCount_, buffer_->getSampleRate()); + stretch_->presetDefault(static_cast(channelCount_), buffer_->getSampleRate()); if (pitchCorrection_) { int extraTailFrames = static_cast((getInputLatency() + getOutputLatency()) * context->getSampleRate()); size_t totalSize = buffer_->getSize() + extraTailFrames; - alignedBus_ = std::make_shared(totalSize, channelCount_, buffer_->getSampleRate()); - alignedBus_->copy(*buffer_, 0, 0, buffer_->getSize()); + alignedBuffer_ = std::make_shared(totalSize, channelCount_, buffer_->getSampleRate()); + alignedBuffer_->copy(*buffer_, 0, 0, buffer_->getSize()); - alignedBus_->zero(buffer_->getSize(), extraTailFrames); + alignedBuffer_->zero(buffer_->getSize(), extraTailFrames); } else { - alignedBus_ = std::make_shared(*buffer_); + alignedBuffer_ = std::make_shared(*buffer_); } audioBuffer_ = std::make_shared(RENDER_QUANTUM_SIZE, channelCount_, context->getSampleRate()); - playbackRateBus_ = std::make_shared( + playbackRateBuffer_ = std::make_shared( RENDER_QUANTUM_SIZE * 3, channelCount_, context->getSampleRate()); loopEnd_ = buffer_->getDuration(); @@ -118,23 +118,23 @@ void AudioBufferSourceNode::start(double when, double offset, double duration) { AudioScheduledSourceNode::stop(when + duration); } - if (!alignedBus_) { + if (!alignedBuffer_) { return; } offset = - std::min(offset, static_cast(alignedBus_->getSize()) / alignedBus_->getSampleRate()); + std::min(offset, static_cast(alignedBuffer_->getSize()) / alignedBuffer_->getSampleRate()); if (loop_) { offset = std::min(offset, loopEnd_); } - vReadIndex_ = static_cast(alignedBus_->getSampleRate() * offset); + vReadIndex_ = static_cast(alignedBuffer_->getSampleRate() * offset); } void AudioBufferSourceNode::disable() { AudioScheduledSourceNode::disable(); - alignedBus_.reset(); + alignedBuffer_.reset(); } void AudioBufferSourceNode::setOnLoopEndedCallbackId(uint64_t callbackId) { @@ -150,7 +150,7 @@ std::shared_ptr AudioBufferSourceNode::processNode( int framesToProcess) { if (auto locker = Locker::tryLock(getBufferLock())) { // No audio data to fill, zero the output and return. - if (!alignedBus_) { + if (!alignedBuffer_) { processingBuffer->zero(); return processingBuffer; } @@ -223,16 +223,16 @@ void AudioBufferSourceNode::processWithoutInterpolation( assert(readIndex >= 0); assert(writeIndex >= 0); - assert(readIndex + framesToCopy <= alignedBus_->getSize()); + assert(readIndex + framesToCopy <= alignedBuffer_->getSize()); assert(writeIndex + framesToCopy <= processingBuffer->getSize()); // Direction is forward, we can normally copy the data if (direction == 1) { - processingBuffer->copy(*alignedBus_, readIndex, writeIndex, framesToCopy); + processingBuffer->copy(*alignedBuffer_, readIndex, writeIndex, framesToCopy); } else { - for (int ch = 0; ch < processingBuffer->getNumberOfChannels(); ch += 1) { + for (size_t ch = 0; ch < processingBuffer->getNumberOfChannels(); ch += 1) { processingBuffer->getChannel(ch)->copyReverse( - *alignedBus_->getChannel(ch), readIndex, writeIndex, framesToCopy); + *alignedBuffer_->getChannel(ch), readIndex, writeIndex, framesToCopy); } } @@ -298,9 +298,9 @@ void AudioBufferSourceNode::processWithInterpolation( nextReadIndex = loop_ ? frameStart : readIndex; } - for (int i = 0; i < processingBuffer->getNumberOfChannels(); i += 1) { + for (size_t i = 0; i < processingBuffer->getNumberOfChannels(); i++) { auto destination = processingBuffer->getChannel(i)->span(); - const auto source = alignedBus_->getChannel(i)->span(); + const auto source = alignedBuffer_->getChannel(i)->span(); destination[writeIndex] = dsp::linearInterpolate(source, readIndex, nextReadIndex, factor); } @@ -329,7 +329,7 @@ double AudioBufferSourceNode::getVirtualStartFrame(float sampleRate) const { } double AudioBufferSourceNode::getVirtualEndFrame(float sampleRate) { - auto inputBufferLength = static_cast(alignedBus_->getSize()); + auto inputBufferLength = static_cast(alignedBuffer_->getSize()); auto loopEndFrame = loopEnd_ * sampleRate; return loop_ && loopEndFrame > 0 && loopStart_ < loopEnd_ diff --git a/packages/react-native-audio-api/common/cpp/audioapi/core/sources/AudioBufferSourceNode.h b/packages/react-native-audio-api/common/cpp/audioapi/core/sources/AudioBufferSourceNode.h index 0667ad9d2..5a28a2c95 100644 --- a/packages/react-native-audio-api/common/cpp/audioapi/core/sources/AudioBufferSourceNode.h +++ b/packages/react-native-audio-api/common/cpp/audioapi/core/sources/AudioBufferSourceNode.h @@ -55,7 +55,7 @@ class AudioBufferSourceNode : public AudioBufferBaseSourceNode { // User provided buffer std::shared_ptr buffer_; - std::shared_ptr alignedBus_; + std::shared_ptr alignedBuffer_; std::atomic onLoopEndedCallbackId_ = 0; // 0 means no callback void sendOnLoopEndedEvent(); diff --git a/packages/react-native-audio-api/common/cpp/audioapi/core/sources/ConstantSourceNode.cpp b/packages/react-native-audio-api/common/cpp/audioapi/core/sources/ConstantSourceNode.cpp index ca728f201..bbe14374a 100644 --- a/packages/react-native-audio-api/common/cpp/audioapi/core/sources/ConstantSourceNode.cpp +++ b/packages/react-native-audio-api/common/cpp/audioapi/core/sources/ConstantSourceNode.cpp @@ -48,7 +48,7 @@ std::shared_ptr ConstantSourceNode::processNode( auto offsetChannel = offsetParam_->processARateParam(framesToProcess, context->getCurrentTime())->getChannel(0); - for (int channel = 0; channel < processingBuffer->getNumberOfChannels(); ++channel) { + for (size_t channel = 0; channel < processingBuffer->getNumberOfChannels(); ++channel) { processingBuffer->getChannel(channel)->copy( *offsetChannel, startOffset, startOffset, offsetLength); } diff --git a/packages/react-native-audio-api/common/cpp/audioapi/core/sources/OscillatorNode.cpp b/packages/react-native-audio-api/common/cpp/audioapi/core/sources/OscillatorNode.cpp index cfab566fc..2c5516c86 100644 --- a/packages/react-native-audio-api/common/cpp/audioapi/core/sources/OscillatorNode.cpp +++ b/packages/react-native-audio-api/common/cpp/audioapi/core/sources/OscillatorNode.cpp @@ -92,7 +92,7 @@ std::shared_ptr OscillatorNode::processNode( auto finalPhase = phase_; - for (int ch = 0; ch < numChannels; ch += 1) { + for (size_t ch = 0; ch < numChannels; ch += 1) { auto channelSpan = processingBuffer->getChannel(ch)->span(); float currentPhase = phase_; diff --git a/packages/react-native-audio-api/common/cpp/audioapi/core/sources/RecorderAdapterNode.cpp b/packages/react-native-audio-api/common/cpp/audioapi/core/sources/RecorderAdapterNode.cpp index 73bac391d..72cecd775 100644 --- a/packages/react-native-audio-api/common/cpp/audioapi/core/sources/RecorderAdapterNode.cpp +++ b/packages/react-native-audio-api/common/cpp/audioapi/core/sources/RecorderAdapterNode.cpp @@ -41,7 +41,7 @@ void RecorderAdapterNode::init(size_t bufferSize, int channelCount) { // we would need to add sample rate conversion as well or other weird bullshit like resampling // context output and not enforcing anything on the system output/input configuration. // A lot of words for a couple of lines of implementation :shrug: - adapterOutputBus_ = + adapterOutputBuffer_ = std::make_shared(RENDER_QUANTUM_SIZE, channelCount_, context->getSampleRate()); isInitialized_ = true; } @@ -49,7 +49,7 @@ void RecorderAdapterNode::init(size_t bufferSize, int channelCount) { void RecorderAdapterNode::cleanup() { isInitialized_ = false; buff_.clear(); - adapterOutputBus_.reset(); + adapterOutputBuffer_.reset(); } std::shared_ptr RecorderAdapterNode::processNode( @@ -62,15 +62,15 @@ std::shared_ptr RecorderAdapterNode::processNode( readFrames(framesToProcess); - processingBuffer->sum(*adapterOutputBus_, ChannelInterpretation::SPEAKERS); + processingBuffer->sum(*adapterOutputBuffer_, ChannelInterpretation::SPEAKERS); return processingBuffer; } void RecorderAdapterNode::readFrames(const size_t framesToRead) { - adapterOutputBus_->zero(); + adapterOutputBuffer_->zero(); for (size_t channel = 0; channel < channelCount_; ++channel) { - buff_[channel]->read(*adapterOutputBus_->getChannel(channel), framesToRead); + buff_[channel]->read(*adapterOutputBuffer_->getChannel(channel), framesToRead); } } diff --git a/packages/react-native-audio-api/common/cpp/audioapi/core/sources/RecorderAdapterNode.h b/packages/react-native-audio-api/common/cpp/audioapi/core/sources/RecorderAdapterNode.h index 6d98e90a2..0e17b264d 100644 --- a/packages/react-native-audio-api/common/cpp/audioapi/core/sources/RecorderAdapterNode.h +++ b/packages/react-native-audio-api/common/cpp/audioapi/core/sources/RecorderAdapterNode.h @@ -36,7 +36,7 @@ class RecorderAdapterNode : public AudioNode { std::shared_ptr processNode( const std::shared_ptr &processingBuffer, int framesToProcess) override; - std::shared_ptr adapterOutputBus_; + std::shared_ptr adapterOutputBuffer_; private: /// @brief Read audio frames from the recorder's internal circular buffer into output buffers. diff --git a/packages/react-native-audio-api/common/cpp/audioapi/core/sources/StreamerNode.cpp b/packages/react-native-audio-api/common/cpp/audioapi/core/sources/StreamerNode.cpp index b48ee9e38..078c01120 100644 --- a/packages/react-native-audio-api/common/cpp/audioapi/core/sources/StreamerNode.cpp +++ b/packages/react-native-audio-api/common/cpp/audioapi/core/sources/StreamerNode.cpp @@ -34,8 +34,8 @@ StreamerNode::StreamerNode( frame_(nullptr), swrCtx_(nullptr), resampledData_(nullptr), - bufferedBus_(nullptr), - bufferedBusSize_(0), + bufferedAudioBuffer_(nullptr), + bufferedAudioBufferSize_(0), audio_stream_index_(-1), maxResampledSamples_(0), processedSamples_(0) {} @@ -131,26 +131,26 @@ std::shared_ptr StreamerNode::processNode( return processingBuffer; } - int bufferRemaining = bufferedBusSize_ - processedSamples_; + int bufferRemaining = bufferedAudioBufferSize_ - processedSamples_; int alreadyProcessed = 0; if (bufferRemaining < framesToProcess) { - if (bufferedBus_ != nullptr) { - processingBuffer->copy(*bufferedBus_, processedSamples_, 0, bufferRemaining); + if (bufferedAudioBuffer_ != nullptr) { + processingBuffer->copy(*bufferedAudioBuffer_, processedSamples_, 0, bufferRemaining); framesToProcess -= bufferRemaining; alreadyProcessed += bufferRemaining; } StreamingData data; auto res = receiver_.try_receive(data); if (res == channels::spsc::ResponseStatus::SUCCESS) { - bufferedBus_ = std::make_shared(std::move(data.buffer)); - bufferedBusSize_ = data.size; + bufferedAudioBuffer_ = std::make_shared(std::move(data.buffer)); + bufferedAudioBufferSize_ = data.size; processedSamples_ = 0; } else { - bufferedBus_ = nullptr; + bufferedAudioBuffer_ = nullptr; } } - if (bufferedBus_ != nullptr) { - processingBuffer->copy(*bufferedBus_, processedSamples_, alreadyProcessed, framesToProcess); + if (bufferedAudioBuffer_ != nullptr) { + processingBuffer->copy(*bufferedAudioBuffer_, processedSamples_, alreadyProcessed, framesToProcess); processedSamples_ += framesToProcess; } #endif // RN_AUDIO_API_FFMPEG_DISABLED @@ -261,7 +261,7 @@ bool StreamerNode::processFrameWithResampler( AudioBuffer buffer = AudioBuffer(converted_samples, codecCtx_->ch_layout.nb_channels, context->getSampleRate()); - for (int ch = 0; ch < codecCtx_->ch_layout.nb_channels; ch++) { + for (size_t ch = 0; ch < codecCtx_->ch_layout.nb_channels; ch++) { auto *src = reinterpret_cast(resampledData_[ch]); buffer.getChannel(ch)->copy(src, 0, 0, converted_samples); } diff --git a/packages/react-native-audio-api/common/cpp/audioapi/core/sources/StreamerNode.h b/packages/react-native-audio-api/common/cpp/audioapi/core/sources/StreamerNode.h index 70b48a268..ed3983f40 100644 --- a/packages/react-native-audio-api/common/cpp/audioapi/core/sources/StreamerNode.h +++ b/packages/react-native-audio-api/common/cpp/audioapi/core/sources/StreamerNode.h @@ -97,9 +97,9 @@ class StreamerNode : public AudioScheduledSourceNode { SwrContext *swrCtx_; uint8_t **resampledData_; // weird ffmpeg way of using raw byte pointers for resampled data - std::shared_ptr bufferedBus_; // audio buffer for buffering hls frames - size_t bufferedBusSize_; // size of currently buffered buffer - int audio_stream_index_; // index of the audio stream channel in the input + std::shared_ptr bufferedAudioBuffer_; // audio buffer for buffering hls frames + size_t bufferedAudioBufferSize_; // size of currently buffered buffer + int audio_stream_index_; // index of the audio stream channel in the input int maxResampledSamples_; size_t processedSamples_; diff --git a/packages/react-native-audio-api/common/cpp/audioapi/core/sources/WorkletSourceNode.cpp b/packages/react-native-audio-api/common/cpp/audioapi/core/sources/WorkletSourceNode.cpp index 8637ee776..09d9450a8 100644 --- a/packages/react-native-audio-api/common/cpp/audioapi/core/sources/WorkletSourceNode.cpp +++ b/packages/react-native-audio-api/common/cpp/audioapi/core/sources/WorkletSourceNode.cpp @@ -77,7 +77,7 @@ std::shared_ptr WorkletSourceNode::processNode( } // Copy the processed data back to the AudioBuffer - for (int i = 0; i < outputChannelCount; ++i) { + for (size_t i = 0; i < outputChannelCount; ++i) { processingBuffer->getChannel(i)->copy( *outputBuffsHandles_[i], 0, startOffset, nonSilentFramesToProcess); } diff --git a/packages/react-native-audio-api/common/cpp/audioapi/core/utils/AudioStretcher.cpp b/packages/react-native-audio-api/common/cpp/audioapi/core/utils/AudioStretcher.cpp index 647787c28..9e4ff8cdd 100644 --- a/packages/react-native-audio-api/common/cpp/audioapi/core/utils/AudioStretcher.cpp +++ b/packages/react-native-audio-api/common/cpp/audioapi/core/utils/AudioStretcher.cpp @@ -15,7 +15,7 @@ std::vector AudioStretcher::castToInt16Buffer(AudioBuffer &buffer) { std::vector int16Buffer(numFrames * numChannels); - for (int ch = 0; ch < numChannels; ++ch) { + for (size_t ch = 0; ch < numChannels; ++ch) { auto channelData = buffer.getChannel(ch)->span(); for (size_t i = 0; i < numFrames; ++i) { int16Buffer[i * numChannels + ch] = floatToInt16(channelData[i]); @@ -61,7 +61,7 @@ std::shared_ptr AudioStretcher::changePlaybackSpeed( auto audioBuffer = std::make_shared(outputFrames, outputChannels, sampleRate); - for (int ch = 0; ch < outputChannels; ++ch) { + for (size_t ch = 0; ch < outputChannels; ++ch) { auto channelData = audioBuffer->getChannel(ch)->span(); for (int i = 0; i < outputFrames; ++i) { channelData[i] = int16ToFloat(stretchedBuffer[i * outputChannels + ch]); diff --git a/packages/react-native-audio-api/common/cpp/audioapi/dsp/AudioUtils.hpp b/packages/react-native-audio-api/common/cpp/audioapi/dsp/AudioUtils.hpp index 41bc36e42..3cdcaa348 100644 --- a/packages/react-native-audio-api/common/cpp/audioapi/dsp/AudioUtils.hpp +++ b/packages/react-native-audio-api/common/cpp/audioapi/dsp/AudioUtils.hpp @@ -29,10 +29,11 @@ namespace audioapi::dsp { } [[nodiscard]] inline float linearToDecibels(float value) { - return 20 * log10f(value); + return 20.0f * log10f(value); } [[nodiscard]] inline float decibelsToLinear(float value) { return static_cast(pow(10, value / 20)); } + } // namespace audioapi::dsp diff --git a/packages/react-native-audio-api/common/cpp/audioapi/dsp/Resampler.cpp b/packages/react-native-audio-api/common/cpp/audioapi/dsp/Resampler.cpp index 278f51474..8dc85dcb8 100644 --- a/packages/react-native-audio-api/common/cpp/audioapi/dsp/Resampler.cpp +++ b/packages/react-native-audio-api/common/cpp/audioapi/dsp/Resampler.cpp @@ -145,7 +145,7 @@ int DownSampler::process( auto outputCount = framesToProcess / 2; - for (int i = 0; i < outputCount; ++i) { + for (size_t i = 0; i < outputCount; ++i) { // convolution for downsampled samples output[i] = stateBuffer_->computeConvolution(*kernel_, 2 * i + 1); } diff --git a/packages/react-native-audio-api/common/cpp/audioapi/libs/ffmpeg/FFmpegDecoding.cpp b/packages/react-native-audio-api/common/cpp/audioapi/libs/ffmpeg/FFmpegDecoding.cpp index 7cca55feb..b46529308 100644 --- a/packages/react-native-audio-api/common/cpp/audioapi/libs/ffmpeg/FFmpegDecoding.cpp +++ b/packages/react-native-audio-api/common/cpp/audioapi/libs/ffmpeg/FFmpegDecoding.cpp @@ -249,7 +249,7 @@ std::shared_ptr decodeAudioFrames( auto audioBuffer = std::make_shared(outputFrames, output_channel_count, output_sample_rate); - for (int ch = 0; ch < output_channel_count; ++ch) { + for (size_t ch = 0; ch < output_channel_count; ++ch) { auto channelData = audioBuffer->getChannel(ch)->span(); for (int i = 0; i < outputFrames; ++i) { channelData[i] = decoded_buffer[i * output_channel_count + ch]; diff --git a/packages/react-native-audio-api/common/cpp/audioapi/utils/AudioArray.cpp b/packages/react-native-audio-api/common/cpp/audioapi/utils/AudioArray.cpp index 8923acab8..6ba9b9f04 100644 --- a/packages/react-native-audio-api/common/cpp/audioapi/utils/AudioArray.cpp +++ b/packages/react-native-audio-api/common/cpp/audioapi/utils/AudioArray.cpp @@ -24,7 +24,7 @@ AudioArray::AudioArray(const float *data, size_t size) : size_(size) { AudioArray::AudioArray(const AudioArray &other) : size_(other.size_) { if (size_ > 0 && other.data_) { data_ = std::make_unique(size_); - std::memcpy(data_.get(), other.data_.get(), size_ * sizeof(float)); + copy(other); } } @@ -58,19 +58,6 @@ AudioArray &AudioArray::operator=(audioapi::AudioArray &&other) noexcept { return *this; } -void AudioArray::resize(size_t size) { - if (size == size_ && data_ != nullptr) { - zero(); - return; - } - - size_ = size; - data_ = (size_ > 0) ? std::make_unique(size_) : nullptr; - if (data_ != nullptr) { - zero(); - } -} - void AudioArray::zero() noexcept { zero(0, size_); } @@ -89,7 +76,7 @@ void AudioArray::sum( size_t destinationStart, size_t length, float gain) { - if (size_ - destinationStart < length || source.size_ - sourceStart < length) { + if (size_ - destinationStart < length || source.size_ - sourceStart < length) [[unlikely]] { throw std::out_of_range("Not enough data to sum two vectors."); } @@ -105,7 +92,7 @@ void AudioArray::multiply(const AudioArray &source) { } void AudioArray::multiply(const audioapi::AudioArray &source, size_t length) { - if (size_ < length || source.size_ < length) { + if (size_ < length || source.size_ < length) [[unlikely]] { throw std::out_of_range("Not enough data to perform vector multiplication."); } @@ -124,7 +111,7 @@ void AudioArray::copy( size_t sourceStart, size_t destinationStart, size_t length) { - if (source.size_ - sourceStart < length) { + if (source.size_ - sourceStart < length) [[unlikely]] { throw std::out_of_range("Not enough data to copy from source."); } @@ -136,7 +123,7 @@ void AudioArray::copy( size_t sourceStart, size_t destinationStart, size_t length) { - if (size_ - destinationStart < length) { + if (size_ - destinationStart < length) [[unlikely]] { throw std::out_of_range("Not enough space to copy to destination."); } @@ -148,7 +135,7 @@ void AudioArray::copyReverse( size_t sourceStart, size_t destinationStart, size_t length) { - if (size_ - destinationStart < length || source.size_ - sourceStart < length) { + if (size_ - destinationStart < length || source.size_ - sourceStart < length) [[unlikely]] { throw std::out_of_range("Not enough space to copy to destination or from source."); } @@ -166,7 +153,7 @@ void AudioArray::copyTo( size_t sourceStart, size_t destinationStart, size_t length) const { - if (size_ - sourceStart < length) { + if (size_ - sourceStart < length) [[unlikely]] { throw std::out_of_range("Not enough data to copy from source."); } @@ -174,7 +161,7 @@ void AudioArray::copyTo( } void AudioArray::copyWithin(size_t sourceStart, size_t destinationStart, size_t length) { - if (size_ - sourceStart < length || size_ - destinationStart < length) { + if (size_ - sourceStart < length || size_ - destinationStart < length) [[unlikely]] { throw std::out_of_range("Not enough space for moving data or data to move."); } @@ -208,7 +195,7 @@ float AudioArray::getMaxAbsValue() const { } float AudioArray::computeConvolution(const audioapi::AudioArray &kernel, size_t startIndex) const { - if (kernel.size_ > size_ - startIndex) { + if (kernel.size_ > size_ - startIndex) [[unlikely]] { throw std::out_of_range("Kernal size exceeds available data for convolution."); } diff --git a/packages/react-native-audio-api/common/cpp/audioapi/utils/AudioArray.h b/packages/react-native-audio-api/common/cpp/audioapi/utils/AudioArray.h index e2fbbed67..68b5f2881 100644 --- a/packages/react-native-audio-api/common/cpp/audioapi/utils/AudioArray.h +++ b/packages/react-native-audio-api/common/cpp/audioapi/utils/AudioArray.h @@ -26,40 +26,40 @@ class AudioArray { AudioArray &operator=(const AudioArray &other); AudioArray &operator=(AudioArray &&other) noexcept; - [[nodiscard]] inline size_t getSize() const noexcept { + [[nodiscard]] size_t getSize() const noexcept { return size_; } - inline float &operator[](size_t index) noexcept { + float &operator[](size_t index) noexcept { return data_[index]; } - inline const float &operator[](size_t index) const noexcept { + const float &operator[](size_t index) const noexcept { return data_[index]; } - [[nodiscard]] inline float *begin() noexcept { + [[nodiscard]] float *begin() noexcept { return data_.get(); } - [[nodiscard]] inline float *end() noexcept { + [[nodiscard]] float *end() noexcept { return data_.get() + size_; } - [[nodiscard]] inline const float *begin() const noexcept { + [[nodiscard]] const float *begin() const noexcept { return data_.get(); } - [[nodiscard]] inline const float *end() const noexcept { + [[nodiscard]] const float *end() const noexcept { return data_.get() + size_; } - [[nodiscard]] inline std::span span() noexcept { + [[nodiscard]] std::span span() noexcept { return {data_.get(), size_}; } - [[nodiscard]] inline std::span span() const noexcept { + [[nodiscard]] std::span span() const noexcept { return {data_.get(), size_}; } - [[nodiscard]] inline std::span subSpan(size_t length, size_t offset = 0) { + [[nodiscard]] std::span subSpan(size_t length, size_t offset = 0) { if (offset + length > size_) { throw std::out_of_range("AudioArray::subSpan - offset + length exceeds array size"); } @@ -67,8 +67,6 @@ class AudioArray { return {data_.get() + offset, length}; } - void resize(size_t size); - void zero() noexcept; void zero(size_t start, size_t length) noexcept; diff --git a/packages/react-native-audio-api/common/cpp/audioapi/utils/AudioBuffer.cpp b/packages/react-native-audio-api/common/cpp/audioapi/utils/AudioBuffer.cpp index 2555ac601..0b22592ae 100644 --- a/packages/react-native-audio-api/common/cpp/audioapi/utils/AudioBuffer.cpp +++ b/packages/react-native-audio-api/common/cpp/audioapi/utils/AudioBuffer.cpp @@ -21,7 +21,10 @@ constexpr int BLOCK_SIZE = 64; AudioBuffer::AudioBuffer(size_t size, int numberOfChannels, float sampleRate) : numberOfChannels_(numberOfChannels), sampleRate_(sampleRate), size_(size) { - createChannels(); + channels_.reserve(numberOfChannels_); + for (size_t i = 0; i < numberOfChannels_; i += 1) { + channels_.emplace_back(std::make_shared(size_)); + } } AudioBuffer::AudioBuffer(const audioapi::AudioBufferOptions &options) @@ -31,10 +34,9 @@ AudioBuffer::AudioBuffer(const AudioBuffer &other) : numberOfChannels_(other.numberOfChannels_), sampleRate_(other.sampleRate_), size_(other.size_) { - createChannels(); - - for (int i = 0; i < numberOfChannels_; i += 1) { - *channels_[i] = *other.channels_[i]; + channels_.reserve(numberOfChannels_); + for (const auto& channel : other.channels_) { + channels_.emplace_back(std::make_shared(*channel)); } } @@ -50,15 +52,26 @@ AudioBuffer::AudioBuffer(audioapi::AudioBuffer &&other) noexcept AudioBuffer &AudioBuffer::operator=(const AudioBuffer &other) { if (this != &other) { - if (numberOfChannels_ != other.numberOfChannels_ || size_ != other.size_) { + sampleRate_ = other.sampleRate_; + + if (numberOfChannels_ != other.numberOfChannels_) { numberOfChannels_ = other.numberOfChannels_; size_ = other.size_; - createChannels(); + channels_.clear(); + channels_.reserve(numberOfChannels_); + + for (const auto& channel : other.channels_) { + channels_.emplace_back(std::make_shared(*channel)); + } + + return *this; } - sampleRate_ = other.sampleRate_; + if (size_ != other.size_) { + size_ = other.size_; + } - for (int i = 0; i < numberOfChannels_; i += 1) { + for (size_t i = 0; i < numberOfChannels_; i += 1) { *channels_[i] = *other.channels_[i]; } } @@ -81,7 +94,7 @@ AudioBuffer &AudioBuffer::operator=(audioapi::AudioBuffer &&other) noexcept { return *this; } -AudioArray *AudioBuffer::getChannel(int index) const { +AudioArray *AudioBuffer::getChannel(size_t index) const { return channels_[index].get(); } @@ -155,7 +168,7 @@ AudioArray *AudioBuffer::getChannelByType(int channelType) const { } } -std::shared_ptr AudioBuffer::getSharedChannel(int index) const { +std::shared_ptr AudioBuffer::getSharedChannel(size_t index) const { return channels_[index]; } @@ -183,8 +196,8 @@ void AudioBuffer::sum( return; } - int numberOfSourceChannels = source.getNumberOfChannels(); - int numberOfChannels = getNumberOfChannels(); + auto numberOfSourceChannels = source.getNumberOfChannels(); + auto numberOfChannels = getNumberOfChannels(); if (interpretation == ChannelInterpretation::DISCRETE) { discreteSum(source, sourceStart, destinationStart, length); @@ -204,7 +217,7 @@ void AudioBuffer::sum( } // Source and destination channel counts are the same. Just sum the channels. - for (int i = 0; i < getNumberOfChannels(); i += 1) { + for (size_t i = 0; i < getNumberOfChannels(); i += 1) { channels_[i]->sum(*source.channels_[i], sourceStart, destinationStart, length); } } @@ -223,7 +236,7 @@ void AudioBuffer::copy( } if (source.getNumberOfChannels() == getNumberOfChannels()) { - for (int i = 0; i < getNumberOfChannels(); i += 1) { + for (size_t i = 0; i < getNumberOfChannels(); i += 1) { channels_[i]->copy(*source.channels_[i], sourceStart, destinationStart, length); } @@ -251,7 +264,7 @@ void AudioBuffer::deinterleaveFrom(const float *source, size_t frames) { } float *channelsPtrs[MAX_CHANNEL_COUNT]; - for (int i = 0; i < numberOfChannels_; ++i) { + for (size_t i = 0; i < numberOfChannels_; ++i) { channelsPtrs[i] = channels_[i]->begin(); } @@ -259,7 +272,7 @@ void AudioBuffer::deinterleaveFrom(const float *source, size_t frames) { size_t blockEnd = std::min(blockStart + BLOCK_SIZE, frames); for (size_t i = blockStart; i < blockEnd; ++i) { const float *frameSource = source + (i * numberOfChannels_); - for (int ch = 0; ch < numberOfChannels_; ++ch) { + for (size_t ch = 0; ch < numberOfChannels_; ++ch) { channelsPtrs[ch][i] = frameSource[ch]; } } @@ -282,7 +295,7 @@ void AudioBuffer::interleaveTo(float *destination, size_t frames) const { } float *channelsPtrs[MAX_CHANNEL_COUNT]; - for (int i = 0; i < numberOfChannels_; ++i) { + for (size_t i = 0; i < numberOfChannels_; ++i) { channelsPtrs[i] = channels_[i]->begin(); } @@ -290,7 +303,7 @@ void AudioBuffer::interleaveTo(float *destination, size_t frames) const { size_t blockEnd = std::min(blockStart + BLOCK_SIZE, frames); for (size_t i = blockStart; i < blockEnd; ++i) { float *frameDest = destination + (i * numberOfChannels_); - for (int ch = 0; ch < numberOfChannels_; ++ch) { + for (size_t ch = 0; ch < numberOfChannels_; ++ch) { frameDest[ch] = channelsPtrs[ch][i]; } } @@ -329,32 +342,17 @@ float AudioBuffer::maxAbsValue() const { * Internal tooling - channel initialization */ -void AudioBuffer::createChannels() { - if (channels_.size() != static_cast(numberOfChannels_)) { - channels_.clear(); - channels_.reserve(numberOfChannels_); - - for (int i = 0; i < numberOfChannels_; i += 1) { - channels_.emplace_back(std::make_shared(size_)); - } - } else { - for (int i = 0; i < numberOfChannels_; i += 1) { - channels_[i]->resize(size_); - } - } -} - void AudioBuffer::discreteSum( const AudioBuffer &source, size_t sourceStart, size_t destinationStart, size_t length) const { - int numberOfChannels = std::min(getNumberOfChannels(), source.getNumberOfChannels()); + auto numberOfChannels = std::min(getNumberOfChannels(), source.getNumberOfChannels()); // In case of source > destination, we "down-mix" and drop the extra channels. // In case of source < destination, we "up-mix" as many channels as we have, // leaving the remaining channels untouched. - for (int i = 0; i < numberOfChannels; i++) { + for (size_t i = 0; i < numberOfChannels; i++) { channels_[i]->sum(*source.channels_[i], sourceStart, destinationStart, length); } } @@ -364,8 +362,8 @@ void AudioBuffer::sumByUpMixing( size_t sourceStart, size_t destinationStart, size_t length) { - int numberOfSourceChannels = source.getNumberOfChannels(); - int numberOfChannels = getNumberOfChannels(); + auto numberOfSourceChannels = source.getNumberOfChannels(); + auto numberOfChannels = getNumberOfChannels(); // Mono to stereo (1 -> 2, 4) if (numberOfSourceChannels == 1 && (numberOfChannels == 2 || numberOfChannels == 4)) { @@ -415,8 +413,8 @@ void AudioBuffer::sumByDownMixing( size_t sourceStart, size_t destinationStart, size_t length) { - int numberOfSourceChannels = source.getNumberOfChannels(); - int numberOfChannels = getNumberOfChannels(); + auto numberOfSourceChannels = source.getNumberOfChannels(); + auto numberOfChannels = getNumberOfChannels(); // Stereo to mono (2 -> 1): output += 0.5 * (input.left + input.right). if (numberOfSourceChannels == 2 && numberOfChannels == 1) { diff --git a/packages/react-native-audio-api/common/cpp/audioapi/utils/AudioBuffer.h b/packages/react-native-audio-api/common/cpp/audioapi/utils/AudioBuffer.h index 5e77f957a..a91bcada8 100644 --- a/packages/react-native-audio-api/common/cpp/audioapi/utils/AudioBuffer.h +++ b/packages/react-native-audio-api/common/cpp/audioapi/utils/AudioBuffer.h @@ -34,34 +34,36 @@ class AudioBuffer { AudioBuffer &operator=(AudioBuffer &&other) noexcept; ~AudioBuffer() = default; - [[nodiscard]] inline int getNumberOfChannels() const noexcept { + [[nodiscard]] size_t getNumberOfChannels() const noexcept { return numberOfChannels_; } - [[nodiscard]] inline float getSampleRate() const noexcept { + [[nodiscard]] float getSampleRate() const noexcept { return sampleRate_; } - [[nodiscard]] inline size_t getSize() const noexcept { + [[nodiscard]] size_t getSize() const noexcept { return size_; } [[nodiscard]] double getDuration() const noexcept { - return static_cast(size_) / getSampleRate(); + return static_cast(size_) / static_cast(getSampleRate()); } /// @brief Get the AudioArray for a specific channel index. /// @param index The channel index. /// @return Pointer to the AudioArray for the specified channel - not owning. - [[nodiscard]] AudioArray *getChannel(int index) const; + [[nodiscard]] AudioArray *getChannel(size_t index) const; /// @brief Get the AudioArray for a specific channel type. - /// @param channelType The channel type (e.g., ChannelLeft, ChannelRight). + /// @param channelType The channel type: ChannelMono = 0, ChannelLeft = 0, + /// ChannelRight = 1, ChannelCenter = 2, ChannelLFE = 3, + /// ChannelSurroundLeft = 4, ChannelSurroundRight = 5 /// @return Pointer to the AudioArray for the specified channel type - not owning. [[nodiscard]] AudioArray *getChannelByType(int channelType) const; /// @brief Get a copy of shared pointer to the AudioArray for a specific channel index. /// @param index The channel index. /// @return Copy of shared pointer to the AudioArray for the specified channel - [[nodiscard]] std::shared_ptr getSharedChannel(int index) const; + [[nodiscard]] std::shared_ptr getSharedChannel(size_t index) const; AudioArray &operator[](size_t index) { return *channels_[index]; @@ -138,11 +140,10 @@ class AudioBuffer { private: std::vector> channels_; - int numberOfChannels_ = 0; + size_t numberOfChannels_ = 0; float sampleRate_ = 0.0f; size_t size_ = 0; - void createChannels(); void discreteSum( const AudioBuffer &source, size_t sourceStart, diff --git a/packages/react-native-audio-api/ios/audioapi/ios/core/IOSAudioPlayer.mm b/packages/react-native-audio-api/ios/audioapi/ios/core/IOSAudioPlayer.mm index f9d05810a..3181fb58e 100644 --- a/packages/react-native-audio-api/ios/audioapi/ios/core/IOSAudioPlayer.mm +++ b/packages/react-native-audio-api/ios/audioapi/ios/core/IOSAudioPlayer.mm @@ -27,7 +27,7 @@ audioBuffer_->zero(); } - for (int channel = 0; channel < channelCount_; channel += 1) { + for (size_t channel = 0; channel < channelCount_; channel += 1) { float *outputChannel = (float *)outputData->mBuffers[channel].mData; audioBuffer_->getChannel(channel)->copyTo( diff --git a/packages/react-native-audio-api/ios/audioapi/ios/core/utils/AudioDecoder.mm b/packages/react-native-audio-api/ios/audioapi/ios/core/utils/AudioDecoder.mm index 8e54daa16..eb1715158 100644 --- a/packages/react-native-audio-api/ios/audioapi/ios/core/utils/AudioDecoder.mm +++ b/packages/react-native-audio-api/ios/audioapi/ios/core/utils/AudioDecoder.mm @@ -150,7 +150,7 @@ auto audioBuffer = std::make_shared(numFramesDecoded, inputChannelCount, inputSampleRate); - for (int ch = 0; ch < inputChannelCount; ++ch) { + for (size_t ch = 0; ch < inputChannelCount; ++ch) { auto channelData = audioBuffer->getChannel(ch)->span(); for (size_t i = 0; i < numFramesDecoded; ++i) { diff --git a/packages/react-native-audio-api/ios/audioapi/ios/core/utils/IOSRecorderCallback.mm b/packages/react-native-audio-api/ios/audioapi/ios/core/utils/IOSRecorderCallback.mm index d922fb74c..abeaeccf0 100644 --- a/packages/react-native-audio-api/ios/audioapi/ios/core/utils/IOSRecorderCallback.mm +++ b/packages/react-native-audio-api/ios/audioapi/ios/core/utils/IOSRecorderCallback.mm @@ -39,7 +39,7 @@ converterInputBuffer_ = nil; converterOutputBuffer_ = nil; - for (int i = 0; i < channelCount_; ++i) { + for (size_t i = 0; i < channelCount_; ++i) { circularBus_[i]->zero(); } } @@ -116,7 +116,7 @@ converterInputBuffer_ = nil; converterOutputBuffer_ = nil; - for (int i = 0; i < channelCount_; ++i) { + for (size_t i = 0; i < channelCount_; ++i) { circularBus_[i]->zero(); } offloader_.reset(); @@ -148,7 +148,7 @@ if (bufferFormat_.sampleRate == sampleRate_ && bufferFormat_.channelCount == channelCount_ && !bufferFormat_.isInterleaved) { // Directly write to circular buffer - for (int i = 0; i < channelCount_; ++i) { + for (size_t i = 0; i < channelCount_; ++i) { auto *data = static_cast(inputBuffer->mBuffers[i].mData); circularBus_[i]->push_back(data, numFrames); } @@ -194,7 +194,7 @@ return; } - for (int i = 0; i < channelCount_; ++i) { + for (size_t i = 0; i < channelCount_; ++i) { auto *data = static_cast(converterOutputBuffer_.audioBufferList->mBuffers[i].mData); circularBus_[i]->push_back(data, outputFrameCount); } From 8587663412428d771a3b2b0d3d2720ecbeefeca7 Mon Sep 17 00:00:00 2001 From: maciejmakowski2003 Date: Thu, 5 Feb 2026 17:45:54 +0100 Subject: [PATCH 26/30] fix: nits --- .../common/cpp/audioapi/utils/AudioBuffer.cpp | 4 ---- 1 file changed, 4 deletions(-) diff --git a/packages/react-native-audio-api/common/cpp/audioapi/utils/AudioBuffer.cpp b/packages/react-native-audio-api/common/cpp/audioapi/utils/AudioBuffer.cpp index 0b22592ae..2349005da 100644 --- a/packages/react-native-audio-api/common/cpp/audioapi/utils/AudioBuffer.cpp +++ b/packages/react-native-audio-api/common/cpp/audioapi/utils/AudioBuffer.cpp @@ -10,10 +10,6 @@ #include #include -// Implementation of channel summing/mixing is based on the WebKit approach, -// source: -// https://github.com/WebKit/WebKit/blob/main/Source/WebCore/platform/audio/AudioBus.cpp - namespace audioapi { const float SQRT_HALF = sqrtf(0.5f); From a033e1265782145636353c0945779b8761dc5a4a Mon Sep 17 00:00:00 2001 From: maciejmakowski2003 Date: Fri, 6 Feb 2026 15:11:31 +0100 Subject: [PATCH 27/30] ci: lint --- .../common/cpp/audioapi/AudioAPIModuleInstaller.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/react-native-audio-api/common/cpp/audioapi/AudioAPIModuleInstaller.h b/packages/react-native-audio-api/common/cpp/audioapi/AudioAPIModuleInstaller.h index 5d8531762..c58ee2519 100644 --- a/packages/react-native-audio-api/common/cpp/audioapi/AudioAPIModuleInstaller.h +++ b/packages/react-native-audio-api/common/cpp/audioapi/AudioAPIModuleInstaller.h @@ -9,8 +9,8 @@ #include #include #include -#include #include +#include #include #include From 0e95b8aa1201a0ae823f39b4ab9cfb0066b66611 Mon Sep 17 00:00:00 2001 From: maciejmakowski2003 Date: Fri, 6 Feb 2026 18:04:05 +0100 Subject: [PATCH 28/30] chore: requested changes from cr --- .../docs/guides/create-your-own-effect.mdx | 2 +- .../cpp/audioapi/core/utils/AudioStretcher.h | 1 - .../common/cpp/audioapi/dsp/Convolver.cpp | 4 +- .../common/cpp/audioapi/dsp/WaveShaper.cpp | 3 +- .../audioapi/libs/ffmpeg/FFmpegDecoding.cpp | 1 - .../common/cpp/audioapi/utils/AudioArray.cpp | 9 +-- .../cpp/audioapi/utils/AudioArrayBuffer.hpp | 41 +++------- .../common/cpp/audioapi/utils/AudioBuffer.cpp | 74 +++++++++---------- .../ios/audioapi/ios/core/IOSAudioPlayer.mm | 5 +- .../ios/audioapi/ios/core/IOSAudioRecorder.mm | 2 +- .../audioapi/ios/core/utils/AudioDecoder.mm | 1 - 11 files changed, 55 insertions(+), 88 deletions(-) diff --git a/packages/audiodocs/docs/guides/create-your-own-effect.mdx b/packages/audiodocs/docs/guides/create-your-own-effect.mdx index e195c92f2..fbdcbe9c1 100644 --- a/packages/audiodocs/docs/guides/create-your-own-effect.mdx +++ b/packages/audiodocs/docs/guides/create-your-own-effect.mdx @@ -80,7 +80,7 @@ namespace audioapi { isInitialized_ = true; } - void MyProcessorNode::processNode(const std::shared_ptr &buffer, + std::shared_ptr MyProcessorNode::processNode(const std::shared_ptr &buffer, int framesToProcess) { // highlight-start for (int channel = 0; channel < buffer->getNumberOfChannels(); ++channel) { diff --git a/packages/react-native-audio-api/common/cpp/audioapi/core/utils/AudioStretcher.h b/packages/react-native-audio-api/common/cpp/audioapi/core/utils/AudioStretcher.h index 94d7894c6..4a8e47482 100644 --- a/packages/react-native-audio-api/common/cpp/audioapi/core/utils/AudioStretcher.h +++ b/packages/react-native-audio-api/common/cpp/audioapi/core/utils/AudioStretcher.h @@ -5,7 +5,6 @@ namespace audioapi { -class AudioBuffer; class AudioBuffer; class AudioStretcher { diff --git a/packages/react-native-audio-api/common/cpp/audioapi/dsp/Convolver.cpp b/packages/react-native-audio-api/common/cpp/audioapi/dsp/Convolver.cpp index ca73e4d5a..d10426919 100644 --- a/packages/react-native-audio-api/common/cpp/audioapi/dsp/Convolver.cpp +++ b/packages/react-native-audio-api/common/cpp/audioapi/dsp/Convolver.cpp @@ -38,10 +38,10 @@ void Convolver::reset() { _segments.clear(); _segmentsIR.clear(); _preMultiplied.clear(); - if (_fftBuffer) { + if (_fftBuffer != nullptr) { _fftBuffer->zero(); } - if (_inputBuffer) { + if (_inputBuffer != nullptr) { _inputBuffer->zero(); } } diff --git a/packages/react-native-audio-api/common/cpp/audioapi/dsp/WaveShaper.cpp b/packages/react-native-audio-api/common/cpp/audioapi/dsp/WaveShaper.cpp index cd846c2ae..8f616d2aa 100644 --- a/packages/react-native-audio-api/common/cpp/audioapi/dsp/WaveShaper.cpp +++ b/packages/react-native-audio-api/common/cpp/audioapi/dsp/WaveShaper.cpp @@ -91,7 +91,8 @@ void WaveShaper::process2x(AudioArray &channelData, int framesToProcess) { downSampler_->process(*tempBuffer2x_, channelData, outputFrames); } -void WaveShaper::process4x(AudioArray &channelData, int framesToProcess) { +void WaveShaper::process4x( + AudioArray &channelData, int framesToProcess) { auto upSamplerOutputFrames = upSampler_->process(channelData, *tempBuffer2x_, framesToProcess); auto upSampler2OutputFrames = upSampler2_->process(*tempBuffer2x_, *tempBuffer4x_, upSamplerOutputFrames); diff --git a/packages/react-native-audio-api/common/cpp/audioapi/libs/ffmpeg/FFmpegDecoding.cpp b/packages/react-native-audio-api/common/cpp/audioapi/libs/ffmpeg/FFmpegDecoding.cpp index b46529308..59aabb408 100644 --- a/packages/react-native-audio-api/common/cpp/audioapi/libs/ffmpeg/FFmpegDecoding.cpp +++ b/packages/react-native-audio-api/common/cpp/audioapi/libs/ffmpeg/FFmpegDecoding.cpp @@ -8,7 +8,6 @@ * FFmpeg, you must comply with the terms of the LGPL for FFmpeg itself. */ -#include #if !RN_AUDIO_API_FFMPEG_DISABLED #include #endif // RN_AUDIO_API_FFMPEG_DISABLED diff --git a/packages/react-native-audio-api/common/cpp/audioapi/utils/AudioArray.cpp b/packages/react-native-audio-api/common/cpp/audioapi/utils/AudioArray.cpp index 6ba9b9f04..cf935dba0 100644 --- a/packages/react-native-audio-api/common/cpp/audioapi/utils/AudioArray.cpp +++ b/packages/react-native-audio-api/common/cpp/audioapi/utils/AudioArray.cpp @@ -29,9 +29,7 @@ AudioArray::AudioArray(const AudioArray &other) : size_(other.size_) { } AudioArray::AudioArray(audioapi::AudioArray &&other) noexcept - : data_(std::move(other.data_)), size_(other.size_) { - other.size_ = 0; -} + : data_(std::move(other.data_)), size_(std::exchange(other.size_, 0)) {} AudioArray &AudioArray::operator=(const audioapi::AudioArray &other) { if (this != &other) { @@ -41,7 +39,7 @@ AudioArray &AudioArray::operator=(const audioapi::AudioArray &other) { } if (size_ > 0 && data_) { - std::memcpy(data_.get(), other.data_.get(), size_ * sizeof(float)); + copy(other); } } @@ -51,8 +49,7 @@ AudioArray &AudioArray::operator=(const audioapi::AudioArray &other) { AudioArray &AudioArray::operator=(audioapi::AudioArray &&other) noexcept { if (this != &other) { data_ = std::move(other.data_); - size_ = other.size_; - other.size_ = 0; + size_ = std::exchange(other.size_, 0); } return *this; diff --git a/packages/react-native-audio-api/common/cpp/audioapi/utils/AudioArrayBuffer.hpp b/packages/react-native-audio-api/common/cpp/audioapi/utils/AudioArrayBuffer.hpp index e72b7c9ac..8462114ed 100644 --- a/packages/react-native-audio-api/common/cpp/audioapi/utils/AudioArrayBuffer.hpp +++ b/packages/react-native-audio-api/common/cpp/audioapi/utils/AudioArrayBuffer.hpp @@ -6,43 +6,26 @@ #if !RN_AUDIO_API_TEST #include - -namespace audioapi { - -using namespace facebook; - -class AudioArrayBuffer : public jsi::MutableBuffer, public AudioArray { - public: - explicit AudioArrayBuffer(size_t size) : AudioArray(size) {}; - AudioArrayBuffer(const float *data, size_t size) : AudioArray(data, size) {}; - - [[nodiscard]] size_t size() const override { - return size_ * sizeof(float); - } - uint8_t *data() override { - return reinterpret_cast(data_.get()); - } -}; - -} // namespace audioapi - +using JsiBuffer = facebook::jsi::MutableBuffer; #else +// Dummy class to inherit from nothing if testing + struct JsiBuffer {}; +#endif namespace audioapi { -class AudioArrayBuffer : public AudioArray { +class AudioArrayBuffer : public JsiBuffer, public AudioArray { public: explicit AudioArrayBuffer(size_t size) : AudioArray(size) {}; AudioArrayBuffer(const float *data, size_t size) : AudioArray(data, size) {}; - [[nodiscard]] size_t size() const { - return size_ * sizeof(float); - } - uint8_t *data() { - return reinterpret_cast(data_.get()); - } +#if !RN_AUDIO_API_TEST + [[nodiscard]] size_t size() const override { return size_ * sizeof(float); } + uint8_t *data() override { return reinterpret_cast(data_.get()); } +#else + [[nodiscard]] size_t size() const { return size_ * sizeof(float); } + uint8_t *data() { return reinterpret_cast(data_.get()); } +#endif }; } // namespace audioapi - -#endif diff --git a/packages/react-native-audio-api/common/cpp/audioapi/utils/AudioBuffer.cpp b/packages/react-native-audio-api/common/cpp/audioapi/utils/AudioBuffer.cpp index 4f272e7c6..23cf06528 100644 --- a/packages/react-native-audio-api/common/cpp/audioapi/utils/AudioBuffer.cpp +++ b/packages/react-native-audio-api/common/cpp/audioapi/utils/AudioBuffer.cpp @@ -17,7 +17,7 @@ constexpr int BLOCK_SIZE = 64; AudioBuffer::AudioBuffer(size_t size, int numberOfChannels, float sampleRate) : numberOfChannels_(numberOfChannels), sampleRate_(sampleRate), size_(size) { channels_.reserve(numberOfChannels_); - for (size_t i = 0; i < numberOfChannels_; i += 1) { + for (size_t i = 0; i < numberOfChannels_; ++i) { channels_.emplace_back(std::make_shared(size_)); } } @@ -34,13 +34,9 @@ AudioBuffer::AudioBuffer(const AudioBuffer &other) AudioBuffer::AudioBuffer(audioapi::AudioBuffer &&other) noexcept : channels_(std::move(other.channels_)), - numberOfChannels_(other.numberOfChannels_), - sampleRate_(other.sampleRate_), - size_(other.size_) { - other.numberOfChannels_ = 0; - other.sampleRate_ = 0.0f; - other.size_ = 0; -} + numberOfChannels_(std::exchange(other.numberOfChannels_, 0)), + sampleRate_(std::exchange(other.sampleRate_, 0.0f)), + size_(std::exchange(other.size_, 0)) {} AudioBuffer &AudioBuffer::operator=(const AudioBuffer &other) { if (this != &other) { @@ -63,7 +59,7 @@ AudioBuffer &AudioBuffer::operator=(const AudioBuffer &other) { size_ = other.size_; } - for (size_t i = 0; i < numberOfChannels_; i += 1) { + for (size_t i = 0; i < numberOfChannels_; ++i) { *channels_[i] = *other.channels_[i]; } } @@ -75,13 +71,9 @@ AudioBuffer &AudioBuffer::operator=(audioapi::AudioBuffer &&other) noexcept { if (this != &other) { channels_ = std::move(other.channels_); - numberOfChannels_ = other.numberOfChannels_; - sampleRate_ = other.sampleRate_; - size_ = other.size_; - - other.numberOfChannels_ = 0; - other.sampleRate_ = 0.0f; - other.size_ = 0; + numberOfChannels_ = std::exchange(other.numberOfChannels_, 0); + sampleRate_ = std::exchange(other.sampleRate_, 0.0f); + size_ = std::exchange(other.size_, 0); } return *this; } @@ -209,7 +201,7 @@ void AudioBuffer::sum( } // Source and destination channel counts are the same. Just sum the channels. - for (size_t i = 0; i < getNumberOfChannels(); i += 1) { + for (size_t i = 0; i < getNumberOfChannels(); ++i) { channels_[i]->sum(*source.channels_[i], sourceStart, destinationStart, length); } } @@ -228,7 +220,7 @@ void AudioBuffer::copy( } if (source.getNumberOfChannels() == getNumberOfChannels()) { - for (size_t i = 0; i < getNumberOfChannels(); i += 1) { + for (size_t i = 0; i < getNumberOfChannels(); ++i) { channels_[i]->copy(*source.channels_[i], sourceStart, destinationStart, length); } @@ -241,34 +233,34 @@ void AudioBuffer::copy( } void AudioBuffer::deinterleaveFrom(const float *source, size_t frames) { - if (frames == 0) { - return; - } + if (frames == 0) { + return; + } - if (numberOfChannels_ == 1) { - channels_[0]->copy(source, 0, 0, frames); - return; - } + if (numberOfChannels_ == 1) { + channels_[0]->copy(source, 0, 0, frames); + return; + } - if (numberOfChannels_ == 2) { - dsp::deinterleaveStereo(source, channels_[0]->begin(), channels_[1]->begin(), frames); - return; - } + if (numberOfChannels_ == 2) { + dsp::deinterleaveStereo(source, channels_[0]->begin(), channels_[1]->begin(), frames); + return; + } - float *channelsPtrs[MAX_CHANNEL_COUNT]; - for (size_t i = 0; i < numberOfChannels_; ++i) { - channelsPtrs[i] = channels_[i]->begin(); - } + float *channelsPtrs[MAX_CHANNEL_COUNT]; + for (size_t i = 0; i < numberOfChannels_; ++i) { + channelsPtrs[i] = channels_[i]->begin(); + } - for (size_t blockStart = 0; blockStart < frames; blockStart += BLOCK_SIZE) { - size_t blockEnd = std::min(blockStart + BLOCK_SIZE, frames); - for (size_t i = blockStart; i < blockEnd; ++i) { - const float *frameSource = source + (i * numberOfChannels_); - for (size_t ch = 0; ch < numberOfChannels_; ++ch) { - channelsPtrs[ch][i] = frameSource[ch]; - } - } + for (size_t blockStart = 0; blockStart < frames; blockStart += BLOCK_SIZE) { + size_t blockEnd = std::min(blockStart + BLOCK_SIZE, frames); + for (size_t i = blockStart; i < blockEnd; ++i) { + const float *frameSource = source + (i * numberOfChannels_); + for (size_t ch = 0; ch < numberOfChannels_; ++ch) { + channelsPtrs[ch][i] = frameSource[ch]; + } } + } } void AudioBuffer::interleaveTo(float *destination, size_t frames) const { diff --git a/packages/react-native-audio-api/ios/audioapi/ios/core/IOSAudioPlayer.mm b/packages/react-native-audio-api/ios/audioapi/ios/core/IOSAudioPlayer.mm index 3181fb58e..5fca12e33 100644 --- a/packages/react-native-audio-api/ios/audioapi/ios/core/IOSAudioPlayer.mm +++ b/packages/react-native-audio-api/ios/audioapi/ios/core/IOSAudioPlayer.mm @@ -96,10 +96,7 @@ { stop(); [audioPlayer_ cleanup]; - - if (audioBuffer_) { - audioBuffer_ = nullptr; - } + audioBuffer_ = nullptr; } } // namespace audioapi diff --git a/packages/react-native-audio-api/ios/audioapi/ios/core/IOSAudioRecorder.mm b/packages/react-native-audio-api/ios/audioapi/ios/core/IOSAudioRecorder.mm index 74c339c9a..d6fb6e7a2 100644 --- a/packages/react-native-audio-api/ios/audioapi/ios/core/IOSAudioRecorder.mm +++ b/packages/react-native-audio-api/ios/audioapi/ios/core/IOSAudioRecorder.mm @@ -51,7 +51,7 @@ if (isConnected()) { if (auto lock = Locker::tryLock(adapterNodeMutex_)) { for (size_t channel = 0; channel < adapterNode_->channelCount_; ++channel) { - float *data = (float *)inputBuffer->mBuffers[channel].mData; + auto data = (float *)inputBuffer->mBuffers[channel].mData; adapterNode_->buff_[channel]->write(data, numFrames); } diff --git a/packages/react-native-audio-api/ios/audioapi/ios/core/utils/AudioDecoder.mm b/packages/react-native-audio-api/ios/audioapi/ios/core/utils/AudioDecoder.mm index eb1715158..a1a68a3b5 100644 --- a/packages/react-native-audio-api/ios/audioapi/ios/core/utils/AudioDecoder.mm +++ b/packages/react-native-audio-api/ios/audioapi/ios/core/utils/AudioDecoder.mm @@ -6,7 +6,6 @@ #include #include #include -#include #if !RN_AUDIO_API_FFMPEG_DISABLED #include #endif // RN_AUDIO_API_FFMPEG_DISABLED From 60ea709e81193ebfe2f770c718f3ff1b414b6ac7 Mon Sep 17 00:00:00 2001 From: maciejmakowski2003 Date: Fri, 6 Feb 2026 18:04:47 +0100 Subject: [PATCH 29/30] ci: lint --- .../cpp/audioapi/utils/AudioArrayBuffer.hpp | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/packages/react-native-audio-api/common/cpp/audioapi/utils/AudioArrayBuffer.hpp b/packages/react-native-audio-api/common/cpp/audioapi/utils/AudioArrayBuffer.hpp index 8462114ed..33632bbc1 100644 --- a/packages/react-native-audio-api/common/cpp/audioapi/utils/AudioArrayBuffer.hpp +++ b/packages/react-native-audio-api/common/cpp/audioapi/utils/AudioArrayBuffer.hpp @@ -9,7 +9,7 @@ using JsiBuffer = facebook::jsi::MutableBuffer; #else // Dummy class to inherit from nothing if testing - struct JsiBuffer {}; +struct JsiBuffer {}; #endif namespace audioapi { @@ -20,11 +20,19 @@ class AudioArrayBuffer : public JsiBuffer, public AudioArray { AudioArrayBuffer(const float *data, size_t size) : AudioArray(data, size) {}; #if !RN_AUDIO_API_TEST - [[nodiscard]] size_t size() const override { return size_ * sizeof(float); } - uint8_t *data() override { return reinterpret_cast(data_.get()); } + [[nodiscard]] size_t size() const override { + return size_ * sizeof(float); + } + uint8_t *data() override { + return reinterpret_cast(data_.get()); + } #else - [[nodiscard]] size_t size() const { return size_ * sizeof(float); } - uint8_t *data() { return reinterpret_cast(data_.get()); } + [[nodiscard]] size_t size() const { + return size_ * sizeof(float); + } + uint8_t *data() { + return reinterpret_cast(data_.get()); + } #endif }; From 3c43693fcd077e5ea2b8d8bd2e3c3cd3d41aced5 Mon Sep 17 00:00:00 2001 From: maciejmakowski2003 Date: Mon, 9 Feb 2026 12:04:15 +0100 Subject: [PATCH 30/30] refactor: get channel by type --- .../core/effects/StereoPannerNode.cpp | 2 +- .../common/cpp/audioapi/utils/AudioBuffer.cpp | 77 +++---------------- .../common/cpp/audioapi/utils/AudioBuffer.h | 14 ++++ 3 files changed, 26 insertions(+), 67 deletions(-) diff --git a/packages/react-native-audio-api/common/cpp/audioapi/core/effects/StereoPannerNode.cpp b/packages/react-native-audio-api/common/cpp/audioapi/core/effects/StereoPannerNode.cpp index a0bade59c..7b81797c5 100644 --- a/packages/react-native-audio-api/common/cpp/audioapi/core/effects/StereoPannerNode.cpp +++ b/packages/react-native-audio-api/common/cpp/audioapi/core/effects/StereoPannerNode.cpp @@ -51,7 +51,7 @@ std::shared_ptr StereoPannerNode::processNode( time += deltaTime; } } else { // Input is stereo - auto inputLeft = processingBuffer->getChannelByType(AudioBuffer::ChannelMono)->span(); + auto inputLeft = processingBuffer->getChannelByType(AudioBuffer::ChannelLeft)->span(); auto inputRight = processingBuffer->getChannelByType(AudioBuffer::ChannelRight)->span(); for (int i = 0; i < framesToProcess; i++) { diff --git a/packages/react-native-audio-api/common/cpp/audioapi/utils/AudioBuffer.cpp b/packages/react-native-audio-api/common/cpp/audioapi/utils/AudioBuffer.cpp index 23cf06528..587afc168 100644 --- a/packages/react-native-audio-api/common/cpp/audioapi/utils/AudioBuffer.cpp +++ b/packages/react-native-audio-api/common/cpp/audioapi/utils/AudioBuffer.cpp @@ -83,73 +83,18 @@ AudioArray *AudioBuffer::getChannel(size_t index) const { } AudioArray *AudioBuffer::getChannelByType(int channelType) const { - switch (getNumberOfChannels()) { - case 1: // mono - if (channelType == ChannelMono) { - return getChannel(0); - } - return nullptr; - - case 2: // stereo - switch (channelType) { - case ChannelLeft: - return getChannel(0); - case ChannelRight: - return getChannel(1); - default: - return nullptr; - } - - case 4: // quad - switch (channelType) { - case ChannelLeft: - return getChannel(0); - case ChannelRight: - return getChannel(1); - case ChannelSurroundLeft: - return getChannel(2); - case ChannelSurroundRight: - return getChannel(3); - default: - return nullptr; - } - - case 5: // 5.0 - switch (channelType) { - case ChannelLeft: - return getChannel(0); - case ChannelRight: - return getChannel(1); - case ChannelCenter: - return getChannel(2); - case ChannelSurroundLeft: - return getChannel(3); - case ChannelSurroundRight: - return getChannel(4); - default: - return nullptr; - } + auto it = kChannelLayouts.find(getNumberOfChannels()); + if (it == kChannelLayouts.end()) { + return nullptr; + } + const auto& channelOrder = it->second; + for (size_t i = 0; i < channelOrder.size(); ++i) { + if (channelOrder[i] == channelType) { + return getChannel(i); + } + } - case 6: // 5.1 - switch (channelType) { - case ChannelLeft: - return getChannel(0); - case ChannelRight: - return getChannel(1); - case ChannelCenter: - return getChannel(2); - case ChannelLFE: - return getChannel(3); - case ChannelSurroundLeft: - return getChannel(4); - case ChannelSurroundRight: - return getChannel(5); - default: - return nullptr; - } - default: - return nullptr; - } + return nullptr; } std::shared_ptr AudioBuffer::getSharedChannel(size_t index) const { diff --git a/packages/react-native-audio-api/common/cpp/audioapi/utils/AudioBuffer.h b/packages/react-native-audio-api/common/cpp/audioapi/utils/AudioBuffer.h index 43d82a902..8b17f5301 100644 --- a/packages/react-native-audio-api/common/cpp/audioapi/utils/AudioBuffer.h +++ b/packages/react-native-audio-api/common/cpp/audioapi/utils/AudioBuffer.h @@ -7,6 +7,7 @@ #include #include #include +#include #include namespace audioapi { @@ -143,6 +144,19 @@ class AudioBuffer { float sampleRate_ = 0.0f; size_t size_ = 0; + inline static const std::unordered_map> kChannelLayouts = { + {1, {ChannelMono}}, + {2, {ChannelLeft, ChannelRight}}, + {4, {ChannelLeft, ChannelRight, ChannelSurroundLeft, ChannelSurroundRight}}, + {5, {ChannelLeft, ChannelRight, ChannelCenter, ChannelSurroundLeft, ChannelSurroundRight}}, + {6, + {ChannelLeft, + ChannelRight, + ChannelCenter, + ChannelLFE, + ChannelSurroundLeft, + ChannelSurroundRight}}}; + void discreteSum( const AudioBuffer &source, size_t sourceStart,