csound-catalog-0.3.0: src/Csound/Catalog/Drum/Tr808.hs
-- | Drums of the Korg TR-808 drum machine (recoded from Iain McCurdy).
module Csound.Catalog.Drum.Tr808(
TrSpec(..),
bass, bass2, snare, openHiHat, closedHiHat,
lowTom, midTom, highTom, cymbal, claves, rimShot,
maraca, highConga, midConga, lowConga,
-- * Generic
bass', bass2', bdSpec, bdSpec2, snare', snSpec, openHiHat', ohSpec, closedHiHat', chSpec,
lowTom', ltSpec, midTom', mtSpec, highTom', htSpec, cymbal', cymSpec, claves', clSpec, rimShot', rimSpec,
maraca', marSpec, highConga', hcSpec, midConga', mcSpec, lowConga', lcSpec,
-- * Sampler
bd, bd2, sn, ohh, chh, htom, mtom, ltom, cym, cl, rim, mar, hcon, mcon, lcon,
-- ** Generic
bd', bd2', sn', ohh', chh', htom', mtom', ltom', cym', cl', rim', mar', hcon', mcon', lcon'
) where
import Control.Monad
import Csound.Base
import Csound.Sam
-- don't forget to update the gen-opcodes and the hackage opcodes
rndAmp :: Sig -> SE Sig
rndAmp a = do
k <- birnd 0.09
return $ a * (1 + sig k)
data TrSpec = TrSpec {
trDur :: D
, trTune :: D
, trCps :: D
, trRnd :: Maybe D
}
cpsSpec cps = TrSpec
{ trDur = 0.8
, trTune = 0
, trCps = cps
, trRnd = Just 0.085 }
rndVal :: D -> D -> D -> SE D
rndVal total amount x = do
k <- birnd amount
return $ x + k * total
rndDur amt x = rndVal x amt x
rndCps amt x = rndVal x (amt / 10) x
rndTune amt x = rndVal 0.7 amt x
rndSpec ::TrSpec -> SE TrSpec
rndSpec spec = do
dur <- rndDur'
tune <- rndTune'
cps <- rndCps'
return $ spec
{ trDur = dur
, trTune = tune
, trCps = cps }
where
rndDur' = (maybe return rndDur $ (trRnd spec)) $ trDur spec
rndTune' = (maybe return rndTune $ (trRnd spec)) $ trTune spec
rndCps' = (maybe return rndCps $ (trRnd spec)) $ trCps spec
bdSpec = TrSpec
{ trDur = 0.95
, trTune = 1
, trCps = 55
, trRnd = Just 0.05 }
addDur' dt x = xtratim dt >> return x
addDur = addDur' 0.1
bass = bass' bdSpec
bass' spec = pureBass' =<< rndSpec spec
pureBass' :: TrSpec -> SE Sig
pureBass' spec = rndAmp =<< addDur amix
where
dur = trDur spec
cps = trCps spec
kmul = transegr [0.2, dur * 0.5, -15, 0.01, dur * 0.5, 0, 0] dur 0 0
kbend = transegr [0.5, 1.2, -4, 0, 1, 0, 0] dur 0 0
asig = gbuzz 0.5 (sig cps * semitone kbend) 20 1 kmul cosine
aenv = transeg [1, dur - 0.004, -6, 0]
att = linseg [0, 0.004, 1]
asig1 = asig * aenv * att
aenv1 = linseg [1, 0.07, 0]
acps = expsega [8 * cps,0.07,0.001]
aimp = oscili aenv1 acps sine
amix = asig1 * 0.7 + aimp * 0.25
bdSpec2 = TrSpec
{ trDur = 1.3
, trTune = 1
, trCps = 57
, trRnd = Just 0.05 }
bass2 = bass2' bdSpec2
bass2' spec = pureBass2' =<< rndSpec spec
pureBass2' :: TrSpec -> SE Sig
pureBass2' spec = (rndAmp <=< addDur) $ compr $ mul (expsegr [1, 0.6 * dur, 0.1, 0.4 * dur, 0.001] (0.4 * dur) 0.001) $
fosc 1 2 (0.5 * xeg 0.01 0.1 0.2 0.5) (cps * semitone (expseg [12, 0.01, 27, 0.3, 0.001]))
where
compr x = dam x 0.65 2.4 2.3 0.05 0.1
dur = trDur spec
cps = sig $ trCps spec
snSpec = cpsSpec 342
snare = snare' snSpec
snare' spec = pureSnare' =<< rndSpec spec
-- sound consists of two sine tones, an octave apart and a noise signal
pureSnare' :: TrSpec -> SE Sig
pureSnare' spec = rndAmp =<< addDur =<< (apitch + anoise)
where
dur = trDur spec
tune = trTune spec
cps = trCps spec
iNseDur = dur * 0.3
iPchDur = dur * 0.1
-- sine tones component
aenv1 = expsegr [1, iPchDur, 0.0001] iNseDur 0.0001
apitch1 = rndOsc (sig cps)
apitch2 = rndOsc (0.5 * sig cps)
apitch = mul (0.75 * aenv1) (apitch1 + apitch2)
-- noise component
aenv2 = expon 1 iNseDur 0.0005
kcf = expsegr [5000, 0.1, 3000] iNseDur 0.0001
anoise = mul aenv2 $ do
x <- noise 0.75 0
return $ blp kcf $ bhp 1000 $ bbp (10000 * octave (sig tune)) 10000 x
ohSpec = cpsSpec 296
chSpec = cpsSpec 296
openHiHat = openHiHat' ohSpec
closedHiHat = closedHiHat' chSpec
openHiHat' :: TrSpec -> SE Sig
openHiHat' spec = genHiHat (linsegr [1, (dur/2) - 0.05, 0.1, 0.05, 0] dur 0) spec
where dur = trDur spec
closedHiHat' :: TrSpec -> SE Sig
closedHiHat' spec = genHiHat (expsega [1, (dur / 2), 0.001]) spec
where dur = trDur spec
-- sound consists of 6 pulse oscillators mixed with a noise component
-- cps = 296
genHiHat :: Sig -> TrSpec -> SE Sig
genHiHat pitchedEnv spec = rndAmp =<< addDur =<< (amix1 + anoise)
where
dur = trDur spec
tune = trTune spec
cps = trCps spec
halfDur = dur * 0.5
-- pitched element
harmonics = [1.0, 0.962, 1.233, 1.175,1.419, 2.821]
amix = mul 0.5 $ fmap sum $ mapM (rndPw 0.25 . sig . (* (cps * octave tune))) harmonics
amix1 = mul pitchedEnv $ at (\asig -> bhp 5000 $ bhp 5000 $ reson asig (5000 * octave (sig tune)) 5000 `withD` 1) amix
-- noise element
kcf = expseg [20000, 0.7, 9000, halfDur-0.1, 9000]
anoise = mul pitchedEnv $ do
x <- noise 0.8 0
return $ bhp 8000 $ blp kcf x
htSpec = cpsSpec 200
mtSpec = cpsSpec 133
ltSpec = cpsSpec 90
lowTom = lowTom' ltSpec
midTom = midTom' mtSpec
highTom = highTom' htSpec
-- cps = 200
highTom' :: TrSpec -> SE Sig
highTom' = genTom 0.5 (400, 100, 1000)
-- cps = 133
midTom' :: TrSpec -> SE Sig
midTom' = genTom 0.6 (400, 100, 600)
-- cps = 90
lowTom' :: TrSpec -> SE Sig
lowTom' = genTom 0.6 (40, 100, 600)
genTom :: D -> (Sig, Sig, Sig) -> TrSpec -> SE Sig
genTom durDt (resonCf, hpCf, lpCf) spec = rndAmp =<< addDur =<< (asig + anoise)
where
dur = trDur spec
tune = trTune spec
cps = trCps spec
ifrq = cps * octave tune
halfDur = durDt * dur
-- sine tone signal
aAmpEnv = transeg [1, halfDur, -10, 0.001]
afmod = expsega [5, 0.125/ifrq, 1]
asig = mul (-aAmpEnv) $ rndOsc (sig ifrq * afmod)
-- noise signal
aEnvNse = transeg [1, halfDur, -6 , 0.001]
otune = sig $ octave tune
anoise = mul aEnvNse $ do
x <- noise 1 0.4
return $ blp (lpCf * otune) $ bhp (hpCf * otune) $ reson x (resonCf * otune) 800 `withD` 1
cymSpec = cpsSpec 296
cymbal = cymbal' cymSpec
-- sound consists of 6 pulse oscillators mixed with a noise component
-- cps = 296
cymbal' :: TrSpec -> SE Sig
cymbal' spec = rndAmp =<< addDur =<< (fmap (amix1 + ) anoise)
where
dur = trDur spec
tune = trTune spec
cps = trCps spec
fullDur = dur * 2
-- pitched element
harmonics = [1.0, 0.962, 1.233, 1.175,1.419, 2.821]
aenv = expon 1 fullDur 0.0001
amix = mul 0.5 $ sum $ fmap (pw 0.25 . sig . (* (cps * octave tune))) harmonics
amix1 = mul aenv $ blp 12000 $ blp 12000 $ bhp 10000 $ reson amix (5000 * octave (sig tune)) 5000 `withD` 1
-- noise element
aenv2 = expsega [1,0.3,0.07,fullDur-0.1,0.00001]
kcf = expseg [14000, 0.7, 7000, fullDur-0.1, 5000]
anoise = mul aenv2 $ do
x <- noise 0.8 0
return $ bhp 8000 $ blp kcf x
clSpec = cpsSpec 2500
claves = claves' clSpec
-- cps = 2500
claves' :: TrSpec -> SE Sig
claves' spec = rndAmp =<< addDur =<< asig
where
dur = trDur spec
tune = trTune spec
cps = trCps spec
ifrq = cps * octave tune
dt = 0.045 * dur
aenv = expsega [1, dt, 0.001]
afmod = expsega [3,0.00005,1]
asig = mul (- 0.4 * (aenv-0.001)) $ rndOsc (sig ifrq * afmod)
rimSpec = cpsSpec 1700
rimShot = rimShot' rimSpec
rimShot' spec = pureRimShot' =<< rndSpec spec
-- cps = 1700
pureRimShot' :: TrSpec -> SE Sig
pureRimShot' spec = rndAmp =<< addDur =<< (mul 0.8 $ aring + anoise)
where
dur = trDur spec
tune = trTune spec
cps = trCps spec
fullDur = 0.027 * dur
-- ring
aenv1 = expsega [1,fullDur,0.001]
ifrq1 = sig $ cps * octave tune
aring = mul (0.5 * (aenv1 - 0.001)) $ at (bbp ifrq1 (ifrq1 * 8)) $ rndOscBy tabTR808RimShot ifrq1
-- noise
aenv2 = expsega [1, 0.002, 0.8, 0.005, 0.5, fullDur-0.002-0.005, 0.0001]
kcf = expsegr [4000, fullDur, 20] fullDur 20
anoise = mul (aenv2 - 0.001) $ fmap (blp kcf) $ noise 1 0
tabTR808RimShot = setSize 1024 $ sines [0.971,0.269,0.041,0.054,0.011,0.013,0.08,0.0065,0.005,0.004,0.003,0.003,0.002,0.002,0.002,0.002,0.002,0.001,0.001,0.001,0.001,0.001,0.002,0.001,0.001]
cowSpec = cpsSpec 562
cowbell = cowbell' cowSpec
-- cps = 562
cowbell' :: TrSpec -> SE Sig
cowbell' spec = rndAmp =<< addDur =<< ares
where
dur = trDur spec
tune = trTune spec
cps = trCps spec
ifrq1 = sig $ cps * octave tune
ifrq2 = 1.5 * ifrq1
fullDur = 0.7 * dur
ishape = -30
ipw = 0.5
kenv1 = transeg [1,fullDur*0.3,ishape,0.2, fullDur*0.7,ishape,0.2]
kenv2 = expon 1 fullDur 0.0005
kenv = kenv1 * kenv2
amix = mul 0.65 $ rndPw 0.5 ifrq1 + rndPw 0.5 ifrq2
iLPF2 = 10000
kcf = expseg [12000,0.07,iLPF2,1,iLPF2]
alpf = at (blp kcf) amix
abpf = at (\x -> reson x ifrq2 25) amix
ares = mul (0.08 * kenv) $ at dcblock2 $ mul (0.06 * kenv1) abpf + mul 0.5 alpf + mul 0.9 amix
-- TODO clap
{-
instr 112 ;CLAP
krelease release ;SENSE RELEASE OF THIS NOTE ('1' WHEN RELEASED, OTHERWISE ZERO)
chnset 1-krelease,"Act12" ;TURN ON ACTIVE LIGHT WHEN NOTE STARTS, TURN IT OFF WHEN NOTE ENDS
iTimGap = 0.01 ;GAP BETWEEN EVENTS DURING ATTACK PORTION OF CLAP
idur1 = 0.02 ;DURING OF THE THREE INITIAL 'CLAPS'
idur2 = 2*i(gkdur12) ;DURATION OF THE FOURTH, MAIN, CLAP
idens = 8000 ;DENSITY OF THE NOISE SIGNAL USED TO FORM THE CLAPS
iamp1 = 0.5 ;AMPLITUDE OF AUDIO BEFORE BANDPASS FILTER IN OUTPUT
iamp2 = 1 ;AMPLITUDE OF AUDIO AFTER BANDPASS FILTER IN OUTPUT
if frac(p1)==0 then ;IF THIS IS THE INITIAL NOTE (p1 WILL BE AN INTEGER)
; del. dur env.shape
event_i "i", p1+0.1, 0, idur1, p4 ;CALL THIS INSTRUMENT 4 TIMES. ADD A FRACTION ONTO p1 TO BE ABLE TO DIFFERENTIATE THESE SUBSEQUENT NOTES
event_i "i", p1+0.1, iTimGap, idur1, p4
event_i "i", p1+0.1, iTimGap*2, idur1, p4
event_i "i", p1+0.1, iTimGap*3, idur2, p4
else
kenv transeg 1,p3,-25,0 ;AMPLITUDE ENVELOPE
iamp random 0.7,1 ;SLIGHT RANDOMISATION OF AMPLITUDE
anoise pinkish kenv*iamp
iBPF = 1100*octave(i(gktune12)) ;FREQUENCY OF THE BANDPASS FILTER
ibw = 2000*octave(i(gktune12)) ;BANDWIDTH OF THE BANDPASS FILTER
iHPF = 1000 ;FREQUENCY OF A HIGHPASS FILTER
iLPF = 1 ;SCALER FOR FREQUENCY OF A LOWPASS FILTER
kcf expseg 8000,0.07,1700,1,800,2,500,1,500 ;CREATE CUTOFF FREQUENCY ENVELOPE
asig butlp anoise,kcf*iLPF ;LOWPASS FILTER THE SOUND
asig buthp asig,iHPF ;HIGHPASS FILTER THE SOUND
ares reson asig,iBPF,ibw,1 ;BANDPASS FILTER THE SOUND (CREATE A NEW SIGNAL)
asig dcblock2 (asig*iamp1)+(ares*iamp2) ;MIX BANDPASS FILTERED AND NON-BANDPASS FILTERED SOUND ELEMENTS
asig = asig*p4*i(gklevel12)*1.75*gklevel ;SCALE AMPLITUDE
aL,aR pan2 asig,i(gkpan12) ;PAN MONOPHONIC SIGNAL
outs aL,aR ;SEND AUDIO TO OUTPUTS
endif
endin
-}
{-
clap :: D -> D -> D -> Sig
clap dur tune cps =
where
iTimGap = 0.01
-}
marSpec = cpsSpec 450
maraca = maraca' marSpec
maraca' :: TrSpec -> SE Sig
maraca' spec = rndAmp =<< addDur =<< anoise
where
dur = trDur spec
tune = trTune spec
cps = trCps spec
fullDur = 0.07* dur
otune = sig $ octave tune
iHPF = limit (6000 * otune) 20 (sig getSampleRate / 2)
iLPF = limit (12000 * otune) 20 (sig getSampleRate / 3)
aenv = expsega [0.4,0.014* dur,1,0.01 * dur, 0.05, 0.05 * dur, 0.001]
anoise = mul aenv $ fmap (blp iLPF . bhp iHPF) $ noise 0.75 0
hcSpec = cpsSpec 420
mcSpec = cpsSpec 310
lcSpec = cpsSpec 227
highConga = highConga' hcSpec
midConga = midConga' mcSpec
lowConga = lowConga' lcSpec
-- high conga
-- cps = 420
highConga' :: TrSpec -> SE Sig
highConga' = genConga 0.22
-- cps = 310
midConga' :: TrSpec -> SE Sig
midConga' = genConga 0.33
-- cps = 227
lowConga' :: TrSpec -> SE Sig
lowConga' = genConga 0.41
genConga :: D -> TrSpec -> SE Sig
genConga dt spec = rndAmp =<< addDur =<< asig
where
dur = trDur spec
tune = trTune spec
cps = trCps spec
ifrq = cps * octave tune
fullDur = dt * dur
aenv = transeg [0.7,1/ifrq,1,1,fullDur,-6,0.001]
afmod = expsega [3,0.25/ifrq,1]
asig = mul (-0.25 * aenv) $ rndOsc (sig ifrq * afmod)
-----------------------------------------------------
-- sampler
mkSam = limSam 1
-- | Bass drum
bd :: Sam
bd = mkSam bass
bd2 :: Sam
bd2 = mkSam bass2
-- | Snare
sn :: Sam
sn = mkSam snare
-- | Open hi-hat
ohh :: Sam
ohh = mkSam openHiHat
-- | Closed hi-hat
chh :: Sam
chh = mkSam closedHiHat
-- | High tom
htom :: Sam
htom = mkSam highTom
-- | Middle tom
mtom :: Sam
mtom = mkSam midTom
-- | Low tom
ltom :: Sam
ltom = mkSam lowTom
-- | Cymbal
cym :: Sam
cym = mkSam cymbal
-- | Claves
cl :: Sam
cl = mkSam claves
-- | Rim shot
rim :: Sam
rim = mkSam rimShot
-- | Maracas
mar :: Sam
mar = mkSam maraca
-- | High conga
hcon :: Sam
hcon = mkSam highConga
-- | Middle conga
mcon :: Sam
mcon = mkSam midConga
-- | Low conga
lcon :: Sam
lcon = mkSam lowConga
-- generic sam
mkSam' f spec = mkSam $ f spec
-- | Bass drum
bd' :: TrSpec -> Sam
bd' = mkSam' bass'
bd2' :: TrSpec -> Sam
bd2' = mkSam' bass2'
-- | Snare
sn' :: TrSpec -> Sam
sn' = mkSam' snare'
-- | Open hi-hat
ohh' :: TrSpec -> Sam
ohh' = mkSam' openHiHat'
-- | Closed hi-hat
chh' :: TrSpec -> Sam
chh' = mkSam' closedHiHat'
-- | High tom
htom' :: TrSpec -> Sam
htom' = mkSam' highTom'
-- | Middle tom
mtom' :: TrSpec -> Sam
mtom' = mkSam' midTom'
-- | Low tom
ltom' :: TrSpec -> Sam
ltom' = mkSam' lowTom'
-- | Cymbal
cym' :: TrSpec -> Sam
cym' = mkSam' cymbal'
-- | Claves
cl' :: TrSpec -> Sam
cl' = mkSam' claves'
-- | Rim shot
rim' :: TrSpec -> Sam
rim' = mkSam' rimShot'
-- | Maracas
mar' :: TrSpec -> Sam
mar' = mkSam' maraca'
-- | High conga
hcon' :: TrSpec -> Sam
hcon' = mkSam' highConga'
-- | Middle conga
mcon' :: TrSpec -> Sam
mcon' = mkSam' midConga'
-- | Low conga
lcon' :: TrSpec -> Sam
lcon' = mkSam' lowConga'