Fx
This commit is contained in:
@@ -37,6 +37,8 @@ kotlin {
|
||||
val commonMain by getting {
|
||||
dependencies {
|
||||
implementation(project(":common"))
|
||||
|
||||
implementation("nl.astraeus:vst-worklet-base:1.0.0-SNAPSHOT")
|
||||
}
|
||||
}
|
||||
val jsMain by getting {
|
||||
|
||||
@@ -1,43 +0,0 @@
|
||||
package nl.astraeus.vst
|
||||
|
||||
import org.khronos.webgl.Float32Array
|
||||
import org.w3c.dom.MessagePort
|
||||
|
||||
enum class AutomationRate(
|
||||
val rate: String
|
||||
) {
|
||||
A_RATE("a-rate"),
|
||||
K_RATE("k-rate")
|
||||
}
|
||||
|
||||
interface AudioParam {
|
||||
var value: Double
|
||||
var automationRate: AutomationRate
|
||||
val defaultValue: Double
|
||||
val minValue: Double
|
||||
val maxValue: Double
|
||||
}
|
||||
|
||||
interface AudioParamMap {
|
||||
operator fun get(name: String): AudioParam
|
||||
}
|
||||
|
||||
abstract external class AudioWorkletProcessor {
|
||||
/** [MDN Reference](https://developer.mozilla.org/docs/Web/API/AudioWorkletNode/parameters) */
|
||||
//val parameters: AudioParamMap;
|
||||
/** [MDN Reference](https://developer.mozilla.org/docs/Web/API/AudioWorkletNode/port) */
|
||||
@JsName("port")
|
||||
val port: MessagePort
|
||||
|
||||
@JsName("process")
|
||||
open fun process (
|
||||
inputs: Array<Array<Float32Array>>,
|
||||
outputs: Array<Array<Float32Array>>,
|
||||
parameters: dynamic
|
||||
) : Boolean { definedExternally }
|
||||
|
||||
}
|
||||
|
||||
external fun registerProcessor(name: String, processorCtor: JsClass<*>)
|
||||
external val sampleRate: Int
|
||||
external val currentTime: Double
|
||||
@@ -66,6 +66,11 @@ class VstChipProcessor : AudioWorkletProcessor() {
|
||||
}
|
||||
var waveform = Waveform.SINE.ordinal
|
||||
var dutyCycle = 0.5
|
||||
var fmFreq = 0.0
|
||||
var fmAmp = 0.0
|
||||
var amFreq = 0.0
|
||||
var amAmp = 0.0
|
||||
val sampleLength = 1 / sampleRate.toDouble()
|
||||
|
||||
init {
|
||||
this.port.onmessage = ::handleMessage
|
||||
@@ -106,6 +111,7 @@ class VstChipProcessor : AudioWorkletProcessor() {
|
||||
|
||||
private fun playMidi(bytes: Int32Array) {
|
||||
if (bytes.length > 0) {
|
||||
//console.log("Received", bytes)
|
||||
when(bytes[0]) {
|
||||
0x90 -> {
|
||||
if (bytes.length == 3) {
|
||||
@@ -119,6 +125,7 @@ class VstChipProcessor : AudioWorkletProcessor() {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
0x80 -> {
|
||||
if (bytes.length >= 2) {
|
||||
val note = bytes[1]
|
||||
@@ -126,6 +133,7 @@ class VstChipProcessor : AudioWorkletProcessor() {
|
||||
noteOff(note)
|
||||
}
|
||||
}
|
||||
|
||||
0xc9 -> {
|
||||
if (bytes.length >= 1) {
|
||||
val waveform = bytes[1]
|
||||
@@ -135,18 +143,44 @@ class VstChipProcessor : AudioWorkletProcessor() {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
0xb0 -> {
|
||||
if (bytes.length == 3) {
|
||||
val knob = bytes[1]
|
||||
val value = bytes[2]
|
||||
|
||||
when(knob) {
|
||||
when (knob) {
|
||||
0x4a -> {
|
||||
dutyCycle = value / 127.0
|
||||
}
|
||||
|
||||
0x4b -> {
|
||||
fmFreq = value / 127.0
|
||||
}
|
||||
|
||||
0x4c -> {
|
||||
fmAmp = value / 127.0
|
||||
}
|
||||
|
||||
0x47 -> {
|
||||
amFreq = value / 127.0
|
||||
}
|
||||
|
||||
0x48 -> {
|
||||
amAmp = value / 127.0
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
0xe0 -> {
|
||||
if (bytes.length == 3) {
|
||||
val lsb = bytes[1]
|
||||
val msb = bytes[2]
|
||||
|
||||
amFreq = (((msb - 0x40) + (lsb / 127.0)) / 0x40) * 10.0
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -167,7 +201,7 @@ class VstChipProcessor : AudioWorkletProcessor() {
|
||||
notes[i].state = NoteState.ON
|
||||
|
||||
val n = Note.fromMidi(note)
|
||||
console.log("Playing note: ${n.sharp} (${n.freq})")
|
||||
//console.log("Playing note: ${n.sharp} (${n.freq})")
|
||||
break
|
||||
}
|
||||
}
|
||||
@@ -205,13 +239,16 @@ class VstChipProcessor : AudioWorkletProcessor() {
|
||||
note.releaseSamples--
|
||||
targetVolume *= (note.releaseSamples / 10000f)
|
||||
}
|
||||
note.actualVolume += (targetVolume - note.actualVolume) * 0.001f
|
||||
note.actualVolume += (targetVolume - note.actualVolume) * 0.0001f
|
||||
|
||||
if (note.state == NoteState.RELEASED && note.actualVolume <= 0) {
|
||||
note.state = NoteState.OFF
|
||||
}
|
||||
|
||||
val cycleOffset = note.cycleOffset
|
||||
var cycleOffset = note.cycleOffset
|
||||
val fmModulation = sin(sampleLength * fmFreq * 10f * PI2 * note.sample).toFloat() * fmAmp * 5f
|
||||
val amModulation = 1f + (sin(sampleLength * amFreq * 10f * PI2 * note.sample) * amAmp).toFloat()
|
||||
cycleOffset += fmModulation
|
||||
|
||||
val waveValue: Float = when (waveform) {
|
||||
0 -> {
|
||||
@@ -233,13 +270,14 @@ class VstChipProcessor : AudioWorkletProcessor() {
|
||||
}
|
||||
}
|
||||
|
||||
left[i] = left[i] + waveValue * note.actualVolume * 0.3f
|
||||
right[i] = right[i] + waveValue * note.actualVolume * 0.3f
|
||||
left[i] = left[i] + waveValue * note.actualVolume * 0.3f * amModulation
|
||||
right[i] = right[i] + waveValue * note.actualVolume * 0.3f * amModulation
|
||||
|
||||
note.cycleOffset += sampleDelta
|
||||
if (cycleOffset > 1f) {
|
||||
note.cycleOffset -= 1f
|
||||
}
|
||||
note.sample++
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user