Skip to content

Commit

Permalink
Merge branch 'main' into feat/android/biquad-filter
Browse files Browse the repository at this point in the history
  • Loading branch information
Maciej Makowski committed Aug 20, 2024
2 parents 690dc9b + b31ef27 commit b787655
Show file tree
Hide file tree
Showing 35 changed files with 489 additions and 162 deletions.
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -76,3 +76,6 @@ android/keystores/debug.keystore

# generated by bob
lib/

# Android
.kotlin
12 changes: 6 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -61,17 +61,17 @@ npm install react-native-audio-context
</details>

<details>
<summary><b>AudioParam</b><br/> Android: ✅ <br />iOS: </summary>
<summary><b>AudioParam</b><br/> Android: ✅ <br />iOS: </summary>

| Method / Property | iOS | Android |
| ------------------------------ | --- | ------- |
| 🔹value |||
| 🔹defaultValue |||
| 🔹minValue |||
| 🔹maxValue |||
| 🔘setValueAtTime | ||
| 🔘linearRampToValueAtTime | ||
| 🔘exponentialRampToValueAtTime | ||
| 🔘setValueAtTime | ||
| 🔘linearRampToValueAtTime | ||
| 🔘exponentialRampToValueAtTime | ||

</details>

Expand All @@ -96,11 +96,11 @@ npm install react-native-audio-context
</details>

<details>
<summary><b>StereoPannerNode</b><br/> Android: ✅ <br />iOS: </summary>
<summary><b>StereoPannerNode</b><br/> Android: ✅ <br />iOS: </summary>

| Method / Property | iOS | Android |
| ----------------- | --- | ------- |
| 🔹pan | ||
| 🔹pan | ||

</details>

Expand Down
12 changes: 12 additions & 0 deletions cpp/AudioParam/ios/AudioParamWrapper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,18 @@ namespace audiocontext
double AudioParamWrapper::getDefaultValue() const {
return param_->getDefaultValue();
}

void AudioParamWrapper::setValueAtTime(double value, double startTime) {
return param_->setValueAtTime(value, startTime);
}

void AudioParamWrapper::linearRampToValueAtTime(double value, double endTime) {
return param_->linearRampToValueAtTime(value, endTime);
}

void AudioParamWrapper::exponentialRampToValueAtTime(double value, double endTime) {
return param_->exponentialRampToValueAtTime(value, endTime);
}
} // namespace audiocontext
#endif

4 changes: 2 additions & 2 deletions cpp/OscillatorNode/ios/OscillatorNodeWrapper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,11 @@ namespace audiocontext
}

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

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

void OscillatorNodeWrapper::setType(const std::string& type) {
Expand Down
1 change: 1 addition & 0 deletions example/src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ const App: React.FC = () => {
oscillatorRef.current.type = 'sine';

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

panRef.current = audioContextRef.current.createStereoPanner();
panRef.current.pan.value = INITIAL_PAN;
Expand Down
9 changes: 6 additions & 3 deletions example/src/sound-engines/Kick.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import {
AudioContext,
type OscillatorNode,
type GainNode,
type OscillatorNode,
} from 'react-native-audio-context';

import { Platform } from 'react-native';
import type { SoundEngine } from './SoundEngine';

export class Kick implements SoundEngine {
Expand All @@ -25,7 +25,10 @@ export class Kick implements SoundEngine {
this.gain = this.audioContext.createGain();
this.oscillator = this.audioContext.createOscillator();
this.oscillator.connect(this.gain);
this.gain.connect(this.audioContext.destination!);

if (Platform.OS === 'android') {
this.gain.connect(this.audioContext.destination!);
}
}

play(time: number) {
Expand Down
5 changes: 1 addition & 4 deletions ios/context/AudioContext.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,16 +11,13 @@
@interface AudioContext : NSObject

@property (nonatomic, strong) AVAudioEngine *audioEngine;
@property (nonatomic, strong) NSMutableArray<OscillatorNode *> *connectedOscillators;
@property (nonatomic, assign) uint64_t contextStartTime;
@property (nonatomic, assign) ContextStateEnum state;
@property (nonatomic, assign) double sampleRate;

- (instancetype)init;

- (void)connectOscillator:(OscillatorNode *)node;

- (void)processNodes;
- (void)clean;

- (double)getCurrentTime;

Expand Down
14 changes: 5 additions & 9 deletions ios/context/AudioContext.m
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,6 @@ - (instancetype)init {
return self;
}

self.connectedOscillators = [NSMutableArray array];

self.audioEngine = [[AVAudioEngine alloc] init];
self.audioEngine.mainMixerNode.outputVolume = 1;

Expand All @@ -19,14 +17,12 @@ - (instancetype)init {
return self;
}

- (void)connectOscillator:(OscillatorNode *)node {
[self.connectedOscillators addObject:node];
}

- (void)processNodes {
for (OscillatorNode *oscillator in self.connectedOscillators) {
[oscillator process:oscillator.buffer playerNode:oscillator.playerNode];
- (void)clean {
if (self.audioEngine.isRunning) {
[self.audioEngine stop];
}

self.audioEngine = nil;
}

- (double)getCurrentTime {
Expand Down
1 change: 1 addition & 0 deletions ios/context/IOSAudioContext.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ namespace audiocontext {
class IOSAudioContext {
public:
explicit IOSAudioContext();
~IOSAudioContext();
double getCurrentTime();
std::string getState();
double getSampleRate();
Expand Down
5 changes: 5 additions & 0 deletions ios/context/IOSAudioContext.mm
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,11 @@
audioContext_ = [[AudioContext alloc] init];
}

IOSAudioContext::~IOSAudioContext() {
[audioContext_ clean];
audioContext_ = nil;
}

double IOSAudioContext::getCurrentTime() {
return [audioContext_ getCurrentTime];
}
Expand Down
6 changes: 3 additions & 3 deletions ios/nodes/AudioNode/AudioNode.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,9 @@
@property (nonatomic, strong) NSMutableArray<AudioNode *> *connectedNodes;
@property (nonatomic, strong) AudioContext *context;

- (instancetype)init:(AudioContext *)context;
- (void)process:(AVAudioPCMBuffer *)buffer playerNode:(AVAudioPlayerNode *)playerNode;
- (void)deprocess:(AVAudioPCMBuffer *)buffer playerNode:(AVAudioPlayerNode *)playerNode nodeToDeprocess:(AudioNode *)node;
- (instancetype)initWithContext:(AudioContext *)context;
- (void)clean;
- (void)process:(float *)buffer frameCount:(AVAudioFrameCount)frameCount;
- (void)connect:(AudioNode *)node;
- (void)disconnect:(AudioNode *)node;
- (int)getNumberOfInputs;
Expand Down
38 changes: 7 additions & 31 deletions ios/nodes/AudioNode/AudioNode.m
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

@implementation AudioNode

- (instancetype)init:(AudioContext *)context {
- (instancetype)initWithContext:(AudioContext *)context {
if (self = [super init]) {
_connectedNodes = [NSMutableArray array];
_context = context;
Expand All @@ -12,15 +12,15 @@ - (instancetype)init:(AudioContext *)context {
return self;
}

- (void)process:(AVAudioPCMBuffer *)buffer playerNode:(AVAudioPlayerNode *)playerNode {
for (AudioNode *node in _connectedNodes) {
[node process:buffer playerNode:playerNode];
}
- (void)clean {
_context = nil;
[_connectedNodes removeAllObjects];
_connectedNodes = nil;
}

- (void)deprocess:(AVAudioPCMBuffer *)buffer playerNode:(AVAudioPlayerNode *)playerNode nodeToDeprocess:(AudioNode *)node {
- (void)process:(float *)buffer frameCount:(AVAudioFrameCount)frameCount {
for (AudioNode *node in _connectedNodes) {
[node deprocess:buffer playerNode:playerNode nodeToDeprocess:node];
[node process:buffer frameCount:frameCount];
}
}

Expand All @@ -33,34 +33,10 @@ - (void)connect:(AudioNode *)node {
- (void)disconnect:(AudioNode *)node {
NSUInteger index = [_connectedNodes indexOfObject:node];
if (index != NSNotFound) {
[self findNodesToDeprocess:node];
[_connectedNodes removeObjectAtIndex:index];
}
}

- (void)findNodesToDeprocess:(AudioNode *)node {
NSMutableArray<OscillatorNode *> *connectedOscillators = _context.connectedOscillators;
for (OscillatorNode *osNode in connectedOscillators) {
if ([self findNodesToDeprocessHelper:osNode]) {
[node deprocess:osNode.buffer playerNode:osNode.playerNode nodeToDeprocess:node];
}
}
}

- (Boolean)findNodesToDeprocessHelper:(AudioNode *)node {
if (node == self) {
return true;
}

for (AudioNode *cn in node.connectedNodes) {
if ([self findNodesToDeprocessHelper:cn]) {
return true;
}
}

return false;
}

- (int)getNumberOfInputs {
return _numberOfInputs;
}
Expand Down
1 change: 1 addition & 0 deletions ios/nodes/AudioNode/IOSAudioNode.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ typedef struct objc_object AudioNode;
namespace audiocontext {
class IOSAudioNode {
public:
~IOSAudioNode();
AudioNode *audioNode_;
virtual void connect(std::shared_ptr<IOSAudioNode> node);
virtual void disconnect(std::shared_ptr<IOSAudioNode> node);
Expand Down
5 changes: 5 additions & 0 deletions ios/nodes/AudioNode/IOSAudioNode.mm
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
#include <IOSAudioNode.h>

namespace audiocontext {
IOSAudioNode::~IOSAudioNode() {
[audioNode_ clean];
audioNode_ = nil;
}

void IOSAudioNode::connect(std::shared_ptr<IOSAudioNode> node) {
[audioNode_ connect:(node->audioNode_)];
}
Expand Down
3 changes: 2 additions & 1 deletion ios/nodes/GainNode/GainNode.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@

@property (nonatomic, strong) AudioParam *audioParam;

- (instancetype)init:(AudioContext *)context;
- (instancetype)initWithContext:(AudioContext *)context;
- (void)clean;

@end
28 changes: 10 additions & 18 deletions ios/nodes/GainNode/GainNode.m
Original file line number Diff line number Diff line change
Expand Up @@ -3,34 +3,26 @@

@implementation GainNode

- (instancetype)init:(AudioContext *)context {
if (self = [super init:context]) {
_audioParam = [[AudioParam alloc] init:context value:0.5 minValue:0 maxValue:1];
- (instancetype)initWithContext:(AudioContext *)context {
if (self = [super initWithContext:context]) {
_audioParam = [[AudioParam alloc] initWithContext:context value:0.5 minValue:0 maxValue:1];
self.numberOfInputs = 1;
self.numberOfOutputs = 1;
}

return self;
}

- (void)process:(AVAudioPCMBuffer *)buffer playerNode:(AVAudioPlayerNode *)playerNode {
playerNode.volume = [_audioParam getValue];

[super process:buffer playerNode:playerNode];
- (void)clean {
_audioParam = nil;
}

- (void)deprocess:(AVAudioPCMBuffer *)buffer playerNode:(AVAudioPlayerNode *)playerNode nodeToDeprocess:(AudioNode *)node {
if (node == self) {
playerNode.volume = 0.5;

// Deprocess all nodes connected to the disconnected node
for (AudioNode *cn in self.connectedNodes) {
[cn deprocess:buffer playerNode:playerNode nodeToDeprocess:cn];
}
} else {
// Continue searching for disconnected node
[super deprocess:buffer playerNode:playerNode nodeToDeprocess:node];
- (void)process:(float *)buffer frameCount:(AVAudioFrameCount)frameCount {
for (int frame = 0; frame < frameCount; frame++) {
buffer[frame] *= [_audioParam getValueAtTime:[self.context getCurrentTime]];
}

[super process:buffer frameCount:frameCount];
}

@end
1 change: 1 addition & 0 deletions ios/nodes/GainNode/IOSGainNode.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ namespace audiocontext {
class IOSGainNode : public IOSAudioNode {
public:
explicit IOSGainNode(std::shared_ptr<IOSAudioContext> context);
~IOSGainNode();
std::shared_ptr<IOSAudioParam> getAudioParam();

protected:
Expand Down
7 changes: 6 additions & 1 deletion ios/nodes/GainNode/IOSGainNode.mm
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,12 @@
namespace audiocontext {

IOSGainNode::IOSGainNode(std::shared_ptr<IOSAudioContext> context) {
audioNode_ = gainNode_ = [[GainNode alloc] init:context->audioContext_];
audioNode_ = gainNode_ = [[GainNode alloc] initWithContext:context->audioContext_];
}

IOSGainNode::~IOSGainNode() {
[gainNode_ clean];
audioNode_ = gainNode_ = nil;
}

std::shared_ptr<IOSAudioParam> IOSGainNode::getAudioParam() {
Expand Down
5 changes: 3 additions & 2 deletions ios/nodes/Oscillator/IOSOscillator.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,9 @@ namespace audiocontext {
class IOSOscillator : public IOSAudioNode {
public:
explicit IOSOscillator(std::shared_ptr<IOSAudioContext> context);
void start() const;
void stop() const;
~IOSOscillator();
void start(double time) const;
void stop(double time) const;
void setType(const std::string &type) const;
std::string getType() const;
std::shared_ptr<IOSAudioParam> getFrequencyParam();
Expand Down
15 changes: 10 additions & 5 deletions ios/nodes/Oscillator/IOSOscillator.mm
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,20 @@
namespace audiocontext {

IOSOscillator::IOSOscillator(std::shared_ptr<IOSAudioContext> context) {
audioNode_ = oscillatorNode_ = [[OscillatorNode alloc] init:context->audioContext_];
audioNode_ = oscillatorNode_ = [[OscillatorNode alloc] initWithContext:context->audioContext_];
}

void IOSOscillator::start() const {
[oscillatorNode_ start];
IOSOscillator::~IOSOscillator() {
[oscillatorNode_ clean];
audioNode_ = oscillatorNode_ = nil;
}

void IOSOscillator::stop() const {
[oscillatorNode_ stop];
void IOSOscillator::start(double time) const {
[oscillatorNode_ start:time];
}

void IOSOscillator::stop(double time) const {
[oscillatorNode_ stop:time];
}

void IOSOscillator::setType(const std::string &type) const {
Expand Down
Loading

0 comments on commit b787655

Please sign in to comment.