Skip to content

Commit

Permalink
[#201] [Core] AudioBus - support for multiple node connections and mi…
Browse files Browse the repository at this point in the history
…xed amount of channels (#206)

* feat: working on new buffer structure

* feat: more work

* feat: channel mixer

* feat: add some comments

* fix: spellchecker howling

* fix: linter howling

* fix: linter howling part 1.27

* fix: politely obey to false-positive linter check

* feat: working on AudioPlayer implementation using AudioBus

* feat: processNode implementations

* feat: self-abuse

* feat: migrate gain node

* feat: audio bus & audio array range operators

* feat: audio buffer source node - rewrite to use audio bus and complicate the matter

* fix: some memory alloc fixes

* fix: get back to previous scheduling impl

* fix: cleanup logs

* feat: update translations

* fix: uncomment all oscilator example params

* fix: more fixes

* feat: locker + audio node manager wip

* fix: remove silencer + add post and preproc

* feat: working on decontruction

* feat: something is working

* fix: hi-hat sound

* feat: proper deconstruction

* fix: unused variable, android player pointer usage

* fix: linter

* fix: linter2 - the return of the explicit?

* Update packages/react-native-audio-api/common/cpp/core/AudioBus.cpp

* Update packages/react-native-audio-api/common/cpp/core/AudioBus.cpp

* fix: cleanup

* fix: redundant HAVE_ACCELERATE directive
  • Loading branch information
michalsek authored Nov 26, 2024
1 parent 4199cef commit 3c924bf
Show file tree
Hide file tree
Showing 43 changed files with 1,484 additions and 363 deletions.
1 change: 1 addition & 0 deletions .github/actions/spelling/allow.txt
Original file line number Diff line number Diff line change
Expand Up @@ -28,4 +28,5 @@ rnaa

tada
vec
rnaa

Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ class Clap implements SoundEngine {
}

createNoiseBuffer() {
const bufferSize = this.audioContext.sampleRate / 10;
const bufferSize = this.audioContext.sampleRate / 5;
const buffer = this.audioContext.createBuffer(
1,
bufferSize,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ class HiHat implements SoundEngine {
const oscillator = this.audioContext.createOscillator();
oscillator.type = 'square';
oscillator.frequency.value = this.tone * ratio;

const bandpassFilter = this.audioContext.createBiquadFilter();
const highpassFilter = this.audioContext.createBiquadFilter();
const gain = this.audioContext.createGain();
Expand All @@ -46,6 +47,7 @@ class HiHat implements SoundEngine {
bandpassFilter.connect(highpassFilter);
highpassFilter.connect(gain);
gain.connect(this.audioContext.destination!);

oscillator.start(time);
oscillator.stop(time + this.decay);
});
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>IDEDidComputeMac32BitWarning</key>
<true/>
</dict>
</plist>
4 changes: 2 additions & 2 deletions apps/fabric-example/ios/Podfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -2063,8 +2063,8 @@ SPEC CHECKSUMS:
RNReanimated: 77242c6d67416988a2fd9f5cf574bb3e60016362
RNScreens: e389d6a6a66a4f0d3662924ecae803073ccce8ec
SocketRocket: d4aabe649be1e368d1318fdf28a022d714d65748
Yoga: f8ec45ce98bba1bc93dd28f2ee37215180e6d2b6
Yoga: 1d66db49f38fd9e576a1d7c3b081e46ab4c28b9e

PODFILE CHECKSUM: 75ad38075e71875257a2590065853ea6a608b897

COCOAPODS: 1.15.2
COCOAPODS: 1.16.2
5 changes: 0 additions & 5 deletions packages/react-native-audio-api/android/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,6 @@ project(react-native-audio-api)
set(CMAKE_VERBOSE_MAKEFILE ON)
set(CMAKE_CXX_STANDARD 20)

# Detect the operating system
if(APPLE)
set(HAVE_ACCELERATE TRUE)
endif()

# Detect the processor and SIMD support
if(CMAKE_SYSTEM_PROCESSOR STREQUAL "arm64" OR CMAKE_SYSTEM_PROCESSOR STREQUAL "aarch64")
set(HAVE_ARM_NEON_INTRINSICS TRUE)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,16 @@

#include "AudioBus.h"
#include "Constants.h"
#include "AudioArray.h"
#include "AudioPlayer.h"
#include "AudioContext.h"

namespace audioapi {
AudioPlayer::AudioPlayer(const std::function<void(float *, int)> &renderAudio)

AudioPlayer::AudioPlayer(const std::function<void(AudioBus*, int)> &renderAudio)
: renderAudio_(renderAudio) {
AudioStreamBuilder builder;

builder.setSharingMode(SharingMode::Exclusive)
->setFormat(AudioFormat::Float)
->setFormatConversionAllowed(true)
Expand All @@ -13,12 +19,18 @@ AudioPlayer::AudioPlayer(const std::function<void(float *, int)> &renderAudio)
->setSampleRateConversionQuality(SampleRateConversionQuality::Medium)
->setDataCallback(this)
->openStream(mStream_);

mBus_ = std::make_shared<AudioBus>(getSampleRate(), getBufferSizeInFrames(), CHANNEL_COUNT);
}

int AudioPlayer::getSampleRate() const {
return mStream_->getSampleRate();
}

int AudioPlayer::getBufferSizeInFrames() const {
return mStream_->getBufferSizeInFrames();
}

void AudioPlayer::start() {
if (mStream_) {
mStream_->requestStart();
Expand All @@ -38,8 +50,17 @@ DataCallbackResult AudioPlayer::onAudioReady(
void *audioData,
int32_t numFrames) {
auto buffer = static_cast<float *>(audioData);
renderAudio_(buffer, numFrames);

renderAudio_(mBus_.get(), numFrames);

// TODO: optimize this with SIMD?
for (int32_t i = 0; i < numFrames; i += 1) {
for (int channel = 0; channel < CHANNEL_COUNT; channel += 1) {
buffer[i * CHANNEL_COUNT + channel] = mBus_->getChannel(channel)->getData()[i];
}
}

return DataCallbackResult::Continue;
}

} // namespace audioapi
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,14 @@ namespace audioapi {
using namespace oboe;

class AudioContext;
class AudioBus;

class AudioPlayer : public AudioStreamDataCallback {
public:
explicit AudioPlayer(const std::function<void(float *, int)> &renderAudio);
explicit AudioPlayer(const std::function<void(AudioBus*, int)> &renderAudio);

int getSampleRate() const;
int getBufferSizeInFrames() const;
void start();
void stop();

Expand All @@ -23,8 +25,9 @@ class AudioPlayer : public AudioStreamDataCallback {
int32_t numFrames) override;

private:
std::function<void(float *, int)> renderAudio_;
std::function<void(AudioBus*, int)> renderAudio_;
std::shared_ptr<AudioStream> mStream_;
std::shared_ptr<AudioBus> mBus_;
};

} // namespace audioapi
103 changes: 103 additions & 0 deletions packages/react-native-audio-api/common/cpp/core/AudioArray.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
#include <algorithm>

#include "AudioArray.h"
#include "VectorMath.h"

namespace audioapi {

AudioArray::AudioArray(int size) : size_(size), data_(0) {
resize(size);
}

AudioArray::~AudioArray() {
if (data_) {
delete[] data_;
data_ = 0;
}
}

int AudioArray::getSize() const {
return size_;
}

float* AudioArray::getData() const {
return data_;
}

float& AudioArray::operator[](int index) {
return data_[index];
}

const float& AudioArray::operator[](int index) const {
return data_[index];
}

void AudioArray::normalize() {
float maxAbsValue = getMaxAbsValue();

if (maxAbsValue == 0.0f || maxAbsValue == 1.0f) {
return;
}

VectorMath::multiplyByScalar(data_, 1.0f / maxAbsValue, data_, size_);
}

void AudioArray::resize(int size) {
if (size == size_) {
if (!data_) {
data_ = new float[size];
}

zero(0, size);
return;
}

delete[] data_;
size_ = size;
data_ = new float[size_];

zero(0, size_);
}

void AudioArray::scale(float value) {
VectorMath::multiplyByScalar(data_, value, data_, size_);
}

float AudioArray::getMaxAbsValue() const {
return VectorMath::maximumMagnitude(data_, size_);
}

void AudioArray::zero() {
zero(0, size_);
}

void AudioArray::zero(int start, int length) {
memset(data_ + start, 0, length * sizeof(float));
}

void AudioArray::sum(const AudioArray* source) {
sum(source, 0, 0, size_);
}

void AudioArray::sum(const AudioArray* source, int start, int length) {
sum(source, start, start, length);
}

void AudioArray::sum(const AudioArray* source, int sourceStart, int destinationStart, int length) {
VectorMath::add(data_ + destinationStart, source->getData() + sourceStart, data_ + destinationStart, length);
}

void AudioArray::copy(const AudioArray* source) {
copy(source, 0, size_);
}

void AudioArray::copy(const AudioArray* source, int start, int length) {
copy(source, start, start, length);
}

void AudioArray::copy(const AudioArray* source, int sourceStart, int destinationStart, int length) {
memcpy(data_ + destinationStart, source->getData() + sourceStart, length * sizeof(float));
}

} // namespace audioapi

42 changes: 42 additions & 0 deletions packages/react-native-audio-api/common/cpp/core/AudioArray.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
#pragma once

#include <memory>
#include <algorithm>

namespace audioapi {

class AudioArray {
public:
explicit AudioArray(int size);
~AudioArray();

[[nodiscard]] int getSize() const;
float* getData() const;


float& operator[](int index);
const float& operator[](int index) const;

void normalize();
void resize(int size);
void scale(float value);
float getMaxAbsValue() const;

void zero();
void zero(int start, int length);

void sum(const AudioArray* source);
void sum(const AudioArray* source, int start, int length);
void sum(const AudioArray* source, int sourceStart, int destinationStart, int length);

void copy(const AudioArray* source);
void copy(const AudioArray* source, int start, int length);
void copy(const AudioArray* source, int sourceStart, int destinationStart, int length);


private:
float *data_;
int size_;
};

} // namespace audioapi
Loading

0 comments on commit 3c924bf

Please sign in to comment.