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.Moog        as Moog
import qualified Synthesizer.Plain.Filter.Recursive.Comb        as Comb
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 qualified Control.Monad.Exception.Synchronous as Exc
import System.Process (rawSystem, )
import System.Exit (ExitCode, )


main :: IO ExitCode
main :: IO ExitCode
main =
   let rate :: Double
rate = Double
44100
   in  ExceptionalT Int IO () -> IO ExitCode
forall (m :: * -> *).
Functor m =>
ExceptionalT Int m () -> m ExitCode
Exc.toExitCodeT (ExceptionalT Int IO () -> IO ExitCode)
-> ExceptionalT Int IO () -> IO ExitCode
forall a b. (a -> b) -> a -> b
$
       do {- File.writeMono "test" rate
                (take (round (3*rate)) (soundD rate)) -}
          IO ExitCode -> ExceptionalT Int IO ()
forall (m :: * -> *).
Functor m =>
m ExitCode -> ExceptionalT Int m ()
Exc.fromExitCodeT (IO ExitCode -> ExceptionalT Int IO ())
-> IO ExitCode -> ExceptionalT Int IO ()
forall a b. (a -> b) -> a -> b
$ FilePath -> Double -> (Double -> [Double]) -> IO ExitCode
forall a. C a => FilePath -> a -> (a -> [a]) -> IO ExitCode
File.renderMonoToInt16 FilePath
"test.aiff" Double
rate Double -> [Double]
soundE
          IO ExitCode -> ExceptionalT Int IO ()
forall (m :: * -> *).
Functor m =>
m ExitCode -> ExceptionalT Int m ()
Exc.fromExitCodeT (IO ExitCode -> ExceptionalT Int IO ())
-> IO ExitCode -> ExceptionalT Int IO ()
forall a b. (a -> b) -> a -> b
$ FilePath -> [FilePath] -> IO ExitCode
rawSystem FilePath
"play" [FilePath
"test.aiff"]


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

soundE :: Double -> [Double]
soundE = Double -> [Double]
glass

{- moved to synthesizer-filter
soundD = flangedSaw
soundC _ = guitarRaw
-}

cFreq :: Double
cFreq :: Double
cFreq = Double
521.3417849066773

soundB :: Double -> [Double]
soundB Double
sampleRate =
   let baseFreq :: Double
baseFreq = Double
cFreqDouble -> Double -> Double
forall a. Fractional a => a -> a -> a
/Double
2
       chord :: [Double]
chord = (Double -> Double -> Double -> Double)
-> [Double] -> [Double] -> [Double] -> [Double]
forall a b c d. (a -> b -> c -> d) -> [a] -> [b] -> [c] -> [d]
zipWith3 (\Double
x Double
y Double
z -> (Double
xDouble -> Double -> Double
forall a. Num a => a -> a -> a
+Double
yDouble -> Double -> Double
forall a. Num a => a -> a -> a
+Double
z)Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/Double
5)
                        (Double -> Double -> [Double]
forall a. (Random a, C a, C a) => a -> a -> [a]
choir Double
sampleRate (Double
baseFreqDouble -> Double -> Double
forall a. Num a => a -> a -> a
*Double
1Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/Double
1))
                        (Double -> Double -> [Double]
forall a. (Random a, C a, C a) => a -> a -> [a]
choir Double
sampleRate (Double
baseFreqDouble -> Double -> Double
forall a. Num a => a -> a -> a
*Double
5Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/Double
4))
                        (Double -> Double -> [Double]
forall a. (Random a, C a, C a) => a -> a -> [a]
choir Double
sampleRate (Double
baseFreqDouble -> Double -> Double
forall a. Num a => a -> a -> a
*Double
3Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/Double
2))
       filterFreqs :: [Double]
filterFreqs = (Double -> Double) -> [Double] -> [Double]
forall a b. (a -> b) -> [a] -> [b]
map (Double
3000Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/Double
sampleRateDouble -> Double -> Double
forall a. Num a => a -> a -> a
*)
                         ((Double -> Double) -> [Double] -> [Double]
forall a b. (a -> b) -> [a] -> [b]
map Double -> Double
forall a. Floating a => a -> a
sin ((Double -> Double) -> Double -> [Double]
forall a. (a -> a) -> a -> [a]
iterate (Double
forall a. Floating a => a
piDouble -> Double -> Double
forall a. Fractional a => a -> a -> a
/(Double
6Double -> Double -> Double
forall a. Num a => a -> a -> a
*Double
sampleRate)Double -> Double -> Double
forall a. Num a => a -> a -> a
+) Double
0))
   in  Int -> [Double] -> [Double] -> [Double] -> [Double]
forall a v. (C a, C a v) => Int -> T a -> T a -> T v -> T v
Butter.lowpassPole Int
8 (Double -> [Double]
forall a. a -> [a]
repeat (Double
0.3::Double)) [Double]
filterFreqs ([Double]
chord::[Double])

soundA :: Double -> [Double]
soundA Double
sampleRate =
   Double -> Double -> [Double]
forall a. (Random a, C a, C a) => a -> a -> [a]
choir Double
sampleRate Double
cFreq

sound9 :: Double -> [Double]
sound9 Double
sampleRate =
   (Double -> Double) -> [Double] -> [Double]
forall a b. (a -> b) -> [a] -> [b]
map (Double -> Double -> Double
forall a. Num a => a -> a -> a
*Double
0.1) (Double -> Double -> [[Double]]
forall a. (Random a, C a, C a) => a -> a -> [[a]]
accumulatedSaws Double
sampleRate Double
cFreq [[Double]] -> Int -> [Double]
forall a. HasCallStack => [a] -> Int -> a
!! Int
20)

sound8 :: Double -> [Double]
sound8 Double
sampleRate =
   let filterFreqs :: [Double]
filterFreqs = Double -> Double -> [Double]
forall y. C y => y -> y -> T y
exponential2 (-Double
0.5Double -> Double -> Double
forall a. Num a => a -> a -> a
*Double
sampleRate) (Double
100Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/Double
sampleRate)
   --  Cheby.lowpassBPole
   --  Cheby.highpassBPole
   --  Cheby.lowpassAPole
   --  Cheby.highpassAPole
   in  Int -> [Double] -> [Double] -> [Double] -> [Double]
forall a v. (C a, C a v) => Int -> T a -> T a -> T v -> T v
Cheby.lowpassBPole Int
8 (Double -> [Double]
forall a. a -> [a]
repeat (Double
0.3::Double)) [Double]
filterFreqs ([Double]
forall y. (C y, Random y) => T y
Noise.white::[Double])

sound7 :: Double -> [Double]
sound7 Double
sampleRate =
   let filterFreqs :: [Double]
filterFreqs = Double -> Double -> [Double]
forall y. C y => y -> y -> T y
exponential2 (-Double
0.5Double -> Double -> Double
forall a. Num a => a -> a -> a
*Double
sampleRate) (Double
100Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/Double
sampleRate)
   --  butterworthHighpass
   in  Int -> [Double] -> [Double] -> [Double] -> [Double]
forall a v. (C a, C a v) => Int -> T a -> T a -> T v -> T v
Butter.lowpassPole Int
8 (Double -> [Double]
forall a. a -> [a]
repeat (Double
0.3::Double)) [Double]
filterFreqs ([Double]
forall y. (C y, Random y) => T y
Noise.white::[Double])

-- a moog filter which randomly changes the resonance frequency
sound6 :: Double -> [Double]
sound6 Double
sampleRate =
   let order :: Int
order = Int
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 :: [Parameter Double]
control0 = Parameter Double -> [Parameter Double]
forall a. a -> [a]
repeat (Int -> Pole Double -> Parameter Double
forall a. C a => Int -> Pole a -> Parameter a
Moog.parameter Int
order (Double -> Double -> Pole Double
forall a. a -> a -> Pole a
Filter.Pole Double
10 (Double
400Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/Double
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  Int -> [Parameter Double] -> [Double] -> [Double]
forall a v. (C a, C a v) => Int -> T (Parameter a) -> T v -> T v
Moog.lowpass Int
order [Parameter Double]
control0
          ((Double -> Double) -> [Double] -> [Double]
forall a b. (a -> b) -> [a] -> [b]
map (Double
0.5Double -> Double -> Double
forall a. Num a => a -> a -> a
*) (Double -> Double -> [Double]
forall a. (C a, C a, C a a) => a -> a -> [a]
fatSawChord Double
sampleRate Double
220))

sound5 :: Double -> [Double]
sound5 Double
sampleRate =
   [Int] -> Double -> [Double] -> [Double]
forall a v. (C a, C a v) => [Int] -> a -> T v -> T v
Comb.runMulti
      ((Double -> Int) -> [Double] -> [Int]
forall a b. (a -> b) -> [a] -> [b]
map (\Double
t -> Double -> Int
forall b. Integral b => Double -> b
forall a b. (RealFrac a, Integral b) => a -> b
round (Double
tDouble -> Double -> Double
forall a. Num a => a -> a -> a
*Double
sampleRate)) [Double
0.08,Double
0.13,Double
0.21])
      (Double
0.3::Double) (Double -> Double -> [Double]
forall a. (C a, C a) => a -> a -> [a]
bell Double
sampleRate Double
441)
sound4 :: Double -> [Double]
sound4 Double
sampleRate =
   Int -> ([Double] -> [Double]) -> [Double] -> [Double]
forall v. C v => Int -> (T v -> T v) -> T v -> T v
Comb.runProc
      (Double -> Int
forall b. Integral b => Double -> b
forall a b. (RealFrac a, Integral b) => a -> b
round (Double
0.3Double -> Double -> Double
forall a. Num a => a -> a -> a
*Double
sampleRate))
      (T (Parameter Double) -> [Double] -> [Double]
forall a v. (C a, C a v) => T (Parameter a) -> T v -> T v
Filt1.lowpass
          (Parameter Double -> T (Parameter Double)
forall a. a -> [a]
repeat (Double -> Parameter Double
forall a. C a => a -> Parameter a
Filt1.parameter (Double
441Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/Double
sampleRate::Double))))
      (Double -> Double -> [Double]
forall a. (C a, C a) => a -> a -> [a]
bell Double
sampleRate Double
441)

sound3 :: Double -> [Double]
sound3 Double
sampleRate = Double -> Double -> Double -> Double -> [Double]
forall a. (C a, C a, C a a) => a -> a -> a -> a -> [a]
allpassPlain Double
sampleRate Double
0.3 Double
1 Double
441
sound2 :: Double -> [Double]
sound2 Double
sampleRate = Double -> Int -> Double -> Double -> Double -> [Double]
forall a. (C a, C a, C a a) => a -> Int -> a -> a -> a -> [a]
allpassDown  Double
sampleRate Int
10 Double
0.5 Double
1000 Double
441

sound1 :: Double -> [Double]
sound1 Double
sampleRate = (Double -> Double) -> [Double] -> [Double]
forall a b. (a -> b) -> [a] -> [b]
map (Double
0.1Double -> Double -> Double
forall a. Num a => a -> a -> a
*) (Double -> Int -> Double -> Double -> Double -> [Double]
forall a. (C a, C a, C a a) => a -> Int -> a -> a -> a -> [a]
moogDown Double
sampleRate Int
6 Double
0.4 Double
5000 Double
441)
sound0 :: Double -> [Double]
sound0 Double
sampleRate = (Double -> Double) -> [Double] -> [Double]
forall a b. (a -> b) -> [a] -> [b]
map (Double
0.3Double -> Double -> Double
forall a. Num a => a -> a -> a
*) (Double -> Int -> Double -> Double -> Double -> [Double]
forall a. (C a, C a, C a a) => a -> Int -> a -> a -> a -> [a]
moogReso Double
sampleRate Int
6 Double
0.1 Double
2000 Double
441)

soundm0 :: Double -> [Double]
soundm0 Double
sampleRate = Double -> Double -> [Double]
forall a. (C a, C a, C a a) => a -> a -> [a]
fatSawChordFilter Double
sampleRate Double
110