I've worked out the algorithm in case it's useful to other programmers. This could be useful for finding ranges where clef and enharmonics
do matter, or for help in transposing.
If this sort of thing is not your cup of tea, please ignore it!-------------------------------------------------------
As you process a clip file, you need to capture each clef change, as it provides input into the algorithm. Then each note should be processed individually.
Andrew Purdam's transpose script does this note processing very elegantly. One day
real-soon now I'm gonna learn PHP so I can
write the tools I need rather than just being envious!
First, you need a look-up/conversion of some sort for clefs, so that:
bass = 6, tenor = 2, alto = 0, treble = -6. Other clefs can be added later if NWC includes them. The value is the position of Middle C in the clef.
Second you need a look-up for octave-shift, so that:
8va = 7, (none) = 0, 8vb = -7.
Next you need another look-up for accidentals, so that:
double flat = -2, flat = -1, natural (or nothing) = 0, sharp = 1, double sharp = 2
Instead of any of the look-up tables, you could use "if" statements.
NWC 2 MIDICALCULATE:
- alto_clef_position = note_position - clef_lookup + shift_lookup
- octave_offset = truncate(alto_clef_position / 7) * 12
- semitone_offset = truncate(mod(alto_clef_position,7) * 7 / 4 + 0.5 )
- MIDI_value = 60 + octave_offset + semitone_offset + accidental_lookup
This is the standard MIDI value for the note, with Middle C = 60.
MIDI 2 NWCCALCULATE:
- note_position = truncate((MIDI_value - 60) * 7 / 12 + 0.1) + clef_lookup - shift_lookup
- semitone_offset = mod(MIDI_value,12)
- accidental_offset = mod(mod(semitone_offset,5),2)-(semitone_offset*2-21)*truncate(semitone_offset/10) [this will be 0 or 1]
- if (accidental_offset = 1) then accidental is "#" else accidental is nothing
I've tested for all MIDI values 0 to 127. I'm not happy with the formula for accidental_offset in MIDI2NWC, and will try to find something more succinct. It can always be replaced by something like:
accidental is nothing: if semitone_offset in {1, 3, 6, 8, 10} then accidental is "#".
Yes - I realised the effect of key signature and accidentals overnight! (it's about 7:30 AM where I am)
I'll have a bit more of a think and adjust the algorithm.
Cheers, Ewan
in Canberra
The obvious thing is to Force Accidentals before you start - it should all work fine then!