/* **************************************************************************** * * FILE: midi_pov.inc * * DESCRIPTION: Works in conjunction with the output of * midi_pov.pl. This file contains macros that * facilitate access to the information * in the include file created by the Perl * script. * * USAGE: * * note_val(track, note, pre, post) * For the given track number and the given note number, returns * zero if the note is off right now (based on clock) and one if * note is on right now. If pre is non-zero, then it will also * return a non-zero value for up to
 seconds before a
 *      note-on event, depending on the velocity of the note event.
 *      If post is non-zero, then it will return a non-zero value for
 *      exactly  seconds after a note-off event, not dependant
 *      on velocity.
 *
 * note_val_all_tracks(note, pre, post)
 *      Works similarly to note_val, except that it checks all tracks in
 *      the MIDI file for any notes occurring now, based on clock.
 *
 * note_val_instrument(track, instrument, note, pre, post)
 *      Works similarly to note_val, except that it only returns true
 *      if the specified note is on for the specified instrument
 *      (i.e. "Acoustic Grand").
 *
 * note_val_instrument_all_tracks(instrument, note, pre, post)
 *      Works similarly to note_val_instrument, except that it
 *      checks all tracks in the MIDI file for any notes for the
 *      specified instrument occurring now, based on clock.
 *
 * note_val_patch(track, patch, note, pre, post)
 *      Works similarly to note_val, except that it only returns true
 *      if the specified note is on for the specified numerical patch
 *      value [0...127].
 *
 * note_val_patch_all_tracks(patch, note, pre, post)
 *      Works similarly to note_val_patch, except that it
 *      checks all tracks in the MIDI file for any notes for the
 *      specified patch value occurring now, based on clock.
 *
 * white_key(note)
 *      Returns one if the specified note would be a white key on a
 *      piano keyboard (natural note). Zero indicates a black key
 *      (sharp or flat).
 *
 * ***************************************************************************/

#declare Note_Letters = array[12] {"C","Cs","D","Ds","E","F","Fs","G","Gs","A","As","B"}

#macro octave(note)
    int(note/12)
#end

#macro note_num(note)
    mod(note,12)
#end

#macro note_letter(note)
    Note_Letters[note_num(note)]
#end

#macro white_key(note)
    (strlen(note_letter(note)) = 1)
#end

#macro note_val(track, note, pre, post)
    #local NV_count = Track_Count_Map[track][note];
    #local NV_notes = Track_Notes_Map[track][note];
    #local s_target=clock * Total_Seconds;
    #local out=0;
    #local i=0;
    #while (i < NV_count)
        #if (NV_notes[i][0] <= s_target &
             s_target <= NV_notes[i][1])
            #local out=1;
        #else
            #local velocity = pre*(1-NV_notes[i][2]/127);
            #if (NV_notes[i][0] > s_target &
                        NV_notes[i][0] != 0 &
                 s_target > NV_notes[i][0] - velocity)
                #local out = max(out,
                    1 - ((NV_notes[i][0]-s_target) / velocity));
            #else
                #if (NV_notes[i][1] < s_target &
                        NV_notes[i][1] != 0 &
                     s_target < NV_notes[i][1] + post)
                    #local out = max(out,
                        1 - ((s_target-NV_notes[i][1]) / post));
                #end
            #end
        #end
        #local i = i + 1;
    #end
    out
#end

#macro note_val_all_tracks(key, pre, post)
    #local i=0;
    #local out=0;
    #while (i < Num_Tracks)
        #local out = max(out, note_val(i, key, pre, post));
        #local i = i + 1;
    #end
    out
#end

#macro note_val_instrument(track, instrument, note, pre, post)
    #local NV_count = Track_Count_Map[track][note];
    #local NV_notes = Track_Notes_Map[track][note];
    #local s_target=clock * Total_Seconds;
    #local out=0;
    #local i=0;
    #while (i < NV_count)
        #if (strcmp(Instrument_Map[NV_notes[i][3]], instrument) = 0)
            #if (NV_notes[i][0] <= s_target &
                    s_target <= NV_notes[i][1])
                #local out=1;
            #else
                #local velocity = pre*(1-NV_notes[i][2]/127);
                #if (NV_notes[i][0] > s_target &
                        NV_notes[i][0] != 0 &
                        s_target > NV_notes[i][0] - velocity)
                    #local out = max(out,
                        1 - ((NV_notes[i][0]-s_target) / velocity));
                #else
                    #if (NV_notes[i][1] < s_target &
                            NV_notes[i][1] != 0 &
                            s_target < NV_notes[i][1] + post)
                        #local out = max(out,
                            1 - ((s_target-NV_notes[i][1])
                                / post));
                    #end
                #end
            #end
            #local i = i + 1;
        #end
    #end
    out
#end


#macro note_val_patch(track, patch, key, pre, post)
    note_val_instrument(track, Instrument_map[patch], note, pre, post)
#end

#macro note_val_instrument_all_tracks(instrument, note, pre, post)
    #local i=0;
    #local out=0;
    #while (i < Num_Tracks)
        #local out = max(out,
            note_val_instrument(i, instrument, note, pre, post));
        #local i = i + 1;
    #end
    out
#end

#macro note_val_patch_all_tracks(patch, key, pre, post)
    note_val_instrument_all_tracks(track, Instrument_map[patch], note,
        pre, post)
#end