content: > {-#  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]
  
  