Skip to content

Commit

Permalink
Merge pull request #39 from software-mansion-labs/feat/android/gain-node
Browse files Browse the repository at this point in the history
Feat/android/gain node
  • Loading branch information
maciejmakowski2003 authored Jul 25, 2024
2 parents 2c94497 + 9749b8d commit 5f2694f
Show file tree
Hide file tree
Showing 36 changed files with 450 additions and 114 deletions.
10 changes: 8 additions & 2 deletions android/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ include_directories(
../cpp/AudioDestinationNode
../cpp/OscillatorNode
../cpp/AudioNode
../cpp/GainNode
src/main/cpp
../node_modules/react-native/ReactCommon/jsi
../node_modules/react-native/ReactAndroid/src/main/jni/react/jni
Expand All @@ -27,8 +28,9 @@ add_library(react-native-audio-context SHARED
src/main/cpp/OnLoad.cpp
src/main/cpp/AudioContext
src/main/cpp/OscillatorNode
src/main/cpp/AudioDestinationNode
src/main/cpp/AudioDestinationNode.h
src/main/cpp/AudioNode
src/main/cpp/GainNode

../cpp/AudioContext/AudioContextHostObject
../cpp/AudioContext/AudioContextWrapper.h
Expand All @@ -42,9 +44,13 @@ add_library(react-native-audio-context SHARED
../cpp/OscillatorNode/OscillatorNodeWrapper.h
../cpp/OscillatorNode/android/OscillatorNodeWrapper.cpp

../cpp/AudioNode/AudioNodeHostObject.h
../cpp/AudioNode/AudioNodeHostObject
../cpp/AudioNode/AudioNodeWrapper.h
../cpp/AudioNode/android/AudioNodeWrapper.cpp

../cpp/GainNode/GainNodeHostObject
../cpp/GainNode/GainNodeWrapper.h
../cpp/GainNode/android/GainNodeWrapper.cpp
)

find_package(ReactAndroid REQUIRED CONFIG)
Expand Down
11 changes: 10 additions & 1 deletion android/src/main/cpp/AudioContext.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ namespace audiocontext
return std::shared_ptr<OscillatorNode>(oscillatorCppInstance);
}

std::shared_ptr<AudioDestinationNode> AudioContext::getDestination()
std::shared_ptr<AudioDestinationNode> AudioContext::getDestination()
{
static const auto method = javaClassLocal()->getMethod<AudioDestinationNode()>("getDestination");
auto destination = method(javaObject_.get());
Expand All @@ -31,4 +31,13 @@ namespace audiocontext
return std::shared_ptr<AudioDestinationNode>(destinationCppInstance);
}

std::shared_ptr<GainNode> AudioContext::createGain()
{
static const auto method = javaClassLocal()->getMethod<GainNode()>("createGain");
auto gain = method(javaObject_.get());
auto gainCppInstance = gain->cthis();

return std::shared_ptr<GainNode>(gainCppInstance);
}

} // namespace audiocontext
4 changes: 3 additions & 1 deletion android/src/main/cpp/AudioContext.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,10 @@
#include <react/jni/JMessageQueueThread.h>
#include <memory>
#include "AudioContextHostObject.h"
#include "AudioContextWrapper.h"
#include "OscillatorNode.h"
#include "AudioDestinationNode.h"
#include "AudioContextWrapper.h"
#include "GainNode.h"

namespace audiocontext
{
Expand Down Expand Up @@ -39,6 +40,7 @@ namespace audiocontext

std::shared_ptr<OscillatorNode> createOscillator();
std::shared_ptr<AudioDestinationNode> getDestination();
std::shared_ptr<GainNode> createGain();

void install(jlong jsContext);

Expand Down
7 changes: 0 additions & 7 deletions android/src/main/cpp/AudioDestinationNode.cpp

This file was deleted.

4 changes: 1 addition & 3 deletions android/src/main/cpp/AudioDestinationNode.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,13 @@
#include <react/jni/CxxModuleWrapper.h>
#include <react/jni/JMessageQueueThread.h>
#include <memory>
#include "OscillatorNode.h"
#include "AudioNode.h"

namespace audiocontext {

using namespace facebook;
using namespace facebook::jni;

class OscillatorNode;

class AudioDestinationNode : public jni::HybridClass<AudioDestinationNode, AudioNode> {
public:
static auto constexpr kJavaDescriptor = "Lcom/audiocontext/nodes/AudioDestinationNode;";
Expand Down
16 changes: 16 additions & 0 deletions android/src/main/cpp/GainNode.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
#include "GainNode.h"

namespace audiocontext{

using namespace facebook::jni;

double GainNode::getGain(){
static const auto method = javaClassLocal()->getMethod<jdouble()>("getGain");
return method(javaObject_.get());
}

void GainNode::setGain(double gain){
static const auto method = javaClassLocal()->getMethod<void(jdouble)>("setGain");
method(javaObject_.get(), gain);
}
}
23 changes: 23 additions & 0 deletions android/src/main/cpp/GainNode.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
#pragma once

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

namespace audiocontext {

using namespace facebook;
using namespace facebook::jni;

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

double getGain();

void setGain(double gain);
};

} // namespace audiocontext
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package com.audiocontext.context

import com.audiocontext.nodes.AudioDestinationNode
import com.audiocontext.nodes.GainNode
import com.audiocontext.nodes.oscillator.OscillatorNode
import com.facebook.jni.HybridData

Expand All @@ -27,4 +28,8 @@ class AudioContext() : BaseAudioContext {
override fun createOscillator(): OscillatorNode {
return OscillatorNode(this)
}

override fun createGain(): GainNode {
return GainNode(this)
}
}
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
package com.audiocontext.context

import com.audiocontext.nodes.AudioDestinationNode
import com.audiocontext.nodes.GainNode
import com.audiocontext.nodes.oscillator.OscillatorNode

interface BaseAudioContext {
val sampleRate: Int
val destination: AudioDestinationNode

abstract fun createOscillator(): OscillatorNode
abstract fun createGain(): GainNode
}
Original file line number Diff line number Diff line change
@@ -1,10 +1,8 @@
package com.audiocontext.nodes

import android.media.AudioTrack
import android.util.Log
import com.audiocontext.context.BaseAudioContext
import com.facebook.jni.HybridData
import com.facebook.react.bridge.ReactApplicationContext


class AudioDestinationNode(context: BaseAudioContext): AudioNode(context) {
Expand Down
22 changes: 22 additions & 0 deletions android/src/main/java/com/audiocontext/nodes/GainNode.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package com.audiocontext.nodes

import android.media.AudioTrack
import com.audiocontext.context.BaseAudioContext
import com.facebook.jni.HybridData

class GainNode(context: BaseAudioContext): AudioNode(context) {
override val numberOfInputs: Int = 1
override val numberOfOutputs: Int = 1
private var gain: Double = 1.0
get() = field
set(value) {
field = value
}

private val mHybridData: HybridData? = initHybrid();

override fun process(buffer: ShortArray, audioTrack: AudioTrack) {
audioTrack.setVolume(gain.toFloat())
super.process(buffer, audioTrack)
}
}
8 changes: 8 additions & 0 deletions cpp/AudioContext/AudioContextHostObject.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,14 @@ namespace audiocontext {
return jsi::Object::createFromHostObject(runtime, destinationHostObject);
}

if(propName == "createGain") {
return jsi::Function::createFromHostFunction(runtime, propNameId, 0, [this](jsi::Runtime& runtime, const jsi::Value& thisValue, const jsi::Value* arguments, size_t count) -> jsi::Value {
auto gain = wrapper_->createGain();
auto gainHostObject = GainNodeHostObject::createFromWrapper(gain);
return jsi::Object::createFromHostObject(runtime, gainHostObject);
});
}

throw std::runtime_error("Not yet implemented!");
}

Expand Down
1 change: 1 addition & 0 deletions cpp/AudioContext/AudioContextHostObject.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
#include "AudioContextWrapper.h"
#include "OscillatorNodeHostObject.h"
#include "AudioDestinationNodeHostObject.h"
#include "GainNodeHostObject.h"

namespace audiocontext
{
Expand Down
4 changes: 3 additions & 1 deletion cpp/AudioContext/AudioContextWrapper.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
#include <utility>
#include "OscillatorNodeWrapper.h"
#include "AudioDestinationNodeWrapper.h"
#include "GainNodeWrapper.h"

#ifdef ANDROID
#include "AudioContext.h"
Expand All @@ -30,11 +31,12 @@ namespace audiocontext {
public:
#ifdef ANDROID
explicit AudioContextWrapper(
std::shared_ptr<AudioContext> audiocontext) : audiocontext_(audiocontext) {}
const std::shared_ptr<AudioContext> &audiocontext) : audiocontext_(audiocontext) {}
#else
explicit AudioContextWrapper() {}
#endif
std::shared_ptr<OscillatorNodeWrapper> createOscillator();
std::shared_ptr<AudioDestinationNodeWrapper> getDestination();
std::shared_ptr<GainNodeWrapper> createGain();
};
} // namespace audiocontext
5 changes: 5 additions & 0 deletions cpp/AudioContext/android/AudioContextWrapper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,5 +12,10 @@ namespace audiocontext {
auto destination = audiocontext_->getDestination();
return std::make_shared<AudioDestinationNodeWrapper>(destination);
}

std::shared_ptr<GainNodeWrapper> AudioContextWrapper::createGain() {
auto gain = audiocontext_->createGain();
return std::make_shared<GainNodeWrapper>(gain);
}
} // namespace audiocontext
#endif
5 changes: 2 additions & 3 deletions cpp/AudioDestinationNode/AudioDestinationNodeHostObject.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,21 +8,20 @@ namespace audiocontext {
using namespace facebook;

class AudioDestinationNodeWrapper;
class OscillatorNodeWrapper;

class AudioDestinationNodeHostObject : public AudioNodeHostObject {

protected:
std::shared_ptr<AudioDestinationNodeWrapper> wrapper_;

public:
explicit AudioDestinationNodeHostObject(std::shared_ptr<AudioDestinationNodeWrapper> wrapper): AudioNodeHostObject(wrapper), wrapper_(wrapper) {}
explicit AudioDestinationNodeHostObject(const std::shared_ptr<AudioDestinationNodeWrapper> &wrapper): AudioNodeHostObject(wrapper), wrapper_(wrapper) {}

jsi::Value get(jsi::Runtime& runtime, const jsi::PropNameID& name) override;
void set(jsi::Runtime& runtime, const jsi::PropNameID& name, const jsi::Value& value) override;
std::vector<jsi::PropNameID> getPropertyNames(jsi::Runtime& rt) override;

static std::shared_ptr<AudioDestinationNodeHostObject> createFromWrapper(std::shared_ptr<AudioDestinationNodeWrapper> wrapper) {
static std::shared_ptr<AudioDestinationNodeHostObject> createFromWrapper(const std::shared_ptr<AudioDestinationNodeWrapper> &wrapper) {
return std::make_shared<AudioDestinationNodeHostObject>(wrapper);
}
};
Expand Down
9 changes: 3 additions & 6 deletions cpp/AudioDestinationNode/AudioDestinationNodeWrapper.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

#ifdef ANDROID
#include "AudioDestinationNode.h"
#include "OscillatorNodeWrapper.h"
#include "AudioNodeWrapper.h"
#endif

#include "AudioNodeWrapper.h"
Expand All @@ -18,15 +18,12 @@ namespace audiocontext {
class AudioDestinationNodeWrapper: public AudioNodeWrapper {
#ifdef ANDROID
private:
friend class OscillatorNodeWrapper;

std::shared_ptr<AudioDestinationNode> destination_;
#endif

public:
#ifdef ANDROID
explicit AudioDestinationNodeWrapper(std::shared_ptr<AudioDestinationNode> destination) : AudioNodeWrapper(destination), destination_(destination) {}
explicit AudioDestinationNodeWrapper(const std::shared_ptr<AudioDestinationNode> &destination) : AudioNodeWrapper(destination), destination_(destination) {}
#else
public:
explicit AudioDestinationNodeWrapper() {}
#endif
};
Expand Down
45 changes: 45 additions & 0 deletions cpp/AudioNode/AudioNodeHostObject.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
#include "AudioNodeHostObject.h"

namespace audiocontext {
using namespace facebook;

std::vector<jsi::PropNameID> AudioNodeHostObject::getPropertyNames(jsi::Runtime& runtime) {
std::vector<jsi::PropNameID> propertyNames;
propertyNames.push_back(jsi::PropNameID::forAscii(runtime, "connect"));
propertyNames.push_back(jsi::PropNameID::forAscii(runtime, "disconnect"));
return propertyNames;
}

jsi::Value AudioNodeHostObject::get(jsi::Runtime& runtime, const jsi::PropNameID& propNameId) {
auto propName = propNameId.utf8(runtime);

if (propName == "connect")
{
return jsi::Function::createFromHostFunction(runtime, propNameId, 1, [this](jsi::Runtime &rt, const jsi::Value &thisValue, const jsi::Value *args, size_t count) -> jsi::Value
{
auto node = args[0].getObject(rt).getHostObject<AudioNodeHostObject>(rt);
wrapper_->connect(std::shared_ptr<AudioNodeHostObject>(node)->wrapper_);
return jsi::Value::undefined();
});
}

if (propName == "disconnect")
{
return jsi::Function::createFromHostFunction(runtime, propNameId, 1, [this](jsi::Runtime &rt, const jsi::Value &thisValue, const jsi::Value *args, size_t count) -> jsi::Value
{
auto node = args[0].getObject(rt).getHostObject<AudioNodeHostObject>(rt);
wrapper_->disconnect(std::shared_ptr<AudioNodeHostObject>(node)->wrapper_);
return jsi::Value::undefined();
});
}

throw std::runtime_error("Not yet implemented!");
}

void AudioNodeHostObject::set(jsi::Runtime& runtime, const jsi::PropNameID& propNameId, const jsi::Value& value) {
auto propName = propNameId.utf8(runtime);

throw std::runtime_error("Not yet implemented!");
}

}
8 changes: 6 additions & 2 deletions cpp/AudioNode/AudioNodeHostObject.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,14 @@ namespace audiocontext {

class AudioNodeHostObject : public jsi::HostObject {

public:
protected:
std::shared_ptr<AudioNodeWrapper> wrapper_;

public:
explicit AudioNodeHostObject(std::shared_ptr<AudioNodeWrapper> wrapper) : wrapper_(wrapper) {}
explicit AudioNodeHostObject(const std::shared_ptr<AudioNodeWrapper> &wrapper) : wrapper_(wrapper) {}

jsi::Value get(jsi::Runtime& runtime, const jsi::PropNameID& name) override;
void set(jsi::Runtime& runtime, const jsi::PropNameID& name, const jsi::Value& value) override;
std::vector<jsi::PropNameID> getPropertyNames(jsi::Runtime& rt) override;
};
} // namespace audiocontext
Loading

0 comments on commit 5f2694f

Please sign in to comment.