Print This Post Print This Post

Towards a better Guitar-to-MIDI Converter

Most Guitar-to-MIDI converters are a grave disappointment. Recently, I’ve been playing with the idea of adding electronic scanning to one of my guitars and using this to output MIDI – it works but has several disadvantages, not the least being that it involves irreversible surgery to a guitar. My prototype is a £35 (GBP) second-hand acoustic Fender Squier. It’s ‘just-good-enough’ as a test bed, but I don’t lose any sleep despite hurting it – a lot.

Work is still on-going, but encouraging, and I’m busy now scaling everything down in size so that most of it can be put inside the guitar body, rather than bolted onto the top of the soundboard. In parallel with this work, I’ve been playing recently with a small Guitar-to-MIDI project featured in EPE Magazine October 2009. This little unit is impressive and beats hands-down the relatively expensive SONUS/MODUS stuff around.

The project has been quite popular, and I’ve decided to incorporate some of the techniques into my own unit. I haven’t decided on a final format to present my work in yet, but will use this post, and maybe others, to fully document the work.

The first thing I did to the EPE unit was add diagnostics and look at the code in action on the oscilloscope. Others who have tackled/are tackling the project might benefit from these so I’m publishing these here.

First of all here’s a trace capture showing the initial string pluck and the subsequent processing. Refer to the source-code I’ve supplied for both the ‘PEAK’ and ‘TIMING’ routines which will show you where I’ve output the blue diagnostic trace transitions.

Guitar-to-MIDI showing initial string pluck and subsequent processing.

Guitar-to-MIDI showing initial string pluck and subsequent processing.

Secondly, here’s a set of traces with the ‘TIMING’ routine annotated in more detail.

Guitar-toMIDI showing TIMING processing in more detail

Guitar-toMIDI showing 'TIMING' processing in more detail

And now for the relevant code. Note my #ifdef CODESHOW conditional compilation to provide the blue trace transitions in the oscilloscope dumps above. First the PEAKS routine:

;--- WAVEFORM PEAK LEVEL DETECTION FOR 12MS ---

PEAKS

#ifdef CODESHOW
			BCF PORTB,0
#endif
			CLRF	PEAKH        ; PEAKH := 0;
			MOVLW	255
			MOVWF	PEAKL        ; PEAKL := 255

			; !!! JWB use TMR0 instead of loop counter
			bcf INTCON,2
			movlw 255-110 ; [for ~14ms to accomodate drop 'D'] : 14ms = 28,000 CKP at FOSC 8Mhz/4. Prescaled at 256 is count of 109.375.
			movwf TMR0

CL1			CALL 	ADC
			MOVF	ADRESH,W     ; W := PEAKH - ADC
			SUBWF	PEAKH,W
			BTFSS	STATUS,C
			CALL	UPDATE_PEAKH

			MOVF	PEAKL,W      ; W := PEAKL - ADC
			SUBWF	ADRESH,W
			BTFSS	STATUS,C
			CALL	UPDATE_PEAKL

			; test TMR0 hasn't timed out
			BTFSS INTCON,2
			GOTO CL1

#ifdef CODESHOW
			BSF PORTB,0
#endif
			RETURN

UPDATE_PEAKH
			MOVF	ADRESH,W     ; PEAKH := ADC
			MOVWF	PEAKH
			RETURN

UPDATE_PEAKL
			MOVF	ADRESH,W     ; PEAKL := ADC
			MOVWF	PEAKL
			RETURN

And now the ‘TIMING‘ routine.

TIMING		CLRF	TMR1L
			CLRF	TMR1H
#ifdef CODESHOW
			; debug
			BCF PORTB, 0
#endif

T1			BTFSC	TMR1H,5
			GOTO	TERROR
			BCF		MARKER,3
			CALL	ADC
			MOVF	TRIGL,W
			SUBWF	ADRESH,W
			BTFSC	STATUS,C			;IS ADRESH - TRIGL +VE IE CARRY SET?
			GOTO	T1					;NO, SO RETEST UNTIL IT IS
#ifdef CODESHOW
			; debug
			BSF PORTB,0
#endif

T2			BTFSC	TMR1H,5
			GOTO	TERROR
			CALL	ADC
			MOVF	ADRESH,W
			SUBWF	TRIGH,W
			BTFSC	STATUS,C			;IS ADRESH - TRIGH +VE IE CARRY SET?
			GOTO	T2					;NO, SO RETEST UNTIL IT IS

			CLRF 	TMR1L
			CLRF 	TMR1H
			NOP
#ifdef CODESHOW
			; debug
			BCF PORTB, 0
#endif

T3			BTFSC	TMR1H,5
			GOTO	TERROR
			CALL	ADC
			MOVF	TRIGL,W
			SUBWF	ADRESH,W
			BTFSC	STATUS,C			;IS ADRESH - TRIGL +VE IE CARRY SET?
			GOTO	T3					;YES, SO RETEST UNTIL IT IS
#ifdef CODESHOW
			; debug
			BSF PORTB, 0
#endif
T4			BTFSC	TMR1H,5
			GOTO	TERROR
			CALL	ADC
			MOVF	ADRESH,W
			SUBWF	TRIGH,W
			BTFSC	STATUS,C			;IS ADRESH - TRIGH +VE IE CARRY SET?
			GOTO	T4					;NO, SO RETEST UNTIL IT IS

			BCF		T1CON,0				;STOP THE TIMER TO RETRIEVE THE DATA
#ifdef CODESHOW
			; debug
			BCF PORTB,0
#endif
			MOVF 	TMR1L,W
			MOVWF 	LOBYTE

			MOVF 	TMR1H,W
			MOVWF 	HIBYTE

			BSF		T1CON,0				;RESTART THE TIMER
#ifdef CODESHOW
			; debug
			BSF PORTB,0
#endif
			RETURN

TERROR
			BSF		MARKER,3
			RETURN

Note that I’ve made one or two changes to the original code. I’ve detailed these in the source-header, which is given below:

;     GUITAR TO MIDI CONVERTER
;
; This version V2.00 modified by JWB 03 Sep 2010
; 1. Now using 8Mhz Osc.
; 2. Added facilities to debug on serial port
; and PORTB,0 output pin
; 3. Annotated lookup table
;
; JWB 4 sep
; 1. Now using TMR0 instead of loop counter in PEAKS routine
;    To allow easier definition of 'window'
;    Also frees up 2 RAM slots
;

	ERRORLEVEL -302 ; JWB 7th Aug 2010 remove message about using proper bank

My amended source-code is appended in a zip file here: http://joebrown.org.uk/images/GuitarToMIDI/PICGUITARTOMIDI._5sep2010.zip

Copy the code below to your web site.
x 
  • Share/Bookmark
PDF Download    Send article as PDF   

1 comment to Towards a better Guitar-to-MIDI Converter

You must be logged in to post a comment.