> {-# LANGUAGE Arrows #-} > module HSoM.Examples.AMandFM where > import Euterpea > import FRP.UISF.AuxFunctions > tab1 = tableSinesN 4096 [1] > tremolo :: Clock c => > Double -> Double -> SigFun c () Double > tremolo tfrq dep = proc () -> do > trem <- osc tab1 0 -< tfrq > outA -< 1 + dep*trem > amfmInst :: Instr (Mono AudRate) > -- Dur -> AbsPitch -> Volume -> AudSF () Double > amfmInst dur ap vol ps = > let f = apToHz ap > v = fromIntegral vol / 100 > d = fromRational dur > (tremAmt, tremFreq, vibAmt, vibFreq) = > if length ps < 4 then (0, 1, 0, 1) > else (ps !! 0, ps !! 1, ps !! 2, ps !! 3) > in proc () -> do > asr <- envLineSeg [0,1,1,0] [d*0.01, d*0.98, d*0.01] -< () > vibSig <- osc tab1 0 -< vibFreq > sineSig <- osc tab1 0 -< f + f*vibSig*vibAmt > tremEnv <- tremolo tremFreq tremAmt -< () > outA -< (1-tremAmt) * asr * tremEnv * sineSig > iMap :: InstrMap (Mono AudRate) > iMap = [(CustomInstrument "AMFM", amfmInst)] > mkAMFM :: FilePath -> [Double] -> IO () > mkAMFM str p = writeWav str iMap $ > instrument (CustomInstrument "AMFM") $ > note 2 ((C,4::Octave), [Params p]) > amfm1 = mkAMFM "amfm1.wav" [] -- neither trem nor vib > amfm2 = mkAMFM "amfm2.wav" [0.2,1.5,0.0,1.0] -- trem only > amfm3 = mkAMFM "amfm3.wav" [0.0,1.0,0.02,4.0] -- vib only > amfm4 = mkAMFM "amfm4.wav" [0.2,1.5,0.02,4.0] -- both Vibrato and tremolo into the audible frequency range: > amfm5 = mkAMFM "amfm5.wav" [0.2,50.0,0.0,1.0] -- trem only > amfm6 = mkAMFM "amfm6.wav" [0.0,1.0,0.05,100.0] -- vib only > amfm7 = mkAMFM "amfm7.wav" [0.2,50.0,0.05,100.0] -- both > writeAll = sequence [amfm1, amfm2, amfm3, amfm4, amfm5, amfm6, amfm7]