Skip to content

Commit

Permalink
Feat/audio buffer (#105)
Browse files Browse the repository at this point in the history
* fix: removed duplicated code

* fix: removed deltaTime property

* feat: impemented AudioBuffer in kotlin

* feat: addec channel properties

* fix: fixed bug

* feat: added enums

* feat: implemented channel properties in different nodes

* feat: replaced buffer list with AudioBuffer class

* feat: implemented mixing buffers

* refactor: refractored mixing

* feat: added AudioBufferSourceNode

* refactor: start, stop methods refactoring

* fix: fixed hihat ios bug

* refactor: changed getBuffer method name to fillBuffer

* fix: fixed AudioTrack reusing

* feat: implemented getters for channel properties of AudioNode

* feat: updated api coverage map

* feat: implemented AudioBufferSourceNode commonclasses

* feat: implemneted JNi AudioBuffer class and added targets to CMakeList.txt

* feat: implemented AudioBufferSourceNode classes

* refactor: changed static_cast to dynamic_cast

* Revert "refactor: changed static_cast to dynamic_cast"

This reverts commit 8d7500a.

* fix: fixed array serialization and typo in descriptor

* feat: added createBuffer and createBufferSource methods and proper types

* fix: fixed bugs and added setChannelData method

* fix: trying to fix sigsegv during creating AudioBufferSource

* refactor: refactored includes

* feat: implemented Clap sound

* fix: fixed AudioBufferSourceNode buffer filling

* fix: fixed OscillatorNode buffer filling, buffer filling in Clap and types

* fix: merge changes

---------

Co-authored-by: Maciej Makowski <[email protected]>
  • Loading branch information
maciejmakowski2003 and Maciej Makowski authored Sep 4, 2024
1 parent 715cf83 commit fec8936
Show file tree
Hide file tree
Showing 64 changed files with 1,320 additions and 154 deletions.
17 changes: 10 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,13 +32,16 @@ npm install react-native-audio-context
<details>
<summary><b>AudioNode</b><br/> Android: ✅ <br />iOS: ✅</summary>

| Method / Property | iOS | Android |
| ----------------- | --- | ------- |
| 🔹context |||
| 🔹numberOfInputs |||
| 🔹numberOfOutputs |||
| 🔘connect |||
| 🔘disconnect |||
| Method / Property | iOS | Android |
| ------------------------ | --- | ------- |
| 🔹context |||
| 🔹numberOfInputs |||
| 🔹numberOfOutputs |||
| 🔹channelCount |||
| 🔹channelCountMode |||
| 🔹channelInterpretation |||
| 🔘connect |||
| 🔘disconnect |||

</details>

Expand Down
4 changes: 4 additions & 0 deletions android/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ set(INCLUDE_DIRS
../cpp/StereoPannerNode
../cpp/AudioParam
../cpp/BiquadFilterNode
../cpp/AudioBuffer
../cpp/AudioBufferSourceNode

src/main/cpp
src/main/cpp/AudioContext
Expand All @@ -31,6 +33,8 @@ set(INCLUDE_DIRS
src/main/cpp/StereoPannerNode
src/main/cpp/AudioParam
src/main/cpp/BiquadFilterNode
src/main/cpp/AudioBuffer
src/main/cpp/AudioBufferSourceNode

../node_modules/react-native/ReactCommon/jsi
../node_modules/react-native/ReactAndroid/src/main/jni/react/jni
Expand Down
57 changes: 57 additions & 0 deletions android/src/main/cpp/AudioBuffer/AudioBuffer.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
#include "AudioBuffer.h"

namespace audiocontext {

AudioBuffer::AudioBuffer(jni::alias_ref<AudioBuffer::jhybridobject>& jThis): javaPart_(make_global(jThis)) {}

int AudioBuffer::getSampleRate() {
static const auto method = javaClassStatic()->getMethod<jint()>("getSampleRate");
return method(javaPart_);
}

int AudioBuffer::getLength() {
static const auto method = javaClassStatic()->getMethod<jint()>("getLength");
return method(javaPart_);
}

double AudioBuffer::getDuration() {
static const auto method = javaClassStatic()->getMethod<jdouble()>("getDuration");
return method(javaPart_);
}

int AudioBuffer::getNumberOfChannels() {
static const auto method = javaClassStatic()->getMethod<jint()>("getNumberOfChannels");
return method(javaPart_);
}

short **AudioBuffer::getChannelData(int channel) {
static const auto method = javaClassStatic()->getMethod<JArrayShort (jint)>("getChannelData");
auto jArray = method(javaPart_, channel);
auto length = jArray->size();

auto channelData = new short*[length];
auto pin = jArray->pin();
for (int i = 0; i < length; i++) {
channelData[i] = &pin[i];
}

return channelData;
}

void AudioBuffer::setChannelData(int channel, short** data) {
static const auto method = javaClassStatic()->getMethod<void(jint, jshortArray)>("setChannelData");
std::vector<jshort> buffer(getLength());
for (int i = 0; i < getLength(); i++) {
buffer[i] = *data[i];
}
auto jArray = JArrayShort::newArray(getLength());
jArray->setRegion(0, getLength(), buffer.data());

method(javaPart_, channel, jArray.get());
}

void AudioBuffer::prepareForDeconstruction() {
javaPart_.reset();
}

} // namespace audiocontext
44 changes: 44 additions & 0 deletions android/src/main/cpp/AudioBuffer/AudioBuffer.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
#pragma once

#include <fbjni/fbjni.h>
#include <react/jni/CxxModuleWrapper.h>
#include <react/jni/JMessageQueueThread.h>
#include <memory>

namespace audiocontext {

using namespace facebook;
using namespace facebook::jni;

class AudioBuffer : public jni::HybridClass<AudioBuffer> {
public:
static auto constexpr kJavaDescriptor = "Lcom/audiocontext/utils/AudioBuffer;";

static jni::local_ref<AudioBuffer::jhybriddata> initHybrid(jni::alias_ref<jhybridobject> jThis)
{
return makeCxxInstance(jThis);
}

static void registerNatives() {
registerHybrid({
makeNativeMethod("initHybrid", AudioBuffer::initHybrid),
});
}

int getSampleRate();
int getLength();
double getDuration();
int getNumberOfChannels();
short** getChannelData(int channel);
void setChannelData(int channel, short** data);
void prepareForDeconstruction();

public:
friend HybridBase;

global_ref<AudioBuffer::javaobject> javaPart_;

explicit AudioBuffer(jni::alias_ref<AudioBuffer::jhybridobject>& jThis);
};

} // namespace audiocontext
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
#include "AudioBufferSourceNode.h"

namespace audiocontext {

using namespace facebook::jni;

void AudioBufferSourceNode::start(double time) {
static const auto method = javaClassLocal()->getMethod<void(jdouble)>("start");
method(javaPart_.get(), time);
}

void AudioBufferSourceNode::stop(double time) {
static const auto method = javaClassLocal()->getMethod<void(jdouble)>("stop");
method(javaPart_.get(), time);
}

bool AudioBufferSourceNode::getLoop() {
static const auto method = javaClassLocal()->getMethod<jboolean()>("getLoop");
return method(javaPart_.get());
}

void AudioBufferSourceNode::setLoop(bool loop) {
static const auto method = javaClassLocal()->getMethod<void(jboolean)>("setLoop");
method(javaPart_.get(), loop);
}

AudioBuffer *AudioBufferSourceNode::getBuffer() {
static const auto method = javaClassLocal()->getMethod<AudioBuffer()>("getBuffer");
auto buffer = method(javaPart_.get());

return buffer->cthis();
}

void AudioBufferSourceNode::setBuffer(const AudioBuffer* buffer) {
static const auto method = javaClassLocal()->getMethod<void(AudioBuffer::javaobject)>("setBuffer");
method(javaPart_.get(), buffer->javaPart_.get());
}
} // namespace audiocontext
22 changes: 22 additions & 0 deletions android/src/main/cpp/AudioBufferSourceNode/AudioBufferSourceNode.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
#pragma once

#include "AudioNode.h"
#include "AudioBuffer.h"

namespace audiocontext {

using namespace facebook;
using namespace facebook::jni;

class AudioBufferSourceNode : public jni::HybridClass<AudioBufferSourceNode, AudioNode> {
public:
static auto constexpr kJavaDescriptor = "Lcom/audiocontext/nodes/AudioBufferSourceNode;";

void start(double time);
void stop(double time);
bool getLoop();
void setLoop(bool loop);
AudioBuffer* getBuffer();
void setBuffer(const AudioBuffer* buffer);
};
}// namespace audiocontext
16 changes: 16 additions & 0 deletions android/src/main/cpp/AudioContext/AudioContext.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,22 @@ namespace audiocontext
return biquadFilter->cthis();
}

AudioBufferSourceNode* AudioContext::createBufferSource()
{
static const auto method = javaClassLocal()->getMethod<AudioBufferSourceNode()>("createBufferSource");
auto bufferSource = method(javaPart_.get());

return bufferSource->cthis();
}

AudioBuffer* AudioContext::createBuffer(int sampleRate, int length, int numberOfChannels)
{
static const auto method = javaClassLocal()->getMethod<AudioBuffer(int, int, int)>("createBuffer");
auto buffer = method(javaPart_.get(), sampleRate, length, numberOfChannels);

return buffer->cthis();
}

std::string AudioContext::getState()
{
static const auto method = javaClassLocal()->getMethod<JString()>("getState");
Expand Down
4 changes: 4 additions & 0 deletions android/src/main/cpp/AudioContext/AudioContext.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@
#include "GainNode.h"
#include "StereoPannerNode.h"
#include "BiquadFilterNode.h"
#include "AudioBufferSourceNode.h"
#include "AudioBuffer.h"

namespace audiocontext
{
Expand Down Expand Up @@ -44,6 +46,8 @@ namespace audiocontext
GainNode* createGain();
StereoPannerNode* createStereoPanner();
BiquadFilterNode* createBiquadFilter();
AudioBufferSourceNode* createBufferSource();
AudioBuffer* createBuffer(int sampleRate, int length, int numberOfChannels);
std::string getState();
int getSampleRate();
double getCurrentTime();
Expand Down
15 changes: 15 additions & 0 deletions android/src/main/cpp/AudioNode/AudioNode.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,21 @@ namespace audiocontext {
return method(javaPart_.get());
}

int AudioNode::getChannelCount() {
static const auto method = javaClassLocal()->getMethod<int()>("getChannelCount");
return method(javaPart_.get());
}

std::string AudioNode::getChannelCountMode() {
static const auto method = javaClassLocal()->getMethod<JString()>("getChannelCountMode");
return method(javaPart_.get())->toStdString();
}

std::string AudioNode::getChannelInterpretation() {
static const auto method = javaClassLocal()->getMethod<JString()>("getChannelInterpretation");
return method(javaPart_.get())->toStdString();
}

void AudioNode::connect(const AudioNode *node) {
static const auto method = javaClassLocal()->getMethod<void(AudioNode::javaobject)>(
"connect");
Expand Down
5 changes: 4 additions & 1 deletion android/src/main/cpp/AudioNode/AudioNode.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ namespace audiocontext {

class AudioNode : public jni::HybridClass<AudioNode> {
public:
static auto constexpr kJavaDescriptor = "Lcom/audiocontext/nodes/AudioNode;";
static auto constexpr kJavaDescriptor = "Lcom/audiocontext/nodes/audionode/AudioNode;";

static jni::local_ref<AudioNode::jhybriddata> initHybrid(jni::alias_ref<jhybridobject> jThis)
{
Expand All @@ -27,6 +27,9 @@ namespace audiocontext {

int getNumberOfInputs();
int getNumberOfOutputs();
int getChannelCount();
std::string getChannelCountMode();
std::string getChannelInterpretation();
void connect(const AudioNode *node);
void disconnect(const AudioNode *node);
void resetJavaPart();
Expand Down
4 changes: 0 additions & 4 deletions android/src/main/cpp/BiquadFilterNode/BiquadFilterNode.h
Original file line number Diff line number Diff line change
@@ -1,9 +1,5 @@
#pragma once

#include <fbjni/fbjni.h>
#include <react/jni/CxxModuleWrapper.h>
#include <react/jni/JMessageQueueThread.h>
#include <memory>
#include "AudioNode.h"
#include "AudioParam.h"

Expand Down
4 changes: 0 additions & 4 deletions android/src/main/cpp/GainNode/GainNode.h
Original file line number Diff line number Diff line change
@@ -1,9 +1,5 @@
#pragma once

#include <fbjni/fbjni.h>
#include <react/jni/CxxModuleWrapper.h>
#include <react/jni/JMessageQueueThread.h>
#include <memory>
#include "AudioNode.h"
#include "AudioParam.h"

Expand Down
2 changes: 2 additions & 0 deletions android/src/main/cpp/OnLoad.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
#include "AudioContext.h"
#include "AudioNode.h"
#include "AudioParam.h"
#include "AudioBuffer.h"

using namespace audiocontext;

Expand All @@ -11,5 +12,6 @@ JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void *reserved)
AudioContext::registerNatives();
AudioNode::registerNatives();
AudioParam::registerNatives();
AudioBuffer::registerNatives();
});
}
4 changes: 0 additions & 4 deletions android/src/main/cpp/OscillatorNode/OscillatorNode.h
Original file line number Diff line number Diff line change
@@ -1,9 +1,5 @@
#pragma once

#include <fbjni/fbjni.h>
#include <react/jni/CxxModuleWrapper.h>
#include <react/jni/JMessageQueueThread.h>
#include <memory>
#include "AudioNode.h"
#include "AudioParam.h"

Expand Down
4 changes: 0 additions & 4 deletions android/src/main/cpp/StereoPannerNode/StereoPannerNode.h
Original file line number Diff line number Diff line change
@@ -1,9 +1,5 @@
#pragma once

#include <fbjni/fbjni.h>
#include <react/jni/CxxModuleWrapper.h>
#include <react/jni/JMessageQueueThread.h>
#include <memory>
#include "AudioNode.h"
#include "AudioParam.h"

Expand Down
Loading

0 comments on commit fec8936

Please sign in to comment.