Create midiHelp() function
This commit is contained in:
@@ -2,12 +2,15 @@ package io.smnp.ext
|
||||
|
||||
import io.smnp.environment.Environment
|
||||
import io.smnp.ext.function.MidiFunction
|
||||
import io.smnp.ext.function.MidiHelpFunction
|
||||
import io.smnp.ext.midi.MidiSequencer
|
||||
import org.pf4j.Extension
|
||||
|
||||
@Extension
|
||||
class MidiModule : NativeModuleProvider("smnp.audio.midi") {
|
||||
override fun functions() = listOf(MidiFunction())
|
||||
override fun functions() = listOf(MidiFunction(), MidiHelpFunction())
|
||||
|
||||
override fun dependencies() = listOf("smnp.music")
|
||||
|
||||
override fun onModuleLoad(environment: Environment) {
|
||||
MidiSequencer.init()
|
||||
|
||||
@@ -0,0 +1,67 @@
|
||||
package io.smnp.ext.function
|
||||
|
||||
import io.smnp.callable.function.Function
|
||||
import io.smnp.callable.function.FunctionDefinitionTool
|
||||
import io.smnp.callable.signature.Signature.Companion.simple
|
||||
import io.smnp.data.entity.Note
|
||||
import io.smnp.data.enumeration.Pitch
|
||||
import io.smnp.error.CustomException
|
||||
import io.smnp.ext.midi.MidiSequencer
|
||||
import io.smnp.type.enumeration.DataType.*
|
||||
import io.smnp.type.matcher.Matcher.Companion.ofType
|
||||
import io.smnp.type.matcher.Matcher.Companion.optional
|
||||
import io.smnp.type.model.Value
|
||||
|
||||
class MidiHelpFunction : Function("midiHelp") {
|
||||
override fun define(new: FunctionDefinitionTool) {
|
||||
new function simple(ofType(STRING)) body { _, (command) ->
|
||||
val cmd = command.value as String
|
||||
when (cmd.toLowerCase()) {
|
||||
"instruments" -> MidiSequencer.instruments.forEachIndexed { index, instrument -> println("$index: $instrument") }
|
||||
else -> throw CustomException("Unknown command '$cmd' - available commands: 'instruments', '<instrumentId>'")
|
||||
}
|
||||
|
||||
Value.void()
|
||||
}
|
||||
|
||||
new function simple(
|
||||
ofType(INT),
|
||||
optional(ofType(INT)),
|
||||
optional(ofType(NOTE)),
|
||||
optional(ofType(NOTE)),
|
||||
optional(ofType(INT))
|
||||
) body { environment, args ->
|
||||
val instrument = args[0].value as Int
|
||||
val bpm = args.getOrNull(1)?.value as Int? ?: 120
|
||||
val begin = args.getOrNull(2) ?: Value.note(Note(Pitch.C, 0, 4, false))
|
||||
val end = args.getOrNull(3) ?: Value.note(Note(Pitch.H, 5, 4, false))
|
||||
val channel = args.getOrNull(4)?.value as Int? ?: 1
|
||||
|
||||
if(channel > 16) {
|
||||
throw CustomException("MIDI standard supports max to 16 channels and that number has been exceeded")
|
||||
}
|
||||
|
||||
val notes = Value.list(
|
||||
listOf(Value.string("i:$instrument")) + environment.invokeFunction(
|
||||
"range",
|
||||
listOf(begin, end)
|
||||
).value as List<Value>
|
||||
).unwrap() as List<Any>
|
||||
|
||||
println(MidiSequencer.instruments[instrument])
|
||||
println("Channel: $channel")
|
||||
println("BPM: $bpm")
|
||||
println("Range: ${begin.value} - ${end.value}")
|
||||
|
||||
notes.forEachIndexed { index, it ->
|
||||
if (index > 0) {
|
||||
println(it)
|
||||
MidiSequencer.playChannels(mapOf(channel to listOf(listOf("i:$instrument", it))), mapOf("bpm" to bpm))
|
||||
Thread.sleep(100)
|
||||
}
|
||||
}
|
||||
|
||||
Value.void()
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -25,6 +25,9 @@ object MidiSequencer {
|
||||
const val ZERO = 0x00
|
||||
}
|
||||
|
||||
val instruments: List<String>
|
||||
get() = MidiSystem.getSynthesizer().availableInstruments.map { it.toString() }
|
||||
|
||||
fun playChannels(channels: Map<Int, List<List<Any>>>, config: Map<String, Any>) {
|
||||
val sequence = Sequence(Sequence.PPQ, PPQ)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user