This page is intended for developers of the Bol Processor BP3 (read installation). It is not a formal description of the algorithms carried by the console's C code, but rather an illustration of their management of musical processes, which may be useful for checking or extending algorithms.
When the Bol Processor produces MIDI material (real-time or files), each note is associated with two events: a NoteOn at its beginning and a NoteOff at its end. Additional parameters are its velocity (range 0 to 127) and its MIDI channel (range 1 to 16).
When a keyboard instrument is used to produce the sound, each NoteOn will press a key at the appropriate location. By default, note C4 (in English notation) will press key #60. A NoteOff of the same pitch will release the key.
All examples on this page can be found in the "-da.checkNoteOff" project. NoteOn/NoteOff tracking can be enabled by selecting this option in the "-se.checkNoteOff" settings of the project.
Read also: Csound checkup
Superimposed notes
Consider this example:
{C4____, -C4__-, --C4--} D4

Two (or more) consecutive NoteOns of the same note and the same channel should not be sent to a MIDI instrument. Nevertheless, the attacks of C4, which occur at the 1.00 s and 2.00 s times in this example, should be audible. To achieve this, they are automatically preceded by a NoteOff.
The list of NoteOn/NoteOff events is as follows:
NoteOn C4 channel 1 at 0 ms
NoteOff C4 channel 1 at 1000 ms
NoteOn C4 channel 1 at 1000 ms
NoteOff C4 channel 1 at 2000 ms
NoteOn C4 channel 1 at 2000 ms
NoteOff C4 channel 1 at 5000 ms
NoteOn D4 channel 1 at 5000 ms
NoteOff D4 channel 1 at 6000 ms
This feature is not necessary for the creation of Csound scores. The score generated by this example 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 refinement of this process for fast movements: read Dealing with fast movements.
NoteOn timing on fast movements
Let us look at this musical 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}}

Fast movements could be problematic when using a _rndtime(x) control, which sends NoteOns at random times ± x milliseconds, for example:
_rndtime(50) {3/2, {{1/8, C#4 D4} {7/8, C#4} B3 C#4}}
A large random time (50 ms) has been chosen to make the graphs clearer. In general, _rndtime(x) is used for a less mechanical rendering of simultaneous notes, with 10 to 20 ms being the recommended value for keyboard instruments.
Errors would occur if the order of fast notes were reversed. However, this does not happen because the timing of the NoteOns in fast movements is not made random:

Below we will deal with the elimination of some NoteOns except in fast movements: read Dealing with fast movements.
The following example is the (slowed down) first measure of François Couperin's Les Ombres Errantes (1730) (read page) with a quantization of 50 ms and a randomisation 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}}

These relatively high values have been chosen to show that the order of notes is respected in fast movements. Quantization (typically 20 ms) is generally necessary to play a complicated polymetric structure, such as an entire piece of music. Once the times of the NoteOns have been calculated and rounded to the quantization grid, they are given small random changes. However, notes in a fast motion (C5 B4 C5) and the first note after this motion (B4) are excluded from the randomisation.
Duplication of notes in a MusicXML score
When several MIDI channels are used, we can imagine that each of them controls a separate keyboard, or that the channels are combined to control the same keyboard. The first case is called Omni Off Poly mode and the second case is called Multi mode (see details).
Importing music from MusicXML scores often creates a Bol Processor score that uses different MIDI channels (or Csound instruments). If the music is sent on a single channel or played by an instrument in Multi mode, there may be overlaps for the same note assigned to different channels.
This situation is also found in music imported from MusicXML scores (see details of this process). For example, again the first measure of François Couperin's Les Ombres errantes:

Notes at the bottom of the staff: Eb4, D4, C4 are shown both as quarter notes and as eight notes. As this dual status cannot be managed in the MusicXML score, they are duplicated (link to the XML score). This duplication is necessary for the conventional representation of the staff.
The staff would look less conventional if the redundant eight notes Eb4, D4, C4 were suppressed (link to the modified XML score):

The output of the Bol Processor from the original XML score is as follows, with duplicate notes clearly marked:

Note that the durations of C5 and Eb5 are extended to allow slurs to be played correctly (see explanation)
The Bol Processor score is an overlay of three lines created by sequentially interpreting 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 converted into a single polymetric expression (with legato 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 redundant eight notes Eb4, D4, C4 would require a backtracking to modify the second line when reading the notes of the third line. But this complicated process is not necessary because the Bol Processor handles duplicate notes correctly. The following piano roll shows this:

This rendering requires a proper control of NoteOffs and NoteOns. This can be done in several ways. (For geeks) we present the old method (before version BP3.2) and the new one.
The old method

The image on the right shows the beginning of a sequence of MIDI events played by a synthesiser. (The date "6.802" is actually time 0.) Events are distributed on separate MIDI channels to allow for microtonal adjustments by the pitchbender. (Pitchbender messages are not displayed.)
The performance starts with a NoteOn C5, then a NoteOn Eb4 at the same date. However, another NoteOn Eb4 is required at the same time. However, two NoteOns of the same note and the same channel should not be sent to a MIDI instrument. so, a NoteOff Eb4 is sent just before the second NoteOn Eb4, all at the same time. In this way, the first NoteOn/NoteOff EB4 sequence is not audible because its duration is zero.
At time 1 second, a NoteOn C4 is sent as expected. The sound-object graph shows that the Eb4 eight note is ending, but no NoteOff is sent because the Eb4 quarter note should continue 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 synthesiser at the same time. This worked because the NoteOn/Noteoff order was respected, and they could be processed by the synthesiser even if the times were (almost) identical. The new method aims to eliminate this case.
To achieve this, the machine calculates "MaxDeltaTime", an estimate of the maximum time between two NoteOns (of the same note and channel), beyond which they should be interpreted as separate events. If dates are randomised by _rndtime(x), then MaxDeltaTime is set to 2 times x. Otherwise it is set to 2 times the quantization. If there is no quantization and no randomisation, it is set to 20 milliseconds.
A Trace NoteOn/Noteoff option can be selected in the new version to display the sequence of notes along with indications of decisions made to send or keep a NoteOn message. Here is the sequence for the first measure of Couperin's Les Ombres Errantes randomised to ± 50 ms and quantified 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 channel 1 at 2 ms
NoteOn C5 channel 1 at 14 ms
? Eb4 channel 1 at = 27 ms, last = 2, delta = 25 > 100 ms ¿
NoteOn G4 channel 1 at 1031 ms
? C5 channel 1 at = 1955 ms, last = 14, delta = 1941 > 100 ms ¿
NoteOff C5 channel 1 at 1955 ms
NoteOn C5 channel 1 at 1955 ms
NoteOn D4 channel 1 at 1995 ms
NoteOff Eb4 channel 1 at 2002 ms
? D4 channel 1 at = 2030 ms, last = 1995, delta = 35 > 100 ms ¿
NoteOff G4 channel 1 at 2031 ms
NoteOn B4 channel 1 at 2159 ms
? C5 channel 1 at = 2316 ms, last = 1955, delta = 361 > 100 ms ¿
NoteOff C5 channel 1 at 2316 ms
NoteOn C5 channel 1 at 2316 ms
NoteOff B4 channel 1 at 2326 ms
NoteOff C5 channel 1 at 2483 ms
NoteOn B4 channel 1 at 2497 ms
NoteOn F4 channel 1 at 2961 ms
NoteOn C4 channel 1 at 3951 ms
NoteOff F4 channel 1 at 3961 ms
NoteOff D4 channel 1 at 3995 ms
NoteOff B4 channel 1 at 3997 ms
NoteOn Eb5 channel 1 at 4031 ms
? C4 channel 1 at = 4040 ms, last = 3951, delta = 89 > 100 ms ¿
NoteOn Eb4 channel 1 at 4981 ms
NoteOff C4 channel 1 at 5951 ms
NoteOff Eb4 channel 1 at 5981 ms
NoteOff Eb5 channel 1 at 6431 ms
This trace shows that the machine compared the time interval between successive NoteOns of the same note and channel. On the green line, this interval was 25 ms, which is less than 100 ms, so the Eb4 NoteOn (of the duplicated note) was discarded. On the red lines, the intervals were greater than 100 ms and the NoteOns were played.
Channel information is irrelevant, as microtonal adjustments assign a specific channel to each note and its pitchbend adjustment. However, this selection of NoteOns is made prior to the assignment of specific channels for microtonal corrections.
Dealing with fast movements
The new method (BP3.2.0 and higher) eliminates NoteOns of the same note and channel if they occur in an interval less than MaxDeltaTime. However it takes into account fast movements. For example:
_rndtime(50) {3/2, {E5 A4 E5}, {{1/8, C#4 D4} {7/8, C#4} B3 C#4}}

In this example, two different occurrences of C#4 should be separated by less than MaxDeltaTime (100 ms). The following trace shows that the sequence C#4 D4 C#4 (a trill) has been identified as a fast movement, and no time separation condition has been applied:
NoteOn C#4 channel 1 at 0 ms
NoteOn E5 channel 1 at 14 ms
NoteOff C#4 channel 1 at 31 ms
NoteOn D4 channel 1 at 31 ms
NoteOff D4 channel 1 at 62 ms
NoteOn C#4 channel 1 at 62 ms
NoteOn B3 channel 1 at 493 ms
NoteOff C#4 channel 1 at 500 ms
NoteOff E5 channel 1 at 514 ms
NoteOn A4 channel 1 at 531 ms
NoteOn E5 channel 1 at 955 ms
NoteOn C#4 channel 1 at 983 ms
NoteOff B3 channel 1 at 993 ms
NoteOff A4 channel 1 at 1031 ms
NoteOff E5 channel 1 at 1455 ms
NoteOff C#4 channel 1 at 1483 ms
A quantization of 20 ms may not be desirable for rendering fast movements such as:
{1/16, C4 - E4 F4} {15/16, G4 A4 B4}
The graphic shows that notes E4 and F4 have been assigned the same time (60 ms)

If the quantization is set to 10 ms, the differentiation of the timings is retained:

NoteOn C4 channel 1 at 0 ms
NoteOff C4 channel 1 at 15 ms
NoteOn E4 channel 1 at 31 ms
NoteOff E4 channel 1 at 46 ms
NoteOn F4 channel 1 at 46 ms
NoteOff F4 channel 1 at 62 ms
NoteOn G4 channel 1 at 62 ms
NoteOff G4 channel 1 at 375 ms
NoteOn A4 channel 1 at 375 ms
NoteOff A4 channel 1 at 687 ms
NoteOn B4 channel 1 at 687 ms
NoteOff B4 channel 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