{-# Language FlexibleContexts #-}
-- | Effects
module Csound.Air.Fx(
    -- * Reverbs
    reverbsc1, rever1, rever2, reverTime,
    smallRoom, smallHall, largeHall, magicCave,
    smallRoom2, smallHall2, largeHall2, magicCave2,

    room, chamber, hall, cave,

    -- ** Impulse Responce convolution reverbs
    --
    -- | Be careful with volumes. Some IRs can require scaling with really small coefficients like 0.01.
    --
    monoIR, stereoIR, stereoIR2, pmonoIR, pstereoIR, pstereoIR2,
    monoIR', stereoIR', stereoIR2',
    ZConvSpec(..), zconv, zconv',

    -- * Delays
    MaxDelayTime, DelayTime, Feedback, Balance,
    echo, fvdelay, fvdelays, funDelays, tabDelay,
    PingPongSpec(..), pingPong, pingPong', csdPingPong,

    -- ** Tape echo
    EchoGain, RandomSpreadSig,
    tapeRead, tapeWrite,
    tapeEcho,

    -- * Distortion
    distortion,

    -- * Chorus
    DepthSig, RateSig, WidthSig, ToneSig,
    chorus,
    -- solinaChorus, testSolinaChorus,

    -- * Flanger
    flange,

    -- * Phase
    phase1, harmPhase, powerPhase,

    -- * Effects with unit parameters
    -- | Implemented by Iain McCurdy's Csound code.

    DriveSig, SensitivitySig, BaseCps, Resonance, TimeSig, BitsReductionSig, FoldoverSig,
    TremWaveSig, RatioSig, FftSize,

    fxDistort, stChorus2, fxPhaser,
    fxFlanger, analogDelay, fxEcho, fxFilter,
    fxWhite, fxPink, equalizer, eq4, eq7,
    fxGain,

    fxAnalogDelay, fxDistortion, fxFollower, fxReverse, fxLoFi, fxChorus2, fxAutoPan, fxTrem, fxPitchShifter, fxFreqShifter,
    fxCompress,

    -- * Eq
    audaciousEq,

    -- * Misc
    trackerSplice, pitchShifterDelay
) where

import Prelude hiding (min, max, mod)

import Data.Boolean
import Data.Default

import Csound.Typed
import Csound.Typed.Opcode hiding (gain)
import Csound.Tab

import Csound.Air.Wave(Lfo, unipolar, oscBy, white, pink)
import Csound.Air.Filter
import Csound.Typed.Plugins hiding(pitchShifterDelay,
    fxAnalogDelay, fxDistortion, fxEnvelopeFollower, fxFlanger, fxFreqShifter, fxLoFi,
    fxPanTrem, fxPhaser, fxPitchShifter, fxReverse, fxChorus2, tapeEcho)

import qualified Csound.Typed.Plugins as P(pitchShifterDelay,
    fxAnalogDelay, fxDistortion, fxEnvelopeFollower, fxFlanger, fxFreqShifter, fxLoFi,
    fxPanTrem, fxPhaser, fxPitchShifter, fxReverse, fxChorus2, fxPingPong, tapeEcho)

-- | Mono version of the cool reverberation opcode reverbsc.
--
-- > reverbsc1 asig feedbackLevel cutOffFreq
reverbsc1 :: Sig -> Feedback -> ToneSig -> Sig
reverbsc1 :: Sig -> Sig -> Sig -> Sig
reverbsc1 Sig
x Sig
k Sig
co = Sig
0.5 Sig -> Sig -> Sig
forall a. Num a => a -> a -> a
* (Sig
a Sig -> Sig -> Sig
forall a. Num a => a -> a -> a
+ Sig
b)
    where (Sig
a, Sig
b) = (Sig, Sig) -> (Sig, Sig)
ar2 ((Sig, Sig) -> (Sig, Sig)) -> (Sig, Sig) -> (Sig, Sig)
forall a b. (a -> b) -> a -> b
$ Sig -> Sig -> Sig -> Sig -> (Sig, Sig)
reverbsc Sig
x Sig
x Sig
k Sig
co


---------------------------------------------------------------------------
-- Reverbs

-- | Reverb with given time.
reverTime :: DelayTime -> Sig -> Sig
reverTime :: Sig -> Sig -> Sig
reverTime Sig
dt Sig
a =  Sig -> Sig -> Sig -> Sig
nreverb Sig
a Sig
dt Sig
0.3

-- | Mono reverb (based on reverbsc)
--
-- > rever1 feedback asig
rever1 :: Feedback -> Sig -> (Sig, Sig)
rever1 :: Sig -> Sig -> (Sig, Sig)
rever1 Sig
fbk Sig
a = Sig -> Sig -> Sig -> Sig -> (Sig, Sig)
reverbsc Sig
a Sig
a Sig
fbk Sig
12000

-- | Mono reverb (based on reverbsc)
--
-- > rever2 feedback (asigLeft, asigRight)
rever2 :: Feedback -> Sig2 -> Sig2
rever2 :: Sig -> (Sig, Sig) -> (Sig, Sig)
rever2 Sig
fbk (Sig
a1, Sig
a2) = (Sig
a1 Sig -> Sig -> Sig
forall a. Num a => a -> a -> a
+ Sig
wa1, Sig
a2 Sig -> Sig -> Sig
forall a. Num a => a -> a -> a
+ Sig
wa2)
    where (Sig
wa1, Sig
wa2) = Sig -> Sig -> Sig -> Sig -> (Sig, Sig)
reverbsc Sig
a1 Sig
a2 Sig
fbk Sig
12000

-- | Mono reverb for small room.
smallRoom :: Sig -> (Sig, Sig)
smallRoom :: Sig -> (Sig, Sig)
smallRoom = Sig -> Sig -> (Sig, Sig)
rever1 Sig
0.6

-- | Mono reverb for small hall.
smallHall :: Sig -> (Sig, Sig)
smallHall :: Sig -> (Sig, Sig)
smallHall = Sig -> Sig -> (Sig, Sig)
rever1 Sig
0.8

-- | Mono reverb for large hall.
largeHall :: Sig -> (Sig, Sig)
largeHall :: Sig -> (Sig, Sig)
largeHall = Sig -> Sig -> (Sig, Sig)
rever1 Sig
0.9

-- | The magic cave reverb (mono).
magicCave :: Sig -> (Sig, Sig)
magicCave :: Sig -> (Sig, Sig)
magicCave = Sig -> Sig -> (Sig, Sig)
rever1 Sig
0.99

-- | Stereo reverb for small room.
smallRoom2 :: Sig2 -> Sig2
smallRoom2 :: (Sig, Sig) -> (Sig, Sig)
smallRoom2 = Sig -> (Sig, Sig) -> (Sig, Sig)
rever2 Sig
0.6

-- | Stereo reverb for small hall.
smallHall2 :: Sig2 -> Sig2
smallHall2 :: (Sig, Sig) -> (Sig, Sig)
smallHall2 = Sig -> (Sig, Sig) -> (Sig, Sig)
rever2 Sig
0.8

-- | Stereo reverb for large hall.
largeHall2 :: Sig2 -> Sig2
largeHall2 :: (Sig, Sig) -> (Sig, Sig)
largeHall2 = Sig -> (Sig, Sig) -> (Sig, Sig)
rever2 Sig
0.9

-- | The magic cave reverb (stereo).
magicCave2 :: Sig2 -> Sig2
magicCave2 :: (Sig, Sig) -> (Sig, Sig)
magicCave2 = Sig -> (Sig, Sig) -> (Sig, Sig)
rever2 Sig
0.99

---------------------------------------------------------------------------------

-- | An alias for
--
-- > let room dryWet asig = mixAt dryWet smallRoom2 asig
room :: MixAt Sig2 Sig2 a => Sig -> a -> AtOut Sig2 Sig2 a
room :: Sig -> a -> AtOut (Sig, Sig) (Sig, Sig) a
room Sig
mx a
ain = Sig
-> ((Sig, Sig) -> (Sig, Sig)) -> a -> AtOut (Sig, Sig) (Sig, Sig) a
forall a b c. MixAt a b c => Sig -> (a -> b) -> c -> AtOut a b c
mixAt Sig
mx (Sig, Sig) -> (Sig, Sig)
smallRoom2 a
ain

-- | An alias for
--
-- > let room dryWet asig = mixAt dryWet smallHall2 asig
chamber :: MixAt Sig2 Sig2 a => Sig -> a -> AtOut Sig2 Sig2 a
chamber :: Sig -> a -> AtOut (Sig, Sig) (Sig, Sig) a
chamber Sig
mx a
ain = Sig
-> ((Sig, Sig) -> (Sig, Sig)) -> a -> AtOut (Sig, Sig) (Sig, Sig) a
forall a b c. MixAt a b c => Sig -> (a -> b) -> c -> AtOut a b c
mixAt Sig
mx (Sig, Sig) -> (Sig, Sig)
smallHall2 a
ain

-- | An alias for
--
-- > let room dryWet asig = mixAt dryWet largeHall2 asig
hall :: MixAt Sig2 Sig2 a => Sig -> a -> AtOut Sig2 Sig2 a
hall :: Sig -> a -> AtOut (Sig, Sig) (Sig, Sig) a
hall Sig
mx a
ain = Sig
-> ((Sig, Sig) -> (Sig, Sig)) -> a -> AtOut (Sig, Sig) (Sig, Sig) a
forall a b c. MixAt a b c => Sig -> (a -> b) -> c -> AtOut a b c
mixAt Sig
mx (Sig, Sig) -> (Sig, Sig)
largeHall2 a
ain

-- | An alias for
--
-- > let room dryWet asig = mixAt dryWet magicCave2 asig
cave :: MixAt Sig2 Sig2 a => Sig -> a -> AtOut Sig2 Sig2 a
cave :: Sig -> a -> AtOut (Sig, Sig) (Sig, Sig) a
cave Sig
mx a
ain = Sig
-> ((Sig, Sig) -> (Sig, Sig)) -> a -> AtOut (Sig, Sig) (Sig, Sig) a
forall a b c. MixAt a b c => Sig -> (a -> b) -> c -> AtOut a b c
mixAt Sig
mx (Sig, Sig) -> (Sig, Sig)
magicCave2 a
ain

---------------------------------------------------------------------------------
-- IR reverbs

-- | Fast zero delay convolution with impulse response that is contained in mono-audio file.
--
-- > monoIR irFile ain
monoIR :: FilePath -> Sig -> Sig
monoIR :: FilePath -> Sig -> Sig
monoIR = ZConvSpec -> FilePath -> Sig -> Sig
monoIR' ZConvSpec
forall a. Default a => a
def

-- | Fast zero delay convolution with impulse response that is contained in mono-audio file.
-- We can specify aux parameters for convolution algorithm (see @zconv'@).
--
-- > monoIR' spec irFile ain
monoIR' :: ZConvSpec -> FilePath -> Sig -> Sig
monoIR' :: ZConvSpec -> FilePath -> Sig -> Sig
monoIR' ZConvSpec
spec FilePath
fileName Sig
ain = ZConvSpec -> Tab -> Sig -> Sig
zconv' ZConvSpec
spec (FilePath -> Tab
wavLeft FilePath
fileName) Sig
ain

-- | Fast zero delay convolution with impulse response that is contained in stereo-audio file.
--
-- > stereoIR irFile ain
stereoIR :: FilePath -> Sig2 -> Sig2
stereoIR :: FilePath -> (Sig, Sig) -> (Sig, Sig)
stereoIR = ZConvSpec -> FilePath -> (Sig, Sig) -> (Sig, Sig)
stereoIR' ZConvSpec
forall a. Default a => a
def

-- | Fast zero delay convolution with impulse response that is contained in stereo-audio file.
-- We can specify aux parameters for convolution algorithm (see @zconv'@).
--
-- > stereoIR' spec irFile ain
stereoIR' :: ZConvSpec -> FilePath -> Sig2 -> Sig2
stereoIR' :: ZConvSpec -> FilePath -> (Sig, Sig) -> (Sig, Sig)
stereoIR' ZConvSpec
spec FilePath
fileName (Sig
ainL, Sig
ainR) = (ZConvSpec -> Tab -> Sig -> Sig
zconv' ZConvSpec
spec (FilePath -> Tab
wavLeft FilePath
fileName) Sig
ainL, ZConvSpec -> Tab -> Sig -> Sig
zconv' ZConvSpec
spec (FilePath -> Tab
wavRight FilePath
fileName) Sig
ainR)

-- | If IR is encoded in a couple of mono files.
stereoIR2 :: (FilePath, FilePath) -> Sig2 -> Sig2
stereoIR2 :: (FilePath, FilePath) -> (Sig, Sig) -> (Sig, Sig)
stereoIR2 = ZConvSpec -> (FilePath, FilePath) -> (Sig, Sig) -> (Sig, Sig)
stereoIR2' ZConvSpec
forall a. Default a => a
def

-- | If IR is encoded in a couple of mono files.
stereoIR2' :: ZConvSpec -> (FilePath, FilePath) -> Sig2 -> Sig2
stereoIR2' :: ZConvSpec -> (FilePath, FilePath) -> (Sig, Sig) -> (Sig, Sig)
stereoIR2' ZConvSpec
spec (FilePath
file1, FilePath
file2) (Sig
ainL, Sig
ainR) = (ZConvSpec -> FilePath -> Sig -> Sig
monoIR' ZConvSpec
spec FilePath
file1 Sig
ainL, ZConvSpec -> FilePath -> Sig -> Sig
monoIR' ZConvSpec
spec FilePath
file2 Sig
ainR)

-- | Precise mono IR with pconvolve (requires a lot of CPU).
pmonoIR :: FilePath -> Sig -> Sig
pmonoIR :: FilePath -> Sig -> Sig
pmonoIR FilePath
fileName Sig
ain = Sig -> Str -> Sig
forall a. Tuple a => Sig -> Str -> a
pconvolve Sig
ain (FilePath -> Str
text FilePath
fileName)

-- | Precise stereo IR with pconvolve (requires a lot of CPU).
pstereoIR :: FilePath -> Sig2 -> Sig2
pstereoIR :: FilePath -> (Sig, Sig) -> (Sig, Sig)
pstereoIR FilePath
fileName (Sig
ainL, Sig
ainR) = Sig -> Str -> (Sig, Sig)
forall a. Tuple a => Sig -> Str -> a
pconvolve ((Sig
ainL Sig -> Sig -> Sig
forall a. Num a => a -> a -> a
+ Sig
ainR) Sig -> Sig -> Sig
forall a. Num a => a -> a -> a
* Sig
0.5) (FilePath -> Str
text FilePath
fileName)

pstereoIR2 :: (FilePath, FilePath) -> Sig2 -> Sig2
pstereoIR2 :: (FilePath, FilePath) -> (Sig, Sig) -> (Sig, Sig)
pstereoIR2 (FilePath
file1, FilePath
file2) (Sig
ainL, Sig
ainR) = (FilePath -> Sig -> Sig
pmonoIR FilePath
file1 Sig
ainL, FilePath -> Sig -> Sig
pmonoIR FilePath
file2 Sig
ainR)


---------------------------------------------------------------------------------
-- Delays

-- | The maximum delay time.
type MaxDelayTime = D

-- | The delaya time
type DelayTime = Sig

-- | Feedback for delay
type Feedback = Sig

-- | Dry/Wet mix value (ranges from 0 to 1). The 0 is all dry. The 1 is all wet.
type Balance = Sig

-- | The simplest delay with feedback. Arguments are: delay length and decay ratio.
--
-- > echo delayLength ratio
echo :: MaxDelayTime -> Feedback -> Sig -> Sig
echo :: MaxDelayTime -> Sig -> Sig -> Sig
echo MaxDelayTime
len Sig
fb Sig
x = Sig
x Sig -> Sig -> Sig
forall a. Num a => a -> a -> a
+ Sig -> Sig -> Sig -> Sig
flanger Sig
x (MaxDelayTime -> Sig
sig MaxDelayTime
len) Sig
fb Sig -> MaxDelayTime -> Sig
forall a. Tuple a => a -> MaxDelayTime -> a
`withD` (MaxDelayTime
len MaxDelayTime -> MaxDelayTime -> MaxDelayTime
forall a. Num a => a -> a -> a
+ MaxDelayTime
0.005)

-- | Delay with feedback.
--
-- > fdelay maxDelayLength delayLength feedback balance
fvdelay :: MaxDelayTime -> DelayTime -> Feedback -> Sig -> Sig
fvdelay :: MaxDelayTime -> Sig -> Sig -> Sig -> Sig
fvdelay MaxDelayTime
len Sig
dt Sig
fb Sig
a = Sig
a Sig -> Sig -> Sig
forall a. Num a => a -> a -> a
+ Sig -> Sig -> Sig -> Sig
flanger Sig
a Sig
dt Sig
fb Sig -> MaxDelayTime -> Sig
forall a. Tuple a => a -> MaxDelayTime -> a
`withD` MaxDelayTime
len

-- | Multitap delay. Arguments are: max delay length, list of pairs @(delayLength, decayRatio)@,
-- balance of mixed signal with processed signal.
--
-- > fdelay maxDelayLength  delays balance asig
fvdelays :: MaxDelayTime -> [(DelayTime, Feedback)] -> Balance -> Sig -> SE Sig
fvdelays :: MaxDelayTime -> [(Sig, Sig)] -> Sig -> Sig -> SE Sig
fvdelays MaxDelayTime
len [(Sig, Sig)]
dtArgs Sig
mx Sig
a = MaxDelayTime -> [(Sig, Sig -> Sig)] -> Sig -> Sig -> SE Sig
funDelays MaxDelayTime
len ([Sig] -> [Sig -> Sig] -> [(Sig, Sig -> Sig)]
forall a b. [a] -> [b] -> [(a, b)]
zip [Sig]
dts [Sig -> Sig]
fs) Sig
mx Sig
a
    where
        ([Sig]
dts, [Sig]
fbks) = [(Sig, Sig)] -> ([Sig], [Sig])
forall a b. [(a, b)] -> ([a], [b])
unzip [(Sig, Sig)]
dtArgs
        fs :: [Sig -> Sig]
fs = (Sig -> Sig -> Sig) -> [Sig] -> [Sig -> Sig]
forall a b. (a -> b) -> [a] -> [b]
map Sig -> Sig -> Sig
forall a. Num a => a -> a -> a
(*) [Sig]
fbks


-- | Generic multitap delay. It's just like @fvdelays@ but instead of constant feedbackLevel
-- it expects a function for processing a delayed signal on the tap.
--
-- > fdelay maxDelayLength  delays balance asig
funDelays :: MaxDelayTime -> [(DelayTime, Sig -> Sig)] -> Balance -> Sig -> SE Sig
funDelays :: MaxDelayTime -> [(Sig, Sig -> Sig)] -> Sig -> Sig -> SE Sig
funDelays MaxDelayTime
len [(Sig, Sig -> Sig)]
dtArgs Sig
mx Sig
a = do
    Sig
_ <- MaxDelayTime -> SE Sig
delayr MaxDelayTime
len
    [Sig]
aDels <- (Sig -> SE Sig) -> [Sig] -> SE [Sig]
forall (t :: * -> *) (m :: * -> *) a b.
(Traversable t, Monad m) =>
(a -> m b) -> t a -> m (t b)
mapM Sig -> SE Sig
deltap3 [Sig]
dts
    Sig -> SE ()
delayw (Sig -> SE ()) -> Sig -> SE ()
forall a b. (a -> b) -> a -> b
$ Sig
a Sig -> Sig -> Sig
forall a. Num a => a -> a -> a
+ [Sig] -> Sig
forall (t :: * -> *) a. (Foldable t, Num a) => t a -> a
sum (((Sig -> Sig) -> Sig -> Sig) -> [Sig -> Sig] -> [Sig] -> [Sig]
forall a b c. (a -> b -> c) -> [a] -> [b] -> [c]
zipWith (Sig -> Sig) -> Sig -> Sig
forall a b. (a -> b) -> a -> b
($) [Sig -> Sig]
fs [Sig]
aDels)
    Sig -> SE Sig
forall (m :: * -> *) a. Monad m => a -> m a
return (Sig -> SE Sig) -> Sig -> SE Sig
forall a b. (a -> b) -> a -> b
$ Sig
a Sig -> Sig -> Sig
forall a. Num a => a -> a -> a
+ Sig
mx Sig -> Sig -> Sig
forall a. Num a => a -> a -> a
* [Sig] -> Sig
forall (t :: * -> *) a. (Foldable t, Num a) => t a -> a
sum [Sig]
aDels
    where ([Sig]
dts, [Sig -> Sig]
fs) = [(Sig, Sig -> Sig)] -> ([Sig], [Sig -> Sig])
forall a b. [(a, b)] -> ([a], [b])
unzip [(Sig, Sig -> Sig)]
dtArgs

-- | Delay for functions that use some table (as a buffer). As granular synth or mincer.
--
-- > tabDelay fn maxDelayTime delayTime feedback balance asig
tabDelay :: (Tab -> Sig -> SE Sig) -> MaxDelayTime -> DelayTime -> Feedback -> Balance -> Sig -> SE Sig
tabDelay :: (Tab -> Sig -> SE Sig)
-> MaxDelayTime -> Sig -> Sig -> Sig -> Sig -> SE Sig
tabDelay Tab -> Sig -> SE Sig
go MaxDelayTime
maxLength Sig
delTim  Sig
kfeed Sig
kbalance Sig
asig = do
    Tab
buf <- MaxDelayTime -> SE Tab
newTab MaxDelayTime
tabLen
    Ref Sig
ptrRef <- Sig -> SE (Ref Sig)
forall a. Tuple a => a -> SE (Ref a)
newRef (Sig
0 :: Sig)
    Ref Sig
aresRef <- Sig -> SE (Ref Sig)
forall a. Tuple a => a -> SE (Ref a)
newRef (Sig
0 :: Sig)
    Sig
ptr1 <- Ref Sig -> SE Sig
forall a. Tuple a => Ref a -> SE a
readRef Ref Sig
ptrRef
    BoolSig -> SE () -> SE ()
when1 (Sig
ptr1 Sig -> Sig -> BoolSig
forall a bool. (OrdB a, bool ~ BooleanOf a) => a -> a -> bool
>=* MaxDelayTime -> Sig
sig MaxDelayTime
tabLen) (SE () -> SE ()) -> SE () -> SE ()
forall a b. (a -> b) -> a -> b
$ do
        Ref Sig -> Sig -> SE ()
forall a. Tuple a => Ref a -> a -> SE ()
writeRef Ref Sig
ptrRef Sig
0
    Sig
ptr2 <- Ref Sig -> SE Sig
forall a. Tuple a => Ref a -> SE a
readRef Ref Sig
ptrRef

    let kphs :: Sig
kphs = (Sig
ptr2 Sig -> Sig -> Sig
forall a. Fractional a => a -> a -> a
/ MaxDelayTime -> Sig
sig MaxDelayTime
tabLen) Sig -> Sig -> Sig
forall a. Num a => a -> a -> a
- (Sig
delTimSig -> Sig -> Sig
forall a. Fractional a => a -> a -> a
/(MaxDelayTime -> Sig
sig (MaxDelayTime -> Sig) -> MaxDelayTime -> Sig
forall a b. (a -> b) -> a -> b
$ MaxDelayTime
tabLen MaxDelayTime -> MaxDelayTime -> MaxDelayTime
forall a. Fractional a => a -> a -> a
/ MaxDelayTime
getSampleRate))
    Sig
awet <-Tab -> Sig -> SE Sig
go Tab
buf (Sig -> Sig -> Sig -> Sig
wrap Sig
kphs Sig
0 Sig
1)
    Ref Sig -> Sig -> SE ()
forall a. Tuple a => Ref a -> a -> SE ()
writeRef Ref Sig
aresRef (Sig -> SE ()) -> Sig -> SE ()
forall a b. (a -> b) -> a -> b
$ Sig
asig Sig -> Sig -> Sig
forall a. Num a => a -> a -> a
+ Sig
kfeed Sig -> Sig -> Sig
forall a. Num a => a -> a -> a
* Sig
awet
    Sig
ares <- Ref Sig -> SE Sig
forall a. Tuple a => Ref a -> SE a
readRef Ref Sig
aresRef
    Ref Sig -> Sig -> SE ()
forall a. Tuple a => Ref a -> a -> SE ()
writeRef Ref Sig
ptrRef (Sig -> SE ()) -> SE Sig -> SE ()
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< Tab -> Sig -> Sig -> SE Sig
tablewa Tab
buf Sig
ares Sig
0
    Sig -> SE Sig
forall (m :: * -> *) a. Monad m => a -> m a
return (Sig -> SE Sig) -> Sig -> SE Sig
forall a b. (a -> b) -> a -> b
$ (Sig
1 Sig -> Sig -> Sig
forall a. Num a => a -> a -> a
- Sig
kbalance) Sig -> Sig -> Sig
forall a. Num a => a -> a -> a
* Sig
asig Sig -> Sig -> Sig
forall a. Num a => a -> a -> a
+ Sig
kbalance Sig -> Sig -> Sig
forall a. Num a => a -> a -> a
* Sig
awet
    where
        tabLen :: MaxDelayTime
tabLen = MaxDelayTime -> MaxDelayTime
tabSizeSecondsPower2 MaxDelayTime
maxLength

-- | Aux parameters for ping pong delay.
-- They are maximum delay time, low pass filter center frequency and Pan width.
-- The defaults are @(5 sec, 3500, 0.3)@.
data PingPongSpec = PingPongSpec {
        PingPongSpec -> MaxDelayTime
pingPongMaxTime :: MaxDelayTime,
        PingPongSpec -> Sig
pingPongDamp    :: Sig,
        PingPongSpec -> Sig
pingPongWidth   :: Sig
    }

instance Default PingPongSpec where
    def :: PingPongSpec
def = PingPongSpec :: MaxDelayTime -> Sig -> Sig -> PingPongSpec
PingPongSpec {
            pingPongMaxTime :: MaxDelayTime
pingPongMaxTime = MaxDelayTime
5,
            pingPongDamp :: Sig
pingPongDamp    = Sig
3500,
            pingPongWidth :: Sig
pingPongWidth   = Sig
0.6
        }

-- | Ping-pong delay.
--
-- > pingPong delayTime feedback mixLevel
pingPong :: DelayTime -> Feedback -> Balance -> Sig2 -> Sig2
pingPong :: Sig -> Sig -> Sig -> (Sig, Sig) -> (Sig, Sig)
pingPong Sig
delTime Sig
feedback Sig
mixLevel (Sig
ainL, Sig
ainR) = PingPongSpec -> Sig -> Sig -> Sig -> (Sig, Sig) -> (Sig, Sig)
pingPong' PingPongSpec
forall a. Default a => a
def Sig
delTime Sig
feedback Sig
mixLevel (Sig
ainL, Sig
ainR)

-- | Ping-pong delay with miscellaneous arguments.
--
-- > pingPong' spec delayTime feedback mixLevel
pingPong' :: PingPongSpec -> DelayTime -> Feedback -> Balance -> Sig2 -> Sig2
pingPong' :: PingPongSpec -> Sig -> Sig -> Sig -> (Sig, Sig) -> (Sig, Sig)
pingPong' (PingPongSpec MaxDelayTime
maxTime Sig
damp Sig
width) Sig
delTime Sig
feedback Sig
mixLevel (Sig
ainL, Sig
ainR) =
    MaxDelayTime
-> Sig -> Sig -> Sig -> Sig -> Sig -> (Sig, Sig) -> (Sig, Sig)
csdPingPong MaxDelayTime
maxTime Sig
delTime Sig
damp Sig
feedback Sig
width Sig
mixLevel (Sig
ainL, Sig
ainR)

-- | Ping-pong delay defined in csound style. All arguments are present (nothing is hidden).
--
-- > csdPingPong maxTime delTime damp feedback width mixLevel (ainL, ainR)
csdPingPong :: MaxDelayTime -> DelayTime -> Sig -> Feedback -> Sig -> Balance -> Sig2 -> Sig2
csdPingPong :: MaxDelayTime
-> Sig -> Sig -> Sig -> Sig -> Sig -> (Sig, Sig) -> (Sig, Sig)
csdPingPong MaxDelayTime
maxTime Sig
delTime Sig
damp Sig
feedback Sig
width Sig
mixLevel (Sig
ainL, Sig
ainR) = MaxDelayTime
-> Sig -> Sig -> Sig -> Sig -> Sig -> (Sig, Sig) -> (Sig, Sig)
P.fxPingPong MaxDelayTime
maxTime Sig
mixLevel Sig
width Sig
damp Sig
delTime Sig
feedback (Sig
ainL, Sig
ainR)

-- fxPingPong iMaxDelTime kmix kwidth ktone ktime kfeedback (ainL, ainR) = ...

{- substituted with Csound UDO implementation
csdPingPong :: MaxDelayTime -> DelayTime -> Sig -> Feedback -> Sig -> Balance -> Sig2 -> SE Sig2
csdPingPong maxTime delTime damp feedback width mixLevel (ainL, ainR) = do
    afirst <- offsetDelay ainL
    atapL  <- channelDelay afirst
    atapR  <- channelDelay ainR
    return $ mixControl $ widthControl afirst (atapL, atapR)
    where
        offsetDelay ain = do
            abuf <- delayr maxTime
            afirst <- deltap3 delTime
            let afirst1 = tone afirst damp
            delayw ain
            return afirst1

        channelDelay ain = do
            abuf <- delayr (2 * maxTime)
            atap <- deltap3 (2 * delTime)
            let atap1 = tone atap damp
            delayw (ain + atap1 * feedback)
            return atap1

        widthControl afirst (atapL, atapR) = (afirst + atapL + (1 - width) * atapR, atapR + (1 - width) * atapL)

        mixControl (atapL ,atapR) = (cfd mixLevel ainL atapL, cfd mixLevel ainR atapR)
-}

type DepthSig = Sig
type RateSig  = Sig
type WidthSig  = Sig
type ToneSig  = Sig

-- Distortion

-- | Distortion.
--
-- > distort distLevel asig
distortion :: Sig -> Sig -> Sig
distortion :: Sig -> Sig -> Sig
distortion Sig
pre Sig
asig = Sig -> Sig -> Sig -> Sig -> Sig -> Sig
distort1 Sig
asig Sig
pre Sig
0.5 Sig
0 Sig
0 Sig -> MaxDelayTime -> Sig
forall a. Tuple a => a -> MaxDelayTime -> a
`withD` MaxDelayTime
1

-- Chorus

-- | Chorus.
--
-- > chorus depth rate balance asig
chorus :: DepthSig -> RateSig -> Balance -> Sig -> SE Sig
chorus :: Sig -> Sig -> Sig -> Sig -> SE Sig
chorus Sig
depth Sig
rate Sig
mx Sig
asig = do
    Sig
_ <- MaxDelayTime -> SE Sig
delayr MaxDelayTime
1.2
    Sig
adelSig <- Sig -> SE Sig
deltap3 (Sig
0.03 Sig -> Sig -> Sig
forall a. Num a => a -> a -> a
* Sig
depth Sig -> Sig -> Sig
forall a. Num a => a -> a -> a
* Tab -> Sig -> Sig
oscBy Tab
fn (Sig
3 Sig -> Sig -> Sig
forall a. Num a => a -> a -> a
* Sig
rate) Sig -> Sig -> Sig
forall a. Num a => a -> a -> a
+ Sig
0.01)
    Sig -> SE ()
delayw Sig
asig
    Sig -> SE Sig
forall (m :: * -> *) a. Monad m => a -> m a
return (Sig -> SE Sig) -> Sig -> SE Sig
forall a b. (a -> b) -> a -> b
$ Sig -> Sig -> Sig -> Sig
ntrpol Sig
asig Sig
adelSig Sig
mx
    where fn :: Tab
fn = [(PartialNumber, PartialNumber, PartialNumber, PartialNumber)]
-> Tab
sines4 [(PartialNumber
0.5, PartialNumber
1, PartialNumber
180, PartialNumber
1)] -- U-shape parabola

-- Flanger

-- | Flanger. Lfo depth ranges in 0 to 1.
--
-- flanger lfo feedback balance asig
flange :: Lfo -> Feedback -> Balance -> Sig -> Sig
flange :: Sig -> Sig -> Sig -> Sig -> Sig
flange Sig
alfo Sig
fbk Sig
mx Sig
asig = Sig -> Sig -> Sig -> Sig
ntrpol Sig
asig (Sig -> Sig -> Sig -> Sig
flanger Sig
asig Sig
ulfo Sig
fbk) Sig
mx
    where ulfo :: Sig
ulfo = Sig
0.0001 Sig -> Sig -> Sig
forall a. Num a => a -> a -> a
+ Sig
0.02 Sig -> Sig -> Sig
forall a. Num a => a -> a -> a
* Sig -> Sig
unipolar Sig
alfo

-- Phaser

-- | First order phaser.
phase1 :: Sig -> Lfo -> Feedback -> Balance -> Sig -> Sig
phase1 :: Sig -> Sig -> Sig -> Sig -> Sig -> Sig
phase1 Sig
ord Sig
alfo Sig
fbk Sig
mx Sig
asig = Sig -> Sig -> Sig -> Sig
ntrpol Sig
asig (Sig -> Sig -> Sig -> Sig -> Sig
phaser1 Sig
asig (Sig
20 Sig -> Sig -> Sig
forall a. Num a => a -> a -> a
+ Sig -> Sig
unipolar Sig
alfo) Sig
ord Sig
fbk) Sig
mx

-- | Second order phaser. Sweeping gaps in the timbre are placed harmonicaly
harmPhase :: Sig -> Lfo -> Sig -> Sig -> Feedback -> Balance -> Sig -> Sig
harmPhase :: Sig -> Sig -> Sig -> Sig -> Sig -> Sig -> Sig -> Sig
harmPhase Sig
ord Sig
alfo Sig
q Sig
sep Sig
fbk Sig
mx Sig
asig = Sig -> Sig -> Sig -> Sig
ntrpol Sig
asig (Sig -> Sig -> Sig -> Sig -> Sig -> Sig -> Sig -> Sig
phaser2 Sig
asig (Sig
20 Sig -> Sig -> Sig
forall a. Num a => a -> a -> a
+ Sig -> Sig
unipolar Sig
alfo) Sig
q Sig
ord Sig
1 Sig
sep Sig
fbk) Sig
mx

-- | Second order phaser. Sweeping gaps in the timbre are placed by powers of the base frequency.
powerPhase :: Sig -> Lfo -> Sig -> Sig -> Feedback -> Balance -> Sig -> Sig
powerPhase :: Sig -> Sig -> Sig -> Sig -> Sig -> Sig -> Sig -> Sig
powerPhase Sig
ord Sig
alfo Sig
q Sig
sep Sig
fbk Sig
mx Sig
asig = Sig -> Sig -> Sig -> Sig
ntrpol Sig
asig (Sig -> Sig -> Sig -> Sig -> Sig -> Sig -> Sig -> Sig
phaser2 Sig
asig (Sig
20 Sig -> Sig -> Sig
forall a. Num a => a -> a -> a
+ Sig -> Sig
unipolar Sig
alfo) Sig
q Sig
ord Sig
2 Sig
sep Sig
fbk) Sig
mx


-----------------------------------------------------------------
-- new effects

expScale :: Sig -> (Sig, Sig) -> Sig -> Sig
expScale :: Sig -> (Sig, Sig) -> Sig -> Sig
expScale Sig
steep (Sig
min, Sig
max) Sig
a = Sig -> Sig -> Sig -> Sig
scale (Sig -> Sig -> Sig
expcurve Sig
a Sig
steep) Sig
max Sig
min

logScale :: Sig -> (Sig, Sig) -> Sig -> Sig
logScale :: Sig -> (Sig, Sig) -> Sig -> Sig
logScale Sig
steep (Sig
min, Sig
max) Sig
a = Sig -> Sig -> Sig -> Sig
scale (Sig -> Sig -> Sig
logcurve Sig
a Sig
steep) Sig
max Sig
min

dryWetMix :: Sig -> (Sig, Sig)
dryWetMix :: Sig -> (Sig, Sig)
dryWetMix Sig
kmix = (Sig
kDry, Sig
kWet)
    where
        iWet :: Tab
iWet = Int -> Tab -> Tab
setSize Int
1024 (Tab -> Tab) -> Tab -> Tab
forall a b. (a -> b) -> a -> b
$ [PartialNumber] -> Tab
elins [PartialNumber
0, PartialNumber
1, PartialNumber
1]
        iDry :: Tab
iDry = Int -> Tab -> Tab
setSize Int
1024 (Tab -> Tab) -> Tab -> Tab
forall a b. (a -> b) -> a -> b
$ [PartialNumber] -> Tab
elins [PartialNumber
1, PartialNumber
1, PartialNumber
0]
        kWet :: Sig
kWet = Sig -> Sig
kr (Sig -> Sig) -> Sig -> Sig
forall a b. (a -> b) -> a -> b
$ Sig -> Tab -> Sig
forall a. SigOrD a => a -> Tab -> a
table Sig
kmix Tab
iWet Sig -> MaxDelayTime -> Sig
forall a. Tuple a => a -> MaxDelayTime -> a
`withD` MaxDelayTime
1
        kDry :: Sig
kDry = Sig -> Sig
kr (Sig -> Sig) -> Sig -> Sig
forall a b. (a -> b) -> a -> b
$ Sig -> Tab -> Sig
forall a. SigOrD a => a -> Tab -> a
table Sig
kmix Tab
iDry Sig -> MaxDelayTime -> Sig
forall a. Tuple a => a -> MaxDelayTime -> a
`withD` MaxDelayTime
1

fxWet :: (Num a, SigSpace a) => Sig -> a -> a -> a
fxWet :: Sig -> a -> a -> a
fxWet Sig
mixSig a
ain a
aout = Sig -> a -> a
forall a. SigSpace a => Sig -> a -> a
mul Sig
dry a
ain a -> a -> a
forall a. Num a => a -> a -> a
+ Sig -> a -> a
forall a. SigSpace a => Sig -> a -> a
mul Sig
wet a
aout
    where (Sig
dry, Sig
wet) = Sig -> (Sig, Sig)
dryWetMix Sig
mixSig

-- Distortion

-- | Distortion
--
-- > fxDistort level drive tone sigIn
fxDistort :: Feedback -> Sig -> ToneSig -> Sig -> Sig
fxDistort :: Sig -> Sig -> Sig -> Sig -> Sig
fxDistort Sig
klevel Sig
kdrive Sig
ktone Sig
ain = Sig
aout Sig -> Sig -> Sig
forall a. Num a => a -> a -> a
* (Sig -> Sig -> Sig -> Sig
scale Sig
klevel Sig
0.8 Sig
0) Sig -> Sig -> Sig
forall a. Num a => a -> a -> a
* Sig
kGainComp1
    where
        aout :: Sig
aout = Sig -> Sig -> Sig
blp Sig
kLPF (Sig -> Sig) -> Sig -> Sig
forall a b. (a -> b) -> a -> b
$ Sig -> Sig -> Sig -> Sig -> Sig -> Sig
distort1 Sig
ain Sig
kpregain Sig
kpostgain Sig
0 Sig
0

        drive :: Sig
drive = Sig -> (Sig, Sig) -> Sig -> Sig
expScale Sig
8 (Sig
0.01, Sig
0.4) Sig
kdrive
        kGainComp1 :: Sig
kGainComp1 = Sig -> (Sig, Sig) -> Sig -> Sig
logScale Sig
700 (Sig
5,Sig
1) Sig
ktone

        kpregain :: Sig
kpregain = Sig
100 Sig -> Sig -> Sig
forall a. Num a => a -> a -> a
* Sig
drive
        kpostgain :: Sig
kpostgain = Sig
0.5 Sig -> Sig -> Sig
forall a. Num a => a -> a -> a
* ((Sig
1 Sig -> Sig -> Sig
forall a. Num a => a -> a -> a
- Sig
drive) Sig -> Sig -> Sig
forall a. Num a => a -> a -> a
* Sig
0.4 Sig -> Sig -> Sig
forall a. Num a => a -> a -> a
+ Sig
0.6)

        kLPF :: Sig
kLPF = Sig -> (Sig, Sig) -> Sig -> Sig
logScale Sig
700 (Sig
200, Sig
12000) Sig
ktone

-- Stereo chorus

-- | Stereo chorus.
--
-- > stChorus2 mix rate depth width sigIn
stChorus2 :: Balance -> RateSig -> DepthSig -> WidthSig -> Sig2 -> Sig2
stChorus2 :: Sig -> Sig -> Sig -> Sig -> (Sig, Sig) -> (Sig, Sig)
stChorus2 Sig
kmix Sig
krate' Sig
kdepth Sig
kwidth (Sig
aleft, Sig
aright) = Sig -> (Sig, Sig) -> (Sig, Sig) -> (Sig, Sig)
forall a. (Num a, SigSpace a) => Sig -> a -> a -> a
fxWet Sig
kmix (Sig
aleft, Sig
aright) (Sig
aoutL, Sig
aoutR)
    where
        krate :: Sig
krate = Sig -> (Sig, Sig) -> Sig -> Sig
expScale Sig
20 (Sig
0.001, Sig
7) Sig
krate'
        ilfoshape :: Tab
ilfoshape = Int -> Tab -> Tab
setSize Int
131072 (Tab -> Tab) -> Tab -> Tab
forall a b. (a -> b) -> a -> b
$ [(PartialNumber, PartialNumber, PartialNumber, PartialNumber)]
-> Tab
sines4 [(PartialNumber
1, PartialNumber
0.5, PartialNumber
0, PartialNumber
0.5)]
        kporttime :: Sig
kporttime = [MaxDelayTime] -> Sig
linseg  [MaxDelayTime
0, MaxDelayTime
0.001, MaxDelayTime
0.02]
        kChoDepth :: Sig
kChoDepth = Sig -> Sig
interp (Sig -> Sig) -> Sig -> Sig
forall a b. (a -> b) -> a -> b
$ Sig -> Sig -> Sig
portk  (Sig
kdepthSig -> Sig -> Sig
forall a. Num a => a -> a -> a
*Sig
0.01) Sig
kporttime
        amodL :: Sig
amodL = Sig -> Tab -> Sig -> Sig
osciliktp   Sig
krate Tab
ilfoshape Sig
0
        amodR :: Sig
amodR = Sig -> Tab -> Sig -> Sig
osciliktp   Sig
krate Tab
ilfoshape (Sig
kwidthSig -> Sig -> Sig
forall a. Num a => a -> a -> a
*Sig
0.5)
        vdel :: Sig -> Sig -> Sig
vdel Sig
mod Sig
x = Sig -> Sig -> MaxDelayTime -> Sig
vdelay Sig
x (Sig
mod Sig -> Sig -> Sig
forall a. Num a => a -> a -> a
* Sig
kChoDepth Sig -> Sig -> Sig
forall a. Num a => a -> a -> a
* Sig
1000) (MaxDelayTime
1.2 MaxDelayTime -> MaxDelayTime -> MaxDelayTime
forall a. Num a => a -> a -> a
* MaxDelayTime
1000)
        aChoL :: Sig
aChoL = Sig -> Sig -> Sig
vdel Sig
amodL Sig
aleft
        aChoR :: Sig
aChoR = Sig -> Sig -> Sig
vdel Sig
amodR Sig
aright
        aoutL :: Sig
aoutL = Sig
0.6 Sig -> Sig -> Sig
forall a. Num a => a -> a -> a
* (Sig
aChoL Sig -> Sig -> Sig
forall a. Num a => a -> a -> a
+ Sig
aleft)
        aoutR :: Sig
aoutR = Sig
0.6 Sig -> Sig -> Sig
forall a. Num a => a -> a -> a
* (Sig
aChoR Sig -> Sig -> Sig
forall a. Num a => a -> a -> a
+ Sig
aright)

-- Analog delay

-- | Analog delay.
--
-- > analogDelay mix feedback time tone sigIn
analogDelay :: Balance -> Feedback -> DelayTime -> ToneSig -> Sig -> Sig
analogDelay :: Sig -> Sig -> Sig -> Sig -> Sig -> Sig
analogDelay Sig
kmix Sig
kfback Sig
ktime  Sig
ktone Sig
ain = Sig -> Sig -> Sig -> Sig -> Sig -> Sig
P.fxAnalogDelay Sig
kmix Sig
kfback Sig
ktime  Sig
ktone Sig
ain

-- Filter

-- | Filter effect (a pair of butterworth low and high pass filters).
--
-- > fxFilter lowPassfFreq highPassFreq gain
fxFilter :: Sig -> Sig -> Sig -> Sig -> Sig
fxFilter :: Sig -> Sig -> Sig -> Sig -> Sig
fxFilter Sig
kLPF' Sig
kHPF' Sig
kgain' Sig
ain = Sig -> Sig -> Sig
forall a. SigSpace a => Sig -> a -> a
mul Sig
kgain (Sig -> Sig) -> Sig -> Sig
forall a b. (a -> b) -> a -> b
$ (Sig -> Sig) -> Sig -> Sig
forall b. (b -> b) -> b -> b
app (Sig -> Sig -> Sig
blp Sig
kLPF) (Sig -> Sig) -> Sig -> Sig
forall a b. (a -> b) -> a -> b
$ (Sig -> Sig) -> Sig -> Sig
forall b. (b -> b) -> b -> b
app (Sig -> Sig -> Sig
bhp Sig
kHPF) (Sig -> Sig) -> Sig -> Sig
forall a b. (a -> b) -> a -> b
$ Sig
ain
    where
        app :: (b -> b) -> b -> b
app b -> b
f = b -> b
f (b -> b) -> (b -> b) -> b -> b
forall b c a. (b -> c) -> (a -> b) -> a -> c
. b -> b
f
        kLPF :: Sig
kLPF = Sig -> Sig
scaleFreq Sig
kLPF'
        kHPF :: Sig
kHPF = Sig -> Sig
scaleFreq Sig
kHPF'
        kgain :: Sig
kgain = Sig -> Sig -> Sig -> Sig
scale Sig
kgain' Sig
20 Sig
0
        scaleFreq :: Sig -> Sig
scaleFreq Sig
x = Sig -> (Sig, Sig) -> Sig -> Sig
expScale Sig
4 (Sig
20, Sig
20000) Sig
x

-- Equalizer

-- | Equalizer
--
-- > equalizer gainsAndFrequencies gain sigIn
equalizer :: [(Sig, Sig)] -> Sig -> Sig -> Sig
equalizer :: [(Sig, Sig)] -> Sig -> Sig -> Sig
equalizer [(Sig, Sig)]
fs Sig
gainSig Sig
ain0 = case [(Sig, Sig)]
fs of
    []   -> Sig
ain
    (Sig, Sig)
x:[] -> MaxDelayTime -> (Sig, Sig) -> Sig -> Sig
g MaxDelayTime
0 (Sig, Sig)
x Sig
ain
    (Sig, Sig)
x:(Sig, Sig)
y:[] -> [Sig] -> Sig
forall a. Fractional a => [a] -> a
mean [MaxDelayTime -> (Sig, Sig) -> Sig -> Sig
g MaxDelayTime
1 (Sig, Sig)
x Sig
ain, MaxDelayTime -> (Sig, Sig) -> Sig -> Sig
g MaxDelayTime
2 (Sig, Sig)
y Sig
ain]
    (Sig, Sig)
x:[(Sig, Sig)]
xs -> [Sig] -> Sig
forall a. Fractional a => [a] -> a
mean ([Sig] -> Sig) -> [Sig] -> Sig
forall a b. (a -> b) -> a -> b
$ (MaxDelayTime -> (Sig, Sig) -> Sig -> Sig
g MaxDelayTime
1 (Sig, Sig)
x Sig
ain Sig -> [Sig] -> [Sig]
forall a. a -> [a] -> [a]
: ) ([Sig] -> [Sig]) -> [Sig] -> [Sig]
forall a b. (a -> b) -> a -> b
$ (((Sig, Sig) -> Sig) -> [(Sig, Sig)] -> [Sig]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (\(Sig, Sig)
y -> MaxDelayTime -> (Sig, Sig) -> Sig -> Sig
g MaxDelayTime
0 (Sig, Sig)
y Sig
ain) ([(Sig, Sig)] -> [(Sig, Sig)]
forall a. [a] -> [a]
init [(Sig, Sig)]
xs)) [Sig] -> [Sig] -> [Sig]
forall a. [a] -> [a] -> [a]
++ [MaxDelayTime -> (Sig, Sig) -> Sig -> Sig
g MaxDelayTime
2 ([(Sig, Sig)] -> (Sig, Sig)
forall a. [a] -> a
last [(Sig, Sig)]
xs) Sig
ain]
    where
        iQ :: Sig
iQ = Sig
1
        iEQcurve :: Tab
iEQcurve = Tab -> Tab
skipNorm (Tab -> Tab) -> Tab -> Tab
forall a b. (a -> b) -> a -> b
$ Int -> Tab -> Tab
setSize Int
4096 (Tab -> Tab) -> Tab -> Tab
forall a b. (a -> b) -> a -> b
$ [PartialNumber] -> Tab
startEnds [PartialNumber
1PartialNumber -> PartialNumber -> PartialNumber
forall a. Fractional a => a -> a -> a
/PartialNumber
64,PartialNumber
4096,PartialNumber
7.9,PartialNumber
64]
        iGainCurve :: Tab
iGainCurve = Tab -> Tab
skipNorm (Tab -> Tab) -> Tab -> Tab
forall a b. (a -> b) -> a -> b
$ Int -> Tab -> Tab
setSize Int
4096 (Tab -> Tab) -> Tab -> Tab
forall a b. (a -> b) -> a -> b
$ [PartialNumber] -> Tab
startEnds [PartialNumber
0.5,PartialNumber
4096,PartialNumber
3,PartialNumber
4]
        g :: MaxDelayTime -> (Sig, Sig) -> Sig -> Sig
g MaxDelayTime
ty (Sig
gain, Sig
freq) Sig
asig = Sig -> Sig -> Sig -> Sig -> Sig
pareq  Sig
asig Sig
freq (Sig -> Tab -> Sig
forall a. SigOrD a => a -> Tab -> a
table Sig
gain Tab
iEQcurve Sig -> MaxDelayTime -> Sig
forall a. Tuple a => a -> MaxDelayTime -> a
`withD` MaxDelayTime
1) Sig
iQ Sig -> MaxDelayTime -> Sig
forall a. Tuple a => a -> MaxDelayTime -> a
`withD` MaxDelayTime
ty
        kgain :: Sig
kgain = Sig -> Tab -> Sig
forall a. SigOrD a => a -> Tab -> a
table Sig
gainSig Tab
iGainCurve Sig -> MaxDelayTime -> Sig
forall a. Tuple a => a -> MaxDelayTime -> a
`withD` MaxDelayTime
1
        ain :: Sig
ain = Sig
kgain Sig -> Sig -> Sig
forall a. Num a => a -> a -> a
* Sig
ain0

-- | Equalizer with frequencies: 100, 200, 400, 800, 1600, 3200, 6400
eq7 :: [Sig] -> Sig -> Sig -> Sig
eq7 :: [Sig] -> Sig -> Sig -> Sig
eq7 [Sig]
gs = [(Sig, Sig)] -> Sig -> Sig -> Sig
equalizer ([Sig] -> [Sig] -> [(Sig, Sig)]
forall a b. [a] -> [b] -> [(a, b)]
zip [Sig]
gs ([Sig] -> [(Sig, Sig)]) -> [Sig] -> [(Sig, Sig)]
forall a b. (a -> b) -> a -> b
$ (Sig -> Sig) -> [Sig] -> [Sig]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (Sig
100 Sig -> Sig -> Sig
forall a. Num a => a -> a -> a
* ) [Sig
1, Sig
2, Sig
4, Sig
8, Sig
16, Sig
32, Sig
64])

-- | Equalizer with frequencies: 100, 400, 1600, 6400
eq4 :: [Sig] -> Sig -> Sig -> Sig
eq4 :: [Sig] -> Sig -> Sig -> Sig
eq4 [Sig]
gs = [(Sig, Sig)] -> Sig -> Sig -> Sig
equalizer ([Sig] -> [Sig] -> [(Sig, Sig)]
forall a b. [a] -> [b] -> [(a, b)]
zip [Sig]
gs ([Sig] -> [(Sig, Sig)]) -> [Sig] -> [(Sig, Sig)]
forall a b. (a -> b) -> a -> b
$ (Sig -> Sig) -> [Sig] -> [Sig]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (Sig
100 Sig -> Sig -> Sig
forall a. Num a => a -> a -> a
* ) [Sig
1, Sig
4, Sig
16, Sig
64])

-- | Gain
--
-- > fxGain gain sigIn
fxGain :: SigSpace a => Sig -> a -> a
fxGain :: Sig -> a -> a
fxGain = Sig -> a -> a
forall a. SigSpace a => Sig -> a -> a
mul

-- Noise

-- | Adds filtered white noize to the signal
--
-- > fxWhite lfoFreq depth sigIn
fxWhite :: Sig -> Sig -> Sig -> SE Sig
fxWhite :: Sig -> Sig -> Sig -> SE Sig
fxWhite Sig
freq Sig
depth Sig
ain = do
    Sig
noiseSig <- SE Sig
white
    Sig -> SE Sig
forall (m :: * -> *) a. Monad m => a -> m a
return (Sig -> SE Sig) -> Sig -> SE Sig
forall a b. (a -> b) -> a -> b
$ Sig
ain Sig -> Sig -> Sig
forall a. Num a => a -> a -> a
+ Sig
0.5 Sig -> Sig -> Sig
forall a. Num a => a -> a -> a
* Sig
depth Sig -> Sig -> Sig
forall a. Num a => a -> a -> a
* Sig -> Sig -> Sig
blp Sig
cps Sig
noiseSig
    where cps :: Sig
cps = Sig -> (Sig, Sig) -> Sig -> Sig
expScale Sig
4 (Sig
20, Sig
20000) Sig
freq

-- | Adds filtered pink noize to the signal
--
-- > fxWhite lfoFreq depth sigIn
fxPink :: Sig -> Sig -> Sig -> SE Sig
fxPink :: Sig -> Sig -> Sig -> SE Sig
fxPink Sig
freq Sig
depth Sig
ain = do
    Sig
noiseSig <- SE Sig
pink
    Sig -> SE Sig
forall (m :: * -> *) a. Monad m => a -> m a
return (Sig -> SE Sig) -> Sig -> SE Sig
forall a b. (a -> b) -> a -> b
$ Sig
ain Sig -> Sig -> Sig
forall a. Num a => a -> a -> a
+ Sig
0.5 Sig -> Sig -> Sig
forall a. Num a => a -> a -> a
* Sig
depth Sig -> Sig -> Sig
forall a. Num a => a -> a -> a
* Sig -> Sig -> Sig
blp Sig
cps Sig
noiseSig
    where cps :: Sig
cps = Sig -> (Sig, Sig) -> Sig -> Sig
expScale Sig
4 (Sig
20, Sig
20000) Sig
freq

-- Echo

-- | Simplified delay
--
-- > fxEcho maxDelayLength delTime feedback sigIn
fxEcho :: D -> Sig -> Sig -> Sig -> Sig
fxEcho :: MaxDelayTime -> Sig -> Sig -> Sig -> Sig
fxEcho MaxDelayTime
maxLen Sig
ktime Sig
fback = MaxDelayTime -> Sig -> Sig -> Sig -> Sig
fvdelay (MaxDelayTime
5 MaxDelayTime -> MaxDelayTime -> MaxDelayTime
forall a. Num a => a -> a -> a
* MaxDelayTime
maxLen) (MaxDelayTime -> Sig
sig MaxDelayTime
maxLen Sig -> Sig -> Sig
forall a. Num a => a -> a -> a
* Sig
0.95 Sig -> Sig -> Sig
forall a. Num a => a -> a -> a
* Sig
kTime) Sig
fback
    where
        kporttime :: Sig
kporttime = [MaxDelayTime] -> Sig
linseg [MaxDelayTime
0,MaxDelayTime
0.001,MaxDelayTime
0.1]
        kTime :: Sig
kTime = Sig -> Sig -> Sig
portk   Sig
ktime  (Sig
kporttimeSig -> Sig -> Sig
forall a. Num a => a -> a -> a
*Sig
3)

-- | Instrument plays an input signal in different modes.
-- The segments of signal can be played back and forth.
--
-- > trackerSplice maxLength segLength mode
--
-- * @maxLength@ -- the maximum length of the played segment (in seconds)
--
-- * @segLength@ -- the segment length in seconds
--
-- * @mode@ -- mode of the playing. If it's 1 - only a part of the sample is plyaed and
--   it's played forward. The portion of the signal starts from the current playback point.
--   It lasts for segLength. If it's 2 - the segment is played in reverse.
--   Other values produce the normal input signal.
--
-- Original author: Rory Walsh
--
-- Example:
--
-- > main = dac $ do
-- >    let ev ch1 ch2 dt = fmap (\x -> (x, dt)) $ mconcat [
-- >          fmap (const 1.5) $ charOn ch1
-- >        , fmap (const 2.5) $ charOn ch2
-- >        , fmap (const 0) $ charOff ch1 <> charOff ch2]
-- >
-- >    (k, dt) <- stepper (0, 0.1) $ ev 'q' 'w' 0.1 <> ev 'a' 's' 0.2 <> ev 'z' 'x' 0.4
-- >    mul 1.3 $ trackerSplice 0.8 dt (int' k) $ fst $ loopWav 1 "drumLoop.wav"
trackerSplice :: D -> Sig -> Sig -> Sig -> SE Sig
trackerSplice :: MaxDelayTime -> Sig -> Sig -> Sig -> SE Sig
trackerSplice MaxDelayTime
maxLength Sig
segLengthSeconds Sig
kmode Sig
asig = do
    MaxDelayTime -> SE ()
setksmps MaxDelayTime
1
    Ref Sig
kindxRef <- Sig -> SE (Ref Sig)
forall a. Tuple a => a -> SE (Ref a)
newRef (Sig
0 :: Sig)
    Ref MaxDelayTime
ksampRef <- MaxDelayTime -> SE (Ref MaxDelayTime)
forall a. Tuple a => a -> SE (Ref a)
newRef (MaxDelayTime
1 :: D)
    Ref Sig
aoutRef  <- Sig -> SE (Ref Sig)
forall a. Tuple a => a -> SE (Ref a)
newRef (Sig
0 :: Sig)

    Tab
buf <- MaxDelayTime -> SE Tab
newTab (MaxDelayTime -> MaxDelayTime
tabSizeSecondsPower2 MaxDelayTime
maxLength)
    let segLength :: Sig
segLength = Sig
segLengthSeconds Sig -> Sig -> Sig
forall a. Num a => a -> a -> a
* MaxDelayTime -> Sig
sig MaxDelayTime
getSampleRate
        andx :: Sig
andx = Sig -> Sig
phasor (MaxDelayTime -> Sig
sig (MaxDelayTime -> Sig) -> MaxDelayTime -> Sig
forall a b. (a -> b) -> a -> b
$ MaxDelayTime
getSampleRate MaxDelayTime -> MaxDelayTime -> MaxDelayTime
forall a. Fractional a => a -> a -> a
/ Tab -> MaxDelayTime
ftlen Tab
buf)
        andx1 :: Sig
andx1 = Sig -> MaxDelayTime -> Sig
delay Sig
andx MaxDelayTime
1
    Sig -> Sig -> Tab -> SE ()
tabw Sig
asig (Sig
andx Sig -> Sig -> Sig
forall a. Num a => a -> a -> a
* MaxDelayTime -> Sig
sig (Tab -> MaxDelayTime
ftlen Tab
buf)) Tab
buf
    MaxDelayTime
ksamp <- Ref MaxDelayTime -> SE MaxDelayTime
forall a. Tuple a => Ref a -> SE a
readRef Ref MaxDelayTime
ksampRef
    let apos :: Sig
apos = Sig -> Sig -> Sig
samphold (Sig
andx1 Sig -> Sig -> Sig
forall a. Num a => a -> a -> a
* MaxDelayTime -> Sig
sig (Tab -> MaxDelayTime
ftlen Tab
buf)) (MaxDelayTime -> Sig
sig MaxDelayTime
ksamp)

    [(BoolSig, SE ())] -> SE () -> SE ()
whens [
        (Sig
kmode Sig -> Sig -> BoolSig
forall a bool. (OrdB a, bool ~ BooleanOf a) => a -> a -> bool
>=* Sig
1 BoolSig -> BoolSig -> BoolSig
forall b. Boolean b => b -> b -> b
&&* Sig
kmode Sig -> Sig -> BooleanOf Sig
forall a. OrdB a => a -> a -> BooleanOf a
`lessThan` Sig
2, do
                Sig
kindx1 <- Ref Sig -> SE Sig
forall a. Tuple a => Ref a -> SE a
readRef Ref Sig
kindxRef
                Ref Sig -> Sig -> SE ()
forall a. Tuple a => Ref a -> a -> SE ()
writeRef Ref Sig
kindxRef (Sig -> SE ()) -> Sig -> SE ()
forall a b. (a -> b) -> a -> b
$ BoolSig -> Sig -> Sig -> Sig
forall a bool. (IfB a, bool ~ BooleanOf a) => bool -> a -> a -> a
ifB (Sig
kindx1 Sig -> Sig -> BoolSig
forall a bool. (OrdB a, bool ~ BooleanOf a) => a -> a -> bool
>* Sig
segLength) Sig
0 (Sig
kindx1 Sig -> Sig -> Sig
forall a. Num a => a -> a -> a
+ Sig
1)
                Sig
kindx2 <- Ref Sig -> SE Sig
forall a. Tuple a => Ref a -> SE a
readRef Ref Sig
kindxRef
                BoolSig -> SE () -> SE ()
when1 (Sig
kindx2 Sig -> Sig -> Sig
forall a. Num a => a -> a -> a
+ Sig
apos Sig -> Sig -> BoolSig
forall a bool. (OrdB a, bool ~ BooleanOf a) => a -> a -> bool
>* MaxDelayTime -> Sig
sig (Tab -> MaxDelayTime
ftlen Tab
buf)) (SE () -> SE ()) -> SE () -> SE ()
forall a b. (a -> b) -> a -> b
$ do
                    Ref Sig -> Sig -> SE ()
forall a. Tuple a => Ref a -> a -> SE ()
writeRef Ref Sig
kindxRef (Sig -> SE ()) -> Sig -> SE ()
forall a b. (a -> b) -> a -> b
$ (-Sig
segLength)

                Sig
kindx3 <- Ref Sig -> SE Sig
forall a. Tuple a => Ref a -> SE a
readRef Ref Sig
kindxRef

                Ref Sig -> Sig -> SE ()
forall a. Tuple a => Ref a -> a -> SE ()
writeRef Ref Sig
aoutRef (Sig -> SE ()) -> Sig -> SE ()
forall a b. (a -> b) -> a -> b
$ Sig -> Tab -> Sig
forall a. SigOrD a => a -> Tab -> a
table (Sig
apos Sig -> Sig -> Sig
forall a. Num a => a -> a -> a
+ Sig
kindx3) Tab
buf Sig -> [MaxDelayTime] -> Sig
forall a. Tuple a => a -> [MaxDelayTime] -> a
`withDs` [MaxDelayTime
0, MaxDelayTime
1]
                Ref MaxDelayTime -> MaxDelayTime -> SE ()
forall a. Tuple a => Ref a -> a -> SE ()
writeRef Ref MaxDelayTime
ksampRef MaxDelayTime
0
        ), (Sig
kmode Sig -> Sig -> BoolSig
forall a bool. (OrdB a, bool ~ BooleanOf a) => a -> a -> bool
>=* Sig
2 BoolSig -> BoolSig -> BoolSig
forall b. Boolean b => b -> b -> b
&&* Sig
kmode Sig -> Sig -> BooleanOf Sig
forall a. OrdB a => a -> a -> BooleanOf a
`lessThan` Sig
3, do
                Sig
kindx1 <- Ref Sig -> SE Sig
forall a. Tuple a => Ref a -> SE a
readRef Ref Sig
kindxRef
                Ref Sig -> Sig -> SE ()
forall a. Tuple a => Ref a -> a -> SE ()
writeRef Ref Sig
kindxRef (Sig -> SE ()) -> Sig -> SE ()
forall a b. (a -> b) -> a -> b
$ BoolSig -> Sig -> Sig -> Sig
forall a bool. (IfB a, bool ~ BooleanOf a) => bool -> a -> a -> a
ifB ((Sig
kindx1Sig -> Sig -> Sig
forall a. Num a => a -> a -> a
+Sig
apos) Sig -> Sig -> BoolSig
forall a bool. (OrdB a, bool ~ BooleanOf a) => a -> a -> bool
<=* Sig
0) (MaxDelayTime -> Sig
sig (Tab -> MaxDelayTime
ftlen Tab
buf) Sig -> Sig -> Sig
forall a. Num a => a -> a -> a
- Sig
apos) (Sig
kindx1Sig -> Sig -> Sig
forall a. Num a => a -> a -> a
-Sig
1)
                Sig
kindx2 <- Ref Sig -> SE Sig
forall a. Tuple a => Ref a -> SE a
readRef Ref Sig
kindxRef
                Ref Sig -> Sig -> SE ()
forall a. Tuple a => Ref a -> a -> SE ()
writeRef Ref Sig
aoutRef (Sig -> SE ()) -> Sig -> SE ()
forall a b. (a -> b) -> a -> b
$ Sig -> Tab -> Sig
forall a. SigOrD a => a -> Tab -> a
table (Sig
aposSig -> Sig -> Sig
forall a. Num a => a -> a -> a
+Sig
kindx2) Tab
buf Sig -> [MaxDelayTime] -> Sig
forall a. Tuple a => a -> [MaxDelayTime] -> a
`withDs` [MaxDelayTime
0, MaxDelayTime
1]
                Ref MaxDelayTime -> MaxDelayTime -> SE ()
forall a. Tuple a => Ref a -> a -> SE ()
writeRef Ref MaxDelayTime
ksampRef MaxDelayTime
0
        )] (do
                Ref MaxDelayTime -> MaxDelayTime -> SE ()
forall a. Tuple a => Ref a -> a -> SE ()
writeRef Ref MaxDelayTime
ksampRef MaxDelayTime
1
                Ref Sig -> Sig -> SE ()
forall a. Tuple a => Ref a -> a -> SE ()
writeRef Ref Sig
aoutRef Sig
asig)

    Sig
aout <-Ref Sig -> SE Sig
forall a. Tuple a => Ref a -> SE a
readRef Ref Sig
aoutRef
    Sig -> SE Sig
forall (m :: * -> *) a. Monad m => a -> m a
return Sig
aout



-- | Mean value.
mean :: Fractional a => [a] -> a
mean :: [a] -> a
mean [a]
xs = [a] -> a
forall (t :: * -> *) a. (Foldable t, Num a) => t a -> a
sum [a]
xs a -> a -> a
forall a. Fractional a => a -> a -> a
/ (Int -> a
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Int -> a) -> Int -> a
forall a b. (a -> b) -> a -> b
$ [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [a]
xs)

---------------------------------------------------
-- rename the arguments and comment

-- | PitchShifterDelay
--
-- A pitch shifter effect that employs delay lines
--
-- > pitchShifterDelay maxDelayTime delayTime (feedback1, feedback2) transposeRatio ain
--
-- Arguments
--
-- * @maxDelayTime @ --  maximum delay time (kdlt should not exceed this value)
--
-- * @transposeRatio @ --  pitch transposition (in semitones)
--
-- * @delayTime      @ --  delay time employed by the pitch shifter effect (should be within the range ksmps/sr and imaxdlt)
--
-- * @feedback1      @ --  feedback using method 1 (output from delay taps are fed back directly into their own buffers before enveloping and mixing)
--
-- * @feedback2      @ --  feedback using method 2 (enveloped and mixed output from both taps is fed back into both buffers)--
--
-- * @ain            @ --  input audio to be pitch shifted
pitchShifterDelay :: MaxDelayTime -> (Feedback, Feedback) -> DelayTime -> Sig -> Sig -> Sig
pitchShifterDelay :: MaxDelayTime -> (Sig, Sig) -> Sig -> Sig -> Sig -> Sig
pitchShifterDelay MaxDelayTime
maxDelayTime (Sig
fb1, Sig
fb2) Sig
dlt Sig
ratio Sig
ain = MaxDelayTime -> (Sig, Sig) -> Sig -> Sig -> Sig -> Sig
P.pitchShifterDelay MaxDelayTime
maxDelayTime (Sig
fb1, Sig
fb2) Sig
dlt Sig
ratio Sig
ain

-- | Delay line with low-pass filter in the feedback chain.
-- The filter adds natural decay to the echoes.
--
-- > fxAnalogDelay mixRatio delayTime feedback toneRatio ain
--
-- Note that the center frequency of the filter is measured in normalized units (form 0  to 1).
fxAnalogDelay :: Balance -> DelayTime -> Feedback -> ToneSig -> Sig -> Sig
fxAnalogDelay :: Sig -> Sig -> Sig -> Sig -> Sig -> Sig
fxAnalogDelay Sig
kmix Sig
kdelay Sig
kfback Sig
ktone Sig
ain = Sig -> Sig -> Sig -> Sig -> Sig -> Sig
P.fxAnalogDelay Sig
kmix Sig
kdelay Sig
kfback Sig
ktone Sig
ain

type DriveSig = Sig

-- | Distortion unit with low-pass filter.
--
-- > fxDistortion driveLevel toneRatio ain
--
-- Note that the center frequency of the filter is measured in normalized units (form 0  to 1).
fxDistortion :: DriveSig -> ToneSig -> Sig -> Sig
fxDistortion :: Sig -> Sig -> Sig -> Sig
fxDistortion Sig
kdrive Sig
ktone Sig
ain = Sig -> Sig -> Sig -> Sig -> Sig
P.fxDistortion Sig
1 Sig
kdrive Sig
ktone Sig
ain

type SensitivitySig = Sig
type BaseCps = Sig
type Resonance = Sig

-- | Envelope follower.
--
-- > fxFollower sensitivity baseFrequencyRatio resonance ain
--
-- Arguments:
--
-- * @sensitivity        @ --  sensitivity of the envelope follower (suggested range: 0 to 1)
--
-- * @baseFrequencyRatio @ --  base frequency of the filter before modulation by the input dynamics (range: 0 to 1)
--
-- ; @resonance          @ --  resonance of the lowpass filter (suggested range: 0 to 1)
fxFollower :: SensitivitySig -> BaseCps -> Resonance -> Sig -> Sig
fxFollower :: Sig -> Sig -> Sig -> Sig -> Sig
fxFollower Sig
ksens Sig
kbaseFreq Sig
kreson = Sig -> Sig -> Sig -> Sig -> Sig
P.fxEnvelopeFollower Sig
ksens Sig
kbaseFreq (Sig
0.99 Sig -> Sig -> Sig
forall a. Num a => a -> a -> a
* Sig
kreson)

type TimeSig = Sig

-- | An effect that reverses an audio stream in chunks
--
-- > fxReverse time
--
-- @time@ -- the size of the chunck in seconds.
fxReverse :: TimeSig -> Sig -> Sig
fxReverse :: Sig -> Sig -> Sig
fxReverse Sig
ktime = Sig -> Sig -> Sig
P.fxReverse Sig
ktime

-- | A flanger effect following the typical design of a so called 'stomp box'
--
-- >  fxFlanger rate depth delayTime feedback ain =
--
-- Arguments
--
-- * @rate      @ --  rate control of the lfo of the effect *NOT IN HERTZ* (range 0 to 1)
--
-- * @depth     @ --  depth of the lfo of the effect (range 0 to 1)
--
-- * @delayTime @ --  static delay offset of the flanging effect (range 0 to 1)
--
-- * @feedback  @ --  feedback and therefore intensity of the effect (range 0 to 1)
--
-- * @ain       @ --  input audio to which the flanging effect will be applied
fxFlanger :: RateSig -> DepthSig -> DelayTime -> Feedback -> Sig -> Sig
fxFlanger :: Sig -> Sig -> Sig -> Sig -> Sig -> Sig
fxFlanger Sig
krate Sig
kdepth Sig
kdelay Sig
kfback Sig
ain = Sig -> Sig -> Sig -> Sig -> Sig -> Sig
P.fxFlanger Sig
krate Sig
kdepth Sig
kdelay Sig
kfback Sig
ain

-- | Phaser
--
-- An phase shifting effect that mimics the design of a so called 'stomp box'
--
-- > fxPhaser rate depth freq fback ain
--
-- Arguments:
--
-- * @rate  @ --  rate of lfo of the effect (range 0 to 1)
--
-- * @depth @ --  depth of lfo of the effect (range 0 to 1)
--
-- * @freq  @ --  centre frequency of the phase shifting effect in octaves (suggested range 6 to 11)
--
-- * @fback @ --  feedback and therefore intensity of the effect (range 0 to 1)
--
-- * @ain   @ --  input audio to be pitch shifted
fxPhaser :: RateSig -> DepthSig -> BaseCps -> Feedback -> Sig -> Sig
fxPhaser :: Sig -> Sig -> Sig -> Sig -> Sig -> Sig
fxPhaser Sig
krate Sig
kdepth Sig
cps Sig
kfback Sig
ain = Sig -> Sig -> Sig -> Sig -> Sig -> Sig
P.fxPhaser Sig
krate Sig
kdepth (Sig
6 Sig -> Sig -> Sig
forall a. Num a => a -> a -> a
+ Sig
5 Sig -> Sig -> Sig
forall a. Num a => a -> a -> a
* Sig
cps) Sig
kfback Sig
ain

type BitsReductionSig = Sig
type FoldoverSig = Sig

-- | LoFi
--
-- 'Low Fidelity' distorting effects of bit reduction and downsampling (foldover)
--
-- > fxLoFi  bits fold ain = ...
--
-- Arguments
--
-- * @bits  @ --  bit depth reduction (range 0 to 1)
--
-- * @fold  @ --  amount of foldover (range 0 to 1)
--
-- * @ain   @ --  input audio to have low fidelity distortion effects applied
fxLoFi :: BitsReductionSig -> FoldoverSig -> Sig -> Sig
fxLoFi :: Sig -> Sig -> Sig -> Sig
fxLoFi Sig
kbits Sig
kfold Sig
ain = Sig -> Sig -> Sig -> Sig
P.fxLoFi (Sig
0.6 Sig -> Sig -> Sig
forall a. Num a => a -> a -> a
* Sig
kbits) Sig
kfold Sig
ain

-- | Stereo Chorus
--
-- A stereo chorus effect
--
-- > fxChorus2 rate depth width (ainLeft, ainRight)
--
-- Arguments
--
-- * @rate  @ --  rate control of the lfo of the effect *NOT IN HERTZ* (range 0 to 1)
--
-- * @depth @ --  depth of the lfo of the effect (range 0 to 1)
--
-- * @width @ --  width of stereo widening (range 0 to 1)
--
-- * @ainX  @ --  input stereo signal
fxChorus2 :: RateSig -> DepthSig -> WidthSig -> Sig2 -> Sig2
fxChorus2 :: Sig -> Sig -> Sig -> (Sig, Sig) -> (Sig, Sig)
fxChorus2 Sig
krate Sig
kdepth Sig
kwidth (Sig, Sig)
ain = Sig -> Sig -> Sig -> (Sig, Sig) -> (Sig, Sig)
P.fxChorus2 Sig
krate Sig
kdepth Sig
kwidth (Sig, Sig)
ain

type TremWaveSig = Sig

-- | Auto pan
--
-- > fxAutoPan wave rate depth ain
--
-- ; Arguments:
--
-- * @wave  @ --  waveform used by the lfo (0=sine 1=triangle 2=square)
--
-- * @rate  @ --  rate control of the lfo of the effect *NOT IN HERTZ* (range 0 to 1)
--
-- * @depth @ --  depth of the lfo of the effect (range 0 to 1)
--
-- * @mode  @ --  mode of the effect (0=auto-panning 1=tremolo)
--
-- * @ain   @ --  input stereo audio
fxAutoPan :: TremWaveSig -> DepthSig -> RateSig -> Sig2 -> Sig2
fxAutoPan :: Sig -> Sig -> Sig -> (Sig, Sig) -> (Sig, Sig)
fxAutoPan Sig
tremWave Sig
kdepth Sig
krate = Sig -> Sig -> Sig -> Sig -> (Sig, Sig) -> (Sig, Sig)
P.fxPanTrem Sig
kdepth Sig
krate Sig
0 Sig
tremWave

-- | Tremolo
--
-- tremolo effect
--
-- > fxTrem wave rate depth ain
--
-- ; Arguments:
--
-- * @wave  @ --  waveform used by the lfo (0=sine 1=triangle 2=square)
--
-- * @rate  @ --  rate control of the lfo of the effect *NOT IN HERTZ* (range 0 to 1)
--
-- * @depth @ --  depth of the lfo of the effect (range 0 to 1)
--
-- * @mode  @ --  mode of the effect (0=auto-panning 1=tremolo)
--
-- * @ain   @ --  input stereo audio
fxTrem :: TremWaveSig -> DepthSig -> RateSig -> Sig2 -> Sig2
fxTrem :: Sig -> Sig -> Sig -> (Sig, Sig) -> (Sig, Sig)
fxTrem Sig
tremWave Sig
kdepth Sig
krate = Sig -> Sig -> Sig -> Sig -> (Sig, Sig) -> (Sig, Sig)
P.fxPanTrem Sig
kdepth Sig
krate Sig
1 Sig
tremWave

type RatioSig = Sig
type FftSize  = D

-- | PitchShifter
--
--  A pitch shifter effect based on FFT technology
--
-- > fxPitchShifter  fftSize mixRatio transposeRatio feedback ain
--
-- Arguments
--
-- * @fftSize  @ -- size for FFT analysis (good values 1024, 512, 256, 2048), the higher values introduce latency but lower values are less accurate.
--
-- * @mix      @ --  dry / wet mix of the output signal (range 0 to 1)
--
-- * @transpose@ -- pitch ratio
--
-- * @feedback @ --  control of the amount of output signal fed back into the input of the effect (suggested range 0 to 1)
--
-- * @ain      @ --  input audio to be pitch shifted
fxPitchShifter :: FftSize -> Balance -> RatioSig -> Feedback -> Sig -> Sig
fxPitchShifter :: MaxDelayTime -> Sig -> Sig -> Sig -> Sig -> Sig
fxPitchShifter MaxDelayTime
ifftSize Sig
kmix Sig
ratio Sig
kfback = MaxDelayTime -> Sig -> Sig -> Sig -> Sig -> Sig
P.fxPitchShifter MaxDelayTime
ifftSize Sig
kmix Sig
ratio Sig
kfback

-- | FreqShifter
-- ; ----------------
-- ; A frequency shifter effect using the hilbert filter
-- ;
-- ; aout  FreqShifter  adry,kmix,kfreq,kmult,kfback
-- ;
-- ; Performance
-- ; -----------
-- ; adry   --  input audio to be frequency shifted
-- ; kmix   --  dry / wet mix of the output signal (range 0 to 1)
-- ; kfreq  --  frequency of frequency shifter effect (suggested range -1000 to 1000)
-- ; kmult  --  multiplier of frequency value for fine tuning control (suggested range -1 to 1)
-- ; kfback --  control of the amount of output signal fed back into the input of the effect (suggested range 0 to 1)
fxFreqShifter :: Balance -> Sig -> Sig -> Feedback -> Sig -> Sig
fxFreqShifter :: Sig -> Sig -> Sig -> Sig -> Sig -> Sig
fxFreqShifter Sig
kmix Sig
freq Sig
kmul Sig
kfback = Sig -> Sig -> Sig -> Sig -> Sig -> Sig
P.fxFreqShifter Sig
kmix Sig
freq Sig
kmul Sig
kfback


-- | Compressor. All arguments are relative (range in 0 to 1).
--
-- > fxCompress thresh (loknee, hiknee) ratio (att, rel) gain ain
fxCompress :: Sig -> (Sig, Sig) -> Sig -> (Sig, Sig) -> Sig -> Sig -> Sig
fxCompress :: Sig -> (Sig, Sig) -> Sig -> (Sig, Sig) -> Sig -> Sig -> Sig
fxCompress Sig
thresh (Sig
loknee, Sig
hiknee) Sig
ratio (Sig
att, Sig
rel) Sig
gain  Sig
x = Sig
gain' Sig -> Sig -> Sig
forall a. Num a => a -> a -> a
* Sig
-> Sig
-> Sig
-> Sig
-> Sig
-> Sig
-> Sig
-> Sig
-> MaxDelayTime
-> Sig
compress Sig
x Sig
x Sig
thresh' Sig
loknee' Sig
hiknee' Sig
ratio' Sig
att' Sig
rel' MaxDelayTime
0.05
    where
        gain' :: Sig
gain' = Sig -> Sig
forall a. SigOrD a => a -> a
ampdb (Sig -> Sig) -> Sig -> Sig
forall a b. (a -> b) -> a -> b
$ (Sig, Sig) -> Sig -> Sig
forall a. Num a => (a, a) -> a -> a
onLin (-Sig
36, Sig
36) Sig
gain
        thresh' :: Sig
thresh' = (Sig, Sig) -> Sig -> Sig
forall a. Num a => (a, a) -> a -> a
onLin (Sig
0, Sig
120) Sig
thresh
        att' :: Sig
att' = (Sig, Sig) -> Sig -> Sig
onExp (Sig
0, Sig
1) Sig
att
        rel' :: Sig
rel' = (Sig, Sig) -> Sig -> Sig
onExp (Sig
0, Sig
1) Sig
rel
        ratio' :: Sig
ratio' = (Sig, Sig) -> Sig -> Sig
onExp (Sig
1, Sig
30000) Sig
ratio
        loknee' :: Sig
loknee' = (Sig, Sig) -> Sig -> Sig
forall a. Num a => (a, a) -> a -> a
onLin (Sig
0, Sig
120) Sig
loknee
        hiknee' :: Sig
hiknee' = (Sig, Sig) -> Sig -> Sig
forall a. Num a => (a, a) -> a -> a
onLin (Sig
0, Sig
120) Sig
hiknee

        onLin :: (a, a) -> a -> a
onLin (a
min, a
max) a
val = a
min a -> a -> a
forall a. Num a => a -> a -> a
+ a
val a -> a -> a
forall a. Num a => a -> a -> a
* (a
max a -> a -> a
forall a. Num a => a -> a -> a
- a
min)
        onExp :: (Sig, Sig) -> Sig -> Sig
onExp (Sig
min, Sig
max) Sig
val = Sig -> Sig -> Sig -> Sig
scale (Sig -> Sig -> Sig
expcurve Sig
val Sig
4) Sig
max Sig
min

-------------------------------
-- tape echo

type EchoGain = Sig
type RandomSpreadSig = Sig

-- | Tape echo - simulates tape echo/delay
--
-- > tapeEcho size feedback echoGain tone randomSpread ain
--
-- * size - how many heads in the tape
-- * feedback
-- * echo gain
-- * tone - normalized center frequency of the filter (0  to 1)
-- * randomSpread - quality of the tape (the higher - the worser)
tapeEcho :: D -> DelayTime -> Feedback -> EchoGain -> ToneSig -> RandomSpreadSig -> Sig -> Sig
tapeEcho :: MaxDelayTime -> Sig -> Sig -> Sig -> Sig -> Sig -> Sig -> Sig
tapeEcho MaxDelayTime
n Sig
dt Sig
fb Sig
echoGain Sig
ktoneNorm Sig
spread Sig
ain = MaxDelayTime -> Sig -> Sig -> Sig -> Sig -> Sig -> Sig -> Sig
P.tapeEcho MaxDelayTime
n Sig
dt Sig
echoGain Sig
fb Sig
ktone Sig
spread Sig
ain
    where
        ktone :: Sig
ktone = Sig -> Sig
fromNormTone Sig
ktoneNorm

fromNormTone :: Sig -> Sig
fromNormTone :: Sig -> Sig
fromNormTone Sig
ktoneNorm = Sig -> Sig -> Sig
portk (Sig -> Sig -> Sig -> Sig
scale (Sig -> Sig -> Sig
expcurve Sig
ktoneNorm Sig
4) Sig
12000 Sig
100) Sig
0.1