;Written by Iain McCurdy, 2008

;THE delay OPCODES IS PLACED IN A SEPARATE, ALWAYS ON, INSTRUMENT FROM THE SOURCE SOUND PRODUCING INSTRUMENT.
;THE IS A COMMONLY USED TECHNIQUE WITH TIME SMEARING OPCODES AND EFFECTS LIKE REVERBS AND DELAYS.

;ksmps MAY NEED TO BE LOW (AND kr THEREFORE HIGH) WHEN WORKING WITH SHORT DELAY TIMES DEFINED INITIALLY AT KRATE

<CsoundSynthesizer>

<CsOptions>
-idevaudio -odevaudio -b400
</CsOptions>

<CsInstruments>

sr 		= 	44100	;SAMPLE RATE
ksmps 		= 	10	;NUMBER OF AUDIO SAMPLES IN EACH CONTROL CYCLE (MAY NEED TO BE LOW WHEN WORKING WITH SHORT DELAY TIMES DEFINED INITIALLY AT KRATE)
nchnls 		= 	2	;NUMBER OF CHANNELS (2=STEREO)
0dbfs		=	1	;MAXIMUM SOUND INTENSITY LEVEL REGARDLESS OF BIT DEPTH

gimaxdelay	=	5	;MAXIMUM DELAY TIME VARIABLE USED BOTH BY THE ORCHESTRA CODE AND BY FLTK WIDGET CODE IN THE HEADER

;FLTK INTERFACE CODE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
FLcolor	255, 255, 255, 0, 0, 0	;SETUP BASIC COLOURS
;			LABEL                    | WIDTH | HEIGHT | X | Y
		FLpanel	"Stereo Ping-Pong Delay",   500,    250,    0,  0

;                                                      				ON | OFF | TYPE | WIDTH | HEIGHT | X | Y | OPCODE | INS | STARTTIM | DUR
gkImpulse,ihImpulse		FLbutton	"Short Impulse Sound",		1,    0,    21,    200,     40,    5,  5,    0,      1,      0,      0.1

;VALUE_DISPLAY_BOXES			 	WIDTH | HEIGHT | X | Y
iddlt				FLvalue	" ",      70,    20,     5,  75
idmix				FLvalue	" ",      70,    20,     5, 125
idfeedbackamt			FLvalue	" ",      70,    20,     5, 175
idamp				FLvalue	" ",      70,    20,     5, 225
idInGain			FLvalue	" ",      50,    20,   210,  25

;SLIDERS					            			MIN |  MAX     | EXP | TYPE |      DISP    | WIDTH | HEIGHT | X | Y
gkdlt,ihdlt			FLslider 	"Delay Time (sec.)",		.001,gimaxdelay, -1,    23,           iddlt,   490,     25,    5,  50
gkmix,ihmix			FLslider 	"Dry/Wet Mix",			0,      1,        0,    23,           idmix,   490,     25,    5, 100
gkfeedamt,ihfeedamt		FLslider 	"Feedback Amount",		-1,     1,        0,    23,   idfeedbackamt,   490,     25,    5, 150
gkamp,ihamp			FLslider 	"Output Amplitude Rescaling",	0,      1,        0,    23,           idamp,   490,     25,    5, 200
gkInGain,ihInGain		FLslider 	"Live Input Gain",		0,      1,        0,    23,        idInGain,   285,     20,  210,   5

;SET_INITIAL_VALUES		VALUE | HANDLE
		FLsetVal_i	.33, 	ihdlt
		FLsetVal_i	0.5, 	ihmix
		FLsetVal_i	0.66, 	ihfeedamt
		FLsetVal_i	.7, 	ihamp
		FLsetVal_i	0, 	ihInGain

		FLpanel_end	;END OF PANEL CONTENTS

;INSTRUCTIONS AND INFO PANEL
				FLpanel	" ", 515, 700, 512, 0
				FLscroll     515, 700, 0, 0
;TEXT BOXES												TYPE | FONT | SIZE | WIDTH | HEIGHT | X | Y
ih		 	FLbox  	"                    Stereo Ping-Pong Delay                   ", 	1,      5,     14,    490,    20,     5,   0
ih		 	FLbox  	"-------------------------------------------------------------", 	1,      5,     14,    490,    20,     5,  20
ih		 	FLbox  	"This example implements the classic ping-pong delay effect.  ", 	1,      5,     14,    490,    20,     5,  40
ih		 	FLbox  	"To implement the effect a total of three delay buffers are   ", 	1,      5,     14,    490,    20,     5,  60
ih		 	FLbox  	"required. One for the left channel with its own feedback     ", 	1,      5,     14,    490,    20,     5,  80
ih		 	FLbox  	"loop, one for the right channel with its own feedback loop   ", 	1,      5,     14,    490,    20,     5, 100
ih		 	FLbox  	"and a third one to create an initial delay offset in the     ", 	1,      5,     14,    490,    20,     5, 120
ih		 	FLbox  	"right channel. The first echo we will hear will be in the    ", 	1,      5,     14,    490,    20,     5, 140
ih		 	FLbox  	"left channel. The offsetting delay buffer has no feedback    ", 	1,      5,     14,    490,    20,     5, 160
ih		 	FLbox  	"loop.                                                        ", 	1,      5,     14,    490,    20,     5, 180
ih		 	FLbox  	"The schematic is shown below:                                ", 	1,      5,     14,    490,    20,     5, 200
ih		 	FLbox  	"                           (feedback)                        ", 	1,      5,     14,    490,    20,     5, 220
ih		 	FLbox  	"                        +-------<------+                     ", 	1,      5,     14,    490,    20,     5, 240
ih		 	FLbox  	"                        |              |                     ", 	1,      5,     14,    490,    20,     5, 260
ih		 	FLbox  	"                        v  +--------+  ^                     ", 	1,      5,     14,    490,    20,     5, 280
ih		 	FLbox  	"                        |  |        |  |                     ", 	1,      5,     14,    490,    20,     5, 300
ih		 	FLbox  	"      +-----------------+--+Delay L +--+---->LEFT_OUT        ", 	1,      5,     14,    490,    20,     5, 320
ih		 	FLbox  	"      |                    |time x 2|                        ", 	1,      5,     14,    490,    20,     5, 340
ih		 	FLbox  	"      |                    +--------+                        ", 	1,      5,     14,    490,    20,     5, 360
ih		 	FLbox  	"      |                                                      ", 	1,      5,     14,    490,    20,     5, 380
ih		 	FLbox  	" IN->-+                                                      ", 	1,      5,     14,    490,    20,     5, 400
ih		 	FLbox  	"      |                                                      ", 	1,      5,     14,    490,    20,     5, 420
ih		 	FLbox  	"      |     +--------+     +--------+                        ", 	1,      5,     14,    490,    20,     5, 440
ih		 	FLbox  	"      |     |Offset  |     |        |                        ", 	1,      5,     14,    490,    20,     5, 460
ih		 	FLbox  	"      +-----+Delay   +--+--+Delay  R+--+---->RIGHT_OUT       ", 	1,      5,     14,    490,    20,     5, 480
ih		 	FLbox  	"            |time x 1|  |  |time x 2|  |                     ", 	1,      5,     14,    490,    20,     5, 500
ih		 	FLbox  	"            +--------+  ^  +--------+  v                     ", 	1,      5,     14,    490,    20,     5, 520
ih		 	FLbox  	"                        |              |                     ", 	1,      5,     14,    490,    20,     5, 540
ih		 	FLbox  	"                        +-------<------+                     ", 	1,      5,     14,    490,    20,     5, 560
ih		 	FLbox  	"                           (feedback)                        ", 	1,      5,     14,    490,    20,     5, 580
ih		 	FLbox  	"                                                             ", 	1,      5,     14,    490,    20,     5, 600
ih		 	FLbox  	"The delay time for the offsetting delay is the same as that  ", 	1,      5,     14,    490,    20,     5, 620
ih		 	FLbox  	"defined by the on-screen slider for delay time. The delay    ", 	1,      5,     14,    490,    20,     5, 640
ih		 	FLbox  	"times for the other two delays with feedback are twice the   ", 	1,      5,     14,    490,    20,     5, 660
ih		 	FLbox  	"value defined by the slider. When the echoes alternate       ", 	1,      5,     14,    490,    20,     5, 680
ih		 	FLbox  	"the perceived delay time will be the same as that defined by ", 	1,      5,     14,    490,    20,     5, 700
ih		 	FLbox  	"the slider.                                                  ", 	1,      5,     14,    490,    20,     5, 720
ih		 	FLbox  	"The input sound for the effect in this example can be either ", 	1,      5,     14,    490,    20,     5, 740
ih		 	FLbox  	"a short synthesised impulse triggered by the button or the   ", 	1,      5,     14,    490,    20,     5, 760
ih		 	FLbox  	"computer's live input controlled by the 'Input Gain' slider. ", 	1,      5,     14,    490,    20,     5, 780

				FLscrollEnd                                                                                                                                                 
				FLpanel_end                                                                                                      
                                                                                                                                                 
				FLrun	;RUN THE FLTK WIDGET THREAD                                                                              
;END OF FLTK INTERFACE CODE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;                     
                                                                                                                                                 
instr	1	;GENERATES A SHORT SYNTHESISED IMPULSE SOUND                                                                                                     
	aenv		expseg	0.0001, 0.01, 1, p3-0.01, 0.0001	;PERCUSSIVE-TYPE AMPLITUDE ENVELOPE
	asig1		noise	0.3 * aenv, 0				;GENERATE A 'WHITE NOISE' SIGNAL
	iCutoff_Oct	random	6,14					;CREATE A RANDOM VALUE FOR CUTOFF FREQUENCY (IN OCT FORMAT)
	asig2		butlp	asig1, cpsoct(iCutoff_Oct)		;LOWPASS FILTER WHITE NOISE
	gasig		balance	asig2, asig1				;BALANCE FILTERED SIGNAL WITH UNFILTERED WHITE NOISE SIGNAL TO COMPENSATE FOR AMPLITUDE LOSS
endin

instr 		2	;STEREO PING-PONG DELAY INSTRUMENT - ALSO READS LIVE INPUT SIGNAL
	gasig		init	0		;SET INITIAL STATE OF GLOBAL AUDIO SIGNAL (SILENCE)
	aInL, aInR	ins			;READ LIVE AUDIO INPUT
	aInL		=	(aInL * gkInGain) + gasig	;MIX LIVE AUDIO IN WITH GLOBAL AUDIO SIGNAL RECEIVED FROM INSTR 1
	aInR		=	(aInR * gkInGain) + gasig	;MIX LIVE AUDIO IN WITH GLOBAL AUDIO SIGNAL RECEIVED FROM INSTR 1
	
	iporttime	=		.1	;PORTAMENTO TIME
	kporttime	linseg		0, .001, iporttime, 1, iporttime ;USE OF AN ENVELOPE VALUE THAT QUICKLY RAMPS UP FROM ZERO TO THE REQUIRED VALUE. THIS PREVENTS VARIABLES GLIDING TO THEIR REQUIRED VALUES EACH TIME THE INSTRUMENT IS STARTED
	kdlt		portk		gkdlt, kporttime ;PORTAMENTO IS APPLIED TO THE VARIABLE 'gkdlt'. A NEW VARIABLE 'kdlt' IS CREATED.
	adlt		interp		kdlt	;A NEW A-RATE VARIABLE 'adlt' IS CREATED BY INTERPOLATING THE K-RATE VARIABLE 'kdlt' 
	
	;;;RIGHT CHANNEL OFFSET;;;NO FEEDBACK!!;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
	abufferR_OS	delayr	gimaxdelay	;CREATE A DELAY BUFFER OF imaxdelay SECONDS DURATION
	adelsigR_OS 	deltap3	adlt		;TAP THE DELAY LINE AT adlt SECONDS
			delayw	aInL		;WRITE AUDIO SOURCE INTO THE BEGINNING OF THE BUFFER
	
	;;;LEFT CHANNEL DELAY;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
	abufferL	delayr	gimaxdelay*2			;CREATE A DELAY BUFFER OF 5 SECONDS DURATION (EQUIVALENT TO THE MAXIMUM DELAY TIME POSSIBLE USING THIS EXAMPLE)
	adelsigL 	deltap3	adlt*2				;TAP THE DELAY LINE AT gkdlt SECONDS
			delayw	aInR + (adelsigL * gkfeedamt)	;WRITE AUDIO SOURCE AND FEEDBACK SIGNAL INTO THE BEGINNING OF THE BUFFER
	
	abufferR	delayr	gimaxdelay*2				;CREATE A DELAY BUFFER OF 5 SECONDS DURATION (EQUIVALENT TO THE MAXIMUM DELAY TIME POSSIBLE USING THIS EXAMPLE)
	adelsigR 	deltap3	adlt*2					;TAP THE DELAY LINE AT gkdlt SECONDS
			delayw	adelsigR_OS + (adelsigR * gkfeedamt)	;WRITE AUDIO SOURCE AND FEEDBACK SIGNAL INTO THE BEGINNING OF THE BUFFER
		
			outs		((adelsigL * gkmix) + (aInL * (1-gkmix))) * gkamp, (((adelsigR + adelsigR_OS) * gkmix) + (aInR * (1-gkmix))) * gkamp	;CREATE A MIX BETWEEN THE WET AND THE DRY SIGNALS AT THE OUTPUT
	gasig		=	0	;CLEAR THE GLOBAL AUDIO SEND VARIABLES
endin

</CsInstruments>

<CsScore>
;INSTR | START | DURATION
i  2       0       3600	;INSTRUMENT 2 (DELAY INSTRUMENT) PLAYS for 1 HOUR (AND KEEPS PERFORMANCE GOING)
</CsScore>

</CsoundSynthesizer>