Real-time MIDI

    

In May 2024, the Bol Processor BP3 acquired the abil­i­ty to man­age the input and out­put of MIDI events. This allows it to “com­mu­ni­cate” in real time with exter­nal MIDI devices (key­boards, syn­the­siz­ers) and even with oth­er instances of BP3 run­ning on the same machine.

For geeks and pro­gram­mers: This fea­ture had already been imple­ment­ed in the ear­li­er (MacOS only) ver­sion called ‘BP2’. However, the imple­men­ta­tion in a C lan­guage ‘con­sole’ to work in MacOS, Linux and Windows envi­ron­ments was more tech­ni­cal. In addi­tion, the con­cept of “real time” in the cur­rent set­up is dif­fer­ent from the pre­vi­ous one using Opcode Music System.

At the time of writ­ing, real-time MIDI does not com­pile well on Windows, and the Linux envi­ron­ment has not yet been tried. We are work­ing on this. The fol­low­ing exam­ples will work exact­ly the same in all envi­ron­ments. They have been test­ed on a recent MacOS (Sonoma) com­put­er.

Setting up the MIDI environment

Let us assume that you have suc­cess­ful­ly down­loaded, installed and com­piled the Bol proces­sor BP3 as described on the page Bol Processor ‘BP3’ and its PHP inter­face.

In Bol Processor jar­gon, a ‘project’ is either a gram­mar (with a ‘-gr’ pre­fix) or a set of data (with a ‘-da’ pre­fix). So cre­ate or load a sim­ple project, e.g. “-da.acceleration” which can be found in the “ctests” fold­er (down­load it here).

An output

By default, a project is set up to cre­ate MIDI files, as shown on the selec­tor. Make sure your project is work­ing! Then select Real-time MIDI and click SAVE.

The selec­tor will now dis­play a dif­fer­ent image, as shown below:

By default, it says that the MIDI ‘port’ used for send­ing events is the num­ber ‘0′, and the MIDI ‘port’ used for receiv­ing events is the num­ber ‘1’. This is the most com­mon sit­u­a­tion. However, we can­not rely on port num­bers alone, because they change when we turn on and off the MIDI devices con­nect­ed to the com­put­er. The only reli­able iden­ti­fi­ca­tion is its name, which is emp­ty by default.

First of all, check the MIDI out­put. Turn on a MIDI device (syn­the­siz­er, piano, etc.) con­nect­ed to the com­put­er. On my per­son­al Mac, I usu­al­ly use the Pianoteq syn­the­sis­er, which pro­duces a phys­i­cal mod­el syn­the­sis of var­i­ous key­board instru­ments. It com­mu­ni­cates with BP3 via a device called the Inter-Application Communication (IAC) archi­tec­tureread this if you need details.

The IAC dri­ver is installed by default on recent MacOS sys­tems. (It is a part of the CoreMIDI frame­work pro­vid­ed by Apple.) It allows you to cre­ate vir­tu­al MIDI devices that enable MIDI appli­ca­tions to com­mu­ni­cate inter­nal­ly with­in the same machine with­out requir­ing exter­nal MIDI hard­ware. Equivalent devices exist in the Linux and Windows envi­ron­ments, see below.

The IAC also com­mu­ni­cates with exter­nal MIDI devices via the USB ports, BlueTooth and pos­si­bly more net­work pro­to­cols. We’ll try it later.

To set up the IAC, run the Audio MIDI Setup appli­ca­tion (in the Utilities fold­er). Ask it to show “MIDI Studio”. On my per­son­al com­put­er, it looks like this: the IAC dri­ver, the Pianoteq syn­the­sis­er, a Pocket Key 15 key­board con­nect­ed to a USB port, and a Yamaha piano con­nect­ed by stan­dard MIDI cables and a MIDI/USB inter­face. The Yamaha piano appears grey because it is switched off.

On active MIDI devices you will see tri­an­gles indi­cat­ing input/output ports. These are used to con­nect devices direct­ly by draw­ing a ‘cable’ to con­nect them. We don’t need to use these ‘con­nec­tors’ as BP3 com­mu­ni­cates via the IAC MIDI ports.

The eas­i­est way to pro­ceed now is to run the project and see if any sounds are pro­duced… Whatever the result, at the end of the (poten­tial­ly silent) per­for­mance, you will see a Show all … mes­sages but­ton along with a blink­ing red sig­nal “=> 1 warn­ing”. Click on the but­ton to read detailed expla­na­tions of the fail­ure (or success):

Setting up MacOS MIDI sys­tem
MIDI out­put = 0: “Bus 1” 👉 the num­ber of your choice
MIDI out­put = 1: “Bus 2”
MIDI out­put = 2: “Pocket Key 25”
MIDI input = 0: “Bus 1”
MIDI input = 1: “Bus 2” 👉 the num­ber of your choice
MIDI input = 2: “Pocket Key 25”
BP3 will be inter­ac­tive
Warning: name of MIDI source or/and out­put changed (see above)

This all makes sense giv­en the Audi MIDI Setup shown above. The Bol Processor scanned all out­put and input MIDI ports. Given port ‘0’ as an out­put by default, it assigned it to “Bus 1” which the ‘port’ set up in IAC. It also assigned MIDI input to port ‘1’, but we won’t need this immediately.

If your syn­the­sis­er hap­pens to be con­nect­ed to “Bus 1”, you will hear sounds and the prob­lem is solved. Let us assume that you are run­ning Pianoteq and hear noth­ing. Open the set­tings of Pianoteq and select “Devices”. All you have to do is check “IAC Driver Bus 1”. You might also check oth­er inputs, includ­ing Pocket Key 25 if you want to con­nect your key­board direct­ly to Pianoteq, but these are extra procedures.

Opening Pianoteq set­tings informed us that it is com­mu­ni­cat­ing with IAC, and it sug­gest­ed to use a IAC ‘Bus’ for this communication. 

Screenshot

All you need to do to ensure that the con­nec­tion remains cor­rect when more devices are switched on/off and MIDI port num­bers change is to write the name “Bus 1″ to MIDI out­put. In the same way, you can write “Pocket Key 25″ (or what­ev­er is detect­ed as your input MIDI device) to MIDI input, as we may use it lat­er. Note that MIDI port num­bers are now irrel­e­vant, as names take prece­dence. BP3 will cor­rect them automatically.

To the right of the MIDI port name is anoth­er emp­ty field where you can enter a com­ment. For exam­ple, write “Pianoteq synth” to the right of “Bus 1”.

Let us now switch on the Yamaha piano, which is con­nect­ed via a USB MIDI inter­face. This is some­times tricky and has noth­ing to do with the BP3! The USB MIDI inter­face I use has a green light that indi­cates it has pow­er. However, if the piano is actu­al­ly com­mu­ni­cat­ing with it, we should see a flash­ing red light. I have found that some­times it is nec­es­sary to restart the com­put­er after switch­ing on the piano…

As soon as the red light flash­es, open the Pianoteq set­tings. Great! We can now see that the piano is recog­nised and con­nect­ed. The eas­i­est way to con­nect it to the BP3 is to delete the MIDI out­put name “Bus 1”, click SAVE, then PLAY. Whatever hap­pens, we’ll get a warn­ing and see the fol­low­ing diagnosis:

MIDI input = 1: “Pocket Key 25”
MIDI out­put = 0: “???”
Setting up MacOS MIDI sys­tem
MIDI out­put = 0: “Bus 1” 👉 the num­ber of your choice
MIDI out­put = 1: “Bus 2”
MIDI out­put = 2: “Pocket Key 25”
MIDI out­put = 3: “USB MIDI Interface
MIDI input = 0: “Bus 1”
MIDI input = 1: “Bus 2” 👉 the num­ber of your choice
MIDI input = 2: “Pocket Key 25” 👉 the name of your choice
MIDI input = 3: “USB MIDI Interface”
BP3 will be inter­ac­tive
Warning: name of MIDI source or/and out­put changed (see above)

As the MIDI input is iden­ti­fied as “Pocket Key 25”, it is cor­rect­ly con­nect­ing to port ‘2.’ But the Yamaha piano is iden­ti­fied as “USB MIDI Interface”. This is the name we need to copy to the MIDI out­put, then SAVE MIDI ports and PLAY.

We hear the out­put on the Yamaha piano, although port num­bers are incor­rect on the inter­face. The port num­bers (and names) will be fixed: as soon as you save or reload the project

Why does the name “Yamaha piano” appear in the Pianoteq set­tings, but not in the MIDI ports scanned by BP3? This is a mys­tery that expe­ri­enced users of a MIDI stu­dio could prob­a­bly solve…

An input

Setting up an input fol­lows exact­ly the same pro­to­col as set­ting up the out­put. For exam­ple, we can set up the input on “Pocket Key 25” as shown above. “USB MIDI Interface” (the Yamaha piano) is anoth­er pos­si­ble choice. Let us con­tin­ue with Pocket Key 25.

Connecting an input to BP3 is of lit­tle inter­est if BP3 does noth­ing with input events. As of this writ­ing, the only instruc­tion it can han­dle is “Wait for note…”. (The old syn­tax “IN wait for note…” is still valid.) This means that BP3 will stop play­ing until it receives a NoteOn of the note in ques­tion. Let us pro­gram this for example:

_script(Iwait for C3 chan­nel 1) _transpose(12) _vel(60) E2 • D2 E2 • _vel(65) B2 D2 E2 • G2 B2 D2 E2 • _vel(70) F#2 G2 B2 D2 E2 • Bb2 F#2 G2 B2 D2 E2 • _vel(75) C2 Bb2 F#2 G2 B2 D2 E2 • _vel(77) G#2 C2 Bb2 F#2 G2 B2 D2 E2 • _vel(80) A2 G#2 C2 Bb2 F#2 G2 B2 D2 E2 • _vel(85) Eb2 A2 G#2 C2 Bb2 F#2 G2 B2 D2 E2 • _vel(87) C#2 Eb2 A2 G#2 C2 Bb2 F#2 G2 B2 D2 E2 • _vel(90) F2 C#2 Eb2 A2 G#2 C2 Bb2 F#2 G2 B2 D2 E2

The script com­mand says that the per­for­mance should start when note C3 is received on MIDI chan­nel 1. To avoid any con­fu­sion about octave num­bers, I have writ­ten the name on the low­est key of my Pocket Key 25 (see pho­to). This con­fu­sion is made worse by the fact that the Italian/Spanish/French use low­er octave numbers!

So, the labelled key is the one we need to press to start the show. Let’s try it…

When the START but­ton is clicked, a flash­ing STOP but­ton is dis­played. The machine would wait for­ev­er unless the cor­rect MIDI event was received. The STOP but­ton — and the PANIC but­ton at the top right — can be used to abort the process clean­ly. If all goes well, press­ing C3 (on Pianoteq) should pro­duce this sound:

Harm Visser’s ‘-da.acceleration’ example
Note that the _transpose(12) instruc­tion plays note one octave higher!

(This lit­tle piece was com­posed by Harm Visser to illus­trate the peri­od nota­tion. Read his tuto­r­i­al.)

Multiple inter­rup­tions are of course pos­si­ble. Try this:

_script(wait for C3 chan­nel 1) _transpose(12) _vel(60) E2 • D2 E2 • _vel(65) B2 D2 E2 • G2 B2 D2 E2 _script(wait for C4 chan­nel 1) • _vel(70) F#2 G2 B2 D2 E2 • Bb2 F#2 G2 B2 D2 E2 • _vel(75) C2 Bb2 F#2 G2 B2 D2 E2 • _vel(77) G#2 C2 Bb2 F#2 G2 B2 D2 E2 • _vel(80) A2 G#2 C2 Bb2 F#2 G2 B2 D2 E2 • _vel(85) Eb2 A2 G#2 C2 Bb2 F#2 G2 B2 D2 E2 • _vel(87) C#2 Eb2 A2 G#2 C2 Bb2 F#2 G2 B2 D2 E2 • _vel(90) F2 C#2 Eb2 A2 G#2 C2 Bb2 F#2 G2 B2 D2 E2

Now the machine will start its per­for­mance after receiv­ing a NoteOn of C3. It will then stop after three beats and wait for a NoteOn of C4. A note­wor­thy detail is that one sec­ond after an inter­rup­tion, AllNotesOff is sent to all MIDI chan­nels and the ped­als are set to off. This pre­vents notes wait­ing for their NoteOff from being heard.

MIDI input filters

Let us work with the con­tin­u­ous impro­vi­sa­tion called “Mozart’s musi­cal dice game” (called “-gr.Mozart” in the “ctests” fold­er. If this project is set for real-time MIDI, the impro­vi­sa­tion will not stop until we click on the STOP or PANIC but­ton. Inserting as “wait for note…” at the begin­ning would of course stop the per­for­mance on every vari­a­tion. Beware that you will have to write “do2” instead of “C3” due to the note convention!

But let’s try some­thing else, using the exter­nal key­board (the Pocket Key 25 or Yamaha piano) to play notes on top of the per­for­mance. How strange! We don’t hear any notes played on the exter­nal key­board unless it’s con­nect­ed direct­ly to the out­put device.

The rea­son for this becomes clear after click­ing on the FILTER but­ton for MIDI input 2:

All types of MIDI events are list­ed along with how they are processed by BP3. Here we are only inter­est­ed in NoteOn/NoteOff events. The default set­ting is ‘1’, which means that they can trig­ger script com­mands, but are not for­ward­ed to the MIDI out­put. This is why ‘do2’ was able to start the per­for­mance, although we could not hear it.

To play notes over the per­for­mance, we need to set the sta­tus of NoteOn and NoteOff to ‘2’. Note: If we only set the NoteOn sta­tus, BP3 will auto­mat­i­cal­ly set the NoteOff sta­tus to avoid con­fu­sion. Once you have changed the set­tings, click SAVE then PRODUCE ITEM(S).

Since the Pocket Key 25 key­board sends only NoteOn/Noteoff mes­sages, we could as well set oth­er event fil­ters (KeyPressure, etc.) to ‘0’.

These fil­ter set­tings are stored, togeth­er with the MIDI port names or num­bers, in a tem­po­rary file whose name depends on both the ses­sion num­ber (cre­at­ed by your brows­er) and the project name. A copy of these set­tings is stored in the (per­ma­nent) fold­er “midi_resources”. This stor­age makes it pos­si­ble to launch sev­er­al instances of BP3 on the same brows­er or on dif­fer­ent browsers, as we will now see.

Several BP3 performing and communicating

From the pre­vi­ous descrip­tion of inter­ac­tions via MIDI events — lim­it­ed for the time being to wait­ing for a par­tic­u­lar note — you may have guessed that a great fea­ture of the Bol Processor BP3 envi­ron­ment is the pos­si­bil­i­ty of run­ning sev­er­al BP3s, on dif­fer­ent machines, or even on a sin­gle machine and the same brows­er… in coop­er­a­tion with peo­ple play­ing MIDI instruments.

Each instance of BP3 can be thought of as a ‘musi­cian’ with their own com­po­si­tion­al skills embed­ded in a gram­mar or a set of pre-composed ele­ments. We are work­ing on inter­ac­tions that will allow each musi­cian to mod­i­fy the behav­iour of anoth­er musi­cian’s gram­mar, for exam­ple by chang­ing rule weights — which may result in some rules being sup­pressed while oth­ers are dis­played — or chang­ing metronome set­tings if they want to play faster/slower, etc. All these fea­tures were already part of ear­li­er ver­sions (BP2) sev­er­al decades ago!

Now we will check an extreme­ly sim­ple exam­ple using the “wait for note…” script.

Create two projects that con­tain only data, for exam­ple “-da.Beatrix” and “-da.Alan”:

-se.Beatrix
{2, C#4 Eb4 A4 G#4 C4 Bb4 F#4 G4 B4 D4 E4}

-se.Alan
_script(wait for E4 chan­nel 1) {2, - F3 C#3 Eb3 A3 G#3 C3 Bb3 F#3 G3 B3 D3 E3}

Note that these melodies do not con­tain the same num­ber of notes, but they will have the same dura­tion (2 beats) because of their poly­met­ric structures.

We want Alan’s per­for­mance to start pre­cise­ly after the last note of Beatrix’s per­for­mance. As we don’t want E4 to over­lap with F3, we have put a silence ‘-’ before F3.

To man­age the inter­ac­tion, we need an addi­tion­al IAC port which is (auto­mat­i­cal­ly) named “Bus2″. To do this, open Audi MIDI Setup and click on the IAC dri­ver. Then add a port (see pic­ture). You can cre­ate as many ports as you wish.

Set both Beatrix’s MIDI out­put and Alan’s MIDI input to “Bus2″.

Now we want to hear both per­for­mances. Alan’s MIDI out­put is sent to “Bus1″ and will there­fore be audi­ble on the Pianoteq synthesiser.

There are two ways to send Beatrix’s per­for­mance to the Pianoteq synthesiser:

  • Pianoteq set­tings make it pos­si­ble to lis­ten to both “Bus1″ and “Bus2″.
  • You can set up the MIDI event fil­ter on Alan’s project to route input NoteOn/NoteOff events to the cur­rent MIDI out­put. See above for filters.

To play the per­for­mance, click PLAY on Alan’s project so that it is ready to per­form. Then click PLAY on Beatrix’s project. This is the result:

Two phras­es played in sequence by two instances of the BP3 (Beatrix & Alan).

No doubt this sounds rather unmu­si­cal! In fact, we only pub­lish taste­less tech­ni­cal exam­ples to encour­age musi­cians to com­pose inter­est­ing pieces! 😀

Checking the time accuracy

Let us check that the real-time syn­chro­ni­sa­tion is not affect­ed by delays. We’ll now ask Alan and Beatrix to play the same piece of music (one octave apart) in the same time.

This time, Alan will start:

_transpose(12) _vel(60) E2 • D2 E2 • _vel(65) B2 D2 E2 • G2 B2 D2 E2 • _vel(70) F#2 G2 B2 D2 E2 • Bb2 F#2 G2 B2 D2 E2 • _vel(75) C2 Bb2 F#2 G2 B2 D2 E2 • _vel(77) G#2 C2 Bb2 F#2 G2 B2 D2 E2 • _vel(80) A2 G#2 C2 Bb2 F#2 G2 B2 D2 E2 • _vel(85) Eb2 A2 G#2 C2 Bb2 F#2 G2 B2 D2 E2 • _vel(87) C#2 Eb2 A2 G#2 C2 Bb2 F#2 G2 B2 D2 E2 • _vel(90) F2 C#2 Eb2 A2 G#2 C2 Bb2 F#2 G2 B2 D2 E2

Alan will send MIDI events to “Bus2″. Beatrix will lis­ten to “Bus2″ and send MIDI events to “Bus1″ (Pianoteq). Beatrix will have a fil­ter that routes the received events to the out­put. The Pianoteq syn­the­sis­er will be set to lis­ten to “Bus1″ only.

This is the score of Beatrix:

_script(wait for E3 chan­nel 1) _transpose(24) _vel(60) E2 • D2 E2 • _vel(65) B2 D2 E2 • G2 B2 D2 E2 • _vel(70) F#2 G2 B2 D2 E2 • Bb2 F#2 G2 B2 D2 E2 • _vel(75) C2 Bb2 F#2 G2 B2 D2 E2 • _vel(77) G#2 C2 Bb2 F#2 G2 B2 D2 E2 • _vel(80) A2 G#2 C2 Bb2 F#2 G2 B2 D2 E2 • _vel(85) Eb2 A2 G#2 C2 Bb2 F#2 G2 B2 D2 E2 • _vel(87) C#2 Eb2 A2 G#2 C2 Bb2 F#2 G2 B2 D2 E2 • _vel(90) F2 C#2 Eb2 A2 G#2 C2 Bb2 F#2 G2 B2 D2 E2

To start the per­for­mance, first click on the PLAY but­ton of Beatrix’s project, then on the PLAY but­ton of Alan’s project.

Have you noticed that Beatrix is wait­ing for E3, which does not appear in Alan’s score? Oh yes, it does! There is a _transpose(12) com­mand that changes E2 (the first note) to E3. So, it works. This is the performance:

Two super­im­posed per­for­mances (one octave apart), played by two instances of the BP3 (Beatrix & Alan).

Not too bad? Despite the lack of musi­cal inter­est, we must admit that the super­im­po­si­tion is tech­ni­cal­ly accept­able, even if it is not per­fect: there is a delay of about 60 mil­lisec­onds on the first note, the time it takes Beatrix’s machine to detect that it has received a NoteOn for C3. The sub­se­quent notes are pro­grammed to com­pen­sate for this delay, but there are still dis­crep­an­cies (which can be quan­ti­fied on the Pianoteq’s MIDI input). They seem to be caused by delays out­side BP3.

You can adjust the delay in Beatrix’s project set­tings. There is a para­me­ter called “Sync delay”, which is the num­ber of mil­lisec­onds Beatrix’s out­put events should be post­poned after syn­chro­ni­sa­tion. We cur­rent­ly find that 380 ms is a good value.

In fact, the super­im­po­si­tion would sound even bet­ter if both per­for­mances were trig­gered by the same event, such as the con­duc­tor press­ing a key on the exter­nal key­board. This exer­cise was only intend­ed to show that syn­chro­ni­sa­tion between “vir­tu­al musi­cians” works well.

Working with multiple MIDI inputs

In the pre­vi­ous exam­ple, we could decide that Alan’s per­for­mance will start when he receives a par­tic­u­lar note from the Pocket Key 25 key­board. In this case, we need to click on both START but­tons, putting both ‘musi­cians’ in wait mode, but the per­for­mance will not start until the cor­rect key is pressed on the keyboard.

This case is man­age­able with sin­gle inputs on each instance of BP3. More com­pli­cat­ed cas­es, how­ev­er, require exter­nal ‘actors’, such as a Pocket Key 25 key­board send­ing to all the ‘musi­cians’ syn­chro­ni­sa­tion mes­sages, or mes­sages mod­i­fy­ing para­me­ters in gram­mars, chang­ing the metronome val­ue, etc.

To achieve this, the BP3 is a able to man­age mul­ti­ple MIDI inputs.

The new game is as fol­lows: both Beatrix and Alan will take turns play­ing vari­a­tions of Mozart’s musi­cal dice game (see ‘-gr.Mozart’), one octave apart. They will use the Improvise mode to con­tin­ue throw­ing the dice and cre­at­ing vari­a­tions. But they will wait for a sig­nal from the oth­er to start play­ing a new variation.

In short, both musi­cians will use the same gram­mar, with only a small change for mutu­al syn­chro­ni­sa­tion. Their set­tings must be care­ful­ly adjusted:

  • Select Italian/Spanish/French as a note convention
  • Check Non-stop impro­vise
  • Adjust Pclock = 3 and Qclock = 11 to get the same metronome speed of 220 bpm
  • Set Sync delay to 380 ms
  • We do’t want both musi­cians to repeat the same vari­a­tions. So, set the Seed for ran­dom­iza­tion to dif­fer­ent val­ues, for instance ‘1’ and ‘2’. Or set it to zero to instruct the machine to reseed the sequence with an arbi­trary num­ber of its choice.

In the cur­rent ver­sion of BP3, the eas­i­est way to send a sig­nal is to send a note with a veloc­i­ty of zero, which will there­fore go unheard. So we need to change the gram­mar to add these par­tic­u­lar notes.

In fact, the same notes should nev­er be part of the score, so that the sig­nal is real­ly sent at the end. This is easy with Mozart’s game, for exam­ple we can use C# for syn­chro­ni­sa­tion. Below are the tops of the gram­mars used by Beatrix and Alan.

Beatrix ‘-gr.Beatrix’:

-se.Beatrix
ORD
gram#1[1] S --> _script(wait for do#3 chan­nel 1) _vel(80) A B _vel(0) do#2
gram#1[2] A --> A1 A2 A3 A4 A5 A6 A7 A8 A1 A2 A3 A4 A5 A6 A7 A’8
gram#1[3] B --> B1 B2 B3 B4 B5 B6 B7 B8 B1 B2 B3 B4 B5 B6 B7 B8 -------------------
LIN [Select rules ran­dom­ly and apply from left to right]
etc.

Alan’s ‘-gr.Alan’:

-se.Alan
ORD
gram#1[1] S --> _script(wait for do#2 chan­nel 1) _vel(80) _transpose(-12) A B _vel(0) do#4
gram#1[2] A --> A1 A2 A3 A4 A5 A6 A7 A8 A1 A2 A3 A4 A5 A6 A7 A’8
gram#1[3] B --> B1 B2 B3 B4 B5 B6 B7 B8 B1 B2 B3 B4 B5 B6 B7 B8 -------------------
LIN [Select rules ran­dom­ly and apply from left to right]
etc.

Again, we put do#4 at the end of Alan’s per­for­mance because it is played as do#3 (one octave low­er) due to the _transpose(-12) instruc­tion.

Now we need to set up the MIDI inputs and out­puts. Beatrix will send events to “Bus 1″ which is the Pianoteq syn­the­siz­er. She will receive events from “Bus 2″, use them for syn­chro­ni­sa­tion, and for­ward them to the output.

Alan will send events to “Bus 2″ and lis­ten to “Bus 1″ for the synchronisation.

This is all per­fect on paper, but who is going to start? We have cre­at­ed a chick­en and egg sit­u­a­tion, so we need a super­pow­er to start the process! Actually, a nor­mal per­son press­ing a key on a Pocket Key 25 key­board will do.

The (recent) inter­face has a Add an input but­ton. We click it on Alan’s project and paste the name Pocket Key 25. We also use the com­ment fields to remem­ber the use of each port:

To start the con­cert, we’ll click START on both projects. The order is irrel­e­vant. Then we’ll press a key on the Pocket Key 25. Which key?

If we press the do#2 key, we will cer­tain­ly trig­ger Alan’s impro­vi­sa­tion and the cycle will start. But if we press the do#3 key, noth­ing will hap­pen because the fil­ter of the Pocket Key 25’s input, by default, does not trans­mit NoteOns to the out­put. So Beatrix won’t hear it… By set­ting NoteOn to sta­tus ‘2’ (accept and for­ward) on this fil­ter, it will be pos­si­ble to decide who will start the per­for­mance: do#2 for Alan and do#3 for Beatrix.

Here we go (start­ing with Alan):

Alan and Beatrix (two instances of BP3) play­ing vari­a­tions of Mozart’s musi­cal dice game

👉  This sim­ple show should con­vince musi­cians to cre­ate “vir­tu­al bands” of BP3s play­ing dif­fer­ent gram­mars and send­ing spe­cif­ic syn­chro­ni­sa­tion sig­nals accord­ing to which vari­a­tion has just been pro­duced. Along with human per­form­ers who join in the fun!

The “vir­tu­al musi­cians” can be on the same com­put­er or remote­ly con­nect­ed via net­work (BlueTooth) or MIDI cables and USB inter­faces. If they are on the same com­put­er, they can be run on dif­fer­ent browsers and/or the same brows­er. In the lat­ter case, BP3 will not allow the same project to be run in the same session.

The num­ber of MIDI inputs in a project is cur­rent­ly lim­it­ed to 32. It is very unlike­ly that a musi­cian will need more!

Synchronise to a sequence of notes

The fol­low­ing expression

gram#1[1] S --> _script(wait for C3 chan­nel 1) _script(wait for E3 chan­nel 1) etc.

syn­chro­nis­es the pro­duc­tion to the sequence of notes C3 E3 (what­ev­er the dura­tion and veloc­i­ty). This cre­ates inter­est­ing sit­u­a­tions where a “vir­tu­al musi­cian” is expect­ed to start play­ing after receiv­ing a sig­nal (C3) from one part­ner, then a sig­nal (E3) from anoth­er partner.

Remember that because of the MIDI chan­nel spec­i­fi­ca­tion (range 1 to 16), the detec­tion of sig­nals can be very selec­tive. They are also inaudi­ble when trans­mit­ted by NoteOns with veloc­i­ty zero.

Crashing the band!

In the exam­ple of Alan & Beatrix play­ing Mozart, the con­nec­tion seems to cre­ate a loop: Beatrix sends events to Pianoteq and Alan (bus 1), who in turn sends events to Beatrix (bus 2). Isn’t that dangerous?

The rea­son it does­n’t crash is that Alan’s input “fromBeatrix” (Bus 1) is fil­tered: NoteOns are received and processed (for syn­chro­ni­sa­tion), but not passed to the out­put (Bus 2), i.e. to Beatrix. You can try to change the fil­ter of input “Bus1” on Alan’s project, set­ting NoteOns to sta­tus ‘2’ (treat + pass): you will get a superb crash after a flood of notes!

BP3 also per­forms an inter­nal check to ensure that two inputs can­not be assigned to the same port, and that no input uses the same port as an input, as these sit­u­a­tions would result in fatal loops.

Working with multiple MIDI outputs

The BP3 accepts an unlim­it­ed num­ber of MIDI out­puts. In fact, the num­ber assigned to the MIDI ports is lim­it­ed to the num­ber of MIDI devices available…

Example of a project using two inputs and two outputs:

A set­up with two MIDI out­puts and two MIDI inputs

The pro­ce­dure for adding out­puts is the same as the one for adding inputs: click on the Add an out­put but­ton, then enter the name of the MIDI device if you know it exact­ly, oth­er­wise leave it blank and let the machine con­nect it by default to the next avail­able out­put, while sug­gest­ing oth­er options:

Your real-time MIDI set­tings:
MIDI out­put = 0: “Bus 1” - Pianoteq
MIDI out­put = 3: “USB MIDI Interface” - Yamaha piano
MIDI input = 1: “Bus 2” - from Alex
MIDI input = 2: “Pocket Key 25” - a small key­board

🎹 Setting up MacOS MIDI sys­tem
MIDI out­put = 0: “Bus 1” 👉 the name of your choice
MIDI out­put = 3: “USB MIDI Interface” 👉 the name of your choice
MIDI input = 1: “Bus 2” 👉 the name of your choice
MIDI input 1 makes BP3 inter­ac­tive
MIDI input = 2: “Pocket Key 25” 👉 the name of your choice
MIDI input 2 makes BP3 inter­ac­tive

🎶 More MIDI out­put options were avail­able:
MIDI out­put = 1: “Bus 2”
MIDI out­put = 2: “Pocket Key 25”

🎶 More MIDI input options were avail­able:
MIDI input = 0: “Bus 1”
MIDI input = 3: “USB MIDI Interface”

Filtering MIDI outputs

In the exam­ple above, MIDI out­put 3 (the Yamaha piano con­nect­ed to the USB MIDI Interface) has the fol­low­ing filter:

A fil­ter for MIDI out­put 3

The chan­nel fil­ter spec­i­fies that this instru­ment will receive all MIDI chan­nels except num­ber 2. Filtering MIDI chan­nels makes it pos­si­ble to send events exclu­sive­ly to dif­fer­ent instruments.

In this set­up, for exam­ple, chan­nel 2 events can be sent exclu­sive­ly to MIDI out­put 0 (Pianoteq). This allows parts of the musi­cal work to be played by spe­cif­ic instruments.

MIDI events can also be fil­tered by type. The idea is the same as for MIDI input fil­ters, see above.

Using standard MIDI control

MIDI has stan­dard con­trol mes­sages, name­ly Start, Continue and Stop, which can be used to coor­di­nate mul­ti­ple “vir­tu­al musi­cians” (instances of BP3). The advan­tage is the clar­i­ty of the data and the gram­mars pro­grammed for inter­ac­tions. The dis­ad­van­tage is that these mes­sages are not assigned to spe­cif­ic MIDI chan­nels. This can be a prob­lem with a large num­ber of “musi­cians”.

Let us look at a triv­ial exam­ple (of no musi­cal inter­est), again with Beatrix and Alan play­ing togeth­er, but this time they take turns play­ing their items (sim­ple sequences of notes). The same approach can be used with gram­mars where each part is an impro­vi­sa­tion, as we have shown with the Mozart example.

Alan will start first. Below is the data:

E3 D3 C3 _script(MIDI send Start) _script(wait for Continue) A2 B2 C3

In short, he will play three notes (E3 D3 C3), then send a START to Beatrix, then wait for a CONTINUE from Beatrix, and play the final three notes A2 B2 C3.

This is Beatrix’s data:

_script(wait for Start) E4 D4 C4 _script(MIDI send Continue)

So, with Beatrix’s data play­ing, we’ll start the per­for­mance. Her sys­tem will wait for START. Then we’ll start Alan’s data, which will play three notes, then hand over to Beatrix, who will play her part, and return to Alan for the final part…

Start and Continue should be “heard” by Beatrix. Automatically, Stop will have the same status.

This all sounds log­i­cal, but it does­n’t work! We hear Alan’s E3 D3 C3, but then noth­ing… The first rea­son is that Beatrix should be able to hear Alan’s START com­mand, which is no longer a NoteOn as in the pre­vi­ous exam­ples. This means that the fil­ter of her input “Bus 2”, from which she receives Alan’s MIDI mes­sages, must be set cor­rect­ly. The Start event should be received, see pic­ture on the side. Also remem­ber that NoteOn and NoteOff should be received and trans­mit­ted to the out­put (the Pianoteq synth).

Well, now we hear Alan’s E3 D3 C3 fol­lowed with Beatrix’s E4 D4 C4, but then… nothing! 😢

Careful analy­sis is need­ed to solve the prob­lem. But this is sim­ple log­ic. Remember that Alan is play­ing on “Bus 2”, which is not con­nect­ed to any MIDI device. If we hear Alan’s pro­duc­tion, it is because it is received by Beatrix on “Bus 2” and then sent to “Bus 1” (the Pianoteq synth). The prob­lem is that the final part A2 B2 C3 is sent to Beatrix, but she has already stopped lis­ten­ing because her own data is finished!

You can imag­ine a band in which one musi­cian plays an impro­vi­sa­tion and then gives a sig­nal to anoth­er musi­cian to start their own impro­vi­sa­tion, but the oth­er musi­cian has left the place think­ing that the pro­gramme was fin­ished. The solu­tion is to tell the musi­cians not to leave their places until they receive a STOP sig­nal. Maybe a sig­nal from a con­duc­tor (here using the Pocket Key 25 key­board), maybe a sig­nal from the musi­cian who is in charge of end­ing the per­for­mance. So we’ll tell Alan to send a STOP sig­nal at the end of his per­for­mance, and Beatrix to wait for Alan’s STOP sig­nal. Below are the revised scores.

// Alan
E3 D3 C3 _script(MIDI send Start) _script(wait for Continue) A2 B2 C3 _script(MIDI send Stop)

// Beatrix
_script(wait for Start) E4 D4 C4 _script(MIDI send Continue) _script(wait for Stop)

The MIDI mes­sages Start, Continue, Stop have been used here to facil­i­tate the read­ing of scores (or gram­mars), but these can be replaced by NoteOn with veloc­i­ty zero on dif­fer­ent MIDI chan­nels when work­ing with a larg­er num­ber of actors.

For geeks: In the Bol proces­sor, scripts are append­ed to the next fol­low­ing sound object. For exam­ple, _script(wait for Start) is append­ed to note E4 in Beatrix’s score. But what about scripts at the end of a score? The secret is that BP3 cre­ates an invis­i­ble MIDI event (ActiveSensing) at the end of each ele­ment to which it can append the final scripts.

List of scripts for dealing with real-time MIDI

The list below will be kept up to date as there are many scripts on the agen­da. These instruc­tions are not case-sensitive.

Input scripts

Wait for _note_ chan­nel _1…16_Wait for a NoteOn of the spec­i­fied note on the spec­i­fied channel
Wait for StartWait for a Start MIDI mes­sage (250)
Wait for ContinueWait for a Continue MIDI mes­sage (251)
Wait for StopWait for a Stop MIDI mes­sage (252)

Output scripts

Hold for … millisecondsDelay all sub­se­quent events by the spec­i­fied duration
Send StartSend MIDI mes­sage (250)
Send ContinueSend MIDI mes­sage (251)
Send StopSend MIDI mes­sage (252)

Alternatives to IAC

👉  The fol­low­ing is an (unver­i­fied) expla­na­tion from ChatGPT… In a few days (mid-June 2024), we’ll install Windows 10 and Linux in a dual boot on a refur­bished com­put­er. This will make it eas­i­er to fin­ish and fix the com­pi­la­tion in these environments.

Here are the equiv­a­lents of Apple’s IAC (Inter-Application Communication) for each system:

Windows environment

On Windows, you can use soft­ware like loopMIDI or virtualMIDISynth to cre­ate vir­tu­al MIDI ports. These tools work sim­i­lar­ly to the IAC Driver on macOS:

  • loopMIDI: Created by Tobias Erichsen, loopMIDI is a pop­u­lar choice for cre­at­ing vir­tu­al MIDI ports on Windows. It allows you to cre­ate and man­age sev­er­al vir­tu­al ports which can be used by appli­ca­tions to com­mu­ni­cate with each other. 
  • virtualMIDISynth: This is anoth­er tool that can be used to cre­ate a MIDI syn­the­siz­er device which can be accessed via a vir­tu­al MIDI cable. 

These tools inte­grate with soft­ware appli­ca­tions that sup­port MIDI, pro­vid­ing a seam­less way to con­nect var­i­ous MIDI appli­ca­tions with­out need­ing exter­nal MIDI hardware.

Linux environment

On Linux, ALSA (Advanced Linux Sound Architecture) pro­vides capa­bil­i­ties to cre­ate vir­tu­al MIDI devices through its sequenc­ing API:

  • snd-virmidi: This ALSA MIDI dri­ver pro­vides vir­tu­al MIDI ports for send­ing and receiv­ing MIDI between appli­ca­tions run­ning on the same sys­tem. It’s part of the stan­dard ALSA mod­ule set and can be con­fig­ured to pro­vide mul­ti­ple ports.

To set up vir­tu­al MIDI ports on Linux using ALSA, you typ­i­cal­ly need to load the snd-virmidi mod­ule. You can do this by running:

sudo mod­probe snd-virmidi midi_devs=1

This com­mand loads the snd-virmidi mod­ule and sets it up to pro­vide one vir­tu­al MIDI device (you can increase the num­ber of devices by chang­ing the midi_devs para­me­ter). The vir­tu­al ports can then be accessed by MIDI appli­ca­tions on the Linux system.

Integration in Code

For both Windows and Linux, once you have the vir­tu­al MIDI ports set up, appli­ca­tions can open these ports using respec­tive APIs pro­vid­ed by the sys­tem or third-party libraries. In Windows, you might use the Windows MIDI API (part of the Win32 API), and on Linux, you can use the ALSA API to inter­face with these ports.

Here’s a brief overview of how you might use these in code:

  • Windows MIDI API: You would use func­tions like midiOutOpen, midiOutShortMsg, midiInOpen, etc., to send and receive MIDI data.
  • ALSA Sequencer API: On Linux, func­tions from the ALSA library, such as snd_seq_open, snd_seq_event_input, snd_seq_event_output, etc., are used to manip­u­late MIDI data.

These tools and APIs pro­vide robust sup­port for vir­tu­al MIDI con­nec­tions, facil­i­tat­ing diverse musi­cal and audio appli­ca­tion setups across dif­fer­ent oper­at­ing systems.

Leave a Reply

Your email address will not be published. Required fields are marked *