Skip to content

Commit 14b4391

Browse files
committed
MDN audio worklet example. Application
1 parent 0f590b3 commit 14b4391

2 files changed

Lines changed: 132 additions & 2 deletions

File tree

  • tests/worklets/mdn-audioworklet-example/src/commonMain/kotlin/mdn/audioworklet/example
Lines changed: 120 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,123 @@
11
package mdn.audioworklet.example
22

3-
fun main() {
4-
// TODO
3+
import web.audio.*
4+
import web.dom.ElementId
5+
import web.dom.clickEvent
6+
import web.dom.document
7+
import web.dom.inputEvent
8+
import web.events.addHandler
9+
import web.events.once
10+
import web.html.HTMLButtonElement
11+
import web.html.HTMLInputElement
12+
import web.window.loadEvent
13+
import web.window.window
14+
import web.worklets.addModule
15+
16+
var _audioContext: AudioContext? = null
17+
val audioContext: AudioContext
18+
get() = _audioContext ?: error("AudioContext not initialized")
19+
20+
lateinit var hissGainRange: HTMLInputElement
21+
lateinit var oscGainRange: HTMLInputElement
22+
lateinit var gainNode: GainNode
23+
lateinit var hissGainParam: AudioParam
24+
25+
suspend fun main() {
26+
window.loadEvent.once()
27+
28+
document.getElementById(ElementId("toggle"))
29+
.let { it as HTMLButtonElement }
30+
.clickEvent.addHandler { suspendRun(::toggleSound) }
31+
32+
hissGainRange = document.getElementById(ElementId("hiss-gain")) as HTMLInputElement
33+
oscGainRange = document.getElementById(ElementId("osc-gain")) as HTMLInputElement
34+
35+
hissGainRange.inputEvent.addHandler { event ->
36+
val value = event.currentTarget.valueAsNumber.toFloat()
37+
hissGainParam.setValueAtTime(value, audioContext.currentTime)
38+
}
39+
40+
oscGainRange.inputEvent.addHandler { event ->
41+
val value = event.currentTarget.valueAsNumber.toFloat()
42+
gainNode.gain.setValueAtTime(value, audioContext.currentTime)
43+
}
44+
45+
hissGainRange.disabled = true
46+
oscGainRange.disabled = true
47+
}
48+
49+
suspend fun createHissProcessor(): AudioWorkletNode? {
50+
if (_audioContext == null) {
51+
try {
52+
_audioContext = AudioContext()
53+
} catch (_: Exception) {
54+
console.log("** Error: Unable to create audio context")
55+
return null
56+
}
57+
}
58+
59+
var processorNode: AudioWorkletNode
60+
61+
try {
62+
processorNode = AudioWorkletNode(audioContext, "hiss-generator")
63+
} catch (_: Exception) {
64+
try {
65+
console.log("adding...")
66+
audioContext.audioWorklet.addModule(HissGeneratorWorkletModule)
67+
processorNode = AudioWorkletNode(audioContext, "hiss-generator")
68+
} catch (e: Exception) {
69+
console.log("** Error: Unable to create worklet node: $e")
70+
return null
71+
}
72+
}
73+
74+
audioContext.resume()
75+
return processorNode
76+
}
77+
78+
suspend fun audioDemoStart() {
79+
val hissGenNode = createHissProcessor()
80+
if (hissGenNode == null) {
81+
console.log("** Error: unable to create hiss processor")
82+
return
83+
}
84+
val soundSource = OscillatorNode(audioContext)
85+
gainNode = audioContext.createGain()
86+
87+
// Configure the oscillator node
88+
89+
soundSource.type = OscillatorType.square
90+
soundSource.frequency.setValueAtTime(440f, audioContext.currentTime) // (A4)
91+
92+
// Configure the gain for the oscillator
93+
94+
gainNode.gain.setValueAtTime(oscGainRange.valueAsNumber.toFloat(), audioContext.currentTime)
95+
96+
// Connect and start
97+
98+
soundSource
99+
.connect(gainNode)
100+
.connect(hissGenNode)
101+
.connect(audioContext.destination)
102+
soundSource.start()
103+
104+
// Get access to the worklet's gain parameter
105+
106+
hissGainParam = hissGenNode.parameters.get(GAIN)!!
107+
hissGainParam.setValueAtTime(hissGainRange.valueAsNumber.toFloat(), audioContext.currentTime)
108+
}
109+
110+
suspend fun toggleSound() {
111+
if (_audioContext == null) {
112+
audioDemoStart()
113+
114+
hissGainRange.disabled = false
115+
oscGainRange.disabled = false
116+
} else {
117+
hissGainRange.disabled = true
118+
oscGainRange.disabled = true
119+
120+
audioContext.close()
121+
_audioContext = null
122+
}
5123
}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
package mdn.audioworklet.example
2+
3+
import kotlinx.coroutines.CoroutineScope
4+
import kotlinx.coroutines.launch
5+
import kotlin.coroutines.EmptyCoroutineContext
6+
7+
fun suspendRun(
8+
block: suspend () -> Unit,
9+
) {
10+
CoroutineScope(EmptyCoroutineContext)
11+
.launch { block() }
12+
}

0 commit comments

Comments
 (0)