Simple interaction with audioworkler

This commit is contained in:
2022-12-22 20:10:43 +01:00
parent 61a4d5bdc2
commit 69fadeb9b1
8 changed files with 86 additions and 88 deletions

View File

@@ -4,7 +4,7 @@ import org.jetbrains.kotlin.gradle.plugin.KotlinJsCompilerType.IR
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
plugins {
kotlin("multiplatform") version "1.7.20"
kotlin("multiplatform") version "1.8.10"
application
}
@@ -62,11 +62,11 @@ kotlin {
}
application {
mainClass.set("nl.astraeus.application.ServerKt")
mainClass.set("ServerKt")
}
tasks.named<Copy>("jvmProcessResources") {
val jsBrowserDistribution = tasks.named("jsBrowserDistribution")
val jsBrowserDistribution = tasks.named("jsBrowserDevelopmentWebpack")
from(jsBrowserDistribution)
from(tasks.named("jsAudioWorkletBrowserDistribution"))
}
@@ -74,4 +74,4 @@ tasks.named<Copy>("jvmProcessResources") {
tasks.named<JavaExec>("run") {
dependsOn(tasks.named<Jar>("jvmJar"))
classpath(tasks.named<Jar>("jvmJar"))
}
}

View File

@@ -7,6 +7,9 @@ import org.w3c.dom.MessagePort
import kotlin.math.PI
import kotlin.math.sin
const val PI2 = PI * 2
const val NOTE_LENGTH = 2500
@ExperimentalJsExport
@JsExport
object WorkletProcessor {
@@ -16,6 +19,8 @@ object WorkletProcessor {
var note = Note.C2
var offset = 0.0
var note_length = 2500
@JsName("setPort")
fun setPort(port: MessagePort) {
WorkletProcessor.port = port
@@ -26,17 +31,25 @@ object WorkletProcessor {
fun onMessage(message: MessageEvent) {
console.log("WorkletProcessor: Received message", message)
when (message.data) {
"start" -> {
println("Start worklet!")
val data = message.data
if (data is String) {
val parts = data.split("\n")
when (parts[0]) {
"start" -> {
println("Start worklet!")
}
"stop" -> {
}
"set_note_length" -> {
note_length = parts[1].toInt()
}
else ->
console.error("Don't kow how to handle message", message)
}
"stop" -> {
}
else ->
console.error("Don't kow how to handle message", message)
}
}
@@ -46,10 +59,14 @@ object WorkletProcessor {
var delta = note.sampleDelta
for (sample in 0 until samples) {
var value = sin(offset * 2 * PI)
var value = sin(offset * PI2) +
sin(offset * 2 * PI2) * 0.5 +
sin(offset * 3 * PI2) * 0.25 +
sin(offset * 4 * PI2) * 0.15
offset += delta
val noteProgress = tmpCounter % 5000
// new note every NOTE_LENGTH samples
val noteProgress = tmpCounter % note_length
if (noteProgress == 0) {
note = note.transpose(1)
if (note == Note.C7) {
@@ -57,7 +74,8 @@ object WorkletProcessor {
}
delta = note.sampleDelta
}
value *= (1.0 - noteProgress / 5000.0)
// simple envelop from max to 0 every note
value *= (1.0 - noteProgress / note_length.toDouble())
left[sample] = value
right[sample] = value

View File

@@ -1,19 +0,0 @@
import kotlinx.browser.document
import handler.AudioWorkletHandler
fun main() {
AudioWorkletHandler.loadCode()
println("Ok")
document.getElementById("clicker")?.also {
it.addEventListener("click", {
AudioWorkletHandler.createContext {
println("Created context")
AudioWorkletHandler.start()
}
}, "")
}
}

View File

@@ -2,6 +2,7 @@ package nl.astraeus
import kotlinx.browser.document
import nl.astraeus.handler.AudioWorkletHandler
import org.w3c.dom.HTMLInputElement
fun main() {
AudioWorkletHandler.loadCode()
@@ -18,4 +19,17 @@ fun main() {
}, "")
}
print("get noteLength")
document.getElementById("noteLength")?.also {
println("Set noteLength event")
it.addEventListener("change", {
println("Set noteLength 1")
val target = it.target
if (target is HTMLInputElement) {
println("Set noteLength 2")
AudioWorkletHandler.setNoteLength(target.value.toInt())
}
}, "")
}
}

View File

@@ -159,4 +159,7 @@ object AudioWorkletHandler : AudioWorklet(
audioWorkletMessagePort?.postMessage("start")
}
fun setNoteLength(length: Int) {
audioWorkletMessagePort?.postMessage("set_note_length\n$length")
}
}

View File

@@ -1,4 +1,14 @@
.button_div {
margin: 1em;
}
.button {
padding: 3px 5px;
background-color: red;
}
background-color: #2c008f;
color: white;
font-size: large;
}
input {
margin: 1em;
}

View File

@@ -14,15 +14,31 @@ fun HTML.index() {
}
body {
div {
+"Hello from Ktor"
+"We need a button to start because we can only start audio from a user event"
}
div("button_div") {
span("button") {
id = "clicker"
+"Start"
}
}
div {
id = "root"
+ "An example of how to interact with the audioworklet:"
}
span("button") {
id = "clicker"
+ "Start"
div {
label {
htmlFor = "noteLength"
+"Note length (in samples):"
}
input {
id = "noteLength"
type = InputType.number
value = "2500"
min = "1"
max = "100000"
step = "100"
}
}
script(src = "/static/kotlin-audioworklet.js") {}
}

View File

@@ -1,44 +0,0 @@
package nl.astraeus.application
import io.ktor.http.HttpStatusCode
import io.ktor.server.application.*
import io.ktor.server.engine.embeddedServer
import io.ktor.server.html.*
import io.ktor.server.http.content.*
import io.ktor.server.netty.Netty
import io.ktor.server.routing.*
import kotlinx.html.*
fun HTML.index() {
head {
title("Hello from Ktor!")
link("static/worklet.css", "stylesheet" ,"text/css")
}
body {
div {
+"Hello from Ktor"
}
div {
id = "root"
}
span("button") {
id = "clicker"
+ "Start"
}
script(src = "/static/kotlin-audioworklet.js") {}
}
}
fun main() {
embeddedServer(Netty, port = 8080, host = "127.0.0.1") {
routing {
get("/") {
call.respondHtml(HttpStatusCode.OK, HTML::index)
}
static("/static") {
resources()
}
}
}.start(wait = true)
}