[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