import Wave
constant :: Double -> Signal
constant x = Signal (repeat x)
silence :: Signal
silence = constant 0
sine :: Double -> Signal
sine freq = Signal (map sin [0,f..])
where f = 2 * pi * freq / sampleRate
double2Int :: Double -> Int
double2Int = fromInteger . floor
trim :: Signal -> Double -> Signal
trim (Signal xs) t = Signal (take samples xs)
where samples = double2Int (time2Samples t)
instance Num Signal where
(Signal x) + (Signal y) = Signal (zipWith (+) x y)
--(Signal x) - (Signal y) = Signal (zipWith (-) x y)
(Signal x) * (Signal y) = Signal (zipWith (*) x y)
negate (Signal x) = Signal $ map negate x
abs (Signal x) = Signal $ map abs x
signum (Signal x) = Signal $ map signum x
fromInteger a = constant (fromInteger a)
instance Fractional Signal where
(Signal x) / (Signal y) = Signal (zipWith (/) x y)
-- recip (Signal x)
fromRational a = constant (fromRational a)
integrate :: Signal -> Signal
integrate (Signal x) = Signal (integrate' x 0)
integrate' :: [Double] -> Double -> [Double]
integrate' (x:y:xs) i = trapez : (integrate' (y:xs) trapez)
where trapez = i + (x + y) / (2 * sampleRate)
integrate' _ _ = []
modulatedSine :: Double -> Signal -> Signal
modulatedSine c m = Signal $ map sin fs
where f t = 2 * pi * c * t
fs = zipWith (+) (map f [0,1/sampleRate..]) (map (c +) i)
Signal i = integrate m
rampUp :: Double -> Signal
rampUp time = Signal [0,f..1]
where f = 1 / (sampleRate * time)
append :: Signal -> Signal -> Signal
append (Signal x) (Signal y) = Signal (x ++ y)
hullCurve :: Double -> Double -> Double -> Double -> Signal
hullCurve attack decay decayLevel release =
(rampUp attack) `append` decayDown `append` releaseDown
where decayDown = 1 - (rampUp decay) * (1 - constant decayLevel)
releaseDown = (1 - (rampUp release)) * (constant decayLevel)
synthLead :: Double -> Signal
synthLead freq = base * hull
where base = modulatedSine freq (sine freq)
hull = hullCurve 0.004 0.2 0.625 2.0