;@ map s 3 OSCsem OSCsem OSCsem OSCprt
;@ map d OSCcnt
;@ map d BUT006
;@ map d BUT002
;@ map d CLA000
;@ map d CLA000
;@ map d CLA000
;@ map d BUT002
;@ map d BUT002

; TODO Seems to work. Check Decay time

;@ ins k k a
;@ args a
opcode OscPerc, 0, kkkkkkkkkkkkk
; kModLev - 0...1
; kMod - blue - -64..+64
; FREQ SEMI FAC - ALL THE SAME!
; PART MODE = 3
; OSCPERC = OSCA + ENVD
kCoarse,kFine,kTuneMode,kKBT,kModLev,kD,kClick,kPunch,kON,kPitchIn,kModIn,kTrig,kOut xin

	kstate init 0
	kEnv init 0
	kEnvP init 1
	kTime init 0

	aGate zar kTrig
	kGate = k(aGate) ; maybe...
	kMod zkr kModIn

	; We assume that Click changes initial phase 0..0.3
	; only if Click > 0.5 of the range...
	kClick limit kClick,0.5,1
	kClick = (kClick - .5)*.6

if kKBT != 1 goto NoKBT
kNote = gkNote
goto KBT
NoKBT:
kNote = 64
KBT:

kPitch init 64
if kPitchIn == 0 goto Run
kPitch zkr kPitchIn
Run:
kM_ = kPitch+kModLev*kMod+kNote+kFine*0.01
if kTuneMode==3 goto Part
kFreq = cpsmidinn(kM_+kCoarse)
goto Out
Part:
kFreq = cpsmidinn(kM_)*kCoarse
Out:

	kTime limit kTime,0,kD*kr
	if kTime != kD*kr goto skip
		kTime = 0
		kstate = 0
		kEnv = 0
		kEnvP = kPunch+1
skip:
	kGateT trigger kGate, 0.000001, 0
	if kGateT == 1 then
		if kstate == 1 then
			kTime = 0
			kEnv = 1
			kEnvP = kPunch+1
		else
			kstate = 1
			kEnv = 1
			kTime = 0
			kEnvP = kPunch+1
		endif
	else
		if kstate == 1 then
			kTime += 1
			kEnv = exp(-4.2*kTime/(kD*kr))
			kEnvP = 2*(kPunch - kFreq*kTime/kr)
			kEnvP limit kEnvP, 1, 2
		endif
	endif
; we use oscilikts 'cos we need phase sync
aout oscilikts 0.5, kFreq*kEnvP, 1, aGate, kClick
	zaw aout*kON*kEnv, kOut

endop

;@ ins a a a
;@ outs a
opcode OscPerc, 0, kkkkkkkkkkkkk
; kModLev - 0...1
; kMod - blue - -64..+64
; FREQ SEMI FAC - ALL THE SAME!
; PART MODE = 3
; OSCPERC = OSCA + ENVD
kCoarse,kFine,kTuneMode,kKBT,kModLev,kD,kClick,kPunch,kON,kPitchIn,kModIn,kTrig,kOut xin

	kstate init 0
	kEnv init 0
	kEnvP init 1
	kTime init 0

	aGate zar kTrig
	kGate = k(aGate) ; maybe...
	aMod zar kModIn
	kMod = k(aMod) ; maybe...

	; We assume that Click changes initial phase 0..0.3
	; only if Click > 0.5 of the range...
	kClick limit kClick,0.5,1
	kClick = (kClick - .5)*.6

if kKBT != 1 goto NoKBT
kNote = gkNote
goto KBT
NoKBT:
kNote = 64
KBT:

kPitch init 64
if kPitchIn == 0 goto Run
aPitch zar kPitchIn
kPitch = k(aPitch) ; maybe...
Run:
kM_ = kPitch+kModLev*kMod+kNote+kFine*0.01
if kTuneMode==3 goto Part
kFreq = cpsmidinn(kM_+kCoarse)
goto Out
Part:
kFreq = cpsmidinn(kM_)*kCoarse
Out:

	kTime limit kTime,0,kD*kr
	if kTime != kD*kr goto skip
		kTime = 0
		kstate = 0
		kEnv = 0
		kEnvP = kPunch+1
skip:
	kGateT trigger kGate, 0.000001, 0
	if kGateT == 1 then
		if kstate == 1 then
			kTime = 0
			kEnv = 1
			kEnvP = kPunch+1
		else
			kstate = 1
			kEnv = 1
			kTime = 0
			kEnvP = kPunch+1
		endif
	else
		if kstate == 1 then
			kTime += 1
			kEnv = exp(-4.2*kTime/(kD*kr))
			kEnvP = 2*(kPunch - kFreq*kTime/kr)
			kEnvP limit kEnvP, 1, 2
		endif
	endif
; we use oscilikts 'cos we need a phase sync
aout oscilikts 0.5, kFreq*kEnvP, 1, aGate, kClick
	zaw aout*kON*kEnv, kOut

endop
