;WRITTEN BY IAIN MCCURDY, 2008

<CsoundSynthesizer>

<CsOptions>
;UNCOMMENT THE FOLLOWING LINE FOR MIDI INPUT FROM AN EXTERNAL MIDI KEYBOARD
-idevaudio -odevaudio -M0 -b200
;UNCOMMENT THE FOLLOWING LINE FOR MIDI INPUT FROM CSOUNDS VIRTUAL MIDI KEYBOARD (USE THIS IF YOU HAVE NO EXTERNAL MIDI HARDWARE)
;-idevaudio -odevaudio -M0 -+rtmidi=virtual -b200
;-odac4 -iadc4 -M0 -+rtmidi=virtual -b200
</CsOptions>

<CsInstruments>

sr	= 	44100
ksmps	= 	1
nchnls	= 	2

;FLTK INTERFACE CODE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
FLcolor	255, 255, 255, 50, 0, 0
;		LABEL		 	| WIDTH | HEIGHT | X | Y
	FLpanel	"MIDI Tap Tempo",   	   100,    100,    0,  0

;KOUT | HANDLE		FLTEXT	 "LABEL"      | MIN | MAX | STEP | TYPE | WIDTH | HEIGHT | X | Y
gkTempo, gihTempo	FLtext	"Tempo",   	0,   10000, 0.01,    1,     100,     25,   0,  0
gkDlyTim, gihDlyTim	FLtext	"Delay Time",   0,     20,    0,     1,     100,     25,   0, 50

			FLpanel_end

;INSTRUCTIONS AND INFO PANEL                 WIDTH | HEIGHT | X | Y
				FLpanel	" ", 500,     160,   113, 0
;TEXT BOXES												TYPE | FONT | SIZE | WIDTH | HEIGHT | X | Y
ih		 	FLbox  	"                      MIDI Tap Tempo                         ", 	1,      5,     14,    490,    20,     5,  0
ih		 	FLbox  	"-------------------------------------------------------------", 	1,      5,     14,    490,    20,     5,  20
ih		 	FLbox  	"The example demonstrate a method for defining a tempo by     ", 	1,      5,     14,    490,    20,     5,  40
ih		 	FLbox  	"tapping notes on a MIDI keyboard. The time difference between", 	1,      5,     14,    490,    20,     5,  60
ih		 	FLbox  	"consecutive MIDI note-ons is recorded and used to derive a   ", 	1,      5,     14,    490,    20,     5,  80
ih		 	FLbox  	"tempo value. In this example this value is used to define the", 	1,      5,     14,    490,    20,     5, 100
ih		 	FLbox  	"delay time of a simple delay effect that is applied to the   ", 	1,      5,     14,    490,    20,     5, 120
ih		 	FLbox  	"live audio input of the computer.                            ", 	1,      5,     14,    490,    20,     5, 140

				FLpanel_end


			FLrun

gkTime		init	1	;INITIALISE VARIABLE FOR TIME GAP BETWEEN KEY PRESSES
gkDlyTim	init	1	;INITIALISE DELAY TIME VARIABLE USED IN THE DELAY EFFECT IN INSTR 4

instr	1	;MIDI TRIGGERED INSTRUMENT - RECEIVES 'TAPS'
	event_i	"i", p1+2, 0, 0.001, i(gkTime)	;TRIGGER TEMPO CALCULATING INSTRUMENT
	event_i	"i", p1+1, 0, -1		;START 'TIMER' INSTRUMENT (-1 DURATION INDICATES A MONPHONIC HELD NOTE)
	FLsetVal_i	i(gkDlyTim), gihDlyTim	;SEND CURRENT DELAY TIME VALUE TO THE ON-SCREEN FLTK VALUATOR BOX
	turnoff					;TURNOFF THIS INSTRUMENT IMMEDIATELY
endin

instr	2	;TIMER TO MEASURE TIME GAP BETWEEN KEY PRESSES
	gkTime	timeinsts	;timeinsts OUTPUTS THE TIME SINCE THE START OF THE THIS NOTE BEING TRIGGERED
endin

instr	3	;CALCULATE CURRENT TEMPO BASED ON TIME GAP BETWEEN THE LAST TWO KEY PRESSES
	gkDlyTim	init	p4		;SET DELAY TIME (FOR DELAY EFFECT IN INSTR 4) TO CURRENT TIME GAP VALUE
	iTempo		=	60/p4		;DERIVE TEMPO FROM TIME GAP
	FLsetVal_i	iTempo, gihTempo	;SEND CURRENT DELAY TIME VALUE TO THE ON-SCREEN FLTK VALUATOR BOX
endin

instr	4	;DELAY INSTRUMENT - TAKES LIVE AUDIO IN AS ITS INPUT
	iMaxDlyTim	init	10			;INITIALISE VARIABLE FOR MAXIMUM DELAY TIME
	kDlyTim	limit	gkDlyTim, 0.001, iMaxDlyTim	;LIMIT DELAY TIME TO PREVENT CRASHES
	ain1	inch	1				;READ AUDIO FROM LIVE INPUT CHANNEL 1
	aFeedback	init	0			;INITIALISE FEEDBACK SIGNAL FOR FIRST k PASS
	aBuffer	delayr	iMaxDlyTim			;DEFINE AUDIO BUFFER FOR DELAY
	aTap	deltap3	kDlyTim				;READ AUDIO FROM A DELAY TAP FROM WITHIN THIS BUFFER
		delayw	ain1+(aFeedback)		;WRITE AUDIO INTO THE DELAY BUFFER (MIXTURE OF LIVE IN AND FEEDBACK LOOP)
	aFeedback	=	aTap*.5			;DEFINE THE AUDIO FEEDBACK SIGNAL FOR THE NEXT k PASS
	outs	(aTap+ain1)*.5, (aTap+ain1)*.5		;SEND AUDIO TO OUTPUTS (AND ATTENUATE)
endin

</CsInstruments>

<CsScore>
i 1 0 0.001	;INSTR 1 (SHORT NOTE)
i 4 0 3600	;INSTR 4 (DELAY) PLAYS FOR 1 HOUR 
</CsScore>

</CsoundSynthesizer>