module Synthesizer.Plain.Effect where

import qualified Synthesizer.Plain.Noise as Noise
import qualified Synthesizer.Plain.Filter.Recursive as Filter
import qualified Synthesizer.Plain.Filter.Recursive.FirstOrder  as Filt1
-- import qualified Synthesizer.Plain.Filter.Recursive.Allpass     as Allpass
-- import qualified Synthesizer.Plain.Filter.Recursive.Universal   as UniFilter
import qualified Synthesizer.Plain.Filter.Recursive.Moog        as Moog
import qualified Synthesizer.Plain.Filter.Recursive.Comb        as Comb
-- import qualified Synthesizer.Plain.Filter.Recursive.Integration as Integrate
import qualified Synthesizer.Plain.Filter.Recursive.Butterworth as Butter
import qualified Synthesizer.Plain.Filter.Recursive.Chebyshev   as Cheby
import Synthesizer.Plain.Control(exponential2)
import Synthesizer.Plain.Instrument
import Synthesizer.Plain.Effect.Glass(glass)
import qualified Synthesizer.Plain.File as File
import Synthesizer.Filter.Example(guitarRaw, flangedSaw)
--import Interpolation(interpolate,interpolateConstant)
--import System.Random
import System.Exit(ExitCode)
import System.Cmd(rawSystem)

main :: IO ExitCode
main =
   let rate = 44100
   in  do {- File.writeMono "test" rate
                (take (round (3*rate)) (soundD rate)) -}
          File.renderMonoToInt16 "test.aiff" rate soundE
          rawSystem "play" ["test.aiff"]


soundE, soundD,
   soundC, soundB, soundA,
   sound9, sound8, sound7,
   sound6, sound5, sound4,
   sound3, sound2, sound1,
   sound0, soundm0 :: Double -> [Double]

soundE = glass

soundD = flangedSaw

soundC _ = guitarRaw

cFreq :: Double
cFreq = 521.3417849066773

soundB sampleRate =
   let baseFreq = cFreq/2
       chord = zipWith3 (\x y z -> (x+y+z)/5)
                        (choir sampleRate (baseFreq*1/1))
                        (choir sampleRate (baseFreq*5/4))
                        (choir sampleRate (baseFreq*3/2))
       filterFreqs = map (3000/sampleRate*)
                         (map sin (iterate (pi/(6*sampleRate)+) 0))
   in  Butter.lowpassPole 8 (repeat (0.3::Double)) filterFreqs (chord::[Double])

soundA sampleRate =
   choir sampleRate cFreq

sound9 sampleRate =
   map (*0.1) (accumulatedSaws sampleRate cFreq !! 20)

sound8 sampleRate =
   let filterFreqs = exponential2 (-0.5*sampleRate) (100/sampleRate)
   --  Cheby.lowpassBPole
   --  Cheby.highpassBPole
   --  Cheby.lowpassAPole
   --  Cheby.highpassAPole
   in  Cheby.lowpassBPole 8 (repeat (0.3::Double)) filterFreqs (Noise.white::[Double])

sound7 sampleRate =
   let filterFreqs = exponential2 (-0.5*sampleRate) (100/sampleRate)
   --  butterworthHighpass
   in  Butter.lowpassPole 8 (repeat (0.3::Double)) filterFreqs (Noise.white::[Double])

-- a moog filter which randomly changes the resonance frequency
sound6 sampleRate =
   let order = 10
       {- unused
       switchRates = repeat (8/sampleRate)
       filterFreqs = map (\exp -> 100*2**exp/sampleRate)
                         ((randomRs (0,6) (mkStdGen 142857))::[Double])
       filterReso  = 10
        -}

       control0 {-, control1, control2-} :: [Moog.Parameter Double]
       -- constant control
       control0 = repeat (Moog.parameter order (Filter.Pole 10 (400/sampleRate)))
       -- apply moogFilterParam first then resample, fast
       {- Need Additive and VectorSpace instances for MoogFilterParam
       control1 = interpolateConstant 0 switchRates
                     (map (moogFilterParam order)
                          (map (Pole filterReso) filterFreqs))
       -- first resample then apply moogFilterParam, slow
       control2 = map (moogFilterParam order)
                      (map (Pole filterReso)
                           (interpolateConstant 0 switchRates filterFreqs))
       -}
   in  Moog.lowpass order control0
          (map (0.5*) (fatSawChord sampleRate 220))

sound5 sampleRate =
   Comb.runMulti
      (map (\t -> round (t*sampleRate)) [0.08,0.13,0.21])
      (0.3::Double) (bell sampleRate 441)
sound4 sampleRate =
   Comb.runProc
      (round (0.3*sampleRate))
      (Filt1.lowpass
          (repeat (Filt1.parameter (441/sampleRate::Double))))
      (bell sampleRate 441)

sound3 sampleRate = allpassPlain sampleRate 0.3 1 441
sound2 sampleRate = allpassDown  sampleRate 10 0.5 1000 441

sound1 sampleRate = map (0.1*) (moogDown sampleRate 6 0.4 5000 441)
sound0 sampleRate = map (0.3*) (moogReso sampleRate 6 0.1 2000 441)

soundm0 sampleRate = fatSawChordFilter sampleRate 110