module Euterpea.IO.Audio.Basics
(outA, integral, countDown, countUp, upsample, pchToHz, apToHz)
where
import Prelude hiding (init)
import Euterpea.Music.Note.Music
import Euterpea.IO.Audio.Types
import Control.Arrow
import Control.CCA.ArrowP
import Control.CCA.Types
outA :: forall a b . (ArrowInit a) => a b b
outA = arr' [| id |] id
integral ::
forall a p . (ArrowInitP a p, Clock p) => ArrowP a p Double Double
integral
= let dt = 1 / rate (undefined :: p) in
(loop
((arr' [| (\ (x, i) -> let i' = i + x * dt in i') |]
(\ (x, i) -> let i' = i + x * dt in i')
>>> init' [| 0 |] 0)
>>> arr' [| (\ i -> (i, i)) |] (\ i -> (i, i)))
>>> outA)
countDown :: forall a . (ArrowInit a) => Int -> a () Int
countDown x
= (loop
(arr' [| (\ (_, i) -> i 1) |] (\ (_, i) -> i 1) >>>
(init' [| x |] x >>> arr' [| (\ i -> (i, i)) |] (\ i -> (i, i))))
>>> outA)
countUp :: forall a . (ArrowInit a) => a () Int
countUp
= (loop
(arr' [| (\ (_, i) -> i + 1) |] (\ (_, i) -> i + 1) >>>
(init' [| 0 |] 0 >>> arr' [| (\ i -> (i, i)) |] (\ i -> (i, i))))
>>> outA)
upsample ::
forall a p1 p2 b x .
(ArrowChoice a, ArrowInitP a p1, ArrowInitP a p2, Clock p1,
Clock p2, AudioSample b) =>
ArrowP a p1 x b -> ArrowP a p2 x b
upsample f = g
where g = (loop
(arr' [| (\ (x, ~(cc, y)) -> (cc, (x, y))) |]
(\ (x, ~(cc, y)) -> (cc, (x, y)))
>>>
(first
(arr' [| (\ cc -> if cc >= r 1 then 0 else cc + 1) |]
(\ cc -> if cc >= r 1 then 0 else cc + 1)
>>> init' [| 0 |] 0)
>>>
arr' [| (\ (cc, (x, y)) -> ((cc, x, y), cc)) |]
(\ (cc, (x, y)) -> ((cc, x, y), cc)))
>>>
(first
(arr' [| (\ (cc, x, y) -> if cc == 0 then Left x else Right y) |]
(\ (cc, x, y) -> if cc == 0 then Left x else Right y)
>>> (ArrowP (strip f) ||| init' [| zero |] zero))
>>>
arr' [| (\ (y, cc) -> (y, (cc, y))) |]
(\ (y, cc) -> (y, (cc, y)))))
>>> outA)
r = if outRate < inRate then
error "Cannot upsample a signal of higher rate to lower rate" else
outRate / inRate
inRate = rate (undefined :: p1)
outRate = rate (undefined :: p2)
apToHz :: forall a . (Floating a) => AbsPitch -> a
apToHz ap = 440 * 2 ** (fromIntegral (ap absPitch (A, 5)) / 12)
pchToHz :: forall a . (Floating a) => Pitch -> a
pchToHz = apToHz . absPitch