expo-juce 0.3.0 → 0.3.1
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/ios/ExpoJuceModule.swift +47 -47
- package/package.json +1 -1
package/ios/ExpoJuceModule.swift
CHANGED
|
@@ -6,9 +6,6 @@ public class ExpoJuceModule: Module {
|
|
|
6
6
|
public func definition() -> ModuleDefinition {
|
|
7
7
|
Name("ExpoJuce")
|
|
8
8
|
|
|
9
|
-
// Audio engine is initialized lazily on first use, not at module load.
|
|
10
|
-
// Initializing AVAudioEngine in OnCreate can crash before JS is ready.
|
|
11
|
-
|
|
12
9
|
OnDestroy {
|
|
13
10
|
ExpoJuceBridge.stopBeatTimer()
|
|
14
11
|
ExpoJuceBridge.shutdown()
|
|
@@ -20,8 +17,6 @@ public class ExpoJuceModule: Module {
|
|
|
20
17
|
|
|
21
18
|
Events("onChange", "onBeat")
|
|
22
19
|
|
|
23
|
-
// Beat timer only runs while JS has active listeners.
|
|
24
|
-
// This prevents sendEvent from firing before listeners are attached (crash).
|
|
25
20
|
OnStartObserving {
|
|
26
21
|
self.hasListeners = true
|
|
27
22
|
ExpoJuceBridge.startBeatTimer()
|
|
@@ -37,8 +32,13 @@ public class ExpoJuceModule: Module {
|
|
|
37
32
|
}
|
|
38
33
|
|
|
39
34
|
// ── Synth ───────────────────────────────────────────────────────
|
|
35
|
+
// All audio methods use AsyncFunction dispatched on main queue.
|
|
36
|
+
// AVAudioEngine and CoreAudio must be accessed from the main thread.
|
|
37
|
+
// Expo's synchronous Function() runs on the JS/Hermes thread,
|
|
38
|
+
// which is NOT the main thread in production builds — this causes
|
|
39
|
+
// native crashes when calling CoreAudio APIs.
|
|
40
40
|
|
|
41
|
-
|
|
41
|
+
AsyncFunction("setup") { [weak self] in
|
|
42
42
|
ExpoJuceBridge.setup()
|
|
43
43
|
ExpoJuceBridge.setBeatCallback { [weak self] beat, bpm in
|
|
44
44
|
guard let self = self, self.hasListeners else { return }
|
|
@@ -47,61 +47,61 @@ public class ExpoJuceModule: Module {
|
|
|
47
47
|
"bpm": bpm,
|
|
48
48
|
])
|
|
49
49
|
}
|
|
50
|
-
}
|
|
50
|
+
}.runOnQueue(.main)
|
|
51
51
|
|
|
52
|
-
|
|
52
|
+
AsyncFunction("playTone") { (frequency: Double, duration: Double) -> String in
|
|
53
53
|
ExpoJuceBridge.playTone(withFrequency: frequency, duration: duration)
|
|
54
54
|
return "Playing tone at \(frequency)Hz for \(duration)ms"
|
|
55
|
-
}
|
|
55
|
+
}.runOnQueue(.main)
|
|
56
56
|
|
|
57
|
-
|
|
57
|
+
AsyncFunction("setFrequency") { (frequency: Double) in
|
|
58
58
|
ExpoJuceBridge.setFrequency(frequency)
|
|
59
|
-
}
|
|
59
|
+
}.runOnQueue(.main)
|
|
60
60
|
|
|
61
|
-
|
|
61
|
+
AsyncFunction("setLevel") { (level: Double) in
|
|
62
62
|
ExpoJuceBridge.setLevel(level)
|
|
63
|
-
}
|
|
63
|
+
}.runOnQueue(.main)
|
|
64
64
|
|
|
65
|
-
|
|
65
|
+
AsyncFunction("setWaveform") { (waveform: String) in
|
|
66
66
|
ExpoJuceBridge.setWaveform(waveform)
|
|
67
|
-
}
|
|
67
|
+
}.runOnQueue(.main)
|
|
68
68
|
|
|
69
|
-
|
|
69
|
+
AsyncFunction("setHarmonicLevels") { (levels: [Double]) in
|
|
70
70
|
let nsLevels = levels.map { NSNumber(value: $0) }
|
|
71
71
|
ExpoJuceBridge.setHarmonicLevels(nsLevels)
|
|
72
|
-
}
|
|
72
|
+
}.runOnQueue(.main)
|
|
73
73
|
|
|
74
|
-
|
|
74
|
+
AsyncFunction("noteOn") {
|
|
75
75
|
ExpoJuceBridge.noteOn()
|
|
76
|
-
}
|
|
76
|
+
}.runOnQueue(.main)
|
|
77
77
|
|
|
78
|
-
|
|
78
|
+
AsyncFunction("noteOff") {
|
|
79
79
|
ExpoJuceBridge.noteOff()
|
|
80
|
-
}
|
|
80
|
+
}.runOnQueue(.main)
|
|
81
81
|
|
|
82
82
|
// ── DSP Params ──────────────────────────────────────────────────
|
|
83
83
|
|
|
84
|
-
|
|
84
|
+
AsyncFunction("setAttack") { (ms: Double) in
|
|
85
85
|
ExpoJuceBridge.setAttack(ms)
|
|
86
|
-
}
|
|
86
|
+
}.runOnQueue(.main)
|
|
87
87
|
|
|
88
|
-
|
|
88
|
+
AsyncFunction("setRelease") { (ms: Double) in
|
|
89
89
|
ExpoJuceBridge.setRelease(ms)
|
|
90
|
-
}
|
|
90
|
+
}.runOnQueue(.main)
|
|
91
91
|
|
|
92
|
-
|
|
92
|
+
AsyncFunction("setFilterCutoff") { (hz: Double) in
|
|
93
93
|
ExpoJuceBridge.setFilterCutoff(hz)
|
|
94
|
-
}
|
|
94
|
+
}.runOnQueue(.main)
|
|
95
95
|
|
|
96
|
-
|
|
96
|
+
AsyncFunction("setFilterResonance") { (q: Double) in
|
|
97
97
|
ExpoJuceBridge.setFilterResonance(q)
|
|
98
|
-
}
|
|
98
|
+
}.runOnQueue(.main)
|
|
99
99
|
|
|
100
|
-
|
|
100
|
+
AsyncFunction("setDetune") { (cents: Double) in
|
|
101
101
|
ExpoJuceBridge.setDetune(cents)
|
|
102
|
-
}
|
|
102
|
+
}.runOnQueue(.main)
|
|
103
103
|
|
|
104
|
-
|
|
104
|
+
AsyncFunction("setDSPValue") { (param: String, value: Double) in
|
|
105
105
|
switch param {
|
|
106
106
|
case "frequency":
|
|
107
107
|
ExpoJuceBridge.setFrequency(value)
|
|
@@ -120,37 +120,37 @@ public class ExpoJuceModule: Module {
|
|
|
120
120
|
default:
|
|
121
121
|
break
|
|
122
122
|
}
|
|
123
|
-
}
|
|
123
|
+
}.runOnQueue(.main)
|
|
124
124
|
|
|
125
125
|
// ── Transport ───────────────────────────────────────────────────
|
|
126
126
|
|
|
127
|
-
|
|
127
|
+
AsyncFunction("startTransport") {
|
|
128
128
|
ExpoJuceBridge.startTransport()
|
|
129
|
-
}
|
|
129
|
+
}.runOnQueue(.main)
|
|
130
130
|
|
|
131
|
-
|
|
131
|
+
AsyncFunction("stopTransport") {
|
|
132
132
|
ExpoJuceBridge.stopTransport()
|
|
133
|
-
}
|
|
133
|
+
}.runOnQueue(.main)
|
|
134
134
|
|
|
135
|
-
|
|
135
|
+
AsyncFunction("setTempo") { (bpm: Double) in
|
|
136
136
|
ExpoJuceBridge.setTempo(bpm)
|
|
137
|
-
}
|
|
137
|
+
}.runOnQueue(.main)
|
|
138
138
|
|
|
139
|
-
|
|
139
|
+
AsyncFunction("setTransportPosition") { (beat: Double) in
|
|
140
140
|
ExpoJuceBridge.setTransportPosition(beat)
|
|
141
|
-
}
|
|
141
|
+
}.runOnQueue(.main)
|
|
142
142
|
|
|
143
|
-
|
|
143
|
+
AsyncFunction("getTransportPosition") { () -> Double in
|
|
144
144
|
return ExpoJuceBridge.getTransportPosition()
|
|
145
|
-
}
|
|
145
|
+
}.runOnQueue(.main)
|
|
146
146
|
|
|
147
|
-
|
|
147
|
+
AsyncFunction("getTempo") { () -> Double in
|
|
148
148
|
return ExpoJuceBridge.getTempo()
|
|
149
|
-
}
|
|
149
|
+
}.runOnQueue(.main)
|
|
150
150
|
|
|
151
|
-
|
|
151
|
+
AsyncFunction("isTransportPlaying") { () -> Bool in
|
|
152
152
|
return ExpoJuceBridge.isTransportPlaying()
|
|
153
|
-
}
|
|
153
|
+
}.runOnQueue(.main)
|
|
154
154
|
|
|
155
155
|
// ── Async / View ────────────────────────────────────────────────
|
|
156
156
|
|