synthesizer-llvm-0.3: src/Synthesizer/LLVM/Server/Packed/Run.hs
module Synthesizer.LLVM.Server.Packed.Run where
import qualified Synthesizer.LLVM.Server.Packed.Instrument as Instr
import qualified Synthesizer.LLVM.Server.Option as Option
import Synthesizer.LLVM.Server.Packed.Instrument
(Vector, VectorSize, vectorSize, )
import Synthesizer.LLVM.Server.Common
import qualified Sound.ALSA.Sequencer.Event as Event
import qualified Synthesizer.EventList.ALSA.MIDI as Ev
import qualified Synthesizer.PiecewiseConstant.ALSA.MIDI as PC
import qualified Synthesizer.PiecewiseConstant.ALSA.MIDIControllerSet as PCS
import qualified Synthesizer.Generic.ALSA.MIDI as Gen
import qualified Synthesizer.LLVM.Frame.StereoInterleaved as StereoInt
import qualified Synthesizer.LLVM.Frame.Stereo as Stereo
import qualified Synthesizer.LLVM.Filter.Universal as UniFilterL
import qualified Synthesizer.LLVM.CausalParameterized.ProcessPacked as CausalPS
import qualified Synthesizer.LLVM.CausalParameterized.Process as CausalP
import qualified Synthesizer.LLVM.Parameterized.Signal as SigP
import qualified Synthesizer.LLVM.Storable.Signal as SigStL
import qualified Synthesizer.LLVM.Wave as WaveL
import Synthesizer.LLVM.CausalParameterized.Process (($<#), ($<), ($*), )
import Synthesizer.LLVM.Parameterized.Signal (($#), )
import qualified LLVM.Core as LLVM
import qualified Synthesizer.Storable.Signal as SigSt
import qualified Data.StorableVector.Lazy as SVL
import qualified Synthesizer.Plain.Filter.Recursive as FiltR
import qualified Synthesizer.Plain.Filter.Recursive.Universal as UniFilter
import qualified Sound.MIDI.Controller as Ctrl
import qualified Sound.MIDI.Message.Channel.Voice as VoiceMsg
import qualified Sound.MIDI.Message.Channel as ChannelMsg
import qualified Data.EventList.Relative.TimeBody as EventList
import qualified Data.EventList.Relative.MixedTime as EventListMT
import Synthesizer.ApplicativeUtility (liftA4, liftA5, liftA6, )
import Control.Arrow ((<<<), (^<<), arr, first, {- second, -} )
import Control.Applicative (pure, {- liftA, liftA2, -} liftA3, (<*>), )
import Control.Monad.Trans.State (evalState, )
{-
import Data.Tuple.HT (mapPair, fst3, snd3, thd3, )
import qualified Numeric.NonNegative.Class as NonNeg
import qualified Numeric.NonNegative.Wrapper as NonNegW
import qualified Numeric.NonNegative.Chunky as NonNegChunky
-}
import Algebra.IntegralDomain (divUp, )
import NumericPrelude.Numeric (zero, round, (^?), )
import Prelude hiding (Real, round, break, )
vectorChunkSize :: Option.T -> SVL.ChunkSize
vectorChunkSize opts =
case Option.chunkSize opts of
SVL.ChunkSize size ->
SVL.ChunkSize (divUp size vectorSize)
sampleRate :: Num a => Option.T -> a
sampleRate opt =
case Option.sampleRate opt of
SampleRate sr -> sr
{-# INLINE withMIDIEventsMono #-}
withMIDIEventsMono ::
Option.T ->
(Option.T -> Double -> SigSt.T Real -> IO b) ->
(EventList.T Ev.StrictTime [Event.T] -> SigSt.T Vector) -> IO b
withMIDIEventsMono opt action proc =
let rate = sampleRate opt
in do
putStrLn startMessage
Ev.withMIDIEvents
(Option.clientName opt)
(Option.periodTime opt) (rate / fromIntegral vectorSize) $
action opt rate . SigStL.unpack . proc
type StereoVector = StereoInt.T VectorSize Real
{-# INLINE withMIDIEventsStereo #-}
withMIDIEventsStereo ::
Option.T ->
(Option.T -> Double -> SigSt.T (Stereo.T Real) -> IO b) ->
(EventList.T Ev.StrictTime [Event.T] -> SigSt.T StereoVector) ->
IO b
withMIDIEventsStereo opt action proc =
let rate = sampleRate opt
in do
putStrLn startMessage
Ev.withMIDIEvents
(Option.clientName opt)
(Option.periodTime opt) (rate / fromIntegral vectorSize) $
action opt rate . SigStL.unpackStereo . proc
-- maybe this can be merged into a PCS.controllerDiscrete
stair :: Real -> Real
stair i =
let n = fromIntegral (round i :: Int)
r = i - n
in n + 0.01*r
frequencyModulation :: IO ()
frequencyModulation = do
opt <- Option.get
osc <-
SigP.runChunky
((CausalPS.osciSimple WaveL.triangle $<# (LLVM.vector [zero] :: Vector))
$* Instr.frequencyFromBendModulation
(frequencyConst 10)
(Instr.modulation (\fm -> (fm,880))))
withMIDIEventsMono opt play $
osc (vectorChunkSize opt) . (,) (Option.sampleRate opt) .
evalState (PC.bendWheelPressure (Option.channel opt) 2 0.04 (0.03::Real))
keyboard :: IO ()
keyboard = do
opt <- Option.get
sound <-
Instr.pingRelease
$/ 0.4 $/ 0.1 $/ vectorChunkSize opt $/ Option.sampleRate opt
amp <- CausalP.runStorableChunky (CausalPS.amplify $# 0.2)
arrange <- SigStL.makeArranger
withMIDIEventsMono opt play $
(amp () :: SigSt.T Vector -> SigSt.T Vector) .
arrange (vectorChunkSize opt) .
evalState (Gen.sequence (Option.channel opt) sound)
keyboardStereo :: IO ()
keyboardStereo = do
opt <- Option.get
sound <-
Instr.pingStereoRelease
$/ 0.4 $/ 0.1 $/ vectorChunkSize opt $/ Option.sampleRate opt
amp <-
CausalP.runStorableChunky
(CausalP.mapSimple StereoInt.interleave <<<
(CausalPS.amplifyStereo $# 0.2))
arrange <- SigStL.makeArranger
withMIDIEventsStereo opt play $
(amp () :: SigSt.T (Stereo.T Vector) -> SigSt.T StereoVector) .
arrange (vectorChunkSize opt) .
evalState (Gen.sequence (Option.channel opt) sound)
keyboardFM :: IO ()
keyboardFM = do
opt <- Option.get
str <- Instr.softStringFM
amp <-
CausalP.runStorableChunky
(CausalP.mapSimple StereoInt.interleave <<<
(CausalP.amplifyStereo $# 0.2))
arrange <- SigStL.makeArranger
withMIDIEventsStereo opt play $
(amp () :: SigSt.T (Stereo.T Vector) -> SigSt.T StereoVector) .
arrange (vectorChunkSize opt) .
evalState
(do fm <- PC.bendWheelPressure (Option.channel opt) 2 0.04 0.03
Gen.sequenceModulated
fm (Option.channel opt) (flip str (Option.sampleRate opt)))
keyboardFMMulti :: IO ()
keyboardFMMulti = do
opt <- Option.get
str <- Instr.softStringFM
tin <- Instr.tineStereoFM $/ 0.4 $/ 0.1 $/ vectorChunkSize opt
amp <-
CausalP.runStorableChunky
(CausalP.mapSimple StereoInt.interleave <<<
(CausalP.amplifyStereo $# 0.2))
arrange <- SigStL.makeArranger
withMIDIEventsStereo opt play $
(amp () :: SigSt.T (Stereo.T Vector) -> SigSt.T StereoVector) .
arrange (vectorChunkSize opt) .
evalState
(do fm <- PC.bendWheelPressure (Option.channel opt) 2 0.04 0.03
Gen.sequenceModulatedMultiProgram
fm (Option.channel opt)
(VoiceMsg.toProgram 1)
(map (\sound fmlocal -> sound fmlocal $ Option.sampleRate opt) [str, tin]))
controllerAttack, controllerDetune, controllerTimbre0, controllerTimbre1,
controllerFilterCutoff, controllerFilterResonance,
controllerVolume :: VoiceMsg.Controller
controllerAttack = Ctrl.attackTime
controllerDetune = Ctrl.chorusDepth -- Ctrl.effect3Depth
controllerTimbre0 = Ctrl.soundVariation
controllerTimbre1 = Ctrl.timbre
controllerFilterCutoff = Ctrl.effect4Depth
controllerFilterResonance = Ctrl.effect5Depth
controllerVolume = Ctrl.volume
controllerFMDepth1, controllerFMDepth2, controllerFMDepth3, controllerFMDepth4,
controllerFMPartial1, controllerFMPartial2, controllerFMPartial3, controllerFMPartial4
:: VoiceMsg.Controller
controllerFMDepth1 = Ctrl.soundController3
controllerFMDepth2 = Ctrl.soundController5
controllerFMDepth3 = Ctrl.soundController7
controllerFMDepth4 = Ctrl.soundController8
controllerFMPartial1 = Ctrl.generalPurpose1
controllerFMPartial2 = Ctrl.generalPurpose2
controllerFMPartial3 = Ctrl.effect1Depth
controllerFMPartial4 = Ctrl.effect2Depth
keyboardDetuneFMCore ::
FilePath ->
SVL.ChunkSize ->
IO (ChannelMsg.Channel -> VoiceMsg.Program ->
SampleRate Real ->
Ev.Filter (SigSt.T StereoVector))
keyboardDetuneFMCore smpDir vcsize = do
str0 <- Instr.softStringDetuneFM
ssh0 <- Instr.softStringShapeFM
css0 <- Instr.cosineStringStereoFM
asw0 <- Instr.arcSawStringStereoFM
asn0 <- Instr.arcSineStringStereoFM
asq0 <- Instr.arcSquareStringStereoFM
atr0 <- Instr.arcTriangleStringStereoFM
wnd0 <- Instr.wind
wnp0 <- Instr.windPhaser
fms0 <- Instr.fmStringStereoFM
tin0 <- Instr.tineStereoFM
tnc0 <- Instr.tineControlledFM
fnd0 <- Instr.fenderFM
tnb0 <- Instr.tineBankFM
rfm0 <- Instr.resonantFMSynth
png0 <- Instr.pingStereoRelease
pngFM0 <- Instr.pingStereoReleaseFM
sqr0 <- Instr.squareStereoReleaseFM
bel0 <- Instr.bellStereoFM
ben0 <- Instr.bellNoiseStereoFM
flt0 <- Instr.filterSawStereoFM
brs0 <- Instr.brass
tmt0 <- Instr.makeSampledSounds smpDir Instr.tomatensalat
hal0 <- Instr.makeSampledSounds smpDir Instr.hal
grp0 <- Instr.makeSampledSounds smpDir Instr.graphentheorie
let evHead =
fmap (EventListMT.switchBodyL
(error "empty controller stream") const)
flt = evalState $
liftA6 (\rel -> flt0 (4*rel) rel)
(evHead $
PCS.controllerExponential controllerAttack (0.03,0.3) 0.1)
(PCS.controllerLinear controllerDetune (0,0.005) 0.001)
(evHead $
PCS.controllerExponential controllerTimbre0 (100,10000) 1000)
(evHead $
PCS.controllerExponential controllerTimbre1 (0.1,1) 0.1)
(pure vcsize)
(PCS.bendWheelPressure 2 0.04 0.03)
png =
(\rel -> png0 (4*rel) rel vcsize) .
evalState
(evHead $
PCS.controllerExponential controllerAttack (0.03,0.3) 0.1)
pngFM = evalState $
liftA6 (\rel det phs shp -> pngFM0 (4*rel) rel det shp 2 phs)
(evHead $
PCS.controllerExponential controllerAttack (0.03,0.3) 0.1)
(PCS.controllerLinear controllerDetune (0,0.005) 0.001)
(evHead $
PCS.controllerLinear controllerTimbre0 (0,1) 1)
(PCS.controllerExponential controllerTimbre1 (1/pi,0.001) 0.05)
(pure vcsize)
(PCS.bendWheelPressure 2 0.04 0.03)
sqr = evalState $
liftA6 (\rel -> sqr0 (4*rel) rel)
(evHead $
PCS.controllerExponential controllerAttack (0.03,0.3) 0.1)
(PCS.controllerLinear controllerDetune (0,0.005) 0.001)
(PCS.controllerExponential controllerTimbre0 (1/pi,0.001) 0.05)
(PCS.controllerLinear controllerTimbre1 (0,0.25) 0.25)
(pure vcsize)
(PCS.bendWheelPressure 2 0.04 0.03)
tin = evalState $
liftA3 (\rel -> tin0 (4*rel) rel)
(evHead $
PCS.controllerExponential controllerAttack (0.03,0.3) 0.1)
(pure vcsize)
(PCS.bendWheelPressure 2 0.04 0.03)
tnc = evalState $
liftA6 (\rel -> tnc0 (4*rel) rel)
(evHead $
PCS.controllerExponential controllerAttack (0.03,0.3) 0.1)
(PCS.controllerLinear controllerDetune (0,0.005) 0.001)
(fmap (fmap stair) $
PCS.controllerLinear controllerTimbre0 (0.5,6.5) 2)
(PCS.controllerLinear controllerTimbre1 (0,1.5) 1)
(pure vcsize)
(PCS.bendWheelPressure 2 0.04 0.03)
fnd = evalState $
pure (\rel -> fnd0 (4*rel) rel)
<*> (evHead $
PCS.controllerExponential controllerAttack (0.03,0.3) 0.1)
<*> (PCS.controllerLinear controllerDetune (0,0.005) 0.001)
<*> (fmap (fmap stair) $
PCS.controllerLinear controllerTimbre0 (0.5,20.5) 14)
<*> (PCS.controllerLinear controllerTimbre1 (0,1.5) 0.3)
<*> (PCS.controllerLinear controllerFMDepth1 (0,1) 0.25)
<*> (pure vcsize)
<*> (PCS.bendWheelPressure 2 0.04 0.03)
tnb = evalState $
pure (\rel -> tnb0 (4*rel) rel)
<*> (evHead $
PCS.controllerExponential controllerAttack (0.03,0.3) 0.1)
<*> (PCS.controllerLinear controllerDetune (0,0.005) 0.001)
<*> (PCS.controllerLinear controllerFMDepth1 (0,2) 0)
<*> (PCS.controllerLinear controllerFMDepth2 (0,2) 0)
<*> (PCS.controllerLinear controllerFMDepth3 (0,2) 0)
<*> (PCS.controllerLinear controllerFMDepth4 (0,2) 0)
<*> (PCS.controllerLinear controllerFMPartial1 (0,1) 1)
<*> (PCS.controllerLinear controllerFMPartial2 (0,1) 0)
<*> (PCS.controllerLinear controllerFMPartial3 (0,1) 0)
<*> (PCS.controllerLinear controllerFMPartial4 (0,1) 0)
<*> (pure vcsize)
<*> (PCS.bendWheelPressure 2 0.04 0.03)
rfm = evalState $
pure (\rel -> rfm0 (4*rel) rel)
<*> (evHead $
PCS.controllerExponential controllerAttack (0.03,0.3) 0.1)
<*> (PCS.controllerLinear controllerDetune (0,0.005) 0.001)
<*> (PCS.controllerExponential controllerTimbre1 (1,100) 30)
<*> (PCS.controllerLinear controllerTimbre0 (1,15) 3)
<*> (PCS.controllerExponential controllerFMDepth1 (0.005,0.5) 0.1)
<*> (pure vcsize)
<*> (PCS.bendWheelPressure 2 0.04 0.03)
bel = evalState $
liftA4 (\rel -> bel0 (2*rel) rel)
(evHead $
PCS.controllerExponential controllerAttack (0.03,1.0) 0.3)
(PCS.controllerLinear controllerDetune (0,0.005) 0.001)
(pure vcsize)
(PCS.bendWheelPressure 2 0.05 0.02)
ben = evalState $
liftA5 (\rel -> ben0 (2*rel) rel)
(evHead $
PCS.controllerExponential controllerAttack (0.03,1.0) 0.3)
(PCS.controllerLinear controllerTimbre0 (0,1) 0.3)
(PCS.controllerExponential controllerTimbre1 (1,1000) 100)
(pure vcsize)
(PCS.bendWheelPressure 2 0.05 0.02)
str = evalState $
liftA3 str0
(evHead $
PCS.controllerExponential controllerAttack (0.02,2) 0.5)
(PCS.controllerLinear controllerDetune (0,0.01) 0.005)
(PCS.bendWheelPressure 2 0.04 0.03)
ssh = evalState $
liftA4 ssh0
(evHead $
PCS.controllerExponential controllerAttack (0.02,2) 0.5)
(PCS.controllerLinear controllerDetune (0,0.01) 0.005)
(PCS.controllerExponential controllerTimbre0 (1/pi,0.001) 0.05)
(PCS.bendWheelPressure 2 0.04 0.03)
makeArc gen = evalState $
liftA4 gen
(evHead $
PCS.controllerExponential controllerAttack (0.02,2) 0.5)
(PCS.controllerLinear controllerDetune (0,0.01) 0.005)
(PCS.controllerLinear controllerTimbre0 (0.5,9.5) 1.5)
(PCS.bendWheelPressure 2 0.04 0.03)
css = makeArc css0
asw = makeArc asw0
asn = makeArc asn0
asq = makeArc asq0
atr = makeArc atr0
fms = evalState $
liftA5 fms0
(evHead $
PCS.controllerExponential controllerAttack (0.02,2) 0.5)
(PCS.controllerLinear controllerDetune (0,0.01) 0.005)
(PCS.controllerLinear controllerTimbre0 (0,0.5) 0.2)
(PCS.controllerExponential controllerTimbre1 (0.001,10) 0.1)
(PCS.bendWheelPressure 2 0.04 0.03)
wnd = evalState $
liftA3 wnd0
(evHead $
PCS.controllerExponential controllerAttack (0.02,2) 0.5)
(PCS.controllerExponential controllerTimbre1 (1,1000) 100)
(PCS.bendWheelPressure 12 0.8 0)
wnp = evalState $
liftA5 wnp0
(evHead $
PCS.controllerExponential controllerAttack (0.02,2) 0.5)
(PCS.controllerLinear controllerTimbre0 (0,1) 0.5)
(PCS.controllerExponential controllerDetune (50,5000) 500)
(PCS.controllerExponential controllerTimbre1 (1,1000) 100)
(PCS.bendWheelPressure 12 0.8 0)
brs = evalState $
liftA6
(\rel det t0 peak -> brs0 (rel/2) 1.5 (rel/2) rel rel peak det t0)
(evHead $
PCS.controllerExponential controllerAttack (0.01,0.1) 0.01)
(PCS.controllerLinear controllerDetune (0,0.01) 0.005)
(PCS.controllerExponential controllerTimbre0 (1/pi,0.001) 0.05)
(evHead $
PCS.controllerLinear controllerTimbre1 (1,5) 3)
(pure vcsize)
(PCS.bendWheelPressure 2 0.04 0.03)
freqMod =
evalState
(PCS.bendWheelPressure 2 0.04 0.03)
arrange <- SigStL.makeArranger
amp <-
CausalP.runStorableChunky
(CausalP.mapSimple StereoInt.interleave <<<
CausalP.envelopeStereo $<
Instr.piecewiseConstantVector (arr id))
return
(\chan pgm sr -> do
volume <-
PC.controllerExponential chan
controllerVolume
(0.001, 1) 0.2
ctrls <- PCS.fromChannel chan
fmap (amp volume . arrange vcsize) $
Gen.sequenceModulatedMultiProgram
ctrls chan pgm
(map (\sound fm -> sound fm $ sr) $
[tnc, fnd, pngFM, flt, bel, ben, sqr, brs,
ssh, fms, css, asn, atr, asq, asw, wnp] ++
map (.freqMod) tmt0 ++
map (.freqMod) hal0 ++
map (.freqMod) grp0 ++
[str, wnd, png, rfm, tin, tnb]))
keyboardDetuneFM :: IO ()
keyboardDetuneFM = do
opt <- Option.get
proc <- keyboardDetuneFMCore (Option.sampleDirectory opt) (vectorChunkSize opt)
withMIDIEventsStereo opt play $
evalState (proc (Option.channel opt) (VoiceMsg.toProgram 0) (Option.sampleRate opt))
keyboardFilter :: IO ()
keyboardFilter = do
opt <- Option.get
proc <- keyboardDetuneFMCore (Option.sampleDirectory opt) (vectorChunkSize opt)
mix <- CausalP.runStorableChunky
(CausalP.mapSimple StereoInt.interleave <<<
CausalP.mix <<<
first (CausalPS.amplifyStereo 0.5 <<<
CausalP.mapSimple StereoInt.deinterleave)
$< SigP.fromStorableVectorLazy (arr id))
lowpass0 <-
CausalP.runStorableChunky $
-- CausalPS.amplifyStereo 0.1 <<<
CausalPS.pack
(CausalP.stereoFromMonoControlled
(UniFilter.lowpass ^<< UniFilterL.causalP) $<
(SigP.interpolateConstant $# (fromIntegral vectorSize :: Real))
(piecewiseConstant (arr id)))
<<<
CausalP.mapSimple StereoInt.deinterleave
let lowpass ::
PC.T Real -> PC.T Real ->
SigSt.T StereoVector -> SigSt.T (Stereo.T Vector)
lowpass resons freqs =
lowpass0 (fmap UniFilter.parameter
(PC.zipWith FiltR.Pole resons
(fmap (/ sampleRate opt) freqs)))
withMIDIEventsStereo opt play $
evalState
(do {-
It is important to retrieve the global controllers
before they are filtered out by PCS.fromChannel.
-}
let freqBnd v = 880 * 2^?(v/24)
freq <-
PC.controllerExponential (Option.extraChannel opt)
controllerFilterCutoff
(freqBnd (-64), freqBnd 63) 5000
resonance <-
PC.controllerExponential (Option.extraChannel opt)
controllerFilterResonance
(1, 100) 1
filterMusic <-
proc (Option.extraChannel opt) (VoiceMsg.toProgram 8) (Option.sampleRate opt)
pureMusic <-
proc (Option.channel opt) (VoiceMsg.toProgram 0) (Option.sampleRate opt)
return
(pureMusic `mix`
lowpass resonance freq filterMusic))