A problem with playing midi input on Sonic Pi, is that it is difficult to use the incoming note duration directly. This is because a midi signal specifies the start of a note, but doesn’t specify its duration, instead sending another signal when the note finishes. Conversely Sonic Pi programs its internal synths to play a given pitch for a set duration, which is specified when the note starts playing. Thus, you have to compromise and set a convenient duration time for a note when it starts, which is hopefully not far off the correct duration for the note. You can mask this to a certain extent by using :release to specify the time, so that the note dies away as it is played, and also adding reverb can also help to mask the note durations. There are two alternatives. one is to process the midi input in advance, and use an algorithm to convert to to Sonic Pi notation. Such an algorithm was produced byHiroshi TACHIBANA and I wrote an article about its use here and have used it extensively to convert midi files for Sonic Pi use. However, this is no good for live performances, and so I have recently worked on a second method to solve the problem. That is to use a gated synth. In this case, it works by switching on a note as the midi note_on signal is received, and turns it off again as the corresponding note_off signal is received, so the note can be any duration, as specified by the length of the incoming midi note.
I had recently experimented with a “long note” synth, where I started a note of long duration (say 1000 seconds) and then switched it on and off by altering the volume of the note. You could also alter the pitch of the note and other characteristics such as the cutoff value as the note played. It looked promising so I developed this into a polyphonic system with up to 8 parallel notes playing and attempting to switch them on and off by gating the volume setting. In the event, it became rather complicated, and the processing power needed caused timing errors and program drop outs, so eventually I abandoned this in favour of a similar although simpler system. In the new system, instead of switching the note’s volume on and off, I started a new note at the beginning of each midi note_on event, and then maintained that note until the corresponding note_off event. I decided on having up to 8 possible notes playing at the same time, and devised a rather crude scheduling system which allocated a free “note generator” to each note as it was demanded, and then kept track of that note until it was finished, when the “note-generator” was again marked as available for re-use. I just had to keep track of which note was which, so that I knew which one to release when a note_off event was received. (In fact the note_off events where just note_on events with the velocity (or volume) parameter set to zero. The timing of the loops concerned was fairly critical, and I made a lot of use of the set and get commands available in Sonic Pi 3 for recording events and values in the timing log from which they could be retrieved. The system is running close to the limit, and has several timing error warnings, but it does seem robust to keep going regardless.However one consequence is that at present it is not viable to run on a Raspberry Pi 3, although I have tested it satisfactorily on a Mac PowerBook, and on Ubuntu 17.04
The program is split into two parts, because it is too long for a single buffer. However the first part, which merely sets up state information, only needs to be run once, and then remains active until Sonic Pi is shut down. Otherwise the program is fairly easy to follow, the heart consisting of 8 identical synth engines, together with a midi input live_loop which contains the logic to allocate the synths to the received notes.
To keep the program short enough to fit the buffers, I am afraid that I have not added my usual copious comments to it.
You can download the program files here together with an xml file to generate the touch OSC file. IT would be fairly easy to substitute another means of supplying the external input (choice of synth etc) if required.
There is also a video of the project in action here