Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
43fed07
refactor: audio array
Feb 2, 2026
6ad3a2b
feat: audio bus
Feb 2, 2026
f32a9f7
chore: added docs for both utils
Feb 2, 2026
91503c4
ci: lint
Feb 2, 2026
456b139
refactor: audio array and fft
Feb 2, 2026
8f439a6
chore: requested changes
Feb 3, 2026
e74317f
refactor: next part for audio bus and audio array
Feb 3, 2026
d1dede6
refactor: wip
Feb 3, 2026
1eca174
Merge branch 'main' into refactor/internal-tools
Feb 3, 2026
55bb04b
fix: a few fixes
Feb 3, 2026
e3b937c
fix: lint
Feb 3, 2026
83e8fdd
fix: fixed tests
Feb 3, 2026
122b9e0
fix: todos
Feb 4, 2026
a87f2f7
refactor: nits
Feb 4, 2026
58471e4
fix: nitpick
Feb 4, 2026
1b51ce6
refactor: added copyWithin - memmove to audio array
Feb 4, 2026
8127fa2
fix: memmove
Feb 4, 2026
2b01ac3
chore: updated custom processor template
Feb 4, 2026
dd2bf6b
refactor: optimized interleaveTo function
Feb 4, 2026
40d3ce7
refactor: renaming
Feb 4, 2026
7703767
refactor: renaming
Feb 4, 2026
a39e955
refactor: renaming
Feb 4, 2026
f9a3ac2
refactor: doxygen for AudioBuffer
Feb 4, 2026
a92bbf9
refactor: deinterleave audio data using AudioBuffer method
Feb 5, 2026
49537d0
refactor: broader support for circular data structures operations and…
Feb 5, 2026
7a13612
chore: requuested changes from code review
Feb 5, 2026
8587663
fix: nits
Feb 5, 2026
2e7538a
Merge branch 'main' into refactor/internal-tools
Feb 6, 2026
a033e12
ci: lint
Feb 6, 2026
0e95b8a
chore: requested changes from cr
Feb 6, 2026
60ea709
ci: lint
Feb 6, 2026
3c43693
refactor: get channel by type
Feb 9, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion apps/fabric-example/ios/Podfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -3321,7 +3321,7 @@ SPEC CHECKSUMS:
FBLazyVector: 309703e71d3f2f1ed7dc7889d58309c9d77a95a4
fmt: a40bb5bd0294ea969aaaba240a927bd33d878cdd
glog: 5683914934d5b6e4240e497e0f4a3b42d1854183
hermes-engine: 42d6f09ee6ede2feb220e2fb772e8bebb42ca403
hermes-engine: f93b5009d8ccd9429fe2a772351980df8a22a413
RCT-Folly: 846fda9475e61ec7bcbf8a3fe81edfcaeb090669
RCTDeprecation: a41bbdd9af30bf2e5715796b313e44ec43eefff1
RCTRequired: 7be34aabb0b77c3cefe644528df0fa0afad4e4d0
Expand Down
33 changes: 17 additions & 16 deletions packages/audiodocs/docs/guides/create-your-own-effect.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -45,21 +45,22 @@ For the sake of a simplicity, we will use value as a raw `double` type, not wrap
#include <audioapi/core/AudioNode.h>

namespace audioapi {
class AudioBus;
class AudioBuffer;

class MyProcessorNode : public AudioNode {
public:
explicit MyProcessorNode(BaseAudioContext *context);
class MyProcessorNode : public AudioNode {
public:
explicit MyProcessorNode(const std::shared_ptr<BaseAudioContext> &context, );

protected:
void processNode(const std::shared_ptr<AudioBus> &bus,
int framesToProcess) override;
protected:
std::shared_ptr<AudioBuffer>
processNode(const std::shared_ptr<AudioBuffer> &buffer,
int framesToProcess) override;

// highlight-start
private:
double gain; // value responsible for gain value
// highlight-end
};
// highlight-start
private:
double gain; // value responsible for gain value
// highlight-end
};
} // namespace audioapi
```
</details>
Expand All @@ -69,20 +70,20 @@ namespace audioapi {

```cpp
#include "MyProcessorNode.h"
#include <audioapi/utils/AudioBus.h>
#include <audioapi/utils/AudioBuffer.h>
#include <audioapi/utils/AudioArray.h>

namespace audioapi {
MyProcessorNode::MyProcessorNode(BaseAudioContext *context)
MyProcessorNode::MyProcessorNode(const std::shared_ptr<BaseAudioContext> &context)
//highlight-next-line
: AudioNode(context), gain(0.5) {
isInitialized_ = true;
}

void MyProcessorNode::processNode(const std::shared_ptr<AudioBus> &bus,
std::shared_ptr<AudioBuffer> MyProcessorNode::processNode(const std::shared_ptr<AudioBuffer> &buffer,
int framesToProcess) {
// highlight-start
for (int channel = 0; channel < bus->getNumberOfChannels(); ++channel) {
for (int channel = 0; channel < buffer->getNumberOfChannels(); ++channel) {
auto *audioArray = bus->getChannel(channel);
for (size_t i = 0; i < framesToProcess; ++i) {
// Apply gain to each sample in the audio array
Expand Down
Original file line number Diff line number Diff line change
@@ -1,14 +1,16 @@
#include "MyProcessorNode.h"
#include <audioapi/utils/AudioBus.h>
#include <audioapi/utils/AudioBuffer.h>

namespace audioapi {
MyProcessorNode::MyProcessorNode(std::shared_ptr<BaseAudioContext> context)
MyProcessorNode::MyProcessorNode(
const std::shared_ptr<BaseAudioContext> &context, )
: AudioNode(context) {
isInitialized_ = true;
isInitialized_ = true;
}

std::shared_ptr<AudioBus> MyProcessorNode::processNode(const std::shared_ptr<AudioBus> &bus,
int framesToProcess) {
// put your processing logic here
std::shared_ptr<AudioBuffer>
MyProcessorNode::processNode(const std::shared_ptr<AudioBuffer> &buffer,
int framesToProcess) {
// put your processing logic here
}
} // namespace audioapi
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,15 @@
#include <audioapi/core/AudioNode.h>

namespace audioapi {
class AudioBus;
class AudioBuffer;

class MyProcessorNode : public AudioNode {
public:
explicit MyProcessorNode(std::shared_ptr<BaseAudioContext> context);
explicit MyProcessorNode(const std::shared_ptr<BaseAudioContext> &context, );

protected:
std::shared_ptr<AudioBus> processNode(const std::shared_ptr<AudioBus> &bus,
int framesToProcess) override;

std::shared_ptr<AudioBuffer>
processNode(const std::shared_ptr<AudioBuffer> &buffer,
int framesToProcess) override;
};
} // namespace audioapi
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
#include <audioapi/core/utils/Locker.h>
#include <audioapi/events/AudioEventHandlerRegistry.h>
#include <audioapi/utils/AudioArray.h>
#include <audioapi/utils/AudioBus.h>
#include <audioapi/utils/AudioBuffer.h>
#include <audioapi/utils/AudioFileProperties.h>
#include <audioapi/utils/CircularAudioArray.h>
#include <audioapi/utils/CircularOverflowableAudioArray.h>
Expand Down Expand Up @@ -143,7 +143,8 @@ Result<std::string, std::string> AndroidAudioRecorder::start(const std::string &
}

if (isConnected()) {
deinterleavingBuffer_ = std::make_shared<AudioArray>(streamMaxBufferSizeInFrames_);
deinterleavingBuffer_ = std::make_shared<AudioBuffer>(
streamMaxBufferSizeInFrames_, streamChannelCount_, streamSampleRate_);
adapterNode_->init(streamMaxBufferSizeInFrames_, streamChannelCount_);
}

Expand Down Expand Up @@ -324,7 +325,8 @@ void AndroidAudioRecorder::connect(const std::shared_ptr<RecorderAdapterNode> &n
adapterNode_ = node;

if (!isIdle()) {
deinterleavingBuffer_ = std::make_shared<AudioArray>(streamMaxBufferSizeInFrames_);
deinterleavingBuffer_ = std::make_shared<AudioBuffer>(
streamMaxBufferSizeInFrames_, streamChannelCount_, streamSampleRate_);
adapterNode_->init(streamMaxBufferSizeInFrames_, streamChannelCount_);
}

Expand Down Expand Up @@ -374,13 +376,11 @@ oboe::DataCallbackResult AndroidAudioRecorder::onAudioReady(

if (isConnected()) {
if (auto adapterLock = Locker::tryLock(adapterNodeMutex_)) {
for (int channel = 0; channel < streamChannelCount_; ++channel) {
for (int frame = 0; frame < numFrames; ++frame) {
deinterleavingBuffer_->getData()[frame] =
static_cast<float *>(audioData)[frame * streamChannelCount_ + channel];
}
auto const data = static_cast<float *>(audioData);
deinterleavingBuffer_->deinterleaveFrom(data, numFrames);

adapterNode_->buff_[channel]->write(deinterleavingBuffer_->getData(), numFrames);
for (size_t ch = 0; ch < streamChannelCount_; ++ch) {
adapterNode_->buff_[ch]->write(*deinterleavingBuffer_->getChannel(ch), numFrames);
}
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,18 +1,18 @@
#pragma once

#include <audioapi/android/core/NativeAudioRecorder.hpp>
#include <audioapi/core/inputs/AudioRecorder.h>
#include <audioapi/utils/Result.hpp>
#include <oboe/Oboe.h>
#include <functional>
#include <memory>
#include <mutex>
#include <string>
#include <tuple>
#include <mutex>
#include <audioapi/utils/Result.hpp>
#include <audioapi/android/core/NativeAudioRecorder.hpp>

namespace audioapi {

class AudioBus;
class AudioBuffer;
class AudioArray;
class CircularAudioArray;
class AudioFileProperties;
Expand All @@ -22,14 +22,16 @@ class AudioEventHandlerRegistry;

class AndroidAudioRecorder : public oboe::AudioStreamCallback, public AudioRecorder {
public:
explicit AndroidAudioRecorder(const std::shared_ptr<AudioEventHandlerRegistry> &audioEventHandlerRegistry);
explicit AndroidAudioRecorder(
const std::shared_ptr<AudioEventHandlerRegistry> &audioEventHandlerRegistry);
~AndroidAudioRecorder() override;
void cleanup();

Result<std::string, std::string> start(const std::string &fileNameOverride) override;
Result<std::tuple<std::string, double, double>, std::string> stop() override;

Result<std::string, std::string> enableFileOutput(std::shared_ptr<AudioFileProperties> properties) override;
Result<std::string, std::string> enableFileOutput(
std::shared_ptr<AudioFileProperties> properties) override;
void disableFileOutput() override;

void pause() override;
Expand All @@ -38,21 +40,22 @@ class AndroidAudioRecorder : public oboe::AudioStreamCallback, public AudioRecor
bool isPaused() const override;
bool isIdle() const override;

Result<NoneType, std::string> setOnAudioReadyCallback(float sampleRate, size_t bufferLength, int channelCount, uint64_t callbackId)
override;
Result<NoneType, std::string> setOnAudioReadyCallback(
float sampleRate,
size_t bufferLength,
int channelCount,
uint64_t callbackId) override;
void clearOnAudioReadyCallback() override;

void connect(const std::shared_ptr<RecorderAdapterNode> &node) override;
void disconnect() override;

oboe::DataCallbackResult onAudioReady(
oboe::AudioStream *oboeStream,
void *audioData,
int32_t numFrames) override;
oboe::DataCallbackResult
onAudioReady(oboe::AudioStream *oboeStream, void *audioData, int32_t numFrames) override;
void onErrorAfterClose(oboe::AudioStream *oboeStream, oboe::Result error) override;

private:
std::shared_ptr<AudioArray> deinterleavingBuffer_;
std::shared_ptr<AudioBuffer> deinterleavingBuffer_;

float streamSampleRate_;
int32_t streamChannelCount_;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
#include <audioapi/core/AudioContext.h>
#include <audioapi/core/utils/Constants.h>
#include <audioapi/utils/AudioArray.h>
#include <audioapi/utils/AudioBus.h>
#include <audioapi/utils/AudioBuffer.h>
#include <jni.h>

#include <algorithm>
Expand All @@ -12,7 +12,7 @@
namespace audioapi {

AudioPlayer::AudioPlayer(
const std::function<void(std::shared_ptr<AudioBus>, int)> &renderAudio,
const std::function<void(std::shared_ptr<AudioBuffer>, int)> &renderAudio,
float sampleRate,
int channelCount)
: renderAudio_(renderAudio),
Expand Down Expand Up @@ -42,7 +42,7 @@ bool AudioPlayer::openAudioStream() {
return false;
}

audioBus_ = std::make_shared<AudioBus>(RENDER_QUANTUM_SIZE, channelCount_, sampleRate_);
buffer_ = std::make_shared<AudioBuffer>(RENDER_QUANTUM_SIZE, channelCount_, sampleRate_);
return true;
}

Expand Down Expand Up @@ -108,21 +108,17 @@ AudioPlayer::onAudioReady(AudioStream *oboeStream, void *audioData, int32_t numF
int processedFrames = 0;

while (processedFrames < numFrames) {
int framesToProcess = std::min(numFrames - processedFrames, RENDER_QUANTUM_SIZE);
auto framesToProcess = std::min(numFrames - processedFrames, RENDER_QUANTUM_SIZE);

if (isRunning_.load(std::memory_order_acquire)) {
renderAudio_(audioBus_, framesToProcess);
renderAudio_(buffer_, framesToProcess);
} else {
audioBus_->zero();
buffer_->zero();
}

for (int i = 0; i < framesToProcess; i++) {
for (int channel = 0; channel < channelCount_; channel++) {
buffer[(processedFrames + i) * channelCount_ + channel] =
audioBus_->getChannel(channel)->getData()[i];
}
}
float *destination = buffer + (processedFrames * channelCount_);

buffer_->interleaveTo(destination, framesToProcess);
processedFrames += framesToProcess;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,12 @@ namespace audioapi {
using namespace oboe;

class AudioContext;
class AudioBus;
class AudioBuffer;

class AudioPlayer : public AudioStreamDataCallback, AudioStreamErrorCallback {
public:
AudioPlayer(
const std::function<void(std::shared_ptr<AudioBus>, int)> &renderAudio,
const std::function<void(std::shared_ptr<AudioBuffer>, int)> &renderAudio,
float sampleRate,
int channelCount);

Expand All @@ -34,18 +34,15 @@ class AudioPlayer : public AudioStreamDataCallback, AudioStreamErrorCallback {

[[nodiscard]] bool isRunning() const;

DataCallbackResult onAudioReady(
AudioStream *oboeStream,
void *audioData,
int32_t numFrames) override;

void onErrorAfterClose(AudioStream * /* audioStream */, Result /* error */)
DataCallbackResult onAudioReady(AudioStream *oboeStream, void *audioData, int32_t numFrames)
override;

void onErrorAfterClose(AudioStream * /* audioStream */, Result /* error */) override;

private:
std::function<void(std::shared_ptr<AudioBus>, int)> renderAudio_;
std::function<void(std::shared_ptr<AudioBuffer>, int)> renderAudio_;
std::shared_ptr<AudioStream> mStream_;
std::shared_ptr<AudioBus> audioBus_;
std::shared_ptr<AudioBuffer> buffer_;
bool isInitialized_ = false;
float sampleRate_;
int channelCount_;
Expand Down
Loading