From 3c3f3853e60f5ee42f2ce23ffb27827eebeae7af Mon Sep 17 00:00:00 2001 From: michal Date: Wed, 11 Mar 2026 11:14:24 +0100 Subject: [PATCH 1/9] chore: init setup for clang tidy --- packages/react-native-audio-api/.clang-tidy | 20 ++++++++++++++++++++ packages/react-native-audio-api/.clangd | 6 ++++++ 2 files changed, 26 insertions(+) create mode 100644 packages/react-native-audio-api/.clang-tidy create mode 100644 packages/react-native-audio-api/.clangd diff --git a/packages/react-native-audio-api/.clang-tidy b/packages/react-native-audio-api/.clang-tidy new file mode 100644 index 000000000..5a134bbce --- /dev/null +++ b/packages/react-native-audio-api/.clang-tidy @@ -0,0 +1,20 @@ +# Full clang-tidy configuration for react-native-audio-api C++. +# See: https://clang.llvm.org/extra/clang-tidy/checks/list.html +# Tweak checks in .clangd (Diagnostics.ClangTidy.Remove) to disable noisy ones. + +Checks: '-*, + bugprone-*, + modernize-*, + -modernize-use-trailing-return-type, + performance-*, + readability-*, + portability-*, + cppcoreguidelines-*, + -cppcoreguidelines-non-private-member-variables-in-classes, + concurrency-*' + +# Only report in our source (exclude external/, node_modules, build dirs) +HeaderFilterRegex: '.*/(audioapi|common/cpp|src/main/cpp)/.*' + +# Apply .clang-format when applying fixes +FormatStyle: file diff --git a/packages/react-native-audio-api/.clangd b/packages/react-native-audio-api/.clangd new file mode 100644 index 000000000..24a825227 --- /dev/null +++ b/packages/react-native-audio-api/.clangd @@ -0,0 +1,6 @@ +Documentation: + CommentFormat: Doxygen + +Diagnostics: + ClangTidy: + FastCheckFilter: Loose From d3bafe6d4c6114bffb027e9a9308ac50d8541aae Mon Sep 17 00:00:00 2001 From: michal Date: Mon, 16 Mar 2026 07:27:50 +0100 Subject: [PATCH 2/9] refactor: first part of a clang-tidy refactor --- packages/react-native-audio-api/.clang-tidy | 15 ++++- packages/react-native-audio-api/.clangd | 4 ++ .../common/cpp/audioapi/core/AudioContext.h | 2 + .../common/cpp/audioapi/core/AudioNode.cpp | 25 +++++--- .../common/cpp/audioapi/core/AudioNode.h | 27 ++++---- .../common/cpp/audioapi/core/AudioParam.h | 18 +++--- .../cpp/audioapi/core/BaseAudioContext.h | 22 ++++--- .../audioapi/core/analysis/AnalyserNode.cpp | 11 ++-- .../cpp/audioapi/core/analysis/AnalyserNode.h | 11 ++-- .../core/destinations/AudioDestinationNode.h | 2 +- .../core/effects/BiquadFilterNode.cpp | 11 ++-- .../audioapi/core/effects/ConvolverNode.cpp | 20 +++--- .../cpp/audioapi/core/effects/ConvolverNode.h | 4 +- .../cpp/audioapi/core/effects/DelayNode.cpp | 5 +- .../cpp/audioapi/core/effects/DelayNode.h | 2 +- .../cpp/audioapi/core/effects/GainNode.cpp | 7 +- .../audioapi/core/effects/IIRFilterNode.cpp | 13 ++-- .../cpp/audioapi/core/effects/IIRFilterNode.h | 3 +- .../audioapi/core/effects/PeriodicWave.cpp | 64 ++++++++++--------- .../cpp/audioapi/core/effects/PeriodicWave.h | 12 ++-- .../core/effects/StereoPannerNode.cpp | 7 +- .../audioapi/core/effects/WaveShaperNode.cpp | 2 +- .../audioapi/core/effects/WaveShaperNode.h | 4 +- .../cpp/audioapi/core/effects/WorkletNode.h | 3 +- .../cpp/audioapi/core/inputs/AudioRecorder.h | 8 ++- .../core/sources/AudioScheduledSourceNode.h | 9 ++- .../audioapi/core/types/BiquadFilterType.h | 4 +- .../audioapi/core/types/ChannelCountMode.h | 4 +- .../core/types/ChannelInterpretation.h | 4 +- .../cpp/audioapi/core/types/ContextState.h | 4 +- .../cpp/audioapi/core/types/OscillatorType.h | 4 +- .../cpp/audioapi/core/types/OverSampleType.h | 4 +- .../core/types/ParamChangeEventType.h | 4 +- .../core/utils/AudioRecorderCallback.h | 4 ++ .../audioapi/core/utils/AudioStretcher.cpp | 6 +- .../cpp/audioapi/core/utils/AudioStretcher.h | 4 +- .../cpp/audioapi/core/utils/Constants.h | 4 +- .../common/cpp/audioapi/core/utils/Macros.h | 7 ++ .../core/utils/worklets/SafeIncludes.h | 20 ++++-- .../common/cpp/audioapi/dsp/AudioUtils.hpp | 7 +- .../common/cpp/audioapi/dsp/FFT.h | 5 ++ .../common/cpp/audioapi/types/NodeOptions.h | 40 +++++++----- .../common/cpp/audioapi/utils/AudioArray.h | 2 +- .../common/cpp/audioapi/utils/SpscChannel.hpp | 26 ++++---- .../react-native-audio-api/scripts/cpplint.sh | 2 +- 45 files changed, 285 insertions(+), 181 deletions(-) create mode 100644 packages/react-native-audio-api/common/cpp/audioapi/core/utils/Macros.h diff --git a/packages/react-native-audio-api/.clang-tidy b/packages/react-native-audio-api/.clang-tidy index 5a134bbce..83175f767 100644 --- a/packages/react-native-audio-api/.clang-tidy +++ b/packages/react-native-audio-api/.clang-tidy @@ -4,17 +4,26 @@ Checks: '-*, bugprone-*, + -bugprone-easily-swappable-parameters, modernize-*, -modernize-use-trailing-return-type, performance-*, readability-*, - portability-*, + -readability-uppercase-literal-suffix, + -readability-math-missing-parentheses, + -readability-isolate-declaration, + -readability-identifier-length, cppcoreguidelines-*, -cppcoreguidelines-non-private-member-variables-in-classes, + -cppcoreguidelines-pro-bounds-avoid-unchecked-container-access, + -cppcoreguidelines-pro-bounds-pointer-arithmetic, + -cppcoreguidelines-pro-type-union-access, + -cppcoreguidelines-pro-type-reinterpret-cast, + -cppcoreguidelines-avoid-do-while, + -cppcoreguidelines-pro-bounds-constant-array-index, + -cppcoreguidelines-init-variables, concurrency-*' -# Only report in our source (exclude external/, node_modules, build dirs) HeaderFilterRegex: '.*/(audioapi|common/cpp|src/main/cpp)/.*' -# Apply .clang-format when applying fixes FormatStyle: file diff --git a/packages/react-native-audio-api/.clangd b/packages/react-native-audio-api/.clangd index 24a825227..3724509bc 100644 --- a/packages/react-native-audio-api/.clangd +++ b/packages/react-native-audio-api/.clangd @@ -1,6 +1,10 @@ Documentation: CommentFormat: Doxygen +CompileFlags: + Add: + - -std=c++20 + Diagnostics: ClangTidy: FastCheckFilter: Loose 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 57295baec..44c5aa199 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 @@ -1,6 +1,7 @@ #pragma once #include +#include #include #include @@ -20,6 +21,7 @@ class AudioContext : public BaseAudioContext { const std::shared_ptr &audioEventHandlerRegistry, const RuntimeRegistry &runtimeRegistry); ~AudioContext() override; + DELETE_COPY_AND_MOVE(AudioContext); void close(); bool resume(); 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 ed0540b11..eff5098fb 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 @@ -13,6 +13,7 @@ AudioNode::AudioNode( const std::shared_ptr &context, const AudioNodeOptions &options) : context_(context), + audioBuffer_(nullptr), numberOfInputs_(options.numberOfInputs), numberOfOutputs_(options.numberOfOutputs), channelCount_(options.channelCount), @@ -33,35 +34,43 @@ size_t AudioNode::getChannelCount() const { return channelCount_; } -void AudioNode::connect(const std::shared_ptr &node) { +void AudioNode::connect( + const std::shared_ptr + &node) { // NOLINT(readability-convert-member-functions-to-static) if (std::shared_ptr context = context_.lock()) { context->getGraphManager()->addPendingNodeConnection( shared_from_this(), node, AudioGraphManager::ConnectionType::CONNECT); } } -void AudioNode::connect(const std::shared_ptr ¶m) { +void AudioNode::connect( + const std::shared_ptr + ¶m) { // NOLINT(readability-convert-member-functions-to-static) if (std::shared_ptr context = context_.lock()) { context->getGraphManager()->addPendingParamConnection( shared_from_this(), param, AudioGraphManager::ConnectionType::CONNECT); } } -void AudioNode::disconnect() { +void AudioNode::disconnect() { // NOLINT(readability-convert-member-functions-to-static) if (std::shared_ptr context = context_.lock()) { context->getGraphManager()->addPendingNodeConnection( shared_from_this(), nullptr, AudioGraphManager::ConnectionType::DISCONNECT_ALL); } } -void AudioNode::disconnect(const std::shared_ptr &node) { +void AudioNode::disconnect( + const std::shared_ptr + &node) { // NOLINT(readability-convert-member-functions-to-static) if (std::shared_ptr context = context_.lock()) { context->getGraphManager()->addPendingNodeConnection( shared_from_this(), node, AudioGraphManager::ConnectionType::DISCONNECT); } } -void AudioNode::disconnect(const std::shared_ptr ¶m) { +void AudioNode::disconnect( + const std::shared_ptr + ¶m) { // NOLINT(readability-convert-member-functions-to-static) if (std::shared_ptr context = context_.lock()) { context->getGraphManager()->addPendingParamConnection( shared_from_this(), param, AudioGraphManager::ConnectionType::DISCONNECT); @@ -127,7 +136,7 @@ std::shared_ptr AudioNode::processAudio( return processNode(processingBuffer, framesToProcess); } -bool AudioNode::isAlreadyProcessed() { +bool AudioNode::isAlreadyProcessed() { // NOLINT(readability-convert-member-functions-to-static) if (std::shared_ptr context = context_.lock()) { std::size_t currentSampleFrame = context->getCurrentSampleFrame(); @@ -143,13 +152,13 @@ bool AudioNode::isAlreadyProcessed() { } // If context is invalid, consider it as already processed to avoid processing - return true; + return true; // NOLINT(readability-simplify-boolean-expr) } std::shared_ptr AudioNode::processInputs( const std::shared_ptr &outputBuffer, int framesToProcess, - bool checkIsAlreadyProcessed) { + bool checkIsAlreadyProcessed) { // NOLINT(readability-convert-member-functions-to-static) auto processingBuffer = audioBuffer_; processingBuffer->zero(); 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 4890f3848..52690801a 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 @@ -4,6 +4,7 @@ #include #include #include +#include #include #include @@ -25,7 +26,9 @@ class AudioNode : public std::enable_shared_from_this { const AudioNodeOptions &options = AudioNodeOptions()); virtual ~AudioNode(); - size_t getChannelCount() const; + DELETE_COPY_AND_MOVE(AudioNode); + + [[nodiscard]] size_t getChannelCount() const; void connect(const std::shared_ptr &node); void connect(const std::shared_ptr ¶m); void disconnect(); @@ -36,7 +39,8 @@ class AudioNode : public std::enable_shared_from_this { int framesToProcess, bool checkIsAlreadyProcessed); - float getContextSampleRate() const { + [[nodiscard]] float getContextSampleRate() + const { // NOLINT(readability-convert-member-functions-to-static) if (std::shared_ptr context = context_.lock()) { return context->getSampleRate(); } @@ -44,17 +48,18 @@ class AudioNode : public std::enable_shared_from_this { return DEFAULT_SAMPLE_RATE; } - float getNyquistFrequency() const { - return getContextSampleRate() / 2.0f; + [[nodiscard]] float getNyquistFrequency() const { + constexpr float kNyquistDivisor = 2.0f; + return getContextSampleRate() / kNyquistDivisor; } /// @note JS Thread only - bool isEnabled() const; + [[nodiscard]] bool isEnabled() const; /// @note JS Thread only - bool requiresTailProcessing() const; + [[nodiscard]] bool requiresTailProcessing() const; template - bool inline scheduleAudioEvent(F &&event) noexcept { + bool scheduleAudioEvent(F &&event) noexcept { if (std::shared_ptr context = context_.lock()) { return context->scheduleAudioEvent(std::forward(event)); } @@ -78,9 +83,9 @@ class AudioNode : public std::enable_shared_from_this { const ChannelInterpretation channelInterpretation_ = ChannelInterpretation::SPEAKERS; const bool requiresTailProcessing_; - std::unordered_set inputNodes_ = {}; - std::unordered_set> outputNodes_ = {}; - std::unordered_set> outputParams_ = {}; + std::unordered_set inputNodes_; + std::unordered_set> outputNodes_; + std::unordered_set> outputParams_; int numberOfEnabledInputNodes_ = 0; std::atomic isInitialized_ = false; @@ -92,7 +97,7 @@ class AudioNode : public std::enable_shared_from_this { private: bool isEnabled_ = true; - std::vector> inputBuffers_ = {}; + std::vector> inputBuffers_; virtual std::shared_ptr processInputs( const std::shared_ptr &outputBuffer, 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 06abccab8..35ab18d15 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 @@ -23,23 +23,23 @@ class AudioParam { float maxValue, const std::shared_ptr &context); - [[nodiscard]] inline float getValue() const noexcept { + [[nodiscard]] float getValue() const noexcept { return value_.load(std::memory_order_relaxed); } - [[nodiscard]] inline float getDefaultValue() const noexcept { + [[nodiscard]] float getDefaultValue() const noexcept { return defaultValue_; } - [[nodiscard]] inline float getMinValue() const noexcept { + [[nodiscard]] float getMinValue() const noexcept { return minValue_; } - [[nodiscard]] inline float getMaxValue() const noexcept { + [[nodiscard]] float getMaxValue() const noexcept { return maxValue_; } - inline void setValue(float value) { + void setValue(float value) { value_.store(std::clamp(value, minValue_, maxValue_), std::memory_order_release); } @@ -71,7 +71,7 @@ class AudioParam { template < typename F, typename = std::enable_if_t, BaseAudioContext &>>> - bool inline scheduleAudioEvent(F &&event) noexcept { + bool scheduleAudioEvent(F &&event) noexcept { if (std::shared_ptr context = context_.lock()) { return context->scheduleAudioEvent(std::forward(event)); } @@ -118,7 +118,7 @@ class AudioParam { /// @brief Get the end time of the parameter queue. /// @return The end time of the parameter queue or last endTime_ if queue is empty. - inline double getQueueEndTime() const noexcept { + [[nodiscard]] double getQueueEndTime() const noexcept { if (eventsQueue_.isEmpty()) { return endTime_; } @@ -127,7 +127,7 @@ class AudioParam { /// @brief Get the end value of the parameter queue. /// @return The end value of the parameter queue or last endValue_ if queue is empty. - inline float getQueueEndValue() const noexcept { + [[nodiscard]] float getQueueEndValue() const noexcept { if (eventsQueue_.isEmpty()) { return endValue_; } @@ -137,7 +137,7 @@ class AudioParam { /// @brief Update the parameter queue with a new event. /// @param event The new event to add to the queue. /// @note Handles connecting start value of the new event to the end value of the previous event. - inline void updateQueue(ParamChangeEvent &&event) { + void updateQueue(ParamChangeEvent &&event) { eventsQueue_.pushBack(std::move(event)); } float getValueAtTime(double time); 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 fa3c9efad..25f5252d6 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 @@ -55,6 +55,11 @@ struct WaveShaperOptions; class BaseAudioContext : public std::enable_shared_from_this { public: + BaseAudioContext(const BaseAudioContext &) = delete; + BaseAudioContext &operator=(const BaseAudioContext &) = delete; + BaseAudioContext(BaseAudioContext &&) = delete; + BaseAudioContext &operator=(BaseAudioContext &&) = delete; + explicit BaseAudioContext( float sampleRate, const std::shared_ptr &audioEventHandlerRegistry, @@ -65,7 +70,7 @@ class BaseAudioContext : public std::enable_shared_from_this { [[nodiscard]] float getSampleRate() const; [[nodiscard]] double getCurrentTime() const; [[nodiscard]] std::size_t getCurrentSampleFrame() const; - std::shared_ptr getDestination() const; + [[nodiscard]] std::shared_ptr getDestination() const; void setState(ContextState state); @@ -96,8 +101,9 @@ class BaseAudioContext : public std::enable_shared_from_this { const AudioBufferSourceOptions &options); std::shared_ptr createBufferQueueSource( const BaseAudioBufferSourceOptions &options); - std::shared_ptr createPeriodicWave( - const std::vector> &complexData, + [[nodiscard]] std::shared_ptr createPeriodicWave( + const std::vector> + &complexData, // NOLINT(readability-avoid-const-params-in-decls) bool disableNormalization, int length) const; std::shared_ptr createAnalyser(const AnalyserOptions &options); @@ -105,18 +111,18 @@ class BaseAudioContext : public std::enable_shared_from_this { std::shared_ptr createWaveShaper(const WaveShaperOptions &options); std::shared_ptr getBasicWaveForm(OscillatorType type); - std::shared_ptr getGraphManager() const; - std::shared_ptr getAudioEventHandlerRegistry() const; - const RuntimeRegistry &getRuntimeRegistry() const; + [[nodiscard]] std::shared_ptr getGraphManager() const; + [[nodiscard]] std::shared_ptr getAudioEventHandlerRegistry() const; + [[nodiscard]] const RuntimeRegistry &getRuntimeRegistry() const; virtual void initialize(); - void inline processAudioEvents() { + void processAudioEvents() { audioEventScheduler_.processAllEvents(*this); } template - bool inline scheduleAudioEvent(F &&event) noexcept { + bool scheduleAudioEvent(F &&event) noexcept { // NOLINT(cppcoreguidelines-missing-std-forward) if (getState() != ContextState::RUNNING) { processAudioEvents(); event(*this); 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 8f1f3bdb5..39e8ce965 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 @@ -16,6 +16,7 @@ AnalyserNode::AnalyserNode( const std::shared_ptr &context, const AnalyserOptions &options) : AudioNode(context, options), + fftSize_(0), inputArray_(std::make_unique(MAX_FFT_SIZE * 2)), downMixBuffer_( std::make_unique(RENDER_QUANTUM_SIZE, 1, context->getSampleRate())), @@ -81,8 +82,9 @@ void AnalyserNode::getByteTimeDomainData(uint8_t *data, int length) { auto values = frame->timeDomain.span(); + constexpr float byteCenter = 128.0f; for (int i = 0; i < size; i++) { - float scaledValue = 128 * (values[i] + 1); + float scaledValue = byteCenter * (values[i] + 1); scaledValue = std::clamp(scaledValue, 0.0f, static_cast(UINT8_MAX)); data[i] = static_cast(scaledValue); @@ -142,9 +144,8 @@ void AnalyserNode::doFFTAnalysis() { for (int i = 0; i < magnitudeArray_->getSize(); i++) { auto scalarMagnitude = std::abs(complexData_[i]) * magnitudeScale; - magnitudeBufferData[i] = static_cast( - smoothingTimeConstant_ * magnitudeBufferData[i] + - (1 - smoothingTimeConstant_) * scalarMagnitude); + magnitudeBufferData[i] = smoothingTimeConstant_ * magnitudeBufferData[i] + + (1 - smoothingTimeConstant_) * scalarMagnitude; } } @@ -157,7 +158,7 @@ void AnalyserNode::initializeWindowData(int fftSize) { const auto alpha = 2.0f * std::numbers::pi_v * invSizeMinusOne; for (size_t i = 0; i < size; ++i) { - const auto phase = alpha * i; + const auto phase = alpha * static_cast(i); // 4*PI*x is just 2 * (2*PI*x) const auto window = 0.42f - 0.50f * std::cos(phase) + 0.08f * std::cos(2.0f * phase); data[i] = window; 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 c806e820b..4b32f0fa4 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 @@ -26,21 +26,21 @@ class AnalyserNode : public AudioNode { const AnalyserOptions &options); /// @note JS Thread only - float getMinDecibels() const { + [[nodiscard]] float getMinDecibels() const { return minDecibels_; } /// @note JS Thread only - float getMaxDecibels() const { + [[nodiscard]] float getMaxDecibels() const { return maxDecibels_; } /// @note JS Thread only - float getSmoothingTimeConstant() const { + [[nodiscard]] float getSmoothingTimeConstant() const { return smoothingTimeConstant_; } - int getFFTSize() const { + [[nodiscard]] int getFFTSize() const { return fftSize_.load(std::memory_order_acquire); } @@ -107,6 +107,9 @@ class AnalyserNode : public AudioNode { AnalysisFrame(const AnalysisFrame &) = delete; AnalysisFrame &operator=(const AnalysisFrame &) = delete; + AnalysisFrame(AnalysisFrame &&) noexcept = default; + AnalysisFrame &operator=(AnalysisFrame &&) noexcept = default; + ~AnalysisFrame() = default; }; TripleBuffer analysisBuffer_{MAX_FFT_SIZE}; 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 42d54b689..96b840479 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 @@ -23,7 +23,7 @@ class AudioDestinationNode : public AudioNode { double getCurrentTime() const; /// @note Audio Thread only - void renderAudio(const std::shared_ptr &audioData, int numFrames); + void renderAudio(const std::shared_ptr &destinationBuffer, int numFrames); protected: // DestinationNode is triggered by AudioContext using renderAudio 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 5c77ffe48..72a7c509a 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 @@ -36,6 +36,7 @@ // https://webaudio.github.io/Audio-EQ-Cookbook/audio-eq-cookbook.html - math // formulas for filters +// NOLINTBEGIN(cppcoreguidelines-avoid-magic-numbers, readability-magic-numbers, readability-identifier-length) namespace audioapi { @@ -221,7 +222,7 @@ BiquadFilterNode::FilterCoefficients BiquadFilterNode::getLowshelfCoefficients( } float w0 = PI * frequency; - float alpha = 0.5f * std::sin(w0) * std::sqrt(2.0f); + float alpha = 0.5f * std::sin(w0) * std::numbers::sqrt2_v; float cosW = std::cos(w0); float gamma = 2.0f * std::sqrt(A) * alpha; @@ -250,7 +251,7 @@ BiquadFilterNode::FilterCoefficients BiquadFilterNode::getHighshelfCoefficients( float w0 = PI * frequency; // In the original formula: sqrt((A + 1/A) * (1/S - 1) + 2), but we assume // the maximum value S = 1, so it becomes 0 + 2 under the square root - float alpha = 0.5f * std::sin(w0) * std::sqrt(2.0f); + float alpha = 0.5f * std::sin(w0) * std::numbers::sqrt2_v; float cosW = std::cos(w0); float gamma = 2.0f * std::sqrt(A) * alpha; @@ -346,7 +347,7 @@ BiquadFilterNode::FilterCoefficients BiquadFilterNode::applyFilter( normalizedFrequency *= std::pow(2.0f, detune / 1200.0f); } - FilterCoefficients coeffs = {1.0, 0.0, 0.0, 0.0, 0.0}; + FilterCoefficients coeffs = {.b0 = 1.0, .b1 = 0.0, .b2 = 0.0, .a1 = 0.0, .a2 = 0.0}; switch (type) { case BiquadFilterType::LOWPASS: @@ -392,7 +393,7 @@ std::shared_ptr BiquadFilterNode::processNode( auto coeffs = applyFilter(frequency, Q, gain, detune, type_); - float x1, x2, y1, y2; + float x1, x2, y1, y2; // NOLINT(cppcoreguidelines-init-variables) auto numChannels = processingBuffer->getNumberOfChannels(); @@ -435,3 +436,5 @@ std::shared_ptr BiquadFilterNode::processNode( } } // namespace audioapi + +// NOLINTEND(cppcoreguidelines-avoid-magic-numbers, readability-magic-numbers, readability-identifier-length) 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 5415eb6f3..16decc060 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 @@ -5,6 +5,7 @@ #include #include #include +#include #include #include #include @@ -60,8 +61,8 @@ void ConvolverNode::setBuffer( internalBufferIndex_ = 0; } -float ConvolverNode::calculateNormalizationScale(const std::shared_ptr &buffer) { - int numberOfChannels = buffer->getNumberOfChannels(); +float ConvolverNode::calculateNormalizationScale(const std::shared_ptr &buffer) const { + auto numberOfChannels = buffer->getNumberOfChannels(); auto length = buffer->getSize(); float power = 0; @@ -69,7 +70,7 @@ float ConvolverNode::calculateNormalizationScale(const std::shared_ptrgetChannel(channel)->span(); - for (int i = 0; i < length; ++i) { + for (size_t i = 0; i < length; ++i) { float sample = channelData[i]; channelPower += sample * sample; } @@ -77,15 +78,12 @@ float ConvolverNode::calculateNormalizationScale(const std::shared_ptrgetSampleRate(); + power = std::max(power, MIN_IR_POWER); + power = 1 / power; + power *= std::pow(10, GAIN_CALIBRATION * 0.05f); + power *= gainCalibrationSampleRate_ / buffer->getSampleRate(); - return scaleFactor; + return power; } void ConvolverNode::onInputDisabled() { 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 4041d3c5b..c036687d0 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 @@ -11,7 +11,7 @@ static constexpr int GAIN_CALIBRATION = -58; // magic number so that processed signal and dry signal have roughly the same volume -static constexpr double MIN_IR_POWER = 0.000125; +static constexpr float MIN_IR_POWER = 0.000125; namespace audioapi { @@ -34,7 +34,7 @@ class ConvolverNode : public AudioNode { const std::shared_ptr &intermediateBuffer, float scaleFactor); - float calculateNormalizationScale(const std::shared_ptr &buffer); + float calculateNormalizationScale(const std::shared_ptr &buffer) const; protected: std::shared_ptr processNode( 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 2350315be..ecd01d9ed 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 @@ -30,7 +30,7 @@ void DelayNode::onInputDisabled() { numberOfEnabledInputNodes_ -= 1; if (isEnabled() && numberOfEnabledInputNodes_ == 0) { signalledToStop_ = true; - remainingFrames_ = delayTimeParam_->getValue() * getContextSampleRate(); + remainingFrames_ = static_cast(delayTimeParam_->getValue() * getContextSampleRate()); } } @@ -100,7 +100,8 @@ std::shared_ptr DelayNode::processNode( } auto delayTime = delayTimeParam_->processKRateParam(framesToProcess, context->getCurrentTime()); - size_t writeIndex = static_cast(readIndex_ + delayTime * context->getSampleRate()) % + size_t writeIndex = + static_cast(static_cast(readIndex_) + delayTime * context->getSampleRate()) % delayBuffer_->getSize(); delayBufferOperation( processingBuffer, framesToProcess, writeIndex, DelayNode::BufferAction::WRITE); 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 d380952c1..47791a95d 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 @@ -23,7 +23,7 @@ class DelayNode : public AudioNode { private: void onInputDisabled() override; - enum class BufferAction { READ, WRITE }; + enum class BufferAction : uint8_t { READ, WRITE }; void delayBufferOperation( 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 e2afde588..69aed675b 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 @@ -27,14 +27,15 @@ std::shared_ptr GainNode::processNode( const std::shared_ptr &processingBuffer, int framesToProcess) { std::shared_ptr context = context_.lock(); - if (context == nullptr) + if (context == nullptr) { return processingBuffer; + } double time = context->getCurrentTime(); auto gainParamValues = gainParam_->processARateParam(framesToProcess, time); - auto gainValues = gainParamValues->getChannel(0); + auto *gainValues = gainParamValues->getChannel(0); for (size_t i = 0; i < processingBuffer->getNumberOfChannels(); i++) { - auto channel = processingBuffer->getChannel(i); + auto *channel = processingBuffer->getChannel(i); 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 3592fb022..216c3b505 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 @@ -88,8 +88,8 @@ void IIRFilterNode::getFrequencyResponse( auto denominator = IIRFilterNode::evaluatePolynomial(feedback_, z, feedback_.getSize() - 1); auto response = numerator / denominator; - magResponseOutput[k] = static_cast(std::abs(response)); - phaseResponseOutput[k] = static_cast(atan2(imag(response), real(response))); + magResponseOutput[k] = std::abs(response); + phaseResponseOutput[k] = atan2(imag(response), real(response)); } } @@ -105,7 +105,7 @@ std::shared_ptr IIRFilterNode::processNode( size_t feedforwardLength = feedforward_.getSize(); size_t feedbackLength = feedback_.getSize(); - int minLength = std::min(feedbackLength, feedforwardLength); + auto minLength = static_cast(std::min(feedbackLength, feedforwardLength)); int mask = bufferLength - 1; @@ -115,21 +115,22 @@ std::shared_ptr IIRFilterNode::processNode( auto &x = xBuffers_[c]; auto &y = yBuffers_[c]; size_t bufferIndex = bufferIndices_[c]; + size_t k; for (float &sample : channel) { const float x_n = sample; float y_n = feedforward_[0] * sample; - for (int k = 1; k < minLength; ++k) { + for (k = 1; k < minLength; ++k) { int m = (bufferIndex - k) & mask; 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) { + for (k = minLength; k < feedforwardLength; ++k) { y_n = std::fma(feedforward_[k], x[(bufferIndex - k) & mask], y_n); } - for (int k = minLength; k < feedbackLength; ++k) { + for (k = minLength; k < feedbackLength; ++k) { y_n = std::fma(-feedback_[k], y[(bufferIndex - k) & (bufferLength - 1)], y_n); } 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 a5f6416cf..0a30b06d7 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 @@ -70,8 +70,9 @@ class IIRFilterNode : public AudioNode { evaluatePolynomial(const AudioArray &coefficients, std::complex z, int order) { // Use Horner's method to evaluate the polynomial P(z) = sum(coef[k]*z^k, k, 0, order); std::complex result = 0; - for (int k = order; k >= 0; --k) + for (int k = order; k >= 0; --k) { result = result * z + std::complex(coefficients[k]); + } return result; } 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 423c21789..523ee741b 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 @@ -33,23 +33,25 @@ #include #include +// NOLINTBEGIN(readability-magic-numbers, cppcoreguidelines-avoid-magic-numbers) + constexpr unsigned NumberOfOctaveBands = 3; -constexpr float CentsPerRange = 1200.0f / NumberOfOctaveBands; +constexpr float CentsPerRange = static_cast(audioapi::OCTAVE_RANGE) / NumberOfOctaveBands; constexpr float interpolate2Point = 0.3; constexpr float interpolate3Point = 0.16; namespace audioapi { PeriodicWave::PeriodicWave(float sampleRate, bool disableNormalization) - : sampleRate_(sampleRate), disableNormalization_(disableNormalization) { - numberOfRanges_ = static_cast( - round(NumberOfOctaveBands * log2f(static_cast(getPeriodicWaveSize())))); - auto nyquistFrequency = sampleRate_ / 2; - lowestFundamentalFrequency_ = - static_cast(nyquistFrequency) / static_cast(getMaxNumberOfPartials()); - scale_ = static_cast(getPeriodicWaveSize()) / static_cast(sampleRate_); + : sampleRate_(sampleRate), + disableNormalization_(disableNormalization), + numberOfRanges_( + static_cast( + round(NumberOfOctaveBands * log2f(static_cast(getPeriodicWaveSize()))))), + lowestFundamentalFrequency_( + static_cast(sampleRate_ / 2) / static_cast(getMaxNumberOfPartials())), + scale_(static_cast(getPeriodicWaveSize()) / sampleRate_) { bandLimitedTables_ = std::make_unique(getPeriodicWaveSize(), numberOfRanges_, sampleRate_); - fft_ = std::make_unique(getPeriodicWaveSize()); } @@ -102,7 +104,7 @@ int PeriodicWave::getNumberOfPartialsPerRange(int rangeIndex) const { auto centsToCull = static_cast(rangeIndex) * CentsPerRange; // A value from 0 -> 1 representing what fraction of the partials to keep. - auto cullingScale = std::pow(2, -centsToCull / 1200); + auto cullingScale = std::pow(2, -centsToCull / OCTAVE_RANGE); // The very top range will have all the partials culled. int numberOfPartials = @@ -134,17 +136,17 @@ void PeriodicWave::generateBasicWaveForm(OscillatorType type) { // https://mathworld.wolfram.com/FourierSeries.html // Coefficient for sin() - float b; + float coeff{}; auto piFactor = 1.0f / (PI * static_cast(i)); switch (type) { case OscillatorType::SINE: - b = (i == 1) ? 1.0f : 0.0f; + coeff = (i == 1) ? 1.0f : 0.0f; break; case OscillatorType::SQUARE: // https://mathworld.wolfram.com/FourierSeriesSquareWave.html - b = ((i & 1) == 1) ? 4 * piFactor : 0.0f; + coeff = ((i & 1) == 1) ? 4 * piFactor : 0.0f; break; case OscillatorType::SAWTOOTH: // https://mathworld.wolfram.com/FourierSeriesSawtoothWave.html - our @@ -152,21 +154,21 @@ void PeriodicWave::generateBasicWaveForm(OscillatorType type) { // similar. our function - f(x) = 2(x / (2 * pi) - floor(x / (2 * pi) + // 0.5))); // https://www.wolframalpha.com/input?i=2%28x+%2F+%282+*+pi%29+-+floor%28x+%2F+%282+*+pi%29+%2B+0.5%29%29%29%3B - b = 2 * piFactor * ((i & 1) == 1 ? 1.0f : -1.0f); + coeff = 2 * piFactor * ((i & 1) == 1 ? 1.0f : -1.0f); break; case OscillatorType::TRIANGLE: // https://mathworld.wolfram.com/FourierSeriesTriangleWave.html if ((i & 1) == 1) { - b = 8.0f * piFactor * piFactor * ((i & 3) == 1 ? 1.0f : -1.0f); + coeff = 8.0f * piFactor * piFactor * ((i & 3) == 1 ? 1.0f : -1.0f); } else { - b = 0.0f; + coeff = 0.0f; } break; case OscillatorType::CUSTOM: throw std::invalid_argument("Custom waveforms are not supported."); } - complexData[i] = std::complex(0.0f, b); + complexData[i] = std::complex(0.0f, coeff); } createBandLimitedTables(complexData, halfSize); @@ -207,7 +209,7 @@ void PeriodicWave::createBandLimitedTables( // Zero out the DC and nquist components. complexFFTData[0] = {0.0f, 0.0f}; - auto channel = bandLimitedTables_->getChannel(rangeIndex); + auto *channel = bandLimitedTables_->getChannel(rangeIndex); // Perform the inverse FFT to get the time domain representation of the // band-limited waveform. @@ -245,9 +247,10 @@ WaveTableSource PeriodicWave::getWaveDataForFundamentalFrequency(float fundament // get the wave data for the lower and higher range index. // calculate the interpolation factor between the lower and higher range data. return { - bandLimitedTables_->getChannel(lowerRangeIndex), - bandLimitedTables_->getChannel(higherRangeIndex), - pitchRange - static_cast(lowerRangeIndex)}; + .lower = bandLimitedTables_->getChannel(lowerRangeIndex), + .higher = bandLimitedTables_->getChannel(higherRangeIndex), + .interpolationFactor = pitchRange - static_cast(lowerRangeIndex), + }; } float PeriodicWave::doInterpolation( @@ -266,12 +269,9 @@ float PeriodicWave::doInterpolation( auto factor = phase - static_cast(index); if (phaseIncrement >= interpolate2Point) { // linear interpolation - int indices[2]; - - for (int i = 0; i < 2; i++) { - indices[i] = (index + i) & - (getPeriodicWaveSize() - 1); // more efficient alternative to % getPeriodicWaveSize() - } + auto indices = std::array{}; + indices[0] = (index + 0) & (getPeriodicWaveSize() - 1); + indices[1] = (index + 1) & (getPeriodicWaveSize() - 1); auto lowerWaveDataSample1 = lowerWaveData[indices[0]]; auto lowerWaveDataSample2 = lowerWaveData[indices[1]]; @@ -282,13 +282,13 @@ float PeriodicWave::doInterpolation( higherWaveDataSample = (1 - factor) * higherWaveDataSample1 + factor * higherWaveDataSample2; } else if (phaseIncrement >= interpolate3Point) { // 3-point Lagrange // interpolation - int indices[3]; + auto indices = std::array{}; for (int i = 0; i < 3; i++) { indices[i] = (index + i - 1) & (getPeriodicWaveSize() - 1); } - float A[3]; + auto A = std::array{}; A[0] = factor * (factor - 1) / 2; A[1] = 1 - factor * factor; @@ -299,13 +299,13 @@ float PeriodicWave::doInterpolation( higherWaveDataSample += higherWaveData[indices[i]] * A[i]; } } else { // 5-point Lagrange interpolation - int indices[5]; + auto indices = std::array{}; for (int i = 0; i < 5; i++) { indices[i] = (index + i - 2) & (getPeriodicWaveSize() - 1); } - float A[5]; + auto A = std::array{}; A[0] = factor * (factor * factor - 1) * (factor - 2) / 24; A[1] = -factor * (factor - 1) * (factor * factor - 4) / 6; @@ -322,3 +322,5 @@ float PeriodicWave::doInterpolation( return std::lerp(higherWaveDataSample, lowerWaveDataSample, waveTableInterpolationFactor); } } // namespace audioapi + +// NOLINTEND(readability-magic-numbers, cppcoreguidelines-avoid-magic-numbers) 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 5d26c1cd2..fc78dade0 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 @@ -49,7 +49,8 @@ class PeriodicWave { explicit PeriodicWave(float sampleRate, OscillatorType type, bool disableNormalization); explicit PeriodicWave( float sampleRate, - const std::vector> &complexData, + const std::vector> + &complexData, // NOLINT(readability-avoid-const-params-in-decls) int length, bool disableNormalization); @@ -81,19 +82,22 @@ class PeriodicWave { // The higher frequencies are culled to band-limit the waveform. // For each range, the inverse FFT is performed to get the time domain // representation of the band-limited waveform. - void createBandLimitedTables(const std::vector> &complexData, int size); + void createBandLimitedTables( + const std::vector> &complexData, + int size); // NOLINT(readability-avoid-const-params-in-decls) // 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. - WaveTableSource getWaveDataForFundamentalFrequency(float fundamentalFrequency) const; + [[nodiscard]] 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. [[nodiscard]] float doInterpolation( - float bufferIndex, + float phase, float phaseIncrement, float waveTableInterpolationFactor, const AudioArray &lowerWaveData, 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 c2e837518..284e66ed1 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 @@ -26,8 +26,9 @@ std::shared_ptr StereoPannerNode::processNode( const std::shared_ptr &processingBuffer, int framesToProcess) { std::shared_ptr context = context_.lock(); - if (context == nullptr) + if (context == nullptr) { return processingBuffer; + } double time = context->getCurrentTime(); double deltaTime = 1.0 / context->getSampleRate(); @@ -57,8 +58,8 @@ std::shared_ptr StereoPannerNode::processNode( 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 auto gainL = cos(x * PI / 2); + const auto gainR = sin(x * PI / 2); const float inputL = inputLeft[i]; const float inputR = inputRight[i]; 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 fd56d8aae..77780e3ac 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 @@ -46,7 +46,7 @@ std::shared_ptr WaveShaperNode::processNode( } for (size_t channel = 0; channel < processingBuffer->getNumberOfChannels(); channel++) { - auto channelData = processingBuffer->getChannel(channel); + auto *channelData = processingBuffer->getChannel(channel); waveShapers_[channel]->process(*channelData, framesToProcess); } 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 dd6125b47..579830a8e 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 @@ -4,9 +4,7 @@ #include #include -#include #include -#include #include namespace audioapi { @@ -36,7 +34,7 @@ class WaveShaperNode : public AudioNode { OverSampleType oversample_; std::shared_ptr curve_; - std::vector> waveShapers_{}; + std::vector> waveShapers_; }; } // 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 f7a3382cf..5b995895d 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 @@ -2,6 +2,7 @@ #include #include +#include #include #include #include @@ -40,7 +41,7 @@ class WorkletNode : public AudioNode { size_t bufferLength, size_t inputChannelCount, WorkletsRunner &&workletRunner); - + DELETE_COPY_AND_MOVE(WorkletNode); ~WorkletNode() override = default; protected: 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..86decf209 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 @@ -19,10 +19,14 @@ class AudioEventHandlerRegistry; class AudioRecorder { public: - enum class RecorderState { Idle = 0, Recording, Paused }; + enum class RecorderState : uint8_t { Idle = 0, Recording, Paused }; explicit AudioRecorder( const std::shared_ptr &audioEventHandlerRegistry) : audioEventHandlerRegistry_(audioEventHandlerRegistry) {} + AudioRecorder(const AudioRecorder &) = delete; + AudioRecorder(AudioRecorder &&) = delete; + AudioRecorder &operator=(const AudioRecorder &) = delete; + AudioRecorder &operator=(AudioRecorder &&) = delete; virtual ~AudioRecorder() = default; virtual Result start(const std::string &fileNameOverride) = 0; @@ -72,7 +76,7 @@ class AudioRecorder { std::atomic errorCallbackId_{0}; - std::string filePath_{""}; + std::string filePath_; std::shared_ptr fileWriter_ = nullptr; std::shared_ptr adapterNode_ = nullptr; std::shared_ptr dataCallback_ = nullptr; 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 d4129dcd7..ccaf99400 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 @@ -5,6 +5,7 @@ #include #include +#include #include namespace audioapi { @@ -18,7 +19,13 @@ class AudioScheduledSourceNode : public AudioNode { // PLAYING: The node is currently playing. // 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 }; + enum class PlaybackState : std::uint8_t { + UNSCHEDULED, + SCHEDULED, + PLAYING, + STOP_SCHEDULED, + FINISHED + }; explicit AudioScheduledSourceNode( const std::shared_ptr &context, const AudioScheduledSourceNodeOptions &options = AudioScheduledSourceNodeOptions()); diff --git a/packages/react-native-audio-api/common/cpp/audioapi/core/types/BiquadFilterType.h b/packages/react-native-audio-api/common/cpp/audioapi/core/types/BiquadFilterType.h index f9e67a665..39a953d98 100644 --- a/packages/react-native-audio-api/common/cpp/audioapi/core/types/BiquadFilterType.h +++ b/packages/react-native-audio-api/common/cpp/audioapi/core/types/BiquadFilterType.h @@ -1,8 +1,10 @@ #pragma once +#include + namespace audioapi { -enum class BiquadFilterType { +enum class BiquadFilterType : std::uint8_t { LOWPASS, HIGHPASS, BANDPASS, diff --git a/packages/react-native-audio-api/common/cpp/audioapi/core/types/ChannelCountMode.h b/packages/react-native-audio-api/common/cpp/audioapi/core/types/ChannelCountMode.h index a91aa930d..e3fa2e893 100644 --- a/packages/react-native-audio-api/common/cpp/audioapi/core/types/ChannelCountMode.h +++ b/packages/react-native-audio-api/common/cpp/audioapi/core/types/ChannelCountMode.h @@ -1,7 +1,9 @@ #pragma once +#include + namespace audioapi { -enum class ChannelCountMode { MAX, CLAMPED_MAX, EXPLICIT }; +enum class ChannelCountMode : std::uint8_t { MAX, CLAMPED_MAX, EXPLICIT }; } diff --git a/packages/react-native-audio-api/common/cpp/audioapi/core/types/ChannelInterpretation.h b/packages/react-native-audio-api/common/cpp/audioapi/core/types/ChannelInterpretation.h index 45dc1ad74..73ea52e03 100644 --- a/packages/react-native-audio-api/common/cpp/audioapi/core/types/ChannelInterpretation.h +++ b/packages/react-native-audio-api/common/cpp/audioapi/core/types/ChannelInterpretation.h @@ -1,7 +1,9 @@ #pragma once +#include + namespace audioapi { -enum class ChannelInterpretation { SPEAKERS, DISCRETE }; +enum class ChannelInterpretation : std::uint8_t { SPEAKERS, DISCRETE }; } diff --git a/packages/react-native-audio-api/common/cpp/audioapi/core/types/ContextState.h b/packages/react-native-audio-api/common/cpp/audioapi/core/types/ContextState.h index 6a93b0625..c40d7070f 100644 --- a/packages/react-native-audio-api/common/cpp/audioapi/core/types/ContextState.h +++ b/packages/react-native-audio-api/common/cpp/audioapi/core/types/ContextState.h @@ -1,7 +1,9 @@ #pragma once +#include + namespace audioapi { -enum class ContextState { SUSPENDED, RUNNING, CLOSED }; +enum class ContextState : std::uint8_t { SUSPENDED, RUNNING, CLOSED }; } diff --git a/packages/react-native-audio-api/common/cpp/audioapi/core/types/OscillatorType.h b/packages/react-native-audio-api/common/cpp/audioapi/core/types/OscillatorType.h index c25d9e72a..d702830f7 100644 --- a/packages/react-native-audio-api/common/cpp/audioapi/core/types/OscillatorType.h +++ b/packages/react-native-audio-api/common/cpp/audioapi/core/types/OscillatorType.h @@ -1,7 +1,9 @@ #pragma once +#include + namespace audioapi { -enum class OscillatorType { SINE, SQUARE, SAWTOOTH, TRIANGLE, CUSTOM }; +enum class OscillatorType : std::uint8_t { SINE, SQUARE, SAWTOOTH, TRIANGLE, CUSTOM }; } // namespace audioapi diff --git a/packages/react-native-audio-api/common/cpp/audioapi/core/types/OverSampleType.h b/packages/react-native-audio-api/common/cpp/audioapi/core/types/OverSampleType.h index 8ba765169..28254993a 100644 --- a/packages/react-native-audio-api/common/cpp/audioapi/core/types/OverSampleType.h +++ b/packages/react-native-audio-api/common/cpp/audioapi/core/types/OverSampleType.h @@ -1,7 +1,9 @@ #pragma once +#include + namespace audioapi { -enum class OverSampleType { OVERSAMPLE_NONE, OVERSAMPLE_2X, OVERSAMPLE_4X }; +enum class OverSampleType : std::uint8_t { OVERSAMPLE_NONE, OVERSAMPLE_2X, OVERSAMPLE_4X }; } // namespace audioapi diff --git a/packages/react-native-audio-api/common/cpp/audioapi/core/types/ParamChangeEventType.h b/packages/react-native-audio-api/common/cpp/audioapi/core/types/ParamChangeEventType.h index e5bd6b52a..dab646ba9 100644 --- a/packages/react-native-audio-api/common/cpp/audioapi/core/types/ParamChangeEventType.h +++ b/packages/react-native-audio-api/common/cpp/audioapi/core/types/ParamChangeEventType.h @@ -1,8 +1,10 @@ #pragma once +#include + namespace audioapi { -enum class ParamChangeEventType { +enum class ParamChangeEventType : std::uint8_t { LINEAR_RAMP, EXPONENTIAL_RAMP, SET_VALUE, 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 aa37ec754..18f36dc26 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 @@ -23,6 +23,10 @@ class AudioRecorderCallback { size_t bufferLength, int channelCount, uint64_t callbackId); + AudioRecorderCallback(const AudioRecorderCallback &) = delete; + AudioRecorderCallback(AudioRecorderCallback &&) = delete; + AudioRecorderCallback &operator=(const AudioRecorderCallback &) = delete; + AudioRecorderCallback &operator=(AudioRecorderCallback &&) = delete; virtual ~AudioRecorderCallback(); virtual void cleanup() = 0; 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 9e4ff8cdd..eb598b381 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 @@ -38,10 +38,10 @@ std::shared_ptr AudioStretcher::changePlaybackSpeed( std::vector int16Buffer = castToInt16Buffer(buffer); - auto stretcher = stretch_init( + auto *stretcher = stretch_init( static_cast(sampleRate / UPPER_FREQUENCY_LIMIT_DETECTION), static_cast(sampleRate / LOWER_FREQUENCY_LIMIT_DETECTION), - outputChannels, + static_cast(outputChannels), 0x1); int maxOutputFrames = @@ -55,7 +55,7 @@ std::shared_ptr AudioStretcher::changePlaybackSpeed( stretchedBuffer.data(), 1 / playbackSpeed); - outputFrames += stretch_flush(stretcher, stretchedBuffer.data() + (outputFrames)); + outputFrames += stretch_flush(stretcher, stretchedBuffer.data() + outputFrames); stretchedBuffer.resize(outputFrames * outputChannels); stretch_deinit(stretcher); 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 4a8e47482..d3c46ef33 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 @@ -18,10 +18,10 @@ class AudioStretcher { private: static std::vector castToInt16Buffer(AudioBuffer &buffer); - [[nodiscard]] static inline int16_t floatToInt16(float sample) { + [[nodiscard]] static int16_t floatToInt16(float sample) { return static_cast(sample * INT16_MAX); } - [[nodiscard]] static inline float int16ToFloat(int16_t sample) { + [[nodiscard]] static float int16ToFloat(int16_t sample) { return static_cast(sample) / INT16_MAX; } }; diff --git a/packages/react-native-audio-api/common/cpp/audioapi/core/utils/Constants.h b/packages/react-native-audio-api/common/cpp/audioapi/core/utils/Constants.h index dd12c78cd..59d8b8627 100644 --- a/packages/react-native-audio-api/common/cpp/audioapi/core/utils/Constants.h +++ b/packages/react-native-audio-api/common/cpp/audioapi/core/utils/Constants.h @@ -25,8 +25,8 @@ static constexpr float MOST_POSITIVE_SINGLE_FLOAT = static_cast(std::numeric_limits::max()); static constexpr float MOST_NEGATIVE_SINGLE_FLOAT = static_cast(std::numeric_limits::lowest()); -static float LOG2_MOST_POSITIVE_SINGLE_FLOAT = std::log2(MOST_POSITIVE_SINGLE_FLOAT); -static float LOG10_MOST_POSITIVE_SINGLE_FLOAT = std::log10(MOST_POSITIVE_SINGLE_FLOAT); +static const float LOG2_MOST_POSITIVE_SINGLE_FLOAT = std::log2(MOST_POSITIVE_SINGLE_FLOAT); +static const float LOG10_MOST_POSITIVE_SINGLE_FLOAT = std::log10(MOST_POSITIVE_SINGLE_FLOAT); static constexpr float PI = std::numbers::pi_v; // buffer sizes diff --git a/packages/react-native-audio-api/common/cpp/audioapi/core/utils/Macros.h b/packages/react-native-audio-api/common/cpp/audioapi/core/utils/Macros.h new file mode 100644 index 000000000..d246df6c4 --- /dev/null +++ b/packages/react-native-audio-api/common/cpp/audioapi/core/utils/Macros.h @@ -0,0 +1,7 @@ +#pragma once + +#define DELETE_COPY_AND_MOVE(ClassName) \ + ClassName(const ClassName &) = delete; \ + ClassName &operator=(const ClassName &) = delete; \ + ClassName(ClassName &&) = delete; \ + ClassName &operator=(ClassName &&) = delete diff --git a/packages/react-native-audio-api/common/cpp/audioapi/core/utils/worklets/SafeIncludes.h b/packages/react-native-audio-api/common/cpp/audioapi/core/utils/worklets/SafeIncludes.h index 9ccc7824d..6569e6dc5 100644 --- a/packages/react-native-audio-api/common/cpp/audioapi/core/utils/worklets/SafeIncludes.h +++ b/packages/react-native-audio-api/common/cpp/audioapi/core/utils/worklets/SafeIncludes.h @@ -36,16 +36,23 @@ class MessageQueueThread {}; class WorkletsModuleProxy {}; class WorkletRuntime { public: + // NOLINTNEXTLINE(cppcoreguidelines-pro-type-member-init) -- dummy type, members unused explicit WorkletRuntime( uint64_t, const std::shared_ptr &, const std::string &, - const bool){throw RN_AUDIO_API_WORKLETS_DISABLED_ERROR} jsi::Runtime &getJSIRuntime() const { + const bool) { + throw RN_AUDIO_API_WORKLETS_DISABLED_ERROR + } + [[nodiscard]] jsi::Runtime &getJSIRuntime() const { + throw RN_AUDIO_API_WORKLETS_DISABLED_ERROR + } + [[nodiscard]] jsi::Value executeSync(jsi::Runtime &rt, const jsi::Value &worklet) const { + throw RN_AUDIO_API_WORKLETS_DISABLED_ERROR + } + [[nodiscard]] jsi::Value executeSync(std::function &&job) const { + // NOLINT(cppcoreguidelines-rvalue-reference-param-not-moved) throw RN_AUDIO_API_WORKLETS_DISABLED_ERROR} jsi::Value - executeSync(jsi::Runtime &rt, const jsi::Value &worklet) const { - throw RN_AUDIO_API_WORKLETS_DISABLED_ERROR} jsi::Value - executeSync(std::function &&job) const { - throw RN_AUDIO_API_WORKLETS_DISABLED_ERROR} jsi::Value executeSync(const std::function &job) const { throw RN_AUDIO_API_WORKLETS_DISABLED_ERROR } @@ -65,7 +72,8 @@ class SerializableWorklet { /// @brief Struct to hold references to different runtimes used in the AudioAPI /// @note it is used to pass them around and avoid creating multiple instances of the same runtime -struct RuntimeRegistry { +struct + RuntimeRegistry { // NOLINT(cppcoreguidelines-pro-type-member-init) -- weak_ptr/shared_ptr default-init std::weak_ptr uiRuntime; std::shared_ptr audioRuntime; 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 bf0371669..30a98aee9 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 @@ -14,6 +14,7 @@ namespace audioapi::dsp { return static_cast(sampleFrame) / sampleRate; } +// NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables) -- function, not variable [[nodiscard]] inline float linearInterpolate( std::span source, size_t firstIndex, @@ -28,11 +29,13 @@ namespace audioapi::dsp { } [[nodiscard]] inline float linearToDecibels(float value) { - return 20.0f * log10f(value); + constexpr float kDecibelsLinearFactor = 20.0f; + return kDecibelsLinearFactor * log10f(value); } [[nodiscard]] inline float decibelsToLinear(float value) { - return static_cast(pow(10, value / 20)); + constexpr float kDecibelsDenominator = 20.0f; + return static_cast(pow(10, value / kDecibelsDenominator)); } } // namespace audioapi::dsp 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 38daa7397..7930beb30 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 @@ -14,6 +14,11 @@ class FFT { explicit FFT(int size); ~FFT(); + FFT(const FFT &) = delete; + FFT &operator=(const FFT &) = delete; + FFT(FFT &&) = delete; + FFT &operator=(FFT &&) = delete; + template void doFFT(const AudioArray &in, std::vector, Allocator> &out) { pffft_transform_ordered( diff --git a/packages/react-native-audio-api/common/cpp/audioapi/types/NodeOptions.h b/packages/react-native-audio-api/common/cpp/audioapi/types/NodeOptions.h index e5846f1ec..a4e96bfd0 100644 --- a/packages/react-native-audio-api/common/cpp/audioapi/types/NodeOptions.h +++ b/packages/react-native-audio-api/common/cpp/audioapi/types/NodeOptions.h @@ -49,20 +49,20 @@ struct StereoPannerOptions : AudioNodeOptions { channelCountMode = ChannelCountMode::CLAMPED_MAX; } - explicit StereoPannerOptions(AudioNodeOptions &&options) : AudioNodeOptions(options) { + explicit StereoPannerOptions(AudioNodeOptions &&options) : AudioNodeOptions(std::move(options)) { channelCountMode = ChannelCountMode::CLAMPED_MAX; } }; struct ConvolverOptions : AudioNodeOptions { bool disableNormalization = false; - std::shared_ptr buffer; + std::shared_ptr buffer = nullptr; ConvolverOptions() { requiresTailProcessing = true; } - explicit ConvolverOptions(AudioNodeOptions &&options) : AudioNodeOptions(options) { + explicit ConvolverOptions(AudioNodeOptions &&options) : AudioNodeOptions(std::move(options)) { requiresTailProcessing = true; } }; @@ -72,23 +72,29 @@ struct ConstantSourceOptions : AudioScheduledSourceNodeOptions { }; struct AnalyserOptions : AudioNodeOptions { - int fftSize = 2048; - float minDecibels = -100.0f; - float maxDecibels = -30.0f; - float smoothingTimeConstant = 0.8f; + static constexpr int kDefaultFftSize = 2048; + static constexpr float kDefaultMinDecibels = -100.0f; + static constexpr float kDefaultMaxDecibels = -30.0f; + static constexpr float kDefaultSmoothingTimeConstant = 0.8f; + int fftSize = kDefaultFftSize; + float minDecibels = kDefaultMinDecibels; + float maxDecibels = kDefaultMaxDecibels; + float smoothingTimeConstant = kDefaultSmoothingTimeConstant; }; struct BiquadFilterOptions : AudioNodeOptions { + static constexpr float kDefaultFrequency = 350.0f; BiquadFilterType type = BiquadFilterType::LOWPASS; - float frequency = 350.0f; + float frequency = kDefaultFrequency; float detune = 0.0f; float Q = 1.0f; float gain = 0.0f; }; struct OscillatorOptions : AudioScheduledSourceNodeOptions { - std::shared_ptr periodicWave; - float frequency = 440.0f; + static constexpr float kDefaultFrequency = 440.0f; + std::shared_ptr periodicWave = nullptr; + float frequency = kDefaultFrequency; float detune = 0.0f; OscillatorType type = OscillatorType::SINE; }; @@ -100,20 +106,20 @@ struct BaseAudioBufferSourceOptions : AudioScheduledSourceNodeOptions { }; struct AudioBufferSourceOptions : BaseAudioBufferSourceOptions { - std::shared_ptr buffer; + std::shared_ptr buffer = nullptr; float loopStart = 0.0f; float loopEnd = 0.0f; bool loop = false; bool loopSkip = false; explicit AudioBufferSourceOptions(BaseAudioBufferSourceOptions &&options) - : BaseAudioBufferSourceOptions(options) { + : BaseAudioBufferSourceOptions(std::move(options)) { channelCount = 1; } }; struct StreamerOptions : AudioScheduledSourceNodeOptions { - std::string streamPath; + std::string streamPath = {}; }; struct DelayOptions : AudioNodeOptions { @@ -130,8 +136,8 @@ struct DelayOptions : AudioNodeOptions { }; struct IIRFilterOptions : AudioNodeOptions { - std::vector feedforward; - std::vector feedback; + std::vector feedforward = {}; + std::vector feedback = {}; IIRFilterOptions() = default; @@ -145,7 +151,7 @@ struct IIRFilterOptions : AudioNodeOptions { }; struct WaveShaperOptions : AudioNodeOptions { - std::shared_ptr curve; + std::shared_ptr curve = nullptr; OverSampleType oversample = OverSampleType::OVERSAMPLE_NONE; WaveShaperOptions() { @@ -153,7 +159,7 @@ struct WaveShaperOptions : AudioNodeOptions { channelCountMode = ChannelCountMode::CLAMPED_MAX; } - explicit WaveShaperOptions(const AudioNodeOptions &&options) : AudioNodeOptions(options) { + explicit WaveShaperOptions(const AudioNodeOptions &options) : AudioNodeOptions(options) { // to change after graph processing improvement - should be max channelCountMode = ChannelCountMode::CLAMPED_MAX; } 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 6836f51ae..b5dc035f1 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 @@ -58,7 +58,7 @@ class AudioArray { return {data_.get(), size_}; } - [[nodiscard]] std::span subSpan(size_t length, size_t offset = 0) { + [[nodiscard]] std::span subSpan(size_t length, size_t offset = 0) const { if (offset + length > size_) { throw std::out_of_range("AudioArray::subSpan - offset + length exceeds array size"); } diff --git a/packages/react-native-audio-api/common/cpp/audioapi/utils/SpscChannel.hpp b/packages/react-native-audio-api/common/cpp/audioapi/utils/SpscChannel.hpp index df9cf27d8..548a78227 100644 --- a/packages/react-native-audio-api/common/cpp/audioapi/utils/SpscChannel.hpp +++ b/packages/react-native-audio-api/common/cpp/audioapi/utils/SpscChannel.hpp @@ -12,7 +12,7 @@ namespace audioapi::channels::spsc { /// @brief Overflow strategy for sender when the channel is full -enum class OverflowStrategy { +enum class OverflowStrategy : uint8_t { /// @brief Block and wait for space (default behavior) WAIT_ON_FULL, @@ -21,7 +21,7 @@ enum class OverflowStrategy { }; /// @brief Wait strategy for receiver and sender when looping and trying -enum class WaitStrategy { +enum class WaitStrategy : uint8_t { /// @brief Busy loop waiting strategy /// @note should be used when low latency is required and channel is not expected to wait /// @note should be definitely used with OverflowStrategy::OVERWRITE_ON_FULL @@ -40,7 +40,7 @@ enum class WaitStrategy { }; /// @brief Response status for channel operations -enum class ResponseStatus { +enum class ResponseStatus : uint8_t { SUCCESS, CHANNEL_FULL, CHANNEL_EMPTY, @@ -230,11 +230,6 @@ class InnerChannel { capacity_mask_(capacity_ - 1), buffer_( static_cast(operator new[](capacity_ * sizeof(T), std::align_val_t{alignof(T)}))) { - - // Initialize cache values for better performance - rcvCursorCache_ = 0; - sendCursorCache_ = 0; - // Initialize reader state for overwrite strategy if constexpr (Strategy == OverflowStrategy::OVERWRITE_ON_FULL) { oldestOccupied_.store(false, std::memory_order_relaxed); @@ -319,7 +314,7 @@ class InnerChannel { private: /// @brief Try to send with WAIT_ON_FULL strategy (original behavior) template - inline ResponseStatus try_send_wait_on_full(U &&value) noexcept( + ResponseStatus try_send_wait_on_full(U &&value) noexcept( std::is_nothrow_constructible_v) { size_t sendCursor = sendCursor_.load(std::memory_order_relaxed); // only sender thread writes this @@ -328,8 +323,9 @@ class InnerChannel { if (next_sendCursor == rcvCursorCache_) { // Refresh the cache rcvCursorCache_ = rcvCursor_.load(std::memory_order_acquire); - if (next_sendCursor == rcvCursorCache_) + if (next_sendCursor == rcvCursorCache_) { return ResponseStatus::CHANNEL_FULL; + } } // Construct the new element in place @@ -346,7 +342,7 @@ class InnerChannel { /// @brief Try to send with OVERWRITE_ON_FULL strategy template - inline ResponseStatus try_send_overwrite_on_full(U &&value) noexcept( + ResponseStatus try_send_overwrite_on_full(U &&value) noexcept( std::is_nothrow_constructible_v) { size_t sendCursor = sendCursor_.load(std::memory_order_relaxed); // only sender thread writes this @@ -391,12 +387,12 @@ class InnerChannel { /// @param n The input value /// @return The next power of 2 static constexpr size_t next_power_of_2(const size_t n) noexcept { - if (n <= 1) + if (n <= 1) { return 1; - + } // Use bit manipulation for efficiency size_t power = 1; - while (power < n) { + while (power < n) [[likely]] { power <<= 1; } return power; @@ -406,7 +402,7 @@ class InnerChannel { /// @param val The current index /// @return The next index /// @note it might not be used for performance but it is a good reference - inline size_t next_index(const size_t val) const noexcept { + size_t next_index(const size_t val) const noexcept { return (val + 1) & capacity_mask_; } diff --git a/packages/react-native-audio-api/scripts/cpplint.sh b/packages/react-native-audio-api/scripts/cpplint.sh index 306b75c7a..2a41eaa66 100755 --- a/packages/react-native-audio-api/scripts/cpplint.sh +++ b/packages/react-native-audio-api/scripts/cpplint.sh @@ -1,7 +1,7 @@ #!/bin/bash if which cpplint >/dev/null; then - find common/cpp android/src/main/cpp -path 'common/cpp/audioapi/libs' -prune -o -path 'common/cpp/audioapi/external' -prune -o -path 'common/cpp/audioapi/dsp/r8brain' -prune -o \( -name '*.cpp' -o -name '*.h' -o -name '*.hpp' \) -print | xargs cpplint --linelength=100 --filter=-legal/copyright,-readability/todo,-build/namespaces,-build/include_order,-whitespace,-build/c++17,-build/c++20,-runtime/references,-runtime/string,-readability/braces --quiet --recursive "$@" + find common/cpp android/src/main/cpp -path 'common/cpp/audioapi/libs' -prune -o -path 'common/cpp/audioapi/external' -prune -o -path 'common/cpp/audioapi/dsp/r8brain' -prune -o \( -name '*.cpp' -o -name '*.h' -o -name '*.hpp' \) -print | xargs cpplint --linelength=100 --filter=-legal/copyright,-readability/todo,-readability/nolint,-build/namespaces,-build/include_order,-whitespace,-build/c++17,-build/c++20,-runtime/references,-runtime/string,-readability/braces --quiet --recursive "$@" else echo "error: cpplint not installed, download from https://github.com/cpplint/cpplint" 1>&2 exit 1 From b993ca207265ae993b6b1838fad13add16d90c9d Mon Sep 17 00:00:00 2001 From: michal Date: Mon, 16 Mar 2026 15:35:57 +0100 Subject: [PATCH 3/9] refactor: 2nd part --- .../HostObjects/AudioParamHostObject.cpp | 2 +- .../AudioEventHandlerRegistryHostObject.cpp | 5 +- .../sources/AudioBufferHostObject.cpp | 4 +- .../sources/AudioBufferHostObject.h | 4 +- .../AudioBufferQueueSourceNodeHostObject.cpp | 5 +- .../AudioBufferSourceNodeHostObject.cpp | 2 +- .../sources/StreamerNodeHostObject.h | 2 +- .../utils/AudioDecoderHostObject.cpp | 10 ++-- .../HostObjects/utils/JsEnumParser.cpp | 4 ++ .../HostObjects/utils/NodeOptionsParser.h | 4 +- .../common/cpp/audioapi/core/AudioNode.cpp | 3 +- .../common/cpp/audioapi/core/AudioNode.h | 2 +- .../common/cpp/audioapi/core/AudioParam.cpp | 11 ++--- .../cpp/audioapi/core/OfflineAudioContext.cpp | 2 +- .../cpp/audioapi/core/OfflineAudioContext.h | 2 + .../core/destinations/AudioDestinationNode.h | 2 +- .../cpp/audioapi/core/effects/DelayNode.cpp | 3 +- .../audioapi/core/effects/IIRFilterNode.cpp | 13 +++-- .../cpp/audioapi/core/effects/IIRFilterNode.h | 2 +- .../cpp/audioapi/core/effects/WorkletNode.cpp | 11 ++--- .../core/effects/WorkletProcessingNode.cpp | 6 +-- .../sources/AudioBufferBaseSourceNode.cpp | 25 ++++++---- .../core/sources/AudioBufferBaseSourceNode.h | 5 +- .../sources/AudioBufferQueueSourceNode.cpp | 4 +- .../core/sources/AudioBufferQueueSourceNode.h | 13 ++++- .../core/sources/AudioBufferSourceNode.cpp | 3 +- .../core/sources/AudioScheduledSourceNode.cpp | 2 +- .../core/sources/ConstantSourceNode.cpp | 2 +- .../audioapi/core/sources/OscillatorNode.cpp | 11 +++-- .../core/sources/RecorderAdapterNode.cpp | 6 +-- .../core/sources/RecorderAdapterNode.h | 2 +- .../cpp/audioapi/core/utils/AudioDecoder.cpp | 2 +- .../cpp/audioapi/core/utils/AudioDecoder.h | 48 ++++++++++-------- .../audioapi/core/utils/AudioDestructor.hpp | 4 +- .../cpp/audioapi/core/utils/AudioFileWriter.h | 7 ++- .../audioapi/core/utils/AudioGraphManager.h | 25 +++++----- .../core/utils/AudioParamEventQueue.cpp | 6 +-- .../core/utils/AudioParamEventQueue.h | 8 +-- .../core/utils/AudioRecorderCallback.cpp | 2 +- .../core/utils/AudioRecorderCallback.h | 1 + .../cpp/audioapi/core/utils/Constants.h | 1 + .../common/cpp/audioapi/core/utils/Locker.h | 19 ++++++- .../audioapi/core/utils/ParamChangeEvent.hpp | 20 ++++---- .../common/cpp/audioapi/dsp/AudioUtils.hpp | 1 + .../common/cpp/audioapi/dsp/Convolver.cpp | 6 +-- .../common/cpp/audioapi/dsp/Convolver.h | 2 +- .../common/cpp/audioapi/dsp/FFT.cpp | 13 ++--- .../common/cpp/audioapi/dsp/VectorMath.cpp | 16 +++--- .../common/cpp/audioapi/dsp/WaveShaper.cpp | 2 - .../cpp/audioapi/dsp/r8brain/Resampler.cpp | 8 +-- .../cpp/audioapi/dsp/r8brain/Resampler.h | 16 +++--- .../common/cpp/audioapi/events/AudioEvent.h | 4 +- .../events/AudioEventHandlerRegistry.cpp | 2 +- .../common/cpp/audioapi/utils/AudioBuffer.cpp | 10 ++-- .../common/cpp/audioapi/utils/AudioBuffer.h | 4 +- .../common/cpp/audioapi/utils/Result.hpp | 49 +++++++++---------- .../utils/RingBiDirectionalBuffer.hpp | 37 ++++++++------ .../cpp/test/src/core/AudioParamTest.cpp | 4 ++ .../cpp/test/src/core/effects/DelayTest.cpp | 4 ++ .../cpp/test/src/core/effects/GainTest.cpp | 4 ++ .../test/src/core/effects/IIRFilterTest.cpp | 4 ++ .../src/core/effects/StereoPannerTest.cpp | 4 ++ .../src/core/effects/WaveShaperNodeTest.cpp | 4 ++ .../effects/biquad/BiquadFilterChromium.cpp | 4 ++ .../core/effects/biquad/BiquadFilterTest.cpp | 4 ++ .../core/sources/AudioScheduledSourceTest.cpp | 5 ++ .../src/core/sources/ConstantSourceTest.cpp | 4 ++ .../test/src/core/sources/OscillatorTest.cpp | 4 ++ .../cpp/test/src/utils/AudioArrayTest.cpp | 4 ++ .../cpp/test/src/utils/AudioBufferTest.cpp | 3 ++ .../cpp/test/src/utils/TripleBufferTest.cpp | 4 ++ 71 files changed, 331 insertions(+), 210 deletions(-) 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 1d4143307..dc619c851 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 @@ -103,7 +103,7 @@ JSI_HOST_FUNCTION_IMPL(AudioParamHostObject, setTargetAtTime) { JSI_HOST_FUNCTION_IMPL(AudioParamHostObject, setValueCurveAtTime) { auto arrayBuffer = args[0].getObject(runtime).getPropertyAsObject(runtime, "buffer").getArrayBuffer(runtime); - auto rawValues = reinterpret_cast(arrayBuffer.data(runtime)); + auto *rawValues = reinterpret_cast(arrayBuffer.data(runtime)); auto length = static_cast(arrayBuffer.size(runtime) / sizeof(float)); auto values = std::make_shared(rawValues, length); diff --git a/packages/react-native-audio-api/common/cpp/audioapi/HostObjects/events/AudioEventHandlerRegistryHostObject.cpp b/packages/react-native-audio-api/common/cpp/audioapi/HostObjects/events/AudioEventHandlerRegistryHostObject.cpp index dcf42f30a..444101930 100644 --- a/packages/react-native-audio-api/common/cpp/audioapi/HostObjects/events/AudioEventHandlerRegistryHostObject.cpp +++ b/packages/react-native-audio-api/common/cpp/audioapi/HostObjects/events/AudioEventHandlerRegistryHostObject.cpp @@ -7,9 +7,8 @@ namespace audioapi { AudioEventHandlerRegistryHostObject::AudioEventHandlerRegistryHostObject( - const std::shared_ptr &eventHandlerRegistry) { - eventHandlerRegistry_ = eventHandlerRegistry; - + const std::shared_ptr &eventHandlerRegistry) + : eventHandlerRegistry_(eventHandlerRegistry) { addFunctions( JSI_EXPORT_FUNCTION(AudioEventHandlerRegistryHostObject, addAudioEventListener), JSI_EXPORT_FUNCTION(AudioEventHandlerRegistryHostObject, removeAudioEventListener)); 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 a111272d5..447183c69 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 @@ -57,7 +57,7 @@ JSI_HOST_FUNCTION_IMPL(AudioBufferHostObject, getChannelData) { 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 *destination = reinterpret_cast(arrayBuffer.data(runtime)); auto length = arrayBuffer.size(runtime) / sizeof(float); auto channelNumber = static_cast(args[1].getNumber()); auto startInChannel = static_cast(args[2].getNumber()); @@ -70,7 +70,7 @@ JSI_HOST_FUNCTION_IMPL(AudioBufferHostObject, copyFromChannel) { 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 *source = reinterpret_cast(arrayBuffer.data(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/HostObjects/sources/AudioBufferHostObject.h b/packages/react-native-audio-api/common/cpp/audioapi/HostObjects/sources/AudioBufferHostObject.h index 0f8db07d9..f74de7ad0 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 @@ -27,7 +27,9 @@ class AudioBufferHostObject : public JsiHostObject { return *this; } - [[nodiscard]] inline size_t getSizeInBytes() const { + ~AudioBufferHostObject() override = default; + + [[nodiscard]] size_t getSizeInBytes() const { // *2 because every time buffer is passed we create a copy of it. return audioBuffer_->getSize() * audioBuffer_->getNumberOfChannels() * sizeof(float) * 2; } diff --git a/packages/react-native-audio-api/common/cpp/audioapi/HostObjects/sources/AudioBufferQueueSourceNodeHostObject.cpp b/packages/react-native-audio-api/common/cpp/audioapi/HostObjects/sources/AudioBufferQueueSourceNodeHostObject.cpp index 57b071d8c..ec1d063b1 100644 --- a/packages/react-native-audio-api/common/cpp/audioapi/HostObjects/sources/AudioBufferQueueSourceNodeHostObject.cpp +++ b/packages/react-native-audio-api/common/cpp/audioapi/HostObjects/sources/AudioBufferQueueSourceNodeHostObject.cpp @@ -74,8 +74,9 @@ JSI_HOST_FUNCTION_IMPL(AudioBufferQueueSourceNodeHostObject, enqueueBuffer) { std::shared_ptr tailBuffer = nullptr; if (pitchCorrection_ && !stretchHasBeenInit_) { - initStretch(copiedBuffer->getNumberOfChannels(), copiedBuffer->getSampleRate()); - int extraTailFrames = + initStretch( + static_cast(copiedBuffer->getNumberOfChannels()), copiedBuffer->getSampleRate()); + auto extraTailFrames = static_cast((inputLatency_ + outputLatency_) * copiedBuffer->getSampleRate()); tailBuffer = std::make_shared( copiedBuffer->getNumberOfChannels(), extraTailFrames, copiedBuffer->getSampleRate()); diff --git a/packages/react-native-audio-api/common/cpp/audioapi/HostObjects/sources/AudioBufferSourceNodeHostObject.cpp b/packages/react-native-audio-api/common/cpp/audioapi/HostObjects/sources/AudioBufferSourceNodeHostObject.cpp index 02f120edf..be16f585e 100644 --- a/packages/react-native-audio-api/common/cpp/audioapi/HostObjects/sources/AudioBufferSourceNodeHostObject.cpp +++ b/packages/react-native-audio-api/common/cpp/audioapi/HostObjects/sources/AudioBufferSourceNodeHostObject.cpp @@ -180,7 +180,7 @@ void AudioBufferSourceNodeHostObject::setBuffer(const std::shared_ptr(buffer->getNumberOfChannels()), buffer->getSampleRate()); - int extraTailFrames = + auto extraTailFrames = static_cast((inputLatency_ + outputLatency_) * buffer->getSampleRate()); size_t totalSize = buffer->getSize() + extraTailFrames; copiedBuffer = std::make_shared( diff --git a/packages/react-native-audio-api/common/cpp/audioapi/HostObjects/sources/StreamerNodeHostObject.h b/packages/react-native-audio-api/common/cpp/audioapi/HostObjects/sources/StreamerNodeHostObject.h index 38fb94a8d..58352f693 100644 --- a/packages/react-native-audio-api/common/cpp/audioapi/HostObjects/sources/StreamerNodeHostObject.h +++ b/packages/react-native-audio-api/common/cpp/audioapi/HostObjects/sources/StreamerNodeHostObject.h @@ -20,7 +20,7 @@ class StreamerNodeHostObject : public AudioScheduledSourceNodeHostObject { const StreamerOptions &options) : AudioScheduledSourceNodeHostObject(context->createStreamer(options), options) {} - [[nodiscard]] static inline size_t getSizeInBytes() { + [[nodiscard]] static size_t getSizeInBytes() { return SIZE; } diff --git a/packages/react-native-audio-api/common/cpp/audioapi/HostObjects/utils/AudioDecoderHostObject.cpp b/packages/react-native-audio-api/common/cpp/audioapi/HostObjects/utils/AudioDecoderHostObject.cpp index f8143b78b..105f7315a 100644 --- a/packages/react-native-audio-api/common/cpp/audioapi/HostObjects/utils/AudioDecoderHostObject.cpp +++ b/packages/react-native-audio-api/common/cpp/audioapi/HostObjects/utils/AudioDecoderHostObject.cpp @@ -22,10 +22,10 @@ AudioDecoderHostObject::AudioDecoderHostObject( JSI_HOST_FUNCTION_IMPL(AudioDecoderHostObject, decodeWithMemoryBlock) { auto arrayBuffer = args[0].getObject(runtime).getPropertyAsObject(runtime, "buffer").getArrayBuffer(runtime); - auto data = arrayBuffer.data(runtime); + auto *data = arrayBuffer.data(runtime); auto size = static_cast(arrayBuffer.size(runtime)); - auto sampleRate = args[1].getNumber(); + auto sampleRate = static_cast(args[1].getNumber()); auto promise = promiseVendor_->createAsyncPromise([data, size, sampleRate]() -> PromiseResolver { auto result = AudioDecoder::decodeWithMemoryBlock(data, size, sampleRate); @@ -51,7 +51,7 @@ JSI_HOST_FUNCTION_IMPL(AudioDecoderHostObject, decodeWithMemoryBlock) { JSI_HOST_FUNCTION_IMPL(AudioDecoderHostObject, decodeWithFilePath) { auto sourcePath = args[0].getString(runtime).utf8(runtime); - auto sampleRate = args[1].getNumber(); + auto sampleRate = static_cast(args[1].getNumber()); auto promise = promiseVendor_->createAsyncPromise([sourcePath, sampleRate]() -> PromiseResolver { auto result = AudioDecoder::decodeWithFilePath(sourcePath, sampleRate); @@ -78,8 +78,8 @@ JSI_HOST_FUNCTION_IMPL(AudioDecoderHostObject, decodeWithFilePath) { JSI_HOST_FUNCTION_IMPL(AudioDecoderHostObject, decodeWithPCMInBase64) { auto b64 = args[0].getString(runtime).utf8(runtime); - auto inputSampleRate = args[1].getNumber(); - auto inputChannelCount = args[2].getNumber(); + auto inputSampleRate = static_cast(args[1].getNumber()); + auto inputChannelCount = static_cast(args[2].getNumber()); auto interleaved = args[3].getBool(); auto promise = promiseVendor_->createAsyncPromise( diff --git a/packages/react-native-audio-api/common/cpp/audioapi/HostObjects/utils/JsEnumParser.cpp b/packages/react-native-audio-api/common/cpp/audioapi/HostObjects/utils/JsEnumParser.cpp index 8c6f0ba44..9c205d830 100644 --- a/packages/react-native-audio-api/common/cpp/audioapi/HostObjects/utils/JsEnumParser.cpp +++ b/packages/react-native-audio-api/common/cpp/audioapi/HostObjects/utils/JsEnumParser.cpp @@ -3,6 +3,8 @@ namespace audioapi::js_enum_parser { +// NOLINTBEGIN(readability-braces-around-statements) + BiquadFilterType filterTypeFromString(const std::string &type) { if (type == "lowpass") return BiquadFilterType::LOWPASS; @@ -187,3 +189,5 @@ std::string channelInterpretationToString(ChannelInterpretation interpretation) } } } // namespace audioapi::js_enum_parser + +// NOLINTEND(readability-braces-around-statements) 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 7bfcb439d..2a73d4a4a 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 @@ -238,7 +238,7 @@ inline BaseAudioBufferSourceOptions parseBaseAudioBufferSourceOptions( auto pitchCorrectionValue = optionsObject.getProperty(runtime, "pitchCorrection"); if (pitchCorrectionValue.isBool()) { - options.pitchCorrection = static_cast(pitchCorrectionValue.getBool()); + options.pitchCorrection = pitchCorrectionValue.getBool(); } return options; @@ -258,7 +258,7 @@ inline AudioBufferSourceOptions parseAudioBufferSourceOptions( auto loopValue = optionsObject.getProperty(runtime, "loop"); if (loopValue.isBool()) { - options.loop = static_cast(loopValue.getBool()); + options.loop = loopValue.getBool(); } auto loopStartValue = optionsObject.getProperty(runtime, "loopStart"); 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 eff5098fb..aeb2f3455 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 @@ -163,8 +163,7 @@ std::shared_ptr AudioNode::processInputs( processingBuffer->zero(); size_t maxNumberOfChannels = 0; - for (auto it = inputNodes_.begin(), end = inputNodes_.end(); it != end; ++it) { - auto inputNode = *it; + for (auto *inputNode : inputNodes_) { assert(inputNode != nullptr); if (!inputNode->isEnabled()) { 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 52690801a..5e4930cae 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 @@ -78,7 +78,7 @@ class AudioNode : public std::enable_shared_from_this { const int numberOfInputs_ = 1; const int numberOfOutputs_ = 1; - size_t channelCount_ = 2; + int channelCount_ = 2; const ChannelCountMode channelCountMode_ = ChannelCountMode::MAX; const ChannelInterpretation channelInterpretation_ = ChannelInterpretation::SPEAKERS; const bool requiresTailProcessing_; 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 bb440803b..04bed2e22 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 @@ -18,7 +18,6 @@ AudioParam::AudioParam( defaultValue_(defaultValue), minValue_(minValue), maxValue_(maxValue), - eventsQueue_(), startTime_(0), endTime_(0), startValue_(defaultValue), @@ -236,16 +235,17 @@ std::shared_ptr AudioParam::processARateParam(int framesToProcess, auto processingBuffer = calculateInputs(audioBuffer_, framesToProcess); std::shared_ptr context = context_.lock(); - if (context == nullptr) + if (context == nullptr) { return processingBuffer; + } float sampleRate = context->getSampleRate(); auto bufferData = processingBuffer->getChannel(0)->span(); - float timeCache = time; + double timeCache = time; float timeStep = 1.0f / sampleRate; float sample = 0.0f; // Add automated parameter value to each sample - for (size_t i = 0; i < framesToProcess; i++, timeCache += timeStep) { + for (int i = 0; i < framesToProcess; i++, timeCache += timeStep) { sample = getValueAtTime(timeCache); bufferData[i] += sample; } @@ -264,8 +264,7 @@ void AudioParam::processInputs( const std::shared_ptr &outputBuffer, int framesToProcess, bool checkIsAlreadyProcessed) { - for (auto it = inputNodes_.begin(), end = inputNodes_.end(); it != end; ++it) { - auto inputNode = *it; + for (auto *inputNode : inputNodes_) { assert(inputNode != nullptr); if (!inputNode->isEnabled()) { 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 2b21002af..4449aac1d 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 @@ -50,7 +50,7 @@ void OfflineAudioContext::suspend(double when, const std::function &call auto frame = static_cast(when * getSampleRate()); frame = RENDER_QUANTUM_SIZE * ((frame + RENDER_QUANTUM_SIZE - 1) / RENDER_QUANTUM_SIZE); - if (scheduledSuspends_.find(frame) != scheduledSuspends_.end()) { + if (scheduledSuspends_.contains(frame)) { throw std::runtime_error( "cannot schedule more than one suspend at frame " + std::to_string(frame) + " (" + std::to_string(when) + " seconds)"); 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 ce2015d4a..1b8e107f5 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 @@ -1,6 +1,7 @@ #pragma once #include +#include #include #include @@ -21,6 +22,7 @@ class OfflineAudioContext : public BaseAudioContext { const std::shared_ptr &audioEventHandlerRegistry, const RuntimeRegistry &runtimeRegistry); ~OfflineAudioContext() override; + DELETE_COPY_AND_MOVE(OfflineAudioContext); /// @note JS Thread only void resume(); 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 96b840479..b4a0c159b 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 @@ -30,7 +30,7 @@ class AudioDestinationNode : public AudioNode { // processNode function is not necessary and is never called. std::shared_ptr processNode( const std::shared_ptr &processingBuffer, - int) final { + int framesToProcess) final { return processingBuffer; }; 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 ecd01d9ed..19eb74286 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 @@ -43,7 +43,8 @@ void DelayNode::delayBufferOperation( // handle buffer wrap around if (operationStartingIndex + framesToProcess > delayBuffer_->getSize()) { - int framesToEnd = operationStartingIndex + framesToProcess - delayBuffer_->getSize(); + int framesToEnd = + static_cast(operationStartingIndex + framesToProcess - delayBuffer_->getSize()); if (action == BufferAction::WRITE) { delayBuffer_->sum( 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 216c3b505..cc19e6aed 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 @@ -43,7 +43,7 @@ IIRFilterNode::IIRFilterNode( feedback_(createNormalizedArray(options.feedback, options.feedback[0])), xBuffers_(bufferLength, MAX_CHANNEL_COUNT, context->getSampleRate()), yBuffers_(bufferLength, MAX_CHANNEL_COUNT, context->getSampleRate()), - bufferIndices_(bufferLength) { + bufferIndices_() { isInitialized_.store(true, std::memory_order_release); } @@ -84,8 +84,10 @@ void IIRFilterNode::getFrequencyResponse( float omega = -PI * normalizedFreq; auto z = std::complex(std::cos(omega), std::sin(omega)); - auto numerator = IIRFilterNode::evaluatePolynomial(feedforward_, z, feedforward_.getSize() - 1); - auto denominator = IIRFilterNode::evaluatePolynomial(feedback_, z, feedback_.getSize() - 1); + auto numerator = IIRFilterNode::evaluatePolynomial( + feedforward_, z, static_cast(feedforward_.getSize() - 1)); + auto denominator = + IIRFilterNode::evaluatePolynomial(feedback_, z, static_cast(feedback_.getSize() - 1)); auto response = numerator / denominator; magResponseOutput[k] = std::abs(response); @@ -101,7 +103,7 @@ void IIRFilterNode::getFrequencyResponse( std::shared_ptr IIRFilterNode::processNode( const std::shared_ptr &processingBuffer, int framesToProcess) { - int numChannels = processingBuffer->getNumberOfChannels(); + int numChannels = static_cast(processingBuffer->getNumberOfChannels()); size_t feedforwardLength = feedforward_.getSize(); size_t feedbackLength = feedback_.getSize(); @@ -122,7 +124,7 @@ std::shared_ptr IIRFilterNode::processNode( float y_n = feedforward_[0] * sample; for (k = 1; k < minLength; ++k) { - int m = (bufferIndex - k) & mask; + size_t m = (bufferIndex - k) & mask; y_n = std::fma(feedforward_[k], x[m], y_n); y_n = std::fma(-feedback_[k], y[m], y_n); } @@ -135,6 +137,7 @@ std::shared_ptr IIRFilterNode::processNode( } // Avoid denormalized numbers + // NOLINTNEXTLINE(cppcoreguidelines-avoid-magic-numbers, readability-magic-numbers) if (std::abs(y_n) < 1e-15f) { y_n = 0.0f; } 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 0a30b06d7..edb1f4432 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 @@ -64,7 +64,7 @@ class IIRFilterNode : public AudioNode { AudioBuffer xBuffers_; AudioBuffer yBuffers_; - AudioArray bufferIndices_; + std::array bufferIndices_; static std::complex evaluatePolynomial(const AudioArray &coefficients, std::complex z, int order) { 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 d18f15dbd..6c6082fb8 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 @@ -9,9 +9,9 @@ WorkletNode::WorkletNode( const std::shared_ptr &context, size_t bufferLength, size_t inputChannelCount, - WorkletsRunner &&runtime) + WorkletsRunner &&workletRunner) : AudioNode(context), - workletRunner_(std::move(runtime)), + workletRunner_(std::move(workletRunner)), buffer_( std::make_shared(bufferLength, inputChannelCount, context->getSampleRate())), bufferLength_(bufferLength), @@ -23,9 +23,8 @@ WorkletNode::WorkletNode( std::shared_ptr WorkletNode::processNode( const std::shared_ptr &processingBuffer, int framesToProcess) { - size_t processed = 0; - size_t channelCount_ = - std::min(inputChannelCount_, static_cast(processingBuffer->getNumberOfChannels())); + int processed = 0; + size_t channelCount_ = std::min(inputChannelCount_, processingBuffer->getNumberOfChannels()); while (processed < framesToProcess) { size_t framesToWorkletInvoke = bufferLength_ - curBuffIndex_; size_t needsToProcess = framesToProcess - processed; @@ -36,7 +35,7 @@ std::shared_ptr WorkletNode::processNode( /// from [processed, processed + shouldProcess] buffer_->copy(*processingBuffer, processed, curBuffIndex_, shouldProcess); - processed += shouldProcess; + processed += static_cast(shouldProcess); curBuffIndex_ += shouldProcess; /// If we filled the entire buffer, we need to execute the worklet 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 683a34df4..36e345a47 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 @@ -27,7 +27,7 @@ std::shared_ptr WorkletProcessingNode::processNode( int framesToProcess) { size_t channelCount = std::min( static_cast(2), // Fixed to stereo for now - static_cast(processingBuffer->getNumberOfChannels())); + processingBuffer->getNumberOfChannels()); // Copy input data to pre-allocated input buffers for (size_t ch = 0; ch < channelCount; ch++) { @@ -53,7 +53,7 @@ std::shared_ptr WorkletProcessingNode::processNode( // We call unsafely here because we are already on the runtime thread // and the runtime is locked by executeOnRuntimeSync (if // shouldLockRuntime is true) - float time = 0.0f; + double time = 0.0f; if (std::shared_ptr context = context_.lock()) { time = context->getCurrentTime(); } @@ -66,7 +66,7 @@ std::shared_ptr WorkletProcessingNode::processNode( // Copy processed output data back to the processing buffer or zero on failure for (size_t ch = 0; ch < channelCount; ch++) { - auto channelData = processingBuffer->getChannel(ch); + auto *channelData = processingBuffer->getChannel(ch); if (result.has_value()) { // Copy processed output data 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 eedb0ea47..132212c45 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 @@ -35,8 +35,8 @@ AudioBufferBaseSourceNode::AudioBufferBaseSourceNode( MOST_POSITIVE_SINGLE_FLOAT, context)), vReadIndex_(0.0), - onPositionChangedInterval_(static_cast(context->getSampleRate() * 0.1)) {} - + onPositionChangedInterval_( + static_cast(context->getSampleRate() * ON_POSITION_CHANGED_INTERVAL_SECONDS)) {} void AudioBufferBaseSourceNode::initStretch( const std::shared_ptr> &stretch) { stretch_ = stretch; @@ -55,8 +55,9 @@ void AudioBufferBaseSourceNode::setOnPositionChangedCallbackId(uint64_t callback } void AudioBufferBaseSourceNode::setOnPositionChangedInterval(int interval) { - onPositionChangedInterval_ = - static_cast(getContextSampleRate() * static_cast(interval) / 1000); + onPositionChangedInterval_ = static_cast( + getContextSampleRate() * static_cast(interval) * + 1e-3f); //NOLINT(cppcoreguidelines-avoid-magic-numbers, readability-magic-numbers) } int AudioBufferBaseSourceNode::getOnPositionChangedInterval() const { @@ -92,10 +93,14 @@ void AudioBufferBaseSourceNode::processWithPitchCorrection( return; } auto time = context->getCurrentTime(); - auto playbackRate = - std::clamp(playbackRateParam_->processKRateParam(framesToProcess, time), 0.0f, 3.0f); - auto detune = - std::clamp(detuneParam_->processKRateParam(framesToProcess, time) / 100.0f, -12.0f, 12.0f); + auto playbackRate = std::clamp( + playbackRateParam_->processKRateParam(framesToProcess, time), + MIN_PLAYBACK_RATE, + MAX_PLAYBACK_RATE); + auto detune = std::clamp( + detuneParam_->processKRateParam(framesToProcess, time) / 100.0f, + static_cast(-SEMITONES_PER_OCTAVE), + static_cast(SEMITONES_PER_OCTAVE)); playbackRateBuffer_->zero(); @@ -166,7 +171,9 @@ void AudioBufferBaseSourceNode::processWithoutPitchCorrection( float AudioBufferBaseSourceNode::getComputedPlaybackRateValue(int framesToProcess, double time) { auto playbackRate = playbackRateParam_->processKRateParam(framesToProcess, time); - auto detune = std::pow(2.0f, detuneParam_->processKRateParam(framesToProcess, time) / 1200.0f); + auto detune = std::pow( + 2.0f, //NOLINT(cppcoreguidelines-avoid-magic-numbers, readability-magic-numbers) + detuneParam_->processKRateParam(framesToProcess, time) / static_cast(OCTAVE_RANGE)); return playbackRate * 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 f8330650c..8edfd527d 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 @@ -3,9 +3,7 @@ #include #include -#include #include -#include namespace audioapi { @@ -43,6 +41,8 @@ class AudioBufferBaseSourceNode : public AudioScheduledSourceNode { // pitch correction std::shared_ptr> stretch_; std::shared_ptr playbackRateBuffer_; + static constexpr float MAX_PLAYBACK_RATE = 3.0f; + static constexpr float MIN_PLAYBACK_RATE = 0.0f; // k-rate params const std::shared_ptr detuneParam_; @@ -54,6 +54,7 @@ class AudioBufferBaseSourceNode : public AudioScheduledSourceNode { uint64_t onPositionChangedCallbackId_ = 0; // 0 means no callback int onPositionChangedInterval_; int onPositionChangedTime_ = 0; + static constexpr float ON_POSITION_CHANGED_INTERVAL_SECONDS = 0.1f; virtual double getCurrentPosition() const = 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 5a2d8383e..dcbfe748e 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 @@ -172,6 +172,7 @@ void AudioBufferQueueSourceNode::sendOnBufferEndedEvent(size_t bufferId, bool is * Helper functions */ +// todo: refactor so its less complex and more readable void AudioBufferQueueSourceNode::processWithoutInterpolation( const std::shared_ptr &processingBuffer, size_t startOffset, @@ -237,6 +238,7 @@ void AudioBufferQueueSourceNode::processWithoutInterpolation( } } +// todo: refactor so its less complex and more readable void AudioBufferQueueSourceNode::processWithInterpolation( const std::shared_ptr &processingBuffer, size_t startOffset, @@ -304,7 +306,7 @@ void AudioBufferQueueSourceNode::processWithInterpolation( } context->getGraphManager()->addAudioBufferForDestruction(std::move(buffer)); - vReadIndex_ = vReadIndex_ - buffer->getSize(); + vReadIndex_ = vReadIndex_ - static_cast(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 1d56886c9..addabe925 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,5 +1,6 @@ #pragma once +#include #include #include #include @@ -7,7 +8,6 @@ #include #include #include -#include namespace audioapi { @@ -60,7 +60,7 @@ class AudioBufferQueueSourceNode : public AudioBufferBaseSourceNode { private: // User provided buffers - std::list>> buffers_{}; + std::list>> buffers_; bool isPaused_ = false; bool addExtraTailFrames_ = false; @@ -81,6 +81,15 @@ class AudioBufferQueueSourceNode : public AudioBufferBaseSourceNode { size_t startOffset, size_t offsetLength, float playbackRate) override; + + bool advanceToNextBuffer( + BaseAudioContext &context, + const std::shared_ptr &processingBuffer, + size_t bufferId, + std::shared_ptr consumedBuffer, + size_t writeIndex, + size_t framesLeft, + bool forInterpolation = false); }; } // namespace audioapi 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 c4fddbe80..bf495990b 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 @@ -79,7 +79,7 @@ void AudioBufferSourceNode::setBuffer( buffer_ = buffer; playbackRateBuffer_ = playbackRateBuffer; audioBuffer_ = audioBuffer; - channelCount_ = buffer_->getNumberOfChannels(); + channelCount_ = static_cast(buffer_->getNumberOfChannels()); loopEnd_ = buffer_->getDuration(); } @@ -150,6 +150,7 @@ void AudioBufferSourceNode::sendOnLoopEndedEvent() { * Helper functions */ +// todo: refactor so its less complex and more readable void AudioBufferSourceNode::processWithoutInterpolation( const std::shared_ptr &processingBuffer, size_t startOffset, 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 551b93982..b70fba6f1 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 @@ -28,7 +28,7 @@ AudioScheduledSourceNode::AudioScheduledSourceNode( void AudioScheduledSourceNode::start(double when) { #if !RN_AUDIO_API_TEST if (std::shared_ptr context = context_.lock()) { - if (auto audioContext = dynamic_cast(context.get())) { + if (auto *audioContext = dynamic_cast(context.get())) { audioContext->start(); } } 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 8f863698c..adc772e3d 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 @@ -49,7 +49,7 @@ std::shared_ptr ConstantSourceNode::processNode( return processingBuffer; } - auto offsetChannel = + auto *offsetChannel = offsetParam_->processARateParam(framesToProcess, context->getCurrentTime())->getChannel(0); for (size_t channel = 0; channel < processingBuffer->getNumberOfChannels(); ++channel) { 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 2d32fb8dc..a0d54e899 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 @@ -11,15 +11,14 @@ namespace audioapi { OscillatorNode::OscillatorNode( const std::shared_ptr &context, const OscillatorOptions &options) - : AudioScheduledSourceNode(context, options) { + : AudioScheduledSourceNode(context, options), type_(options.type) { frequencyParam_ = std::make_shared( options.frequency, -getNyquistFrequency(), getNyquistFrequency(), context); detuneParam_ = std::make_shared( options.detune, - -1200 * LOG2_MOST_POSITIVE_SINGLE_FLOAT, - 1200 * LOG2_MOST_POSITIVE_SINGLE_FLOAT, + -static_cast(OCTAVE_RANGE) * LOG2_MOST_POSITIVE_SINGLE_FLOAT, + static_cast(OCTAVE_RANGE) * LOG2_MOST_POSITIVE_SINGLE_FLOAT, context); - type_ = options.type; if (options.periodicWave) { periodicWave_ = options.periodicWave; } else { @@ -92,7 +91,9 @@ std::shared_ptr OscillatorNode::processNode( 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 detuneRatio = detuneSpan[i] == 0 + ? 1.0f + : std::pow(2.0f, detuneSpan[i] / static_cast(OCTAVE_RANGE)); auto detunedFrequency = freqSpan[i] * detuneRatio; auto phaseIncrement = detunedFrequency * tableScale; 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 4ac6ba93b..eb800a130 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 @@ -30,7 +30,7 @@ void RecorderAdapterNode::init(size_t bufferSize, int channelCount, float sample buff_.resize(channelCount_); - for (size_t i = 0; i < channelCount_; ++i) { + for (int i = 0; i < channelCount_; ++i) { buff_[i] = std::make_shared(bufferSize); } @@ -59,7 +59,7 @@ void RecorderAdapterNode::init(size_t bufferSize, int channelCount, float sample isInitialized_.store(true, std::memory_order_release); } -void RecorderAdapterNode::cleanup() { +void RecorderAdapterNode::adapterCleanup() { needsResampling_ = false; buff_.clear(); resampler_.reset(); @@ -90,7 +90,7 @@ void RecorderAdapterNode::processResampled(int framesToProcess) { adapterOutputBuffer_->zero(); size_t outputWritten = 0; - const size_t needed = static_cast(framesToProcess); + const auto needed = static_cast(framesToProcess); // Drain leftover resampled samples from the previous call if (overflowSize_ > 0) { 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 d56f54041..e861e15f9 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 @@ -28,7 +28,7 @@ class RecorderAdapterNode : public AudioNode { /// @param channelCount The number of channels. /// @param sampleRate The recorder's native sample rate. void init(size_t bufferSize, int channelCount, float sampleRate); - void cleanup(); + void adapterCleanup(); // TODO: CircularOverflowableAudioBuffer std::vector> buff_; diff --git a/packages/react-native-audio-api/common/cpp/audioapi/core/utils/AudioDecoder.cpp b/packages/react-native-audio-api/common/cpp/audioapi/core/utils/AudioDecoder.cpp index c37448064..d6710d36a 100644 --- a/packages/react-native-audio-api/common/cpp/audioapi/core/utils/AudioDecoder.cpp +++ b/packages/react-native-audio-api/common/cpp/audioapi/core/utils/AudioDecoder.cpp @@ -143,7 +143,7 @@ AudioBufferResult AudioDecoder::decodeWithPCMInBase64( int inputChannelCount, bool interleaved) { auto decodedData = base64_decode(data, false); - const auto uint8Data = reinterpret_cast(decodedData.data()); + const auto *uint8Data = reinterpret_cast(decodedData.data()); size_t numFramesDecoded = decodedData.size() / (inputChannelCount * sizeof(int16_t)); auto audioBuffer = diff --git a/packages/react-native-audio-api/common/cpp/audioapi/core/utils/AudioDecoder.h b/packages/react-native-audio-api/common/cpp/audioapi/core/utils/AudioDecoder.h index 39e0809d9..96713a4d0 100644 --- a/packages/react-native-audio-api/common/cpp/audioapi/core/utils/AudioDecoder.h +++ b/packages/react-native-audio-api/common/cpp/audioapi/core/utils/AudioDecoder.h @@ -49,61 +49,69 @@ class AudioDecoder { const std::vector &buffer, float outputSampleRate, int outputChannels); + // NOLINTBEGIN(readability-magic-numbers, cppcoreguidelines-avoid-magic-numbers) static AudioFormat detectAudioFormat(const void *data, size_t size) { - if (size < 12) + if (size < 12) { return AudioFormat::UNKNOWN; + } const auto *bytes = static_cast(data); // WAV/RIFF - if (std::memcmp(bytes, "RIFF", 4) == 0 && std::memcmp(bytes + 8, "WAVE", 4) == 0) + if (std::memcmp(bytes, "RIFF", 4) == 0 && std::memcmp(bytes + 8, "WAVE", 4) == 0) { return AudioFormat::WAV; + } // OGG - if (std::memcmp(bytes, "OggS", 4) == 0) + if (std::memcmp(bytes, "OggS", 4) == 0) { return AudioFormat::OGG; + } // FLAC - if (std::memcmp(bytes, "fLaC", 4) == 0) + if (std::memcmp(bytes, "fLaC", 4) == 0) { return AudioFormat::FLAC; + } // AAC starts with 0xFF 0xF1 or 0xFF 0xF9 - if (bytes[0] == 0xFF && (bytes[1] & 0xF6) == 0xF0) + if (bytes[0] == 0xFF && (bytes[1] & 0xF6) == 0xF0) { return AudioFormat::AAC; + } // MP3: "ID3" or 11-bit frame sync (0xFF 0xE0) - if (std::memcmp(bytes, "ID3", 3) == 0) + if (std::memcmp(bytes, "ID3", 3) == 0) { return AudioFormat::MP3; - if (bytes[0] == 0xFF && (bytes[1] & 0xE0) == 0xE0) + } + if (bytes[0] == 0xFF && (bytes[1] & 0xE0) == 0xE0) { return AudioFormat::MP3; + } if (std::memcmp(bytes + 4, "ftyp", 4) == 0) { - if (std::memcmp(bytes + 8, "M4A ", 4) == 0) + if (std::memcmp(bytes + 8, "M4A ", 4) == 0) { return AudioFormat::M4A; - else if (std::memcmp(bytes + 8, "qt ", 4) == 0) + } + if (std::memcmp(bytes + 8, "qt ", 4) == 0) { return AudioFormat::MOV; + } return AudioFormat::MP4; } return AudioFormat::UNKNOWN; } - static inline bool pathHasExtension( + // NOLINTEND(readability-magic-numbers, cppcoreguidelines-avoid-magic-numbers) + static bool pathHasExtension( const std::string &path, const std::vector &extensions) { std::string pathLower = path; - std::transform(pathLower.begin(), pathLower.end(), pathLower.begin(), ::tolower); - for (const auto &ext : extensions) { - if (pathLower.ends_with(ext)) - return true; - } - return false; + std::ranges::transform(pathLower, pathLower.begin(), ::tolower); + return std::ranges::any_of( + extensions, [&pathLower](const std::string &ext) { return pathLower.ends_with(ext); }); } - [[nodiscard]] static inline int16_t floatToInt16(float sample) { + [[nodiscard]] static int16_t floatToInt16(float sample) { return static_cast(sample * INT16_MAX); } - [[nodiscard]] static inline float int16ToFloat(int16_t sample) { + [[nodiscard]] static float int16ToFloat(int16_t sample) { return static_cast(sample) / INT16_MAX; } - [[nodiscard]] static inline float uint8ToFloat(uint8_t byte1, uint8_t byte2) { - return static_cast(static_cast((byte2 << 8) | byte1)) / INT16_MAX; + [[nodiscard]] static float uint8ToFloat(uint8_t byte1, uint8_t byte2) { + return static_cast(static_cast((byte2 << CHAR_BIT) | byte1)) / INT16_MAX; } }; diff --git a/packages/react-native-audio-api/common/cpp/audioapi/core/utils/AudioDestructor.hpp b/packages/react-native-audio-api/common/cpp/audioapi/core/utils/AudioDestructor.hpp index 28f768993..2e8b94189 100644 --- a/packages/react-native-audio-api/common/cpp/audioapi/core/utils/AudioDestructor.hpp +++ b/packages/react-native-audio-api/common/cpp/audioapi/core/utils/AudioDestructor.hpp @@ -1,11 +1,11 @@ #pragma once +#include #include #include #include #include #include -#include namespace audioapi { @@ -14,6 +14,8 @@ namespace audioapi { template class AudioDestructor { public: + DELETE_COPY_AND_MOVE(AudioDestructor); + AudioDestructor() : isExiting_(false) { auto [sender, receiver] = channels::spsc::channel< std::shared_ptr, diff --git a/packages/react-native-audio-api/common/cpp/audioapi/core/utils/AudioFileWriter.h b/packages/react-native-audio-api/common/cpp/audioapi/core/utils/AudioFileWriter.h index 464ac82e8..352e140b3 100644 --- a/packages/react-native-audio-api/common/cpp/audioapi/core/utils/AudioFileWriter.h +++ b/packages/react-native-audio-api/common/cpp/audioapi/core/utils/AudioFileWriter.h @@ -1,5 +1,6 @@ #pragma once +#include #include #include #include @@ -12,11 +13,13 @@ namespace audioapi { class AudioFileProperties; class AudioEventHandlerRegistry; -typedef Result OpenFileResult; -typedef Result, std::string> CloseFileResult; +using OpenFileResult = Result; +using CloseFileResult = Result, std::string>; class AudioFileWriter { public: + DELETE_COPY_AND_MOVE(AudioFileWriter); + AudioFileWriter( const std::shared_ptr &audioEventHandlerRegistry, const std::shared_ptr &fileProperties); 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 4a7bd2deb..c06833dc3 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 @@ -1,8 +1,8 @@ #pragma once #include +#include #include - #include #include #include @@ -26,9 +26,9 @@ concept HasCleanupMethod = requires(T t) { class AudioGraphManager { public: - enum class ConnectionType { CONNECT, DISCONNECT, DISCONNECT_ALL, ADD }; - typedef ConnectionType EventType; // for backwards compatibility - enum class EventPayloadType { NODES, PARAMS, SOURCE_NODE, AUDIO_PARAM, NODE }; + enum class ConnectionType : uint8_t { CONNECT, DISCONNECT, DISCONNECT_ALL, ADD }; + using EventType = ConnectionType; // for backwards compatibility + enum class EventPayloadType : uint8_t { NODES, PARAMS, SOURCE_NODE, AUDIO_PARAM, NODE }; union EventPayload { struct { std::shared_ptr from; @@ -49,17 +49,18 @@ class AudioGraphManager { ~EventPayload() {} }; struct Event { - EventType type; - EventPayloadType payloadType; + EventType type = ConnectionType::CONNECT; + EventPayloadType payloadType = EventPayloadType::NODES; EventPayload payload; Event(Event &&other) noexcept; Event &operator=(Event &&other) noexcept; - Event() : type(ConnectionType::CONNECT), payloadType(EventPayloadType::NODES), payload() {} + Event() = default; ~Event(); }; AudioGraphManager(); + DELETE_COPY_AND_MOVE(AudioGraphManager); ~AudioGraphManager(); void preProcessGraph(); @@ -127,19 +128,19 @@ class AudioGraphManager { channels::spsc::Sender sender_; void settlePendingConnections(); - void handleConnectEvent(std::unique_ptr event); - void handleDisconnectEvent(std::unique_ptr event); - void handleDisconnectAllEvent(std::unique_ptr event); + static void handleConnectEvent(std::unique_ptr event); + static void handleDisconnectEvent(std::unique_ptr event); + static void handleDisconnectAllEvent(std::unique_ptr event); void handleAddToDeconstructionEvent(std::unique_ptr event); template - inline static bool canBeDestructed(const std::shared_ptr &object) { + static bool canBeDestructed(const std::shared_ptr &object) { return object.use_count() == 1; } template requires std::derived_from - inline static bool canBeDestructed(std::shared_ptr const &node) { + static bool canBeDestructed(std::shared_ptr const &node) { // If the node is an AudioScheduledSourceNode, we need to check if it is // playing if constexpr (std::is_base_of_v) { diff --git a/packages/react-native-audio-api/common/cpp/audioapi/core/utils/AudioParamEventQueue.cpp b/packages/react-native-audio-api/common/cpp/audioapi/core/utils/AudioParamEventQueue.cpp index 7270a5a9c..a42c6c1f4 100644 --- a/packages/react-native-audio-api/common/cpp/audioapi/core/utils/AudioParamEventQueue.cpp +++ b/packages/react-native-audio-api/common/cpp/audioapi/core/utils/AudioParamEventQueue.cpp @@ -4,7 +4,7 @@ namespace audioapi { -AudioParamEventQueue::AudioParamEventQueue() : eventQueue_() {} +AudioParamEventQueue::AudioParamEventQueue() = default; void AudioParamEventQueue::pushBack(ParamChangeEvent &&event) { if (eventQueue_.isEmpty()) { @@ -33,7 +33,7 @@ bool AudioParamEventQueue::popFront(ParamChangeEvent &event) { void AudioParamEventQueue::cancelScheduledValues(double cancelTime) { while (!eventQueue_.isEmpty()) { - auto &back = eventQueue_.peekBack(); + const auto &back = eventQueue_.peekBack(); if (back.getEndTime() < cancelTime) { break; } @@ -46,7 +46,7 @@ void AudioParamEventQueue::cancelScheduledValues(double cancelTime) { void AudioParamEventQueue::cancelAndHoldAtTime(double cancelTime, double &endTimeCache) { while (!eventQueue_.isEmpty()) { - auto &back = eventQueue_.peekBack(); + const auto &back = eventQueue_.peekBack(); if (back.getEndTime() < cancelTime || back.getStartTime() <= cancelTime) { break; } 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 37abe6ef8..1dd95c570 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 @@ -32,25 +32,25 @@ class AudioParamEventQueue { /// @brief Get the first event in the queue. /// @return The first event in the queue. - inline const ParamChangeEvent &front() const noexcept { + [[nodiscard]] const ParamChangeEvent &front() const noexcept { return eventQueue_.peekFront(); } /// @brief Get the last event in the queue. /// @return The last event in the queue. - inline const ParamChangeEvent &back() const noexcept { + [[nodiscard]] const ParamChangeEvent &back() const noexcept { return eventQueue_.peekBack(); } /// @brief Check if the event queue is empty. /// @return True if the queue is empty, false otherwise. - inline bool isEmpty() const noexcept { + [[nodiscard]] bool isEmpty() const noexcept { return eventQueue_.isEmpty(); } /// @brief Check if the event queue is full. /// @return True if the queue is full, false otherwise. - inline bool isFull() const noexcept { + [[nodiscard]] bool isFull() const noexcept { return eventQueue_.isFull(); } 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 08f3e1c11..6d37a056d 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 @@ -32,7 +32,7 @@ AudioRecorderCallback::AudioRecorderCallback( channelCount_(channelCount), callbackId_(callbackId), audioEventHandlerRegistry_(audioEventHandlerRegistry) { - ringBufferSize_ = std::max(bufferLength * 2, static_cast(8192)); + ringBufferSize_ = std::max(bufferLength * 2, static_cast(DEFAULT_RING_BUFFER_SIZE)); circularBuffer_.resize(channelCount_); for (size_t i = 0; i < channelCount_; ++i) { 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 18f36dc26..42966c89a 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 @@ -52,6 +52,7 @@ class AudioRecorderCallback { std::shared_ptr audioEventHandlerRegistry_; // TODO: CircularAudioBuffer + static constexpr size_t DEFAULT_RING_BUFFER_SIZE = 8192; std::vector> circularBuffer_; static constexpr auto RECORDER_CALLBACK_SPSC_OVERFLOW_STRATEGY = channels::spsc::OverflowStrategy::OVERWRITE_ON_FULL; diff --git a/packages/react-native-audio-api/common/cpp/audioapi/core/utils/Constants.h b/packages/react-native-audio-api/common/cpp/audioapi/core/utils/Constants.h index 59d8b8627..4327f5938 100644 --- a/packages/react-native-audio-api/common/cpp/audioapi/core/utils/Constants.h +++ b/packages/react-native-audio-api/common/cpp/audioapi/core/utils/Constants.h @@ -15,6 +15,7 @@ static constexpr int MAX_CHANNEL_COUNT = 32; static constexpr float DEFAULT_SAMPLE_RATE = 44100.0f; static constexpr int OCTAVE_RANGE = 1200; static constexpr int BIQUAD_GAIN_DB_FACTOR = 40; +static constexpr int SEMITONES_PER_OCTAVE = 12; // stretcher static constexpr float UPPER_FREQUENCY_LIMIT_DETECTION = 333.0f; diff --git a/packages/react-native-audio-api/common/cpp/audioapi/core/utils/Locker.h b/packages/react-native-audio-api/common/cpp/audioapi/core/utils/Locker.h index 36fa77807..34c292635 100644 --- a/packages/react-native-audio-api/common/cpp/audioapi/core/utils/Locker.h +++ b/packages/react-native-audio-api/common/cpp/audioapi/core/utils/Locker.h @@ -16,18 +16,33 @@ class Locker { unlock(); } + Locker(const Locker &) = delete; + Locker &operator=(const Locker &) = delete; + + Locker(Locker &&other) noexcept : lockPtr_(other.lockPtr_) { + other.lockPtr_ = nullptr; + } + Locker &operator=(Locker &&other) noexcept { + if (this != &other) { + unlock(); + lockPtr_ = other.lockPtr_; + other.lockPtr_ = nullptr; + } + return *this; + } + explicit operator bool() const { return lockPtr_ != nullptr; } void lock() { - if (lockPtr_) { + if (lockPtr_ != nullptr) { lockPtr_->lock(); } } void unlock() { - if (lockPtr_) { + if (lockPtr_ != nullptr) { lockPtr_->unlock(); } } diff --git a/packages/react-native-audio-api/common/cpp/audioapi/core/utils/ParamChangeEvent.hpp b/packages/react-native-audio-api/common/cpp/audioapi/core/utils/ParamChangeEvent.hpp index 22b35a647..fb95e024c 100644 --- a/packages/react-native-audio-api/common/cpp/audioapi/core/utils/ParamChangeEvent.hpp +++ b/packages/react-native-audio-api/common/cpp/audioapi/core/utils/ParamChangeEvent.hpp @@ -47,33 +47,33 @@ class ParamChangeEvent { return *this; } - [[nodiscard]] inline double getEndTime() const noexcept { + [[nodiscard]] double getEndTime() const noexcept { return endTime_; } - [[nodiscard]] inline double getStartTime() const noexcept { + [[nodiscard]] double getStartTime() const noexcept { return startTime_; } - [[nodiscard]] inline float getEndValue() const noexcept { + [[nodiscard]] float getEndValue() const noexcept { return endValue_; } - [[nodiscard]] inline float getStartValue() const noexcept { + [[nodiscard]] float getStartValue() const noexcept { return startValue_; } - [[nodiscard]] inline const std::function & + [[nodiscard]] const std::function & getCalculateValue() const noexcept { return calculateValue_; } - [[nodiscard]] inline ParamChangeEventType getType() const noexcept { + [[nodiscard]] ParamChangeEventType getType() const noexcept { return type_; } - inline void setEndTime(double endTime) noexcept { + void setEndTime(double endTime) noexcept { endTime_ = endTime; } - inline void setStartValue(float startValue) noexcept { + void setStartValue(float startValue) noexcept { startValue_ = startValue; } - inline void setEndValue(float endValue) noexcept { + void setEndValue(float endValue) noexcept { endValue_ = endValue; } @@ -83,7 +83,7 @@ class ParamChangeEvent { std::function calculateValue_; float startValue_ = 0.0f; float endValue_ = 0.0f; - ParamChangeEventType type_; + ParamChangeEventType type_ = ParamChangeEventType::SET_VALUE; }; } // namespace audioapi 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 30a98aee9..af2b27e12 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 @@ -35,6 +35,7 @@ namespace audioapi::dsp { [[nodiscard]] inline float decibelsToLinear(float value) { constexpr float kDecibelsDenominator = 20.0f; + // NOLINTNEXTLINE(cppcoreguidelines-avoid-magic-numbers, readability-magic-numbers) return static_cast(pow(10, value / kDecibelsDenominator)); } 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 36eb46919..210950dd6 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 @@ -20,10 +20,7 @@ Convolver::Convolver() _segSize(0), _segCount(0), _fftComplexSize(0), - _segments(), - _segmentsIR(), _fft(nullptr), - _preMultiplied(), _current(0) {} void Convolver::reset() { @@ -185,8 +182,7 @@ void Convolver::process(const AudioArray &input, AudioArray &output) { // The P sub filter spectra are pairwisely multiplied with the input spectra // in the FDL. The results are accumulated in the frequency-domain. memset(_preMultiplied.data(), 0, _preMultiplied.size() * sizeof(std::complex)); - // this is a bottleneck of the algorithm - for (int i = 0; i < _segCount; ++i) { + for (size_t i = 0; i < _segCount; ++i) { const int indexAudio = (_current + i) % _segCount; const auto &impulseResponseSegment = _segmentsIR[i]; const auto &audioSegment = _segments[indexAudio]; 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 8d7b966cb..37ca887ed 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 @@ -21,7 +21,7 @@ class Convolver { bool init(size_t blockSize, const AudioArray &ir, size_t irLen); void process(const AudioArray &input, AudioArray &output); void reset(); - [[nodiscard]] inline size_t getSegCount() const { + [[nodiscard]] size_t getSegCount() const { return _trueSegmentCount; } diff --git a/packages/react-native-audio-api/common/cpp/audioapi/dsp/FFT.cpp b/packages/react-native-audio-api/common/cpp/audioapi/dsp/FFT.cpp index 00a11fbdf..ace99db0f 100644 --- a/packages/react-native-audio-api/common/cpp/audioapi/dsp/FFT.cpp +++ b/packages/react-native-audio-api/common/cpp/audioapi/dsp/FFT.cpp @@ -2,14 +2,9 @@ namespace audioapi::dsp { -FFT::FFT(int size) : size_(size) { - pffftSetup_ = pffft_new_setup(size_, PFFFT_REAL); - work_ = reinterpret_cast(pffft_aligned_malloc(size_ * sizeof(float))); -} - -FFT::~FFT() { - pffft_destroy_setup(pffftSetup_); - pffft_aligned_free(work_); -} +FFT::FFT(int size) + : size_(size), + pffftSetup_(pffft_new_setup(size_, PFFFT_REAL)), + work_(reinterpret_cast(pffft_aligned_malloc(size_ * sizeof(float)))) {} } // namespace audioapi::dsp 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 c8d432a78..28f23f6a6 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 @@ -41,7 +41,7 @@ namespace audioapi::dsp { -#if defined(HAVE_ACCELERATE) +#ifdef HAVE_ACCELERATE void multiplyByScalar( const float *inputVector, @@ -125,7 +125,7 @@ void interleaveStereo( #else -#if defined(HAVE_X86_SSE2) +#ifdef HAVE_X86_SSE2 static inline bool is16ByteAligned(const float *vector) { return !(reinterpret_cast(vector) & 0x0F); } @@ -205,7 +205,7 @@ void addScalar( size_t numberOfElementsToProcess) { size_t n = numberOfElementsToProcess; -#if defined(HAVE_X86_SSE2) +#ifdef HAVE_X86_SSE2 // If the inputVector address is not 16-byte aligned, the first several frames // (at most three) should be processed separately. while (!is16ByteAligned(inputVector) && n) { @@ -273,7 +273,7 @@ void add( size_t numberOfElementsToProcess) { size_t n = numberOfElementsToProcess; -#if defined(HAVE_X86_SSE2) +#ifdef HAVE_X86_SSE2 // If the inputVector address is not 16-byte aligned, the first several frames // (at most three) should be processed separately. while (!is16ByteAligned(inputVector1) && n) { @@ -378,7 +378,7 @@ void subtract( size_t numberOfElementsToProcess) { size_t n = numberOfElementsToProcess; -#if defined(HAVE_X86_SSE2) +#ifdef HAVE_X86_SSE2 // If the inputVector address is not 16-byte aligned, the first several frames // (at most three) should be processed separately. while (!is16ByteAligned(inputVector1) && n) { @@ -481,7 +481,7 @@ void multiply( size_t numberOfElementsToProcess) { size_t n = numberOfElementsToProcess; -#if defined(HAVE_X86_SSE2) +#ifdef HAVE_X86_SSE2 // If the inputVector1 address is not 16-byte aligned, the first several // frames (at most three) should be processed separately. while (!is16ByteAligned(inputVector1) && n) { @@ -550,7 +550,7 @@ float maximumMagnitude(const float *inputVector, size_t numberOfElementsToProces size_t n = numberOfElementsToProcess; float max = 0; -#if defined(HAVE_X86_SSE2) +#ifdef HAVE_X86_SSE2 // If the inputVector address is not 16-byte aligned, the first several frames // (at most three) should be processed separately. while (!is16ByteAligned(inputVector) && n) { @@ -717,7 +717,7 @@ void deinterleaveStereo( size_t n = numberOfFrames; -#if defined(HAVE_ARM_NEON_INTRINSICS) +#ifdef HAVE_ARM_NEON_INTRINSICS // process 4 frames (8 samples) at a time using NEON size_t group = n / 4; while (group--) { 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 d48923b86..c3600db55 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 @@ -50,8 +50,6 @@ void WaveShaper::process(AudioArray &channelData, int framesToProcess) { switch (oversample_) { case OverSampleType::OVERSAMPLE_2X: - processResampled(channelData, framesToProcess); - break; case OverSampleType::OVERSAMPLE_4X: processResampled(channelData, framesToProcess); break; diff --git a/packages/react-native-audio-api/common/cpp/audioapi/dsp/r8brain/Resampler.cpp b/packages/react-native-audio-api/common/cpp/audioapi/dsp/r8brain/Resampler.cpp index 5dfb7609e..d3a66cf78 100644 --- a/packages/react-native-audio-api/common/cpp/audioapi/dsp/r8brain/Resampler.cpp +++ b/packages/react-native-audio-api/common/cpp/audioapi/dsp/r8brain/Resampler.cpp @@ -11,7 +11,7 @@ BaseResampler::BaseResampler(double srcRate, double dstRate, int numChannels, in } } -int BaseResampler::process(const std::vector &input, int l, std::vector &output) { +int BaseResampler::process(std::vector &input, int l, std::vector &output) { int outLen = 0; const size_t numChannels = resamplers_.size(); @@ -55,7 +55,7 @@ MultiChannelResampler::MultiChannelResampler( : BaseResampler(srcRate, dstRate, numChannels, maxInLen) {} int MultiChannelResampler::process( - const audioapi::AudioBuffer &input, + audioapi::AudioBuffer &input, int l, audioapi::AudioBuffer &output) { const size_t numChannels = input.getNumberOfChannels(); @@ -72,12 +72,12 @@ SingleChannelResampler::SingleChannelResampler(double srcRate, double dstRate, i : BaseResampler(srcRate, dstRate, 1, maxInLen) {} int SingleChannelResampler::process( - const audioapi::AudioArray &input, + audioapi::AudioArray &input, int l, audioapi::AudioArray &output) { std::vector inputPtrs(1); std::vector outputPtrs(1); - inputPtrs[0] = const_cast(input.begin()); + inputPtrs[0] = input.begin(); outputPtrs[0] = output.begin(); return BaseResampler::process(inputPtrs, l, outputPtrs); } diff --git a/packages/react-native-audio-api/common/cpp/audioapi/dsp/r8brain/Resampler.h b/packages/react-native-audio-api/common/cpp/audioapi/dsp/r8brain/Resampler.h index 5da979247..afc749f84 100644 --- a/packages/react-native-audio-api/common/cpp/audioapi/dsp/r8brain/Resampler.h +++ b/packages/react-native-audio-api/common/cpp/audioapi/dsp/r8brain/Resampler.h @@ -1,5 +1,6 @@ #pragma once +#include #include #include #include @@ -20,10 +21,11 @@ class BaseResampler { private: std::vector> resamplers_; std::vector> inputBuffers_; + static constexpr int DEFAULT_MAX_IN_LEN = 2048; protected: - BaseResampler(double srcRate, double dstRate, int numChannels, int maxInLen = 2048); - int process(const std::vector &input, int length, std::vector &output); + BaseResampler(double srcRate, double dstRate, int numChannels, int maxInLen = DEFAULT_MAX_IN_LEN); + int process(std::vector &input, int length, std::vector &output); public: virtual ~BaseResampler() = default; @@ -33,15 +35,17 @@ class BaseResampler { class MultiChannelResampler : public BaseResampler { public: - MultiChannelResampler(double srcRate, double dstRate, int numChannels, int maxInLen = 2048); + MultiChannelResampler(double srcRate, double dstRate, int numChannels, int maxInLen); ~MultiChannelResampler() = default; - int process(const audioapi::AudioBuffer &input, int length, audioapi::AudioBuffer &output); + DELETE_COPY_AND_MOVE(MultiChannelResampler); + int process(audioapi::AudioBuffer &input, int length, audioapi::AudioBuffer &output); }; class SingleChannelResampler : public BaseResampler { public: - SingleChannelResampler(double srcRate, double dstRate, int maxInLen = 2048); + SingleChannelResampler(double srcRate, double dstRate, int maxInLen); ~SingleChannelResampler() = default; - int process(const audioapi::AudioArray &input, int length, audioapi::AudioArray &output); + DELETE_COPY_AND_MOVE(SingleChannelResampler); + int process(audioapi::AudioArray &input, int length, audioapi::AudioArray &output); }; } // namespace r8b diff --git a/packages/react-native-audio-api/common/cpp/audioapi/events/AudioEvent.h b/packages/react-native-audio-api/common/cpp/audioapi/events/AudioEvent.h index 1b6339b93..2f669d76a 100644 --- a/packages/react-native-audio-api/common/cpp/audioapi/events/AudioEvent.h +++ b/packages/react-native-audio-api/common/cpp/audioapi/events/AudioEvent.h @@ -1,8 +1,10 @@ #pragma once +#include + namespace audioapi { -enum class AudioEvent { +enum class AudioEvent : uint8_t { PLAYBACK_NOTIFICATION_PLAY, PLAYBACK_NOTIFICATION_PAUSE, PLAYBACK_NOTIFICATION_STOP, diff --git a/packages/react-native-audio-api/common/cpp/audioapi/events/AudioEventHandlerRegistry.cpp b/packages/react-native-audio-api/common/cpp/audioapi/events/AudioEventHandlerRegistry.cpp index e1a055f00..5b1f27a1c 100644 --- a/packages/react-native-audio-api/common/cpp/audioapi/events/AudioEventHandlerRegistry.cpp +++ b/packages/react-native-audio-api/common/cpp/audioapi/events/AudioEventHandlerRegistry.cpp @@ -193,7 +193,7 @@ jsi::Object AudioEventHandlerRegistry::createEventObject( auto eventObject = jsi::Object(*runtime_); for (const auto &pair : body) { - const auto name = pair.first.data(); + const auto *name = pair.first.data(); const auto &value = pair.second; if (std::holds_alternative(value)) { 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 a1fabff8d..f044aaada 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 @@ -9,9 +9,11 @@ #include #include +//NOLINTBEGIN(cppcoreguidelines-avoid-magic-numbers, readability-magic-numbers) + namespace audioapi { -const float SQRT_HALF = sqrtf(0.5f); +const float SQRT_HALF = sqrtf(0.5f); //NOLINT(bugprone-throwing-static-initialization) constexpr int BLOCK_SIZE = 64; AudioBuffer::AudioBuffer(size_t size, int numberOfChannels, float sampleRate) @@ -192,7 +194,7 @@ void AudioBuffer::deinterleaveFrom(const float *source, size_t frames) { return; } - float *channelsPtrs[MAX_CHANNEL_COUNT]; + std::array channelsPtrs{}; for (size_t i = 0; i < numberOfChannels_; ++i) { channelsPtrs[i] = channels_[i]->begin(); } @@ -223,7 +225,7 @@ void AudioBuffer::interleaveTo(float *destination, size_t frames) const { return; } - float *channelsPtrs[MAX_CHANNEL_COUNT]; + std::array channelsPtrs{}; for (size_t i = 0; i < numberOfChannels_; ++i) { channelsPtrs[i] = channels_[i]->begin(); } @@ -379,3 +381,5 @@ void AudioBuffer::sumByDownMixing( } } // namespace audioapi + +//NOLINTEND(cppcoreguidelines-avoid-magic-numbers, readability-magic-numbers) 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 f9b27f046..12a7c94e9 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 @@ -15,7 +15,8 @@ class AudioArrayBuffer; class AudioBuffer { public: - enum { + //NOLINTNEXTLINE(cppcoreguidelines-use-enum-class) + enum : uint8_t { ChannelMono = 0, ChannelLeft = 0, ChannelRight = 1, @@ -147,6 +148,7 @@ class AudioBuffer { float sampleRate_ = 0.0f; size_t size_ = 0; + //NOLINTNEXTLINE(bugprone-throwing-static-initialization) inline static const std::unordered_map> kChannelLayouts = { {1, {ChannelMono}}, {2, {ChannelLeft, ChannelRight}}, diff --git a/packages/react-native-audio-api/common/cpp/audioapi/utils/Result.hpp b/packages/react-native-audio-api/common/cpp/audioapi/utils/Result.hpp index 2986fc981..fe3de6d2e 100644 --- a/packages/react-native-audio-api/common/cpp/audioapi/utils/Result.hpp +++ b/packages/react-native-audio-api/common/cpp/audioapi/utils/Result.hpp @@ -50,10 +50,10 @@ class Result { struct OkTag {}; struct ErrTag {}; - explicit Result(OkTag, const T &value) : ok_value(value), is_ok_(true) {} - explicit Result(OkTag, T &&value) : ok_value(std::move(value)), is_ok_(true) {} - explicit Result(ErrTag, const E &error) : err_value(error), is_ok_(false) {} - explicit Result(ErrTag, E &&error) : err_value(std::move(error)), is_ok_(false) {} + explicit Result(OkTag okTag, const T &value) : ok_value(value), is_ok_(true) {} + explicit Result(OkTag okTag, T &&value) : ok_value(std::move(value)), is_ok_(true) {} + explicit Result(ErrTag errTag, const E &error) : err_value(error), is_ok_(false) {} + explicit Result(ErrTag errTag, E &&error) : err_value(std::move(error)), is_ok_(false) {} public: template @@ -66,8 +66,7 @@ class Result { new (&err_value) E(std::move(err.value)); } - Result(const Result &other) { - is_ok_ = other.is_ok_; + Result(const Result &other) : is_ok_(other.is_ok_) { if (is_ok_) { new (&ok_value) T(other.ok_value); } else { @@ -76,8 +75,8 @@ class Result { } Result(Result &&other) noexcept( - std::is_nothrow_move_constructible_v && std::is_nothrow_move_constructible_v) { - is_ok_ = other.is_ok_; + std::is_nothrow_move_constructible_v && std::is_nothrow_move_constructible_v) + : is_ok_(other.is_ok_) { if (is_ok_) { new (&ok_value) T(std::move(other.ok_value)); } else { @@ -86,13 +85,15 @@ class Result { } Result &operator=(const Result &other) { - if (this == &other) + if (this == &other) { return *this; + } if (is_ok_ == other.is_ok_) { - if (is_ok_) + if (is_ok_) { ok_value = other.ok_value; - else + } else { err_value = other.err_value; + } } else { if (is_ok_) { ok_value.~T(); @@ -110,13 +111,15 @@ class Result { Result &operator=(Result &&other) noexcept( std::is_nothrow_move_assignable_v && std::is_nothrow_move_assignable_v && std::is_nothrow_move_constructible_v && std::is_nothrow_move_constructible_v) { - if (this == &other) + if (this == &other) { return *this; + } if (is_ok_ == other.is_ok_) { - if (is_ok_) + if (is_ok_) { ok_value = std::move(other.ok_value); - else + } else { err_value = std::move(other.err_value); + } } else { if (is_ok_) { ok_value.~T(); @@ -284,9 +287,8 @@ class Result { using ResultType = Result; if (is_ok_) { return ResultType::Ok(ok_func(std::move(ok_value))); - } else { - return ResultType::Err(std::move(err_value)); } + return ResultType::Err(std::move(err_value)); } /// @brief Maps a Result to Result by applying a function to a contained Err value. @@ -296,9 +298,8 @@ class Result { using ResultType = Result; if (is_ok_) { return ResultType::Ok(std::move(ok_value)); - } else { - return ResultType::Err(err_func(std::move(err_value))); } + return ResultType::Err(err_func(std::move(err_value))); } /// @brief Returns the provided default (if Err), or applies a function to the contained value (if Ok). @@ -306,9 +307,8 @@ class Result { [[nodiscard]] auto map_or(F &&ok_func, U &&default_value) && { if (is_ok_) { return ok_func(std::move(ok_value)); - } else { - return std::forward(default_value); } + return std::forward(default_value); } /// @brief Maps a Result to U by applying fallback function default to a contained Err value, or function f to a contained Ok value. @@ -316,9 +316,8 @@ class Result { [[nodiscard]] auto map_or_else(FT &&ok_func, FE &&err_func) && { if (is_ok_) { return ok_func(std::move(ok_value)); - } else { - return err_func(std::move(err_value)); } + return err_func(std::move(err_value)); } /// @brief Calls the provided closure with the contained Ok value, if any, otherwise returns the Err value of self. @@ -328,9 +327,8 @@ class Result { using ResultType = std::invoke_result_t; if (is_ok_) { return ok_func(std::move(ok_value)); - } else { - return ResultType::Err(std::move(err_value)); } + return ResultType::Err(std::move(err_value)); } /// @brief Calls the provided closure with the contained Err value, if any, otherwise returns the Ok value of self. @@ -340,9 +338,8 @@ class Result { using ResultType = std::invoke_result_t; if (is_ok_) { return ResultType::Ok(std::move(ok_value)); - } else { - return err_func(std::move(err_value)); } + return err_func(std::move(err_value)); } private: diff --git a/packages/react-native-audio-api/common/cpp/audioapi/utils/RingBiDirectionalBuffer.hpp b/packages/react-native-audio-api/common/cpp/audioapi/utils/RingBiDirectionalBuffer.hpp index 40fd4322b..51c3f5c1a 100644 --- a/packages/react-native-audio-api/common/cpp/audioapi/utils/RingBiDirectionalBuffer.hpp +++ b/packages/react-native-audio-api/common/cpp/audioapi/utils/RingBiDirectionalBuffer.hpp @@ -1,5 +1,6 @@ #pragma once +#include #include #include #include @@ -17,10 +18,12 @@ template class RingBiDirectionalBuffer { public: /// @brief Constructor for RingBuffer. - RingBiDirectionalBuffer() : headIndex_(0), tailIndex_(0) { + RingBiDirectionalBuffer() + : buffer_( + static_cast(::operator new[]( + capacity_ * sizeof(T), + static_cast(alignof(T))))) { static_assert(isPowerOfTwo(capacity_), "RingBiDirectionalBuffer's capacity must be power of 2"); - buffer_ = static_cast( - ::operator new[](capacity_ * sizeof(T), static_cast(alignof(T)))); } /// @brief Destructor for RingBuffer. @@ -31,6 +34,8 @@ class RingBiDirectionalBuffer { ::operator delete[](buffer_, capacity_ * sizeof(T), static_cast(alignof(T))); } + DELETE_COPY_AND_MOVE(RingBiDirectionalBuffer); + /// @brief Push a value into the ring buffer. /// @tparam U The type of the value to push. /// @param value The value to push. @@ -111,74 +116,74 @@ class RingBiDirectionalBuffer { /// @brief Peek at the front of the buffer. /// @return A const reference to the front element of the buffer. - const inline T &peekFront() const noexcept { + [[nodiscard]] const T &peekFront() const noexcept { return buffer_[headIndex_]; } /// @brief Peek at the back of the buffer. /// @return A const reference to the back element of the buffer. - const inline T &peekBack() const noexcept { + [[nodiscard]] const T &peekBack() const noexcept { return buffer_[prevIndex(tailIndex_)]; } /// @brief Peek at the front of the buffer. /// @return A mutable reference to the front element of the buffer. - inline T &peekFrontMut() noexcept { + [[nodiscard]] T &peekFrontMut() noexcept { return buffer_[headIndex_]; } /// @brief Peek at the back of the buffer. /// @return A mutable reference to the back element of the buffer. - inline T &peekBackMut() noexcept { + [[nodiscard]] T &peekBackMut() noexcept { return buffer_[prevIndex(tailIndex_)]; } /// @brief Check if the buffer is empty. /// @return True if the buffer is empty, false otherwise. - inline bool isEmpty() const noexcept { + [[nodiscard]] bool isEmpty() const noexcept { return headIndex_ == tailIndex_; } /// @brief Check if the buffer is full. /// @return True if the buffer is full, false otherwise. - inline bool isFull() const noexcept { + [[nodiscard]] bool isFull() const noexcept { return nextIndex(tailIndex_) == headIndex_; } /// @brief Get the capacity of the buffer. /// @return The capacity of the buffer. - inline size_t getCapacity() const noexcept { + [[nodiscard]] size_t getCapacity() const noexcept { return capacity_; } /// @brief Get the real capacity of the buffer (excluding one slot for the empty state). /// @return The real capacity of the buffer. - inline size_t getRealCapacity() const noexcept { + [[nodiscard]] size_t getRealCapacity() const noexcept { return capacity_ - 1; } /// @brief Get the number of elements in the buffer. /// @return The number of elements in the buffer. - inline size_t size() const noexcept { + [[nodiscard]] size_t size() const noexcept { return (capacity_ + tailIndex_ - headIndex_) & (capacity_ - 1); } private: T *buffer_; - size_t headIndex_; - size_t tailIndex_; + size_t headIndex_ = 0; + size_t tailIndex_ = 0; /// @brief Get the next index in the buffer. /// @param n The current index. /// @return The next index in the buffer. - inline size_t nextIndex(const size_t n) const noexcept { + [[nodiscard]] size_t nextIndex(const size_t n) const noexcept { return (n + 1) & (capacity_ - 1); } /// @brief Get the previous index in the buffer. /// @param n The current index. /// @return The previous index in the buffer. - inline size_t prevIndex(const size_t n) const noexcept { + [[nodiscard]] size_t prevIndex(const size_t n) const noexcept { return (n - 1) & (capacity_ - 1); } diff --git a/packages/react-native-audio-api/common/cpp/test/src/core/AudioParamTest.cpp b/packages/react-native-audio-api/common/cpp/test/src/core/AudioParamTest.cpp index 47b36bd5f..758140a6a 100644 --- a/packages/react-native-audio-api/common/cpp/test/src/core/AudioParamTest.cpp +++ b/packages/react-native-audio-api/common/cpp/test/src/core/AudioParamTest.cpp @@ -7,6 +7,8 @@ using namespace audioapi; +// NOLINTBEGIN + class AudioParamTest : public ::testing::Test { protected: std::shared_ptr eventRegistry; @@ -209,3 +211,5 @@ TEST_F(AudioParamTest, CancelAndHoldAtTime) { value = param.processKRateParam(1, 0.25); EXPECT_FLOAT_EQ(value, 0.9); } + +// NOLINTEND diff --git a/packages/react-native-audio-api/common/cpp/test/src/core/effects/DelayTest.cpp b/packages/react-native-audio-api/common/cpp/test/src/core/effects/DelayTest.cpp index d3ca4a3e4..40c2f7f2d 100644 --- a/packages/react-native-audio-api/common/cpp/test/src/core/effects/DelayTest.cpp +++ b/packages/react-native-audio-api/common/cpp/test/src/core/effects/DelayTest.cpp @@ -10,6 +10,8 @@ using namespace audioapi; +// NOLINTBEGIN + class DelayTest : public ::testing::Test { protected: std::shared_ptr eventRegistry; @@ -115,3 +117,5 @@ TEST_F(DelayTest, DelayHandlesTailCorrectly) { } } } + +// NOLINTEND diff --git a/packages/react-native-audio-api/common/cpp/test/src/core/effects/GainTest.cpp b/packages/react-native-audio-api/common/cpp/test/src/core/effects/GainTest.cpp index 501daf655..92cd54d3b 100644 --- a/packages/react-native-audio-api/common/cpp/test/src/core/effects/GainTest.cpp +++ b/packages/react-native-audio-api/common/cpp/test/src/core/effects/GainTest.cpp @@ -10,6 +10,8 @@ using namespace audioapi; +// NOLINTBEGIN + class GainTest : public ::testing::Test { protected: std::shared_ptr eventRegistry; @@ -80,3 +82,5 @@ TEST_F(GainTest, GainModulatesVolumeCorrectlyMultiChannel) { EXPECT_FLOAT_EQ((*resultBuffer->getChannel(1))[i], (-i - 1) * GAIN_VALUE); } } + +// NOLINTEND diff --git a/packages/react-native-audio-api/common/cpp/test/src/core/effects/IIRFilterTest.cpp b/packages/react-native-audio-api/common/cpp/test/src/core/effects/IIRFilterTest.cpp index e5212511c..91fb54ce0 100644 --- a/packages/react-native-audio-api/common/cpp/test/src/core/effects/IIRFilterTest.cpp +++ b/packages/react-native-audio-api/common/cpp/test/src/core/effects/IIRFilterTest.cpp @@ -11,6 +11,8 @@ using namespace audioapi; +// NOLINTBEGIN + class IIRFilterTest : public ::testing::Test { protected: std::shared_ptr eventRegistry; @@ -151,3 +153,5 @@ TEST_F(IIRFilterTest, GetFrequencyResponse) { } } } + +// NOLINTEND diff --git a/packages/react-native-audio-api/common/cpp/test/src/core/effects/StereoPannerTest.cpp b/packages/react-native-audio-api/common/cpp/test/src/core/effects/StereoPannerTest.cpp index 123a9adb8..1ef390e26 100644 --- a/packages/react-native-audio-api/common/cpp/test/src/core/effects/StereoPannerTest.cpp +++ b/packages/react-native-audio-api/common/cpp/test/src/core/effects/StereoPannerTest.cpp @@ -10,6 +10,8 @@ using namespace audioapi; +// NOLINTBEGIN + class StereoPannerTest : public ::testing::Test { protected: std::shared_ptr eventRegistry; @@ -127,3 +129,5 @@ TEST_F(StereoPannerTest, PanModulatesInputStereoCorrectlyWithPositivePan) { 1e-4); } } + +// NOLINTEND 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 6faa6bfe4..685fdbff3 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 @@ -11,6 +11,8 @@ using namespace audioapi; +// NOLINTBEGIN + class WaveShaperNodeTest : public ::testing::Test { protected: std::shared_ptr eventRegistry; @@ -75,3 +77,5 @@ TEST_F(WaveShaperNodeTest, NoneOverSamplingProcessesCorrectly) { EXPECT_FLOAT_EQ(resultData[3], 1.0f); EXPECT_FLOAT_EQ(resultData[4], curveData[2]); } + +// NOLINTEND diff --git a/packages/react-native-audio-api/common/cpp/test/src/core/effects/biquad/BiquadFilterChromium.cpp b/packages/react-native-audio-api/common/cpp/test/src/core/effects/biquad/BiquadFilterChromium.cpp index 65301e454..5635a95c5 100644 --- a/packages/react-native-audio-api/common/cpp/test/src/core/effects/biquad/BiquadFilterChromium.cpp +++ b/packages/react-native-audio-api/common/cpp/test/src/core/effects/biquad/BiquadFilterChromium.cpp @@ -37,6 +37,8 @@ namespace audioapi { +// NOLINTBEGIN + // Compute 10^x = exp(x*log(10)) static double pow10(double x) { return std::exp(x * 2.30258509299404568402); @@ -369,4 +371,6 @@ BiquadCoefficients calculateBandpassCoefficients(double frequency, double q) { return normalizeCoefficients(0, 0, 0, 1, 0, 0); } } + +// NOLINTEND } // namespace audioapi diff --git a/packages/react-native-audio-api/common/cpp/test/src/core/effects/biquad/BiquadFilterTest.cpp b/packages/react-native-audio-api/common/cpp/test/src/core/effects/biquad/BiquadFilterTest.cpp index e4953169d..02ab5e7eb 100644 --- a/packages/react-native-audio-api/common/cpp/test/src/core/effects/biquad/BiquadFilterTest.cpp +++ b/packages/react-native-audio-api/common/cpp/test/src/core/effects/biquad/BiquadFilterTest.cpp @@ -6,6 +6,8 @@ namespace audioapi { +// NOLINTBEGIN + void BiquadFilterTest::expectCoefficientsNear( const BiquadFilterNode::FilterCoefficients &actual, const BiquadCoefficients &expected) { @@ -257,3 +259,5 @@ TEST_F(BiquadFilterTest, GetFrequencyResponse) { } } // namespace audioapi + +// NOLINTEND diff --git a/packages/react-native-audio-api/common/cpp/test/src/core/sources/AudioScheduledSourceTest.cpp b/packages/react-native-audio-api/common/cpp/test/src/core/sources/AudioScheduledSourceTest.cpp index ed0c9beb5..b5f3c3d13 100644 --- a/packages/react-native-audio-api/common/cpp/test/src/core/sources/AudioScheduledSourceTest.cpp +++ b/packages/react-native-audio-api/common/cpp/test/src/core/sources/AudioScheduledSourceTest.cpp @@ -8,6 +8,9 @@ #include using namespace audioapi; + +// NOLINTBEGIN + static constexpr int SAMPLE_RATE = 44100; static constexpr int RENDER_QUANTUM = 128; static constexpr double RENDER_QUANTUM_TIME = static_cast(RENDER_QUANTUM) / SAMPLE_RATE; @@ -128,3 +131,5 @@ TEST_F(AudioScheduledSourceTest, IsFinishedStateSetCorrectly) { sourceNode.playFrames(1); EXPECT_TRUE(sourceNode.isFinished()); } + +// NOLINTEND diff --git a/packages/react-native-audio-api/common/cpp/test/src/core/sources/ConstantSourceTest.cpp b/packages/react-native-audio-api/common/cpp/test/src/core/sources/ConstantSourceTest.cpp index 6136b4abe..273bb03a1 100644 --- a/packages/react-native-audio-api/common/cpp/test/src/core/sources/ConstantSourceTest.cpp +++ b/packages/react-native-audio-api/common/cpp/test/src/core/sources/ConstantSourceTest.cpp @@ -10,6 +10,8 @@ using namespace audioapi; +// NOLINTBEGIN + class ConstantSourceTest : public ::testing::Test { protected: std::shared_ptr eventRegistry; @@ -63,3 +65,5 @@ TEST_F(ConstantSourceTest, ConstantSourceOutputsConstantValue) { // EXPECT_FLOAT_EQ((*resultBuffer->getChannel(0))[i], 0.5f); // } } + +// NOLINTEND diff --git a/packages/react-native-audio-api/common/cpp/test/src/core/sources/OscillatorTest.cpp b/packages/react-native-audio-api/common/cpp/test/src/core/sources/OscillatorTest.cpp index fbe9c67ac..0bcd1fff4 100644 --- a/packages/react-native-audio-api/common/cpp/test/src/core/sources/OscillatorTest.cpp +++ b/packages/react-native-audio-api/common/cpp/test/src/core/sources/OscillatorTest.cpp @@ -8,6 +8,8 @@ using namespace audioapi; +// NOLINTBEGIN + class OscillatorTest : public ::testing::Test { protected: std::shared_ptr eventRegistry; @@ -25,3 +27,5 @@ TEST_F(OscillatorTest, OscillatorCanBeCreated) { auto osc = context->createOscillator(OscillatorOptions()); ASSERT_NE(osc, nullptr); } + +// NOLINTEND diff --git a/packages/react-native-audio-api/common/cpp/test/src/utils/AudioArrayTest.cpp b/packages/react-native-audio-api/common/cpp/test/src/utils/AudioArrayTest.cpp index e3e6072e7..58ef45399 100644 --- a/packages/react-native-audio-api/common/cpp/test/src/utils/AudioArrayTest.cpp +++ b/packages/react-native-audio-api/common/cpp/test/src/utils/AudioArrayTest.cpp @@ -9,6 +9,8 @@ using namespace audioapi; static constexpr size_t ARR_SIZE = 128; +// NOLINTBEGIN + class AudioArrayTest : public ::testing::Test { protected: static void fill(AudioArray &arr, float value) { @@ -611,3 +613,5 @@ TEST_F(AudioArrayTest, ComputeConvolutionThrowsOnOutOfRange) { AudioArray kernel(4); EXPECT_THROW(auto x = signal.computeConvolution(kernel, 2), std::out_of_range); } + +// NOLINTEND diff --git a/packages/react-native-audio-api/common/cpp/test/src/utils/AudioBufferTest.cpp b/packages/react-native-audio-api/common/cpp/test/src/utils/AudioBufferTest.cpp index 4ad399162..c291b49ca 100644 --- a/packages/react-native-audio-api/common/cpp/test/src/utils/AudioBufferTest.cpp +++ b/packages/react-native-audio-api/common/cpp/test/src/utils/AudioBufferTest.cpp @@ -7,6 +7,7 @@ using namespace audioapi; +// NOLINTBEGIN static const float SQRT_HALF = sqrtf(0.5f); static constexpr size_t BUF_SIZE = 10; static constexpr float SR = 44100.0f; @@ -632,3 +633,5 @@ TEST_F(AudioBufferTest, DeinterleaveZeroFramesIsNoop) { buf.deinterleaveFrom(dummy, 0); expectChannel(buf, 0, 42.0f); } + +// NOLINTEND diff --git a/packages/react-native-audio-api/common/cpp/test/src/utils/TripleBufferTest.cpp b/packages/react-native-audio-api/common/cpp/test/src/utils/TripleBufferTest.cpp index 339fad378..05dae5e59 100644 --- a/packages/react-native-audio-api/common/cpp/test/src/utils/TripleBufferTest.cpp +++ b/packages/react-native-audio-api/common/cpp/test/src/utils/TripleBufferTest.cpp @@ -12,6 +12,8 @@ struct IntVal { explicit IntVal(int v = 0) : value(v) {} }; +// NOLINTBEGIN + // --------------------------------------------------------------------------- // Functional Tests // --------------------------------------------------------------------------- @@ -265,3 +267,5 @@ TEST_F(TripleBufferTest, StressBothSidesMakeProgress) { EXPECT_GT(writeCount.load(), 1'000); EXPECT_GT(readCount.load(), 1'000); } + +// NOLINTEND From 97ca32088049d43de3db5e4570d627749b475744 Mon Sep 17 00:00:00 2001 From: michal Date: Mon, 16 Mar 2026 16:02:23 +0100 Subject: [PATCH 4/9] chore: renamed directory --- .../common/cpp/{cursor => clangd}/CMakeLists.txt | 0 .../react-native-audio-api/common/cpp/{cursor => clangd}/SETUP.md | 0 .../common/cpp/{cursor => clangd}/generate-and-copy.sh | 0 3 files changed, 0 insertions(+), 0 deletions(-) rename packages/react-native-audio-api/common/cpp/{cursor => clangd}/CMakeLists.txt (100%) rename packages/react-native-audio-api/common/cpp/{cursor => clangd}/SETUP.md (100%) rename packages/react-native-audio-api/common/cpp/{cursor => clangd}/generate-and-copy.sh (100%) diff --git a/packages/react-native-audio-api/common/cpp/cursor/CMakeLists.txt b/packages/react-native-audio-api/common/cpp/clangd/CMakeLists.txt similarity index 100% rename from packages/react-native-audio-api/common/cpp/cursor/CMakeLists.txt rename to packages/react-native-audio-api/common/cpp/clangd/CMakeLists.txt diff --git a/packages/react-native-audio-api/common/cpp/cursor/SETUP.md b/packages/react-native-audio-api/common/cpp/clangd/SETUP.md similarity index 100% rename from packages/react-native-audio-api/common/cpp/cursor/SETUP.md rename to packages/react-native-audio-api/common/cpp/clangd/SETUP.md diff --git a/packages/react-native-audio-api/common/cpp/cursor/generate-and-copy.sh b/packages/react-native-audio-api/common/cpp/clangd/generate-and-copy.sh similarity index 100% rename from packages/react-native-audio-api/common/cpp/cursor/generate-and-copy.sh rename to packages/react-native-audio-api/common/cpp/clangd/generate-and-copy.sh From bd3c1325c016f02452e6a21b8ecfc77cb09650d8 Mon Sep 17 00:00:00 2001 From: michal Date: Mon, 16 Mar 2026 17:51:36 +0100 Subject: [PATCH 5/9] fix: restore fft destructor --- .../react-native-audio-api/common/cpp/audioapi/dsp/FFT.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/packages/react-native-audio-api/common/cpp/audioapi/dsp/FFT.cpp b/packages/react-native-audio-api/common/cpp/audioapi/dsp/FFT.cpp index ace99db0f..cc0e4983d 100644 --- a/packages/react-native-audio-api/common/cpp/audioapi/dsp/FFT.cpp +++ b/packages/react-native-audio-api/common/cpp/audioapi/dsp/FFT.cpp @@ -7,4 +7,9 @@ FFT::FFT(int size) pffftSetup_(pffft_new_setup(size_, PFFFT_REAL)), work_(reinterpret_cast(pffft_aligned_malloc(size_ * sizeof(float)))) {} +FFT::~FFT() { + pffft_destroy_setup(pffftSetup_); + pffft_aligned_free(work_); +} + } // namespace audioapi::dsp From 4c67c09de92bcc4af946f84ab1748375008041bc Mon Sep 17 00:00:00 2001 From: michal Date: Mon, 16 Mar 2026 18:14:06 +0100 Subject: [PATCH 6/9] refactor: uppercase constant --- .../common/cpp/audioapi/core/analysis/AnalyserNode.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) 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 39e8ce965..51e732904 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 @@ -82,9 +82,9 @@ void AnalyserNode::getByteTimeDomainData(uint8_t *data, int length) { auto values = frame->timeDomain.span(); - constexpr float byteCenter = 128.0f; + constexpr float BYTE_CENTER = 128.0f; for (int i = 0; i < size; i++) { - float scaledValue = byteCenter * (values[i] + 1); + float scaledValue = BYTE_CENTER * (values[i] + 1); scaledValue = std::clamp(scaledValue, 0.0f, static_cast(UINT8_MAX)); data[i] = static_cast(scaledValue); From 4db768a9f351eb23f1e3ec984884eb8154f40a11 Mon Sep 17 00:00:00 2001 From: michal Date: Tue, 17 Mar 2026 10:34:17 +0100 Subject: [PATCH 7/9] fix: tests --- .../main/cpp/audioapi/android/core/AndroidAudioRecorder.cpp | 4 ++-- .../ios/audioapi/ios/core/IOSAudioRecorder.mm | 2 +- .../react-native-audio-api/scripts/check-audio-events-sync.sh | 2 +- 3 files changed, 4 insertions(+), 4 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 8765606ce..fe30265e7 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 @@ -51,7 +51,7 @@ AndroidAudioRecorder::~AndroidAudioRecorder() { if (isConnected()) { isConnected_.store(false, std::memory_order_release); - adapterNode_->cleanup(); + adapterNode_->adapterCleanup(); } } @@ -200,7 +200,7 @@ Result, std::string> AndroidAudioRecorde } if (isConnected()) { - adapterNode_->cleanup(); + adapterNode_->adapterCleanup(); } filePath_ = ""; 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 a680c15da..fde7470a7 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 @@ -170,7 +170,7 @@ } if (isConnected()) { - adapterNode_->cleanup(); + adapterNode_->adapterCleanup(); } filePath_ = ""; diff --git a/packages/react-native-audio-api/scripts/check-audio-events-sync.sh b/packages/react-native-audio-api/scripts/check-audio-events-sync.sh index e351dace0..0d49f8e58 100755 --- a/packages/react-native-audio-api/scripts/check-audio-events-sync.sh +++ b/packages/react-native-audio-api/scripts/check-audio-events-sync.sh @@ -24,7 +24,7 @@ if [ ! -f "$KOTLIN_FILE" ]; then fi # Extract enum values from C++ file (lines between typedef enum { and } AudioEvent;) -CPP_ENUMS=$(sed -n '/enum class AudioEvent {/,/};/p' "$CPP_FILE" | \ +CPP_ENUMS=$(sed -n '/enum class AudioEvent : uint8_t {/,/};/p' "$CPP_FILE" | \ grep -E '^\s*[A-Z_]+' | \ sed 's/,//g' | \ sed 's/^[[:space:]]*//' | \ From fa0fbbfe1c61dbe099ff1a7146448e713228e7ea Mon Sep 17 00:00:00 2001 From: michal Date: Wed, 18 Mar 2026 15:27:50 +0100 Subject: [PATCH 8/9] chore: few additions --- .../common/cpp/audioapi/core/effects/WaveShaperNode.cpp | 2 +- .../common/cpp/audioapi/dsp/VectorMath.cpp | 4 ++-- .../common/cpp/audioapi/events/AudioEventHandlerRegistry.cpp | 4 ++++ 3 files changed, 7 insertions(+), 3 deletions(-) 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 b39d1a9ae..7886face4 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 @@ -13,7 +13,7 @@ WaveShaperNode::WaveShaperNode( : AudioNode(context, options), oversample_(options.oversample) { waveShapers_.reserve(6); - for (size_t i = 0; i < channelCount_; i++) { + for (int i = 0; i < channelCount_; i++) { waveShapers_.emplace_back(std::make_unique(nullptr, context->getSampleRate())); } setCurve(options.curve); 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 165c768f8..17133f983 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 @@ -132,7 +132,7 @@ void multiplyByScalar( size_t numberOfElementsToProcess) { size_t n = numberOfElementsToProcess; -#if defined(HAVE_X86_SSE2) +#ifdef HAVE_X86_SSE2 // If the inputVector address is not 16-byte aligned, the first several frames // (at most three) should be processed separately. @@ -734,7 +734,7 @@ void interleaveStereo( size_t n = numberOfFrames; -#if defined(HAVE_ARM_NEON_INTRINSICS) +#ifdef HAVE_ARM_NEON_INTRINSICS // process 4 frames (8 samples) at a time size_t group = n / 4; while (group--) { diff --git a/packages/react-native-audio-api/common/cpp/audioapi/events/AudioEventHandlerRegistry.cpp b/packages/react-native-audio-api/common/cpp/audioapi/events/AudioEventHandlerRegistry.cpp index 5b1f27a1c..e5f58e79a 100644 --- a/packages/react-native-audio-api/common/cpp/audioapi/events/AudioEventHandlerRegistry.cpp +++ b/packages/react-native-audio-api/common/cpp/audioapi/events/AudioEventHandlerRegistry.cpp @@ -65,6 +65,8 @@ void AudioEventHandlerRegistry::unregisterHandler(AudioEvent eventName, uint64_t }); } +// todo: refactor this method to be less complex and more readable +// NOLINTNEXTLINE(readability-function-cognitive-complexity) void AudioEventHandlerRegistry::invokeHandlerWithEventBody( AudioEvent eventName, const std::unordered_map &body) { @@ -122,6 +124,8 @@ void AudioEventHandlerRegistry::invokeHandlerWithEventBody( }); } +// todo: refactor this method to be less complex and more readable +// NOLINTNEXTLINE(readability-function-cognitive-complexity) void AudioEventHandlerRegistry::invokeHandlerWithEventBody( AudioEvent eventName, uint64_t listenerId, From f4bdaa4a373baca94de80a0e8d5ff408e5fcafbf Mon Sep 17 00:00:00 2001 From: michal Date: Wed, 18 Mar 2026 16:39:27 +0100 Subject: [PATCH 9/9] fix: tests --- .../common/cpp/audioapi/core/AudioNode.h | 2 +- .../audioapi/core/effects/IIRFilterNode.cpp | 2 +- .../cpp/audioapi/dsp/r8brain/Resampler.cpp | 85 ---- .../cpp/audioapi/dsp/r8brain/Resampler.h | 51 --- .../common/cpp/audioapi/utils/AudioArray.h | 166 -------- .../common/cpp/audioapi/utils/AudioBuffer.cpp | 385 ------------------ 6 files changed, 2 insertions(+), 689 deletions(-) delete mode 100644 packages/react-native-audio-api/common/cpp/audioapi/dsp/r8brain/Resampler.cpp delete mode 100644 packages/react-native-audio-api/common/cpp/audioapi/dsp/r8brain/Resampler.h delete mode 100644 packages/react-native-audio-api/common/cpp/audioapi/utils/AudioArray.h delete mode 100644 packages/react-native-audio-api/common/cpp/audioapi/utils/AudioBuffer.cpp 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 d7b496cae..a7fa5a817 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 @@ -99,7 +99,7 @@ class AudioNode : public std::enable_shared_from_this { private: bool isEnabled_ = true; - std::vector> inputBuffers_; + std::vector> inputBuffers_; virtual std::shared_ptr processInputs( const std::shared_ptr &outputBuffer, 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 43fa15f18..c9083d4ee 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 @@ -42,7 +42,7 @@ IIRFilterNode::IIRFilterNode( feedback_(createNormalizedArray(options.feedback, options.feedback[0])), xBuffers_(bufferLength, MAX_CHANNEL_COUNT, context->getSampleRate()), yBuffers_(bufferLength, MAX_CHANNEL_COUNT, context->getSampleRate()), - bufferIndices_() { + bufferIndices_(bufferLength) { isInitialized_.store(true, std::memory_order_release); } diff --git a/packages/react-native-audio-api/common/cpp/audioapi/dsp/r8brain/Resampler.cpp b/packages/react-native-audio-api/common/cpp/audioapi/dsp/r8brain/Resampler.cpp deleted file mode 100644 index d3a66cf78..000000000 --- a/packages/react-native-audio-api/common/cpp/audioapi/dsp/r8brain/Resampler.cpp +++ /dev/null @@ -1,85 +0,0 @@ -#include - -namespace r8b { - -BaseResampler::BaseResampler(double srcRate, double dstRate, int numChannels, int maxInLen) { - resamplers_.reserve(static_cast(numChannels)); - inputBuffers_.reserve(static_cast(numChannels)); - for (int i = 0; i < numChannels; ++i) { - resamplers_.emplace_back(std::make_unique(srcRate, dstRate, maxInLen)); - inputBuffers_.emplace_back(static_cast(maxInLen)); - } -} - -int BaseResampler::process(std::vector &input, int l, std::vector &output) { - int outLen = 0; - const size_t numChannels = resamplers_.size(); - - for (size_t i = 0; i < numChannels; ++i) { - const float *__restrict inData = input[i]; - double *__restrict bufData = inputBuffers_[i].data(); - - for (int j = 0; j < l; ++j) { - bufData[j] = static_cast(inData[j]); - } - - double *outPtr = nullptr; - const int currentOutLen = resamplers_[i]->process(bufData, l, outPtr); - outLen = currentOutLen; - - if (currentOutLen > 0 && outPtr != nullptr) { - const double *__restrict resampledData = outPtr; - float *__restrict outData = output[i]; - - for (int j = 0; j < currentOutLen; ++j) { - outData[j] = static_cast(resampledData[j]); - } - } - } - - return outLen; -} - -int BaseResampler::getMaxOutLen() const { - if (resamplers_.empty()) { - return 0; - } - return resamplers_[0]->getMaxOutLen(0); -} - -MultiChannelResampler::MultiChannelResampler( - double srcRate, - double dstRate, - int numChannels, - int maxInLen) - : BaseResampler(srcRate, dstRate, numChannels, maxInLen) {} - -int MultiChannelResampler::process( - audioapi::AudioBuffer &input, - int l, - audioapi::AudioBuffer &output) { - const size_t numChannels = input.getNumberOfChannels(); - std::vector inputPtrs(numChannels); - std::vector outputPtrs(numChannels); - for (size_t i = 0; i < numChannels; ++i) { - inputPtrs[i] = input.getChannel(i)->begin(); - outputPtrs[i] = output.getChannel(i)->begin(); - } - return BaseResampler::process(inputPtrs, l, outputPtrs); -} - -SingleChannelResampler::SingleChannelResampler(double srcRate, double dstRate, int maxInLen) - : BaseResampler(srcRate, dstRate, 1, maxInLen) {} - -int SingleChannelResampler::process( - audioapi::AudioArray &input, - int l, - audioapi::AudioArray &output) { - std::vector inputPtrs(1); - std::vector outputPtrs(1); - inputPtrs[0] = input.begin(); - outputPtrs[0] = output.begin(); - return BaseResampler::process(inputPtrs, l, outputPtrs); -} - -} // namespace r8b diff --git a/packages/react-native-audio-api/common/cpp/audioapi/dsp/r8brain/Resampler.h b/packages/react-native-audio-api/common/cpp/audioapi/dsp/r8brain/Resampler.h deleted file mode 100644 index afc749f84..000000000 --- a/packages/react-native-audio-api/common/cpp/audioapi/dsp/r8brain/Resampler.h +++ /dev/null @@ -1,51 +0,0 @@ -#pragma once - -#include -#include -#include -#include -#include -#include - -// Sample rate converter designed by Aleksey Vaneev of Voxengo on MIT license -#include "CDSPResampler.h" - -namespace r8b { - -class BaseResampler { - BaseResampler(const BaseResampler &) = delete; - BaseResampler &operator=(const BaseResampler &) = delete; - BaseResampler(BaseResampler &&) noexcept = default; - BaseResampler &operator=(BaseResampler &&) noexcept = default; - - private: - std::vector> resamplers_; - std::vector> inputBuffers_; - static constexpr int DEFAULT_MAX_IN_LEN = 2048; - - protected: - BaseResampler(double srcRate, double dstRate, int numChannels, int maxInLen = DEFAULT_MAX_IN_LEN); - int process(std::vector &input, int length, std::vector &output); - - public: - virtual ~BaseResampler() = default; - /** @return Maximum number of output samples per channel for one process() call (for the maxInLen passed to the constructor). */ - int getMaxOutLen() const; -}; - -class MultiChannelResampler : public BaseResampler { - public: - MultiChannelResampler(double srcRate, double dstRate, int numChannels, int maxInLen); - ~MultiChannelResampler() = default; - DELETE_COPY_AND_MOVE(MultiChannelResampler); - int process(audioapi::AudioBuffer &input, int length, audioapi::AudioBuffer &output); -}; - -class SingleChannelResampler : public BaseResampler { - public: - SingleChannelResampler(double srcRate, double dstRate, int maxInLen); - ~SingleChannelResampler() = default; - DELETE_COPY_AND_MOVE(SingleChannelResampler); - int process(audioapi::AudioArray &input, int length, audioapi::AudioArray &output); -}; -} // namespace r8b 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 deleted file mode 100644 index b5dc035f1..000000000 --- a/packages/react-native-audio-api/common/cpp/audioapi/utils/AudioArray.h +++ /dev/null @@ -1,166 +0,0 @@ -#pragma once - -#include -#include -#include -#include - -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; - - AudioArray(const AudioArray &other); - AudioArray(AudioArray &&other) noexcept; - AudioArray &operator=(const AudioArray &other); - AudioArray &operator=(AudioArray &&other) noexcept; - - [[nodiscard]] size_t getSize() const noexcept { - return size_; - } - - float &operator[](size_t index) noexcept { - return data_[index]; - } - const float &operator[](size_t index) const noexcept { - return data_[index]; - } - - [[nodiscard]] float *begin() noexcept { - return data_.get(); - } - [[nodiscard]] float *end() noexcept { - return data_.get() + size_; - } - - [[nodiscard]] const float *begin() const noexcept { - return data_.get(); - } - [[nodiscard]] const float *end() const noexcept { - return data_.get() + size_; - } - - [[nodiscard]] std::span span() noexcept { - return {data_.get(), size_}; - } - - [[nodiscard]] std::span span() const noexcept { - return {data_.get(), size_}; - } - - [[nodiscard]] std::span subSpan(size_t length, size_t offset = 0) const { - if (offset + length > size_) { - throw std::out_of_range("AudioArray::subSpan - offset + length exceeds array size"); - } - - return {data_.get() + offset, length}; - } - - 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 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. - /// @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 are located in two distinct, non-overlapping memory locations. - void sum( - const AudioArray &source, - size_t sourceStart, - size_t destinationStart, - 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 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 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); // NOLINT(build/include_what_you_use) - - /// @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); // NOLINT(build/include_what_you_use) - - /// @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); // NOLINT(build/include_what_you_use) - - /// @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 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 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 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); - - void reverse(); - void normalize(); - void scale(float value); - [[nodiscard]] float getMaxAbsValue() const; - [[nodiscard]] float computeConvolution(const AudioArray &kernel, size_t startIndex = 0) const; - - protected: - std::unique_ptr data_ = nullptr; - size_t size_ = 0; -}; - -} // namespace audioapi 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 deleted file mode 100644 index f044aaada..000000000 --- a/packages/react-native-audio-api/common/cpp/audioapi/utils/AudioBuffer.cpp +++ /dev/null @@ -1,385 +0,0 @@ -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -//NOLINTBEGIN(cppcoreguidelines-avoid-magic-numbers, readability-magic-numbers) - -namespace audioapi { - -const float SQRT_HALF = sqrtf(0.5f); //NOLINT(bugprone-throwing-static-initialization) -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) { - channels_.emplace_back(std::make_shared(size_)); - } -} - -AudioBuffer::AudioBuffer(const AudioBuffer &other) - : numberOfChannels_(other.numberOfChannels_), - sampleRate_(other.sampleRate_), - size_(other.size_) { - channels_.reserve(numberOfChannels_); - for (const auto &channel : other.channels_) { - channels_.emplace_back(std::make_shared(*channel)); - } -} - -AudioBuffer::AudioBuffer(audioapi::AudioBuffer &&other) noexcept - : channels_(std::move(other.channels_)), - 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) { - sampleRate_ = other.sampleRate_; - - if (numberOfChannels_ != other.numberOfChannels_) { - numberOfChannels_ = other.numberOfChannels_; - size_ = other.size_; - channels_.clear(); - channels_.reserve(numberOfChannels_); - - for (const auto &channel : other.channels_) { - channels_.emplace_back(std::make_shared(*channel)); - } - - return *this; - } - - if (size_ != other.size_) { - size_ = other.size_; - } - - for (size_t i = 0; i < numberOfChannels_; ++i) { - *channels_[i] = *other.channels_[i]; - } - } - - return *this; -} - -AudioBuffer &AudioBuffer::operator=(audioapi::AudioBuffer &&other) noexcept { - if (this != &other) { - channels_ = std::move(other.channels_); - - numberOfChannels_ = std::exchange(other.numberOfChannels_, 0); - sampleRate_ = std::exchange(other.sampleRate_, 0.0f); - size_ = std::exchange(other.size_, 0); - } - return *this; -} - -AudioArray *AudioBuffer::getChannel(size_t index) const { - return channels_[index].get(); -} - -AudioArray *AudioBuffer::getChannelByType(int channelType) const { - 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); - } - } - - return nullptr; -} - -std::shared_ptr AudioBuffer::getSharedChannel(size_t index) const { - return channels_[index]; -} - -void AudioBuffer::zero() { - zero(0, getSize()); -} - -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 AudioBuffer::sum(const AudioBuffer &source, ChannelInterpretation interpretation) { - sum(source, 0, 0, getSize(), interpretation); -} - -void AudioBuffer::sum( - const AudioBuffer &source, - size_t sourceStart, - size_t destinationStart, - size_t length, - ChannelInterpretation interpretation) { - if (&source == this) { - return; - } - - auto numberOfSourceChannels = source.getNumberOfChannels(); - auto numberOfChannels = getNumberOfChannels(); - - if (interpretation == ChannelInterpretation::DISCRETE) { - discreteSum(source, sourceStart, destinationStart, length); - return; - } - - // 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 buffer, we need to down-mix. - if (numberOfSourceChannels > numberOfChannels) { - sumByDownMixing(source, sourceStart, destinationStart, length); - return; - } - - // Source and destination channel counts are the same. Just sum the channels. - for (size_t i = 0; i < getNumberOfChannels(); ++i) { - channels_[i]->sum(*source.channels_[i], sourceStart, destinationStart, length); - } -} - -void AudioBuffer::copy(const AudioBuffer &source) { - copy(source, 0, 0, getSize()); -} - -void AudioBuffer::copy( - const AudioBuffer &source, - size_t sourceStart, - size_t destinationStart, - size_t length) { - if (&source == this) { - return; - } - - if (source.getNumberOfChannels() == getNumberOfChannels()) { - for (size_t i = 0; i < getNumberOfChannels(); ++i) { - channels_[i]->copy(*source.channels_[i], sourceStart, destinationStart, length); - } - - return; - } - - // zero + sum is equivalent to copy, but takes care of up/down-mixing. - zero(destinationStart, length); - 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; - } - - std::array channelsPtrs{}; - 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]; - } - } - } -} - -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; - } - - std::array channelsPtrs{}; - 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) { - float *frameDest = destination + (i * numberOfChannels_); - for (size_t ch = 0; ch < numberOfChannels_; ++ch) { - frameDest[ch] = channelsPtrs[ch][i]; - } - } - } -} - -void AudioBuffer::normalize() { - float maxAbsValue = this->maxAbsValue(); - - if (maxAbsValue == 0.0f || maxAbsValue == 1.0f) { - return; - } - - float scale = 1.0f / maxAbsValue; - this->scale(scale); -} - -void AudioBuffer::scale(float value) { - for (auto &channel : channels_) { - channel->scale(value); - } -} - -float AudioBuffer::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 AudioBuffer::discreteSum( - const AudioBuffer &source, - size_t sourceStart, - size_t destinationStart, - size_t length) const { - 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 (size_t i = 0; i < numberOfChannels; i++) { - channels_[i]->sum(*source.channels_[i], sourceStart, destinationStart, length); - } -} - -void AudioBuffer::sumByUpMixing( - const AudioBuffer &source, - size_t sourceStart, - size_t destinationStart, - size_t length) { - auto numberOfSourceChannels = source.getNumberOfChannels(); - auto numberOfChannels = getNumberOfChannels(); - - auto mix = [&](int srcType, int dstType) { - getChannelByType(dstType)->sum( - *source.getChannelByType(srcType), sourceStart, destinationStart, length); - }; - - // Mono to stereo (1 -> 2, 4) - if (numberOfSourceChannels == 1 && (numberOfChannels == 2 || numberOfChannels == 4)) { - mix(ChannelMono, ChannelLeft); - mix(ChannelMono, ChannelRight); - // Mono to 5.1 (1 -> 6) - } else if (numberOfSourceChannels == 1 && numberOfChannels == 6) { - mix(ChannelMono, ChannelCenter); - // Stereo 2 to stereo 4 or 5.1 (2 -> 4, 6) - } else if (numberOfSourceChannels == 2 && (numberOfChannels == 4 || numberOfChannels == 6)) { - mix(ChannelLeft, ChannelLeft); - mix(ChannelRight, ChannelRight); - // Stereo 4 to 5.1 (4 -> 6) - } else if (numberOfSourceChannels == 4 && numberOfChannels == 6) { - mix(ChannelLeft, ChannelLeft); - mix(ChannelRight, ChannelRight); - mix(ChannelSurroundLeft, ChannelSurroundLeft); - mix(ChannelSurroundRight, ChannelSurroundRight); - } else { - discreteSum(source, sourceStart, destinationStart, length); - } -} - -void AudioBuffer::sumByDownMixing( - const AudioBuffer &source, - size_t sourceStart, - size_t destinationStart, - size_t length) { - auto numberOfSourceChannels = source.getNumberOfChannels(); - auto numberOfChannels = getNumberOfChannels(); - - auto mix = [&](int srcType, int dstType, float scale = 1.0f) { - getChannelByType(dstType)->sum( - *source.getChannelByType(srcType), sourceStart, destinationStart, length, scale); - }; - - // Stereo to mono (2 -> 1): output += 0.5 * (input.L + input.R) - if (numberOfSourceChannels == 2 && numberOfChannels == 1) { - mix(ChannelLeft, ChannelMono, 0.5f); - mix(ChannelRight, ChannelMono, 0.5f); - // Stereo 4 to mono (4 -> 1): output += 0.25 * (input.L + input.R + input.SL + input.SR) - } else if (numberOfSourceChannels == 4 && numberOfChannels == 1) { - mix(ChannelLeft, ChannelMono, 0.25f); - mix(ChannelRight, ChannelMono, 0.25f); - mix(ChannelSurroundLeft, ChannelMono, 0.25f); - mix(ChannelSurroundRight, ChannelMono, 0.25f); - // 5.1 to mono (6 -> 1): output += sqrt(0.5)*(L+R) + C + 0.5*(SL+SR) - } else if (numberOfSourceChannels == 6 && numberOfChannels == 1) { - mix(ChannelLeft, ChannelMono, SQRT_HALF); - mix(ChannelRight, ChannelMono, SQRT_HALF); - mix(ChannelCenter, ChannelMono); - mix(ChannelSurroundLeft, ChannelMono, 0.5f); - mix(ChannelSurroundRight, ChannelMono, 0.5f); - // Stereo 4 to stereo 2 (4 -> 2): L += 0.5*(L+SL), R += 0.5*(R+SR) - } else if (numberOfSourceChannels == 4 && numberOfChannels == 2) { - mix(ChannelLeft, ChannelLeft, 0.5f); - mix(ChannelSurroundLeft, ChannelLeft, 0.5f); - mix(ChannelRight, ChannelRight, 0.5f); - mix(ChannelSurroundRight, ChannelRight, 0.5f); - // 5.1 to stereo (6 -> 2): L += L + sqrt(0.5)*(C+SL), R += R + sqrt(0.5)*(C+SR) - } else if (numberOfSourceChannels == 6 && numberOfChannels == 2) { - mix(ChannelLeft, ChannelLeft); - mix(ChannelCenter, ChannelLeft, SQRT_HALF); - mix(ChannelSurroundLeft, ChannelLeft, SQRT_HALF); - mix(ChannelRight, ChannelRight); - mix(ChannelCenter, ChannelRight, SQRT_HALF); - mix(ChannelSurroundRight, ChannelRight, SQRT_HALF); - // 5.1 to stereo 4 (6 -> 4): L += L + sqrt(0.5)*C, R += R + sqrt(0.5)*C, SL += SL, SR += SR - } else if (numberOfSourceChannels == 6 && numberOfChannels == 4) { - mix(ChannelLeft, ChannelLeft); - mix(ChannelCenter, ChannelLeft, SQRT_HALF); - mix(ChannelRight, ChannelRight); - mix(ChannelCenter, ChannelRight, SQRT_HALF); - mix(ChannelSurroundLeft, ChannelSurroundLeft); - mix(ChannelSurroundRight, ChannelSurroundRight); - } else { - discreteSum(source, sourceStart, destinationStart, length); - } -} - -} // namespace audioapi - -//NOLINTEND(cppcoreguidelines-avoid-magic-numbers, readability-magic-numbers)