Waveform/dutyCycle
This commit is contained in:
@@ -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
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user