Skip to content

Commit

Permalink
style: move installation process, fix indents
Browse files Browse the repository at this point in the history
  • Loading branch information
hubgan committed Jul 16, 2024
1 parent 8a03471 commit 5ac87cc
Show file tree
Hide file tree
Showing 10 changed files with 86 additions and 110 deletions.
54 changes: 22 additions & 32 deletions example/src/App.tsx
Original file line number Diff line number Diff line change
@@ -1,56 +1,46 @@
import React, { useCallback, useRef, useState } from 'react';
import { StyleSheet, View, Button, TextInput } from 'react-native';
import React, { useCallback, useEffect, useRef, useState } from 'react';
import { StyleSheet, View, Button, TextInput, Text } from 'react-native';
import { AudioContext, type OscillatorNode } from 'react-native-audio-context';

const BASE_FREQUENCY = 440;

const App: React.FC = () => {
const [frequency, setFrequency] = useState('440');
const [frequency, setFrequency] = useState(BASE_FREQUENCY);
const osc = useRef<OscillatorNode | null>(null);
const osc2 = useRef<OscillatorNode | null>(null);

const start = useCallback(() => {
useEffect(() => {
if (!osc.current) {
const context = new AudioContext();
osc.current = context.createOscillator(+frequency);
osc2.current = context.createOscillator(+frequency);
}

osc.current.start();
}, [frequency]);

const stop = useCallback(() => {
if (!osc.current) {
return;
}

osc.current.stop();
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);

const changeFrequency = useCallback(() => {
if (!osc.current) {
return;
useEffect(() => {
if (osc.current) {
osc.current.frequency = frequency;
}

osc.current.frequency = parseFloat(frequency);
}, [frequency]);

const getFrequency = useCallback(() => {
if (!osc.current) {
return;
}

console.log(osc.current.frequency);
const start = useCallback(() => {
osc.current?.start();
}, []);

return osc.current.frequency;
const stop = useCallback(() => {
osc.current?.stop();
}, []);

return (
<View style={styles.container}>
<Button title="Start1" onPress={start} />
<Button title="Stop1" onPress={stop} />
<Button title="Start" onPress={start} />
<Button title="Stop" onPress={stop} />
<TextInput
value={frequency}
onChangeText={(text) => setFrequency(text)}
value={frequency.toString()}
onChangeText={(text) => setFrequency(+text)}
/>
<Button title="Change frequency" onPress={changeFrequency} />
<Button title="Get current frequency" onPress={getFrequency} />
<Text>Current frequency: {frequency}</Text>
</View>
);
};
Expand Down
20 changes: 11 additions & 9 deletions ios/AudioContextModule.mm
Original file line number Diff line number Diff line change
Expand Up @@ -27,22 +27,24 @@ @implementation AudioContextModule
}
auto& runtime = *jsiRuntime;

auto createOscillator = [](jsi::Runtime& runtime, const jsi::Value& thisVal, const jsi::Value* args, size_t count) -> jsi::Value {
const float frequency = static_cast<float>(args[0].asNumber());

auto cppOscillatorHostObjectPtr = std::make_shared<audiocontext::OscillatorHostObject>(frequency);

const auto& jsiOscillatorHostObject = jsi::Object::createFromHostObject(runtime, cppOscillatorHostObjectPtr);

return jsi::Value(runtime, jsiOscillatorHostObject);
};

runtime.global().setProperty(
runtime,
jsi::String::createFromUtf8(runtime, "createOscillator"),
jsi::Function::createFromHostFunction(
runtime,
jsi::PropNameID::forUtf8(runtime, "createOscillator"),
0,
[](jsi::Runtime& runtime, const jsi::Value& thisVal, const jsi::Value* args, size_t count) -> jsi::Value {
const float frequency = static_cast<float>(args[0].asNumber());

auto cppOscillatorHostObjectPtr = std::make_shared<audiocontext::OscillatorHostObject>(frequency);

const auto& jsiOscillatorHostObject = jsi::Object::createFromHostObject(runtime, cppOscillatorHostObjectPtr);

return jsi::Value(runtime, jsiOscillatorHostObject);
}
createOscillator
)
);

Expand Down
24 changes: 12 additions & 12 deletions ios/PlatformOscillator.mm
Original file line number Diff line number Diff line change
Expand Up @@ -3,20 +3,20 @@

namespace audiocontext {

PlatformOscillator::PlatformOscillator(const float frequency) {
iosOscillator_ = [[IOSOscillator alloc] init:frequency];
}
PlatformOscillator::PlatformOscillator(const float frequency) {
iosOscillator_ = [[IOSOscillator alloc] init:frequency];
}

void PlatformOscillator::start() const {
[iosOscillator_ start];
}
void PlatformOscillator::start() const {
[iosOscillator_ start];
}

void PlatformOscillator::stop() const {
[iosOscillator_ stop];
}
void PlatformOscillator::stop() const {
[iosOscillator_ stop];
}

void PlatformOscillator::changeFrequency(const float frequency) const {
[iosOscillator_ changeFrequency:frequency];
}
void PlatformOscillator::changeFrequency(const float frequency) const {
[iosOscillator_ changeFrequency:frequency];
}

} // namespace audiocontext
6 changes: 1 addition & 5 deletions src/AudioContext.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,5 @@
import Oscillator from './Oscillator/Oscillator';

export class AudioContext {
constructor() {}

public createOscillator(frequency: number) {
return Oscillator(frequency);
return global.createOscillator(frequency);
}
}
37 changes: 0 additions & 37 deletions src/Oscillator/Oscillator.ts

This file was deleted.

1 change: 1 addition & 0 deletions src/Oscillator/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from './types';
6 changes: 0 additions & 6 deletions src/Oscillator/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,3 @@ export interface OscillatorNode {
stop(): void;
frequency: number;
}

// global func declaration for JSI functions
declare global {
function nativeCallSyncHook(): unknown;
var createOscillator: (frequency: number) => OscillatorNode;
}
6 changes: 5 additions & 1 deletion src/index.ts
Original file line number Diff line number Diff line change
@@ -1,2 +1,6 @@
export * from './Oscillator/types';
import { installACModule } from './utils/install';

installACModule();

export * from './Oscillator';
export * from './AudioContext';
8 changes: 8 additions & 0 deletions src/modules/global.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import type { IGainNode } from '../Gain';
import type { OscillatorNode } from '../Oscillator';

export declare global {
function nativeCallSyncHook(): unknown;
var createOscillator: (frequency: number) => OscillatorNode;
var createGain: (gain: number) => IGainNode;
}
34 changes: 26 additions & 8 deletions src/utils/install.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,20 @@
import { NativeModules, Platform } from 'react-native';

export function getAudioContextModule() {
export function installACModule() {
verifyExpoGo();

const AudioContextModule = getAudioContextModule();

verifyOnDevice(AudioContextModule);
installModule(AudioContextModule);
verifyInstallation();
}

function getAudioContextModule() {
const AudioContextModule = NativeModules.AudioContext;
if (AudioContextModule == null) {
let message =
'Failed to install react-native-audio-context: The native `Oscillator` Module could not be found.';
'Failed to install react-native-audio-context: The native `AudioContext` Module could not be found.';
message +=
'\n* Make sure react-native-audio-context is correctly autolinked (run `npx react-native config` to verify)';
if (Platform.OS === 'ios' || Platform.OS === 'macos') {
Expand All @@ -19,7 +29,7 @@ export function getAudioContextModule() {
return AudioContextModule;
}

export function verifyExpoGo() {
function verifyExpoGo() {
const ExpoConstants =
NativeModules.NativeUnimoduleProxy?.modulesConstants?.ExponentConstants;
if (ExpoConstants != null) {
Expand All @@ -33,18 +43,26 @@ export function verifyExpoGo() {
}
}

export function verifyOnDevice(Module: any) {
function verifyOnDevice(Module: any) {
if (global.nativeCallSyncHook == null || Module.install == null) {
throw new Error(
'Failed to install react-native-audio-context: React Native is not running on-device. Oscillator can only be used when synchronous method invocations (JSI) are possible. If you are using a remote debugger (e.g. Chrome), switch to an on-device debugger (e.g. Flipper) instead.'
'Failed to install react-native-audio-context: React Native is not running on-device. Audio Context can only be used when synchronous method invocations (JSI) are possible. If you are using a remote debugger (e.g. Chrome), switch to an on-device debugger (e.g. Flipper) instead.'
);
}
}

export function installModule(Module: any) {
function installModule(Module: any) {
const result = Module.install();
if (result !== true)
if (result !== true) {
throw new Error(
`Failed to install react-native-audio-context: The native Audio Context Module could not be installed! Looks like something went wrong when installing JSI bindings: ${result}`
);
}
}

function verifyInstallation() {
if (global.createOscillator == null)
throw new Error(
`Failed to install react-native-audio-context: The native Oscillator Module could not be installed! Looks like something went wrong when installing JSI bindings: ${result}`
'Failed to install react-native-audio-context, the native initializer private does not exist. Are you trying to use Audio Context from different JS Runtimes?'
);
}

0 comments on commit 5ac87cc

Please sign in to comment.