<Cabbage>
form caption("Horowitz Duo") size(700, 280), colour(0, 51, 153), pluginid("hduo")
keyboard bounds(66, 160, 575, 95) value(40)
label bounds(66, 8, 261, 39) text("Horowitz Duo")
hslider bounds(66, 52, 80, 30) range(0.01, 1, 0.01, 1, 0.001) channel("hi_attack")
label bounds(4, 62, 60, 16) text("HIGH:")
label bounds(66, 90, 80, 16) text("ATTACK")
label bounds(4, 118, 57, 16) text("LOW:")
hslider bounds(66, 112, 80, 30) range(0.01, 1, 0.01, 1, 0.001) channel("lo_attack")
label bounds(150, 90, 80, 16) text("DECAY")
hslider bounds(150, 52, 80, 30) range(0.01, 1, 0.01, 1, 0.001) channel("hi_decay")
hslider bounds(150, 112, 80, 30) range(0.01, 1, 0.01, 1, 0.001) channel("lo_decay")
checkbox bounds(250, 52, 30, 30) channel("hi_organ")
checkbox bounds(252, 112, 30, 30) channel("lo_organ")
label bounds(234, 90, 63, 16) text("ORGAN")
checkbox bounds(320, 52, 30, 30) channel("hi_strings")
label bounds(300, 90, 73, 16) text("STRINGS")

checkbox bounds(322, 112, 30, 30) channel("lo_strings")
label bounds(376, 90, 65, 16) text("STAIRS")

checkbox bounds(388, 52, 30, 30) channel("hi_stairs")
checkbox bounds(390, 112, 30, 30) channel("lo_stairs")
label bounds(446, 90, 56, 16) text("FLUTE")
checkbox bounds(452, 52, 30, 30) channel("hi_flute")
checkbox bounds(454, 110, 30, 30) channel("lo_flute")
hslider bounds(504, 52, 80, 30) range(0, 1, 0, 1, 0.001) channel("hi_chorus")
label bounds(506, 90, 80, 16) text("CHORUS")
hslider bounds(506, 110, 80, 30) range(0, 1, 0, 1, 0.001) channel("lo_chorus")
label bounds(592, 90, 80, 16) text("VOLUME")
hslider bounds(592, 110, 80, 30) range(0, 1, 1, 1, 0.001) channel("lo_volume")
hslider bounds(592, 52, 80, 30) range(0, 1, 1, 1, 0.001) channel("hi_volume")
label bounds(336, 22, 139, 22) text("by Severák")
combobox bounds(592, 22, 80, 20) channel("split") text("C3", "F3", "off - all HI", "off - all LO")
label bounds(504, 24, 80, 16) text("SPLIT AT:")
</Cabbage>
<CsoundSynthesizer>
<CsOptions>
-n -d -+rtmidi=NULL -M0 -m0d --midi-key-cps=4 --midi-velocity-amp=5
</CsOptions>
<CsInstruments>
; Initialize the global variables. 
ksmps = 32
nchnls = 2
0dbfs = 1

giSplit[] fillarray 0, 59, 64, 20, 109

;Author: Iain McCurdy (2012)
;http://iainmccurdy.org/csound.html

opcode	StChorus,aa,aakkakk
	ainL,ainR,krate,kdepth,aoffset,kwidth,kmix	xin			;READ IN INPUT ARGUMENTS
	ilfoshape	ftgentmp	0, 0, 131072, 19, 1, 0.5, 0,  0.5	;POSITIVE DOMAIN ONLY SINE WAVE
	kporttime	linseg	0,0.001,0.02					;RAMPING UP PORTAMENTO VARIABLE
	kChoDepth	portk	kdepth*0.01, kporttime				;SMOOTH VARIABLE CHANGES WITH PORTK
	aChoDepth	interp	kChoDepth					;INTERPOLATE TO CREATE A-RATE VERSION OF K-RATE VARIABLE
	amodL 		osciliktp 	krate, ilfoshape, 0			;LEFT CHANNEL LFO
	amodR 		osciliktp 	krate, ilfoshape, kwidth*0.5		;THE PHASE OF THE RIGHT CHANNEL LFO IS ADJUSTABLE
	amodL		=		(amodL*aChoDepth)+aoffset			;RESCALE AND OFFSET LFO (LEFT CHANNEL)
	amodR		=		(amodR*aChoDepth)+aoffset			;RESCALE AND OFFSET LFO (RIGHT CHANNEL)
	aChoL		vdelay	ainL, amodL*1000, 1.2*1000			;CREATE VARYING DELAYED / CHORUSED SIGNAL (LEFT CHANNEL) 
	aChoR		vdelay	ainR, amodR*1000, 1.2*1000			;CREATE VARYING DELAYED / CHORUSED SIGNAL (RIGHT CHANNEL)
	aoutL		ntrpol 	ainL*0.6, aChoL*0.6, kmix			;MIX DRY AND WET SIGNAL (LEFT CHANNEL)
	aoutR		ntrpol 	ainR*0.6, aChoR*0.6, kmix			;MIX DRY AND WET SIGNAL (RIGHT CHANNEL)
			xout	aoutL,aoutR					;SEND AUDIO BACK TO CALLER INSTRUMENT
endop

opcode	StChorusRspline,aa,aakkkkkk
	ainL,ainR,krate,kdereg,kdepth,koffset,kwidth,kmix	xin		;READ IN INPUT ARGUMENTS
	kporttime	linseg	0,0.001,0.02					;RAMPING UP PORTAMENTO VARIABLE
	kChoDepth	portk	kdepth*0.01, kporttime				;SMOOTH VARIABLE CHANGES WITH PORTK	
	kmod1		rspline	koffset,kChoDepth, krate*4+0.01, ((krate*4*kdereg)+0.01)
	kmod2		rspline	kChoDepth,koffset, krate*4+0.01, ((krate*4*kdereg)+0.01)
	kmod1		limit	kmod1,0.0001,1.2
	kmod2		limit	kmod2,0.0001,1.2
	amod1		interp	kmod1	
	amod2		interp	kmod2
	aCho1		vdelay	ainL, amod1*1000, 1.2*1000			;CREATE VARYING DELAYED / CHORUSED SIGNAL (LEFT CHANNEL) 
	aCho2		vdelay	ainR, amod2*1000, 1.2*1000			;CREATE VARYING DELAYED / CHORUSED SIGNAL (RIGHT CHANNEL)
	kpan		rspline	0,1,krate,2*krate*kdereg			;PANNING
	kpan		limit	kpan,0,1
	apan		interp	kpan
	aChoL		=	(aCho1*apan)+(aCho2*(1-apan))
	aChoR		=	(aCho2*apan)+(aCho1*(1-apan))
	aChoL		ntrpol	aChoL,aCho1,kwidth				;WIDTH PROCESSING BETWEEN AUTO-PANNED AND HARD-PANNED
	aChoR		ntrpol	aChoR,aCho2,kwidth
	aoutL		ntrpol 	ainL*0.6, aChoL*0.6, kmix			;MIX DRY AND WET SIGNAL (LEFT CHANNEL)
	aoutR		ntrpol 	ainR*0.6, aChoR*0.6, kmix			;MIX DRY AND WET SIGNAL (RIGHT CHANNEL)
			xout	aoutL,aoutR					;SEND AUDIO BACK TO CALLER INSTRUMENT
endop


;instrument will be triggered by keyboard widget
instr 1
    irawsplit chnget "split"
    isplit = giSplit[irawsplit]
    inotnum notnum
    
    if inotnum>isplit then
       iattack chnget "hi_attack"
       idecay chnget "hi_decay"
       iorgan chnget "hi_organ"
       istrings chnget "hi_strings"
       istairs chnget "hi_stairs"
       iflute chnget "hi_flute" 
    else
       iattack chnget "lo_attack"
       idecay chnget "lo_decay"
       iorgan chnget "lo_organ"
       istrings chnget "lo_strings"
       istairs chnget "lo_stairs"
       iflute chnget "lo_flute"
    endif

    aOut = 0
    
    if iorgan==1 then
        aOrganSaw vco2 0.092, p4, 4, 0.5
        aOrganPulse vco2 0.3, p4, 2, 0.117
        aOrgan moogladder2 aOrganSaw + aOrganPulse, 9200, 0
        aOut = aOut + aOrgan
    endif
    
    if istrings==1 then
        aStringsOne vco2 0.15, p4, 4, 0.01
        aStringsTwo vco2 0.15, p4 * cent(13), 4, 0.01
        aOut = aOut + aStringsOne + aStringsTwo
    endif
    
    if istairs==1 then
        aStairsPulse vco2 0.05, p4, 2, 0.5
        aStairsSub vco2 0.1, p4 / 2, 2, 0.5
        aOut = aOut + aStairsPulse + aStairsSub 
    endif
    
    if iflute==1 then
        aFlute vco2 0.3, p4 * 2, 2, 0.5
        aFlute moogladder aFlute, 6204, 0.2
        aOut = aOut + aFlute
    endif
    

    kEnv madsr iattack, 0.0001, 1, idecay
    
    if inotnum>isplit then
        kVol chnget "hi_volume"
        chnmix aOut*kEnv*kVol, "ahi"
    else
        kVol chnget "lo_volume"
        chnmix aOut*kEnv*kVol, "alo"
    endif
       
    ;outs aOut*kEnv*kVol, aOut*kEnv*kVol
endin

instr 2
    khi_chorus chnget "hi_chorus"
    klo_chorus chnget "lo_chorus"
    
    aHi chnget "ahi"
    aLo chnget "alo"
    krate = 0.5
    kdereg = 0
    kdepth = 0.2
    koffset = 0.001
    kwidth = 0.75
    
    ; TODO - reverse engineer this part
    kporttime	linseg	0,0.001,0.05
    koffset	portk	koffset,kporttime*0.5
    aoffset	interp	koffset
    
    kdereg	rspline	-kdereg, kdereg, 0.1, 0.5
    ktrem	rspline	0,-1,0.1,0.5
    ktrem	pow	2,ktrem
    
    
    aHiL,aHiR	StChorus	aHi,aHi,krate*octave(kdereg),kdepth*ktrem,aoffset,kwidth,khi_chorus
    aLoL,aLoR	StChorus	aLo,aLo,krate*octave(kdereg),kdepth*ktrem,aoffset,kwidth,klo_chorus
    
    outs aHiL + aLoL, aHiR + aLoR  
    
    chnclear "ahi"
    chnclear "alo"
endin


</CsInstruments>
<CsScore>
;causes Csound to run for about 7000 years...
f0 z
i2 0 -1
</CsScore>
</CsoundSynthesizer>
