Waveform/dutyCycle

This commit is contained in:
2024-06-18 17:41:22 +02:00
parent 94dec1f636
commit 945f4bb016
3 changed files with 76 additions and 18 deletions

View File

@@ -49,6 +49,13 @@ class PlayingNote(
var actualVolume = 0f
}
enum class Waveform {
SINE,
SQUARE,
TRIANGLE,
SAWTOOTH
}
@ExperimentalJsExport
@JsExport
class VstChipProcessor : AudioWorkletProcessor() {
@@ -57,6 +64,8 @@ class VstChipProcessor : AudioWorkletProcessor() {
0
)
}
var waveform = Waveform.SINE.ordinal
var dutyCycle = 0.5
init {
this.port.onmessage = ::handleMessage
@@ -117,6 +126,27 @@ class VstChipProcessor : AudioWorkletProcessor() {
noteOff(note)
}
}
0xc9 -> {
if (bytes.length >= 1) {
val waveform = bytes[1]
if (waveform < 4) {
this.waveform = waveform
}
}
}
0xb0 -> {
if (bytes.length == 3) {
val knob = bytes[1]
val value = bytes[2]
when(knob) {
0x4a -> {
dutyCycle = value / 127.0
}
}
}
}
}
}
}
@@ -175,20 +205,39 @@ class VstChipProcessor : AudioWorkletProcessor() {
note.releaseSamples--
targetVolume *= (note.releaseSamples / 10000f)
}
note.actualVolume += (targetVolume - note.actualVolume) * 0.005f
note.actualVolume += (targetVolume - note.actualVolume) * 0.001f
if (note.state == NoteState.RELEASED && note.actualVolume <= 0) {
note.state = NoteState.OFF
}
left[i] = left[i] + sin(note.cycleOffset * PI2).toFloat() * note.actualVolume * 0.3f
right[i] = right[i] + sin(note.cycleOffset * PI2).toFloat() * note.actualVolume * 0.3f
val cycleOffset = note.cycleOffset
//left[i] = left[i] + if (note.cycleOffset < 0.5) { 0.3f } else { -0.3f } * note.actualVolume //sin(note.cycleOffset * PI2).toFloat() * note.actualVolume * 0.3f
//right[i] = right[i] + if (note.cycleOffset < 0.5) { 0.3f } else { -0.3f } * note.actualVolume //sin(note.cycleOffset * PI2).toFloat() * note.actualVolume * 0.3f
val waveValue: Float = when (waveform) {
0 -> {
sin(cycleOffset * PI2).toFloat()
}
1 -> {
if (cycleOffset < dutyCycle) { 1f } else { -1f }
}
2 -> when {
cycleOffset < 0.25 -> 4 * cycleOffset
cycleOffset < 0.75 -> 2 - 4 * cycleOffset
else -> 4 * cycleOffset - 4
}.toFloat()
3 -> {
((cycleOffset * 2f) - 1f).toFloat()
}
else -> {
if (cycleOffset < 0.5) { 1f } else { -1f }
}
}
left[i] = left[i] + waveValue * note.actualVolume * 0.3f
right[i] = right[i] + waveValue * note.actualVolume * 0.3f
note.cycleOffset += sampleDelta
if (note.cycleOffset > 1f) {
if (cycleOffset > 1f) {
note.cycleOffset -= 1f
}
}

View File

@@ -15,16 +15,16 @@ enum class Note(
val sharp: String,
val flat: String
) {
NONE("---", "---"),
No02("C--","C--"),
NO03("C#-","Db-"),
NO04("D--","D--"),
NO05("D#-","Eb-"),
NO06("E--","E--"),
NO07("F--","F--"),
NO08("F#-","Gb-"),
NO09("G--","G--"),
NO10("G#-","Ab-"),
NO01("C--","C--"),
NO02("C#-","Db-"),
NO03("D--","D--"),
NO04("D#-","Eb-"),
NO05("E--","E--"),
NO06("F--","F--"),
NO07("F#-","Gb-"),
NO08("G--","G--"),
NO09("G#-","Ab-"),
NO10("A--","A--"),
NO11("A#-","Bb-"),
NO12("B--","B--"),
C0("C-0","C-0"),
@@ -148,12 +148,13 @@ enum class Note(
//A9("A-9","A-9"),
//A9s("A#9","Bb9"),
//B9("B-9","B-9"),
NONE("---", "---"),
UP("^^^","^^^"),
END("XXX","XXX"),
;
// 69 = A4.ordinal
val freq: Double = round(440.0 * 2.0.pow((ordinal - 69)/12.0) * 100.0) / 100.0
val freq: Double = round(440.0 * 2.0.pow((ordinal - 69)/12.0) * 10000.0) / 10000.0
val cycleLength: Double = 1.0 / freq
var sampleDelta: Double = 0.0

View File

@@ -3,6 +3,8 @@ package nl.astraeus.vst.chip.midi
import kotlinx.browser.window
import nl.astraeus.vst.chip.audio.VstChipWorklet
import nl.astraeus.vst.chip.view.MainView
import org.khronos.webgl.Uint8Array
import org.khronos.webgl.get
external class MIDIInput {
val connection: String
@@ -77,7 +79,13 @@ object Midi {
}
currentInput?.onmidimessage = { message ->
console.log("Midi message:", message)
val data = message.data as Uint8Array
val hex = StringBuilder()
for (index in 0 until data.length) {
hex.append(data[index].toString(16))
hex.append(" ")
}
console.log("Midi message:", hex)
VstChipWorklet.postMessage(
message.data
)