expo-juce 0.2.10 → 0.2.13
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/android/src/main/java/expo/modules/juce/ExpoJuceModule.kt +51 -0
- package/android/src/main/java/expo/modules/juce/ExpoJuceView.kt +7 -0
- package/build/ExpoJuce.types.d.ts +4 -0
- package/build/ExpoJuce.types.d.ts.map +1 -1
- package/build/ExpoJuce.types.js.map +1 -1
- package/build/index.d.ts +15 -2
- package/build/index.d.ts.map +1 -1
- package/build/index.js +43 -0
- package/build/index.js.map +1 -1
- package/ios/ExpoJuceBridge.h +21 -0
- package/ios/ExpoJuceBridge.m +58 -1
- package/ios/ExpoJuceModule.swift +75 -1
- package/ios/JuceConfig.h +3 -0
- package/ios/JuceToneGenerator.h +21 -0
- package/ios/JuceToneGenerator.mm +268 -22
- package/ios/juce_modules/juce_audio_basics/midi/ump/juce_UMPMidi1ToBytestreamTranslator.h +227 -0
- package/ios/juce_modules/juce_audio_basics/midi/ump/juce_UMP_test.cpp +1018 -0
- package/ios/juce_modules/juce_audio_basics/utilities/juce_ADSR_test.cpp +269 -0
- package/ios/juce_modules/juce_core/containers/juce_Enumerate_test.cpp +138 -0
- package/ios/juce_modules/juce_core/containers/juce_FixedSizeFunction_test.cpp +373 -0
- package/ios/juce_modules/juce_core/containers/juce_HashMap_test.cpp +290 -0
- package/ios/juce_modules/juce_core/containers/juce_ListenerList_test.cpp +504 -0
- package/ios/juce_modules/juce_core/containers/juce_Optional_test.cpp +640 -0
- package/ios/juce_modules/juce_core/javascript/juce_JSONSerialisation_test.cpp +629 -0
- package/ios/juce_modules/juce_core/maths/juce_MathsFunctions_test.cpp +555 -0
- package/ios/juce_modules/juce_core/memory/juce_SharedResourcePointer_test.cpp +111 -0
- package/ios/juce_modules/juce_core/misc/juce_EnumHelpers_test.cpp +104 -0
- package/ios/juce_modules/juce_core/native/juce_ObjCHelpers_mac_test.mm +121 -0
- package/ios/juce_modules/juce_core/unit_tests/juce_UnitTest.cpp +298 -0
- package/ios/juce_modules/juce_core/unit_tests/juce_UnitTest.h +464 -0
- package/ios/juce_modules/juce_core/unit_tests/juce_UnitTestCategories.h +65 -0
- package/ios/juce_modules/juce_data_structures/values/juce_ValueTreePropertyWithDefault_test.cpp +106 -0
- package/ios/juce_modules/juce_dsp/containers/juce_AudioBlock_test.cpp +506 -0
- package/ios/juce_modules/juce_dsp/containers/juce_SIMDRegister_test.cpp +886 -0
- package/ios/juce_modules/juce_dsp/frequency/juce_Convolution_test.cpp +587 -0
- package/ios/juce_modules/juce_dsp/frequency/juce_FFT_test.cpp +224 -0
- package/ios/juce_modules/juce_dsp/maths/juce_LogRampedValue_test.cpp +102 -0
- package/ios/juce_modules/juce_dsp/maths/juce_Matrix_test.cpp +179 -0
- package/ios/juce_modules/juce_dsp/processors/juce_FIRFilter_test.cpp +228 -0
- package/ios/juce_modules/juce_dsp/processors/juce_ProcessorChain_test.cpp +173 -0
- package/package.json +2 -2
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
package expo.modules.juce
|
|
2
|
+
|
|
3
|
+
import expo.modules.kotlin.modules.Module
|
|
4
|
+
import expo.modules.kotlin.modules.ModuleDefinition
|
|
5
|
+
|
|
6
|
+
class ExpoJuceModule : Module() {
|
|
7
|
+
// Each module class must implement the definition function. The definition consists of components
|
|
8
|
+
// that describes the module's functionality and behavior.
|
|
9
|
+
// See https://docs.expo.dev/modules/module-api for more details about available components.
|
|
10
|
+
override fun definition() = ModuleDefinition {
|
|
11
|
+
// Sets the name of the module that JavaScript code will use to refer to the module. Takes a string as an argument.
|
|
12
|
+
// Can be inferred from module's class name, but it's recommended to set it explicitly for clarity.
|
|
13
|
+
// The module will be accessible from `requireNativeModule('ExpoJuce')` in JavaScript.
|
|
14
|
+
Name("ExpoJuce")
|
|
15
|
+
|
|
16
|
+
// Sets constant properties on the module. Can take a dictionary or a closure that returns a dictionary.
|
|
17
|
+
Constants(
|
|
18
|
+
"PI" to Math.PI
|
|
19
|
+
)
|
|
20
|
+
|
|
21
|
+
// Defines event names that the module can send to JavaScript.
|
|
22
|
+
Events("onChange")
|
|
23
|
+
|
|
24
|
+
// Defines a JavaScript synchronous function that runs the native code on the JavaScript thread.
|
|
25
|
+
Function("hello") {
|
|
26
|
+
"Hello world! 👋"
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
Function("getApiKey") {
|
|
30
|
+
return@Function "api-key"
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
// Defines a JavaScript function that always returns a Promise and whose native code
|
|
34
|
+
// is by default dispatched on the different thread than the JavaScript runtime runs on.
|
|
35
|
+
AsyncFunction("setValueAsync") { value: String ->
|
|
36
|
+
// Send an event to JavaScript.
|
|
37
|
+
sendEvent("onChange", mapOf(
|
|
38
|
+
"value" to value
|
|
39
|
+
))
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
// Enables the module to be used as a native view. Definition components that are accepted as part of
|
|
43
|
+
// the view definition: Prop, Events.
|
|
44
|
+
View(ExpoJuceView::class) {
|
|
45
|
+
// Defines a setter for the `name` prop.
|
|
46
|
+
Prop("name") { view: ExpoJuceView, prop: String ->
|
|
47
|
+
println(prop)
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ExpoJuce.types.d.ts","sourceRoot":"","sources":["../src/ExpoJuce.types.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,kBAAkB,GAAG;IAC/B,KAAK,EAAE,MAAM,CAAC;CACf,CAAC;AAEF,MAAM,MAAM,iBAAiB,GAAG;IAC9B,IAAI,EAAE,MAAM,CAAC;CACd,CAAC"}
|
|
1
|
+
{"version":3,"file":"ExpoJuce.types.d.ts","sourceRoot":"","sources":["../src/ExpoJuce.types.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,kBAAkB,GAAG;IAC/B,KAAK,EAAE,MAAM,CAAC;CACf,CAAC;AAEF,MAAM,MAAM,gBAAgB,GAAG;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,EAAE,MAAM,CAAC;CACb,CAAC;AAEF,MAAM,MAAM,iBAAiB,GAAG;IAC9B,IAAI,EAAE,MAAM,CAAC;CACd,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ExpoJuce.types.js","sourceRoot":"","sources":["../src/ExpoJuce.types.ts"],"names":[],"mappings":"","sourcesContent":["export type ChangeEventPayload = {\n value: string;\n};\n\nexport type ExpoJuceViewProps = {\n name: string;\n};\n"]}
|
|
1
|
+
{"version":3,"file":"ExpoJuce.types.js","sourceRoot":"","sources":["../src/ExpoJuce.types.ts"],"names":[],"mappings":"","sourcesContent":["export type ChangeEventPayload = {\n value: string;\n};\n\nexport type BeatEventPayload = {\n beat: number;\n bpm: number;\n};\n\nexport type ExpoJuceViewProps = {\n name: string;\n};\n"]}
|
package/build/index.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Subscription } from 'expo-modules-core';
|
|
2
2
|
import ExpoJuceView from './ExpoJuceView';
|
|
3
|
-
import { ChangeEventPayload, ExpoJuceViewProps } from './ExpoJuce.types';
|
|
3
|
+
import { ChangeEventPayload, BeatEventPayload, ExpoJuceViewProps } from './ExpoJuce.types';
|
|
4
4
|
export declare const PI: any;
|
|
5
5
|
export declare function hello(): string;
|
|
6
6
|
export declare function playTone(frequency: number, duration: number): string;
|
|
@@ -10,8 +10,21 @@ export declare function setWaveform(waveform: 'sine' | 'square' | 'saw' | 'trian
|
|
|
10
10
|
export declare function setHarmonicLevels(levels: number[]): void;
|
|
11
11
|
export declare function noteOn(): void;
|
|
12
12
|
export declare function noteOff(): void;
|
|
13
|
+
export declare function setAttack(ms: number): void;
|
|
14
|
+
export declare function setRelease(ms: number): void;
|
|
15
|
+
export declare function setFilterCutoff(hz: number): void;
|
|
16
|
+
export declare function setFilterResonance(q: number): void;
|
|
17
|
+
export declare function setDetune(cents: number): void;
|
|
13
18
|
export declare function setDSPValue(param: string, value: number): void;
|
|
19
|
+
export declare function startTransport(): void;
|
|
20
|
+
export declare function stopTransport(): void;
|
|
21
|
+
export declare function setTempo(bpm: number): void;
|
|
22
|
+
export declare function setTransportPosition(beat: number): void;
|
|
23
|
+
export declare function getTransportPosition(): number;
|
|
24
|
+
export declare function getTempo(): number;
|
|
25
|
+
export declare function isTransportPlaying(): boolean;
|
|
14
26
|
export declare function setValueAsync(value: string): Promise<any>;
|
|
15
27
|
export declare function addChangeListener(listener: (event: ChangeEventPayload) => void): Subscription;
|
|
16
|
-
export
|
|
28
|
+
export declare function addBeatListener(listener: (event: BeatEventPayload) => void): Subscription;
|
|
29
|
+
export { ExpoJuceView, ExpoJuceViewProps, ChangeEventPayload, BeatEventPayload };
|
|
17
30
|
//# sourceMappingURL=index.d.ts.map
|
package/build/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAoC,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAGnF,OAAO,YAAY,MAAM,gBAAgB,CAAC;AAC1C,OAAO,EAAE,kBAAkB,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAoC,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAGnF,OAAO,YAAY,MAAM,gBAAgB,CAAC;AAC1C,OAAO,EAAE,kBAAkB,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AAE3F,eAAO,MAAM,EAAE,KAAoB,CAAC;AAEpC,wBAAgB,KAAK,IAAI,MAAM,CAE9B;AAID,wBAAgB,QAAQ,CAAC,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,CAEpE;AAED,wBAAgB,YAAY,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,CAEpD;AAED,wBAAgB,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAE5C;AAED,wBAAgB,WAAW,CAAC,QAAQ,EAAE,MAAM,GAAG,QAAQ,GAAG,KAAK,GAAG,UAAU,GAAG,IAAI,CAElF;AAED,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,IAAI,CAExD;AAED,wBAAgB,MAAM,IAAI,IAAI,CAE7B;AAED,wBAAgB,OAAO,IAAI,IAAI,CAE9B;AAID,wBAAgB,SAAS,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI,CAE1C;AAED,wBAAgB,UAAU,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI,CAE3C;AAED,wBAAgB,eAAe,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI,CAEhD;AAED,wBAAgB,kBAAkB,CAAC,CAAC,EAAE,MAAM,GAAG,IAAI,CAElD;AAED,wBAAgB,SAAS,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAE7C;AAED,wBAAgB,WAAW,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI,CAE9D;AAID,wBAAgB,cAAc,IAAI,IAAI,CAErC;AAED,wBAAgB,aAAa,IAAI,IAAI,CAEpC;AAED,wBAAgB,QAAQ,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAE1C;AAED,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAEvD;AAED,wBAAgB,oBAAoB,IAAI,MAAM,CAE7C;AAED,wBAAgB,QAAQ,IAAI,MAAM,CAEjC;AAED,wBAAgB,kBAAkB,IAAI,OAAO,CAE5C;AAID,wBAAsB,aAAa,CAAC,KAAK,EAAE,MAAM,gBAEhD;AAID,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,CAAC,KAAK,EAAE,kBAAkB,KAAK,IAAI,GAAG,YAAY,CAE7F;AAED,wBAAgB,eAAe,CAAC,QAAQ,EAAE,CAAC,KAAK,EAAE,gBAAgB,KAAK,IAAI,GAAG,YAAY,CAEzF;AAED,OAAO,EAAE,YAAY,EAAE,iBAAiB,EAAE,kBAAkB,EAAE,gBAAgB,EAAE,CAAC"}
|
package/build/index.js
CHANGED
|
@@ -5,6 +5,7 @@ export const PI = ExpoJuceModule.PI;
|
|
|
5
5
|
export function hello() {
|
|
6
6
|
return ExpoJuceModule.hello();
|
|
7
7
|
}
|
|
8
|
+
// ── Synth ───────────────────────────────────────────────────────────
|
|
8
9
|
export function playTone(frequency, duration) {
|
|
9
10
|
return ExpoJuceModule.playTone(frequency, duration);
|
|
10
11
|
}
|
|
@@ -26,9 +27,48 @@ export function noteOn() {
|
|
|
26
27
|
export function noteOff() {
|
|
27
28
|
ExpoJuceModule.noteOff();
|
|
28
29
|
}
|
|
30
|
+
// ── DSP Params ──────────────────────────────────────────────────────
|
|
31
|
+
export function setAttack(ms) {
|
|
32
|
+
ExpoJuceModule.setAttack(ms);
|
|
33
|
+
}
|
|
34
|
+
export function setRelease(ms) {
|
|
35
|
+
ExpoJuceModule.setRelease(ms);
|
|
36
|
+
}
|
|
37
|
+
export function setFilterCutoff(hz) {
|
|
38
|
+
ExpoJuceModule.setFilterCutoff(hz);
|
|
39
|
+
}
|
|
40
|
+
export function setFilterResonance(q) {
|
|
41
|
+
ExpoJuceModule.setFilterResonance(q);
|
|
42
|
+
}
|
|
43
|
+
export function setDetune(cents) {
|
|
44
|
+
ExpoJuceModule.setDetune(cents);
|
|
45
|
+
}
|
|
29
46
|
export function setDSPValue(param, value) {
|
|
30
47
|
ExpoJuceModule.setDSPValue(param, value);
|
|
31
48
|
}
|
|
49
|
+
// ── Transport ───────────────────────────────────────────────────────
|
|
50
|
+
export function startTransport() {
|
|
51
|
+
ExpoJuceModule.startTransport();
|
|
52
|
+
}
|
|
53
|
+
export function stopTransport() {
|
|
54
|
+
ExpoJuceModule.stopTransport();
|
|
55
|
+
}
|
|
56
|
+
export function setTempo(bpm) {
|
|
57
|
+
ExpoJuceModule.setTempo(bpm);
|
|
58
|
+
}
|
|
59
|
+
export function setTransportPosition(beat) {
|
|
60
|
+
ExpoJuceModule.setTransportPosition(beat);
|
|
61
|
+
}
|
|
62
|
+
export function getTransportPosition() {
|
|
63
|
+
return ExpoJuceModule.getTransportPosition();
|
|
64
|
+
}
|
|
65
|
+
export function getTempo() {
|
|
66
|
+
return ExpoJuceModule.getTempo();
|
|
67
|
+
}
|
|
68
|
+
export function isTransportPlaying() {
|
|
69
|
+
return ExpoJuceModule.isTransportPlaying();
|
|
70
|
+
}
|
|
71
|
+
// ── Events ──────────────────────────────────────────────────────────
|
|
32
72
|
export async function setValueAsync(value) {
|
|
33
73
|
return await ExpoJuceModule.setValueAsync(value);
|
|
34
74
|
}
|
|
@@ -36,5 +76,8 @@ const emitter = new EventEmitter(ExpoJuceModule ?? NativeModulesProxy.ExpoJuce);
|
|
|
36
76
|
export function addChangeListener(listener) {
|
|
37
77
|
return emitter.addListener('onChange', listener);
|
|
38
78
|
}
|
|
79
|
+
export function addBeatListener(listener) {
|
|
80
|
+
return emitter.addListener('onBeat', listener);
|
|
81
|
+
}
|
|
39
82
|
export { ExpoJuceView };
|
|
40
83
|
//# sourceMappingURL=index.js.map
|
package/build/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,YAAY,EAAgB,MAAM,mBAAmB,CAAC;AAEnF,OAAO,cAAc,MAAM,kBAAkB,CAAC;AAC9C,OAAO,YAAY,MAAM,gBAAgB,CAAC;AAG1C,MAAM,CAAC,MAAM,EAAE,GAAG,cAAc,CAAC,EAAE,CAAC;AAEpC,MAAM,UAAU,KAAK;IACnB,OAAO,cAAc,CAAC,KAAK,EAAE,CAAC;AAChC,CAAC;AAED,MAAM,UAAU,QAAQ,CAAC,SAAiB,EAAE,QAAgB;IAC1D,OAAO,cAAc,CAAC,QAAQ,CAAC,SAAS,EAAE,QAAQ,CAAC,CAAC;AACtD,CAAC;AAED,MAAM,UAAU,YAAY,CAAC,SAAiB;IAC5C,cAAc,CAAC,YAAY,CAAC,SAAS,CAAC,CAAC;AACzC,CAAC;AAED,MAAM,UAAU,QAAQ,CAAC,KAAa;IACpC,cAAc,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;AACjC,CAAC;AAED,MAAM,UAAU,WAAW,CAAC,QAAgD;IAC1E,cAAc,CAAC,WAAW,CAAC,QAAQ,CAAC,CAAC;AACvC,CAAC;AAED,MAAM,UAAU,iBAAiB,CAAC,MAAgB;IAChD,cAAc,CAAC,iBAAiB,CAAC,MAAM,CAAC,CAAC;AAC3C,CAAC;AAED,MAAM,UAAU,MAAM;IACpB,cAAc,CAAC,MAAM,EAAE,CAAC;AAC1B,CAAC;AAED,MAAM,UAAU,OAAO;IACrB,cAAc,CAAC,OAAO,EAAE,CAAC;AAC3B,CAAC;AAED,MAAM,UAAU,WAAW,CAAC,KAAa,EAAE,KAAa;IACtD,cAAc,CAAC,WAAW,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC;AAC3C,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,aAAa,CAAC,KAAa;IAC/C,OAAO,MAAM,cAAc,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC;AACnD,CAAC;AAED,MAAM,OAAO,GAAG,IAAI,YAAY,CAAC,cAAc,IAAI,kBAAkB,CAAC,QAAQ,CAAC,CAAC;AAEhF,MAAM,UAAU,iBAAiB,CAAC,QAA6C;IAC7E,OAAO,OAAO,CAAC,WAAW,CAAqB,UAAU,EAAE,QAAQ,CAAC,CAAC;AACvE,CAAC;AAED,OAAO,EAAE,YAAY,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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","sourcesContent":["import { NativeModulesProxy, EventEmitter, Subscription } from 'expo-modules-core';\n\nimport ExpoJuceModule from './ExpoJuceModule';\nimport ExpoJuceView from './ExpoJuceView';\nimport { ChangeEventPayload, BeatEventPayload, ExpoJuceViewProps } from './ExpoJuce.types';\n\nexport const PI = ExpoJuceModule.PI;\n\nexport function hello(): string {\n return ExpoJuceModule.hello();\n}\n\n// ── Synth ───────────────────────────────────────────────────────────\n\nexport function playTone(frequency: number, duration: number): string {\n return ExpoJuceModule.playTone(frequency, duration);\n}\n\nexport function setFrequency(frequency: number): void {\n ExpoJuceModule.setFrequency(frequency);\n}\n\nexport function setLevel(level: number): void {\n ExpoJuceModule.setLevel(level);\n}\n\nexport function setWaveform(waveform: 'sine' | 'square' | 'saw' | 'triangle'): void {\n ExpoJuceModule.setWaveform(waveform);\n}\n\nexport function setHarmonicLevels(levels: number[]): void {\n ExpoJuceModule.setHarmonicLevels(levels);\n}\n\nexport function noteOn(): void {\n ExpoJuceModule.noteOn();\n}\n\nexport function noteOff(): void {\n ExpoJuceModule.noteOff();\n}\n\n// ── DSP Params ──────────────────────────────────────────────────────\n\nexport function setAttack(ms: number): void {\n ExpoJuceModule.setAttack(ms);\n}\n\nexport function setRelease(ms: number): void {\n ExpoJuceModule.setRelease(ms);\n}\n\nexport function setFilterCutoff(hz: number): void {\n ExpoJuceModule.setFilterCutoff(hz);\n}\n\nexport function setFilterResonance(q: number): void {\n ExpoJuceModule.setFilterResonance(q);\n}\n\nexport function setDetune(cents: number): void {\n ExpoJuceModule.setDetune(cents);\n}\n\nexport function setDSPValue(param: string, value: number): void {\n ExpoJuceModule.setDSPValue(param, value);\n}\n\n// ── Transport ───────────────────────────────────────────────────────\n\nexport function startTransport(): void {\n ExpoJuceModule.startTransport();\n}\n\nexport function stopTransport(): void {\n ExpoJuceModule.stopTransport();\n}\n\nexport function setTempo(bpm: number): void {\n ExpoJuceModule.setTempo(bpm);\n}\n\nexport function setTransportPosition(beat: number): void {\n ExpoJuceModule.setTransportPosition(beat);\n}\n\nexport function getTransportPosition(): number {\n return ExpoJuceModule.getTransportPosition();\n}\n\nexport function getTempo(): number {\n return ExpoJuceModule.getTempo();\n}\n\nexport function isTransportPlaying(): boolean {\n return ExpoJuceModule.isTransportPlaying();\n}\n\n// ── Events ──────────────────────────────────────────────────────────\n\nexport async function setValueAsync(value: string) {\n return await ExpoJuceModule.setValueAsync(value);\n}\n\nconst emitter = new EventEmitter(ExpoJuceModule ?? NativeModulesProxy.ExpoJuce);\n\nexport function addChangeListener(listener: (event: ChangeEventPayload) => void): Subscription {\n return emitter.addListener<ChangeEventPayload>('onChange', listener);\n}\n\nexport function addBeatListener(listener: (event: BeatEventPayload) => void): Subscription {\n return emitter.addListener<BeatEventPayload>('onBeat', listener);\n}\n\nexport { ExpoJuceView, ExpoJuceViewProps, ChangeEventPayload, BeatEventPayload };\n"]}
|
package/ios/ExpoJuceBridge.h
CHANGED
|
@@ -2,10 +2,14 @@
|
|
|
2
2
|
|
|
3
3
|
NS_ASSUME_NONNULL_BEGIN
|
|
4
4
|
|
|
5
|
+
typedef void(^ExpoJuceBeatBlock)(double beat, double bpm);
|
|
6
|
+
|
|
5
7
|
@interface ExpoJuceBridge : NSObject
|
|
6
8
|
|
|
7
9
|
+ (void)setup;
|
|
8
10
|
+ (void)shutdown;
|
|
11
|
+
|
|
12
|
+
// ── Synth ─────────────────────────────────────────────────────────
|
|
9
13
|
+ (void)playToneWithFrequency:(double)frequency duration:(double)duration;
|
|
10
14
|
+ (void)setFrequency:(double)frequency;
|
|
11
15
|
+ (void)setLevel:(double)level;
|
|
@@ -14,6 +18,23 @@ NS_ASSUME_NONNULL_BEGIN
|
|
|
14
18
|
+ (void)noteOn;
|
|
15
19
|
+ (void)noteOff;
|
|
16
20
|
|
|
21
|
+
// ── DSP Params ────────────────────────────────────────────────────
|
|
22
|
+
+ (void)setAttack:(double)ms;
|
|
23
|
+
+ (void)setRelease:(double)ms;
|
|
24
|
+
+ (void)setFilterCutoff:(double)hz;
|
|
25
|
+
+ (void)setFilterResonance:(double)q;
|
|
26
|
+
+ (void)setDetune:(double)cents;
|
|
27
|
+
|
|
28
|
+
// ── Transport ─────────────────────────────────────────────────────
|
|
29
|
+
+ (void)startTransport;
|
|
30
|
+
+ (void)stopTransport;
|
|
31
|
+
+ (void)setTempo:(double)bpm;
|
|
32
|
+
+ (void)setTransportPosition:(double)beat;
|
|
33
|
+
+ (double)getTransportPosition;
|
|
34
|
+
+ (double)getTempo;
|
|
35
|
+
+ (BOOL)isTransportPlaying;
|
|
36
|
+
+ (void)setBeatCallback:(ExpoJuceBeatBlock)callback;
|
|
37
|
+
|
|
17
38
|
@end
|
|
18
39
|
|
|
19
40
|
NS_ASSUME_NONNULL_END
|
package/ios/ExpoJuceBridge.m
CHANGED
|
@@ -4,7 +4,6 @@
|
|
|
4
4
|
@implementation ExpoJuceBridge
|
|
5
5
|
|
|
6
6
|
+ (void)setup {
|
|
7
|
-
// Access the singleton — audio engine is initialized in its -init
|
|
8
7
|
[JuceToneGenerator sharedInstance];
|
|
9
8
|
}
|
|
10
9
|
|
|
@@ -12,6 +11,8 @@
|
|
|
12
11
|
[[JuceToneGenerator sharedInstance] shutdown];
|
|
13
12
|
}
|
|
14
13
|
|
|
14
|
+
// ── Synth ─────────────────────────────────────────────────────────
|
|
15
|
+
|
|
15
16
|
+ (void)playToneWithFrequency:(double)frequency duration:(double)duration {
|
|
16
17
|
[[JuceToneGenerator sharedInstance] playToneWithFrequency:frequency duration:duration];
|
|
17
18
|
}
|
|
@@ -40,4 +41,60 @@
|
|
|
40
41
|
[[JuceToneGenerator sharedInstance] noteOff];
|
|
41
42
|
}
|
|
42
43
|
|
|
44
|
+
// ── DSP Params ────────────────────────────────────────────────────
|
|
45
|
+
|
|
46
|
+
+ (void)setAttack:(double)ms {
|
|
47
|
+
[[JuceToneGenerator sharedInstance] setAttack:ms];
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
+ (void)setRelease:(double)ms {
|
|
51
|
+
[[JuceToneGenerator sharedInstance] setRelease:ms];
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
+ (void)setFilterCutoff:(double)hz {
|
|
55
|
+
[[JuceToneGenerator sharedInstance] setFilterCutoff:hz];
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
+ (void)setFilterResonance:(double)q {
|
|
59
|
+
[[JuceToneGenerator sharedInstance] setFilterResonance:q];
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
+ (void)setDetune:(double)cents {
|
|
63
|
+
[[JuceToneGenerator sharedInstance] setDetune:cents];
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
// ── Transport ─────────────────────────────────────────────────────
|
|
67
|
+
|
|
68
|
+
+ (void)startTransport {
|
|
69
|
+
[[JuceToneGenerator sharedInstance] startTransport];
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
+ (void)stopTransport {
|
|
73
|
+
[[JuceToneGenerator sharedInstance] stopTransport];
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
+ (void)setTempo:(double)bpm {
|
|
77
|
+
[[JuceToneGenerator sharedInstance] setTempo:bpm];
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
+ (void)setTransportPosition:(double)beat {
|
|
81
|
+
[[JuceToneGenerator sharedInstance] setTransportPosition:beat];
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
+ (double)getTransportPosition {
|
|
85
|
+
return [[JuceToneGenerator sharedInstance] getTransportPosition];
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
+ (double)getTempo {
|
|
89
|
+
return [[JuceToneGenerator sharedInstance] getTempo];
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
+ (BOOL)isTransportPlaying {
|
|
93
|
+
return [[JuceToneGenerator sharedInstance] isTransportPlaying];
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
+ (void)setBeatCallback:(ExpoJuceBeatBlock)callback {
|
|
97
|
+
[[JuceToneGenerator sharedInstance] setBeatCallback:callback];
|
|
98
|
+
}
|
|
99
|
+
|
|
43
100
|
@end
|
package/ios/ExpoJuceModule.swift
CHANGED
|
@@ -6,6 +6,14 @@ public class ExpoJuceModule: Module {
|
|
|
6
6
|
|
|
7
7
|
OnCreate {
|
|
8
8
|
ExpoJuceBridge.setup()
|
|
9
|
+
|
|
10
|
+
// Wire native beat callback → JS "onBeat" event
|
|
11
|
+
ExpoJuceBridge.setBeatCallback { [weak self] beat, bpm in
|
|
12
|
+
self?.sendEvent("onBeat", [
|
|
13
|
+
"beat": beat,
|
|
14
|
+
"bpm": bpm,
|
|
15
|
+
])
|
|
16
|
+
}
|
|
9
17
|
}
|
|
10
18
|
|
|
11
19
|
OnDestroy {
|
|
@@ -16,12 +24,14 @@ public class ExpoJuceModule: Module {
|
|
|
16
24
|
"PI": Double.pi
|
|
17
25
|
])
|
|
18
26
|
|
|
19
|
-
Events("onChange")
|
|
27
|
+
Events("onChange", "onBeat")
|
|
20
28
|
|
|
21
29
|
Function("hello") {
|
|
22
30
|
return "Hello world!"
|
|
23
31
|
}
|
|
24
32
|
|
|
33
|
+
// ── Synth ───────────────────────────────────────────────────────
|
|
34
|
+
|
|
25
35
|
Function("playTone") { (frequency: Double, duration: Double) -> String in
|
|
26
36
|
ExpoJuceBridge.playTone(withFrequency: frequency, duration: duration)
|
|
27
37
|
return "Playing tone at \(frequency)Hz for \(duration)ms"
|
|
@@ -52,17 +62,81 @@ public class ExpoJuceModule: Module {
|
|
|
52
62
|
ExpoJuceBridge.noteOff()
|
|
53
63
|
}
|
|
54
64
|
|
|
65
|
+
// ── DSP Params ──────────────────────────────────────────────────
|
|
66
|
+
|
|
67
|
+
Function("setAttack") { (ms: Double) in
|
|
68
|
+
ExpoJuceBridge.setAttack(ms)
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
Function("setRelease") { (ms: Double) in
|
|
72
|
+
ExpoJuceBridge.setRelease(ms)
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
Function("setFilterCutoff") { (hz: Double) in
|
|
76
|
+
ExpoJuceBridge.setFilterCutoff(hz)
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
Function("setFilterResonance") { (q: Double) in
|
|
80
|
+
ExpoJuceBridge.setFilterResonance(q)
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
Function("setDetune") { (cents: Double) in
|
|
84
|
+
ExpoJuceBridge.setDetune(cents)
|
|
85
|
+
}
|
|
86
|
+
|
|
55
87
|
Function("setDSPValue") { (param: String, value: Double) in
|
|
56
88
|
switch param {
|
|
57
89
|
case "frequency":
|
|
58
90
|
ExpoJuceBridge.setFrequency(value)
|
|
59
91
|
case "level":
|
|
60
92
|
ExpoJuceBridge.setLevel(value)
|
|
93
|
+
case "attack":
|
|
94
|
+
ExpoJuceBridge.setAttack(value)
|
|
95
|
+
case "release":
|
|
96
|
+
ExpoJuceBridge.setRelease(value)
|
|
97
|
+
case "filterCutoff":
|
|
98
|
+
ExpoJuceBridge.setFilterCutoff(value)
|
|
99
|
+
case "filterResonance":
|
|
100
|
+
ExpoJuceBridge.setFilterResonance(value)
|
|
101
|
+
case "detune":
|
|
102
|
+
ExpoJuceBridge.setDetune(value)
|
|
61
103
|
default:
|
|
62
104
|
break
|
|
63
105
|
}
|
|
64
106
|
}
|
|
65
107
|
|
|
108
|
+
// ── Transport ───────────────────────────────────────────────────
|
|
109
|
+
|
|
110
|
+
Function("startTransport") {
|
|
111
|
+
ExpoJuceBridge.startTransport()
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
Function("stopTransport") {
|
|
115
|
+
ExpoJuceBridge.stopTransport()
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
Function("setTempo") { (bpm: Double) in
|
|
119
|
+
ExpoJuceBridge.setTempo(bpm)
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
Function("setTransportPosition") { (beat: Double) in
|
|
123
|
+
ExpoJuceBridge.setTransportPosition(beat)
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
Function("getTransportPosition") { () -> Double in
|
|
127
|
+
return ExpoJuceBridge.getTransportPosition()
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
Function("getTempo") { () -> Double in
|
|
131
|
+
return ExpoJuceBridge.getTempo()
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
Function("isTransportPlaying") { () -> Bool in
|
|
135
|
+
return ExpoJuceBridge.isTransportPlaying()
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
// ── Async / View ────────────────────────────────────────────────
|
|
139
|
+
|
|
66
140
|
AsyncFunction("setValueAsync") { (value: String) in
|
|
67
141
|
self.sendEvent("onChange", [
|
|
68
142
|
"value": value
|
package/ios/JuceConfig.h
CHANGED
package/ios/JuceToneGenerator.h
CHANGED
|
@@ -1,10 +1,14 @@
|
|
|
1
1
|
#import <Foundation/Foundation.h>
|
|
2
2
|
|
|
3
|
+
typedef void(^BeatCallback)(double beat, double bpm);
|
|
4
|
+
|
|
3
5
|
@interface JuceToneGenerator : NSObject
|
|
4
6
|
|
|
5
7
|
+ (instancetype)sharedInstance;
|
|
6
8
|
- (void)initialize;
|
|
7
9
|
- (void)shutdown;
|
|
10
|
+
|
|
11
|
+
// ── Synth ─────────────────────────────────────────────────────────
|
|
8
12
|
- (void)playToneWithFrequency:(double)frequency duration:(double)duration;
|
|
9
13
|
- (void)setFrequency:(double)frequency;
|
|
10
14
|
- (void)setLevel:(double)level;
|
|
@@ -13,4 +17,21 @@
|
|
|
13
17
|
- (void)noteOn;
|
|
14
18
|
- (void)noteOff;
|
|
15
19
|
|
|
20
|
+
// ── DSP Params ────────────────────────────────────────────────────
|
|
21
|
+
- (void)setAttack:(double)ms;
|
|
22
|
+
- (void)setRelease:(double)ms;
|
|
23
|
+
- (void)setFilterCutoff:(double)hz;
|
|
24
|
+
- (void)setFilterResonance:(double)q;
|
|
25
|
+
- (void)setDetune:(double)cents;
|
|
26
|
+
|
|
27
|
+
// ── Transport ─────────────────────────────────────────────────────
|
|
28
|
+
- (void)startTransport;
|
|
29
|
+
- (void)stopTransport;
|
|
30
|
+
- (void)setTempo:(double)bpm;
|
|
31
|
+
- (void)setTransportPosition:(double)beat;
|
|
32
|
+
- (double)getTransportPosition;
|
|
33
|
+
- (double)getTempo;
|
|
34
|
+
- (BOOL)isTransportPlaying;
|
|
35
|
+
- (void)setBeatCallback:(BeatCallback)callback;
|
|
36
|
+
|
|
16
37
|
@end
|