; PARAFONIK string synthetiser
; 
; Basic code by Steven Yi
; adapted by Severak
<Cabbage>
form caption("Parafonik") size(400, 300), colour(58, 110, 182), pluginid("def1")
keyboard bounds(2, 174, 400, 100)
label bounds(60, 6, 252, 33) text("Parafonik")
hslider bounds(120, 44, 124, 30) range(0.1, 1, 0.1, 1, 0.001) channel("portk")
</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

;; Mixing signals
ga1 init 0
ga2 init 0

;; voice count
gkcount init 0

instr 1
  
  ;; CODE FOR COUNTING ACTIVE VOICES
  kreleased init 0
  gkcount init i(gkcount) + 1
  
  if(release() == 1 && kreleased == 0) then
    kreleased = 1
    gkcount -= 1
  endif
  
  ;; processing for MIDI key/velocity
  icps = cpsmidi()
  ivel = 15; ampmidi(20)
  ;print ivel
  iamp = ampdbfs(-20 + ivel)
  ipan = 0.5
  ipch = icps
  
  ;; 2 Sawtooth VCO's, one ocatve apart
  asig = vco2(iamp, ipch)
  asig += vco2(iamp * 0.5, ipch * 2)  

  asig *= linsegr(0, 0.01, 1, .01, 0)
  asig *= iamp
  
  al, ar pan2 asig, ipan

  ;out(al, ar)
  
  ga1 += al
  ga2 += ar
endin 

instr 2
  
  ;printk2 gkcount
  
  ;; SHARED VCF SECTION
  icut = cpsoct(11.00)
  ga1 = zdf_2pole(ga1, icut, 0.5)
  ga2 = zdf_2pole(ga2, icut, 0.5)
 
  ;; ENVELOPE BASED ON VOICE COUNT
  ;; USES port TO GENERATE ENVELOPE 
  gkon = (gkcount > 0) ? 1 : 0
 
  ;; (0,1) => (-30,0) dB => amp
  gkenv = ampdbfs(-30 + 30 * portk(gkon, chnget("portk") ))
  
  ga1 *= gkenv
  ga2 *= gkenv
  
;  asig *= linsegr(0, 0.1, 1, 0.5, 0.5, 0.25, 0) * 0.5
  
  ;; REVERB SEND MIXING
  a1, a2 reverbsc ga1, ga2, 0.70, 10000
  
  a1 = ntrpol(a1, ga1, 0.8)
  a2 = ntrpol(a2, ga2, 0.8)  
  
  out(a1, a2)
  ga1 = 0
  ga2 = 0
endin 

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