(MacOS only for now…) Now works on Windows too - and opcodes names have been updated…
The ability to read MIDI files within an instrument has always been missing in Csound, until now Last week I pushed two new Cabbage opcodes to the code base. You can try them out with the latest dev build of Cabbage. They are relatively untested, so be gentle! I will add them to the docs once they have been properly tested.
Opcodes described below.
cabbageMidiFileInfo Opcode
This opcode takes a path to a MIDI file and prints some useful debug information about the file, including the file type, the last time stamp, the number of tracks, a list and all time changes and a list of all time signature changes, listed by timestamps in seconds
The channels can hold strings or numbers, but only numeric channels work with the optional threshold arguments.
Added in Cabbage v2.9.5
Syntax
cabbageMidiFileInfo SMidifile
Initialization
-
SMidifile
– midi filename, must be an absolute path
cabbageMidiFileReader Opcode
This opcode outputs an array of MIDI events in the form of numbers (ala midiin
, alongside a trigger signal to indicate an event has been received. The number of events received in each k-cycle is also output.
Added in Cabbage v2.9.5
Syntax
kStatus[], kChan[], kNote[], kVel[], kNumEvents, kTrig cabbageMidiFileReader SMidifile, iTrackNum, kPlay, kSpeedFactor[, iSkipTime]
Initialization
-
SMidifile
– midi filename, must be an absolute path -
iTrackNum
– the track number you wish to read. (Use the cabbageMidiFileInfo opcode to determine the number of tracks if you are sure) -
iSkipTime
(optional) – sets the initial skip time in second, defaults to 0.
Performance
-
kPlay
– set to 1 start playback, 0 to pause. -
kSpeedFactor
– used to increase/decrease playback speed. This basically acts as a timestamp multiplier. Larger values will slow down playback, while smaller values will increase playback speed.
Example
<Cabbage>
form caption("Midi playback") size(400, 100), colour(40), guiMode("queue") pluginId("def1")
rslider bounds(114, 8, 60, 60) channel("transpose") range(-24, 24, 0, 1, 1), text("Transpose")
checkbox bounds(8, 8, 100, 30) channel("play"), text("Play"),
rslider bounds(178, 8, 60, 60) channel("speed") range(0.5, 2, 1, 1, 0.001), text("Speed")
</Cabbage>
<CsoundSynthesizer>
<CsOptions>
-n -d -m0d
</CsOptions>
<CsInstruments>010
; Initialize the global variables.
ksmps = 128
nchnls = 2
0dbfs = 1
instr 1
SCsdPath chnget "CSD_PATH"
SMidifile init sprintf("%s/Prelude1.mid", SCsdPath)
cabbageMidiFileInfo SMidifile
kEventIndex = 0
kNoteIndex init 0
kStatus[], kChan[], kNote[], kVel[], kNumEvents, kTrig cabbageMidiFileReader SMidifile, 1, cabbageGetValue("play"), cabbageGetValue("speed"), 0
knotelength init 0
knoteontime init 0
if kTrig == 1 then
while kEventIndex < kNumEvents do
if (kStatus[kEventIndex] == 128) then //note off
turnoff2 2, 1, 1
elseif (kStatus[kEventIndex] == 144) then //note on
event "i", 2, 0, 10, kNote[kEventIndex]+cabbageGetValue:k("transpose"), kVel[kEventIndex]/127
endif
kEventIndex += 1
od
endif
endin
instr 2
kEnv madsr 0.1, .2, .6, .1
a1 oscili kEnv*p5, cpsmidinn(p4), 1
outs a1*.01, a1*.01
endin
</CsInstruments>
<CsScore>
f1 0 4096 10 1 0 .25 0 .17
;causes Csound to run for about 7000 years...
f0 z
;starts instrument 1 and runs it for a week
i1 0 [60*60*24*7]
;i3 0 10
</CsScore>
</CsoundSynthesizer>