[linux-audio-user] NoteEdit 2.6.0: MIDI-->multiple voices per staff

Joerg Anders j.anders at informatik.tu-chemnitz.de
Wed Jun 16 15:58:43 EDT 2004


On Wed, 16 Jun 2004, Chris Cannam wrote:

> 
> Is this based on pitch?

I'm not quite sure whether this gives always good results
(or at least in most cases.)

It is a mix: I divide the midi data into chunks. A junk is
a portion of adjacent midi notes at leats 4 quarters long.

The start and stop of every chunk is a non-overlapping moment
(I hope it is always possible to find  such a moment in a
distance shorter than - say -  32 quarters):


   |-- event 1 ---|    |--event2---| |-event3--|     |---|

     |-----event 4-------| |--event 5-| |-event6--|
  ^                                                ^
  |  start  of chunk;  first possible end of chunk |
     

After that I create a fully meshed graph with all events as
nodes:


       |-------  e1 \----------
       |       / |            |
       |  -- e2--|--  e5 ---- |
       |  |  | \ | /  |     | |
       |  |  | / - \  |     | |
       |--|- e3 -|-- e6-----|-|
          |   \  |  /      /
          \ --- e4 -------


For every edge I compute costs in both directions (thus
every egde are actually 2 edges):

   if (MidiOnTime(j) - (MidiOffTime(i) < 0) {
      costs(i, j) = infinity
   }
   else {
      costs(i, j) = PITCH_DIST_COST_FAC * |(pitch(i) - pitch(j))| +
                    START_DIST_FAC  * (MidiOnTime(j) - (MidiOffTime(i))
   }

 (see miditimescale.cpp: initialize_desicion_tree)

Whereby PITCH_DIST_COST_FAC and START_DIST_FAC are empirically
choosen values. Thus, the notes close together regarding the
pitch and the time distance get the lowest costs.

Then I select 2 unmarked notes:
  first note: The note with lowest midiOnTime;
  last note: The note with higest midiOnTime
  
and I compute the shortest path from first note to last note
using Dijkstra's shortest path algorithm.

I mark all notes from first to last note belonging to one voice end
repeat the selection and the Dijkstra algorithm till all notes are marked.
Thus, every note is assigned to a voice.

Till now I sort the voices. Again I use a cost function:

cost (voice_i) = PITCH_FAC * sum_of_all_pitches /  num_pitches + COUNT_FAC * num_pitches;

 (see miditimescale.cpp: sort_voices)

The voice with highest costs is the first voice. The formula shall
ensure the voice with the higest pitches is the first voice but
avoid that a voice with only 2 notes becomes the first voice and
a voice with 1000 notes becomes the 2nd voice.

Perhaps it is an error to sort the voices after the Dijkstra algoritm. I'll test
other possibilities.

As a last (or better first) step I have to take into account
the triplets. Unfortunately, the triplet recognition does not
yet work (is commented out). But for successful triplet
recognition it is certainly necessary to recognize the
triplets before the voice distribution takes place.

I had an algorithm but it failed in these case:


                      3
              -----------------
              |               |
       |\       |\    |\    |\     |\
       |        |     |     |      |
       |        |     |     |      |
       /        /     /     /      /
        \-----/              \-----/

           
-- 
J.Anders, Chemnitz, GERMANY (ja at informatik.tu-chemnitz.de)


More information about the linux-audio-user mailing list