Skip to content

Commit

Permalink
Merge branch 'main' into feat/android/gain-node
Browse files Browse the repository at this point in the history
  • Loading branch information
maciejmakowski2003 authored Jul 25, 2024
2 parents 276d5f0 + 2c94497 commit 1266a6c
Show file tree
Hide file tree
Showing 33 changed files with 570 additions and 36 deletions.
8 changes: 4 additions & 4 deletions cpp/AudioContext/AudioContextHostObject.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,15 +20,15 @@ namespace audiocontext
std::shared_ptr<AudioContextWrapper> wrapper_;

public:
explicit AudioContextHostObject(const std::shared_ptr<AudioContextWrapper> &wrapper) : wrapper_(wrapper) {}

static void createAndInstallFromWrapper(const std::shared_ptr<AudioContextWrapper> &wrapper, jlong jsContext) {
explicit AudioContextHostObject(std::shared_ptr<AudioContextWrapper> wrapper) : wrapper_(wrapper) {}
#ifdef ANDROID
static void createAndInstallFromWrapper(const std::shared_ptr<AudioContextWrapper>& wrapper, jlong jsContext) {
auto runtime = reinterpret_cast<jsi::Runtime *>(jsContext);
auto hostObject = std::make_shared<AudioContextHostObject>(wrapper);
auto object = jsi::Object::createFromHostObject(*runtime, hostObject);
runtime->global().setProperty(*runtime, "__AudioContext", std::move(object));
}

#endif
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;
Expand Down
2 changes: 2 additions & 0 deletions cpp/AudioContext/AudioContextWrapper.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@

#ifdef ANDROID
#include "AudioContext.h"
#else
#include "OscillatorNodeHostObject.h"
#endif

namespace audiocontext {
Expand Down
2 changes: 2 additions & 0 deletions cpp/AudioContext/android/AudioContextWrapper.cpp
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
#ifdef ANDROID
#include "AudioContextWrapper.h"

namespace audiocontext {
Expand All @@ -17,3 +18,4 @@ namespace audiocontext {
return std::make_shared<GainNodeWrapper>(gain);
}
} // namespace audiocontext
#endif
Empty file removed cpp/AudioContext/ios/.keep
Empty file.
14 changes: 14 additions & 0 deletions cpp/AudioContext/ios/AudioContextWrapper.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
#ifndef ANDROID
#include "AudioContextWrapper.h"

namespace audiocontext {

std::shared_ptr<OscillatorNodeWrapper> AudioContextWrapper::createOscillator() {
return std::make_shared<OscillatorNodeWrapper>();
}

std::shared_ptr<AudioDestinationNodeWrapper> AudioContextWrapper::getDestination() {
throw std::runtime_error("[AudioContextHostObject::getDestination] Not yet implemented!");
}
} // namespace audiocontext
#endif
3 changes: 2 additions & 1 deletion cpp/AudioDestinationNode/AudioDestinationNodeWrapper.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,9 @@
#include "AudioNodeWrapper.h"
#endif

#include "AudioNodeWrapper.h"

namespace audiocontext {
using namespace facebook;

#ifdef ANDROID
class AudioDestinationNode;
Expand Down
2 changes: 0 additions & 2 deletions cpp/AudioNode/AudioNodeWrapper.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,6 @@
#endif

namespace audiocontext {
using namespace facebook;

class AudioNodeWrapper {
#ifdef ANDROID
protected:
Expand Down
3 changes: 3 additions & 0 deletions cpp/AudioNode/android/AudioNodeWrapper.cpp
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
#ifdef ANDROID
#include "AudioNodeWrapper.h"

namespace audiocontext {
Expand All @@ -10,3 +11,5 @@ namespace audiocontext {
node_->disconnect(node->node_);
}
}

#endif
Empty file removed cpp/AudioNode/ios/.keep
Empty file.
15 changes: 15 additions & 0 deletions cpp/AudioNode/ios/AudioNodeWrapper.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
#ifndef ANDROID
#include "AudioNodeWrapper.h"
#include "iostream"

namespace audiocontext {

void AudioNodeWrapper::connect(const std::shared_ptr<AudioNodeWrapper> node) const {
throw std::runtime_error("[AudioNodeWrapper::connect] Not yet implemented!");
}

void AudioNodeWrapper::disconnect(const std::shared_ptr<AudioNodeWrapper> node) const {
throw std::runtime_error("[AudioNodeWrapper::disconnect] Not yet implemented!");
}
}
#endif
12 changes: 7 additions & 5 deletions cpp/OscillatorNode/OscillatorNodeWrapper.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,25 +5,27 @@

#ifdef ANDROID
#include "OscillatorNode.h"
#else
#include "IOSOscillator.h"
#endif

namespace audiocontext {
using namespace facebook;

#ifdef ANDROID
class OscillatorNode;
#endif

class OscillatorNodeWrapper: public AudioNodeWrapper {
#ifdef ANDROID
private:
std::shared_ptr<OscillatorNode> oscillator_;
#else
std::shared_ptr<IOSOscillator> oscillator_;
#endif

public:
explicit OscillatorNodeWrapper(const std::shared_ptr<OscillatorNode> &oscillator) : AudioNodeWrapper(
oscillator), oscillator_(oscillator) {}
#else
public:
explicit OscillatorNodeWrapper() {}
explicit OscillatorNodeWrapper() : oscillator_(std::make_shared<IOSOscillator>()) {}
#endif
double getFrequency();
double getDetune();
Expand Down
2 changes: 2 additions & 0 deletions cpp/OscillatorNode/android/OscillatorNodeWrapper.cpp
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
#ifdef ANDROID
#include "OscillatorNodeWrapper.h"

namespace audiocontext {
Expand Down Expand Up @@ -34,3 +35,4 @@ namespace audiocontext {
oscillator_->setWaveType(type);
}
}
#endif
Empty file removed cpp/OscillatorNode/ios/.keep
Empty file.
38 changes: 38 additions & 0 deletions cpp/OscillatorNode/ios/OscillatorNodeWrapper.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
#ifndef ANDROID
#include "OscillatorNodeWrapper.h"

namespace audiocontext {

double OscillatorNodeWrapper::getFrequency() {
return oscillator_->getFrequency();
}

double OscillatorNodeWrapper::getDetune() {
return oscillator_->getDetune();
}

std::string OscillatorNodeWrapper::getType() {
return oscillator_->getType();
}

void OscillatorNodeWrapper::start(double time) {
oscillator_->start();
}

void OscillatorNodeWrapper::stop(double time) {
oscillator_->stop();
}

void OscillatorNodeWrapper::setFrequency(double frequency) {
oscillator_->changeFrequency(frequency);
}

void OscillatorNodeWrapper::setDetune(double detune) {
oscillator_->changeDetune(detune);
}

void OscillatorNodeWrapper::setType(const std::string& type) {
oscillator_->setType(type);
}
}
#endif
17 changes: 9 additions & 8 deletions example/src/App.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/* eslint-disable react/react-in-jsx-scope */
import { Button, StyleSheet, Text, View } from 'react-native';
import { Button, Platform, StyleSheet, Text, View } from 'react-native';
import { useRef, useState, useEffect } from 'react';
import { Slider } from '@miblanchard/react-native-slider';

Expand All @@ -9,12 +9,12 @@ import {
type Gain,
} from 'react-native-audio-context';

const App = () => {
const App: React.FC = () => {
const [isPlaying, setIsPlaying] = useState<boolean>(false);
const [gain, setGain] = useState<number>(1.0);
const [frequency, setFrequency] = useState<number>(440);
const [detune, setDetune] = useState<number>(0);

Check failure on line 17 in example/src/App.tsx

View workflow job for this annotation

GitHub Actions / lint

Delete `··`
const audioContextRef = useRef<AudioContext | null>(null);
const oscillatorRef = useRef<Oscillator | null>(null);
const gainRef = useRef<Gain | null>(null);
Expand All @@ -29,10 +29,11 @@ const App = () => {

gainRef.current = audioContextRef.current.createGain();
gainRef.current.gain = gain;

const destination = audioContextRef.current.destination;
oscillatorRef.current.connect(gainRef.current);
gainRef.current.connect(destination);

Check failure on line 32 in example/src/App.tsx

View workflow job for this annotation

GitHub Actions / lint

Delete `······`
if (Platform.OS === 'android') {
const destination = audioContextRef.current.destination;
oscillatorRef.current.connect(destination!);
}
};

const handleGainChange = (value: number[]) => {
Expand All @@ -58,7 +59,7 @@ const App = () => {
oscillatorRef.current.detune = newValue;
}
};

Check failure on line 62 in example/src/App.tsx

View workflow job for this annotation

GitHub Actions / lint

Delete `··`
useEffect(() => {
return () => {
oscillatorRef.current?.stop(0);
Expand Down
5 changes: 5 additions & 0 deletions ios/AudioContextModule.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
#import <React/RCTBridgeModule.h>

@interface AudioContextModule : NSObject <RCTBridgeModule>

@end
14 changes: 8 additions & 6 deletions ios/JSIExampleModule.mm → ios/AudioContextModule.mm
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
#import "JSIExampleModule.h"
#import "AudioContextModule.h"

#import <React/RCTBridge+Private.h>
#import <React/RCTUtils.h>
#import <jsi/jsi.h>

#import "../cpp/JSIExampleHostObject.h"
#import "../cpp/AudioContext/AudioContextHostObject.h"
#import "../cpp/AudioContext/AudioContextWrapper.h"

@implementation JSIExampleModule
@implementation AudioContextModule

RCT_EXPORT_MODULE(JSIExample)
RCT_EXPORT_MODULE(AudioContextModule)

RCT_EXPORT_BLOCKING_SYNCHRONOUS_METHOD(install)
{
Expand All @@ -27,9 +28,10 @@ @implementation JSIExampleModule
}
auto& runtime = *jsiRuntime;

auto hostObject = std::make_shared<example::JSIExampleHostObject>();
auto wrapper = std::make_shared<audiocontext::AudioContextWrapper>();
auto hostObject = std::make_shared<audiocontext::AudioContextHostObject>(wrapper);
auto object = jsi::Object::createFromHostObject(runtime, hostObject);
runtime.global().setProperty(runtime, "__JSIExampleProxy", std::move(object));
runtime.global().setProperty(runtime, "__AudioContext", std::move(object));

NSLog(@"Successfully installed JSI bindings for react-native-audio-context!");
return @true;
Expand Down
5 changes: 0 additions & 5 deletions ios/JSIExampleModule.h

This file was deleted.

14 changes: 14 additions & 0 deletions ios/nodes/AudioNode/AudioNode.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
#import <Foundation/Foundation.h>
#import <AVFoundation/AVFoundation.h>

@interface AudioNode : NSObject

@property (nonatomic, readonly) NSInteger numberOfInputs;
@property (nonatomic, readonly) NSInteger numberOfOutputs;
@property (nonatomic, strong) NSMutableArray<AudioNode *> *connectedNodes;

- (void)connect:(AudioNode *)node;
- (void)disconnect;
- (void)process;

@end
29 changes: 29 additions & 0 deletions ios/nodes/AudioNode/AudioNode.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
#import "AudioNode.h"

@implementation AudioNode

- (instancetype)init {
if (self = [super init]) {
_connectedNodes = [NSMutableArray array];
}

return self;
}

- (void)connect:(AudioNode *)node {
if (self.numberOfOutputs > 0) {
[self.connectedNodes addObject:node];
}
}

- (void)disconnect {
[self.connectedNodes removeAllObjects];
}

- (void)process {
for (AudioNode *node in self.connectedNodes) {
[node process];
}
}

@end
8 changes: 8 additions & 0 deletions ios/nodes/AudioScheduledSourceNode/AudioScheduledSourceNode.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
#import "AudioNode.h"

@interface AudioScheduledSourceNode : AudioNode

- (void)start;
- (void)stop;

@end
20 changes: 20 additions & 0 deletions ios/nodes/AudioScheduledSourceNode/AudioScheduledSourceNode.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
#import "AudioScheduledSourceNode.h"

@implementation AudioScheduledSourceNode

- (void)start {
NSLog(@"Attempting to call `start` on a base class where it is not implemented. You must override `start` in a subclass.");
@throw [NSException exceptionWithName:NSInternalInconsistencyException
reason:[NSString stringWithFormat:@"You must override %@ in a subclass", NSStringFromSelector(_cmd)]
userInfo:nil];
}

- (void)stop {
NSLog(@"Attempting to call `stop` on a base class where it is not implemented. You must override `stop` in a subclass.");
@throw [NSException exceptionWithName:NSInternalInconsistencyException
reason:[NSString stringWithFormat:@"You must override %@ in a subclass", NSStringFromSelector(_cmd)]
userInfo:nil];
}

@end

27 changes: 27 additions & 0 deletions ios/nodes/Oscillator/IOSOscillator.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
#pragma once

#ifdef __OBJC__ // when compiled as Objective-C++
#import <OscillatorNode.h>
#else // when compiled as C++
typedef struct objc_object OscillatorNode;
#endif // __OBJC__

#include <string>

namespace audiocontext {
class IOSOscillator {
public:
explicit IOSOscillator();
void start() const;
void stop() const;
void changeFrequency(const float frequency) const;
float getFrequency() const;
void changeDetune(const float detune) const;
float getDetune() const;
void setType(const std::string &type) const;
std::string getType() const;

protected:
OscillatorNode *OscillatorNode_;
};
} // namespace audiocontext
Loading

0 comments on commit 1266a6c

Please sign in to comment.