;WRITTEN BY IAIN MCCURDY, 2008

<CsoundSynthesizer>

<CsOptions>
-odevaudio -b400
</CsOptions>

<CsInstruments>

sr 	= 	44100  
ksmps 	= 	1
nchnls 	= 	2
0dbfs	=	1

;FLTK INTERFACE CODE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
FLcolor	210, 210, 255, 0, 0, 0	;SET INTERFACE COLOURS
		FLpanel	" ", 550, 200, 0, 0
;                                             		ON | OFF | TYPE | WIDTH | HEIGHT | X | Y | OPCODE | I | STARTTIM | IDUR |  p4
gkOnOff,ihOnOff	FLbutton	"Play/Stop",		1,    0,    22,    100,     25,    5,  5,   0,      1,     0,       -1
gkClear,ihClear	FLbutton	"Clear All",		1,    0,    21,     80,     25,  270,  5,   0,    102,     0,       0.01

FLsetColor	190, 190, 190, ihOnOff		;SET PRIMARY COLOUR TO GREY
FLsetColor2	255, 255, 50, ihOnOff		;SET SECONDARY COLOUR TO YELLOW

;COUNTERS				MIN | MAX | STEP1 | STEP2 | TYPE | WIDTH | HEIGHT | POS_X | POS_Y | OPCODE
gkBPM,ihBPM 	FLcount		"BPM",	1,    999,    1,     10,     21,   150,     25,     110,      5,     -1
FLsetColor	255, 255, 255, ihBPM		;SET SECONDARY COLOUR TO WHITE

;BORDERS					ITYPE, IFONT, ISIZE, IWIDTH, IHEIGHT, IX, IY
ih		 	FLbox  	" ", 		5,        9,    15,    80,    125,    98, 68
ih		 	FLbox  	" ", 		5,        9,    15,    80,    125,   178, 68
ih		 	FLbox  	" ", 		5,        9,    15,    80,    125,   258, 68
ih		 	FLbox  	" ", 		5,        9,    15,    80,    125,   338, 68
ih		 	FLbox  	"G A I N", 	1,        9,    15,   100,     20,   420, 22

;TEXT BOXES					TYPE | FONT | SIZE | WIDTH | HEIGHT | X | Y
ih		 	FLbox  	"       Kick",	1,      5,     13,     90,     12,     0,  73
ih		 	FLbox  	"    Kalimba",	1,      5,     13,     90,     12,     0,  93
ih		 	FLbox  	"      Snare",	1,      5,     13,     90,     12,     0, 113
ih		 	FLbox  	"H.H. Closed",	1,      5,     13,     90,     12,     0, 133
ih		 	FLbox  	"  H.H. Open",	1,      5,     13,     90,     12,     0, 153
ih		 	FLbox  	" Tambourine",	1,      5,     13,     90,     12,     0, 173

;SLIDERS			            			MIN  | MAX | EXP | TYPE | DISP | WIDTH | HEIGHT | X | Y
gkMasterGain, ihMasterGain	FLslider 	"Master",	0,      1,    0,    3,     -1,   100,      15,  420,  42
gkphs, gihphs			FLslider 	"",		0,      1,    0,    1,     -1,   305,       9,  106,  58
FLsetColor2	0,255,0,gihphs
FLsetColor	255, 255, 255, ihMasterGain		;SET PRIMARY COLOUR TO WHITE

iy	init	50	;Y OFFSET

#define	ROW(COUNT)	#iy	=	iy+20
;                                             		ON | OFF | TYPE | WIDTH | HEIGHT | X | Y | OPCODE |   I     | STARTTIM | IDUR |  p4
gk$COUNT,gih$COUNT_01	FLbutton	" ",		1,    0,    4,     20,     20,    100, iy,   0,    9+$COUNT,    0,        0,     1 
gk$COUNT,gih$COUNT_02	FLbutton	" ",		1,    0,    4,     20,     20,    120, iy,   0,    9+$COUNT,    0,        0,     2  
gk$COUNT,gih$COUNT_03	FLbutton	" ",		1,    0,    4,     20,     20,    140, iy,   0,    9+$COUNT,    0,        0,     3  
gk$COUNT,gih$COUNT_04	FLbutton	" ",		1,    0,    4,     20,     20,    160, iy,   0,    9+$COUNT,    0,        0,     4  
gk$COUNT,gih$COUNT_05	FLbutton	" ",		1,    0,    4,     20,     20,    180, iy,   0,    9+$COUNT,    0,        0,     5  
gk$COUNT,gih$COUNT_06	FLbutton	" ",		1,    0,    4,     20,     20,    200, iy,   0,    9+$COUNT,    0,        0,     6  
gk$COUNT,gih$COUNT_07	FLbutton	" ",		1,    0,    4,     20,     20,    220, iy,   0,    9+$COUNT,    0,        0,     7  
gk$COUNT,gih$COUNT_08	FLbutton	" ",		1,    0,    4,     20,     20,    240, iy,   0,    9+$COUNT,    0,        0,     8  
gk$COUNT,gih$COUNT_09	FLbutton	" ",		1,    0,    4,     20,     20,    260, iy,   0,    9+$COUNT,    0,        0,     9  
gk$COUNT,gih$COUNT_10	FLbutton	" ",		1,    0,    4,     20,     20,    280, iy,   0,    9+$COUNT,    0,        0,     10 
gk$COUNT,gih$COUNT_11	FLbutton	" ",		1,    0,    4,     20,     20,    300, iy,   0,    9+$COUNT,    0,        0,     11 
gk$COUNT,gih$COUNT_12	FLbutton	" ",		1,    0,    4,     20,     20,    320, iy,   0,    9+$COUNT,    0,        0,     12 
gk$COUNT,gih$COUNT_13	FLbutton	" ",		1,    0,    4,     20,     20,    340, iy,   0,    9+$COUNT,    0,        0,     13 
gk$COUNT,gih$COUNT_14	FLbutton	" ",		1,    0,    4,     20,     20,    360, iy,   0,    9+$COUNT,    0,        0,     14 
gk$COUNT,gih$COUNT_15	FLbutton	" ",		1,    0,    4,     20,     20,    380, iy,   0,    9+$COUNT,    0,        0,     15 
gk$COUNT,gih$COUNT_16	FLbutton	" ",		1,    0,    4,     20,     20,    400, iy,   0,    9+$COUNT,    0,        0,     16
gk$COUNTGain, ih$COUNTGain		FLslider 	"",		0,      1,    0,    3,     -1,   100,      15,  420, iy+2
FLsetVal_i	0.7, 	ih$COUNTGain
FLsetColor	255, 255, 255, ih$COUNTGain		;SET PRIMARY COLOUR TO WHITE
#
$ROW(1)
$ROW(2)
$ROW(3)
$ROW(4)
$ROW(5)
$ROW(6)

;INITIALISE FLTK VALUATORS
		FLsetVal_i	100, 	ihBPM
		FLsetVal_i	.5, 	ihMasterGain

		FLpanel_end	;END OF PANEL CONTENTS

FLcolor	255, 255, 255, 0, 0, 0	;SET INTERFACE COLOURS
;INSTRUCTIONS AND INFO PANEL
				FLpanel	" ", 500, 400, 562, 0
;TEXT BOXES												TYPE | FONT | SIZE | WIDTH | HEIGHT | X | Y
ih		 	FLbox  	"                    Simple Drum Sequencer                    ", 	1,      5,     14,    490,    15,     5,  0
ih		 	FLbox  	"-------------------------------------------------------------", 	1,      5,     14,    490,    15,     5,  20
ih		 	FLbox  	"This example demonstrates how to contruct a simple looping   ", 	1,      5,     14,    490,    15,     5,  40
ih		 	FLbox  	"drum sequencer. Sequence data (i.e. play/don't play) is      ", 	1,      5,     14,    490,    15,     5,  60
ih		 	FLbox  	"stored is GEN 2 function tables. This data is retrieved and  ", 	1,      5,     14,    490,    15,     5,  80
ih		 	FLbox  	"played the 'timedseq' and 'schedkwhen' opcodes.              ", 	1,      5,     14,    490,    15,     5, 100
ih		 	FLbox  	"Each time a sequence event is changed the function table     ", 	1,      5,     14,    490,    15,     5, 120
ih	  	 	FLbox  	"corresponding to that sound is updated with the new data.    ", 	1,      5,     14,    490,    15,     5, 140
ih		 	FLbox  	"Tempo is adjustable and there is a gain control for each     ", 	1,      5,     14,    490,    15,     5, 160
ih		 	FLbox  	"sound as well as a master gain control.                      ", 	1,      5,     14,    490,    15,     5, 180
ih		 	FLbox  	"An additional feature is that sound 4 (closed hi-hat) will   ", 	1,      5,     14,    490,    15,     5, 200
ih		 	FLbox  	"cut off sound 5 (open hi-hat) as would happen with a real    ", 	1,      5,     14,    490,    15,     5, 220
ih		 	FLbox  	"hi-hat.                                                      ", 	1,      5,     14,    490,    15,     5, 240
ih		 	FLbox  	"Sounds are produced using either simple synthesis or one of  ", 	1,      5,     14,    490,    15,     5, 260
ih		 	FLbox  	"Csound's physical modelling opcodes.                         ", 	1,      5,     14,    490,    15,     5, 280
ih		 	FLbox  	"Obviously there are numererous programs and plugins that     ", 	1,      5,     14,    490,    15,     5, 300
ih		 	FLbox  	"perform a similar task but this example at least serves to   ", 	1,      5,     14,    490,    15,     5, 320
ih		 	FLbox  	"prove that this can be done in Csound and there remains to   ", 	1,      5,     14,    490,    15,     5, 340
ih		 	FLbox  	"possibility to expand this technique into something much more", 	1,      5,     14,    490,    15,     5, 360
ih		 	FLbox  	"unique.                                                      ", 	1,      5,     14,    490,    15,     5, 380

				FLpanel_end

		FLrun		;RUN THE WIDGET THREAD!

gisine		ftgen		0,0,4096,10,1	;SINE WAVE
gkphs		init		0

;FUNCTION TABLE FOR STORAGE OF SEQUENCE DATA FOR SOUND 1
gi01		ftgen		0,0,128,-2,	0,	0.25,	.001,	0,\
						0,	0.5,	.001,	0,\
						0,	0.75,	.001,	0,\
						0,	1,	.001,	0,\
						0,	1.25,	.001,	0,\
						0,	1.5,	.001,	0,\
						0,	1.75,	.001,	0,\
						0,	2,	.001,	0,\
						0,	2.25,	.001,	0,\
						0,	2.5,	.001,	0,\
						0,	2.75,	.001,	0,\
						0,	3,	.001,	0,\
						0,	3.25,	.001,	0,\
						0,	3.5,	.001,	0,\
						0,	3.75,	.001,	0,\
						0,	4,	.001,	0,\
						-1,	4,	-1,	-1

gi02		ftgen		0,0,128,-2,0	;EMPTY TABLES INITIALLY. CONTENTS WILL BE COPIED FROM TABLE gi01
gi03		ftgen		0,0,128,-2,0	;EMPTY TABLES INITIALLY. CONTENTS WILL BE COPIED FROM TABLE gi01
gi04		ftgen		0,0,128,-2,0	;EMPTY TABLES INITIALLY. CONTENTS WILL BE COPIED FROM TABLE gi01
gi05		ftgen		0,0,128,-2,0	;EMPTY TABLES INITIALLY. CONTENTS WILL BE COPIED FROM TABLE gi01
gi06		ftgen		0,0,128,-2,0	;EMPTY TABLES INITIALLY. CONTENTS WILL BE COPIED FROM TABLE gi01
gisine		ftgen		0,0,4096,10,1	;SINE WAVE

instr	1	; NOTE TRIGGERING INSTRUMENT
	if	gkOnOff!=0	goto	CONTINUE
	turnoff
	CONTINUE:
	
	kBPS	=	gkBPM/60	;CONVERT BEATS PER MINUTE TO BEATS PER SECOND
	isubdiv		=	4	;NUMBER OF SUBDIVISIONS OF THE BEAT
	kphs    	phasor  kBPS/isubdiv	;CREATE MOVING PHASE VALUE 
	ktrigger	metro	20
	FLsetVal	ktrigger, kphs, gihphs
	ktimpnt 	=        kphs * isubdiv	;RESCALE POINTER
	kp1		init	0		;INITIALISE P-FIELD VALUES OUTPUT BY timedseq
	kp2		init	0               ;INITIALISE P-FIELD VALUES OUTPUT BY timedseq
	kp3		init	0               ;INITIALISE P-FIELD VALUES OUTPUT BY timedseq
	kp4		init	0               ;INITIALISE P-FIELD VALUES OUTPUT BY timedseq
	
	ktrig   timedseq ktimpnt,gi01, kp1, kp2,kp3, kp4	;CREATE NOTE TRIGGERS AND P-FIELDS FOR SOUND 1 FROM FUNCTION TABLE gi01 
	;OPCODE 	TRIGGER | MINTIM | MAXNUM | INSNUM | WHEN | DUR | P4 | P5
	schedkwhen 	ktrig,      0,       0,        2,     0,    kp3,  kp4,  1	;TRIGGER INTERROGATION INSTRUMENT
	
	ktrig   timedseq ktimpnt,gi02, kp1, kp2,kp3, kp4	;CREATE NOTE TRIGGERS AND P-FIELDS FOR SOUND 2 FROM FUNCTION TABLE gi02 
	;OPCODE 	TRIGGER | MINTIM | MAXNUM | INSNUM | WHEN | DUR | P4 | P5
	schedkwhen	ktrig,       0,       0,      2,       0,   kp3,   kp4, 2
	
	ktrig   timedseq ktimpnt,gi03, kp1, kp2,kp3, kp4	;CREATE NOTE TRIGGERS AND P-FIELDS FOR SOUND 3 FROM FUNCTION TABLE gi03 
	;OPCODE 	TRIGGER | MINTIM | MAXNUM | INSNUM | WHEN | DUR | P4 | P5
	schedkwhen	ktrig,       0,       0,      2,       0,   kp3,   kp4, 3
	
	ktrig   timedseq ktimpnt,gi04, kp1, kp2,kp3, kp4	;CREATE NOTE TRIGGERS AND P-FIELDS FOR SOUND 4 FROM FUNCTION TABLE gi04 
	;OPCODE 	TRIGGER | MINTIM | MAXNUM | INSNUM | WHEN | DUR | P4 | P5
	schedkwhen 	ktrig,       0,       0,      2,       0,   kp3,   kp4, 4
	
	ktrig   timedseq ktimpnt,gi05, kp1, kp2,kp3, kp4	;CREATE NOTE TRIGGERS AND P-FIELDS FOR SOUND 5 FROM FUNCTION TABLE gi05 
	;OPCODE 	TRIGGER | MINTIM | MAXNUM | INSNUM | WHEN | DUR | P4 | P5
	schedkwhen	ktrig,       0,       0,      2,       0,   kp3,   kp4, 5
	
	ktrig   timedseq ktimpnt,gi06, kp1, kp2,kp3, kp4	;CREATE NOTE TRIGGERS AND P-FIELDS FOR SOUND 6 FROM FUNCTION TABLE gi06 
	;OPCODE 	TRIGGER | MINTIM | MAXNUM | INSNUM | WHEN | DUR | P4 | P5
	schedkwhen 	ktrig,       0,       0,      2,       0,   kp3,   kp4, 6
endin

instr	2	;INTERROGATE EVENT AND DETERMINE WHETHER A SOUND SHOULD BE PLAYED OR NOT
	if	p4=1	then			;IF EVENT VARIABLE IS '1'...
		event_i	"i", p1+p5, 0, p3	;...PLAY A SOUND
	endif					;END OF CONDITIONAL BRANCH
endin

instr	3	;SOUND 1 - BASS DRUM
	p3	=	.2		;DEFINE DURATION FOR THIS SOUND
	aenv	expon	1,p3,0.001	;AMPLITUDE ENVELOPE - PERCUSSIVE DECAY
	kcps	expon	200,p3,20	;PITCH GLISSANDO
	;OUTPUT	OPCODE	AMPLITUDE                             | FREQUENCY | FUNCTION_TABLE
	asig	oscil	aenv*i(gk1Gain)*i(gkMasterGain)*1.6,     kcps,       gisine 		;OSCILLATOR
		outs	asig, asig	;SEND AUDIO TO OUTPUTS
endin

instr	4	;SOUND 2 - KALIMBA (BAR MODEL)
	p3	=	2.6		;DEFINE DURATION FOR THIS SOUND
	asig 	barmodel	1, 1, 80, 1, 0, 2.6, 0.5, 6000, 0.07	;KALIMBA SOUND CREATED USING barmodel OPCODE (SEE CSOUND MANUAL FOR MORE INFO.)
		outs	asig*i(gk2Gain)*i(gkMasterGain), asig*i(gk2Gain)*i(gkMasterGain) 	;SEND AUDIO TO OUTPUTS AND ATTENUATE  USING GAIN CONTROLS
endin

instr	5	;SOUND 3 - SNARE
	p3	=	0.3		;DEFINE DURATION FOR THIS SOUND
	aenv	expon	1,p3,0.001	;AMPLITUDE ENVELOPE - PERCUSSIVE DECAY
	anse	noise	1, 0 	;CREATE NOISE COMPONENT FOR SNARE DRUM SOUND
	kcps	expon	400,p3,20				;CREATE TONE COMPONENT FREQUENCY GLISSANDO FOR SNARE DRUM SOUND
	ajit	randomi	0.2,1.8,10000				;JITTER ON FREQUENCY FOR TONE COMPONENT
	atne	oscil	aenv*i(gk3Gain)*i(gkMasterGain),kcps*ajit,gisine	;CREATE TONE COMPONENT
	asig	sum	anse*0.5, atne*5	;MIX NOISE AND TONE SOUND COMPONENTS
	ares 	vcomb 	asig, 0.02, 0.0035, .1	;PASS SIGNAL THROUGH ACOMB FILTER TO CREATE STATIC HARMONIC RESONANCE
		outs	ares*aenv*i(gk3Gain)*i(gkMasterGain), ares*aenv*i(gk3Gain)*i(gkMasterGain)	;SEND AUDIO TO OUTPUTS, APPLY ENVELOPE AND ATTENTUATE USING GAIN CONTROLS 
endin

instr	6	;SOUND 4 - CLOSED HI-HAT
	turnoff2 7,0,0	;TURN OFF ALL INSTANCES OF instr 7 (OPEN HI-HAT)
	p3	=	0.1		;DEFINE DURATION FOR THIS SOUND
	aenv	expon	1,p3,0.001	;AMPLITUDE ENVELOPE - PERCUSSIVE DECAY
	asig	noise	aenv*i(gk4Gain)*i(gkMasterGain), 0	;CREATE SOUND FOR CLOSED HI-HAT
	asig	buthp	asig, 7000					;HIGHPASS FILTER SOUND
		outs	asig, asig	;SEND AUDIO TO OUTPUTS
endin

instr	7	;SOUND 5 - OPEN HI-HAT
	p3	=	1		;DEFINE DURATION FOR THIS SOUND
	aenv	expon	1,p3,0.001	;AMPLITUDE ENVELOPE - PERCUSSIVE DECAY
	asig	noise	aenv*i(gk5Gain)*i(gkMasterGain), 0	;CREATE SOUND FOR CLOSED HI-HAT
	asig	buthp	asig, 7000					;HIGHPASS FILTER SOUND	
		outs	asig, asig	;SEND AUDIO TO OUTPUTS
endin

instr	8	;SOUND 6 - TAMBOURINE
	        p3	=	0.5		;DEFINE DURATION FOR THIS SOUND
	asig	tambourine	i(gk6Gain)*i(gkMasterGain)*0.3,0.01 ,32, 0.47, 0, 2300 , 5600, 8000	;TAMBOURINE SOUND CREATED USING tambourine PHYSICAL MODELLING OPCODE (SEE CSOUND MANUAL FOR MORE INFO.)
		outs	asig, asig	;SEND AUDIO TO OUTPUTS
endin

instr	10	;WRITE SEQUENCE VALUE TO TABLE FOR SOUND 1
	tableiw	i(gk1), ((p4-1)*4)+3, gi01 	
endin

instr	11	;WRITE SEQUENCE VALUE TO TABLE FOR SOUND 2
	tableiw	i(gk2), ((p4-1)*4)+3, gi02 	
endin

instr	12	;WRITE SEQUENCE VALUE TO TABLE FOR SOUND 3
	tableiw	i(gk3), ((p4-1)*4)+3, gi03 	
endin

instr	13	;WRITE SEQUENCE VALUE TO TABLE FOR SOUND 4
	tableiw	i(gk4), ((p4-1)*4)+3, gi04
endin

instr	14	;WRITE SEQUENCE VALUE TO TABLE FOR SOUND 5
	tableiw	i(gk5), ((p4-1)*4)+3, gi05 	
endin

instr	15	;WRITE SEQUENCE VALUE TO TABLE FOR SOUND 6
	tableiw	i(gk6), ((p4-1)*4)+3, gi06 	
endin

instr	100	;COPY TABLE 1 TO ALL OTHER TABLES (PERFORMED ONCE AT THE BEGINNING OF THE PERFORMANCE)
	tableicopy gi02, gi01
	tableicopy gi03, gi01
	tableicopy gi04, gi01
	tableicopy gi05, gi01
	tableicopy gi06, gi01
endin

instr	101	;SET INITIAL PATTERN
	FLsetVal_i	1, gih1_01
	FLsetVal_i	1, gih1_04
	FLsetVal_i	1, gih1_09
	FLsetVal_i	1, gih1_11
	FLsetVal_i	1, gih1_14

	FLsetVal_i	1, gih2_05
	FLsetVal_i	1, gih2_16

	FLsetVal_i	1, gih3_05
	FLsetVal_i	1, gih3_08
	FLsetVal_i	1, gih3_13
	FLsetVal_i	1, gih3_15

	FLsetVal_i	1, gih4_01
	FLsetVal_i	1, gih4_02
	FLsetVal_i	1, gih4_04
	FLsetVal_i	1, gih4_05
	FLsetVal_i	1, gih4_06
	FLsetVal_i	1, gih4_09
	FLsetVal_i	1, gih4_10
	FLsetVal_i	1, gih4_12
	FLsetVal_i	1, gih4_13
	FLsetVal_i	1, gih4_14

	FLsetVal_i	1, gih5_03
	FLsetVal_i	1, gih5_07
	FLsetVal_i	1, gih5_11
	FLsetVal_i	1, gih5_15

	FLsetVal_i	1, gih6_01
	FLsetVal_i	1, gih6_03
	FLsetVal_i	1, gih6_05
	FLsetVal_i	1, gih6_07
	FLsetVal_i	1, gih6_09
	FLsetVal_i	1, gih6_11
	FLsetVal_i	1, gih6_13
	FLsetVal_i	1, gih6_15
endin

instr	102	;CLEAR ALL PATTERNS
#define	ROW(N)
	#
	FLsetVal_i	0, gih$N_01
	FLsetVal_i	0, gih$N_02
	FLsetVal_i	0, gih$N_03
	FLsetVal_i	0, gih$N_04
	FLsetVal_i	0, gih$N_05
	FLsetVal_i	0, gih$N_06
	FLsetVal_i	0, gih$N_07
	FLsetVal_i	0, gih$N_08
	FLsetVal_i	0, gih$N_09
	FLsetVal_i	0, gih$N_10
	FLsetVal_i	0, gih$N_11
	FLsetVal_i	0, gih$N_12
	FLsetVal_i	0, gih$N_13
	FLsetVal_i	0, gih$N_14
	FLsetVal_i	0, gih$N_15
	FLsetVal_i	0, gih$N_16
	#
	$ROW(1)
	$ROW(2)
	$ROW(3)
	$ROW(4)
	$ROW(5)
	$ROW(6)
endin
</CsInstruments>

<CsScore>
f 0 3600	;DUMMY SCORE EVENT - ALLOWS REALTIME PERFORMANCE FOR 1 HOUR
i 100 0 0	;TRIGGER INITIALISATION PASS IN INSTR 100 AT THE BEGINNING OF THE PERFORMANCE
i 101 0 0	;SET INITIAL PATTERN
</CsScore>

</CsoundSynthesizer>