[sdiy] MonoSynth Note Priority over MIDI
Tom Wiltshire
tom at electricdruid.net
Wed Oct 22 07:09:22 CEST 2014
On 22 Oct 2014, at 04:08, Chris McDowell <declareupdate at gmail.com> wrote:
>> Do you search for it in the stack and pull it out and toss it?
>
> Indeed you do. (Or one does). I keep a “note stack” array and a “stack height” variable. Note on increments stack height. note off decrements stack height, searches for the note in the stack, removes it and slides the others notes in the stack down to fill the gap (it’s definitely a bit confusing, I had to do some serious scribbling on paper to get it right). Stack height is used as the index to the note stack, and represents the current note output.
>
> Looks silly typed out like that. Worth drawing on paper!
>
> Maybe someone here has an easier way to do it right?
>
> Chris
I did it a similar way, with a stack of notes. New notes coming in go on the top of the stack and push older notes down. If a note is released, the stack is searched, and it is removed if present, and the remaining notes in the stack moved up to fill the gap.
The only difference between my way and yours seems to be that I didn't keep track of the stack height. Instead, I used the fact that MIDI notes are 7-bit and I was storing them in bytes. This means the top bit is always clear for a note, and I was able to use "top bit set" in my stack to represent "this position is empty". Thus when a note is released, you fall back to the next one in the stack, as long as the top bit is clear. If the top bit is set, the last held note has just been released.
Code (PIC ASM) pasted below for those that are interested. This is a simple 4 note stack, the first one I did.
MIDI_NoteOff: ; 08 = 0x80 = Note Off
; Which note was it that was released?
; Test Note 1
movf NOTE1, w
xorwf MIDI_DATA1, w ; MIDI_DATA1 is the Note Number
btfsc ZEROBIT
goto ShiftUpFromNote1
; Test Note 2
movf NOTE2, w
xorwf MIDI_DATA1,w
btfsc ZEROBIT
goto ShiftUpFromNote2
; Test Note 3
movf NOTE3, w
xorwf MIDI_DATA1, w
btfsc ZEROBIT
goto ShiftUpFromNote3
; Test Note 4
movf NOTE4, w
xorwf MIDI_DATA1, w
btfsc ZEROBIT
goto ShiftUpFromNote4
; Ok, so the released note isn't in our list any more.
return
ShiftUpFromNote1:
movf NOTE2, w
movwf NOTE1
ShiftUpFromNote2:
movf NOTE3, w
movwf NOTE2
ShiftUpFromNote3:
movf NOTE4, w
movwf NOTE3
ShiftUpFromNote4:
bsf NOTE4, 7 ; There is no shift up, but we need to wipe it
; Was this the last note we just released?
btfss NOTE1, 7 ; If the top note is empty, the stack is empty
goto UseStackedNote
NoMoreNotes:
; Yes, it was the last note that was playing
movlb D'0' ; Bank 0
bcf GATE ; Turn the Gate Off
bcf LEGATO
return
UseStackedNote:
; No, it wasn't - there are other notes held
movf NOTE1, w
movwf MIDI_NOTE ; Make the new top note the note played
; The GATE remains high, but we do get a new TRIGGER
; bsf TRIGGER
; *** SET UP SOME TIMER FOR THE TRIGGER PULSE?? ***
return
MIDI_NoteOn: ; 09 = 0x90 = Note On
; If Velocity=0, then this is really a Note Off
movf MIDI_DATA2, f ; Data Byte 2 is Velocity
btfsc ZEROBIT
goto MIDI_NoteOff ; So jump to Note Off instead
; Ok, so it is definitely a Note On message
; Move all notes down the Note Stack
movf NOTE3, w
movwf NOTE4 ; If Note 4 was important, we've just lost it!
movf NOTE2, w
movwf NOTE3
movf NOTE1, w
movwf NOTE2
; Put the new note in at the top
movf MIDI_DATA1, w ; MIDI_DATA1 is the Note Number
movwf NOTE1
; Use this as the new pitch
movwf MIDI_NOTE
; Is the GATE on already?
movlb D'0' ; Bank 0
btfsc GATE
bsf LEGATO ; The notes are LEGATO if so.
; Ensure that the GATE is on now, even if it wasn't before
bsf GATE ; Turn the Gate on
; Send a trigger too if required
; btfsc ENV_RETRIG
; bsf TRIGGER
return
More information about the Synth-diy
mailing list