Control of NoteOn/NoteOff

   

This page is intend­ed for devel­op­ers of the Bol Processor BP3 (read instal­la­tion). It is not a for­mal descrip­tion of the algo­rithms car­ried by the console's C code, but rather an illus­tra­tion of their man­age­ment of musi­cal process­es, which may be use­ful for check­ing or extend­ing algorithms.

When the Bol Processor pro­duces MIDI mate­r­i­al (real-time or files), each note is asso­ci­at­ed with two events: a NoteOn at its begin­ning and a NoteOff at its end. Additional para­me­ters are its veloc­i­ty (range 0 to 127) and its MIDI chan­nel (range 1 to 16).

When a key­board instru­ment is used to pro­duce the sound, each NoteOn will press a key at the appro­pri­ate loca­tion. By default, note C4 (in English nota­tion) will press key #60. A NoteOff of the same pitch will release the key.

All exam­ples on this page can be found in the "-da.checkNoteOff" project. NoteOn/NoteOff track­ing can be enabled by select­ing this option in the "-se.checkNoteOff" set­tings of the project.

Read also: Csound check­up

Superimposed notes

Consider this example:

{C4____, -C4__-, --C4--} D4

Two (or more) con­sec­u­tive NoteOns of the same note and the same chan­nel should not be sent to a MIDI instru­ment. Nevertheless, the attacks of C4, which occur at the 1.00 s and 2.00 s times in this exam­ple, should be audi­ble. To achieve this, they are auto­mat­i­cal­ly pre­ced­ed by a NoteOff.

The list of NoteOn/NoteOff events is as follows:

NoteOn C4 chan­nel 1 at 0 ms
NoteOff C4 channel 1 at 1000 ms
NoteOn C4 chan­nel 1 at 1000 ms
NoteOff C4 channel 1 at 2000 ms
NoteOn C4 chan­nel 1 at 2000 ms
NoteOff C4 chan­nel 1 at 5000 ms
NoteOn D4 chan­nel 1 at 5000 ms
NoteOff D4 chan­nel 1 at 6000 ms

This fea­ture is not nec­es­sary for the cre­ation of Csound scores. The score gen­er­at­ed by this exam­ple is as follows:

i1 0.000 5.000 8.00 90.000 90.000 0.000 0.000 0.000 0.000 ; C4
i1 1.000 3.000 8.00 90.000 90.000 0.000 0.000 0.000 0.000 ; C4
i1 2.000 1.000 8.00 90.000 90.000 0.000 0.000 0.000 0.000 ; C4
i1 5.000 1.000 8.02 90.000 90.000 0.000 0.000 0.000 0.000 ; D4

Below we will show a refine­ment of this process for fast move­ments: read Dealing with fast move­ments.

NoteOn timing on fast movements

Let us look at this musi­cal phrase played with a metronome at 60 beats per second:

{3/2, {E5 A4 E5}, {{1/8, C#4 D4} {7/8, C#4} B3 C#4}}

Excerpt of François Couperin "Le Petit Rien" (1722)

Fast move­ments could be prob­lem­at­ic when using a _rndtime(x) con­trol, which sends NoteOns at ran­dom times ± x mil­lisec­onds, for example:

_rndtime(50) {3/2, {{1/8, C#4 D4} {7/8, C#4} B3 C#4}}

A large ran­dom time (50 ms) has been cho­sen to make the graphs clear­er. In gen­er­al, _rndtime(x) is used for a less mechan­i­cal ren­der­ing of simul­ta­ne­ous notes, with 10 to 20 ms being the rec­om­mend­ed val­ue for key­board instruments.

Errors would occur if the order of fast notes were reversed. However, this does not hap­pen because the tim­ing of the NoteOns in fast move­ments is not made random:

The same excerpt with 50 ms ran­dom time, except on the start­ing fast sequence C#4 D4 C#4.

Below we will deal with the elim­i­na­tion of some NoteOns except in fast move­ments: read Dealing with fast move­ments.

The fol­low­ing exam­ple is the (slowed down) first mea­sure of François Couperin's Les Ombres Errantes (1730) (read page) with a quan­ti­za­tion of 50 ms and a ran­domi­sa­tion of 50 ms:

_tempo(1/2) _rndtime(50) {{3, _legato(20) C5 _legato(0){1/4,C5 B4 C5}{3/4,B4}_legato(20) Eb5,{1/2,Eb4}{5/2,G4 D4 F4 C4 Eb4},Eb4 D4 C4}}

First mea­sure of François Couperin's Les Ombres Errantes (1730) with quan­ti­za­tion and ran­domised NoteOns

These rel­a­tive­ly high val­ues have been cho­sen to show that the order of notes is respect­ed in fast move­ments. Quantization (typ­i­cal­ly 20 ms) is gen­er­al­ly nec­es­sary to play a com­pli­cat­ed poly­met­ric struc­ture, such as an entire piece of music. Once the times of the NoteOns have been cal­cu­lat­ed and round­ed to the quan­ti­za­tion grid, they are giv­en small ran­dom changes. However, notes in a fast motion (C5 B4 C5) and the first note after this motion (B4) are exclud­ed from the randomisation.

Duplication of notes in a MusicXML score

When sev­er­al MIDI chan­nels are used, we can imag­ine that each of them con­trols a sep­a­rate key­board, or that the chan­nels are com­bined to con­trol the same key­board. The first case is called Omni Off Poly mode and the sec­ond case is called Multi mode (see details).

Importing music from MusicXML scores often cre­ates a Bol Processor score that uses dif­fer­ent MIDI chan­nels (or Csound instru­ments). If the music is sent on a sin­gle chan­nel or played by an instru­ment in Multi mode, there may be over­laps for the same note assigned to dif­fer­ent channels.

This sit­u­a­tion is also found in music import­ed from MusicXML scores (see details of this process). For exam­ple, again the first mea­sure of François Couperin's Les Ombres errantes:

Original staff (source) - Creative Commons CC0 1.0 Universal
This (slowed down) inter­pre­ta­tion is micro­ton­al­ly adjust­ed accord­ing to the Rameau en si bémol tem­pera­ment (see expla­na­tion).

Notes at the bot­tom of the staff: Eb4, D4, C4 are shown both as quar­ter notes and as eight notes. As this dual sta­tus can­not be man­aged in the MusicXML score, they are dupli­cat­ed (link to the XML score). This dupli­ca­tion is nec­es­sary for the con­ven­tion­al rep­re­sen­ta­tion of the staff.

The staff would look less con­ven­tion­al if the redun­dant eight notes Eb4, D4, C4 were sup­pressed (link to the mod­i­fied XML score):

Modified staff drawn by MuseScore 3

The out­put of the Bol Processor from the orig­i­nal XML score is as fol­lows, with dupli­cate notes clear­ly marked:

A sound-object dis­play of the Bol Processor's inter­pre­ta­tion of the MusicXML score.
Note that the dura­tions of C5 and Eb5 are extend­ed to allow slurs to be played cor­rect­ly (see expla­na­tion)

The Bol Processor score is an over­lay of three lines cre­at­ed by sequen­tial­ly inter­pret­ing the XML score:

C5 slur {1/4,C5 B4 C5} {3/4,B4} Eb5 slur
{1/2,Eb4}{5/2,G4 D4 F4 C4 Eb4}
Eb4 D4 C4

which is then con­vert­ed into a sin­gle poly­met­ric expres­sion (with lega­to in place of slurs):

-to.tryTunings
_scale(rameau_en_sib,0) {3, _legato(20) C5 _legato(0) {1/4, C5 B4 C5} {3/4, B4} _legato(20) Eb5, {1/2, Eb4}{5/2, G4 D4 F4 C4 Eb4}, Eb4 D4 C4}

Eliminating the redun­dant eight notes Eb4, D4, C4 would require a back­track­ing to mod­i­fy the sec­ond line when read­ing the notes of the third line. But this com­pli­cat­ed process is not nec­es­sary because the Bol Processor han­dles dupli­cate notes cor­rect­ly. The fol­low­ing piano roll shows this:

A piano roll dis­play of the Bol Processor's inter­pre­ta­tion of the MusicXML score. 

This ren­der­ing requires a prop­er con­trol of NoteOffs and NoteOns. This can be done in sev­er­al ways. (For geeks) we present the old method (before ver­sion BP3.2) and the new one.

The old method

Events list­ed by the PianoTeq synthesiser

The image on the right shows the begin­ning of a sequence of MIDI events played by a syn­the­sis­er. (The date "6.802" is actu­al­ly time 0.) Events are dis­trib­uted on sep­a­rate MIDI chan­nels to allow for micro­ton­al adjust­ments by the pitch­ben­der. (Pitchbender mes­sages are not displayed.)

The per­for­mance starts with a NoteOn C5, then a NoteOn Eb4 at the same date. However, anoth­er NoteOn Eb4 is required at the same time. However, two NoteOns of the same note and the same chan­nel should not be sent to a MIDI instru­ment. so, a NoteOff Eb4 is sent just before the sec­ond NoteOn Eb4, all at the same time. In this way, the first NoteOn/NoteOff EB4 sequence is not audi­ble because its dura­tion is zero.

At time 1 sec­ond, a NoteOn C4 is sent as expect­ed. The sound-object graph shows that the Eb4 eight note is end­ing, but no NoteOff is sent because the Eb4 quar­ter note should con­tin­ue to sound. The NoteOff Eb4 will only occur at time 2 seconds.

The new method

In the old method, sequences of NoteOn and Noteoff of the same note could be sent to the syn­the­sis­er at the same time. This worked because the NoteOn/Noteoff order was respect­ed, and they could be processed by the syn­the­sis­er even if the times were (almost) iden­ti­cal. The new method aims to elim­i­nate this case.

To achieve this, the machine cal­cu­lates "MaxDeltaTime", an esti­mate of the max­i­mum time between two NoteOns (of the same note and chan­nel), beyond which they should be inter­pret­ed as sep­a­rate events. If dates are ran­domised by _rndtime(x), then MaxDeltaTime is set to 2 times x. Otherwise it is set to 2 times the quan­ti­za­tion. If there is no quan­ti­za­tion and no ran­domi­sa­tion, it is set to 20 milliseconds.

A Trace NoteOn/Noteoff option can be select­ed in the new ver­sion to dis­play the sequence of notes along with indi­ca­tions of deci­sions made to send or keep a NoteOn mes­sage. Here is the sequence for the first mea­sure of Couperin's Les Ombres Errantes ran­domised to ± 50 ms and quan­ti­fied to 20 ms. Therefore, we expect MaxDeltaTime to be set to 100 milliseconds.

_tempo(1/2) _rndtime(50) {{3, _legato(20) C5 _legato(0){1/4,C5 B4 C5}{3/4,B4}_legato(20) Eb5,{1/2,Eb4}{5/2,G4 D4 F4 C4 Eb4},Eb4 D4 C4}}

The NoteOn/NoteOff trace is as follows:

NoteOn Eb4 chan­nel 1 at 2 ms
NoteOn C5 chan­nel 1 at 14 ms
? Eb4 channel 1 at = 27 ms, last = 2, delta = 25 > 100 ms ¿
NoteOn G4 chan­nel 1 at 1031 ms
? C5 channel 1 at = 1955 ms, last = 14, delta = 1941 > 100 ms ¿
NoteOff C5 chan­nel 1 at 1955 ms
NoteOn C5 chan­nel 1 at 1955 ms
NoteOn D4 chan­nel 1 at 1995 ms
NoteOff Eb4 chan­nel 1 at 2002 ms
? D4 chan­nel 1 at = 2030 ms, last = 1995, delta = 35 > 100 ms ¿
NoteOff G4 chan­nel 1 at 2031 ms
NoteOn B4 chan­nel 1 at 2159 ms
? C5 channel 1 at = 2316 ms, last = 1955, delta = 361 > 100 ms ¿
NoteOff C5 chan­nel 1 at 2316 ms
NoteOn C5 chan­nel 1 at 2316 ms
NoteOff B4 chan­nel 1 at 2326 ms
NoteOff C5 chan­nel 1 at 2483 ms
NoteOn B4 chan­nel 1 at 2497 ms
NoteOn F4 chan­nel 1 at 2961 ms
NoteOn C4 chan­nel 1 at 3951 ms
NoteOff F4 chan­nel 1 at 3961 ms
NoteOff D4 chan­nel 1 at 3995 ms
NoteOff B4 chan­nel 1 at 3997 ms
NoteOn Eb5 chan­nel 1 at 4031 ms
? C4 chan­nel 1 at = 4040 ms, last = 3951, delta = 89 > 100 ms ¿
NoteOn Eb4 chan­nel 1 at 4981 ms
NoteOff C4 chan­nel 1 at 5951 ms
NoteOff Eb4 chan­nel 1 at 5981 ms
NoteOff Eb5 chan­nel 1 at 6431 ms

This trace shows that the machine com­pared the time inter­val between suc­ces­sive NoteOns of the same note and chan­nel. On the green line, this inter­val was 25 ms, which is less than 100 ms, so the Eb4 NoteOn (of the dupli­cat­ed note) was dis­card­ed. On the red lines, the inter­vals were greater than 100 ms and the NoteOns were played.

Channel infor­ma­tion is irrel­e­vant, as micro­ton­al adjust­ments assign a spe­cif­ic chan­nel to each note and its pitch­bend adjust­ment. However, this selec­tion of NoteOns is made pri­or to the assign­ment of spe­cif­ic chan­nels for micro­ton­al corrections.

Dealing with fast movements

The new method (BP3.2.0 and high­er) elim­i­nates NoteOns of the same note and chan­nel if they occur in an inter­val less than MaxDeltaTime. However it takes into account fast move­ments. For example:

_rndtime(50) {3/2, {E5 A4 E5}, {{1/8, C#4 D4} {7/8, C#4} B3 C#4}}

In this exam­ple, two dif­fer­ent occur­rences of C#4 should be sep­a­rat­ed by less than MaxDeltaTime (100 ms). The fol­low­ing trace shows that the sequence C#4 D4 C#4 (a trill) has been iden­ti­fied as a fast move­ment, and no time sep­a­ra­tion con­di­tion has been applied:

NoteOn C#4 chan­nel 1 at 0 ms
NoteOn E5 chan­nel 1 at 14 ms
NoteOff C#4 chan­nel 1 at 31 ms
NoteOn D4 chan­nel 1 at 31 ms
NoteOff D4 chan­nel 1 at 62 ms
NoteOn C#4 chan­nel 1 at 62 ms
NoteOn B3 chan­nel 1 at 493 ms
NoteOff C#4 chan­nel 1 at 500 ms
NoteOff E5 chan­nel 1 at 514 ms
NoteOn A4 chan­nel 1 at 531 ms
NoteOn E5 chan­nel 1 at 955 ms
NoteOn C#4 chan­nel 1 at 983 ms
NoteOff B3 chan­nel 1 at 993 ms
NoteOff A4 chan­nel 1 at 1031 ms
NoteOff E5 chan­nel 1 at 1455 ms
NoteOff C#4 chan­nel 1 at 1483 ms

A quan­ti­za­tion of 20 ms may not be desir­able for ren­der­ing fast move­ments such as:

{1/16, C4 - E4 F4} {15/16, G4 A4 B4}

The graph­ic shows that notes E4 and F4 have been assigned the same time (60 ms)

If the quan­ti­za­tion is set to 10 ms, the dif­fer­en­ti­a­tion of the tim­ings is retained:

NoteOn C4 chan­nel 1 at 0 ms
NoteOff C4 chan­nel 1 at 15 ms
NoteOn E4 chan­nel 1 at 31 ms
NoteOff E4 chan­nel 1 at 46 ms
NoteOn F4 chan­nel 1 at 46 ms
NoteOff F4 chan­nel 1 at 62 ms
NoteOn G4 chan­nel 1 at 62 ms
NoteOff G4 chan­nel 1 at 375 ms
NoteOn A4 chan­nel 1 at 375 ms
NoteOff A4 chan­nel 1 at 687 ms
NoteOn B4 chan­nel 1 at 687 ms
NoteOff B4 chan­nel 1 at 1000 ms

i1 0.000 0.015 8.00 90.000 90.000 0.000 0.000 0.000 0.000 ; C4
i1 0.031 0.015 8.04 90.000 90.000 0.000 0.000 0.000 0.000 ; E4
i1 0.046 0.016 8.05 90.000 90.000 0.000 0.000 0.000 0.000 ; F4
i1 0.062 0.313 8.07 90.000 90.000 0.000 0.000 0.000 0.000 ; G4
i1 0.375 0.312 8.09 90.000 90.000 0.000 0.000 0.000 0.000 ; A4
i1 0.687 0.313 8.11 90.000 90.000 0.000 0.000 0.000 0.000 ; B4

Created by Bernard Bel, January 2025

Leave a Reply

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