synthesizer-llvm 0.3 → 0.5
raw patch · 91 files changed
+11009/−8266 lines, 91 filesdep +explicit-exceptiondep +jackdep +llvm-tfdep −HListdep −functional-arrowdep −llvmdep ~alsa-pcmdep ~alsa-seqdep ~containersnew-component:exe:synthi-llvm-alsanew-component:exe:synthi-llvm-jacknew-component:exe:synthi-llvm-render
Dependencies added: explicit-exception, jack, llvm-tf, synthesizer-llvm, synthesizer-midi, tfp, unsafe
Dependencies removed: HList, functional-arrow, llvm, type-level
Dependency ranges changed: alsa-pcm, alsa-seq, containers, filepath, llvm-extra, midi, midi-alsa, numeric-prelude, sox, synthesizer-alsa, synthesizer-core, transformers, utility-ht, vault
Files
- alsa/Synthesizer/LLVM/Server.hs +82/−0
- alsa/Synthesizer/LLVM/Server/ALSA.hs +165/−0
- alsa/Synthesizer/LLVM/Server/CausalPacked/Run.hs +179/−0
- alsa/Synthesizer/LLVM/Server/CausalPacked/Test.hs +579/−0
- alsa/Synthesizer/LLVM/Server/Option.hs +168/−0
- alsa/Synthesizer/LLVM/Server/Packed/Run.hs +493/−0
- alsa/Synthesizer/LLVM/Server/Packed/Test.hs +697/−0
- alsa/Synthesizer/LLVM/Server/Scalar/Run.hs +154/−0
- alsa/Synthesizer/LLVM/Server/Scalar/Test.hs +86/−0
- example/Synthesizer/LLVM/LAC2011.hs +335/−0
- example/Synthesizer/LLVM/LNdW2011.hs +554/−0
- example/Synthesizer/LLVM/Test.hs +1382/−0
- jack/Synthesizer/LLVM/Server/JACK.hs +227/−0
- render/Synthesizer/LLVM/Server/Render.hs +153/−0
- src/Synthesizer/LLVM/ALSA/BendModulation.hs +0/−85
- src/Synthesizer/LLVM/ALSA/MIDI.hs +0/−176
- src/Synthesizer/LLVM/Causal/Process.hs +37/−21
- src/Synthesizer/LLVM/CausalParameterized/Controlled.hs +72/−50
- src/Synthesizer/LLVM/CausalParameterized/ControlledPacked.hs +73/−61
- src/Synthesizer/LLVM/CausalParameterized/Functional.hs +122/−28
- src/Synthesizer/LLVM/CausalParameterized/FunctionalPlug.hs +342/−0
- src/Synthesizer/LLVM/CausalParameterized/Process.hs +107/−109
- src/Synthesizer/LLVM/CausalParameterized/ProcessPacked.hs +102/−96
- src/Synthesizer/LLVM/CausalParameterized/ProcessPrivate.hs +43/−37
- src/Synthesizer/LLVM/CausalParameterized/ProcessValue.hs +84/−0
- src/Synthesizer/LLVM/Complex.hs +11/−13
- src/Synthesizer/LLVM/ConstantPiece.hs +21/−21
- src/Synthesizer/LLVM/Debug/Storable.hs +9/−6
- src/Synthesizer/LLVM/Execution.hs +14/−18
- src/Synthesizer/LLVM/Filter/Allpass.hs +92/−123
- src/Synthesizer/LLVM/Filter/Butterworth.hs +13/−12
- src/Synthesizer/LLVM/Filter/Chebyshev.hs +21/−19
- src/Synthesizer/LLVM/Filter/ComplexFirstOrder.hs +29/−43
- src/Synthesizer/LLVM/Filter/ComplexFirstOrderPacked.hs +22/−26
- src/Synthesizer/LLVM/Filter/FirstOrder.hs +33/−63
- src/Synthesizer/LLVM/Filter/Moog.hs +75/−69
- src/Synthesizer/LLVM/Filter/SecondOrder.hs +78/−105
- src/Synthesizer/LLVM/Filter/SecondOrderCascade.hs +40/−36
- src/Synthesizer/LLVM/Filter/SecondOrderPacked.hs +17/−16
- src/Synthesizer/LLVM/Filter/Universal.hs +54/−49
- src/Synthesizer/LLVM/Frame.hs +9/−36
- src/Synthesizer/LLVM/Frame/SerialVector.hs +588/−0
- src/Synthesizer/LLVM/Frame/Stereo.hs +36/−22
- src/Synthesizer/LLVM/Frame/StereoInterleaved.hs +142/−78
- src/Synthesizer/LLVM/Generator/Exponential2.hs +63/−68
- src/Synthesizer/LLVM/LAC2011.hs +0/−328
- src/Synthesizer/LLVM/LNdW2011.hs +0/−543
- src/Synthesizer/LLVM/MIDI.hs +177/−0
- src/Synthesizer/LLVM/MIDI/BendModulation.hs +91/−0
- src/Synthesizer/LLVM/Parameter.hs +2/−1
- src/Synthesizer/LLVM/Parameterized/Signal.hs +88/−102
- src/Synthesizer/LLVM/Parameterized/SignalPacked.hs +170/−139
- src/Synthesizer/LLVM/Parameterized/SignalPrivate.hs +41/−31
- src/Synthesizer/LLVM/Plug/Input.hs +46/−42
- src/Synthesizer/LLVM/Plug/Output.hs +24/−25
- src/Synthesizer/LLVM/Random.hs +10/−8
- src/Synthesizer/LLVM/RingBuffer.hs +9/−11
- src/Synthesizer/LLVM/SerialVector.hs +0/−17
- src/Synthesizer/LLVM/Server.hs +0/−69
- src/Synthesizer/LLVM/Server/CausalPacked/Arrange.hs +427/−0
- src/Synthesizer/LLVM/Server/CausalPacked/Instrument.hs +230/−239
- src/Synthesizer/LLVM/Server/CausalPacked/InstrumentPlug.hs +102/−0
- src/Synthesizer/LLVM/Server/CausalPacked/Run.hs +0/−424
- src/Synthesizer/LLVM/Server/CausalPacked/Speech.hs +162/−0
- src/Synthesizer/LLVM/Server/CausalPacked/Test.hs +0/−346
- src/Synthesizer/LLVM/Server/Common.hs +48/−63
- src/Synthesizer/LLVM/Server/CommonPacked.hs +69/−0
- src/Synthesizer/LLVM/Server/Option.hs +0/−196
- src/Synthesizer/LLVM/Server/Packed/Instrument.hs +149/−239
- src/Synthesizer/LLVM/Server/Packed/Run.hs +0/−504
- src/Synthesizer/LLVM/Server/Packed/Test.hs +0/−727
- src/Synthesizer/LLVM/Server/SampledSound.hs +100/−0
- src/Synthesizer/LLVM/Server/Scalar/Instrument.hs +5/−4
- src/Synthesizer/LLVM/Server/Scalar/Run.hs +0/−147
- src/Synthesizer/LLVM/Server/Scalar/Test.hs +0/−85
- src/Synthesizer/LLVM/Simple/Signal.hs +46/−32
- src/Synthesizer/LLVM/Simple/Value.hs +172/−80
- src/Synthesizer/LLVM/Simple/Vanilla.hs +12/−18
- src/Synthesizer/LLVM/Storable/Process.hs +11/−11
- src/Synthesizer/LLVM/Storable/Signal.hs +49/−48
- src/Synthesizer/LLVM/Test.hs +0/−1336
- src/Synthesizer/LLVM/Wave.hs +66/−84
- src/Test/Main.hs +0/−22
- src/Test/Synthesizer/LLVM/Filter.hs +0/−500
- src/Test/Synthesizer/LLVM/Packed.hs +0/−200
- src/Test/Synthesizer/LLVM/Utility.hs +0/−101
- synthesizer-llvm.cabal +239/−58
- testsuite/Test/Main.hs +22/−0
- testsuite/Test/Synthesizer/LLVM/Filter.hs +505/−0
- testsuite/Test/Synthesizer/LLVM/Packed.hs +206/−0
- testsuite/Test/Synthesizer/LLVM/Utility.hs +128/−0
+ alsa/Synthesizer/LLVM/Server.hs view
@@ -0,0 +1,82 @@+module Main where++import qualified Synthesizer.LLVM.Server.CausalPacked.Test as ServerCausalTest+import qualified Synthesizer.LLVM.Server.CausalPacked.Run as ServerCausal+import qualified Synthesizer.LLVM.Server.Packed.Test as ServerPackedTest+import qualified Synthesizer.LLVM.Server.Packed.Run as ServerPacked+import qualified Synthesizer.LLVM.Server.Scalar.Test as ServerScalarTest+import qualified Synthesizer.LLVM.Server.Scalar.Run as ServerScalar++import qualified LLVM.Core as LLVM+++part :: Int+part = 106++main :: IO ()+main =+ LLVM.initializeNativeTarget >>+ case part of+ 000 -> ServerScalar.pitchBend+ 001 -> ServerScalar.frequencyModulation+ 002 -> ServerScalar.keyboard+ 003 -> ServerScalar.keyboardStereo+ 004 -> ServerScalar.keyboardMulti+ 005 -> ServerScalar.keyboardStereoMulti+ 100 -> ServerPacked.frequencyModulation+ 101 -> ServerPacked.keyboard+ 102 -> ServerPacked.keyboardStereo+ 103 -> ServerPacked.keyboardFM+ 104 -> ServerPacked.keyboardFMMulti+ 105 -> ServerPacked.keyboardDetuneFM+ 106 -> ServerPacked.keyboardFilter -- there is still a leak when playing for a long time with arcStrings+ 150 -> ServerCausal.keyboard+ 151 -> ServerCausal.keyboardFM+ 152 -> ServerCausal.keyboardDetuneFM+ 153 -> ServerCausal.keyboardMultiChannel+ 154 -> ServerCausal.voder+ 155 -> ServerCausal.formant+ 200 -> ServerScalarTest.pitchBend0+ 201 -> ServerScalarTest.pitchBend1+ 202 -> ServerScalarTest.pitchBend2+ 203 -> ServerScalarTest.sequencePress+ 300 -> ServerPackedTest.adsr+ 301 -> ServerPackedTest.sequencePlain+ 302 -> ServerPackedTest.sequenceLLVM+ 303 -> ServerPackedTest.sequencePitchBendCycle+ 304 -> ServerPackedTest.sequencePitchBendSimple+ 305 -> ServerPackedTest.sequencePitchBend+ 306 -> ServerPackedTest.sequenceModulated+ 307 -> ServerPackedTest.sequencePress+ 308 -> ServerPackedTest.sequenceModulatedLong+ 309 -> ServerPackedTest.sequenceModulatedLongFM+ 310 -> ServerPackedTest.sequenceModulatedRepeat+ 311 -> ServerPackedTest.sequenceSample+ 312 -> ServerPackedTest.sequenceSample1 -- leak+-- 313 -> ServerPackedTest.testSequenceSample1a -- leak+ 320 -> ServerPackedTest.sequenceSample2 -- leak+ 321 -> ServerPackedTest.sequenceSample3 -- leak+ 322 -> ServerPackedTest.sequenceSample4 -- leak+ 323 -> ServerPackedTest.sequenceFM1 -- leak+ 324 -> ServerPackedTest.bellNoiseStereoTest+ 400 -> ServerCausalTest.render+ 401 -> ServerCausalTest.sequenceNothing+ 402 -> ServerCausalTest.sequenceSingleLong+ 403 -> ServerCausalTest.sequenceSingleShort+ 404 -> ServerCausalTest.sequenceLoop+ 405 -> ServerCausalTest.sequenceStaccato+ 406 -> ServerCausalTest.sequenceControlled+ 407 -> ServerCausalTest.sequenceControlledModulated+ 409 -> ServerCausalTest.functional+ 410 -> ServerCausalTest.functionalPlug+ 411 -> ServerCausalTest.functionalTine >>+ ServerCausalTest.functionalPlugTine+ 412 -> ServerCausalTest.sampledSound+ 413 -> ServerCausalTest.sampledSoundCrash+ 414 -> ServerCausalTest.sampledSoundMono+ 415 -> ServerCausalTest.frequencyModulation+ 416 -> ServerCausalTest.frequencyModulationIO+ 417 -> ServerCausalTest.frequencyModulationStrictIO+ 418 -> ServerCausalTest.frequencyModulationSawIO+ 419 -> ServerCausalTest.envelopeIO+ _ -> error "not implemented server part"
+ alsa/Synthesizer/LLVM/Server/ALSA.hs view
@@ -0,0 +1,165 @@+module Synthesizer.LLVM.Server.ALSA (+ Output,+ play, playChunk,+ record,+ put,+ startMessage,+ makeNote,+ ) where++import qualified Synthesizer.LLVM.Server.Option as Option++import qualified Synthesizer.ALSA.CausalIO.Process as PIO++import qualified Sound.ALSA.Sequencer.Event as Event+import qualified Sound.ALSA.Sequencer.Address as Addr+import qualified Sound.ALSA.Sequencer.Time as Time+import qualified Sound.ALSA.Sequencer.RealTime as RealTime++import qualified Sound.ALSA.PCM.Node.ALSA as PCM+import qualified Sound.ALSA.PCM.Parameters.Software as SwParam+import qualified Sound.ALSA.PCM.Parameters.Hardware as HwParam++import qualified Synthesizer.Storable.Signal as SigSt++import qualified Data.StorableVector.Lazy as SVL+import qualified Data.StorableVector.Base as SVB++import qualified Algebra.Additive as Additive++import Control.Functor.HT (void, )++import qualified System.IO as IO++-- import NumericPrelude.Numeric (zero, round, )++import Prelude hiding (Real, round, )+++getOptParams :: Option.T -> h -> ((PCM.Size, PCM.SampleFreq), h)+getOptParams opt h =+ ((case Option.chunkSize opt of SVL.ChunkSize size -> size,+ case Option.sampleRate opt of+ Nothing -> 44100+ Just (Option.SampleRate rate) -> rate),+ h)+++type Output handle signal a = Option.T -> PIO.Output handle signal a++record ::+ (PCM.SampleFmt y) =>+ FilePath -> Output IO.Handle (SigSt.T y) ()+record name opt =+ (fmap (getOptParams opt) $ IO.openFile name IO.WriteMode,+ IO.hClose,+ SVL.hPut)++put :: (Show signal) => Output () signal ()+put opt =+ (return $ getOptParams opt (),+ return,+ \() -> print)+++playChunk ::+ (Additive.C y, PCM.SampleFmt y) =>+ Output (PCM.Handle HwParam.Interleaved y) (SVB.Vector y) ()+playChunk opt =+ (openPCM opt, closePCM, write)+++-- ToDo: do not record the empty chunk that is inserted for latency+{-# INLINE play #-}+play ::+ (Additive.C y, PCM.SampleFmt y) =>+ Output (PCM.Handle HwParam.Interleaved y) (SigSt.T y) ()+play opt =+ (openPCM opt, closePCM, \h -> mapM_ (write h) . SVL.chunks)+{-+ Play.auto (Play.makeSink+ (Option.device opts) (Option.periodTime opts) (round rate)) .+ SigSt.append (SigSt.replicate (Option.chunkSize opts) (Option.latency opts) zero)+-- FiltG.delayPosLazySize (Option.chunkSize opts) (Option.latency opts)+-- FiltG.delayPos (Option.latency opts)+-}+++putLog :: String -> IO ()+putLog = putStrLn++openPCM ::+ (PCM.Access i, PCM.SampleFmt y) =>+ Option.T ->+ IO ((PCM.Size, PCM.SampleFreq), PCM.Handle i y)+openPCM opt = do+ putLog "alsaOpen"+ (((bufferSize,periodSize),(bufferTime,periodTime),sampleRate), h) <-+ PCM.open (PCM.modes []) PCM.StreamPlayback+ (setHwParams (Option.sampleRate opt) (Option.chunkSize opt))+ (\q@(sizes,_,_) -> do+ uncurry SwParam.setBufferSize sizes+ return q)+ (Option.device opt)+ PCM.prepare h+ putLog $ "bufferTime = " ++ show bufferTime+ putLog $ "bufferSize = " ++ show bufferSize+ putLog $ "periodTime = " ++ show periodTime+ putLog $ "periodSize = " ++ show periodSize+ return ((periodSize, sampleRate), h)++closePCM :: PCM.Handle i y -> IO ()+closePCM pcm = do+ putLog "alsaClose"+ PCM.drain pcm+ PCM.close pcm++setHwParams ::+ Maybe (Option.SampleRate Int) ->+ SVL.ChunkSize ->+ HwParam.T i y ((PCM.Size,PCM.Size),(PCM.Time,PCM.Time),PCM.SampleFreq)+ -- ^ ((bufferSize,periodSize),(bufferTime,periodTime),sampleRate)+setHwParams mrate (SVL.ChunkSize periodSize) = do+ (actualRate,_) <-+ case mrate of+ Nothing -> do+ HwParam.setRateResample False+ HwParam.setRateNear 44100 EQ+ Just (Option.SampleRate rate) -> do+ HwParam.setRateResample True+ HwParam.setRateNear rate EQ+ (actualPeriodSize,_) <-+ HwParam.setPeriodSizeNear periodSize EQ+ actualBufferSize <-+ HwParam.setBufferSizeNear+ (max periodSize (actualPeriodSize*4))++ (actualBufferTime,_) <- HwParam.getBufferTime+ (actualPeriodTime,_) <- HwParam.getPeriodTime+ return ((actualBufferSize, actualPeriodSize),+ (actualBufferTime, actualPeriodTime),+ actualRate)++write ::+ (PCM.SampleFmt y) =>+ PCM.Handle PCM.Interleaved y -> SVB.Vector y -> IO ()+write h xs =+ SVB.withStartPtr xs $ \buf ->+ void . PCM.writeiRetry h buf . fromIntegral++++startMessage :: String+startMessage =+ "run 'aconnect' to connect to the MIDI controller"+++-- cf. synthesizer-alsa:Synthesizer.ALSA.Storable.Server.Test+makeNote :: Event.NoteEv -> Int -> Event.T+makeNote typ pit =+ (Event.simple Addr.subscribers $ Event.NoteEv typ $+ Event.simpleNote (Event.Channel 0)+ (Event.Pitch $ fromIntegral pit) Event.normalVelocity)+ { Event.time =+ Time.consAbs $ Time.Real $ RealTime.fromInteger 0+ }
+ alsa/Synthesizer/LLVM/Server/CausalPacked/Run.hs view
@@ -0,0 +1,179 @@+module Synthesizer.LLVM.Server.CausalPacked.Run where++import qualified Synthesizer.LLVM.Server.CausalPacked.Arrange as Arrange+import Synthesizer.LLVM.Server.CausalPacked.Arrange+ (StereoVector, controllerExponentialDim, (&+&), )++import qualified Sound.MIDI.Controller as Ctrl++import qualified Synthesizer.LLVM.Server.CausalPacked.Speech as Speech+import qualified Synthesizer.LLVM.Server.Option as Option+import Synthesizer.LLVM.Server.ALSA (playChunk, startMessage, )+import Synthesizer.LLVM.Server.Common++import qualified Sound.ALSA.Sequencer.Event as Event++import qualified Synthesizer.MIDI.CausalIO.ControllerSet as MCS+import qualified Synthesizer.MIDI.CausalIO.Process as MIO+import qualified Synthesizer.ALSA.CausalIO.Process as PAlsa+import qualified Synthesizer.CausalIO.Process as PIO++import qualified Synthesizer.LLVM.CausalParameterized.Process as CausalP+import qualified Synthesizer.LLVM.Storable.Signal as SigStL++import qualified Synthesizer.LLVM.Frame.StereoInterleaved as StereoInt++import qualified Data.StorableVector as SV++import qualified Synthesizer.Zip as Zip++import qualified Sound.ALSA.PCM as PCM++import qualified Sound.MIDI.Message.Channel.Voice as VoiceMsg+import qualified Sound.MIDI.Message.Channel as ChannelMsg++import Control.Arrow (Arrow, (<<<), (^<<), arr, )+import Control.Category (id, )++import qualified Number.DimensionTerm as DN++import qualified Algebra.Additive as Additive++{-+import qualified Numeric.NonNegative.Class as NonNeg+import qualified Numeric.NonNegative.Wrapper as NonNegW+import qualified Numeric.NonNegative.Chunky as NonNegChunky+-}++import Prelude hiding (Real, id, )++++playFromEvents ::+ (PCM.SampleFmt a, Additive.C a) =>+ Option.T ->+ (SampleRate Real ->+ PIO.T (MIO.Events Event.T) (SV.Vector a)) ->+ IO ()+playFromEvents opt process = do+ putStrLn startMessage+ PAlsa.playFromEventsWithParams (playChunk opt)+ (Option.clientName opt)+ (\(_size,rate) ->+ process (SampleRate $ fromIntegral rate))+++keyboard :: IO ()+keyboard = do+ opt <- Option.get+ proc <- Arrange.keyboard++ playFromEvents opt $ \ sampleRate ->+ arr SigStL.unpackStrict+ <<<+ proc (Option.channel opt) sampleRate+++keyboardFM :: IO ()+keyboardFM = do+ opt <- Option.get+ proc <-+ Arrange.keyboardFM+ (CausalP.mapSimple StereoInt.interleave)+ (Option.channel opt)+ playFromEvents opt $ \ sampleRate ->+ SigStL.unpackStereoStrict ^<< proc sampleRate++keyboardDetuneFMCore ::+ Option.T ->+ IO (ChannelMsg.Channel -> VoiceMsg.Program ->+ SampleRate Real ->+ PIO.T (MIO.Events Event.T) (SV.Vector StereoVector))+keyboardDetuneFMCore opt =+ Arrange.keyboardDetuneFMCore+ (CausalP.mapSimple StereoInt.interleave)+ (Option.sampleDirectory opt)++keyboardDetuneFM :: IO ()+keyboardDetuneFM = do+ opt <- Option.get+ proc <- keyboardDetuneFMCore opt+ playFromEvents opt $ \ sampleRate ->+ arr SigStL.unpackStereoStrict+ <<<+ proc (Option.channel opt) (VoiceMsg.toProgram 0) sampleRate++keyboardMultiChannel :: IO ()+keyboardMultiChannel = do+ opt <- Option.get+ proc <- keyboardDetuneFMCore opt+ mix <- CausalP.processIO CausalP.mix++ playFromEvents opt $ \ sampleRate ->+ arr SigStL.unpackStereoStrict+ <<<+ foldl1+ (\x y -> mix () <<< Zip.arrowFanout x y)+ (map+ (\chan ->+ proc (ChannelMsg.toChannel chan) (VoiceMsg.toProgram 0)+ sampleRate)+ [0 .. 3])+++voder :: IO ()+voder = do+ opt <- Option.get+ proc <-+ Arrange.voder+ (CausalP.mapSimple StereoInt.interleave)+ (Option.sampleDirectory opt)++ playFromEvents opt $ \ sampleRate ->+ arr SigStL.unpackStereoStrict+ <<<+ proc (Option.channel opt) (VoiceMsg.toProgram 4) sampleRate+++formant :: IO ()+formant = do+ opt <- Option.get+ proc <-+ Arrange.keyboardDetuneFMCore id+ (Option.sampleDirectory opt)+ form <- Speech.filterFormant+ mix <- CausalP.processIO CausalP.mix+ interleave <-+ CausalP.processIO+ (CausalP.mapSimple StereoInt.interleave)++ playFromEvents opt $ \ sampleRate ->+ arr SigStL.unpackStereoStrict+ <<<+ interleave ()+ <<<+ foldl1+ (\x y -> mix () <<< Zip.arrowFanout x y)+ (zipWith+ (\n (freq, amp, reson) ->+ form sampleRate+ <<<+ Zip.arrowFirst+ (MCS.controllerExponential (Ctrl.fromInt $ 16+n) (0.01,1) amp+ &+&+ (MCS.controllerExponential (Ctrl.fromInt $ 26+n) (1,100) reson+ &+&+ controllerExponentialDim (Ctrl.fromInt $ 21+n)+ (DN.frequency 100, DN.frequency 10000)+ (DN.frequency freq))))+ [0..]+ [( 650, 1.00, 30),+ (1080, 0.25, 30),+ (2650, 0.20, 30),+ (2900, 0.16, 30),+ (3250, 0.01, 30)+ ])+ <<<+ MCS.fromChannel (Option.channel opt)+ &+&+ proc (Option.channel opt) (VoiceMsg.toProgram 4) sampleRate
+ alsa/Synthesizer/LLVM/Server/CausalPacked/Test.hs view
@@ -0,0 +1,579 @@+module Synthesizer.LLVM.Server.CausalPacked.Test where++import qualified Synthesizer.LLVM.Server.CausalPacked.InstrumentPlug as InstrFP+import qualified Synthesizer.LLVM.Server.CausalPacked.Instrument as Instr+import qualified Synthesizer.LLVM.Server.SampledSound as Sample+import qualified Synthesizer.LLVM.Server.Option as Option+import Synthesizer.LLVM.Server.CausalPacked.Arrange+ ((&+&), shortTime, controllerExponentialDim, )+import Synthesizer.LLVM.Server.CommonPacked+ (Vector, )+import Synthesizer.LLVM.Server.Common hiding+ (Instrument, )++import qualified Sound.ALSA.Sequencer.Event as Event+-- import qualified Sound.ALSA.Sequencer.Connect as Connect+import qualified Sound.ALSA.Sequencer.Address as Addr+import qualified Synthesizer.MIDI.Generic as Gen++import qualified Synthesizer.LLVM.Frame.StereoInterleaved as StereoInt+import qualified Synthesizer.LLVM.Frame.Stereo as Stereo+import qualified Synthesizer.LLVM.Frame.SerialVector as Serial++import qualified Sound.MIDI.Controller as Ctrl+import qualified Sound.MIDI.Message.Channel.Voice as VoiceMsg++import qualified Synthesizer.CausalIO.Gate as Gate+import qualified Synthesizer.Zip as Zip++import qualified Synthesizer.ALSA.CausalIO.Process as PAlsa+import Synthesizer.MIDI.Storable (Instrument, )++import qualified Synthesizer.MIDI.PiecewiseConstant.ControllerSet as PCS+import qualified Synthesizer.MIDI.CausalIO.ControllerSet as MCS+import qualified Synthesizer.MIDI.CausalIO.Process as MIO+import qualified Synthesizer.CausalIO.Process as PIO++import qualified Synthesizer.LLVM.CausalParameterized.FunctionalPlug as FP+import qualified Synthesizer.LLVM.CausalParameterized.Functional as F+import qualified Synthesizer.LLVM.CausalParameterized.Process as CausalP+import qualified Synthesizer.LLVM.Parameterized.Signal as SigP+import qualified Synthesizer.LLVM.Storable.Process as CausalSt+import qualified Synthesizer.LLVM.Storable.Signal as SigStL+import qualified Synthesizer.LLVM.MIDI.BendModulation as BM+import qualified Synthesizer.LLVM.Wave as Wave+import Synthesizer.LLVM.CausalParameterized.Process (($*), ($<), )++import qualified Synthesizer.Generic.Cut as CutG+import qualified Synthesizer.Storable.Cut as CutSt+import qualified Data.StorableVector.Lazy as SVL+import qualified Data.StorableVector as SV++import qualified Data.EventList.Relative.TimeBody as EventList+import qualified Data.EventList.Relative.TimeTime as EventListTT+import qualified Data.EventList.Relative.TimeMixed as EventListTM+import qualified Data.EventList.Relative.BodyTime as EventListBT++import Control.Arrow ((<<<), (<<^), (^<<), arr, first, )+import Control.Category (id, )+import Control.Applicative (pure, )+import Control.Monad (when, )+import Control.Monad.Trans.State (evalState, )++import qualified Data.Map as Map++-- import qualified Numeric.NonNegative.Class as NonNeg+import qualified Numeric.NonNegative.Wrapper as NonNegW+-- import qualified Numeric.NonNegative.Chunky as NonNegChunky++import qualified Number.DimensionTerm as DN++import Data.Word (Word8, Word32, )+import Data.Int (Int32, )++import Foreign.Storable (Storable, )+import qualified System.IO as IO+import Control.Exception (bracket, )++-- import NumericPrelude.Numeric (zero, round, (^?), )+import Prelude hiding (Real, round, break, id, )+++sampleRate :: Option.SampleRate Real+sampleRate = Option.SampleRate Option.defaultSampleRate++{- |+try to reproduce a space leak+-}+sequencePlain :: IO ()+sequencePlain =+ SVL.writeFile "/tmp/test.f32" $+-- print $ last $ SVL.chunks $+ CutSt.arrange Option.defaultChunkSize $+ evalState (Gen.sequence Option.defaultChannel (error "no sound" :: Instrument Real Real)) $+ let evs = EventList.cons 10 ([]::[Event.T]) evs+ in evs+++-- see playFromEvents+writeTest ::+ (CutG.Read t, Storable a) =>+ PIO.T t (SV.Vector a) -> [t] -> IO ()+writeTest (PIO.Cons next create delete) evsChunky =+ IO.withFile "/tmp/test.f32" IO.WriteMode $ \h ->+ bracket create delete $+ let loop evs s0 =+ case evs of+ [] -> return ()+ chunk : rest -> do+ (pcm, s1) <- next chunk s0+ SV.hPut h pcm+ when+ (CutG.length pcm >= CutG.length chunk)+ (loop rest s1)+ in loop evsChunky++render :: IO ()+render = do+ ping <- Instr.pingRelease $/ 1 $/ 0.1 -- leaky+-- ping <- Instr.ping -- not leaky++ writeTest (ping sampleRate 10 440) $+ replicate 10000 $ Gate.chunk 512 Nothing++sequenceEvents :: [PAlsa.Events] -> IO ()+sequenceEvents evs = do+ arrange <- CausalSt.makeArranger++ ping <- Instr.pingRelease $/ 1 $/ 0.1 -- leaky+-- ping <- Instr.ping -- not leaky++ let proc =+ arrange+ <<<+ arr shortTime+ <<<+ MIO.sequenceCore+ Option.defaultChannel+ (\ _pgm -> ping sampleRate)++ writeTest proc evs++sequenceNothing :: IO ()+sequenceNothing =+ sequenceEvents $+ let evs = EventList.cons 10 [] evs+ in chopEvents 512 $ EventListTM.takeTime (10^(7::Int)) evs+++noteEvent ::+ Event.NoteEv ->+ Word8 ->+ Word8 ->+ Word8 ->+ Event.T+noteEvent mode chan pitch velocity =+ -- Event.simple (Connect.toSubscribers Addr.subscribers) $+ Event.simple Addr.subscribers $ Event.NoteEv mode $+ Event.simpleNote+ (Event.Channel $ fromIntegral chan)+ (Event.Pitch $ fromIntegral pitch)+ (Event.Velocity $ fromIntegral velocity)++ctrlEvent ::+ Word8 ->+ Word32 ->+ Int32 ->+ Event.T+ctrlEvent chan cc cval =+ -- Event.simple (Connect.toSubscribers Addr.subscribers) $+ Event.simple Addr.subscribers $+ Event.CtrlEv Event.Controller $+ Event.Ctrl+ (Event.Channel $ fromIntegral chan)+ (Event.Parameter $ fromIntegral cc)+ (Event.Value $ fromIntegral cval)++sequenceSingleLong :: IO ()+sequenceSingleLong = do+ sequenceEvents $+ let evs = EventList.cons 10 [] evs+ in chopEvents 512 $+ EventListTM.takeTime (10^(7::Int)) $+ EventList.cons 0 [noteEvent Event.NoteOn 0 60 64] evs++sequenceSingleShort :: IO ()+sequenceSingleShort = do+ sequenceEvents $+ let evs = EventList.cons 10 [] evs+ in chopEvents 512 $+ EventListTM.takeTime (10^(7::Int)) $+ EventList.cons 0 [noteEvent Event.NoteOn 0 60 64] $+ EventList.cons 10 [noteEvent Event.NoteOff 0 60 64] evs++{-+Although it consumes constant memory,+the memory usage is quite high,+e.g. 40MB for chunk size 100000 and peiod 1100.+This might be caused by the large overlapping in the release phases.+You need only 6MB heap for the same chunksize and period 11000.+-}+sequenceLoop :: IO ()+sequenceLoop = do+ sequenceEvents $+ let evs =+ EventList.cons 11001+ [noteEvent Event.NoteOff 0 60 50,+ noteEvent Event.NoteOn 0 60 50] evs+ in chopEvents 100000 $+ EventListTM.takeTime (10^(7::Int)) $+ EventList.cons 0 [noteEvent Event.NoteOn 0 60 50] evs++sequenceStaccato :: IO ()+sequenceStaccato = do+ sequenceEvents $+ let evs =+ EventList.cons 551 [noteEvent Event.NoteOff 0 60 50] $+ EventList.cons 550 [noteEvent Event.NoteOn 0 60 50] evs+ in chopEvents 100000 $+ EventListTM.takeTime (10^(7::Int)) $+ EventList.cons 0 [noteEvent Event.NoteOn 0 60 50] evs++++sequenceControlledEvents :: [PAlsa.Events] -> IO ()+sequenceControlledEvents chunkedEvents = do+ opt <- Option.get+ arrange <- CausalSt.makeArranger+ amp <-+ CausalP.processIO+ (CausalP.mapSimple StereoInt.interleave <<<+ CausalP.envelopeStereo <<<+ first (CausalP.mapSimple Serial.upsample))++ ping <- Instr.pingStereoReleaseFM++ let timeControlPercussive =+ controllerExponentialDim Ctrl.attackTime+ (DN.time 0.1, DN.time 2.5) (DN.time 0.8)+ &+&+ controllerExponentialDim Ctrl.releaseTime+ (DN.time 0.03, DN.time 0.3) (DN.time 0.1)++ frequencyControlPercussive =+ MCS.controllerLinear controllerDetune (0,0.005) 0.001+ &+&+ MCS.bendWheelPressure 2 0.04 0.03++ pingProc vel freq =+ ping sampleRate vel freq+ <<<+ Zip.arrowSecond+ (timeControlPercussive+ &+&+ ((MCS.controllerExponential controllerTimbre0 (0.3,10) 0.05+ &+&+ controllerExponentialDim controllerTimbre1+ (DN.time 0.01, DN.time 10) (DN.time 5))+ &+&+ ((MCS.controllerLinear Ctrl.soundController5 (0,10) 2+ &+&+ controllerExponentialDim Ctrl.soundController7+ (DN.time 0.03, DN.time 1) (DN.time 0.5))+ &+&+ frequencyControlPercussive)))++ let proc =+ arr SigStL.unpackStereoStrict+ <<<+ amp ()+ <<<+ (MCS.controllerExponential controllerVolume (0.001, 1) (0.2::Float)+ <<^ Zip.second)+ &+&+ (arrange+ <<<+ arr shortTime+ <<<+ MIO.sequenceModulated+ (Option.channel opt) (\ _pgm -> pingProc))+ <<<+ id &+& MCS.fromChannel (Option.channel opt)++ writeTest proc chunkedEvents+++sequenceControlled :: IO ()+sequenceControlled =+ sequenceControlledEvents $+ let evs = EventList.cons 10 [] evs+ in chopEvents 512 $+ EventListTM.takeTime (10^(7::Int)) $+ EventList.cons 0 [noteEvent Event.NoteOn 0 60 64] evs++sequenceControlledModulated :: IO ()+sequenceControlledModulated =+ sequenceControlledEvents $+ chopEvents 512 $+ EventListTM.takeTime (10^(7::Int)) $+ EventList.cons 0 [noteEvent Event.NoteOn 0 60 64] $+ EventList.fromPairList $+ map (\ev -> (10,[ev])) $ cycle $+ map (ctrlEvent 0 1) [0..127]+++sampledSound :: IO ()+sampledSound = do+ opt <- Option.get++ amp <-+ CausalP.processIO+ (CausalP.mapSimple StereoInt.interleave)++ tomatoSmps <-+ Instr.makeSampledSounds (Option.sampleDirectory opt) Sample.tomatensalat++ let tomato smp vel freq =+ smp sampleRate vel freq+ <<<+ Zip.arrowSecond+ (MCS.controllerLinear controllerDetune (0,0.005) 0.001+ &+&+ MCS.bendWheelPressure 2 0.04 0.03)++ writeTest+ (arr SigStL.unpackStereoStrict+ <<<+ amp ()+ <<<+ tomato (last tomatoSmps) 0 440) $+ map+ (\m ->+ Zip.consChecked "Test.sampledSound"+ (Gate.chunk 512 m)+ (PCS.Cons Map.empty (EventListTT.pause 512))) $+ replicate 10 Nothing +++ Just (100, VoiceMsg.normalVelocity) :+ replicate 4 Nothing++sampledSoundMono :: IO ()+sampledSoundMono = do+ opt <- Option.get++ case Sample.tomatensalat of+ (name, positions, period) -> do+ smp <- Sample.load (Option.sampleDirectory opt ++ "/" ++ name)+ case Sample.parts (Sample.Cons smp (last positions) period) of+ (_attack, _sustain, release) ->+ SVL.writeFile "/tmp/release.f32" release++ tomatoSmps <-+ Instr.makeSampledSoundsMono (Option.sampleDirectory opt) Sample.tomatensalat++ let tomato smp vel freq =+ smp sampleRate vel freq+ <<<+ Zip.arrowSecond (MCS.bendWheelPressure 2 0.04 0.03)++ writeTest (tomato (last tomatoSmps) 0 220) $+ map+ (\m ->+ Zip.consChecked "Test.sampledSound"+ (Gate.chunk 512 m)+ (PCS.Cons Map.empty (EventListTT.pause 512))) $+ replicate 10 Nothing +++ Just (256, VoiceMsg.normalVelocity) :+ replicate 10 Nothing++{-+This one crashes sometimes in LLVM-3.0 when optimizations are enabled.+-}+sampledSoundCrash :: IO ()+sampledSoundCrash = do+ opt <- Option.get++ amp <-+ CausalP.processIO+ (CausalP.mapSimple StereoInt.interleave)++ tomatoSmps <-+ Instr.makeSampledSounds (Option.sampleDirectory opt) Sample.tomatensalat++ let tomato smp vel freq =+ smp sampleRate vel freq+ <<<+ Zip.arrowSecond+ (MCS.controllerLinear controllerDetune (0,0.005) 0.001+ &+&+ MCS.bendWheelPressure 2 0.04 0.03)++ writeTest+ (arr SigStL.unpackStereoStrict+ <<<+ amp ()+ <<<+ tomato (head tomatoSmps) 0 440) $+ map+ (\m ->+ Zip.consChecked "Test.sampledSound"+ (Gate.chunk 512 m)+ (PCS.Cons Map.empty (EventListTT.pause 512))) $+ replicate 10 Nothing +++ Just (100, VoiceMsg.normalVelocity) :+ replicate 10 Nothing+++lfo :: SVL.Vector Real+lfo =+ SigP.renderChunky (SVL.chunkSize 512)+ (1 + 0.1 * SigP.osciSimple Wave.approxSine2 (pure (0::Float)) 0.0001)+ ()++asMono :: vector Real -> vector Real+asMono = id++frequencyModulation :: IO ()+frequencyModulation = do+ opt <- Option.get+ smp <-+ case Sample.tomatensalat of+ (name, _positions, _period) ->+ Sample.load (Option.sampleDirectory opt ++ "/" ++ name)++ SVL.writeFile "/tmp/test.f32" .+ asMono .+ (\f -> f smp lfo) =<<+ CausalP.runStorableChunky+ (CausalP.frequencyModulationLinear $+ SigP.fromStorableVectorLazy id)+++frequencyModulationIO :: IO ()+frequencyModulationIO = do+ opt <- Option.get+ smp <-+ case Sample.tomatensalat of+ (name, _positions, _period) ->+ Sample.load (Option.sampleDirectory opt ++ "/" ++ name)++ proc <-+ CausalP.processIO+ (CausalP.frequencyModulationLinear $+ SigP.fromStorableVectorLazy id)++ writeTest (proc smp :: PIO.T (SV.Vector Real) (SV.Vector Real)) $+ SVL.chunks lfo++frequencyModulationStrictIO :: IO ()+frequencyModulationStrictIO = do+ opt <- Option.get+ smp <-+ case Sample.tomatensalat of+ (name, _positions, _period) ->+ Sample.load (Option.sampleDirectory opt ++ "/" ++ name)++ proc <-+ CausalP.processIO+ (CausalP.frequencyModulationLinear $+ SigP.fromStorableVector id)++ writeTest+ (proc (SV.concat $ SVL.chunks smp) ::+ PIO.T (SV.Vector Real) (SV.Vector Real)) $+ SVL.chunks lfo++frequencyModulationSawIO :: IO ()+frequencyModulationSawIO = do+ proc <-+ CausalP.processIO+ (CausalP.frequencyModulationLinear+ (CausalP.take 50000 $* SigP.osciSaw 0 id))++ writeTest (proc (0.01::Real) :: PIO.T (SV.Vector Real) (SV.Vector Real)) $+ SVL.chunks lfo++envelopeIO :: IO ()+envelopeIO = do+ opt <- Option.get+ smp <-+ case Sample.tomatensalat of+ (name, _positions, _period) ->+ Sample.load (Option.sampleDirectory opt ++ "/" ++ name)++ proc <-+ CausalP.processIO+ (CausalP.envelope $< SigP.fromStorableVectorLazy id)++ writeTest (proc smp :: PIO.T (SV.Vector Real) (SV.Vector Real)) $+ SVL.chunks lfo+++functional :: IO ()+functional = do+ phaser <-+ CausalP.processIO $ F.withArgs $ \ratio ->+ let freq = frequency id+ noise =+ F.lift $ CausalP.fromSignal $+ SigP.noise 12 (recip freq)+ in (1-ratio) * noise ++ ratio * (CausalP.delay (pure (0::Float)) 100 F.$& noise)++ writeTest+ (phaser (sampleRate, 200000) ::+ PIO.T (EventListBT.T NonNegW.Int Float) (SV.Vector Float)) $+ map (\y -> EventListBT.singleton y 10000)+ [0, 0.25, 0.5, 0.75, 1.00]+++functionalPlug :: IO ()+functionalPlug = do+ phaser <-+ FP.withArgs $ \ratio0 ->+ let freq = frequency id+ ratio = FP.plug ratio0+ noise = FP.fromSignal $ SigP.noise 12 (recip freq)+ in (1-ratio) * noise ++ ratio * (CausalP.delay (pure (0::Float)) 100 FP.$& noise)++ writeTest+ (phaser () (sampleRate, 200000) ::+ PIO.T (EventListBT.T NonNegW.Int Float) (SV.Vector Float)) $+ map (\y -> EventListBT.singleton y 10000)+ [0, 0.25, 0.5, 0.75, 1.00]+++makeUnpackStereoStrict ::+ IO (PIO.T (SV.Vector (Stereo.T Vector)) (SV.Vector (Stereo.T Real)))+makeUnpackStereoStrict =+ fmap (\proc -> SigStL.unpackStereoStrict ^<< proc ()) $+ CausalP.processIO+ (CausalP.mapSimple StereoInt.interleave)+{-+makeUnpackStereoStrict ::+ IO (SV.Vector (Stereo.T Vector) -> SV.Vector (Stereo.T Real))+makeUnpackStereoStrict =+ SigStL.makeUnpackGenericStrict+-}++functionalTine :: IO ()+functionalTine = do+ ping <- Instr.tineStereoFM+ unpack <- makeUnpackStereoStrict+ let cs = 512+ writeTest (unpack <<< ping sampleRate 0 440) $+ replicate 100 $+ Zip.Cons+ (Gate.chunk 512 Nothing)+ (Zip.Cons+ (Zip.Cons+ (EventListBT.singleton (DN.time 1) cs)+ (EventListBT.singleton (DN.time 1) cs))+ (Zip.Cons+ (Zip.Cons+ (EventListBT.singleton 2 cs)+ (EventListBT.singleton 1 cs))+ (Zip.Cons+ (EventListBT.singleton 0.001 cs)+ (EventListBT.singleton (BM.Cons 1 0.01) cs))))++functionalPlugTine :: IO ()+functionalPlugTine = do+ ping <- InstrFP.tineStereoFM+ unpack <- makeUnpackStereoStrict+ let cs = 512+ writeTest (unpack <<< ping sampleRate 0 440) $+ replicate 100 $+ Zip.Cons+ (Gate.chunk 512 Nothing)+ (Zip.Cons+ (Zip.Cons+ (EventListBT.singleton (DN.time 1) cs)+ (EventListBT.singleton (DN.time 1) cs))+ (Zip.Cons+ (Zip.Cons+ (EventListBT.singleton 2 cs)+ (EventListBT.singleton 1 cs))+ (Zip.Cons+ (EventListBT.singleton 0.001 cs)+ (EventListBT.singleton (BM.Cons 1 0.01) cs))))
+ alsa/Synthesizer/LLVM/Server/Option.hs view
@@ -0,0 +1,168 @@+module Synthesizer.LLVM.Server.Option (+ T(..),+ get,+ defaultChannel,+ Play.defaultChunkSize,+ defaultSampleRate,+ defaultLatency,+ SampleRate(SampleRate),+ ) where++import Synthesizer.LLVM.Server.Common (SampleRate(SampleRate), )+import qualified Synthesizer.ALSA.Storable.Play as Play+import qualified Data.StorableVector.Lazy as SVL+import Synthesizer.ALSA.EventList (ClientName(ClientName))++import qualified Sound.MIDI.Message.Channel as ChannelMsg++import System.Console.GetOpt+ (getOpt, ArgOrder(..), OptDescr(..), ArgDescr(..), usageInfo, )+import System.Environment (getArgs, getProgName, )+import System.Exit (exitSuccess, exitFailure, )+import qualified System.IO as IO++import Control.Monad (when, )++import Prelude hiding (Real, )+++data T =+ Cons {+ device :: Play.Device,+ clientName :: ClientName,+ channel, extraChannel :: ChannelMsg.Channel,+ sampleDirectory :: FilePath,+ sampleRate :: Maybe (SampleRate Int),+ chunkSize :: SVL.ChunkSize,+ latency :: Int+ }+ deriving (Show)+++deflt :: T+deflt =+ Cons {+ device = Play.defaultDevice,+ clientName = defaultClientName,+ channel = defaultChannel,+ extraChannel = ChannelMsg.toChannel 1,+ sampleDirectory = "speech",+ sampleRate = Nothing,+ chunkSize = Play.defaultChunkSize,+ latency = defaultLatency+ }++defaultClientName :: ClientName+defaultClientName =+ ClientName "Haskell-LLVM-Synthesizer"++defaultChannel :: ChannelMsg.Channel+defaultChannel = ChannelMsg.toChannel 0++defaultSampleRate :: Num a => a+-- defaultSampleRate = 24000+-- defaultSampleRate = 48000+defaultSampleRate = 44100++defaultLatency :: Int+defaultLatency =+ -- 0+ -- 256+ 1024++++exitFailureMsg :: String -> IO a+exitFailureMsg msg =+ IO.hPutStrLn IO.stderr msg >> exitFailure++parseChannel :: String -> IO ChannelMsg.Channel+parseChannel str =+ case reads str of+ [(chan, "")] ->+ if 0<=chan && chan<16+ then return $ ChannelMsg.toChannel chan+ else exitFailureMsg "MIDI channel must a number from 0..15"+ _ ->+ exitFailureMsg $ "channel must be a number, but is '" ++ str ++ "'"++parseNumber ::+ (Read a) =>+ String -> (a -> Bool) -> String -> String -> IO a+parseNumber name constraint constraintName str =+ case reads str of+ [(n, "")] ->+ if constraint n+ then return n+ else exitFailureMsg $ name ++ " must be a " ++ constraintName ++ " number"+ _ ->+ exitFailureMsg $ name ++ " must be a number, but is '" ++ str ++ "'"++maxInt :: Integer+maxInt =+ fromIntegral (maxBound :: Int)+++{-+Guide for common Linux/Unix command-line options:+ http://www.faqs.org/docs/artu/ch10s05.html+-}+description :: [OptDescr (T -> IO T)]+description =+ Option ['h'] ["help"]+ (NoArg $ \ _flags -> do+ programName <- getProgName+ putStrLn+ (usageInfo ("Usage: " ++ programName ++ " [OPTIONS]") description)+ exitSuccess)+ "show options" :+ Option ['d'] ["device"]+ (flip ReqArg "NAME" $ \str flags ->+ return $ flags{device = str})+ "select ALSA output device" :+ Option [] ["clientname"]+ (flip ReqArg "NAME" $ \str flags ->+ return $ flags{clientName = ClientName str})+ "name of the ALSA client" :+ Option ['r'] ["samplerate"]+ (flip ReqArg "RATE" $ \str flags ->+ fmap (\rate -> flags{sampleRate = Just $ SampleRate $ fromInteger rate}) $+ parseNumber "sample-rate" (\n -> 0<n && n<=maxInt) "positive" str)+ "sample-rate in samples per second" :+ Option ['b'] ["blocksize"]+ (flip ReqArg "SIZE" $ \str flags ->+ fmap (\size -> flags{chunkSize = SVL.ChunkSize $ fromInteger size}) $+ parseNumber "blocksize" (\n -> 0<n && n<=maxInt) "positive" str)+ "block size as number of sample-frames" :+ Option [] ["latency"]+ (flip ReqArg "SIZE" $ \str flags ->+ fmap (\size -> flags{latency = fromInteger size}) $+ parseNumber "latency" (\n -> 0<=n && n<=maxInt) "non-negative" str)+ "latency as number of sample-frames" :+ Option ['c'] ["channel"]+ (flip ReqArg "CHANNEL" $ \str flags ->+ fmap (\chan -> flags{channel = chan}) $+ parseChannel str)+ "select MIDI input channel (0-based)" :+ Option [] ["extra-channel"]+ (flip ReqArg "CHANNEL" $ \str flags ->+ fmap (\chan -> flags{extraChannel = chan}) $+ parseChannel str)+ "select MIDI channel with effects" :+ Option ['I'] ["sample-directory"]+ (flip ReqArg "DIR" $ \str flags ->+ return $ flags{sampleDirectory = str})+ "directory for sound samples" :+ []+++get :: IO T+get = do+ argv <- getArgs+ let (opts, files, errors) = getOpt RequireOrder description argv+ when (not $ null errors) $+ exitFailureMsg (init (concat errors))+ when (not $ null files) $+ exitFailureMsg $+ "Do not know what to do with arguments " ++ show files+ foldl (>>=) (return deflt) opts
+ alsa/Synthesizer/LLVM/Server/Packed/Run.hs view
@@ -0,0 +1,493 @@+module Synthesizer.LLVM.Server.Packed.Run where++import qualified Synthesizer.LLVM.Server.Packed.Instrument as Instr+import qualified Synthesizer.LLVM.Server.SampledSound as Sample+import qualified Synthesizer.LLVM.Server.Option as Option+import Synthesizer.LLVM.Server.ALSA (Output, play, startMessage, )+import Synthesizer.LLVM.Server.CommonPacked+ (Vector, VectorSize, vectorSize, stair, )+import Synthesizer.LLVM.Server.Common++import qualified Synthesizer.ALSA.EventList as Ev+import qualified Sound.ALSA.Sequencer.Event as Event++import qualified Synthesizer.MIDI.EventList as MidiEv+import qualified Synthesizer.MIDI.PiecewiseConstant as PC+import qualified Synthesizer.MIDI.PiecewiseConstant.ControllerSet as PCS+import qualified Synthesizer.MIDI.Generic 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 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, )+import Control.Applicative (pure, {- liftA, liftA2, -} liftA3, (<*>), )+import Control.Monad.Trans.State (evalState, )++import Control.Exception (bracket, )++{-+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, (^?), (+), )+import Prelude hiding (Real, break, (+), )++++{-# INLINE withMIDIEventsMono #-}+withMIDIEventsMono ::+ Option.T ->+ Output handle (SigSt.T Real) a ->+ (SigSt.ChunkSize -> SampleRate Real ->+ EventList.T Ev.StrictTime [Event.T] -> SigSt.T Vector) -> IO a+withMIDIEventsMono opt output process = do+ putStrLn startMessage+ case output opt of+ (open,close,write) ->+ bracket open (close . snd) $ \((chunkSize,rate),h) ->+ let rrate = fromIntegral rate :: Double+ in Ev.withMIDIEvents+ (Option.clientName opt)+ (fromIntegral chunkSize / rrate)+ (rrate / fromIntegral vectorSize)+ (write h .+ SigStL.unpack .+ process (SigSt.chunkSize $ divUp chunkSize vectorSize)+ (Option.SampleRate $ fromIntegral rate))++type StereoVector = StereoInt.T VectorSize Real++{-# INLINE withMIDIEventsStereo #-}+withMIDIEventsStereo ::+ Option.T ->+ Output handle (SigSt.T (Stereo.T Real)) a ->+ (SigSt.ChunkSize -> SampleRate Real ->+ EventList.T Ev.StrictTime [Event.T] -> SigSt.T StereoVector) ->+ IO a+withMIDIEventsStereo opt output process = do+ putStrLn startMessage+ case output opt of+ (open,close,write) ->+ bracket open (close . snd) $ \((chunkSize,rate),h) ->+ let rrate = fromIntegral rate :: Double+ in Ev.withMIDIEvents+ (Option.clientName opt)+ (fromIntegral chunkSize / rrate)+ (rrate / fromIntegral vectorSize)+ (write h .+ SigStL.unpackStereo .+ process (SigSt.chunkSize $ divUp chunkSize vectorSize)+ (Option.SampleRate $ fromIntegral rate))+++frequencyModulation :: IO ()+frequencyModulation = do+ opt <- Option.get+ osc <-+ SigP.runChunky+ ((CausalPS.osciSimple WaveL.triangle $< zero)+ $* Instr.frequencyFromBendModulation+ (frequencyConst 10)+ (Instr.modulation (\fm -> (fm,880))))+ withMIDIEventsMono opt play $ \vectorChunkSize sampleRate ->+ osc vectorChunkSize . (,) sampleRate .+ 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+ amp <- CausalP.runStorableChunky (CausalPS.amplify (arr id))+ arrange <- SigStL.makeArranger+ withMIDIEventsMono opt play $ \vectorChunkSize sampleRate ->+ (amp :: Real -> SigSt.T Vector -> SigSt.T Vector) 0.2 .+ arrange vectorChunkSize .+ evalState+ (Gen.sequence (Option.channel opt) $+ sound vectorChunkSize sampleRate)++keyboardStereo :: IO ()+keyboardStereo = do+ opt <- Option.get+ sound <- Instr.pingStereoRelease $/ 0.4 $/ 0.1+ amp <-+ CausalP.runStorableChunky+ (CausalP.mapSimple StereoInt.interleave <<<+ CausalPS.amplifyStereo (arr id))+ arrange <- SigStL.makeArranger+ withMIDIEventsStereo opt play $ \vectorChunkSize sampleRate ->+ (amp :: Real -> SigSt.T (Stereo.T Vector) -> SigSt.T StereoVector) 0.2 .+ arrange vectorChunkSize .+ evalState+ (Gen.sequence (Option.channel opt) $+ sound vectorChunkSize sampleRate)++keyboardFM :: IO ()+keyboardFM = do+ opt <- Option.get+ str <- Instr.softStringFM+ amp <-+ CausalP.runStorableChunky+ (CausalP.mapSimple StereoInt.interleave <<<+ CausalPS.amplifyStereo (arr id))+ arrange <- SigStL.makeArranger+ withMIDIEventsStereo opt play $ \vectorChunkSize sampleRate ->+ (amp :: Real -> SigSt.T (Stereo.T Vector) -> SigSt.T StereoVector) 0.2 .+ arrange vectorChunkSize .+ evalState+ (do fm <- PC.bendWheelPressure (Option.channel opt) 2 0.04 0.03+ Gen.sequenceModulated+ fm (Option.channel opt) (flip str sampleRate))++keyboardFMMulti :: IO ()+keyboardFMMulti = do+ opt <- Option.get+ str <- Instr.softStringFM+ tin <- Instr.tineStereoFM $/ 0.4 $/ 0.1+ amp <-+ CausalP.runStorableChunky+ (CausalP.mapSimple StereoInt.interleave <<<+ CausalPS.amplifyStereo (arr id))+ arrange <- SigStL.makeArranger+ withMIDIEventsStereo opt play $ \vectorChunkSize sampleRate ->+ (amp :: Real -> SigSt.T (Stereo.T Vector) -> SigSt.T StereoVector) 0.2 .+ arrange vectorChunkSize .+ 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 $ sampleRate)+ [str, tin vectorChunkSize]))++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 ->+ IO (ChannelMsg.Channel -> VoiceMsg.Program ->+ SVL.ChunkSize -> SampleRate Real ->+ MidiEv.Filter Event.T (SigSt.T StereoVector))+keyboardDetuneFMCore smpDir = 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 Sample.tomatensalat+ hal0 <- Instr.makeSampledSounds smpDir Sample.hal+ grp0 <- Instr.makeSampledSounds smpDir Sample.graphentheorie+++ arrange <- SigStL.makeArranger+ amp <-+ CausalP.runStorableChunky+ (CausalP.mapSimple StereoInt.interleave <<<+ CausalP.envelopeStereo $<+ Instr.piecewiseConstantVector (arr id))+ return $ \chan pgm vcsize sr -> do+ 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)+++ 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)+ withMIDIEventsStereo opt play $ \vectorChunkSize sampleRate ->+ evalState (proc (Option.channel opt) (VoiceMsg.toProgram 0) vectorChunkSize sampleRate)++keyboardFilter :: IO ()+keyboardFilter = do+ opt <- Option.get+ proc <- keyboardDetuneFMCore (Option.sampleDirectory opt)+ mix <- CausalP.runStorableChunky $+ arr id+ ++ (CausalP.mapSimple (StereoInt.amplify 0.5)+ <<<+ CausalP.fromSignal (SigP.fromStorableVectorLazy (arr id)))++ lowpass0 <-+ CausalP.runStorableChunky $+ CausalP.mapSimple StereoInt.interleave+ <<<+-- 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 ::+ Option.SampleRate Real -> PC.T Real -> PC.T Real ->+ SigSt.T StereoVector -> SigSt.T StereoVector+ lowpass (Option.SampleRate sr) resons freqs =+ lowpass0 $ fmap UniFilter.parameter $+ PC.zipWith FiltR.Pole resons $ fmap (/ sr) freqs++ withMIDIEventsStereo opt play $ \vectorChunkSize sampleRate ->+ 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)+ vectorChunkSize sampleRate+ pureMusic <-+ proc (Option.channel opt) (VoiceMsg.toProgram 0)+ vectorChunkSize sampleRate+ return+ (pureMusic `mix`+ lowpass sampleRate resonance freq filterMusic))
+ alsa/Synthesizer/LLVM/Server/Packed/Test.hs view
@@ -0,0 +1,697 @@+module Synthesizer.LLVM.Server.Packed.Test where++import qualified Synthesizer.LLVM.Server.Packed.Instrument as Instr+import qualified Synthesizer.LLVM.Server.Option as Option+import qualified Synthesizer.LLVM.Server.SampledSound as Sample+import Synthesizer.LLVM.Server.ALSA (makeNote, )+import Synthesizer.LLVM.Server.CommonPacked+ (Vector, vectorSize, )+import Synthesizer.LLVM.Server.Common hiding+ (Instrument, )++import qualified Sound.ALSA.Sequencer.Event as Event+import qualified Synthesizer.MIDI.PiecewiseConstant as PC+import qualified Synthesizer.MIDI.Generic as Gen++import qualified Synthesizer.LLVM.Frame.Stereo as Stereo+import qualified Synthesizer.LLVM.Frame.SerialVector as Serial++import qualified Synthesizer.ALSA.Storable.Play as Play+import Synthesizer.MIDI.Storable (Instrument, chunkSizesFromLazyTime, )++import qualified Synthesizer.LLVM.MIDI.BendModulation as BM+import qualified Synthesizer.LLVM.CausalParameterized.ProcessPacked as CausalPS+import qualified Synthesizer.LLVM.Parameterized.SignalPacked as SigPS+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 Synthesizer.LLVM.CausalParameterized.Process (($*), )++import qualified Synthesizer.Storable.Cut as CutSt+import qualified Synthesizer.Storable.Signal as SigSt+import qualified Data.StorableVector.Lazy.Pattern as SVP+import qualified Data.StorableVector.Lazy as SVL+-- import qualified Data.StorableVector as SV++import qualified Data.EventList.Relative.TimeBody as EventList+import qualified Data.EventList.Relative.BodyTime as EventListBT++import Control.Arrow ((<<<), arr, )+import Control.Applicative (pure, liftA, liftA2, )+import Control.Monad.Trans.State (evalState, )++{-+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 qualified Algebra.RealRing as RealRing+import qualified Algebra.Additive as Additive+-}++-- import NumericPrelude.Numeric (zero, round, (^?), )+import Prelude hiding (Real, round, break, )+++vectorChunkSize :: SVL.ChunkSize+vectorChunkSize =+ case Play.defaultChunkSize of+ SVL.ChunkSize size ->+ SVL.ChunkSize (divUp size vectorSize)++sampleRatePlain :: Num a => a+sampleRatePlain = Option.defaultSampleRate++sampleRate :: Option.SampleRate Real+sampleRate = Option.SampleRate Option.defaultSampleRate+++emptyEvents :: time -> EventList.T time [Event.T]+emptyEvents t =+ let evs = EventList.cons t [] evs+ in evs+++{- |+try to reproduce a space leak+-}+sequencePlain :: IO ()+sequencePlain =+ SVL.writeFile "test.f32" $+-- print $ last $ SVL.chunks $+ CutSt.arrange Option.defaultChunkSize $+ evalState (Gen.sequence Option.defaultChannel (error "no sound" :: Instrument Real Real)) $+ emptyEvents 10++sequenceLLVM :: IO ()+sequenceLLVM = do+ arrange <- SigStL.makeArranger+ SVL.writeFile "test.f32" $+-- print $ last $ SVL.chunks $+ arrange vectorChunkSize $+ evalState (Gen.sequence Option.defaultChannel (error "no sound" :: Instrument Real Vector)) $+ emptyEvents 10++sequencePitchBendCycle :: IO ()+sequencePitchBendCycle = do+ arrange <- SigStL.makeArranger+ SVL.writeFile "test.f32" $+ arrange vectorChunkSize $+ evalState+ (let -- fm = error "undefined pitch bend"+ fm = EventListBT.cons 1 10 fm+ in Gen.sequenceModulated fm Option.defaultChannel+ (error "no sound" ::+ PC.T Real -> Instrument Real Vector)) $+ emptyEvents 10++sequencePitchBendSimple :: IO ()+sequencePitchBendSimple = do+ arrange <- SigStL.makeArranger+ SVL.writeFile "test.f32" $+ arrange vectorChunkSize $+ evalState+ (let fm y = EventListBT.cons y 10 (fm (2-y))+ in Gen.sequenceModulated (fm 1) Option.defaultChannel+ (error "no sound" ::+ PC.T Real -> Instrument Real Vector)) $+ emptyEvents 10++sequencePitchBend :: IO ()+sequencePitchBend = do+ arrange <- SigStL.makeArranger+ SVL.writeFile "test.f32" $+ arrange vectorChunkSize $+ evalState+ (do fm <- PC.pitchBend Option.defaultChannel 2 0.01+ Gen.sequenceModulated fm Option.defaultChannel+ (error "no sound" ::+ PC.T Real -> Instrument Real Vector)) $+ emptyEvents 10++sequenceModulated :: IO ()+sequenceModulated = do+ arrange <- SigStL.makeArranger+ SVL.writeFile "test.f32" $+ arrange vectorChunkSize $+ evalState+ (do fm <- PC.bendWheelPressure Option.defaultChannel 2 0.04 0.03+ Gen.sequenceModulated fm Option.defaultChannel+ (error "no sound" ::+ PC.T (BM.T Real) ->+ Instrument Real Vector)) $+ emptyEvents 10++sequenceModulatedLong :: IO ()+sequenceModulatedLong = do+ arrange <- SigStL.makeArranger+-- sound <- Instr.softStringReleaseEnvelope $/ sampleRate+ sound <- Instr.softString $/ sampleRate -- space leak+-- sound <- Instr.pingReleaseEnvelope $/ 1 $/ sampleRate -- no space leak+-- sound <- Instr.pingRelease $/ 1 $/ 1 $/ sampleRate -- no space leak+ SVL.writeFile "test.f32" $+ arrange vectorChunkSize $+ evalState (Gen.sequence Option.defaultChannel sound) $+ let evs t = EventList.cons t [] (evs (20-t))+ in EventList.cons 10 [makeNote Event.NoteOn 60] $+ EventList.cons 10 [makeNote Event.NoteOn 64] $+ evs 10++sequenceModulatedLongFM :: IO ()+sequenceModulatedLongFM = do+ arrange <- SigStL.makeArranger+ sound <- Instr.softStringFM+ SVL.writeFile "test.f32" $+ arrange vectorChunkSize $+ evalState+ (do fm <- PC.bendWheelPressure Option.defaultChannel 2 0.04 0.03+ Gen.sequenceModulated fm Option.defaultChannel+ (\fmlocal -> sound fmlocal $ sampleRate)) $+ let evs t = EventList.cons t [] (evs (20-t))+ in EventList.cons 10 [makeNote Event.NoteOn 60] $+ EventList.cons 10 [makeNote Event.NoteOn 64] $+ evs 10++sequenceModulatedRepeat :: IO ()+sequenceModulatedRepeat = do+ arrange <- SigStL.makeArranger+ sound <- Instr.softStringFM+ SVL.writeFile "test.f32" $+ arrange vectorChunkSize $+ evalState+ (do fm <- PC.bendWheelPressure Option.defaultChannel 2 0.04 0.03+ Gen.sequenceModulated fm Option.defaultChannel+ (\fmlocal -> sound fmlocal $ sampleRate)) $+ let evs t =+ EventList.cons t [makeNote Event.NoteOn 60] $+ EventList.cons t [makeNote Event.NoteOff 60] $+ evs (20-t)+ in evs 10++sequencePress :: IO ()+sequencePress = do+ arrange <- SigStL.makeArranger+-- sound <- Instr.softString $/ sampleRate+-- sound <- Instr.softStringReleaseEnvelope $/ sampleRate+ sound <- Instr.pingReleaseEnvelope $/ 1 $/ 1 $/ vectorChunkSize $/ sampleRate+ SVL.writeFile "test.f32" $+ arrange vectorChunkSize $+ evalState+ (Gen.sequence Option.defaultChannel (\ _freq -> sound)) $+ let evs t =+ EventList.cons t [makeNote Event.NoteOn 60] $+ EventList.cons t [makeNote Event.NoteOff 60] $+ evs (20-t)+ in evs 10+++sampledSoundTest0 ::+ IO (Sample.T ->+ PC.T (BM.T Real) ->+ Instrument Real (Stereo.T Vector))+sampledSoundTest0 =+ liftA+ (\osc smp _fm _vel _freq _dur ->+ osc Option.defaultChunkSize (Sample.body smp))+ (SigP.runChunky+ (let smp = arr id+ in fmap (\x -> Stereo.cons x x) $+ SigPS.pack $+ SigP.fromStorableVectorLazy smp))++sampledSoundTest1 ::+ IO (Sample.T ->+ PC.T (BM.T Real) ->+ Instrument Real (Stereo.T Vector))+sampledSoundTest1 =+ liftA+ (\osc smp _fm _vel _freq _dur ->+ osc Option.defaultChunkSize (Sample.body smp))+ (SigP.runChunky+ (let smp = arr id+ in CausalP.stereoFromMono+ (CausalPS.pack+ (CausalP.frequencyModulationLinear+ (SigP.fromStorableVectorLazy smp)))+ $* liftA2 Stereo.cons+ (SigPS.constant 0.999)+ (SigPS.constant 1.001)))+-- $* (SigPS.constant $# Stereo.cons 0.999 1.001)))++sampledSoundTest2 ::+ IO (Sample.T ->+ PC.T (BM.T Real) ->+ Instrument Real (Stereo.T Vector))+sampledSoundTest2 =+ liftA+ (\osc smp fm _vel freq dur ->+ let pos = Sample.positions smp+ body =+ SigSt.take (Sample.length pos) $+ SigSt.drop (Sample.start pos) $+ Sample.body smp+ in SVP.take (chunkSizesFromLazyTime dur) $+ osc Option.defaultChunkSize+ (sampleRate, (body, (fm, freq * Sample.period smp))))+ (SigP.runChunky+ (let smp = signal fst+ fm = Instr.modulation snd+ in (CausalP.stereoFromMono+ (CausalPS.pack+ (CausalP.frequencyModulationLinear+ (SigP.fromStorableVectorLazy smp)))+ <<<+ liftA2 Stereo.cons+ (CausalPS.amplify 0.999)+ (CausalPS.amplify 1.001))+ $* Instr.frequencyFromBendModulation (frequencyConst 3) fm))++sampledSoundTest3SpaceLeak ::+ IO (Sample.T ->+ PC.T (BM.T Real) ->+ Instrument Real (Stereo.T Vector))+sampledSoundTest3SpaceLeak =+ liftA+ (\osc smp _fm vel freq dur ->+ {-+ We split the frequency modulation signal+ in order to get a smooth frequency modulation curve.+ Without (periodic) frequency modulation+ we could just split the piecewise constant control curve @fm@.+ -}+ let (sustainFM, releaseFM) =+ SVP.splitAt (chunkSizesFromLazyTime dur) $+ (SigSt.repeat Option.defaultChunkSize+ (Serial.fromList [freq*Sample.period smp/sampleRatePlain])+ :: SigSt.T Vector)+ pos = Sample.positions smp+ amp = 2 * amplitudeFromVelocity vel+ (attack, sustain, release) = Sample.parts smp+ in osc+ (amp,+ attack `SigSt.append`+ SVL.cycle (SigSt.take (Sample.loopLength pos) sustain))+ sustainFM+ `SigSt.append`+ osc (amp,release) releaseFM)+ (CausalP.runStorableChunky+ (let smp = arr snd+ amp = arr fst+ in CausalPS.amplifyStereo amp+ <<<+ CausalP.stereoFromMono+ (CausalPS.pack+ (CausalP.frequencyModulationLinear+ (SigP.fromStorableVectorLazy smp)))+ <<<+ liftA2 Stereo.cons+ (CausalPS.amplify 0.999)+ (CausalPS.amplify 1.001)))++sampledSoundTest4NoSpaceLeak ::+ IO (Sample.T ->+ PC.T (BM.T Real) ->+ Instrument Real (Stereo.T Vector))+sampledSoundTest4NoSpaceLeak =+ liftA+ (\freqMod smp fm _vel freq dur ->+ {-+ We split the frequency modulation signal+ in order to get a smooth frequency modulation curve.+ Without (periodic) frequency modulation+ we could just split the piecewise constant control curve @fm@.+ -}+ let (sustainFM, releaseFM) =+ SVP.splitAt (chunkSizesFromLazyTime dur) $+ (freqMod+ (chunkSizesFromLazyTime (PC.duration fm))+ (sampleRate, (fm, freq*Sample.period smp)) :: SigSt.T Vector)+ in SigSt.map+ (\x -> Stereo.cons x x)+ (sustainFM `SigSt.append` releaseFM))+ (SigP.runChunkyPattern+ (Instr.frequencyFromBendModulation+ (frequencyConst 3) (Instr.modulation id)))++sampledSoundTest5LargeSpaceLeak ::+ IO (Sample.T ->+ PC.T (BM.T Real) ->+ Instrument Real (Stereo.T Vector))+sampledSoundTest5LargeSpaceLeak =+ liftA2+ (\osc freqMod smp fm vel freq dur ->+ {-+ We split the frequency modulation signal+ in order to get a smooth frequency modulation curve.+ Without (periodic) frequency modulation+ we could just split the piecewise constant control curve @fm@.+ -}+ let (sustainFM, releaseFM) =+ SVP.splitAt (chunkSizesFromLazyTime dur) $+ (freqMod+ (chunkSizesFromLazyTime (PC.duration fm))+ (sampleRate, (fm, freq*Sample.period smp)) :: SigSt.T Vector)+ pos = Sample.positions smp+ amp = 2 * amplitudeFromVelocity vel+ (attack, sustain, release) = Sample.parts smp+ in osc+ (amp,+ attack `SigSt.append`+ SVL.cycle (SigSt.take (Sample.loopLength pos) sustain))+ sustainFM+ `SigSt.append`+ osc (amp,release) releaseFM)+ (CausalP.runStorableChunky+ (arr (\x -> Stereo.cons x x)))+ (SigP.runChunkyPattern+ (Instr.frequencyFromBendModulation+ (frequencyConst 3) (Instr.modulation id)))+++sampledSoundSmallSpaceLeak4 ::+ IO (Sample.T ->+ PC.T (BM.T Real) ->+ Instrument Real (Stereo.T Vector))+sampledSoundSmallSpaceLeak4 =+ liftA+ (\osc smp _fm _vel freq dur ->+ let (sustainFM, releaseFM) =+ SVP.splitAt (chunkSizesFromLazyTime dur) $+ (SigSt.repeat Option.defaultChunkSize+ (Serial.fromList [freq*Sample.period smp/sampleRatePlain])+ :: SigSt.T Vector)+ in osc () sustainFM+ `SigSt.append`+ SigSt.map (\x -> Stereo.cons x x) releaseFM)+ (CausalP.runStorableChunky+ (arr (\x -> Stereo.cons x x)))++sampledSoundSmallSpaceLeak4a ::+ IO (Sample.T ->+ PC.T (BM.T Real) ->+ Instrument Real (Stereo.T Vector))+sampledSoundSmallSpaceLeak4a =+ liftA+ (\osc smp _fm _vel freq dur ->+ case SVP.splitAt (chunkSizesFromLazyTime dur) $+ (SigSt.repeat Option.defaultChunkSize+ (Serial.fromList [freq*Sample.period smp/sampleRatePlain])+ :: SigSt.T Vector) of+ (sustainFM, releaseFM) ->+ osc () sustainFM+ `SigSt.append`+ SigSt.map (\x -> Stereo.cons x x) releaseFM)+ (CausalP.runStorableChunky+ (arr (\x -> Stereo.cons x x)))++sampledSoundNoSmallSpaceLeak3 ::+ IO (Sample.T ->+ PC.T (BM.T Real) ->+ Instrument Real (Stereo.T Vector))+sampledSoundNoSmallSpaceLeak3 =+ pure+ (\smp _fm _vel freq dur ->+ let (sustainFM, releaseFM) =+ SVP.splitAt (chunkSizesFromLazyTime dur) $+ (SigSt.repeat Option.defaultChunkSize+ (Serial.fromList [freq*Sample.period smp/sampleRatePlain])+ :: SigSt.T Vector)+ in SigSt.map (\x -> Stereo.cons x x) sustainFM+ `SigSt.append`+ SigSt.map (\x -> Stereo.cons x x) releaseFM)++{-# NOINLINE amplifySVL #-}+amplifySVL :: SVL.Vector Vector -> SVL.Vector Vector+amplifySVL = SigSt.map (2*)++sampledSoundNoSmallSpaceLeak2 ::+ IO (Sample.T ->+ PC.T (BM.T Real) ->+ Instrument Real (Stereo.T Vector))+sampledSoundNoSmallSpaceLeak2 =+ liftA+ (\osc smp _fm _vel freq dur ->+ let (sustainFM, releaseFM) =+ SVP.splitAt (chunkSizesFromLazyTime dur) $+ (SigSt.repeat Option.defaultChunkSize+ (Serial.fromList [freq*Sample.period smp/sampleRatePlain])+ :: SigSt.T Vector)+ in osc ()+ (amplifySVL sustainFM+ `SigSt.append`+ amplifySVL releaseFM))+ (CausalP.runStorableChunky+ (arr (\x -> Stereo.cons x x)))++sampledSoundSmallSpaceLeak1 ::+ IO (Sample.T ->+ PC.T (BM.T Real) ->+ Instrument Real (Stereo.T Vector))+sampledSoundSmallSpaceLeak1 =+ liftA+ (\osc smp _fm _vel freq dur ->+ let (sustainFM, releaseFM) =+ SVP.splitAt (chunkSizesFromLazyTime dur) $+ (SigSt.repeat Option.defaultChunkSize+ (Serial.fromList [freq*Sample.period smp/sampleRatePlain])+ :: SigSt.T Vector)+ in osc () sustainFM+ `SigSt.append`+ osc () releaseFM)+ (CausalP.runStorableChunky+ (arr (\x -> Stereo.cons x x)))++sampledSoundSmallSpaceLeak0 ::+ IO (Sample.T ->+ PC.T (BM.T Real) ->+ Instrument Real (Stereo.T Vector))+sampledSoundSmallSpaceLeak0 =+ liftA+ (\osc smp _fm vel freq dur ->+ {-+ We split the frequency modulation signal+ in order to get a smooth frequency modulation curve.+ Without (periodic) frequency modulation+ we could just split the piecewise constant control curve @fm@.+ -}+ let (sustainFM, releaseFM) =+ SVP.splitAt (chunkSizesFromLazyTime dur) $+ (SigSt.repeat Option.defaultChunkSize+ (Serial.fromList [freq*Sample.period smp/sampleRatePlain])+ :: SigSt.T Vector)+ pos = Sample.positions smp+ amp = 2 * amplitudeFromVelocity vel+ (attack, sustain, release) = Sample.parts smp+ in osc+ (amp,+ attack `SigSt.append`+ SVL.cycle (SigSt.take (Sample.loopLength pos) sustain))+ sustainFM+ `SigSt.append`+ osc (amp,release) releaseFM)+ (CausalP.runStorableChunky+ (arr (\x -> Stereo.cons x x)))++++sequenceSample :: IO ()+sequenceSample = do+ arrange <- SigStL.makeArranger+ sampler <- sampledSoundTest2+ let sound =+ sampler (Sample.Cons (SigSt.replicate Option.defaultChunkSize 100000 0)+ (Sample.Positions 0 100000 50000 50000)+ 100)+ SVL.writeFile "test.f32" $+ arrange vectorChunkSize $+ evalState+ (do fm <- PC.bendWheelPressure Option.defaultChannel 2 0.04 0.03+ Gen.sequenceModulated fm Option.defaultChannel sound) $+ let evs t = EventList.cons t [] (evs (20-t))+ in EventList.cons 10 [makeNote Event.NoteOn 60] $+ evs 10++{-+sequenceSample1 :: IO ()+sequenceSample1 = do+ sampler <- Instr.sampledSound+ let sound =+ sampler (SampledSound (SigSt.replicate Option.defaultChunkSize 100000 0)+ (SamplePositions 0 100000 50000 50000)+ 100)+ SVL.writeFile "test.f32" $+ sound+{-+ (let evs f =+ EventListBT.cons (BM.Cons 0.001 f) 10 (evs (0.02-f))+ in evs 0.01)+-}+ (let evs t =+ EventListBT.cons (BM.Cons 0.01 0.001) t (evs (20-t))+ in evs 10)+{-+ (PCS.Cons+ (Map.singleton+ (PC.Controller VoiceMsg.modulation) 1)+ (let evs t = EventList.cons t [] (evs (20-t))+ in EventListMT.consTime 10 $ evs 10))+-}+ 0.01 1+-- (NonNegChunky.fromChunks $ repeat $ NonNegW.fromNumber 10)+ (NonNegChunky.fromChunks $ map NonNegW.fromNumber $ iterate (20-) 10)+-}++sequenceSample1 :: IO ()+sequenceSample1 = do+ sampler <- sampledSoundSmallSpaceLeak4a+ let sound =+ sampler (Sample.Cons (SigSt.replicate Option.defaultChunkSize 100000 0)+ (Sample.Positions 0 100000 50000 50000)+ 100)+ SVL.writeFile "test.f32" $+ sound+ (let evs = EventListBT.cons (BM.Cons 0.01 0.001) 1 evs+ in evs)+ 0.01 1+ (NonNegChunky.fromChunks $ repeat $ NonNegW.fromNumber 10)++{-+sequenceSample1a :: IO ()+sequenceSample1a = do+{-+ makeStereoLLVM <-+ CausalP.runStorableChunky2 -- NoSpaceLeak+ (arr (\x -> Stereo.cons x x))+ let stereoLLVM = makeStereoLLVM ()+-}+ stereoLLVM <- CausalP.runStorableChunky3+ let stereoPlain = SigSt.map (\x -> Stereo.cons x x)+ SVL.writeFile "test.f32" $+ let dur = NonNegChunky.fromChunks $ repeat $ SVL.chunkSize 10+ !(sustainFM, releaseFM) =+ SVP.splitAt dur $+ (SigSt.repeat Option.defaultChunkSize (Serial.fromList [1])+ :: SigSt.T Vector)+ in case 3::Int of+ -- no leak+ 0 -> stereoLLVM $ sustainFM `SigSt.append` releaseFM+ -- no leak+ 1 -> stereoPlain $ sustainFM `SigSt.append` releaseFM+ -- no leak+ 2 -> stereoPlain sustainFM `SigSt.append` stereoPlain releaseFM+ -- leak+ 3 -> stereoLLVM sustainFM `SigSt.append` stereoPlain releaseFM+ -- no leak+ 4 -> stereoPlain sustainFM `SigSt.append` stereoLLVM releaseFM+ -- leak+ 5 -> stereoLLVM sustainFM `SigSt.append` stereoLLVM releaseFM+-}++sequenceSample2 :: IO ()+sequenceSample2 = do+ arrange <- SigStL.makeArranger+ sampler <- sampledSoundTest2+ let sound =+ sampler (Sample.Cons (SigSt.replicate Option.defaultChunkSize 100000 0)+ (Sample.Positions 0 100000 50000 50000)+ 100)+ SVL.writeFile "test.f32" $+ arrange vectorChunkSize $+ evalState+ (do bend <- PC.pitchBend Option.defaultChannel 2 0.01+ let fm = fmap (\t -> BM.Cons t t) bend+ Gen.sequenceModulated fm Option.defaultChannel sound) $+ let evs t = EventList.cons t [] (evs (20-t))+ in EventList.cons 10 [makeNote Event.NoteOn 60] $+ evs 10++{-+Interestingly, when the program aborts because of heap exhaustion,+then the generated file has size 137MB independent of the heap size+(I tried sizes from 1MB to 64MB).+-}+sequenceSample3 :: IO ()+sequenceSample3 = do+ arrange <- SigStL.makeArranger+ sampler <- sampledSoundTest2+ let sound =+ sampler (Sample.Cons (SigSt.replicate Option.defaultChunkSize 100000 0)+ (Sample.Positions 0 100000 50000 50000)+ 100)+ SVL.writeFile "test.f32" $+ arrange vectorChunkSize $+ evalState+ (let evs =+ EventListBT.cons (BM.Cons 0.01 0.001) 10 evs+ in Gen.sequence Option.defaultChannel (sound evs)) $+ let evs = EventList.cons 10 [] evs+ in EventList.cons 10 [makeNote Event.NoteOn 60] evs++sequenceSample4 :: IO ()+sequenceSample4 = do+ arrange <- SigStL.makeArranger+ sampler <- Instr.sampledSound+-- sampler <- sampledSoundTest2+ let sound =+ sampler (Sample.Cons (SigSt.replicate Option.defaultChunkSize 100000 0)+ (Sample.Positions 0 100000 50000 50000)+ 100)+ SVL.writeFile "test.f32" $+ arrange vectorChunkSize $+ evalState+ (let evs =+ EventListBT.cons (BM.Cons 0.01 0.001) 10 evs+ in Gen.sequenceCore+ Option.defaultChannel Gen.errorNoProgram+ (Gen.Modulator () return+ (return . Gen.renderInstrumentIgnoreProgram (sound evs sampleRate)))) $+ let evs = EventList.cons 10 [] evs+ in EventList.cons 10 [makeNote Event.NoteOn 60] evs++sequenceFM1 :: IO ()+sequenceFM1 = do+ arrange <- SigStL.makeArranger+ sound <- Instr.softStringFM $/+ let evs =+ EventListBT.cons (BM.Cons 0.01 0.001) 10 evs+ in evs+-- sound <- Instr.softStringReleaseEnvelope+ SVL.writeFile "test.f32" $+ arrange vectorChunkSize $+ evalState+ (Gen.sequenceCore+ Option.defaultChannel Gen.errorNoProgram+ (Gen.Modulator () return+ (return . Gen.renderInstrumentIgnoreProgram (sound sampleRate)))) $+ let evs = EventList.cons 10 [] evs+ in EventList.cons 10 [makeNote Event.NoteOn 60] evs+{-+ sound+ 0.01 1+ (NonNegChunky.fromChunks $ map NonNegW.fromNumber $ iterate (20-) 10)+-}+++adsr :: IO ()+adsr = do+ env <- Instr.adsr+ SVL.writeFile "adsr.f32" $+ env 0.2 2 0.15 0.3 0.5 vectorChunkSize sampleRate (-0.5) 88200+++constCtrl :: a -> PC.T a+constCtrl x =+ let xs = EventListBT.cons x 10000 xs+ in xs++bellNoiseStereoTest :: IO ()+bellNoiseStereoTest = do+ str <- Instr.bellNoiseStereoFM+ SVL.writeFile "bellnoise.f32" $+ str 0.3 0.1 (constCtrl 0.3) (constCtrl 100)+ vectorChunkSize+ (constCtrl (BM.Cons 1 0.01)) sampleRate 0 440+ 100000
+ alsa/Synthesizer/LLVM/Server/Scalar/Run.hs view
@@ -0,0 +1,154 @@+module Synthesizer.LLVM.Server.Scalar.Run where++import qualified Synthesizer.LLVM.Server.Scalar.Instrument as Instr+import qualified Synthesizer.LLVM.Server.Option as Option+import Synthesizer.LLVM.Server.ALSA (Output, play, startMessage, )+import Synthesizer.LLVM.Server.Common++import qualified Sound.ALSA.Sequencer.Event as Event+import qualified Data.EventList.Relative.TimeBody as EventList++import qualified Synthesizer.LLVM.Frame.Stereo as Stereo+import qualified Synthesizer.LLVM.MIDI as MIDIL+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 qualified Synthesizer.Storable.Signal as SigSt++import qualified Synthesizer.ALSA.EventList as Ev++import qualified Synthesizer.MIDI.PiecewiseConstant as PC+import qualified Synthesizer.MIDI.Generic as Gen++import qualified Sound.MIDI.Message.Channel.Voice as VoiceMsg++import Control.Arrow ((<<<), arr, )+import Control.Monad.Trans.State (evalState, )++import Control.Exception (bracket, )++import NumericPrelude.Numeric (zero, (*>), )+import Prelude hiding (Real, break, )+++{-# INLINE withMIDIEvents #-}+withMIDIEvents ::+ Option.T ->+ Output handle signal a ->+ (SigSt.ChunkSize -> SampleRate Real ->+ EventList.T Ev.StrictTime [Event.T] -> signal) -> IO a+withMIDIEvents opt output process = do+ putStrLn startMessage+ case output opt of+ (open,close,write) ->+ bracket open (close . snd) $ \((chunkSize,rate),h) ->+ let rrate = fromIntegral rate :: Double+ in Ev.withMIDIEvents+ (Option.clientName opt)+ (fromIntegral chunkSize / rrate)+ rrate+ (write h .+ process (SigSt.chunkSize chunkSize)+ (Option.SampleRate $ fromIntegral rate))++++freq :: Option.SampleRate Real -> Real -> Real+freq (Option.SampleRate sampleRate) f =+ f / sampleRate+++pitchBend :: IO ()+pitchBend = do+ opt <- Option.get+ osc <-+ SigP.runChunky+ ((CausalP.osciSimple WaveL.triangle $<# (zero::Real))+ $* piecewiseConstant (arr id))+ withMIDIEvents opt play $ \chunkSize sampleRate ->+ (id :: SigSt.T Real -> SigSt.T Real) .+ osc chunkSize .+ evalState (PC.pitchBend (Option.channel opt) 2 (freq sampleRate 880))+++frequencyModulation :: IO ()+frequencyModulation = do+ opt <- Option.get+ osc <-+ SigP.runChunky+ (((CausalP.osciSimple WaveL.triangle $<# (zero::Real))+ <<< (MIDIL.frequencyFromBendModulation (frequencyConst (10::Real))))+ $* piecewiseConstant (arr (\(sr,ctrl) -> transposeModulation sr 880 ctrl)))+ withMIDIEvents opt play $ \chunkSize sampleRate ->+ (id :: SigSt.T Real -> SigSt.T Real) .+ osc chunkSize . (,) sampleRate .+ evalState (PC.bendWheelPressure (Option.channel opt) 2 0.04 (0.03::Real))++++keyboard :: IO ()+keyboard = do+ opt <- Option.get+-- sound <- Instr.pingDur+{-+ sound <-+ fmap (\s vel _freq dur -> s vel dur) $+ (Instr.pingReleaseEnvelope $/ 0.4 $/ 0.1)+-}+ sound <- Instr.pingRelease $/ 0.4 $/ 0.1+ amp <- CausalP.runStorableChunky (CausalP.amplify (arr id))+ arrange <- SigStL.makeArranger+ withMIDIEvents opt play $ \chunkSize sampleRate ->+ (amp :: Real -> SigSt.T Real -> SigSt.T Real) 0.2 .+ arrange chunkSize .+ evalState+ (Gen.sequence+ (Option.channel opt)+ (sound chunkSize sampleRate))++keyboardStereo :: IO ()+keyboardStereo = do+ opt <- Option.get+ sound <- Instr.pingStereoRelease $/ 0.4 $/ 0.1+ amp <- CausalP.runStorableChunky (CausalP.amplifyStereo (arr id))+ arrange <- SigStL.makeArranger+ withMIDIEvents opt play $ \chunkSize sampleRate ->+ (amp :: Real -> SigSt.T (Stereo.T Real) -> SigSt.T (Stereo.T Real)) 0.2 .+ arrange chunkSize .+ evalState+ (Gen.sequence+ (Option.channel opt)+ (sound chunkSize sampleRate))++keyboardMulti :: IO ()+keyboardMulti = do+ opt <- Option.get+ png <- Instr.pingDur+ pngRel <- Instr.pingRelease $/ 0.4 $/ 0.1 $/ Option.chunkSize opt+ tin <- Instr.tine $/ 0.4 $/ 0.1 $/ Option.chunkSize opt+ arrange <- SigStL.makeArranger+ withMIDIEvents opt play $ \chunkSize sampleRate ->+-- playALSA (Bld.put :: Int16 -> Bld.Builder Int16) (sampleRate opt::Real) .+ SigSt.map (0.2*) .+ arrange chunkSize .+ evalState (Gen.sequenceMultiProgram (Option.channel opt)+ (VoiceMsg.toProgram 2)+ (map ($ sampleRate) [png, pngRel, tin]))++keyboardStereoMulti :: IO ()+keyboardStereoMulti = do+ opt <- Option.get+ png <- Instr.pingStereoRelease $/ 0.4 $/ 0.1+ tin <- Instr.tineStereo $/ 0.4 $/ 0.1+ str <- Instr.softString+ arrange <- SigStL.makeArranger+ withMIDIEvents opt play $ \chunkSize sampleRate ->+-- playALSA (Bld.put :: Int16 -> Bld.Builder Int16) (sampleRate opt::Real) .+ SigSt.map ((0.2::Real)*>) .+ arrange chunkSize .+ evalState (Gen.sequenceMultiProgram (Option.channel opt)+ (VoiceMsg.toProgram 1)+ (map (\sound -> sound chunkSize sampleRate) [png, tin, const str]))
+ alsa/Synthesizer/LLVM/Server/Scalar/Test.hs view
@@ -0,0 +1,86 @@+module Synthesizer.LLVM.Server.Scalar.Test where++import qualified Synthesizer.LLVM.Server.Scalar.Instrument as Instr+import qualified Synthesizer.LLVM.Server.Option as Option+import Synthesizer.LLVM.Server.Scalar.Run (withMIDIEvents, )+import Synthesizer.LLVM.Server.ALSA (record, put, makeNote, )+import Synthesizer.LLVM.Server.Common++import qualified Sound.ALSA.Sequencer.Event as Event+import qualified Synthesizer.MIDI.PiecewiseConstant as PC+import qualified Synthesizer.MIDI.Generic as Gen++import qualified Synthesizer.LLVM.CausalParameterized.Process as CausalP+import qualified Synthesizer.LLVM.Parameterized.Signal as SigP+import qualified Synthesizer.LLVM.Wave as WaveL+import Synthesizer.LLVM.CausalParameterized.Process (($<#), ($*), )++import qualified Synthesizer.Storable.Cut as CutSt+import qualified Synthesizer.Storable.Signal as SigSt+import qualified Data.StorableVector.Lazy as SVL++import qualified Data.EventList.Relative.TimeBody as EventList++import Control.Arrow (arr, )+import Control.Monad.Trans.State (evalState, )++import NumericPrelude.Numeric (zero, )+import Prelude hiding (Real, )+++sampleRate :: Real+sampleRate =+ Option.defaultSampleRate+++pitchBend0 :: IO ()+pitchBend0 = do+ osc <-+ SigP.runChunky+ ((CausalP.osciSimple WaveL.triangle $<# (zero::Real))+ $* piecewiseConstant (arr id))+ SVL.writeFile "test.f32" $+ (id :: SigSt.T Real -> SigSt.T Real) .+ osc Option.defaultChunkSize .+ evalState (PC.pitchBend Option.defaultChannel 2 (880/sampleRate)) $+ let evs = EventList.cons 100 [] evs+ in EventList.cons 0 ([]::[Event.T]) evs++pitchBend1 :: IO ()+pitchBend1 = do+ opt <- Option.get+ osc <-+ SigP.runChunky+ ((CausalP.osciSimple WaveL.triangle $<# (zero::Real))+ $* piecewiseConstant (arr id))+ withMIDIEvents opt (record "test.f32") $ \ _size _rate ->+ (id :: SigSt.T Real -> SigSt.T Real) .+ osc Option.defaultChunkSize .+ evalState (PC.pitchBend Option.defaultChannel 2 (880/sampleRate))++pitchBend2 :: IO ()+pitchBend2 = do+ opt <- Option.get+ withMIDIEvents opt put $ \ _size _rate -> id++++sequencePress :: IO ()+sequencePress = do+-- arrange <- SigStL.makeArranger+-- sound <- Instr.softString+-- sound <- Instr.softStringReleaseEnvelope+-- sound <- Instr.pingReleaseEnvelope $/ 1 $/ Option.defaultChunkSize+-- sound <- Instr.pingDur+-- sound <- Instr.pingDurTake+ let sound = Instr.dummy Option.defaultChunkSize (SampleRate sampleRate)+ SVL.writeFile "test.f32" $+ CutSt.arrange Option.defaultChunkSize $+ evalState+ (do Gen.sequence Option.defaultChannel sound) $+ let evs t =+ EventList.cons t [makeNote Event.NoteOn 60] $+ EventList.cons t [makeNote Event.NoteOff 60] $+ evs (20-t)+ in evs 10+
+ example/Synthesizer/LLVM/LAC2011.hs view
@@ -0,0 +1,335 @@+{-# LANGUAGE NoImplicitPrelude #-}+{-# OPTIONS_GHC -fno-warn-unused-imports #-}+module Synthesizer.LLVM.LAC2011 where++import qualified Synthesizer.LLVM.Filter.ComplexFirstOrderPacked as BandPass+import qualified Synthesizer.LLVM.Filter.Allpass as Allpass+import qualified Synthesizer.LLVM.Filter.Butterworth as Butterworth+import qualified Synthesizer.LLVM.Filter.Chebyshev as Chebyshev+import qualified Synthesizer.LLVM.Filter.FirstOrder as Filt1+import qualified Synthesizer.LLVM.Filter.SecondOrder as Filt2+import qualified Synthesizer.LLVM.Filter.SecondOrderPacked as Filt2P+import qualified Synthesizer.LLVM.Filter.Moog as Moog+import qualified Synthesizer.LLVM.Filter.Universal as UniFilter+import qualified Synthesizer.LLVM.CausalParameterized.Controlled as CtrlP+import qualified Synthesizer.LLVM.CausalParameterized.ControlledPacked as CtrlPS+import qualified Synthesizer.LLVM.CausalParameterized.ProcessPacked as CausalPS+import qualified Synthesizer.LLVM.CausalParameterized.Process as CausalP+import qualified Synthesizer.LLVM.Causal.Process as Causal+import qualified Synthesizer.LLVM.Simple.Signal as Gen+import qualified Synthesizer.LLVM.Storable.Signal as SigStL+import qualified Synthesizer.LLVM.Frame.SerialVector as Serial+import qualified Synthesizer.LLVM.Frame as Frame+import qualified Synthesizer.LLVM.Wave as Wave+import qualified Synthesizer.LLVM.Parameter as Param++import qualified LLVM.Extra.ScalarOrVector as SoV+import qualified LLVM.Extra.Memory as Memory+import qualified LLVM.Extra.Arithmetic as A+import qualified LLVM.Extra.Class as C+import LLVM.Core (Value, value, valueOf, Vector, constVector, constOf, )+import LLVM.Util.Arithmetic () -- Floating instance for TValue+import qualified LLVM.Core as LLVM+import Types.Data.Num (D4, D8, D16, d0, d1, d2, d3, d4, d5, d6, d7, d8, )+import qualified Types.Data.Num as TypeNum++import qualified Synthesizer.LLVM.Parameterized.SignalPacked as GenPS+import qualified Synthesizer.LLVM.Parameterized.Signal as GenP+import Synthesizer.LLVM.CausalParameterized.Process (($<), ($*), ($*#), )+import Synthesizer.LLVM.Parameterized.Signal (($#), )++import qualified Synthesizer.Plain.Filter.Recursive as FiltR+import qualified Synthesizer.Plain.Filter.Recursive.FirstOrder as Filt1Core+import qualified Synthesizer.Plain.Filter.Recursive.SecondOrder as Filt2Core++import Control.Arrow (Arrow, arr, (&&&), (^<<), )+import Control.Category ((<<<), (.), id, )+import Control.Monad ((<=<), )+import Control.Applicative (liftA2, pure, )+import Control.Functor.HT (void, )+import Data.Traversable (traverse, )++import Foreign.Storable (Storable, )+import qualified Data.StorableVector.Lazy as SVL+import qualified Data.StorableVector as SV++import qualified Data.EventList.Relative.TimeBody as EventList+import qualified Data.EventList.Relative.BodyTime as EventListBT+import qualified Data.EventList.Relative.MixedTime as EventListMT+import qualified Data.EventList.Relative.TimeMixed as EventListTM+import qualified Numeric.NonNegative.Wrapper as NonNeg++import qualified Synthesizer.LLVM.Frame.Stereo as Stereo++import qualified Sound.Sox.Option.Format as SoxOption+import qualified Sound.Sox.Frame as SoxFrame+import qualified Sound.Sox.Play as SoxPlay++import qualified Sound.ALSA.PCM as ALSA+import qualified Synthesizer.ALSA.Storable.Play as Play++import Data.Word (Word32, )+-- import qualified Data.Function.HT as F+import Data.List (genericLength, )+import System.Random (randomRs, mkStdGen, )++import qualified System.IO as IO+-- import System.Exit (ExitCode, )++import qualified Algebra.Field as Field+import qualified Algebra.Ring as Ring+import qualified Algebra.Additive as Additive++import NumericPrelude.Numeric+import NumericPrelude.Base hiding (fst, snd, id, (.), )+import qualified NumericPrelude.Base as P+++asMono :: vector Float -> vector Float+asMono = id++asStereo :: vector (Stereo.T Float) -> vector (Stereo.T Float)+asStereo = id++asMonoPacked :: vector (LLVM.Vector D4 Float) -> vector (LLVM.Vector D4 Float)+asMonoPacked = id++asMonoPacked16 :: vector (LLVM.Vector D16 Float) -> vector (LLVM.Vector D16 Float)+asMonoPacked16 = id++asWord32 :: vector Word32 -> vector Word32+asWord32 = id++asWord32Packed :: vector (LLVM.Vector D4 Word32) -> vector (LLVM.Vector D4 Word32)+asWord32Packed = id+++playStereo :: Gen.T (Stereo.T (Value Float)) -> IO ()+playStereo =+ playStereoStream .+ Gen.renderChunky (SVL.chunkSize 100000)++playStereoStream :: SVL.Vector (Stereo.T Float) -> IO ()+playStereoStream = playStreamSox++playMono :: Gen.T (Value Float) -> IO ()+playMono =+ playMonoStream .+ Gen.renderChunky (SVL.chunkSize 100000)++playMonoParam :: GenP.T () (Value Float) -> IO ()+playMonoParam =+ playMonoStream .+ ($ ()) .+ ($ SVL.chunkSize 100000) <=<+ GenP.runChunky++playMonoPacked :: GenP.T () (Serial.Value D4 Float) -> IO ()+playMonoPacked =+ playMonoStream .+ SigStL.unpack .+ ($ ()) .+ ($ SVL.chunkSize 100000) <=<+ GenP.runChunky++playMonoStream :: SVL.Vector Float -> IO ()+playMonoStream = playStreamSox+++{-+play ::+ (C.MakeValueTuple y, ValueTuple y ~ a, Memory.C a struct) =>+ Gen.T a -> IO ()+play =+ playStreamSox .+ Gen.renderChunky (SVL.chunkSize 100000)+-}++playStreamALSA ::+ (Additive.C y, ALSA.SampleFmt y) =>+ SVL.Vector y -> IO ()+playStreamALSA =+ Play.auto (Play.makeSink Play.defaultDevice (0.05::Double) sampleRate)++-- reacts faster to CTRL-C+playStreamSox ::+ (Storable y, SoxFrame.C y) =>+ SVL.Vector y -> IO ()+playStreamSox =+ void . SoxPlay.simple SVL.hPut SoxOption.none 44100+++sampleRate :: Ring.C a => a+sampleRate = 44100++intSecond :: Ring.C a => Float -> a+intSecond t = fromInteger $ round $ t * sampleRate++secondP :: Param.T p Float -> Param.T p Float+secondP t = t * sampleRate++hertzP :: Param.T p Float -> Param.T p Float+hertzP f = f / sampleRate++second :: Field.C a => a -> a+second t = t * sampleRate++hertz :: Field.C a => a -> a+hertz f = f / sampleRate++{-+second :: Float -> Param.T p Float+second t = return (t * sampleRate)++hertz :: Float -> Param.T p Float+hertz f = return (f / sampleRate)+-}++sine :: IO ()+sine =+ playMono (0.99 * Gen.osci Wave.sine 0 (hertz 440))++ping :: IO ()+ping =+ playMono (Gen.exponential2 (second 1) 1 * Gen.osci Wave.triangle 0 (hertz 440))++tremolo :: IO ()+tremolo =+ playMono (Gen.osci Wave.sine 0 (hertz 0.3) * Gen.osci Wave.triangle 0 (hertz 440))+++stereo :: IO ()+stereo =+ playStereo (liftA2 Stereo.cons (Gen.osci Wave.triangle 0 (hertz 439)) (Gen.osci Wave.triangle 0 (hertz 441)))++stereoFancy :: IO ()+stereoFancy =+ playStereo (traverse (Gen.osci Wave.triangle 0 . hertz) (Stereo.cons 439 441))+++fst :: Arrow arrow => arrow (a,b) a+fst = arr P.fst++snd :: Arrow arrow => arrow (a,b) b+snd = arr P.snd+++pingParam :: IO (Float -> SVL.Vector Float)+pingParam =+ fmap ($ SVL.chunkSize 1024) $+ GenP.runChunky $+ GenP.exponential2 (second 0.3) 1 * GenP.osciSimple Wave.triangle 0 id++playPingParam :: IO ()+playPingParam = do+ png <- pingParam+ playMonoStream (SVL.take (intSecond 1) $ png (hertz 880))++melody :: IO (SVL.Vector Float)+melody = do+ png <- pingParam+ return $ SVL.concat $ map (SVL.take (intSecond 0.2) . png . hertz) $ cycle [440, 550, 660, 880]++playMelody :: IO ()+playMelody = do+ mel <- melody+ playMonoStream mel++pingParam2 :: IO ((Float, Float) -> SVL.Vector Float)+pingParam2 =+ fmap ($ SVL.chunkSize 1024) $+ GenP.runChunky $+ GenP.exponential2 (second 0.3) fst * GenP.osciSimple Wave.triangle 0 snd++playMelody2 :: IO ()+playMelody2 = do+ png <- pingParam2+ playMonoStream $ SVL.concat $ map (SVL.take (intSecond 0.2) . png) $ zip (map sin $ [0,0.1..]) (cycle $ map hertz [440, 550, 660, 880])+++retard :: GenP.T p (Value Float) -> GenP.T p (Value Float)+retard xs =+ CausalP.frequencyModulationLinear xs .+ CausalP.mapSimple (A.fdiv (LLVM.valueOf 1)) $*+ GenP.rampCore (1 / secondP 10) 1++playRetarded :: IO ()+playRetarded = do+ mel <- melody+ playMonoParam $ retard $ GenP.fromStorableVectorLazy $ pure $ mel++++pingGen :: GenP.T p (Value Float)+pingGen =+ GenP.exponential2 (second 0.5) 0.7 *+ GenP.osciSimple Wave.triangle 0 (hertzP 440)++zerop :: Param.T p Float+zerop = pure zero++delayp :: Param.T p Int -> CausalP.T p (Value Float) (Value Float)+delayp = CausalP.delay zerop++delay :: IO ()+delay =+ playMonoParam $+ pingGen + 0.7 * (delayp (intSecond 0.5) $* pingGen)++delayArrow :: IO ()+delayArrow =+ playMonoParam+ ((id + 0.7 * delayp (intSecond 0.5)) $* pingGen)++comb :: IO ()+comb =+ playMonoParam $+ (CausalP.loop zerop+ (id &&& 0.7 * delayp (intSecond 0.5)+ <<< CausalP.mix) $*+ pingGen)+++lfoSine ::+ Param.T p Float ->+ GenP.T p (Moog.Parameter D8 (Value Float))+lfoSine reduct =+ CausalP.mapSimple (Moog.parameter d8 (valueOf (30::Float))) .+ CausalP.mapExponential 2 (hertz 700) $*+ GenP.osciSimple Wave.sine 0 (reduct * hertz 0.1)++filterSweep :: IO ()+filterSweep =+ playMonoParam $+ (0.2 * CtrlP.processCtrlRate 128 lfoSine+ $* GenP.noise 0 0.3)+++pingPacked :: IO ()+pingPacked =+ playMonoPacked (GenPS.exponential2 (second 1) 1 * GenPS.osciSimple Wave.triangle 0 (hertz 440))++++{-+Module can be loaded into GHCi only when synthesizer-llvm was installed with+$ cabal install --enable-shared++In contrast to that, you have to install with+$ cabal install -fbuildTests -fbuildExamples --enable-shared --disable-library-profiling --ghc-option=-dynamic+for build the executables.+But then GHCi complains:++$ ghci+GHCi, version 6.12.3: http://www.haskell.org/ghc/ :? for help+Loading package ghc-prim ... linking ... done.+Loading package integer-gmp ... linking ... done.+Loading package base ... linking ... done.+Loading package ffi-1.0 ... linking ... done.+[1 of 1] Compiling Main ( src/Synthesizer/LLVM/Test.hs, interpreted )++src/Synthesizer/LLVM/Test.hs:4:0:+ Bad interface file: /home/thielema/.cabal/lib/synthesizer-llvm-0.3/ghc-6.12.3/Synthesizer/LLVM/Filter/ComplexFirstOrderPacked.hi+ mismatched interface file ways (wanted "", got "dyn")+Failed, modules loaded: none.+-}
+ example/Synthesizer/LLVM/LNdW2011.hs view
@@ -0,0 +1,554 @@+{-# LANGUAGE NoImplicitPrelude #-}+{-# LANGUAGE TypeFamilies #-}+{-# OPTIONS_GHC -fno-warn-unused-imports #-}+module Synthesizer.LLVM.LNdW2011 where++import qualified Synthesizer.LLVM.Plug.Input as PIn+import qualified Synthesizer.LLVM.Plug.Output as POut+import qualified Synthesizer.MIDI.PiecewiseConstant.ControllerSet as PCS+import qualified Synthesizer.MIDI.CausalIO.ControllerSelection as MCS+import qualified Synthesizer.MIDI.CausalIO.Process as PMIDI+import qualified Synthesizer.ALSA.CausalIO.Process as PALSA+import qualified Synthesizer.CausalIO.Process as PIO+import qualified Synthesizer.MIDI.Value as MV+import qualified Synthesizer.Zip as Zip+import Synthesizer.ALSA.EventList (ClientName(ClientName))++import qualified Sound.MIDI.Controller as Ctrl+import qualified Sound.MIDI.Message.Channel as ChannelMsg++import qualified Synthesizer.LLVM.Filter.ComplexFirstOrderPacked as BandPass+import qualified Synthesizer.LLVM.Filter.Allpass as Allpass+import qualified Synthesizer.LLVM.Filter.Butterworth as Butterworth+import qualified Synthesizer.LLVM.Filter.Chebyshev as Chebyshev+import qualified Synthesizer.LLVM.Filter.FirstOrder as Filt1+import qualified Synthesizer.LLVM.Filter.SecondOrder as Filt2+import qualified Synthesizer.LLVM.Filter.SecondOrderPacked as Filt2P+import qualified Synthesizer.LLVM.Filter.Moog as Moog+import qualified Synthesizer.LLVM.Filter.Universal as UniFilter+import qualified Synthesizer.LLVM.CausalParameterized.Controlled as CtrlP+import qualified Synthesizer.LLVM.CausalParameterized.ControlledPacked as CtrlPS+import qualified Synthesizer.LLVM.CausalParameterized.ProcessPacked as CausalPS+import qualified Synthesizer.LLVM.CausalParameterized.Process as CausalP+import qualified Synthesizer.LLVM.Causal.Process as Causal+import qualified Synthesizer.LLVM.Simple.Signal as Gen+import qualified Synthesizer.LLVM.Simple.Value as Value+import qualified Synthesizer.LLVM.Storable.Signal as SigStL+import qualified Synthesizer.LLVM.Frame.SerialVector as Serial+import qualified Synthesizer.LLVM.Frame as Frame+import qualified Synthesizer.LLVM.Wave as Wave+import qualified Synthesizer.LLVM.Parameter as Param++import qualified LLVM.Extra.ScalarOrVector as SoV+import qualified LLVM.Extra.Memory as Memory+import qualified LLVM.Extra.Arithmetic as A+import qualified LLVM.Extra.Class as C+import LLVM.Core (Value, value, valueOf, constVector, constOf, )+import LLVM.Util.Arithmetic () -- Floating instance for TValue+import qualified LLVM.Core as LLVM+import Types.Data.Num (D4, D8, D16, d0, d1, d2, d3, d4, d5, d6, d7, d8, )+import qualified Types.Data.Num as TypeNum++import qualified Synthesizer.LLVM.Parameterized.SignalPacked as GenPS+import qualified Synthesizer.LLVM.Parameterized.Signal as GenP+import Synthesizer.LLVM.CausalParameterized.Process (($<), ($*), ($*#), ($<#), )+import Synthesizer.LLVM.Parameterized.Signal (($#), )++import qualified Synthesizer.Plain.Filter.Recursive as FiltR+import qualified Synthesizer.Plain.Filter.Recursive.FirstOrder as Filt1Core+import qualified Synthesizer.Plain.Filter.Recursive.SecondOrder as Filt2Core++import qualified Synthesizer.Causal.Spatial as Spatial++import qualified Control.Monad.Trans.State as State+import qualified Control.Arrow as Arr+import Control.Arrow (Arrow, arr, (&&&), (^<<), (^>>), )+import Control.Category ((<<<), (.), id, (>>>), )+import Control.Monad (liftM2, (<=<), )+import Control.Applicative (liftA2, pure, )+import Control.Functor.HT (void, )+import Data.Tuple.HT (mapPair, )+import Data.Traversable (traverse, )++import Foreign.Storable (Storable, )+import qualified Data.StorableVector.Lazy as SVL+import qualified Data.StorableVector as SV++import qualified Data.EventList.Relative.TimeBody as EventList+import qualified Data.EventList.Relative.BodyTime as EventListBT+import qualified Data.EventList.Relative.MixedTime as EventListMT+import qualified Data.EventList.Relative.TimeMixed as EventListTM+import qualified Data.EventList.Relative.TimeTime as EventListTT+import qualified Numeric.NonNegative.Wrapper as NonNegW+import qualified Numeric.NonNegative.Class as NonNeg++import qualified Synthesizer.LLVM.Frame.Stereo as Stereo+import qualified Synthesizer.LLVM.Frame.StereoInterleaved as StereoInt++import qualified Sound.Sox.Option.Format as SoxOption+import qualified Sound.Sox.Frame as SoxFrame+import qualified Sound.Sox.Play as SoxPlay++import qualified Sound.ALSA.PCM as ALSA+import qualified Synthesizer.ALSA.Storable.Play as Play++import Data.Word (Word32, )+-- import qualified Data.Function.HT as F+import Data.List (genericLength, )+import System.Random (randomRs, mkStdGen, )++import qualified System.IO as IO+-- import System.Exit (ExitCode, )++import qualified Algebra.NormedSpace.Euclidean as NormedEuc+import qualified Algebra.Field as Field+import qualified Algebra.Ring as Ring+import qualified Algebra.Additive as Additive+import qualified Algebra.IntegralDomain as Integral++import NumericPrelude.Numeric+import NumericPrelude.Base hiding (fst, snd, id, (.), )+import qualified NumericPrelude.Base as P+++asMono :: vector Float -> vector Float+asMono = id++asStereo :: vector (Stereo.T Float) -> vector (Stereo.T Float)+asStereo = id++asMonoPacked :: vector Vector -> vector Vector+asMonoPacked = id++asMonoPacked16 :: vector (LLVM.Vector D16 Float) -> vector (LLVM.Vector D16 Float)+asMonoPacked16 = id++asWord32 :: vector Word32 -> vector Word32+asWord32 = id++asWord32Packed :: vector (LLVM.Vector D4 Word32) -> vector (LLVM.Vector D4 Word32)+asWord32Packed = id+++playStereo :: Gen.T (Stereo.T (Value Float)) -> IO ()+playStereo =+ playStereoStream .+ Gen.renderChunky (SVL.chunkSize 100000)++playStereoStream :: SVL.Vector (Stereo.T Float) -> IO ()+playStereoStream = playStreamSox++playMono :: Gen.T (Value Float) -> IO ()+playMono =+ playMonoStream .+ Gen.renderChunky (SVL.chunkSize 100000)++playMonoParam :: GenP.T () (Value Float) -> IO ()+playMonoParam =+ playMonoStream .+ ($ ()) .+ ($ SVL.chunkSize 100000) <=<+ GenP.runChunky++playMonoPacked :: GenP.T () VectorValue -> IO ()+playMonoPacked =+ playMonoStream .+ SigStL.unpack .+ ($ ()) .+ ($ SVL.chunkSize 100000) <=<+ GenP.runChunky++playMonoStream :: SVL.Vector Float -> IO ()+playMonoStream = playStreamSox+++playStreamALSA ::+ (Additive.C y, ALSA.SampleFmt y) =>+ SVL.Vector y -> IO ()+playStreamALSA =+ Play.auto (Play.makeSink Play.defaultDevice (0.05::Double) sampleRate)++-- reacts faster to CTRL-C+playStreamSox ::+ (Storable y, SoxFrame.C y) =>+ SVL.Vector y -> IO ()+playStreamSox =+ void . SoxPlay.simple SVL.hPut SoxOption.none 44100+++sampleRate :: Ring.C a => a+sampleRate = 44100++type Vector = Serial.Plain VectorSize Float+type VectorSize = TypeNum.D4+type VectorValue = Serial.Value VectorSize Float++vectorSize :: Int+vectorSize = TypeNum.fromIntegerT (undefined :: VectorSize)++vectorRate :: Field.C a => a+vectorRate = sampleRate / fromIntegral vectorSize++++intSecond :: Ring.C a => Float -> a+intSecond t = fromInteger $ round $ t * sampleRate++second :: Field.C a => a -> a+second t = t * sampleRate++hertz :: Field.C a => a -> a+hertz f = f / sampleRate++++fst :: Arrow arrow => arrow (a,b) a+fst = arr P.fst++snd :: Arrow arrow => arrow (a,b) b+snd = arr P.snd+++playFromEvents ::+ (ALSA.SampleFmt a, Additive.C a) =>+ Double ->+ Double ->+ PIO.T PALSA.Events (SV.Vector a) ->+ IO ()+playFromEvents latency period =+ PALSA.playFromEvents+ Play.defaultDevice (ClientName "Haskell-LLVM-demo")+ latency period sampleRate+++modulation :: IO ()+modulation = do+ proc <-+ CausalP.processIO+ (0.95 * (CausalP.osciSimple Wave.approxSine4 $< 0))+ playFromEvents 0.01 (0.015::Double)+ ((proc () :: PIO.T (EventListBT.T NonNegW.Int Float) (SV.Vector Float))+ .+ PMIDI.controllerExponential+ (ChannelMsg.toChannel 0)+ Ctrl.modulation+ (hertz 500, hertz 2000) (hertz 1000))+++vectorBlockSize :: Double+vectorBlockSize = fromIntegral $ 150*vectorSize++subsample :: (Integral.C t) => t -> t -> State.State t t+subsample step t =+ State.state $ \r -> divMod (r+t) step+{-+ do modify (t+)+ (q,r) <- gets (flip divMod step)+ put r+ return q+-}++subsampleBT :: EventListBT.T NonNegW.Int a -> EventListBT.T NonNegW.Int a+subsampleBT =+ flip State.evalState NonNeg.zero .+ EventListBT.mapTimeM (subsample (NonNegW.fromNumberMsg "vectorSize" vectorSize))++modulationPacked :: IO ()+modulationPacked = do+ proc <-+ CausalP.processIO+ (0.95 * (CausalPS.osciSimple Wave.approxSine4 $< 0)+ .+ CausalP.mapSimple Serial.upsample)+ playFromEvents 0.01 (vectorBlockSize/sampleRate)+ (arr SigStL.unpackStrict+ .+ (proc () :: PIO.T (EventListBT.T NonNegW.Int Float) (SV.Vector Vector))+ .+ arr subsampleBT+ .+ PMIDI.controllerExponential+ (ChannelMsg.toChannel 0)+ Ctrl.modulation+ (hertz 500, hertz 2000) (hertz 1000))+++bubbles :: IO ()+bubbles = do+ proc <-+ CausalP.processIO+ (0.95 * (CausalP.osciSimple Wave.sine $< 0)+ .+ (fst.fst * (1 + snd.fst * snd))+ .+ Arr.second (CausalP.osciSimple Wave.saw $< 0))+ playFromEvents 0.01 (0.015::Double)+ ((proc () ::+ PIO.T+ (Zip.T+ (Zip.T+ (EventListBT.T NonNegW.Int Float)+ (EventListBT.T NonNegW.Int Float))+ (EventListBT.T NonNegW.Int Float))+ (SV.Vector Float))+ .+ PIO.zip+ (PIO.zip+ (PMIDI.controllerExponential+ (ChannelMsg.toChannel 0)+ Ctrl.modulation+ (hertz 500, hertz 2000) (hertz 1000))+ (PMIDI.controllerLinear+ (ChannelMsg.toChannel 0)+ Ctrl.timbre+ (-1, 1) (-0.1)))+ (PMIDI.controllerExponential+ (ChannelMsg.toChannel 0)+ Ctrl.soundVariation+ (hertz 1, hertz 10) (hertz 1)))++bubblesSet :: IO ()+bubblesSet = do+ proc <-+ CausalP.processIOCore+ (PIn.controllerSet d6)+ (CausalP.arrayElement d0 *+ (CausalP.osciSimple Wave.sine $< 0)+ .+ (CausalP.arrayElement d1+ *+ (1 - CausalP.arrayElement d2 *+ (CausalP.osciSimple Wave.saw $< 0) .+ CausalP.arrayElement d3)+ *+ (1 - CausalP.arrayElement d4 *+ (CausalP.osciSimple Wave.saw $< 0) .+ CausalP.arrayElement d5)))+ POut.storableVector+ playFromEvents 0.01 (0.015::Double)+ ((proc () :: PIO.T (PCS.T Int Float) (SV.Vector Float))+ .+ MCS.filter [+ MCS.controllerExponential Ctrl.volume (0.001, 0.99) 0.5,+ MCS.controllerExponential Ctrl.modulation (hertz 500, hertz 2000) (hertz 1000),+ MCS.controllerLinear Ctrl.soundVariation (-1, 1) 0.7,+ MCS.controllerExponential Ctrl.timbre (hertz 0.2, hertz 5) (hertz 1),+ MCS.controllerLinear Ctrl.soundController5 (-1, 1) 0.5,+ MCS.controllerExponential Ctrl.soundController7 (hertz 2, hertz 20) (hertz 10)]+ .+ MCS.fromChannel (ChannelMsg.toChannel 0))+++subsamplePCS :: PCS.T key a -> PCS.T key a+subsamplePCS =+ PCS.mapStream $+ flip State.evalState NonNeg.zero .+ EventListTT.mapTimeM (subsample (NonNegW.fromNumberMsg "vectorSize" $ fromIntegral vectorSize))++bubblesPacked :: IO ()+bubblesPacked = do+ proc <-+ CausalP.processIOCore+ (PIn.controllerSet d6)+ (CausalPS.arrayElement d0 *+ (CausalPS.osciSimple Wave.approxSine4 $< 0)+ .+ (CausalPS.arrayElement d1+ *+ (1 - CausalPS.arrayElement d2 *+ (CausalPS.osciSimple Wave.saw $< 0) .+ CausalPS.arrayElement d3)+ *+ (1 - CausalPS.arrayElement d4 *+ (CausalPS.osciSimple Wave.saw $< 0) .+ CausalPS.arrayElement d5)))+ POut.storableVector+ playFromEvents 0.01 (vectorBlockSize/sampleRate)+ (arr SigStL.unpackStrict+ .+ (proc () :: PIO.T (PCS.T Int Float) (SV.Vector Vector))+ .+ arr subsamplePCS+ .+ MCS.filter [+ MCS.controllerExponential Ctrl.volume (0.001, 0.99) 0.5,+ MCS.controllerExponential Ctrl.modulation (hertz 500, hertz 2000) (hertz 1000),+ MCS.controllerLinear Ctrl.soundVariation (-1, 1) 0.7,+ MCS.controllerExponential Ctrl.timbre (hertz 0.2, hertz 5) (hertz 1),+ MCS.controllerLinear Ctrl.soundController5 (-1, 1) 0.5,+ MCS.controllerExponential Ctrl.soundController7 (hertz 2, hertz 20) (hertz 10)]+ .+ MCS.fromChannel (ChannelMsg.toChannel 0))+++{-+Implementation of 'moveAround' that just lifts the corresponding plain function+in the @Spatial@ module from @synthesizer-core@.+Unfortunately, this way we get a @PseudoModule v v@ constraint+that cannot be satisfied with @LLVM.Vector@s.+-}+moveAround2dLifted ::+ (A.Transcendental v, A.PseudoModule v v,+ A.Real v, A.RationalConstant v) =>+ Value.T v -> Value.T v -> (Value.T v, Value.T v) ->+ CausalP.T p (v, v) (v, v)+moveAround2dLifted att sonicDelay ear =+ CausalP.mapSimple+ (uncurry (liftM2 (,)) .+ mapPair (Value.decons, Value.decons) .+ Spatial.moveAround att sonicDelay ear .+ mapPair (Value.constantValue, Value.constantValue))++moveAround2d ::+ (A.Algebraic v, A.RationalConstant v) =>+ Value.T v -> Value.T v -> (Value.T v, Value.T v) ->+ CausalP.T p (v, v) (v, v)+moveAround2d att sonicDelay ear =+ CausalP.mapSimple $ Value.flattenFunction $+ (\dist -> (sonicDelay*dist, 1/(att+dist)^2)) .+ euclideanNorm2d . subtract ear++euclideanNorm2d ::+ (A.Algebraic a) =>+ (Value.T a, Value.T a) -> Value.T a+euclideanNorm2d (x,y) =+ Value.sqrt $ Value.square x + Value.square y++mapFunc ::+ (Value.Flatten a, Value.Flatten b) =>+ (a -> b) ->+ CausalP.T p (Value.Registers a) (Value.Registers b)+mapFunc f =+ CausalP.mapSimple (Value.flattenFunction f)++flyChannel ::+ (Value.T (Value Float), Value.T (Value Float)) ->+ CausalP.T p (Value Float, (Value Float, Value Float)) (Value Float)+flyChannel ear =+ ((snd ^>> moveAround2d 1 0.1 ear >>> Arr.first (negate id))+ &&&+ (Arr.second+ (2 * ((CausalP.differentiate $# (0::Float, 0::Float))+ >>>+ mapFunc euclideanNorm2d))+ >>>+ CausalP.mix))+ >>>+ arr (\((phase,volume), speed) -> (volume, (phase,speed)))+ >>>+ Arr.second (CausalP.osciSimple Wave.saw)+ >>>+ (CausalP.envelope * 10)++fly :: IO ()+fly = do+ let slow =+ Filt1.lowpassCausalP $<#+ Filt1Core.parameter (1/sampleRate::Float)+ let fast =+ Filt1.lowpassCausalP $<#+ Filt1Core.parameter (30/sampleRate::Float)+ proc <-+ CausalP.processIOCore+ (PIn.controllerSet d5)+ ((CausalP.arrayElement d0 &&&+ (liftA2 (,)+ (CausalP.arrayElement d2)+ (liftA2 (,)+ ((CausalP.arrayElement d3 >>> slow)+ ++ CausalP.arrayElement d1 *+ (CausalP.fromSignal (GenP.noise 366210 0.3) >>> fast >>> fast))+ ((CausalP.arrayElement d4 >>> slow)+ ++ CausalP.arrayElement d1 *+ (CausalP.fromSignal (GenP.noise 234298 0.3) >>> fast >>> fast)))+ >>>+ liftA2 Stereo.cons+ (flyChannel (-1,0))+ (flyChannel ( 1,0))))+ >>>+ CausalP.envelopeStereo)+ POut.storableVector+ playFromEvents 0.01 (0.015::Double)+ ((proc () :: PIO.T (PCS.T Int Float) (SV.Vector (Stereo.T Float)))+ .+ MCS.filter [+ MCS.controllerExponential Ctrl.volume (0.001, 0.99) 0.2,+ MCS.controllerLinear Ctrl.modulation (0, 5) 2,+ MCS.pitchBend 2 (hertz 250),+ MCS.controllerLinear Ctrl.vectorX (-10, 10) 0,+ MCS.controllerLinear Ctrl.vectorY (-10, 10) 0]+ .+ MCS.fromChannel (ChannelMsg.toChannel 0))+++flyChannelPacked ::+ (Value.T VectorValue, Value.T VectorValue) ->+ CausalP.T p (VectorValue, (VectorValue, VectorValue)) VectorValue+flyChannelPacked ear =+ ((snd ^>> moveAround2d 1 0.1 ear >>> Arr.first (negate id))+ &&&+ (Arr.second+ (2 * ((CausalPS.differentiate $# (0::Float, 0::Float))+ >>>+ mapFunc euclideanNorm2d))+ >>>+ CausalP.mix))+ >>>+ arr (\((phase,volume), speed) -> (volume, (phase,speed)))+ >>>+ Arr.second (CausalPS.osciSimple Wave.saw)+ >>>+ CausalP.envelope+ >>>+ CausalPS.amplify 10+++flyPacked :: IO ()+flyPacked = do+ let slow =+ Filt1.lowpassCausalPackedP $<#+ Filt1Core.parameter (1/sampleRate::Float)+ let fast =+ Filt1.lowpassCausalPackedP $<#+ Filt1Core.parameter (30/sampleRate::Float)+ proc <-+ CausalP.processIOCore+ (PIn.controllerSet d5)+ ((CausalPS.arrayElement d0 &&&+ (liftA2 (,)+ (CausalPS.arrayElement d2)+ (liftA2 (,)+ ((CausalPS.arrayElement d3 >>> slow)+ ++ CausalPS.arrayElement d1 *+ (CausalP.fromSignal (GenPS.noise 366210 0.3) >>> fast >>> fast))+ ((CausalPS.arrayElement d4 >>> slow)+ ++ CausalPS.arrayElement d1 *+ (CausalP.fromSignal (GenPS.noise 234298 0.3) >>> fast >>> fast)))+ >>>+ liftA2 Stereo.cons+ (flyChannelPacked (-1,0))+ (flyChannelPacked ( 1,0))))+ >>>+ CausalP.envelopeStereo+ >>>+ CausalP.mapSimple StereoInt.interleave)+ POut.storableVector+ playFromEvents 0.01 (vectorBlockSize/sampleRate)+ (arr SigStL.unpackStereoStrict+ .+ (proc () :: PIO.T (PCS.T Int Float) (SV.Vector (StereoInt.T VectorSize Float)))+ .+ arr subsamplePCS+ .+ MCS.filter [+ MCS.controllerExponential Ctrl.volume (0.001, 0.99) 0.2,+ MCS.controllerLinear Ctrl.modulation (0, 5) 2,+ MCS.pitchBend 2 (hertz 250),+ MCS.controllerLinear Ctrl.vectorX (-10, 10) 0,+ MCS.controllerLinear Ctrl.vectorY (-10, 10) 0]+ .+ MCS.fromChannel (ChannelMsg.toChannel 0))
+ example/Synthesizer/LLVM/Test.hs view
@@ -0,0 +1,1382 @@+{-# LANGUAGE Rank2Types #-}+module Main where++import Synthesizer.LLVM.LAC2011 ()+import qualified Synthesizer.LLVM.LNdW2011 as LNdW2011++import qualified Synthesizer.LLVM.Filter.ComplexFirstOrderPacked as BandPass+import qualified Synthesizer.LLVM.Filter.Allpass as Allpass+import qualified Synthesizer.LLVM.Filter.Butterworth as Butterworth+import qualified Synthesizer.LLVM.Filter.Chebyshev as Chebyshev+import qualified Synthesizer.LLVM.Filter.FirstOrder as Filt1+import qualified Synthesizer.LLVM.Filter.SecondOrder as Filt2+import qualified Synthesizer.LLVM.Filter.SecondOrderPacked as Filt2P+import qualified Synthesizer.LLVM.Filter.Moog as Moog+import qualified Synthesizer.LLVM.Filter.Universal as UniFilter+import qualified Synthesizer.LLVM.CausalParameterized.Controlled as CtrlP+import qualified Synthesizer.LLVM.CausalParameterized.ControlledPacked as CtrlPS+import qualified Synthesizer.LLVM.CausalParameterized.ProcessPacked as CausalPS+import qualified Synthesizer.LLVM.CausalParameterized.Process as CausalP+import qualified Synthesizer.LLVM.CausalParameterized.Functional as Func+import qualified Synthesizer.LLVM.Causal.Process as Causal+import qualified Synthesizer.LLVM.Simple.Signal as Sig+import qualified Synthesizer.LLVM.Storable.Signal as SigStL+import qualified Synthesizer.LLVM.Frame as Frame+import qualified Synthesizer.LLVM.Wave as Wave+import qualified Synthesizer.LLVM.Frame.SerialVector as Serial+import qualified Synthesizer.LLVM.Parameter as Param++import qualified LLVM.Extra.Memory as Memory+import qualified LLVM.Extra.Arithmetic as A+import LLVM.Core (Value, value, valueOf, Vector, constVector, constOf, )+import LLVM.Util.Arithmetic () -- Floating instance for TValue+import qualified LLVM.Core as LLVM+import Types.Data.Num (D4, D8, D16, )+import qualified Types.Data.Num as TypeNum++import qualified Synthesizer.LLVM.Parameterized.SignalPacked as SigPS+import qualified Synthesizer.LLVM.Parameterized.Signal as SigP+import Synthesizer.LLVM.CausalParameterized.Process (($<), ($*), ($*#), )+import Synthesizer.LLVM.Parameterized.Signal (($#), )++import qualified Synthesizer.Plain.Filter.Recursive as FiltR+import qualified Synthesizer.Plain.Filter.Recursive.FirstOrder as Filt1Core+import qualified Synthesizer.Plain.Filter.Recursive.SecondOrder as Filt2Core++import Control.Arrow (Arrow, arr, (&&&), (^<<), (***), )+import Control.Category ((<<<), (.), id, )+import Control.Applicative (pure, liftA2, )+import Control.Functor.HT (void, )++import qualified Data.StorableVector.Lazy as SVL+import qualified Data.StorableVector as SV++import qualified Data.EventList.Relative.TimeBody as EventList+import qualified Data.EventList.Relative.BodyTime as EventListBT+import qualified Data.EventList.Relative.MixedTime as EventListMT+import qualified Data.EventList.Relative.TimeMixed as EventListTM+import qualified Numeric.NonNegative.Wrapper as NonNeg++import qualified Sound.Sox.Option.Format as SoxOption+import qualified Sound.Sox.Play as SoxPlay+-- import qualified Synthesizer.ALSA.Storable.Play as Play++import qualified Synthesizer.LLVM.Frame.Stereo as Stereo+import qualified Synthesizer.LLVM.Frame.StereoInterleaved as StereoInt++import Data.Word (Word32, )+-- import qualified Data.Function.HT as F+import Data.List (genericLength, )+import System.Random (randomRs, mkStdGen, )++import qualified System.IO as IO+-- import System.Exit (ExitCode, )++import Prelude hiding (fst, snd, id, (.), )+import qualified Prelude as P+++asMono :: vector Float -> vector Float+asMono = id++asStereo :: vector (Stereo.T Float) -> vector (Stereo.T Float)+asStereo = id++asMonoPacked :: vector (Serial.Plain D4 Float) -> vector (Serial.Plain D4 Float)+asMonoPacked = id++asMonoPacked16 :: vector (Serial.Plain D16 Float) -> vector (Serial.Plain D16 Float)+asMonoPacked16 = id++asStereoInterleaved :: vector (StereoInt.T D4 Float) -> vector (StereoInt.T D4 Float)+asStereoInterleaved = id++asWord32 :: vector Word32 -> vector Word32+asWord32 = id++asWord32Packed :: vector (Serial.Plain D4 Word32) -> vector (Serial.Plain D4 Word32)+asWord32Packed = id+++{- |+> playStereo (Sig.amplifyStereo 0.3 $ stereoOsciSaw 0.01)++Unfortunately: If you call :reload,+then the next attempt to play something will be answered by:++ghci: JITEmitter.cpp:110: <unnamed>::JITResolver::JITResolver(llvm::JIT&): Assertion `TheJITResolver == 0 && "Multiple JIT resolvers?"' failed.+-}+playStereo :: Sig.T (Stereo.T (Value Float)) -> IO ()+playStereo =+ playStereoVector .+ Sig.renderChunky (SVL.chunkSize 100000)++playStereoVector :: SVL.Vector (Stereo.T Float) -> IO ()+playStereoVector =+ void . SoxPlay.simple SVL.hPut SoxOption.none 44100++playMono :: Sig.T (Value Float) -> IO ()+playMono =+ playMonoVector .+ Sig.renderChunky (SVL.chunkSize 100000)++playMonoVector :: SVL.Vector Float -> IO ()+playMonoVector =+ void . SoxPlay.simple SVL.hPut SoxOption.none 44100+++playFileMono :: FilePath -> IO ()+playFileMono fileName = do+ IO.withFile fileName IO.ReadMode $ \h ->+ playStereo .+ Sig.fromStorableVectorLazy .+ asStereo . snd+ =<< SVL.hGetContentsAsync (SVL.chunkSize 4321) h+ return ()+++frequency :: Float -> Param.T p Float+frequency = return+++saw :: IO ()+saw =+ SV.writeFile "speedtest.f32" $+ asMono $+ Sig.render 10000000 $+ Sig.osciSaw 0 0.01++exponential :: IO ()+exponential =+ SV.writeFile "speedtest.f32" $+ asMono $+ Sig.render 10000000 $+ Sig.exponential2 50000 1++triangle :: IO ()+triangle =+ SV.writeFile "speedtest.f32" $+ asMono $+ Sig.render 10000000 $+ Sig.osci Wave.triangle 0.25 0.01++trianglePack :: IO ()+trianglePack =+ SV.writeFile "speedtest.f32" $+ asMonoPacked $+ (\xs -> SigP.render xs (div 10000000 4) ()) $+ SigP.mapSimple Wave.triangle $+ SigPS.packSmall $+ SigP.osciCore 0.25 (frequency 4.015803e-4)++trianglePacked :: IO ()+trianglePacked =+ SV.writeFile "speedtest.f32" $+ asMonoPacked $+ (\xs -> SigP.render xs (div 10000000 4) ()) $+ (CausalPS.osciSimple Wave.triangle+ $< SigPS.constant 0.25+ $* SigPS.constant 0.01)++triangleReplicate :: IO ()+triangleReplicate =+ SV.writeFile "speedtest.f32" $+ asMonoPacked $+ (\xs -> SigP.render xs (div 10000000 4) ()) $+ (CausalPS.shapeModOsci+ (\k p -> do+ x <- Wave.triangle =<< Wave.replicate k p+ y <- Wave.approxSine4 =<< Wave.halfEnvelope p+ A.mul x y)+ $< SigPS.rampInf 1000000+ $< SigPS.constant 0+ $* SigPS.constant 0.01)++rationalSine :: IO ()+rationalSine =+ SV.writeFile "speedtest.f32" $+ asMonoPacked $+ (\xs -> SigP.render xs (div 10000000 4) ()) $+ (CausalPS.shapeModOsci Wave.rationalApproxSine1+ $< (0.001 + SigPS.rampInf 10000000)+ $< SigPS.constant 0+ $* SigPS.constant 0.01)++rationalSineStereo :: IO ()+rationalSineStereo =+ SV.writeFile "speedtest.f32" $+ SigStL.unpackStereoStrict $+ asStereoInterleaved $+ (\xs -> SigP.render xs (div 10000000 4) ()) $+ SigP.mapSimple StereoInt.interleave $+ liftA2 Stereo.cons+ (CausalPS.shapeModOsci Wave.rationalApproxSine1+ $< (0.001 + SigPS.rampInf 10000000)+ $< SigPS.constant (-0.25)+ $* SigPS.constant 0.00999)+ (CausalPS.shapeModOsci Wave.rationalApproxSine1+ $< (0.001 + SigPS.rampInf 10000000)+ $< SigPS.constant 0.25+ $* SigPS.constant 0.01001)+++pingSig :: Float -> Sig.T (Value Float)+pingSig freq =+ Sig.envelope+ (Sig.exponential2 50000 1)+ (Sig.osciSaw 0.5 freq)++pingSigP :: SigP.T Float (Value Float)+pingSigP =+ let freq = id+ in SigP.envelope+ (SigP.exponential2 50000 1)+ (SigP.osciSaw 0.5 freq)++ping :: IO ()+ping =+ SV.writeFile "speedtest.f32" $+ asMono $+ Sig.render 10000000 $+ pingSig 0.01++pingSigPacked :: SigP.T Float (Serial.Value D4 Float)+pingSigPacked =+ let freq = id+ in SigP.envelope+ (SigPS.exponential2 50000 1)+ (SigPS.osciSimple Wave.saw 0 freq)++pingPacked :: IO ()+pingPacked =+ SV.writeFile "speedtest.f32" $+ asMonoPacked $+ (\xs -> SigP.render xs (div 10000000 4) 0.01) $+ pingSigPacked++pingUnpack :: IO ()+pingUnpack =+ SV.writeFile "speedtest.f32" $+ asMono $+ (\xs -> SigP.render xs 10000000 0.01) $+ SigPS.unpack $+ pingSigPacked++pingSmooth :: IO ()+pingSmooth =+ SV.writeFile "speedtest-scalar.f32" $+ asMono $+ (\xs -> SigP.render xs 10000000 ()) $+ (Filt1.lowpassCausalP+ $< (fmap Filt1Core.Parameter $+ SigP.mapSimple (A.sub (valueOf 1))+ (SigP.exponential2 50000 $# (1::Float)))+ $* SigP.osciSimple Wave.triangle 0 (frequency 0.01))++pingSmoothPacked :: IO ()+pingSmoothPacked =+ SV.writeFile "speedtest-vector.f32" $+ asMonoPacked $+ (\xs -> SigP.render xs (div 10000000 4) ()) $+ (Filt1.lowpassCausalPackedP+ $< (fmap Filt1Core.Parameter $+ SigP.mapSimple (A.sub (valueOf 1))+ (SigP.exponential2 (50000/4) $# (1::Float)))+ $* SigPS.osciSimple Wave.triangle 0 0.01)++stereoOsciSaw :: Float -> Sig.T (Stereo.T (Value Float))+stereoOsciSaw freq =+ liftA2 Stereo.cons+ (Sig.osciSaw 0.0 (freq*1.001) `Sig.mix`+ Sig.osciSaw 0.2 (freq*1.003) `Sig.mix`+ Sig.osciSaw 0.1 (freq*0.995))+ (Sig.osciSaw 0.1 (freq*1.005) `Sig.mix`+ Sig.osciSaw 0.7 (freq*0.997) `Sig.mix`+ Sig.osciSaw 0.5 (freq*0.999))++stereoOsciSawPacked :: Float -> Sig.T (Stereo.T (Value Float))+stereoOsciSawPacked freq =+ let mix4 =+ Frame.mixVector .+ flip asTypeOf (undefined :: Value (Vector D4 Float))+ in liftA2 Stereo.cons+ (Sig.map mix4 $+ Sig.osciPlain Wave.saw+ (value $ constVector $ map constOf [0.0, 0.2, 0.1, 0.4])+ (value $ constVector $+ map (constOf . (freq*)) [1.001, 1.003, 0.995, 0.996]))+ (Sig.map mix4 $+ Sig.osciPlain Wave.saw+ (value $ constVector $ map constOf [0.1, 0.7, 0.5, 0.7])+ (value $ constVector $+ map (constOf . (freq*)) [1.005, 0.997, 0.999, 1.001]))++stereoOsciSawPacked2 :: Float -> Sig.T (Stereo.T (Value Float))+stereoOsciSawPacked2 freq =+ Sig.map (Frame.mixVectorToStereo .+ flip asTypeOf (undefined :: Value (Vector D8 Float))) $+ Sig.osciPlain (Wave.trapezoidSkew (A.fromRational' 0.2))+ (valueOf $+ LLVM.toVector (0.0, 0.2, 0.1, 0.4, 0.1, 0.7, 0.5, 0.7))+ (value $ constVector $+ map (constOf . (freq*)) $+ [1.001, 1.003, 0.995, 0.996, 1.005, 0.997, 0.999, 1.001])++stereo :: IO ()+stereo =+ SV.writeFile "speedtest.f32" $+ asStereo $+ Sig.render 10000000 $+ Sig.amplifyStereo 0.25 $+ stereoOsciSawPacked2 0.01++lazy :: IO ()+lazy =+ SVL.writeFile "speedtest.f32" $+ SVL.take 10000000 $+ asMono $+ Sig.renderChunky (SVL.chunkSize 100000)+ {- SVL.defaultChunkSize - too slow -} $+ Sig.envelope+ (Sig.exponential2 50000 1)+ (Sig.osci Wave.sine 0.5 0.01 :: Sig.T (Value Float))++lazyStereo :: IO ()+lazyStereo =+ SVL.writeFile "speedtest.f32" $+ SVL.take 10000000 $+ asStereo $+ Sig.renderChunky (SVL.chunkSize 100000) $+ Sig.amplifyStereo 0.25 $+ stereoOsciSawPacked 0.01++packTake :: IO ()+packTake =+ SVL.writeFile "speedtest.f32" $+ asMonoPacked $+ flip (SigP.renderChunky (SVL.chunkSize 1000)) () $+ SigPS.packRotate $+ (CausalP.take 5 $*+ SigP.osciSimple Wave.saw 0 (frequency 0.01))++chord :: Float -> Sig.T (Stereo.T (Value Float))+chord base =+ {-+ This exceeds available vector registers+ and thus needs more stack accesses.+ Thus it needs twice as much time as the simple mixing.+ However doing all 32 oscillators in parallel+ and mix them in one go might be still faster.++ foldl1 (Sig.zipWith Frame.mixStereoV) $+ -}+ foldl1 Sig.mix $+ map (\f -> stereoOsciSawPacked2 (base*f)) $+ 0.25 : 1.00 : 1.25 : 1.50 : []++lazyChord :: IO ()+lazyChord =+ SVL.writeFile "speedtest.f32" $+ SVL.take 10000000 $+ asStereo $+ Sig.renderChunky (SVL.chunkSize 100000) $+ Sig.amplifyStereo 0.1 $+ chord 0.005++filterSweepComplex :: IO ()+filterSweepComplex =+ SVL.writeFile "speedtest.f32" $+ SVL.take 10000000 $+ asStereo $+ Sig.renderChunky (SVL.chunkSize 100000) $+ Sig.amplifyStereo 0.3 $+ Causal.apply BandPass.causal $+ Sig.zip+ (Sig.map (BandPass.parameter (valueOf 100)) $+ Sig.map (\x -> 0.01 * exp (2 * return x)) $+ Sig.osci Wave.sine 0 (0.1/44100)) $+ chord 0.005++lfoSine ::+ (Memory.C a) =>+ (forall r. Value Float -> LLVM.CodeGenFunction r a) ->+ Param.T p Float ->+ SigP.T p a+lfoSine f reduct =+ SigP.mapSimple f $+ SigP.mapSimple (\x -> 0.01 * exp (2 * return x)) $+ SigP.osciSimple Wave.sine 0 (reduct * 0.1/44100)++filterSweep :: IO ()+filterSweep =+ SVL.writeFile "speedtest.f32" $+ SVL.take 10000000 $+ asMono $+ flip (SigP.renderChunky (SVL.chunkSize 10000)) () $+ (0.2 *+ CtrlP.processCtrlRate 128+ (lfoSine (Filt2.bandpassParameter (valueOf 100)))+ $* SigP.osciSimple Wave.saw 0 (frequency 0.01))++filterSweepPacked :: IO ()+filterSweepPacked =+ SVL.writeFile "speedtest.f32" $+ SVL.take (div 10000000 4) $+ asMonoPacked $+ flip (SigP.renderChunky (SVL.chunkSize 10000)) () $+ (0.2 *+ CtrlPS.processCtrlRate 128+ (lfoSine (Filt2.bandpassParameter (valueOf 100)))+ $* SigPS.osciSimple Wave.saw 0 0.01)++exponentialFilter2Packed :: IO ()+exponentialFilter2Packed =+ SVL.writeFile "speedtest.f32" $+ SVL.take (div 10000000 16) $+ asMonoPacked16 $+ flip (SigP.renderChunky (SVL.chunkSize 10000)) () $+ (Filt2.causalPackedP+ $< (SigP.constant $#+ Filt2Core.Parameter (1::Float) 0 0 0 0.99)+ $* (+-- (CausalP.delay1 $# Serial.fromList [0.1,0.01,0.001,0.0001::Float])+-- (CausalP.delay1 $# Serial.fromList [1::Float])+ (CausalP.delay1 $# Serial.fromList ((1::Float):repeat 0))+ $* 0))++filterSweepPacked2 :: IO ()+filterSweepPacked2 =+ SVL.writeFile "speedtest.f32" $+ SVL.take 10000000 $+ asMono $+ flip (SigP.renderChunky (SVL.chunkSize 10000)) () $+ (0.2 *+ CtrlP.processCtrlRate 128+ (lfoSine (Filt2P.bandpassParameter (valueOf 100)))+ $* SigP.osciSimple Wave.saw 0 (frequency 0.01))++butterworthNoisePacked :: IO ()+butterworthNoisePacked =+ SVL.writeFile "speedtest.f32" $+ SVL.take (div 10000000 4) $+ asMonoPacked $+ flip (SigP.renderChunky (SVL.chunkSize 10000)) () $+ (CausalPS.amplify 0.2 .+ CtrlPS.processCtrlRate 128+ (lfoSine (Butterworth.parameter TypeNum.d3 FiltR.Lowpass (valueOf 0.5)))+ $* SigPS.noise 0 0.3)++chebyshevNoisePacked :: IO ()+chebyshevNoisePacked =+ SVL.writeFile "speedtest.f32" $+ SVL.take (div 10000000 4) $+ asMonoPacked $+ flip (SigP.renderChunky (SVL.chunkSize 10000)) () $+ (CausalPS.amplify 0.2 .+ CtrlPS.processCtrlRate 128+ (lfoSine (Chebyshev.parameterA TypeNum.d5 FiltR.Lowpass (valueOf 0.5)))+ $* SigPS.noise 0 0.3)++{-+Provoke non-aligned vector accesses by calling alloca for a record of 5 floats+in LLVM-2.6.+However, the vector accesses are those of noise.+Using scalar Noise there is no problem.+-}+noiseAllocaBug :: IO ()+noiseAllocaBug =+ SVL.writeFile "speedtest.f32" $+ SVL.take (div 10000000 4) $+ asMonoPacked $+ flip (SigP.renderChunky (SVL.chunkSize 10000)) () $+ (CausalPS.amplify 0.2 . Filt2.causalPackedP+ $< (SigP.mapSimple (const $ Memory.load =<< LLVM.alloca) $+ (SigP.constant $# (0::Float)))+ $* SigPS.noise 0 0.3)++noiseAllocaScalar :: IO ()+noiseAllocaScalar =+ SVL.writeFile "speedtest.f32" $+ SVL.take 10000000 $+ asMono $+ flip (SigP.renderChunky (SVL.chunkSize 10000)) () $+ (0.2 * Filt2.causalP+ $< (SigP.mapSimple (const $+ (Memory.load =<< LLVM.alloca ::+ LLVM.CodeGenFunction r (Filt2.Parameter (Value Float)))) $+ (SigP.constant $# (0::Float)))+ $* SigP.noise 0 0.3)+++upsample :: IO ()+upsample =+ SVL.writeFile "speedtest.f32" $+ SVL.take 10000000 $+ asMono $+ Sig.renderChunky (SVL.chunkSize 100000) $+ (let reduct = 128 :: Float+ in Sig.interpolateConstant reduct $+ Sig.osci Wave.sine 0 (reduct*0.1/44100))+++filterSweepControlRateCausal ::+ Causal.T+ (Stereo.T (Value Float))+ (Stereo.T (Value Float))+filterSweepControlRateCausal =+ Causal.amplifyStereo 0.3 <<<+ BandPass.causal <<<+ Causal.feedFst+ (let reduct = 128+ in Sig.interpolateConstant reduct $+ Sig.map (BandPass.parameter (valueOf 100)) $+ Sig.map (\x -> 0.01 * exp (2 * return x)) $+ Sig.osci Wave.sine 0 (reduct*0.1/44100))++filterSweepControlRateProc ::+ Sig.T (Stereo.T (Value Float)) ->+ Sig.T (Stereo.T (Value Float))+filterSweepControlRateProc =+ Causal.apply filterSweepControlRateCausal++{- |+Trigonometric functions are very slow in LLVM+because they are translated to calls to C's math library.+Thus it is advantageous to compute filter parameters+at a lower rate and interpolate constantly.+-}+filterSweepControlRate :: IO ()+filterSweepControlRate =+ SVL.writeFile "speedtest.f32" $+ asStereo $+ SVL.take 10000000 $+ Sig.renderChunky (SVL.chunkSize 100000) $+ filterSweepControlRateProc $+ chord 0.005+++filterSweepMusic :: IO ()+filterSweepMusic =+ do music <- SV.readFile "lichter.f32"+ SVL.writeFile "speedtest.f32" $+ asStereo $+ Sig.renderChunky (SVL.chunkSize 100000) $+ Sig.amplifyStereo 20 $+ filterSweepControlRateProc $+ Sig.fromStorableVector $+ (music :: SV.Vector (Stereo.T Float))+++playFilterSweepMusicLazy :: IO ()+playFilterSweepMusicLazy = do+ IO.withFile "lichter.f32" IO.ReadMode $ \h ->+ playStereo .+-- Sig.amplifyStereo 1.125 .+ Sig.amplifyStereo 20 .+ filterSweepControlRateProc .+ Sig.fromStorableVectorLazy .+ asStereo . snd+ =<< SVL.hGetContentsAsync (SVL.chunkSize 4321) h+ return ()++playFilterSweepMusicCausal :: IO ()+playFilterSweepMusicCausal = do+ do music <- SV.readFile "lichter.f32"+ _ <- SoxPlay.simple SV.hPut SoxOption.none 44100 $+ asStereo $+ Causal.applyStorable+ (Causal.amplifyStereo 20 <<< filterSweepControlRateCausal) $+ (music :: SV.Vector (Stereo.T Float))+ return ()++playFilterSweepMusicCausalLazy :: IO ()+playFilterSweepMusicCausalLazy = do+ IO.withFile "lichter.f32" IO.ReadMode $ \h ->+ playStereoVector .+ Causal.applyStorableChunky+ (Causal.amplifyStereo 20 <<< filterSweepControlRateCausal) .+ asStereo . snd+ =<< SVL.hGetContentsAsync (SVL.chunkSize 43210) h+ return ()++arrangeLazy :: IO ()+arrangeLazy = do+ IO.hSetBuffering IO.stdout IO.NoBuffering+ arrange <- SigStL.makeArranger+ print $+ arrange (SVL.chunkSize 2) $+ EventList.fromPairList $+ (0, SVL.pack (SVL.chunkSize 2) [1,2::Double]) :+ (0, SVL.pack (SVL.chunkSize 2) [3,4,5,6]) :+ (2, SVL.pack (SVL.chunkSize 2) [7,8,9,10]) :+ -- repeat (2, SVL.empty)+-- (2, SVL.empty) :+-- (2, SVL.empty) :+-- (2::NonNeg.Int, error "undefined sound") :+ error "end of list"+ -- []+++{- |+This is inefficient because pingSig is compiled by LLVM+for every occurence of the sound!++randomTones :: IO ()+randomTones = do+ playMonoVector $+ SigStL.arrange (SVL.chunkSize 12345) $+ EventList.fromPairList $ zip+ (cycle $ map (flip div 16 . (44100*)) [1,2,3])+ (cycle $ map (SVL.take 44100 . Sig.renderChunky (SVL.chunkSize 54321) .+ pingSig . (0.01*))+ [1,1.25,1.5,2])+ return ()+-}++{- |+So far we have not managed to compile signals+that depend on parameters.+Thus in order to avoid much recompilation,+we compile and render a few sounds in advance.+-}+pingTones :: [SVL.Vector Float]+pingTones =+ map (SVL.take 44100 . Sig.renderChunky (SVL.chunkSize 4321) .+ pingSig . (0.01*))+ [1,1.25,1.5,2]++pingTonesIO :: IO [SVL.Vector Float]+pingTonesIO =+ fmap+ (\pingVec ->+ map+ (SVL.take 44100 .+ pingVec (SVL.chunkSize 4321) .+ (0.01*))+ [1,1.25,1.5,2])+ (SigP.runChunky pingSigP)++{-+Arrange itself does not seem to have a space leak with temporary data.+However it may leak sound data.+This is not very likely because this would result in a large memory leak.++Generate random tones in order to see whether generated sounds leak.+How does 'arrange' compare with 'concat'?+-}++cycleTones :: IO ()+cycleTones = do+-- playMono $+ pings <- pingTonesIO+ SVL.writeFile "test.f32" $+-- Play.auto (0.01::Double) 44100 $+ asMono $+{-+after 13min runtime memory consumption increased from 2.5 to 3.9+and we get lot of buffer underruns with this implementation of amplification+(renderChunky . amplify . fromStorableVector)+-}+ Sig.renderChunky (SVL.chunkSize 432109) $+ Sig.amplify 0.1 $+ Sig.fromStorableVectorLazy $+{-+after 20min memory consumption increased from 2.5 to 3.4+and we get lot of buffer underruns with applyStorableChunky+-}+{-+applyStorableChunky applied to concatenated zero vectors+starts with memory consumption 1.0 and after an hour, it's still 1.1+without buffer underruns.+-}+{-+ CausalP.applyStorableChunky (CausalP.amplify $# (0.1::Float)) () $+ asMono $+-}+{-+with chunksize 12345678+after 50min runtime the memory consumption increased from 12.0 to 26.2++with chunksize 123+after 25min runtime the memory consumption is constant 7.4+however at start time there 5 buffer underruns, but no more+probably due to initial LLVM compilation++with chunksize 1234567 and SVL.replicate instead of pingTones+we get memory consumption from 1.3 to 3.2 in 15min,+while producing lots of buffer underruns.+After 45min in total, it is still 3.2 of memory consumption.+Is this a memory leak, or isn't it?++with chunksize 12345678 and SVL.replicate+we get from 5.6 to 10.2 in 3min+to 14.9 after total 13min.+-}+{-+ SigStL.arrange (SVL.chunkSize 12345678) $+ EventList.fromPairList $ zip+ (repeat (div 44100 8))+-- (cycle $ map (flip div 4 . (44100*)) [1,2,3])+-}+{-+With plain concatenation of those zero vectors+we stay constantly at 0.4 memory consumption and no buffer underruns over 30min.+-}+ SVL.concat+ (cycle pings)+-- (repeat $ SVL.replicate (SVL.chunkSize 44100) 44100 0)+ return ()+++tonesChunkSize :: SVL.ChunkSize+numTones :: Int++{-+For one-time-compiled fill functions,+larger chunks have no relevant effect on the processing speed.+-}+(tonesChunkSize, numTones) =+ (SVL.chunkSize 441, 200)+-- (SVL.chunkSize 44100, 200)++fst :: Arrow arrow => arrow (a,b) a+fst = arr P.fst++snd :: Arrow arrow => arrow (a,b) b+snd = arr P.snd+++{-# NOINLINE makePing #-}+makePing :: IO ((Float,Float) -> SVL.Vector Float)+makePing =+ let freq = snd+ halfLife = fst+ in fmap ($tonesChunkSize) $+ SigP.runChunky+ (SigP.envelope+ (SigP.exponential2 halfLife 1)+ (SigP.osciSaw 0.5 freq))++tonesDown :: IO ()+tonesDown = do+ let dist = div 44100 10+ pingp <- makePing+ arrange <- SigStL.makeArranger+ playMonoVector $+ CausalP.applyStorableChunky (CausalP.amplify id) (0.03::Float) $+ arrange tonesChunkSize $+ EventList.fromPairList $ zip+ (repeat (NonNeg.fromNumber dist))+ (map (SVL.take (numTones * dist) . curry pingp 50000) $+ iterate (0.999*) 0.01)+ return ()+++vibes :: SigP.T (Float,Float) (Value Float)+vibes =+ let freq = snd+ modDepth = fst+ halfLife = 5000+ -- sine = Wave.sine+ sine = Wave.approxSine4+ in CausalP.envelope+ $< SigP.exponential2 halfLife 1+ $* (((CausalP.osciSimple sine+ $< (CausalP.envelope+ $< SigP.exponential2 halfLife modDepth+ $* (CausalP.osciSimple sine+ $* SigP.constant (return (0::Float) &&& (2*freq)))))+ <<<+ CausalP.mapLinear (0.01*freq) freq+ <<<+ CausalP.osciSimple sine)+ $* SigP.constant (return (0::Float, 0.0001::Float)))++makeVibes :: IO ((Float,Float) -> SVL.Vector Float)+makeVibes =+ fmap ($tonesChunkSize) $+ SigP.runChunky vibes++vibesCycleVector :: ((Float,Float) -> SVL.Vector Float) -> IO (SVL.Vector Float)+vibesCycleVector pingp =+ (\evs -> fmap (\arrange -> arrange tonesChunkSize evs) SigStL.makeArranger) $+ EventList.fromPairList $ zip+ (repeat 5000)+ (map (SVL.take 50000 . pingp) $+ zip+ (map (\k -> 0.5 * (1 - cos k)) $ iterate (0.05+) 0)+ (cycle $ map (0.01*) [1, 1.25, 1.5, 2]))++vibesCycle :: IO ()+vibesCycle = do+ sig <- vibesCycleVector =<< makeVibes+ playMonoVector $+ CausalP.applyStorableChunky (CausalP.amplify id) (0.2::Float) sig+ return ()++vibesEcho :: IO ()+vibesEcho = do+ sig <- vibesCycleVector =<< makeVibes+ playMonoVector $+ CausalP.applyStorableChunky+ (CausalP.amplify id <<<+ CausalP.comb 0.5 7000)+ (0.2::Float) sig+ return ()++vibesReverb :: IO ()+vibesReverb = do+ sig <- vibesCycleVector =<< makeVibes+ playMonoVector $+ CausalP.applyStorableChunky+ (CausalP.amplify id <<<+ CausalP.reverb (mkStdGen 142) 16 (0.9,0.97) (400,1000))+ (0.3::Float) sig+ return ()++vibesReverbStereo :: IO ()+vibesReverbStereo = do+ sig <- vibesCycleVector =<< makeVibes+ playStereoVector $+ CausalP.applyStorableChunky+ (CausalP.amplifyStereo id <<<+ CausalP.stereoFromChannels+ (CausalP.reverb (mkStdGen 142) 16 (0.9,0.97) (400,1000))+ (CausalP.reverb (mkStdGen 857) 16 (0.9,0.97) (400,1000)) <<<+ CausalP.mapSimple Frame.stereoFromMono)+ (0.3::Float) sig+ return ()++++stair :: IO ()+stair =+ SVL.writeFile "speedtest.f32" $+ SVL.take 10000000 $+ asMono $+ flip (SigP.renderChunky tonesChunkSize) () $+ SigP.piecewiseConstant $+ return $+ EventListBT.fromPairList $+ zip+ (iterate (/2) (1::Float))+ (iterate (2*) (1::NonNeg.Int))+++filterBass :: IO ()+filterBass = do+ playStereoVector $+ asStereo $+ flip (SigP.renderChunky tonesChunkSize) () $+ CausalP.apply+ (BandPass.causalP+ <<<+ CausalP.feedSnd+ (liftA2 Stereo.cons+ (SigP.osciSimple Wave.saw 0 (frequency 0.001499))+ (SigP.osciSimple Wave.saw 0 (frequency 0.001501)))+ <<<+ CausalP.mapSimple (BandPass.parameter (valueOf (100::Float)))) $+ SigP.piecewiseConstant $+ return $ EventListBT.fromPairList $+ zip+ (map (((0.03::Float)*) . (2**) . (/12) . fromInteger) $+ randomRs (0,12) (mkStdGen 998))+ (repeat (10000::NonNeg.Int))++ return ()+++{- |+This function is not very efficient,+since it compiles an LLVM mixing routine+for every pair of mixer inputs.+-}+mixVectorRecompile ::+ SVL.Vector Float -> SVL.Vector Float -> SVL.Vector Float+mixVectorRecompile xs ys =+ Sig.renderChunky tonesChunkSize $+ Sig.mix+ (Sig.fromStorableVectorLazy xs)+ (Sig.fromStorableVectorLazy ys)++mixVectorParamIO ::+ IO (SVL.Vector Float -> SVL.Vector Float -> SVL.Vector Float)+mixVectorParamIO =+ fmap curry $+ fmap ($tonesChunkSize) $+ SigP.runChunky+ (SigP.mix+ (SigP.fromStorableVectorLazy fst)+ (SigP.fromStorableVectorLazy snd))++mixVectorCausalIO ::+ IO (SVL.Vector Float -> SVL.Vector Float -> SVL.Vector Float)+mixVectorCausalIO =+ CausalP.runStorableChunky+ (CausalP.mix $<+ SigP.fromStorableVectorLazy id)++mixVectorCausal ::+ SVL.Vector Float -> SVL.Vector Float -> SVL.Vector Float+mixVectorCausal =+ CausalP.applyStorableChunky+ (CausalP.mix $<+ SigP.fromStorableVectorLazy id)++mixVectorStereo ::+ SVL.Vector (Stereo.T Float) ->+ SVL.Vector (Stereo.T Float) ->+ SVL.Vector (Stereo.T Float)+mixVectorStereo =+ CausalP.applyStorableChunky+ (CausalP.mix $<+ SigP.fromStorableVectorLazy id)++mixVectorStereoIO ::+ IO (SVL.Vector (Stereo.T Float) ->+ SVL.Vector (Stereo.T Float) ->+ SVL.Vector (Stereo.T Float))+mixVectorStereoIO =+ CausalP.runStorableChunky+ (CausalP.mix $<+ SigP.fromStorableVectorLazy id)++{-+slightly slower than mixVectorParam+-}+mixVectorHaskell ::+ SVL.Vector Float -> SVL.Vector Float -> SVL.Vector Float+mixVectorHaskell = SVL.zipWith (+)++toneMix :: IO ()+toneMix = do+ pingp <- makePing+ mix <- mixVectorCausalIO+ playMonoVector $+ Causal.applyStorableChunky (Causal.amplify 0.1) $+ foldl1 mix $+ map (curry pingp 1000000) $+ take numTones $+ iterate (*(2/3)) 0.01+ return ()++fadeEnvelope :: SigP.T (Int, Int) (Value Float)+fadeEnvelope =+ let dur :: Param.T (Int, Int) Float+ dur = fmap fromIntegral fst+ in SigP.parabolaFadeIn dur+ `SigP.append`+ (CausalP.take snd $* (SigP.constant $# (1::Float)))+ `SigP.append`+ SigP.parabolaFadeOut dur++fadeEnvelopeWrite :: IO ()+fadeEnvelopeWrite =+ SVL.writeFile "speedtest.f32" $+ asMono $+ SigP.renderChunky (SVL.chunkSize 1234)+ fadeEnvelope (100000, 200000)+++-- | normalize a list of numbers, such that they have a specific average+-- Cf. haskore-supercollider/src/Haskore/Interface/SuperCollider/Example.hs+normalizeLevel :: Fractional a => a -> [a] -> [a]+normalizeLevel newAvrg xs =+ let avrg = sum xs / genericLength xs+ in map ((newAvrg-avrg)+) xs++stereoOsciSawP :: SigP.T Float (Stereo.T (Value Float))+stereoOsciSawP =+ let freq = id+ n = 5+ volume = pure $ recip $ sqrt $ fromIntegral n :: Param.T p Float+ detunes =+ normalizeLevel 1 $ take (2*n) $+ randomRs (0,0.03) $ mkStdGen 912+ phases =+ randomRs (0,1) $ mkStdGen 54+ tones =+ zipWith+ (\phase detune ->+ (SigP.osciSaw $# phase) (fmap (detune*) freq))+ phases detunes+ (tonesLeft,tonesRight) = splitAt n tones+ in SigP.amplifyStereo volume $+ liftA2 Stereo.cons+ (foldl1 SigP.mix tonesLeft)+ (foldl1 SigP.mix tonesRight)++stereoOsciSawVector :: Float -> SVL.Vector (Stereo.T Float)+stereoOsciSawVector =+ SigP.renderChunky tonesChunkSize stereoOsciSawP++stereoOsciSawChord :: [Float] -> SVL.Vector (Stereo.T Float)+stereoOsciSawChord =+ foldl1 mixVectorStereo . map stereoOsciSawVector++stereoOsciSawPad :: Int -> [Float] -> SVL.Vector (Stereo.T Float)+stereoOsciSawPad dur pitches =+ let attack = 20000+ in CausalP.applyStorableChunky+ (CausalP.envelopeStereo $< fadeEnvelope)+ (attack, dur-attack)+ (stereoOsciSawChord pitches)++a0, as0, b0, c1, cs1, d1, ds1, e1, f1, fs1, g1, gs1,+ a1, as1, b1, c2, cs2, d2, ds2, e2, f2, fs2, g2, gs2,+ a2, as2, b2, c3, cs3, d3, ds3, e3, f3, fs3, g3, gs3,+ a3, as3, b3, c4, cs4, d4, ds4, e4, f4, fs4, g4, gs4 :: Float+a0 : as0 : b0 : c1 : cs1 : d1 : ds1 : e1 : f1 : fs1 : g1 : gs1 :+ a1 : as1 : b1 : c2 : cs2 : d2 : ds2 : e2 : f2 : fs2 : g2 : gs2 :+ a2 : as2 : b2 : c3 : cs3 : d3 : ds3 : e3 : f3 : fs3 : g3 : gs3 :+ a3 : as3 : b3 : c4 : cs4 : d4 : ds4 : e4 : f4 : fs4 : g4 : gs4 : _ =+ iterate ((2 ** recip 12) *) (55/44100)+++chordSequence :: [(Int, [Float])]+chordSequence =+ (2, [f1, f2, a2, c3]) :+ (1, [g1, g2, b2, d3]) :+ (2, [c2, g2, c3, e3]) :+ (1, [f1, a2, c3, f3]) :+ (2, [g1, g2, b2, d3]) :+ (1, [gs1, gs2, b2, e3]) :+ (2, [a1, e2, a2, c3]) :+ (1, [g1, g2, b2, d3]) :+ (3, [c2, g2, c3, e3]) :++ (2, [f1, f2, a2, c3]) :+ (1, [g1, g2, b2, d3]) :+ (2, [c2, g2, c3, e3]) :+ (1, [f1, a2, c3, f3]) :+ (2, [g1, g2, b2, d3]) :+ (1, [gs1, gs2, b2, e3]) :+ (2, [a1, e2, a2, c3]) :+ (1, [g1, g2, b2, e3]) :+ (3, [c2, e2, g2, c3]) :+ []+++withDur :: (Int -> a -> v) -> Int -> a -> (v, NonNeg.Int)+withDur f d ps =+ let dur = d*30000+ in (f dur ps, NonNeg.fromNumber dur)+++padMusic :: IO ()+padMusic = do+ arrange <- SigStL.makeArranger+ playStereoVector $+ CausalP.applyStorableChunky (CausalP.amplifyStereo id) (0.1::Float) $+ arrange tonesChunkSize $+ EventListTM.switchTimeR const $+ EventListMT.consTime 0 $+ EventListBT.fromPairList $+ map (\(d,ps) -> withDur stereoOsciSawPad d ps)+ chordSequence+ return ()+++lowpassSweepControlRateCausal ::+ CausalP.T p+ (Stereo.T (Value Float))+ (Stereo.T (Value Float))+lowpassSweepControlRateCausal =+-- CausalP.stereoFromVector $+ CausalP.stereoFromMono $+ UniFilter.lowpass ^<<+ CtrlP.processCtrlRate 128+ (lfoSine (UniFilter.parameter (valueOf (10::Float))))+++moogSweepControlRateCausal ::+ CausalP.T p+ (Stereo.T (Value Float))+ (Stereo.T (Value Float))+moogSweepControlRateCausal =+-- CausalP.stereoFromVector $+ CausalP.stereoFromMono $+ CtrlP.processCtrlRate 128+ (lfoSine (Moog.parameter TypeNum.d8 (valueOf (10::Float))))+++filterMusic :: IO ()+filterMusic = do+ arrange <- SigStL.makeArranger+ playStereoVector $+ CausalP.applyStorableChunky+ (CausalP.amplifyStereo id <<<+ moogSweepControlRateCausal) (0.05::Float) $+ arrange tonesChunkSize $+ EventListTM.switchTimeR const $+ EventListMT.consTime 0 $+ EventListBT.fromPairList $+ map (\(d,ps) -> withDur stereoOsciSawPad d ps)+ chordSequence+ return ()++++stereoOsciSawVectorIO :: IO (Float -> SVL.Vector (Stereo.T Float))+stereoOsciSawVectorIO =+ fmap ($tonesChunkSize) $+ SigP.runChunky $+ stereoOsciSawP++applyFadeEnvelopeIO ::+ IO (Int -> SVL.Vector (Stereo.T Float) -> SVL.Vector (Stereo.T Float))+applyFadeEnvelopeIO =+ fmap+ (\envelope dur sig ->+ let attack = 20000+ in envelope (attack, dur-attack) sig)+ (CausalP.runStorableChunky+ (CausalP.envelopeStereo $< fadeEnvelope))++stereoOsciSawChordIO :: IO ([Float] -> SVL.Vector (Stereo.T Float))+stereoOsciSawChordIO = do+ sawv <- stereoOsciSawVectorIO+ mix <- mixVectorStereoIO+ return (foldl1 mix . map sawv)++stereoOsciSawPadIO :: IO (Int -> [Float] -> SVL.Vector (Stereo.T Float))+stereoOsciSawPadIO = do+ chrd <- stereoOsciSawChordIO+ envelope <- applyFadeEnvelopeIO+ return $+ \ dur pitches -> envelope dur (chrd pitches)++padMusicIO :: IO ()+padMusicIO = do+ arrange <- SigStL.makeArranger+ pad <- stereoOsciSawPadIO+ playStereoVector $+ CausalP.applyStorableChunky (CausalP.amplifyStereo id) (0.08::Float) $+ arrange tonesChunkSize $+ EventListTM.switchTimeR const $+ EventListMT.consTime 0 $+ EventListBT.fromPairList $+ map (uncurry (withDur pad)) $+ chordSequence+ return ()++{-+Apply the envelope separately to each tone of the chord+and mix all tones by 'arrange'.+-}+padMusicSeparate :: IO ()+padMusicSeparate = do+ arrange <- SigStL.makeArranger+ osci <- stereoOsciSawVectorIO+ env <- applyFadeEnvelopeIO+ playStereoVector $+ CausalP.applyStorableChunky (CausalP.amplifyStereo id) (0.08::Float) $+ arrange tonesChunkSize $+ EventList.flatten $+ EventListTM.switchTimeR const $+ EventListMT.consTime 0 $+ EventListBT.fromPairList $+ map (uncurry (withDur (\d ps -> map (\p -> env d (osci p)) ps))) $+ chordSequence+ return ()+++delay :: IO ()+delay =+ SVL.writeFile "speedtest.f32" $+ asMono $+ flip (SigP.renderChunky tonesChunkSize) (0, 10000) $+ CausalP.apply+ ((CausalP.delay $# (0::Float)) fst+ <<< CausalP.take snd) $+ SigP.osciSaw 0 (frequency 0.01)++delayStereo :: IO ()+delayStereo =+ SVL.writeFile "speedtest.f32" $+ asStereo $+ flip (SigP.renderChunky tonesChunkSize) (7, 10000) $+ CausalP.apply+ (CausalP.take snd+ <<<+ liftA2 Stereo.cons+ id ((CausalP.delay $# (0::Float)) fst)) $+ SigP.osciSaw 0 (frequency 0.01)++++allpassControl ::+ (TypeNum.NaturalT n) =>+ n ->+ SigP.T Float (Allpass.CascadeParameter n (Value Float))+allpassControl order =+ let reduct = id+ in SigP.interpolateConstant reduct $+ lfoSine (Allpass.flangerParameter order) reduct++allpassPhaserCausal, allpassPhaserPipeline ::+ SigP.T Float (Value Float) ->+ SigP.T Float (Value Float)+allpassPhaserCausal =+ let order = TypeNum.d16+ in CausalP.apply $+ 0.5 *+ Allpass.phaserP <<<+ CausalP.feedFst (allpassControl order)++allpassPhaserPipeline =+ let order = TypeNum.d16+ in -- (F.nest (TypeNum.fromIntegerT order) SigP.tail .) $+ (SigP.drop (return $ TypeNum.fromIntegerT order) .) $+ CausalP.apply $+ 0.5 *+ Allpass.phaserPipelineP <<<+ CausalP.feedFst (allpassControl order)++allpassPhaser :: IO ()+allpassPhaser =+ SVL.writeFile "speedtest.f32" $+ asMono $+ SVL.take 10000000 $+ flip (SigP.renderChunky (SVL.chunkSize 100000)) 128 $+ allpassPhaserPipeline $+ SigP.osciSaw 0 (frequency 0.01)++noise :: IO ()+noise =+ SVL.writeFile "speedtest.f32" $+ asMono $+ SVL.take 10000000 $+ flip (SigP.renderChunky (SVL.chunkSize 100000)) () $+ (SigP.noise 0 0.3)++noisePacked :: IO ()+noisePacked =+ SVL.writeFile "speedtest.f32" $+ asMonoPacked $+ SVL.take (div 10000000 4) $+ flip (SigP.renderChunky (SVL.chunkSize 100000)) () $+ (SigPS.noise 0 0.3)+-- (SigPS.pack (SigP.noise 0 0.3))+-- (SigPS.packSmall (SigP.noise 0 0.3))++frequencyModulationStorable :: IO ()+frequencyModulationStorable = do+ smp <- SigP.runChunky (SigP.osciSaw 0 (frequency 0.01))+ SVL.writeFile "speedtest.f32" $+ asMono $+ flip (SigP.renderChunky (SVL.chunkSize 100000)) () $+ (CausalP.frequencyModulationLinear+ (SigP.fromStorableVectorLazy $#+ (SVL.take 1000000 $ asMono $+ smp (SVL.chunkSize 1000) ()))+ $*# (0.3::Float))++frequencyModulation :: IO ()+frequencyModulation =+ SVL.writeFile "speedtest.f32" $+ asMono $+ SVL.take 10000000 $+ flip (SigP.renderChunky (SVL.chunkSize 100000)) () $+ (CausalP.frequencyModulationLinear+ (SigP.osciSaw 0 (frequency 0.01))+ $* SigP.exponential2 500000 1)++frequencyModulationStereo :: IO ()+frequencyModulationStereo = do+ smp <- SigP.runChunky (SigP.osciSaw 0 (frequency 0.01))+ SVL.writeFile "speedtest.f32" $+ asStereo $+ flip (SigP.renderChunky (SVL.chunkSize 100000)) () $+ (CausalP.stereoFromMono+ (CausalP.frequencyModulationLinear+ (SigP.fromStorableVectorLazy $#+ (SVL.take 1000000 $ asMono $+ smp (SVL.chunkSize 1000) ())))+ $*# Stereo.cons (0.2999::Float) 0.3001)++frequencyModulationProcess :: IO ()+frequencyModulationProcess =+ SVL.writeFile "speedtest.f32" .+ asMono .+ (\f ->+ f () $ asMono $+ SigP.renderChunky (SVL.chunkSize 512)+ (1 + 0.1 * SigP.osciSimple Wave.approxSine2 (pure (0::Float)) 0.0001)+ ()) =<<+ CausalP.runStorableChunky+ (CausalP.frequencyModulationLinear+ (CausalP.take 50000 $*+ SigP.osciSaw 0 (frequency 0.01)))++++quantize :: IO ()+quantize =+{-+ SV.writeFile "speedtest.f32" $+ asMono $+ (\xs -> SigP.render xs 10000000 ()) $+-}+ SVL.writeFile "speedtest.f32" $+ asMono $+ SVL.take 10000000 $+ flip (SigP.renderChunky (SVL.chunkSize 100000)) () $+ ((CausalP.quantizeLift $# (5.5::Float)) id $*+ SigP.osciSaw 0 (frequency 0.01))++quantizedFilterControl :: IO ()+quantizedFilterControl =+ SVL.writeFile "speedtest.f32" $+ asMono $+ SVL.take 10000000 $+ flip (SigP.renderChunky (SVL.chunkSize 100000)) () $+ CausalP.apply (0.3 * (UniFilter.lowpass ^<< CtrlP.process)) $+ SigP.zip+ ((CausalP.quantizeLift $# (128::Float))+ (CausalP.mapSimple (UniFilter.parameter (valueOf 100)) <<<+-- (CausalP.mapSimple (Moog.parameter TypeNum.d8 (valueOf 100)) <<<+ CausalP.mapSimple (\x -> 0.01 * exp (2 * return x)))+ $* SigP.osciSimple Wave.approxSine2 0 (frequency (0.1/44100))) $+ SigP.osciSaw 0 (frequency 0.01)+++arrowNonShared :: IO ()+arrowNonShared =+ SVL.writeFile "speedtest.f32" $+ asStereo $+ SVL.take 10000000 $+ flip (SigP.renderChunky (SVL.chunkSize 100000)) () $+ (let osci = CausalP.osciSimple Wave.approxSine2+ in liftA2 Stereo.cons osci osci $*+ SigP.constant (return (0::Float, 0.01::Float)))++arrowShared :: IO ()+arrowShared =+ SVL.writeFile "speedtest.f32" $+ asStereo $+ SVL.take 10000000 $+ flip (SigP.renderChunky (SVL.chunkSize 100000)) () $+ (let osci = Func.lift (CausalP.osciSimple Wave.approxSine2)+ in Func.compile (liftA2 Stereo.cons osci osci) $*+ SigP.constant (return (0::Float, 0.01::Float)))++arrowIndependent :: IO ()+arrowIndependent =+ SVL.writeFile "speedtest.f32" $+ asStereo $+ SVL.take 10000000 $+ flip (SigP.renderChunky (SVL.chunkSize 100000)) () $+ (let osci = CausalP.osciSimple Wave.approxSine2+ in Func.compile+ (fmap (uncurry Stereo.cons) $+ osci *** osci Func.$&+ Func.lift id) $*+ SigP.constant (return ((0::Float, 0.01::Float), (0.25::Float, 0.01001::Float))))+++main :: IO ()+main = do+ LLVM.initializeNativeTarget+ arrowIndependent
+ jack/Synthesizer/LLVM/Server/JACK.hs view
@@ -0,0 +1,227 @@+module Main where+-- module Synthesizer.LLVM.Server.JACK where++import qualified Synthesizer.LLVM.Server.CausalPacked.Arrange as Arrange++import Synthesizer.LLVM.Server.CommonPacked (Vector, VectorSize, vectorSize, )++import qualified Synthesizer.LLVM.Server.Option as Option+import Synthesizer.LLVM.Server.Common++import qualified Synthesizer.MIDI.CausalIO.Process as MIO+import qualified Synthesizer.CausalIO.Process as PIO++import qualified Synthesizer.LLVM.CausalParameterized.Process as CausalP+import qualified Synthesizer.LLVM.Storable.Signal as SigStL++import qualified Synthesizer.LLVM.Frame.StereoInterleaved as StereoInt+import qualified Synthesizer.LLVM.Frame.Stereo as Stereo++import qualified Data.StorableVector as SV+import qualified Data.StorableVector.Base as SVB+import Foreign.Marshal.Array (copyArray, )++import qualified Data.EventList.Relative.TimeTime as EventListTT+import qualified Data.EventList.Absolute.TimeTime as EventListAbsTT+import qualified Data.EventList.Absolute.TimeMixed as EventListAbsTM++import qualified Synthesizer.Zip as Zip++import qualified Sound.JACK.Audio as JackAudio+import qualified Sound.JACK.MIDI as JackMIDI+import qualified Sound.JACK.Exception as JackExc+import qualified Sound.JACK as JACK++import Data.IORef (newIORef, readIORef, writeIORef, )++import qualified Sound.MIDI.Message.Channel.Voice as VoiceMsg+import qualified Sound.MIDI.Message.Channel as ChannelMsg+import qualified Sound.MIDI.Message as Msg++import qualified Control.Monad.Exception.Synchronous as Exc+import qualified Control.Monad.Trans.Class as MT++import Control.Arrow (Arrow, (<<<), (^<<), arr, )++{-+import qualified Numeric.NonNegative.Class as NonNeg+import qualified Numeric.NonNegative.Chunky as NonNegChunky+-}+import qualified Numeric.NonNegative.Wrapper as NonNegW++import Prelude hiding (Real, id, )+++type StereoVector = StereoInt.T VectorSize Real++type StrictTime = NonNegW.Integer+++strictTimeFromNFrames :: JACK.NFrames -> StrictTime+strictTimeFromNFrames (JACK.NFrames n) =+ NonNegW.fromNumberMsg "strictTimeFromNFrames" $ fromIntegral n++writeBlock :: JackAudio.Port JACK.Output -> SV.Vector Real -> IO ()+writeBlock output block = do+ outArr <-+ JackAudio.getBufferPtr output $+ JACK.NFrames $ fromIntegral $ SV.length block+ SVB.withStartPtr (SV.map realToFrac block) $+ copyArray outArr++{-# INLINE playFromEvents #-}+playFromEvents ::+ (JACK.Client ->+ (ports -> Exc.ExceptionalT JackExc.All IO ()) ->+ Exc.ExceptionalT JackExc.All IO ()) ->+ (ports -> block -> IO ()) ->+ Option.T ->+ (SampleRate Real ->+ PIO.T Events block) ->+ IO ()+playFromEvents withOutPorts writeBlocks opt process = do+ let Option.ClientName name = Option.clientName opt+ JACK.handleExceptions $+ JACK.withClientDefault name $ \client ->+ JACK.withPort client "input" $ \input ->+ withOutPorts client $ \output -> do+ sampleRate <- MT.lift $ JACK.getSampleRate client+ case process (SampleRate $ fromIntegral sampleRate) of+ PIO.Cons next create delete ->+ {-+ Is the use of 'bracket' correct?+ I think 'delete' must be called with the final state,+ not with the initial one.+ -}+ Exc.bracketT (MT.lift create) (MT.lift . delete) $ \start -> do+ stateRef <- MT.lift $ newIORef start+ let jackProcess nframes = do+ evs <- JackMIDI.readEventsFromPort input nframes+ MT.lift $ do+ let deconsNFrames (JACK.NFrames n) = fromIntegral n+ (block, state) <-+ next+ (EventListTT.collectCoincident $+ EventListTT.mapTime+ (NonNegW.fromNumberMsg "JACK.playFromEvents") $+ EventListTT.fromAbsoluteEventList $+ EventListAbsTT.mapTime+ (flip div (fromIntegral vectorSize) .+ deconsNFrames) $+ EventListAbsTM.snocTime evs nframes)+{-+ (EventListTT.collectCoincident $+ EventListTT.mapTime strictTimeFromNFrames $+ EventListTT.fromAbsoluteEventList $+ EventListAbsTM.snocTime evs nframes)+-}+ =<< readIORef stateRef+ writeIORef stateRef state+ writeBlocks output block+ JACK.withProcess client jackProcess $+ JACK.withActivation client $ MT.lift $ do+ putStrLn $ "started " ++ name ++ "..."+ JACK.waitForBreak+-- MT.lift $ readIORef stateRef++playMonoFromEvents ::+ Option.T ->+ (SampleRate Real ->+ PIO.T Events (SV.Vector Vector)) ->+ IO ()+playMonoFromEvents opt proc =+ playFromEvents+ (flip JACK.withPort "mono")+ writeBlock+ opt+ (\sampleRate -> SigStL.unpackStrict ^<< proc sampleRate)++playStereoFromEvents ::+ Option.T ->+ (SampleRate Real ->+ PIO.T Events (Zip.T (SV.Vector Vector) (SV.Vector Vector))) ->+ IO ()+playStereoFromEvents opt proc =+ playFromEvents+ (\client f ->+ JACK.withPort client "left" $ \left ->+ JACK.withPort client "right" $ \right ->+ f (left, right))+ (\(leftPort,rightPort) (Zip.Cons leftBlock rightBlock) ->+ writeBlock leftPort leftBlock >>+ writeBlock rightPort rightBlock)+ opt+ (\sampleRate ->+ Zip.arrowSplit SigStL.unpackStrict SigStL.unpackStrict+ ^<<+ proc sampleRate)+++keyboard :: IO ()+keyboard = do+ opt <- Option.get+ proc <- Arrange.keyboard++ playMonoFromEvents opt $ proc (Option.channel opt)+++type Events = MIO.Events Msg.T++unconsStereo :: Stereo.T t -> (t, t)+unconsStereo x =+ (Stereo.left x, Stereo.right x)++keyboardFM :: IO ()+keyboardFM = do+ opt <- Option.get+ playStereoFromEvents opt =<<+ Arrange.keyboardFM (arr unconsStereo) (Option.channel opt)+++keyboardDetuneFMCore ::+ FilePath ->+ IO (ChannelMsg.Channel -> VoiceMsg.Program ->+ SampleRate Real ->+ PIO.T+ Events+ (Zip.T (SV.Vector Vector) (SV.Vector Vector)))+keyboardDetuneFMCore =+ Arrange.keyboardDetuneFMCore (arr unconsStereo)++keyboardDetuneFM :: IO ()+keyboardDetuneFM = do+ opt <- Option.get+ proc <- keyboardDetuneFMCore (Option.sampleDirectory opt)+ playStereoFromEvents opt $+ proc (Option.channel opt) (VoiceMsg.toProgram 0)++keyboardMultiChannel :: IO ()+keyboardMultiChannel = do+ opt <- Option.get+ proc <- keyboardDetuneFMCore (Option.sampleDirectory opt)+ mix <- CausalP.processIO CausalP.mix++ playStereoFromEvents opt $ \ sampleRate ->+ foldl1+ (\x y -> mix () <<< Zip.arrowFanout x y)+ (map+ (\chan ->+ proc (ChannelMsg.toChannel chan) (VoiceMsg.toProgram 0)+ sampleRate)+ [0 .. 3])+++voder :: IO ()+voder = do+ opt <- Option.get+ proc <-+ Arrange.voder+ (arr unconsStereo)+ (Option.sampleDirectory opt)++ playStereoFromEvents opt $ \ sampleRate ->+ proc (Option.channel opt) (VoiceMsg.toProgram 5) sampleRate+++main :: IO ()+main = keyboardMultiChannel
+ render/Synthesizer/LLVM/Server/Render.hs view
@@ -0,0 +1,153 @@+module Main (main) where+-- module Synthesizer.LLVM.Server.Render where++import qualified Synthesizer.LLVM.Server.CausalPacked.Arrange as Arrange+import Synthesizer.LLVM.Server.CommonPacked+ (vectorSize, vectorRate, )++import qualified Synthesizer.LLVM.Server.Option as Option+import Synthesizer.LLVM.Server.Common++import qualified Synthesizer.MIDI.CausalIO.Process as MIO+import qualified Synthesizer.CausalIO.Process as PIO+import qualified Synthesizer.PiecewiseConstant.Signal as PC++import qualified Synthesizer.LLVM.CausalParameterized.Process as CausalP+import qualified Synthesizer.LLVM.Storable.Signal as SigStL++import qualified Synthesizer.LLVM.Frame.StereoInterleaved as StereoInt+import qualified Synthesizer.LLVM.Frame.Stereo as Stereo++import qualified Data.StorableVector.Lazy as SVL+import qualified Data.StorableVector as SV++import qualified Data.EventList.Relative.TimeBody as EventList+import qualified Data.EventList.Relative.TimeMixed as EventListTM++import qualified Synthesizer.Zip as Zip++import qualified Sound.MIDI.Message.Channel.Voice as VoiceMsg+import qualified Sound.MIDI.Message.Channel as ChannelMsg++import qualified Sound.MIDI.File as MidiFile+import qualified Sound.MIDI.File.Event as FileEvent+import qualified Sound.MIDI.File.Load as Load++import qualified Sound.Sox.Write as SoxWrite+import qualified Sound.Sox.Play as SoxPlay++import Control.Arrow (Arrow, (<<<), arr, )+import Control.Applicative ((<*>), )++import Data.Monoid (mempty, )++{-+import qualified Numeric.NonNegative.Chunky as NonNegChunky+import qualified Numeric.NonNegative.Class as NonNeg+-}+import qualified Numeric.NonNegative.Wrapper as NonNegW++import qualified System.Exit as Exit+import qualified System.IO as IO++import Prelude hiding (Real, id, )++++strictTimeFromChunkSize :: SVL.ChunkSize -> PC.StrictTime+strictTimeFromChunkSize (SVL.ChunkSize n) =+ NonNegW.fromNumberMsg "strictTimeFromNFrames" $ fromIntegral n+++keyboardMultiChannel ::+ Option.T ->+ IO (SampleRate Real ->+ PIO.T (MIO.Events ChannelMsg.T) (SV.Vector (Stereo.T Real)))+keyboardMultiChannel opt = do+ proc <-+ Arrange.keyboardDetuneFMCore+ (CausalP.mapSimple StereoInt.interleave)+ (Option.sampleDirectory opt)+ mix <- CausalP.processIO CausalP.mix++ return $ \ sampleRate ->+ arr SigStL.unpackStereoStrict+ <<<+ foldl1+ (\x y -> mix () <<< Zip.arrowFanout x y)+ (map+ (\chan ->+ proc (ChannelMsg.toChannel chan) (VoiceMsg.toProgram 0)+ sampleRate)+ [0 .. 3])++{-+This is the duration of rendering after the last MIDI event.++Optimally we would stop rendering after the last sound ends.+Unfortunately with causal processes we have no way+to make the output audio stream longer than the input MIDI stream.+We might make the stream infinitely long+and add an End-Of-Stream marker in the MIDI input+that tells the 'arrange' process to stop after the last sound.+-}+padTime :: Integer+padTime = 2++render ::+ Option.T ->+ IO (MidiFile.T -> SVL.Vector (Stereo.T Real))+render opt = do+ proc <- keyboardMultiChannel opt+ run <- PIO.runCont $ proc $ fmap fromIntegral $ Option.sampleRate opt+ return $+ SVL.fromChunks .+ run (const []) .+ chopEvents (strictTimeFromChunkSize $ Option.chunkSize opt) .+ flip EventListTM.snocTime+ (NonNegW.fromNumberMsg "render end pad" $+ case Option.sampleRate opt of+ SampleRate rate -> padTime * (fromIntegral $ div rate vectorSize)) .+-- flip EventListTM.snocTime (NonNegW.fromNumber 1) .+-- flip EventListTM.snocTime mempty .+ EventList.collectCoincident .+ EventList.mapMaybe (\ev ->+ case ev of+ FileEvent.MIDIEvent mev -> Just mev+ _ -> Nothing) .+ EventList.resample+ (vectorRate $ fmap fromIntegral $ Option.sampleRate opt) .+ (\(MidiFile.Cons typ division tracks) ->+ MidiFile.mergeTracks typ $+ map (MidiFile.secondsFromTicks division) tracks)++handleSoxExit :: IO Exit.ExitCode -> IO ()+handleSoxExit sox = do+ soxResult <- sox+ case soxResult of+ Exit.ExitSuccess -> return ()+ Exit.ExitFailure n -> do+ IO.hPutStrLn IO.stderr $+ "'sox' aborted with exit code " ++ show n+ Exit.exitFailure++main :: IO ()+main = do+ (opt, midiPath, mWavePath) <- Option.get+ case Option.sampleRate opt of+ SampleRate rate ->+ case mWavePath of+ Nothing ->+ handleSoxExit $+ SoxPlay.simple SVL.hPut mempty rate =<<+ (render opt <*> Load.fromFile midiPath)+ -- Rendering to SoX ends with an error code 13, but why?+ Just wavePath ->+ handleSoxExit $+ SoxWrite.simple SVL.hPut mempty wavePath rate =<<+ (render opt <*> Load.fromFile midiPath)+{-+ Just wavePath ->+ SVL.writeFile wavePath =<<+ (render opt <*> Load.fromFile midiPath)+-}
− src/Synthesizer/LLVM/ALSA/BendModulation.hs
@@ -1,85 +0,0 @@-{-# LANGUAGE MultiParamTypeClasses #-}-{-# LANGUAGE UndecidableInstances #-}-{-# LANGUAGE FlexibleInstances #-}-{-# LANGUAGE FlexibleContexts #-}-{-# OPTIONS_GHC -fno-warn-orphans #-}-{- |-Various LLVM related instances of the BM.T type.-I have setup a separate module since these instances are orphan-and need several language extensions.--}-module Synthesizer.LLVM.ALSA.BendModulation (- BM.T(..),- BM.deflt,- BM.shift,- ) where--import qualified Synthesizer.MIDIValue.BendModulation as BM--import qualified LLVM.Extra.Vector as Vector-import qualified LLVM.Extra.Class as Class-import qualified LLVM.Extra.Memory as Memory-import qualified LLVM.Extra.Control as C-import qualified LLVM.Util.Loop as Loop-import qualified LLVM.Core as LLVM--import Control.Applicative (liftA2, )-import qualified Data.TypeLevel.Num as TypeNum---instance (Class.Zero a) => Class.Zero (BM.T a) where- zeroTuple = Class.zeroTuplePointed--{--instance (LLVM.ValueTuple a) => LLVM.ValueTuple (BM.T a) where- buildTuple f = Class.buildTupleTraversable (LLVM.buildTuple f)--instance LLVM.IsTuple a => LLVM.IsTuple (BM.T a) where- tupleDesc = Class.tupleDescFoldable--}--instance (Class.Undefined a) => Class.Undefined (BM.T a) where- undefTuple = Class.undefTuplePointed--instance (C.Select a) => C.Select (BM.T a) where- select = C.selectTraversable--{--instance LLVM.CmpRet a b =>- LLVM.CmpRet (BM.T a) (BM.T b) where--}--instance Class.MakeValueTuple h l =>- Class.MakeValueTuple (BM.T h) (BM.T l) where- valueTupleOf = Class.valueTupleOfFunctor--memory ::- (Memory.C l s, LLVM.IsSized s ss) =>- Memory.Record r (LLVM.Struct (s, (s, ()))) (BM.T l)-memory =- liftA2 BM.Cons- (Memory.element BM.bend TypeNum.d0)- (Memory.element BM.depth TypeNum.d1)--instance- (Memory.C l s, LLVM.IsSized s ss) =>- Memory.C (BM.T l) (LLVM.Struct (s, (s, ()))) where- load = Memory.loadRecord memory- store = Memory.storeRecord memory- decompose = Memory.decomposeRecord memory- compose = Memory.composeRecord memory---instance (Loop.Phi a) => Loop.Phi (BM.T a) where- phis = Class.phisTraversable- addPhis = Class.addPhisFoldable---instance (Vector.ShuffleMatch n v) =>- Vector.ShuffleMatch n (BM.T v) where- shuffleMatch = Vector.shuffleMatchTraversable--instance (Vector.Access n a v) =>- Vector.Access n (BM.T a) (BM.T v) where- insert = Vector.insertTraversable- extract = Vector.extractTraversable
− src/Synthesizer/LLVM/ALSA/MIDI.hs
@@ -1,176 +0,0 @@-{-# LANGUAGE NoImplicitPrelude #-}-{-# LANGUAGE FlexibleContexts #-}-{- |-Convert MIDI events of a MIDI controller to a control signal.--}-module Synthesizer.LLVM.ALSA.MIDI (- module Synthesizer.LLVM.ALSA.MIDI,- Gen.applyModulation,- ) where--import qualified Synthesizer.Generic.ALSA.MIDI as Gen-import qualified Synthesizer.LLVM.ALSA.BendModulation as BM--import Synthesizer.LLVM.CausalParameterized.Process (($>), )-import qualified Synthesizer.LLVM.Parameterized.SignalPacked as SigPS-import qualified Synthesizer.LLVM.CausalParameterized.Process as CausalP-import qualified Synthesizer.LLVM.Parameterized.Signal as SigP-import qualified Synthesizer.LLVM.Parameter as Param-import qualified Synthesizer.LLVM.Wave as Wave--import qualified LLVM.Extra.ScalarOrVector as SoV-import qualified LLVM.Extra.Vector as Vector-import qualified LLVM.Extra.Memory as Memory-import qualified LLVM.Extra.Arithmetic as A-import qualified LLVM.Extra.Class as Class-import qualified LLVM.Core as LLVM--import qualified Data.TypeLevel.Num as TypeNum--import Foreign.Storable (Storable, )--import qualified Algebra.RealField as RealField-import qualified Algebra.Ring as Ring--- import qualified Algebra.Additive as Additive--import Control.Arrow (second, (<<<), (<<^), )-import Control.Monad ({- liftM, -} liftM2, )---- import NumericPrelude.Base-import NumericPrelude.Numeric-import Prelude ()---{--{-# INLINE piecewiseConstantInit #-}-piecewiseConstantInit ::- (Storable y, Class.MakeValueTuple y yl,- Memory.C yl ym, LLVM.IsSized ym ys) =>- y -> EventListTT.T LazyTime y -> SigP.T p yl-piecewiseConstantInit initial evs =- SigP.piecewiseConstant $#- (PC.subdivideInt $- EventListMT.consBody initial evs)---{-# INLINE controllerLinear #-}-controllerLinear ::- (Field.C y, Storable y, Class.MakeValueTuple y yl,- Memory.C yl ym, LLVM.IsSized ym ys) =>- Channel -> Controller ->- (y,y) -> y ->- Filter (SigP.T p yl)-controllerLinear chan ctrl bnd initial =- liftM (piecewiseConstantInit initial .- EventListTT.mapBody (MV.controllerLinear bnd)) $- getControllerEvents chan ctrl---{-# INLINE controllerExponential #-}-controllerExponential ::- (Trans.C y, Storable y, Class.MakeValueTuple y yl,- Memory.C yl ym, LLVM.IsSized ym ys) =>- Channel -> Controller ->- (y,y) -> y ->- Filter (SigP.T p yl)-controllerExponential chan ctrl bnd initial =- liftM (piecewiseConstantInit initial .- EventListTT.mapBody (MV.controllerExponential bnd)) $- getControllerEvents chan ctrl---{- |-@pitchBend channel range center@:-emits frequencies on an exponential scale from-@center/range@ to @center*range@.--}-{-# INLINE pitchBend #-}-pitchBend ::- (Trans.C y, Storable y, Class.MakeValueTuple y yl,- Memory.C yl ym, LLVM.IsSized ym ys) =>- Channel ->- y -> y ->- Filter (SigP.T p yl)-pitchBend chan range center =- liftM (piecewiseConstantInit center .- EventListTT.mapBody (MV.pitchBend range center)) $- getSlice (maybePitchBend chan)--- getPitchBendEvents chan--{-# INLINE channelPressure #-}-channelPressure ::- (Trans.C y, Storable y, Class.MakeValueTuple y yl,- Memory.C yl ym, LLVM.IsSized ym ys) =>- Channel ->- y -> y ->- Filter (SigP.T p yl)-channelPressure chan maxVal initVal =- liftM (piecewiseConstantInit initVal .- EventListTT.mapBody (MV.controllerLinear (0,maxVal))) $- getSlice (maybeChannelPressure chan)---{-# INLINE bendWheelPressure #-}-bendWheelPressure ::- (Ring.C a, LLVM.IsConst a,- RealField.C y, Trans.C y,- LLVM.IsConst y, SoV.Fraction y, SoV.Replicate a y,- Storable y, Class.MakeValueTuple y (LLVM.Value y), LLVM.IsSized y ys) =>- Channel ->- Int -> y -> y -> y ->- Filter (SigP.T p (LLVM.Value y))-bendWheelPressure chan- pitchRange speed wheelDepth pressDepth =- do bend <- pitchBend chan- (2^?(fromIntegral pitchRange/12) `asTypeOf` speed) 1- fm <- controllerLinear chan VoiceMsg.modulation (0,wheelDepth) 0- press <- channelPressure chan pressDepth 0- return $- SigP.envelope bend $- SigP.mapSimple (A.add (LLVM.valueOf 1)) $- SigP.envelope- (SigP.mix fm press)- (SigP.osciSimple Wave.approxSine2 zero $# speed)--}---frequencyFromBendModulation ::- (Ring.C a, LLVM.IsConst a,- Ring.C y, LLVM.IsConst y,- Memory.FirstClass y ym, LLVM.IsSized y ysize, LLVM.IsSized ym ymsize,- Storable y, Class.MakeValueTuple y (LLVM.Value y),- SoV.Fraction y, SoV.Replicate a y) =>- Param.T p y ->- CausalP.T p (BM.T (LLVM.Value y)) (LLVM.Value y)-frequencyFromBendModulation speed =- CausalP.envelope- <<<- second- (CausalP.mapSimple (A.add (SoV.replicateOf 1)) <<< CausalP.envelope- $> SigP.osciSimple Wave.approxSine2 zero speed)- <<^- (\(BM.Cons b m) -> (b,m))---frequencyFromBendModulationPacked ::- (RealField.C a, LLVM.IsConst a, LLVM.IsFloating a,- Memory.FirstClass a am, LLVM.IsSized a asize, LLVM.IsSized am amsize,- LLVM.IsPrimitive am,- Storable a, Class.MakeValueTuple a (LLVM.Value a),- Vector.Real a, SoV.Replicate a (LLVM.Vector n a), TypeNum.Pos n,- TypeNum.Mul n asize vsize, TypeNum.Pos vsize,- TypeNum.Mul n amsize vmsize, TypeNum.Pos vmsize) =>- Param.T p a ->- CausalP.T p- (BM.T (LLVM.Value a))- (LLVM.Value (LLVM.Vector n a))-frequencyFromBendModulationPacked speed =- CausalP.envelope- <<<- second- (CausalP.mapSimple (A.add (SoV.replicateOf 1)) <<< CausalP.envelope- $> SigPS.osciSimple Wave.approxSine2 zero speed)- <<<- CausalP.mapSimple- (\(BM.Cons b m) ->- liftM2 (,) (SoV.replicate b) (SoV.replicate m))
src/Synthesizer/LLVM/Causal/Process.hs view
@@ -1,4 +1,5 @@ {-# LANGUAGE NoImplicitPrelude #-}+{-# LANGUAGE TypeFamilies #-} {-# LANGUAGE ExistentialQuantification #-} {-# LANGUAGE Rank2Types #-} {-# LANGUAGE ForeignFunctionInterface #-}@@ -13,7 +14,7 @@ import qualified LLVM.Extra.ForeignPtr as ForeignPtr import qualified LLVM.Extra.Memory as Memory -- import qualified LLVM.Extra.Control as U-import LLVM.Extra.Class (MakeValueTuple, )+import LLVM.Extra.Class (MakeValueTuple, ValueTuple, ) import qualified Data.StorableVector.Lazy as SVL import qualified Data.StorableVector as SV@@ -36,7 +37,7 @@ import Foreign.ForeignPtr (withForeignPtr, touchForeignPtr, ) import Foreign.Ptr (FunPtr, ) import Control.Exception (bracket, )-import System.IO.Unsafe (unsafePerformIO, unsafeInterleaveIO, )+import qualified System.Unsafe as Unsafe import qualified Number.Ratio as Ratio import qualified Algebra.Field as Field@@ -46,10 +47,12 @@ import NumericPrelude.Numeric import NumericPrelude.Base hiding (and, map, zip, zipWith, ) +import qualified Prelude as P + data T a b =- forall state packed size ioContext.- (Memory.C state packed, IsSized packed size) =>+ forall state ioContext.+ (Memory.C state) => Cons (forall r c. (Phi c) => ioContext ->@@ -65,7 +68,7 @@ -- finalization from IO monad simple ::- (Memory.C state packed, IsSized packed size) =>+ (Memory.C state) => (forall r c. (Phi c) => a -> state -> Maybe.T r c (b, state)) ->@@ -98,7 +101,7 @@ mapAccum (\a s -> fmap (flip (,) s) $ f a) (return ()) mapAccum ::- (Memory.C state packed, IsSized packed size) =>+ (Memory.C state) => (forall r. a -> state -> CodeGenFunction r (b, state)) -> (forall r. CodeGenFunction r state) ->@@ -198,6 +201,20 @@ x / y = zipWith A.fdiv <<< x&&&y +instance (A.PseudoRing b, A.Real b, A.IntegerConstant b) => P.Num (T a b) where+ fromInteger n = pure (A.fromInteger' n)+ negate x = map A.neg <<< x+ x + y = zipWith A.add <<< x&&&y+ x - y = zipWith A.sub <<< x&&&y+ x * y = zipWith A.mul <<< x&&&y+ abs x = map A.abs <<< x+ signum x = map A.signum <<< x++instance (A.Field b, A.Real b, A.RationalConstant b) => P.Fractional (T a b) where+ fromRational x = pure (A.fromRational' x)+ x / y = zipWith A.fdiv <<< x&&&y++ mix :: (A.Additive a) => T (a, a) a@@ -229,11 +246,11 @@ applyStorable ::- (Storable a, MakeValueTuple a valueA, Memory.C valueA structA,- Storable b, MakeValueTuple b valueB, Memory.C valueB structB) =>+ (Storable a, MakeValueTuple a, ValueTuple a ~ valueA, Memory.C valueA,+ Storable b, MakeValueTuple b, ValueTuple b ~ valueB, Memory.C valueB) => T valueA valueB -> SV.Vector a -> SV.Vector b applyStorable (Cons next start createIOContext deleteIOContext) as =- unsafePerformIO $+ Unsafe.performIO $ bracket createIOContext deleteIOContext $ \ ioContext -> SVB.withStartPtr as $ \ aPtr len -> SVB.createAndTrim len $ \ bPtr -> do@@ -266,10 +283,9 @@ compileChunky ::- (Memory.C aValue aStruct,- Memory.C bValue bStruct,- Memory.C state stateStruct,- IsSized stateStruct stateSize) =>+ (Memory.C aValue, Memory.Struct aValue ~ aStruct,+ Memory.C bValue, Memory.Struct bValue ~ bStruct,+ Memory.C state, Memory.Struct state ~ stateStruct) => (forall r. aValue -> state -> Maybe.T r (Value Bool, (Value (Ptr bStruct), state)) (bValue, state)) ->@@ -314,8 +330,8 @@ But this way is disallowed for foreign finalizers. -} runStorableChunky ::- (Storable a, MakeValueTuple a valueA, Memory.C valueA structA,- Storable b, MakeValueTuple b valueB, Memory.C valueB structB) =>+ (Storable a, MakeValueTuple a, ValueTuple a ~ valueA, Memory.C valueA,+ Storable b, MakeValueTuple b, ValueTuple b ~ valueB, Memory.C valueB) => T valueA valueB -> IO (SVL.Vector a -> SVL.Vector b) runStorableChunky (Cons next start createIOContext deleteIOContext) = do@@ -331,10 +347,10 @@ -} ioContextPtr <- ForeignPtr.new (deleteIOContext ioContext) False - return $ \sig -> SVL.fromChunks $ unsafePerformIO $ do+ return $ \sig -> SVL.fromChunks $ Unsafe.performIO $ do statePtr <- ForeignPtr.newInit stopFunc startFunc let go xt =- unsafeInterleaveIO $+ Unsafe.interleaveIO $ case xt of [] -> return [] x:xs -> SVB.withStartPtr x $ \aPtr size -> do@@ -356,12 +372,12 @@ applyStorableChunky ::- (Storable a, MakeValueTuple a valueA, Memory.C valueA structA,- Storable b, MakeValueTuple b valueB, Memory.C valueB structB) =>+ (Storable a, MakeValueTuple a, ValueTuple a ~ valueA, Memory.C valueA,+ Storable b, MakeValueTuple b, ValueTuple b ~ valueB, Memory.C valueB) => T valueA valueB -> SVL.Vector a -> SVL.Vector b applyStorableChunky (Cons next start createIOContext deleteIOContext) sig =- SVL.fromChunks $ unsafePerformIO $ do+ SVL.fromChunks $ Unsafe.performIO $ do ioContext <- createIOContext (startFunc, stopFunc, fill) <- compileChunky (next ioContext) (start ioContext)@@ -376,7 +392,7 @@ ioContextPtr <- ForeignPtr.new (deleteIOContext ioContext) False let go xt =- unsafeInterleaveIO $+ Unsafe.interleaveIO $ case xt of [] -> return [] x:xs -> SVB.withStartPtr x $ \aPtr size -> do
src/Synthesizer/LLVM/CausalParameterized/Controlled.hs view
@@ -1,5 +1,6 @@ {-# LANGUAGE MultiParamTypeClasses #-}-{-# LANGUAGE FunctionalDependencies #-}+{-# LANGUAGE TypeFamilies #-}+{-# LANGUAGE TypeOperators #-} {-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE FlexibleInstances #-} {-# LANGUAGE UndecidableInstances #-}@@ -29,7 +30,8 @@ import qualified LLVM.Extra.Memory as Memory import qualified LLVM.Extra.ScalarOrVector as SoV import qualified LLVM.Extra.Vector as Vector-import qualified LLVM.Extra.Class as Class+import qualified LLVM.Extra.Arithmetic as A+import LLVM.Extra.Class (MakeValueTuple, ValueTuple, ) import qualified LLVM.Core as LLVM import LLVM.Core@@ -37,8 +39,8 @@ import qualified Synthesizer.LLVM.Frame.Stereo as Stereo -import qualified Data.TypeLevel.Num as TypeNum-import qualified Data.TypeLevel.Num.Sets as TypeSet+import qualified Types.Data.Num as TypeNum+import Types.Data.Num.Ops ((:*:), ) import Foreign.Storable (Storable, ) @@ -53,17 +55,19 @@ However it does not uniquely determine the input and output type, since the same filter can run on mono and stereo signals. -}-class C parameter a b | parameter a -> b, parameter b -> a where+class (a ~ Input parameter b, b ~ Output parameter a) => C parameter a b where+ type Input parameter b :: *+ type Output parameter a :: * process :: CausalP.T p (parameter, a) b processCtrlRate :: (C parameter a b,- Memory.C parameter struct, IsSized struct ss,- Memory.FirstClass r rm, IsSized r rs, IsSized rm rmsize,+ Memory.C parameter,+ Memory.FirstClass r, IsSized r, IsSized (Memory.Stored r), Ring.C r, IsFloating r, Storable r, IsConst r,- Class.MakeValueTuple r (Value r),- LLVM.CmpRet r Bool) =>+ MakeValueTuple r, ValueTuple r ~ (Value r),+ LLVM.CmpRet r, LLVM.CmpResult r ~ Bool) => Param.T p r -> (Param.T p r -> SigP.T p parameter) -> CausalP.T p a b@@ -78,91 +82,107 @@ -} instance- (SoV.PseudoModule a v, SoV.IntegerConstant a,- Memory.FirstClass a am, IsSized a as, IsSized am ams,- Memory.FirstClass v vm, IsSized v vs, IsSized vm vms) =>- C (Filt1.Parameter (Value a))- (Value v) (Filt1.Result (Value v)) where+ (A.PseudoModule a v, A.IntegerConstant a,+ Memory.C a, Memory.C v) =>+ C (Filt1.Parameter a) v (Filt1.Result v) where+ type Input (Filt1.Parameter a) (Filt1.Result v) = v+ type Output (Filt1.Parameter a) v = Filt1.Result v process = Filt1.causalP instance- (SoV.PseudoModule a v, SoV.IntegerConstant a,- Memory.FirstClass a am, IsSized a as, IsSized am ams,- Memory.FirstClass v vm, IsSized v vs, IsSized vm vms) =>- C (Filt2.Parameter (Value a))- (Value v) (Value v) where+ (A.PseudoModule a v, A.RationalConstant a,+ Memory.C a, Memory.C v) =>+ C (Filt2.Parameter a) v v where+ type Input (Filt2.Parameter a) v = v+ type Output (Filt2.Parameter a) v = v process = Filt2.causalP instance (Vector.Arithmetic a, SoV.RationalConstant a,- Memory.C (Value (Filt2P.State a)) am, IsSized am size {-,+ Memory.C (Value (Filt2P.State a)) {-, Memory.FirstClass a am, IsSized (Vector TypeNum.D4 a) as, IsSized am ams, LLVM.IsPrimitive am -}) => C (Filt2P.Parameter a) (Value a) (Value a) where+ type Input (Filt2P.Parameter a) (Value a) = Value a+ type Output (Filt2P.Parameter a) (Value a) = Value a process = Filt2P.causalP instance (SoV.PseudoModule a v, SoV.IntegerConstant a,- Memory.FirstClass a am, IsSized a as, IsSized am ams,- Memory.FirstClass v vm, IsSized v vs, IsSized vm vms,- TypeSet.Nat n,- TypeNum.Mul n LLVM.UnknownSize paramSize, TypeSet.Pos paramSize) =>+ Memory.FirstClass a, IsSized a, IsSized (Memory.Stored a),+ Memory.FirstClass v, IsSized v, IsSized (Memory.Stored v),+ TypeNum.NaturalT n,+ TypeNum.PositiveT (n :*: LLVM.UnknownSize)) => C (Cascade.ParameterValue n a) (Value v) (Value v) where+ type Input (Cascade.ParameterValue n a) (Value v) = Value v+ type Output (Cascade.ParameterValue n a) (Value v) = Value v process = Cascade.causalP instance- (SoV.PseudoModule a v, SoV.RationalConstant a,- Memory.FirstClass a am, IsSized a as, IsSized am ams,- Memory.FirstClass v vm, IsSized v vs, IsSized vm vms) =>- C (Allpass.Parameter (Value a))- (Value v) (Value v) where+ (A.PseudoModule a v, A.RationalConstant a,+ Memory.C a, Memory.C v) =>+ C (Allpass.Parameter a) v v where+ type Input (Allpass.Parameter a) v = v+ type Output (Allpass.Parameter a) v = v process = Allpass.causalP instance- (SoV.PseudoModule a v, SoV.RationalConstant a,- Memory.FirstClass a am, IsSized a as, IsSized am ams,- Memory.FirstClass v vm, IsSized v vs, IsSized vm vms,- TypeNum.Nat n) =>- C (Allpass.CascadeParameter n (Value a))- (Value v) (Value v) where+ (A.PseudoModule a v, A.RationalConstant a,+ Memory.C a, Memory.C v,+ TypeNum.NaturalT n) =>+ C (Allpass.CascadeParameter n a) v v where+ type Input (Allpass.CascadeParameter n a) v = v+ type Output (Allpass.CascadeParameter n a) v = v process = Allpass.cascadeP instance (SoV.PseudoModule a v, SoV.IntegerConstant a, Additive.C v, IsConst v,- Memory.FirstClass a am, IsSized a as, IsSized am ams,- Memory.FirstClass v vm, IsSized v vs, IsSized vm vms,- Class.MakeValueTuple a (Value a),- Class.MakeValueTuple v (Value v),+ Memory.FirstClass a, IsSized a, IsSized (Memory.Stored a),+ Memory.FirstClass v, IsSized v, IsSized (Memory.Stored v),+ MakeValueTuple a, ValueTuple a ~ (Value a),+ MakeValueTuple v, ValueTuple v ~ (Value v), Storable v,- TypeSet.Nat n) =>+ TypeNum.NaturalT n) => C (Moog.Parameter n (Value a)) (Value v) (Value v) where+ type Input (Moog.Parameter n (Value a)) (Value v) = Value v+ type Output (Moog.Parameter n (Value a)) (Value v) = Value v process = Moog.causalP +{-+instance+ (A.PseudoModule a v, A.RationalConstant a,+ Memory.C a, Memory.C v,+ TypeNum.NaturalT n) =>+ C (Moog.Parameter n a) v v where+ type Input (Moog.Parameter n a) v = v+ type Output (Moog.Parameter n a) v = v+ process = Moog.causalP+-} instance- (SoV.PseudoModule a v, SoV.RationalConstant a,- Memory.FirstClass a am, IsSized a as, IsSized am ams,- Memory.FirstClass v vm, IsSized v vs, IsSized vm vms) =>- C (UniFilter.Parameter (Value a))- (Value v) (UniFilter.Result (Value v)) where+ (A.PseudoModule a v, A.RationalConstant a,+ Memory.C a, Memory.C v) =>+ C (UniFilter.Parameter a) v (UniFilter.Result v) where+ type Input (UniFilter.Parameter a) (UniFilter.Result v) = v+ type Output (UniFilter.Parameter a) v = UniFilter.Result v process = UniFilter.causalP instance- (IsFloating a, SoV.RationalConstant a,- Memory.FirstClass a am, IsSized a sa, IsSized am ams) =>- C (ComplexFilt.Parameter (Value a))- (Stereo.T (Value a)) (Stereo.T (Value a)) where+ (A.PseudoRing a, A.RationalConstant a, Memory.C a) =>+ C (ComplexFilt.Parameter a) (Stereo.T a) (Stereo.T a) where+ type Input (ComplexFilt.Parameter a) (Stereo.T a) = Stereo.T a+ type Output (ComplexFilt.Parameter a) (Stereo.T a) = Stereo.T a process = ComplexFilt.causalP instance (Vector.Arithmetic a, IsConst a,- Memory.C (Value (Filt2P.State a)) am, IsSized am size) =>+ Memory.C (Value (Filt2P.State a))) => {- (Memory.FirstClass a am, Vector.Arithmetic a, LLVM.IsPrimitive am, IsSized am ams,@@ -170,4 +190,6 @@ -} C (ComplexFiltPack.Parameter a) (Stereo.T (Value a)) (Stereo.T (Value a)) where+ type Input (ComplexFiltPack.Parameter a) (Stereo.T (Value a)) = Stereo.T (Value a)+ type Output (ComplexFiltPack.Parameter a) (Stereo.T (Value a)) = Stereo.T (Value a) process = ComplexFiltPack.causalP
src/Synthesizer/LLVM/CausalParameterized/ControlledPacked.hs view
@@ -1,6 +1,7 @@ {-# LANGUAGE NoImplicitPrelude #-}+{-# LANGUAGE TypeFamilies #-}+{-# LANGUAGE TypeOperators #-} {-# LANGUAGE MultiParamTypeClasses #-}-{-# LANGUAGE FunctionalDependencies #-} {-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE FlexibleInstances #-} {-# LANGUAGE UndecidableInstances #-}@@ -19,26 +20,28 @@ import qualified Synthesizer.LLVM.Filter.Moog as Moog import qualified Synthesizer.LLVM.Filter.Universal as UniFilter +import qualified Synthesizer.LLVM.Frame.SerialVector as Serial 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.Parameter as Param import qualified LLVM.Extra.Memory as Memory import qualified LLVM.Extra.ScalarOrVector as SoV-import qualified LLVM.Extra.Vector as Vector import qualified LLVM.Extra.Class as Class+import qualified LLVM.Extra.Arithmetic as A+import LLVM.Extra.Class (MakeValueTuple, ValueTuple, ) import qualified LLVM.Core as LLVM+import LLVM.Util.Loop (Phi, ) import LLVM.Core- (Value, IsArithmetic, IsFloating, IsConst, IsSized,- Vector, IsPrimitive, )+ (Value, IsFloating, IsConst, IsSized, ) -import qualified Data.TypeLevel.Num as TypeNum-import qualified Data.TypeLevel.Num.Sets as TypeSet+import qualified Types.Data.Num as TypeNum+import Types.Data.Num.Ops ((:*:), ) import Foreign.Storable (Storable, ) -import Control.Arrow ((<<<), first, )+import Control.Arrow ((<<<), arr, first, ) import qualified Algebra.Field as Field -- import qualified Algebra.Module as Module@@ -54,30 +57,32 @@ However it does not uniquely determine the input and output type, since the same filter can run on mono and stereo signals. -}-class C parameter a b | parameter a -> b, parameter b -> a where+class (a ~ Input parameter b, b ~ Output parameter a) => C parameter a b where+ type Input parameter b :: *+ type Output parameter a :: * process :: CausalP.T p (parameter, a) b processCtrlRate :: (C parameter av bv,- Vector.Access n a av,- Vector.Access n b bv,- Memory.C parameter struct, IsSized struct ss,+ Serial.Read av, n ~ Serial.Size av, a ~ Serial.Element av,+ Serial.C bv, n ~ Serial.Size bv, b ~ Serial.Element bv,+ Memory.C parameter, Field.C r, Storable r, IsFloating r,- Memory.FirstClass r rm, IsSized r rs, IsSized rm rms, IsConst r,- Class.MakeValueTuple r (Value r),- LLVM.CmpRet r Bool) =>+ Memory.FirstClass r, Memory.Stored r ~ rm, IsSized r, IsSized rm, IsConst r,+ MakeValueTuple r, ValueTuple r ~ (Value r),+ LLVM.CmpRet r, LLVM.CmpResult r ~ Bool) => Param.T p r -> (Param.T p r -> SigP.T p parameter) -> CausalP.T p av bv processCtrlRate reduct ctrlGen = withSize $ \n -> CausalP.applyFst process (SigP.interpolateConstant- (fmap (/ fromIntegral (TypeNum.toInt n)) reduct)+ (fmap (/ fromInteger (TypeNum.fromIntegerT n)) reduct) (ctrlGen reduct)) withSize ::- (Vector.Access n a av,- Vector.Access n b bv) =>+ (Serial.Read av, n ~ Serial.Size av,+ Serial.Read bv, n ~ Serial.Size bv) => (n -> CausalP.T p av bv) -> CausalP.T p av bv withSize f = f undefined@@ -89,73 +94,80 @@ -} instance- (IsArithmetic a, SoV.IntegerConstant a,- Memory.FirstClass a am, IsSized a as, IsSized am ams,- TypeNum.Pos n, IsPrimitive a) =>- C (Filt1.Parameter (Value a))- (Value (Vector n a)) (Filt1.Result (Value (Vector n a))) where+ (Serial.C v, Serial.Element v ~ a,+ A.PseudoRing a, A.IntegerConstant a, Memory.C a,+ A.PseudoRing v) =>+ C (Filt1.Parameter a) v (Filt1.Result v) where+ type Input (Filt1.Parameter a) (Filt1.Result v) = v+ type Output (Filt1.Parameter a) v = Filt1.Result v process = Filt1.causalPackedP instance- (IsArithmetic a, SoV.IntegerConstant a,- Memory.FirstClass a am, IsSized a as, IsSized am ams,- TypeNum.Pos n, IsPrimitive a, IsPrimitive am,- TypeNum.Mul n as vas, TypeNum.Pos vas,- TypeNum.Mul n ams vams, TypeNum.Pos vams) =>- C (Filt2.Parameter (Value a))- (Value (Vector n a)) (Value (Vector n a)) where+ (Serial.C v, Serial.Element v ~ a,+ A.PseudoRing a, A.IntegerConstant a, Memory.C a,+ A.PseudoRing v, A.IntegerConstant v, Memory.C v) =>+ C (Filt2.Parameter a) v v where+ type Input (Filt2.Parameter a) v = v+ type Output (Filt2.Parameter a) v = v process = Filt2.causalPackedP instance- (IsArithmetic a, SoV.IntegerConstant a, IsPrimitive a, IsPrimitive am,- Memory.FirstClass a am, IsSized a as, IsSized am ams,- TypeSet.Nat n,- TypeNum.Mul n LLVM.UnknownSize paramSize, TypeSet.Pos paramSize,- TypeNum.Pos d,- TypeNum.Mul d as vas, TypeSet.Pos vas,- TypeNum.Mul d ams vams, TypeSet.Pos vams) =>- C (Cascade.ParameterValue n a)- (Value (Vector d a)) (Value (Vector d a)) where+ (A.PseudoModule (LLVM.Value a) v,+ Serial.C v, Serial.Element v ~ LLVM.Value a,+ SoV.IntegerConstant a,+ A.PseudoRing v, A.IntegerConstant v, Memory.C v,+ Memory.FirstClass a, Memory.Stored a ~ am, IsSized a, IsSized am,+ LLVM.IsPrimitive a,+ LLVM.IsPrimitive am,+ TypeNum.PositiveT (n :*: LLVM.UnknownSize),+ TypeNum.NaturalT n) =>+ C (Cascade.ParameterValue n a) v v where+ type Input (Cascade.ParameterValue n a) v = v+ type Output (Cascade.ParameterValue n a) v = v process = Cascade.causalPackedP instance- (IsArithmetic a, SoV.IntegerConstant a,- Memory.FirstClass a am, IsSized a as, IsSized am ams,- TypeNum.Pos n, IsPrimitive a, IsPrimitive am) =>- C (Allpass.Parameter (Value a))- (Value (Vector n a)) (Value (Vector n a)) where+ (Serial.C v, Serial.Element v ~ a,+ Memory.C a, A.IntegerConstant a,+ A.PseudoRing v, A.PseudoRing a) =>+ C (Allpass.Parameter a) v v where+ type Input (Allpass.Parameter a) v = v+ type Output (Allpass.Parameter a) v = v process = Allpass.causalPackedP instance- (IsArithmetic a, SoV.RationalConstant a,- Memory.FirstClass a am, IsSized a as, IsSized am ams,- TypeNum.Pos d, IsPrimitive a,- TypeNum.Nat n) =>- C (Allpass.CascadeParameter n (Value a))- (Value (Vector d a)) (Value (Vector d a)) where+ (TypeNum.NaturalT n,+ Serial.C v, Serial.Element v ~ a,+ A.PseudoRing a, A.IntegerConstant a, Memory.C a,+ A.PseudoRing v, A.RationalConstant v) =>+ C (Allpass.CascadeParameter n a) v v where+ type Input (Allpass.CascadeParameter n a) v = v+ type Output (Allpass.CascadeParameter n a) v = v process = Allpass.cascadePackedP instance (SoV.PseudoModule a a, SoV.IntegerConstant a, Additive.C a,- Memory.FirstClass a am, IsSized a as, IsSized am ams,- Class.MakeValueTuple a (Value a), Storable a,- TypeNum.Pos d, IsPrimitive a,- TypeNum.Nat n) =>+ Memory.FirstClass a, Memory.Stored a ~ am, IsSized a, IsSized am,+ MakeValueTuple a, ValueTuple a ~ (Value a), Storable a,+ TypeNum.PositiveT d, LLVM.IsPrimitive a,+ TypeNum.NaturalT n) => C (Moog.Parameter n (Value a))- (Value (Vector d a)) (Value (Vector d a)) where+ (Serial.Value d a) (Serial.Value d a) where+ type Input (Moog.Parameter n (Value a)) (Serial.Value d a) = (Serial.Value d a)+ type Output (Moog.Parameter n (Value a)) (Serial.Value d a) = (Serial.Value d a) process = CausalPS.pack Moog.causalP <<<- first (CausalP.mapSimple Vector.replicate)+ first (arr Serial.constant) instance- (SoV.PseudoModule a a, SoV.RationalConstant a,- Memory.FirstClass a am, IsSized a as, IsSized am ams,- TypeNum.Pos d, IsPrimitive a) =>- C (UniFilter.Parameter (Value a))- (Value (Vector d a)) (UniFilter.Result (Value (Vector d a))) where+ (Serial.C v, Serial.Element v ~ b, Phi a, Class.Undefined a,+ A.PseudoModule a b, A.IntegerConstant a, Memory.C b) =>+ C (UniFilter.Parameter a) v (UniFilter.Result v) where+ type Input (UniFilter.Parameter a) (UniFilter.Result v) = v+ type Output (UniFilter.Parameter a) v = UniFilter.Result v process = CausalPS.pack UniFilter.causalP <<<- first (CausalP.mapSimple Vector.replicate)+ first (arr Serial.constant)
src/Synthesizer/LLVM/CausalParameterized/Functional.hs view
@@ -1,5 +1,5 @@-{-# LANGUAGE MultiParamTypeClasses #-}-{-# LANGUAGE UndecidableInstances #-}+{-# LANGUAGE TypeFamilies #-}+{-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE ExistentialQuantification #-} {-# LANGUAGE Rank2Types #-} module Synthesizer.LLVM.CausalParameterized.Functional (@@ -7,20 +7,24 @@ lift, ($&), (&|&), compile,+ withArgs, MakeArguments, Arguments, makeArgs, ) where import qualified Synthesizer.LLVM.CausalParameterized.Process as Causal+import qualified Synthesizer.LLVM.Frame.Stereo as Stereo import qualified LLVM.Extra.MaybeContinuation as Maybe import qualified LLVM.Extra.Memory as Memory import qualified LLVM.Extra.Arithmetic as A -import qualified LLVM.Core as LLVM-import LLVM.Extra.Class (MakeValueTuple, )+import LLVM.Extra.Class (MakeValueTuple, ValueTuple, ) import LLVM.Util.Loop (Phi, )-import LLVM.Core (CodeGenFunction, IsSized, )+import LLVM.Core (CodeGenFunction, )+import qualified LLVM.Core as LLVM import qualified Number.Ratio as Ratio+import qualified Algebra.Transcendental as Trans+import qualified Algebra.Algebraic as Algebraic import qualified Algebra.Field as Field import qualified Algebra.Ring as Ring import qualified Algebra.Additive as Additive@@ -39,8 +43,10 @@ import Foreign.Storable (Storable, ) -import System.IO.Unsafe (unsafePerformIO, )+import Data.Tuple.HT (fst3, snd3, thd3, ) +import qualified System.Unsafe as Unsafe+ import Prelude hiding ((.), ) @@ -49,37 +55,32 @@ -- | similar to @Causal.T p a b@ data Code p a b =- forall state packed size ioContext- startParamTuple startParamValue startParamPacked startParamSize- nextParamTuple nextParamValue nextParamPacked nextParamSize.+ forall state ioContext startParamTuple nextParamTuple. (Storable startParamTuple, Storable nextParamTuple,- MakeValueTuple startParamTuple startParamValue,- MakeValueTuple nextParamTuple nextParamValue,- Memory.C startParamValue startParamPacked,- Memory.C nextParamValue nextParamPacked,- LLVM.IsSized startParamPacked startParamSize,- LLVM.IsSized nextParamPacked nextParamSize,- Memory.C state packed,- IsSized packed size) =>+ MakeValueTuple startParamTuple,+ MakeValueTuple nextParamTuple,+ Memory.C (ValueTuple startParamTuple),+ Memory.C (ValueTuple nextParamTuple),+ Memory.C state) => Code (forall r c. (Phi c) =>- nextParamValue ->+ ValueTuple nextParamTuple -> a -> state -> StateT Vault (Maybe.T r c) (b, state)) -- compute next value (forall r.- startParamValue ->+ ValueTuple startParamTuple -> CodeGenFunction r state) -- initial state (p -> IO (ioContext, (nextParamTuple, startParamTuple))) {- initialization from IO monad- This will be run within unsafePerformIO,+ This will be run within Unsafe.performIO, so no observable In/Out actions please! -} (ioContext -> IO ())- -- finalization from IO monad, also run within unsafePerformIO+ -- finalization from IO monad, also run within Unsafe.performIO @@ -141,22 +142,58 @@ f <*> x = fmap (uncurry ($)) $ f &|& x +lift0 :: (forall r. CodeGenFunction r out) -> T p inp out+lift0 f = lift (Causal.mapSimple (const f))++lift1 :: (forall r. a -> CodeGenFunction r out) -> T p inp a -> T p inp out+lift1 f x = Causal.mapSimple f $& x++lift2 :: (forall r. a -> b -> CodeGenFunction r out) -> T p inp a -> T p inp b -> T p inp out+lift2 f x y = Causal.zipWithSimple f $& x&|&y+++instance (A.PseudoRing b, A.Real b, A.IntegerConstant b) => Num (T p a b) where+ fromInteger n = pure (A.fromInteger' n)+ (+) = lift2 A.add+ (-) = lift2 A.sub+ (*) = lift2 A.mul+ abs = lift1 A.abs+ signum = lift1 A.signum++ instance (A.Additive b) => Additive.C (T p a b) where- zero = lift Additive.zero- negate x = Causal.mapSimple A.neg $& x- x + y = Causal.zipWithSimple A.add $& x&|&y- x - y = Causal.zipWithSimple A.sub $& x&|&y+ zero = pure A.zero+ (+) = lift2 A.add+ (-) = lift2 A.sub+ negate = lift1 A.neg instance (A.PseudoRing b, A.IntegerConstant b) => Ring.C (T p a b) where one = pure A.one fromInteger n = pure (A.fromInteger' n)- x * y = Causal.zipWithSimple A.mul $& x&|&y+ (*) = lift2 A.mul instance (A.Field b, A.RationalConstant b) => Field.C (T p a b) where fromRational' x = pure (A.fromRational' $ Ratio.toRational98 x)- x / y = Causal.zipWithSimple A.fdiv $& x&|&y+ (/) = lift2 A.fdiv +instance (A.Transcendental b, A.RationalConstant b) => Algebraic.C (T p a b) where+ sqrt = lift1 A.sqrt+ root n x = lift2 A.pow x (Field.recip $ Ring.fromInteger n)+ x^/r = lift2 A.pow x (Field.fromRational' r) +instance (A.Transcendental b, A.RationalConstant b) => Trans.C (T p a b) where+ pi = lift0 A.pi+ sin = lift1 A.sin+ cos = lift1 A.cos+ (**) = lift2 A.pow+ exp = lift1 A.exp+ log = lift1 A.log++ asin _ = error "LLVM missing intrinsic: asin"+ acos _ = error "LLVM missing intrinsic: acos"+ atan _ = error "LLVM missing intrinsic: atan"++ infixr 0 $& ($&) :: Causal.T p b c -> T p a b -> T p a c@@ -200,7 +237,7 @@ tagUnique :: Code p inp out -> T p inp out tagUnique code =- unsafePerformIO $+ Unsafe.performIO $ fmap (flip tag code) Vault.newKey initialize :: Code p inp out -> Causal.T p inp out@@ -211,3 +248,60 @@ compile :: T p inp out -> Causal.T p inp out compile (Cons code) = initialize code+++{- |+Using 'withArgs' you can simplify++> let x = F.lift (arr fst)+> y = F.lift (arr (fst.snd))+> z = F.lift (arr (snd.snd))+> in F.compile (f x y z)++to++> withArgs $ \(x,(y,z)) -> f x y z+-}+withArgs ::+ (MakeArguments inp) =>+ (Arguments (T p inp) inp -> T p inp out) -> Causal.T p inp out+withArgs = withArgsStart (lift Cat.id)++withArgsStart ::+ (MakeArguments inp) =>+ T p inp inp -> (Arguments (T p inp) inp -> T p inp out) -> Causal.T p inp out+withArgsStart fid f = compile (f (makeArgs fid))+++type family Arguments (f :: * -> *) (arg :: *)++class MakeArguments arg where+ makeArgs :: Functor f => f arg -> Arguments f arg+++{-+I have thought about an Arg type, that marks where to stop descending.+This way we can throw away all of these FlexibleContext instances+and the user can freely choose the granularity of arguments.+However this does not work so easily,+because we would need a functional depedency from, say,+@(Arg a, Arg b)@ to @(a,b)@.+This is the opposite direction to the dependency we use currently.+-}+type instance Arguments f (LLVM.Value a) = f (LLVM.Value a)+instance MakeArguments (LLVM.Value a) where+ makeArgs = id++type instance Arguments f (Stereo.T a) = f (Stereo.T a)+instance MakeArguments (Stereo.T a) where+ makeArgs = id++type instance Arguments f (a,b) = (Arguments f a, Arguments f b)+instance (MakeArguments a, MakeArguments b) =>+ MakeArguments (a,b) where+ makeArgs f = (makeArgs $ fmap fst f, makeArgs $ fmap snd f)++type instance Arguments f (a,b,c) = (Arguments f a, Arguments f b, Arguments f c)+instance (MakeArguments a, MakeArguments b, MakeArguments c) =>+ MakeArguments (a,b,c) where+ makeArgs f = (makeArgs $ fmap fst3 f, makeArgs $ fmap snd3 f, makeArgs $ fmap thd3 f)
+ src/Synthesizer/LLVM/CausalParameterized/FunctionalPlug.hs view
@@ -0,0 +1,342 @@+{-# LANGUAGE TypeFamilies #-}+{-# LANGUAGE ExistentialQuantification #-}+{-# LANGUAGE Rank2Types #-}+{-# LANGUAGE FlexibleContexts #-}+module Synthesizer.LLVM.CausalParameterized.FunctionalPlug (+ T,+ ($&), (&|&),+ run, runPlugOut,+ fromSignal, plug, askParameter, Input,+ withArgs, withArgsPlugOut,+ MakeArguments, Arguments, makeArgs,+ ) where++import qualified Synthesizer.LLVM.Plug.Input as PIn+import qualified Synthesizer.LLVM.Plug.Output as POut++import qualified Synthesizer.LLVM.CausalParameterized.Process as Causal+import qualified Synthesizer.LLVM.Parameterized.Signal as Sig++import qualified Synthesizer.CausalIO.Process as PIO+import qualified Synthesizer.Generic.Cut as CutG+import qualified Synthesizer.Zip as Zip++import qualified Data.EventList.Relative.BodyTime as EventListBT+import qualified Data.StorableVector as SV++import qualified LLVM.Extra.Arithmetic as A+import LLVM.Core (CodeGenFunction, )++import qualified Number.Ratio as Ratio+import qualified Algebra.Transcendental as Trans+import qualified Algebra.Algebraic as Algebraic+import qualified Algebra.Field as Field+import qualified Algebra.Ring as Ring+import qualified Algebra.Additive as Additive++import qualified Control.Monad.Trans.Reader as MR+import qualified Control.Monad.Trans.State as MS++import qualified Data.Set as Set+import qualified Data.Vault as Vault+import Data.Vault (Vault, )+import Data.Unique (Unique, newUnique, )+import Data.Maybe (fromMaybe, )++import Control.Arrow (Arrow, (^<<), (<<^), arr, first, second, )+import Control.Category (Category, id, (.), )+import Control.Applicative (Applicative, (<*>), pure, liftA2, )++import qualified System.Unsafe as Unsafe++import Prelude hiding (id, (.), )+++{- |+This data type detects sharing.+-}+{-+There are two levels of the use of keys.+At the top level, in T's State monad,+we store an object id in order to check,+whether we have already seen a certain object.+If we encounter a known object+then we use the Simple constructor+and fetch the stored Causal output+within the causal process enclosed in Simple.+This and the causal process in the Plugged constructor+are the second level.+These arrows handle a Vault like a state monad+and insert all values they produce into the Vault.+-}+newtype T pp pl inp out =+ Cons (MS.State (Set.Set Unique) (Core pp pl inp out))++{-+We need to hide the x and y types+since these types grow when combining Cores,+and then we could not define numeric instances.+-}+data Core pp pl inp out =+ forall x y. CutG.Read x =>+ Plugged+ (pp -> inp -> x)+ (PIn.T x y)+ (Causal.T pl (y, Vault) (out, Vault))+ |+ {-+ The Simple constructor is needed for reusing shared Causal processes+ and for input without external representation. (a Plug.Input)+ -}+ Simple (Causal.T pl Vault (out, Vault))+++applyCore ::+ Causal.T pl a b ->+ Core pp pl inp a ->+ Core pp pl inp b+applyCore f (Plugged prep plg process) =+ Plugged prep plg (first f . process)+applyCore f (Simple process) =+ Simple (first f . process)++combineCore ::+ Core pp pl inp a ->+ Core pp pl inp b ->+ Core pp pl inp (a,b)+combineCore (Plugged prepA plugA processA) (Plugged prepB plugB processB) =+ Plugged+ (\p -> Zip.arrowFanout (prepA p) (prepB p))+ (PIn.split plugA plugB)+ ((\(a,(b,v)) -> ((a,b), v)) ^<< second processB+ . arr (\((a,v),b) -> (a,(b,v))) .+ first processA <<^ (\((a,b),v) -> ((a,v),b)))+combineCore (Simple processA) (Plugged prepB plugB processB) =+ Plugged prepB plugB+ ((\(b,(a,v)) -> ((a,b), v)) ^<< second processA . processB)+combineCore (Plugged prepA plugA processA) (Simple processB) =+ Plugged prepA plugA+ ((\(a,(b,v)) -> ((a,b), v)) ^<< second processB . processA)+combineCore (Simple processA) (Simple processB) =+ Simple ((\(a,(b,v)) -> ((a,b), v)) ^<< second processB . processA)+++reuseCore :: Vault.Key out -> Core pp pl inp out+reuseCore key =+ Simple (arr (\vault ->+ (fromMaybe (error "key must have been lost") $ Vault.lookup key vault,+ vault)))+++tag ::+ Unique -> Vault.Key out ->+ MS.State (Set.Set Unique) (Core pp pl inp out) ->+ T pp pl inp out+tag unique key stateCore = Cons $ do+ alreadySeen <- MS.gets (Set.member unique)+ if alreadySeen+ then return $ reuseCore key+ else do+ MS.modify (Set.insert unique)+ core <- stateCore+ let store (a,v) = (a, Vault.insert key a v)+ return $+ case core of+ Plugged prep plg process ->+ Plugged prep plg (store ^<< process)+ Simple process ->+ Simple (store ^<< process)++tagUnique ::+ MS.State (Set.Set Unique) (Core pp pl inp out) ->+ T pp pl inp out+tagUnique core =+ Unsafe.performIO $+ fmap ($ core) $ liftA2 tag newUnique Vault.newKey+++infixr 0 $&++($&) ::+ Causal.T pl a b ->+ T pp pl inp a ->+ T pp pl inp b+f $& Cons core =+ tagUnique $ fmap (applyCore f) core+++infixr 3 &|&++(&|&) ::+ T pp pl inp a ->+ T pp pl inp b ->+ T pp pl inp (a,b)+Cons coreA &|& Cons coreB =+ tagUnique $ liftA2 combineCore coreA coreB+++instance Functor (Core pp pl inp) where+ fmap f (Simple process) = Simple (fmap (first f) process)+ fmap f (Plugged prep plg process) = Plugged prep plg (fmap (first f) process)++instance Applicative (Core pp pl inp) where+ pure a = lift0Core $ pure a+ f <*> x = fmap (uncurry ($)) $ combineCore f x++lift0Core :: (forall r. CodeGenFunction r out) -> Core pp pl inp out+lift0Core f = Simple (Causal.mapSimple (\v -> fmap (flip (,) v) f))+++instance Functor (T pp pl inp) where+ fmap f (Cons x) = tagUnique $ fmap (fmap f) x++instance Applicative (T pp pl inp) where+ pure a = tagUnique $ pure $ pure a+ f <*> x = fmap (uncurry ($)) $ f &|& x+++lift0 :: (forall r. CodeGenFunction r out) -> T pp pl inp out+lift0 f = tagUnique $ pure $ lift0Core f++lift1 :: (forall r. a -> CodeGenFunction r out) -> T pp pl inp a -> T pp pl inp out+lift1 f x = Causal.mapSimple f $& x++lift2 :: (forall r. a -> b -> CodeGenFunction r out) -> T pp pl inp a -> T pp pl inp b -> T pp pl inp out+lift2 f x y = Causal.zipWithSimple f $& x&|&y+++instance (A.PseudoRing b, A.Real b, A.IntegerConstant b) => Num (T pp pl a b) where+ fromInteger n = pure (A.fromInteger' n)+ (+) = lift2 A.add+ (-) = lift2 A.sub+ (*) = lift2 A.mul+ abs = lift1 A.abs+ signum = lift1 A.signum+++instance (A.Additive b) => Additive.C (T pp pl a b) where+ zero = pure A.zero+ (+) = lift2 A.add+ (-) = lift2 A.sub+ negate = lift1 A.neg++instance (A.PseudoRing b, A.IntegerConstant b) => Ring.C (T pp pl a b) where+ one = pure A.one+ fromInteger n = pure (A.fromInteger' n)+ (*) = lift2 A.mul++instance (A.Field b, A.RationalConstant b) => Field.C (T pp pl a b) where+ fromRational' x = pure (A.fromRational' $ Ratio.toRational98 x)+ (/) = lift2 A.fdiv++instance (A.Transcendental b, A.RationalConstant b) => Algebraic.C (T pp pl a b) where+ sqrt = lift1 A.sqrt+ root n x = lift2 A.pow x (Field.recip $ Ring.fromInteger n)+ x^/r = lift2 A.pow x (Field.fromRational' r)++instance (A.Transcendental b, A.RationalConstant b) => Trans.C (T pp pl a b) where+ pi = lift0 A.pi+ sin = lift1 A.sin+ cos = lift1 A.cos+ (**) = lift2 A.pow+ exp = lift1 A.exp+ log = lift1 A.log++ asin _ = error "LLVM missing intrinsic: asin"+ acos _ = error "LLVM missing intrinsic: acos"+ atan _ = error "LLVM missing intrinsic: atan"++++fromSignal ::+ Sig.T pl a ->+ T pp pl inp a+fromSignal sig =+ tagUnique $ pure $ Simple (Causal.feedFst sig)++++type Input pp a = MR.Reader (pp, a)++plug ::+ (CutG.Read b, PIn.Default b) =>+ Input pp a b ->+ T pp pl a (PIn.Element b)+plug accessor =+ tagUnique $ pure $+ Plugged+ (curry $ MR.runReader accessor)+ PIn.deflt+ id++askParameter :: Input pp a pp+askParameter = MR.asks fst+++runPlugOut ::+ T pp pl a x -> POut.T x b ->+ IO (pp -> pl -> PIO.T a b)+runPlugOut (Cons core) pout =+ case MS.evalState core Set.empty of+ Plugged prep pin process ->+ fmap (\f pp pl -> f pl <<^ prep pp) $+ Causal.processIOCore+ pin+ (fst ^<< process <<^ flip (,) Vault.empty)+ pout+ Simple _ ->+ error "FunctionalPlug.runPlugOut: no substantial input available"+ -- Simple process ->+ -- Causal.processIOCore pin process pout++run ::+ (POut.Default b) =>+ T pp pl a (POut.Element b) ->+ IO (pp -> pl -> PIO.T a b)+run f = runPlugOut f POut.deflt+++{- |+Cf. 'F.withArgs'.+-}+withArgs ::+ (MakeArguments a, POut.Default b) =>+ (Arguments (Input pp a) a -> T pp pl a (POut.Element b)) ->+ IO (pp -> pl -> PIO.T a b)+withArgs f = withArgsPlugOut f POut.deflt++withArgsPlugOut ::+ (MakeArguments a) =>+ (Arguments (Input pp a) a -> T pp pl a x) ->+ POut.T x b ->+ IO (pp -> pl -> PIO.T a b)+withArgsPlugOut = withArgsPlugOutStart (MR.asks snd)++withArgsPlugOutStart ::+ (MakeArguments a) =>+ Input pp a a ->+ (Arguments (Input pp a) a -> T pp pl a x) ->+ POut.T x b ->+ IO (pp -> pl -> PIO.T a b)+withArgsPlugOutStart fid f = runPlugOut (f (makeArgs fid))++++type family Arguments (f :: * -> *) (arg :: *)++class MakeArguments arg where+ makeArgs :: Functor f => f arg -> Arguments f arg+++type instance Arguments f (EventListBT.T i a) = f (EventListBT.T i a)+instance MakeArguments (EventListBT.T i a) where+ makeArgs = id++type instance Arguments f (SV.Vector a) = f (SV.Vector a)+instance MakeArguments (SV.Vector a) where+ makeArgs = id++type instance Arguments f (Zip.T a b) = (Arguments f a, Arguments f b)+instance (MakeArguments a, MakeArguments b) =>+ MakeArguments (Zip.T a b) where+ makeArgs f = (makeArgs $ fmap Zip.first f, makeArgs $ fmap Zip.second f)
src/Synthesizer/LLVM/CausalParameterized/Process.hs view
@@ -1,4 +1,6 @@ {-# LANGUAGE NoImplicitPrelude #-}+{-# LANGUAGE TypeFamilies #-}+{-# LANGUAGE TypeOperators #-} {-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE ExistentialQuantification #-} {-# LANGUAGE Rank2Types #-}@@ -42,13 +44,14 @@ import qualified LLVM.Extra.Control as C import qualified LLVM.Extra.Class as Class import qualified LLVM.Extra.Arithmetic as A-import LLVM.Extra.Class (MakeValueTuple, Undefined, undefTuple, )+import LLVM.Extra.Class (MakeValueTuple, ValueTuple, Undefined, undefTuple, ) import LLVM.Util.Loop (Phi, ) import LLVM.Core as LLVM-import Data.TypeLevel.Num (D2, )-import Data.TypeLevel.Num.Ops ((:<:), )-import qualified Data.TypeLevel.Num as TypeNum+import Types.Data.Num (D2, )+import Types.Data.Ord ((:<:), )+import qualified Types.Data.Num as TypeNum+import qualified Types.Data.Bool as TypeBool import qualified Control.Monad.HT as M import qualified Control.Arrow as Arr@@ -75,7 +78,7 @@ import Foreign.ForeignPtr (withForeignPtr, ) import Foreign.Ptr (FunPtr, ) import Control.Exception (bracket, )-import System.IO.Unsafe (unsafePerformIO, unsafeInterleaveIO, )+import qualified System.Unsafe as Unsafe import qualified Data.List as List @@ -110,26 +113,26 @@ provide constant input in a comfortable way -} ($*#) ::- (Storable ah, MakeValueTuple ah a,- Memory.C a am, IsSized am as) =>+ (Storable ah, MakeValueTuple ah, ValueTuple ah ~ a,+ Memory.C a) => T p a b -> ah -> Sig.T p b proc $*# x = proc $* (Sig.constant $# x) ($<#) ::- (Storable ah, MakeValueTuple ah a,- Memory.C a am, IsSized am as) =>+ (Storable ah, MakeValueTuple ah, ValueTuple ah ~ a,+ Memory.C a) => T p (a,b) c -> ah -> T p b c proc $<# x = proc $< (Sig.constant $# x) ($>#) ::- (Storable bh, MakeValueTuple bh b,- Memory.C b bm, IsSized bm bs) =>+ (Storable bh, MakeValueTuple bh, ValueTuple bh ~ b,+ Memory.C b) => T p (a,b) c -> bh -> T p a c proc $># x = proc $> (Sig.constant $# x) mapAccumSimple ::- (Memory.C s struct, IsSized struct sa) =>+ (Memory.C s) => (forall r. a -> s -> CodeGenFunction r (b,s)) -> (forall r. CodeGenFunction r s) -> T p a b@@ -149,9 +152,8 @@ {-# INLINE feedbackControlled #-} feedbackControlled :: (Storable ch,- MakeValueTuple ch c,- Memory.C c cp,- IsSized cp cs) =>+ MakeValueTuple ch, ValueTuple ch ~ c,+ Memory.C c) => Param.T p ch -> T p ((ctrl,a),c) b -> T p (ctrl,b) c -> T p (ctrl,a) b feedbackControlled initial forth back =@@ -160,8 +162,11 @@ fromModifier ::- (Value.Flatten ah al, Value.Flatten bh bl, Value.Flatten ch cl,- Value.Flatten sh sl, Memory.C sl sp, IsSized sp ss) =>+ (Value.Flatten ah, Value.Registers ah ~ al,+ Value.Flatten bh, Value.Registers bh ~ bl,+ Value.Flatten ch, Value.Registers ch ~ cl,+ Value.Flatten sh, Value.Registers sh ~ sl,+ Memory.C sl) => Modifier.Simple sh ch ah bh -> T p (cl,al) bl fromModifier (Modifier.Simple initial step) = mapAccumSimple@@ -206,7 +211,8 @@ vectorize ::- (Vector.Access n a va, Vector.Access n b vb) =>+ (Vector.C va, n ~ Vector.Size va, a ~ Vector.Element va,+ Vector.C vb, n ~ Vector.Size vb, b ~ Vector.Element vb) => T p a b -> T p va vb vectorize = vectorizeSize undefined @@ -217,20 +223,22 @@ However, LLVM neglects the order anyway. -} vectorizeSize ::- (Vector.Access n a va, Vector.Access n b vb) =>+ (Vector.C va, n ~ Vector.Size va, a ~ Vector.Element va,+ Vector.C vb, n ~ Vector.Size vb, b ~ Vector.Element vb) => n -> T p a b -> T p va vb vectorizeSize n proc = foldl (\acc i -> replaceChannel i proc acc) (Arr.arr (const $ undefTuple)) $- List.take (TypeNum.toInt n) [0 ..]+ List.take (TypeNum.fromIntegerT n) [0 ..] {- | Given a vector process, replace the i-th output by output that is generated by a scalar process from the i-th input. -} replaceChannel ::- (Vector.Access n a va, Vector.Access n b vb) =>+ (Vector.C va, n ~ Vector.Size va, a ~ Vector.Element va,+ Vector.C vb, n ~ Vector.Size vb, b ~ Vector.Element vb) => Int -> T p a b -> T p va vb -> T p va vb replaceChannel i channel proc = let li = valueOf $ fromIntegral i@@ -242,8 +250,10 @@ Read the i-th element from each array. -} arrayElement ::- (IsFirstClass a, LLVM.GetValue (LLVM.Array dim a) index a,- TypeNum.Nat index, TypeNum.Nat dim, index :<: dim) =>+ (IsFirstClass a, LLVM.GetValue (LLVM.Array dim a) index,+ LLVM.ValueType (LLVM.Array dim a) index ~ a,+ TypeNum.NaturalT index, TypeNum.NaturalT dim,+ (index :<: dim) ~ TypeBool.True) => index -> T p (Value (LLVM.Array dim a)) (Value a) arrayElement i = mapSimple (\array -> LLVM.extractvalue array i)@@ -252,7 +262,8 @@ Read the i-th element from an aggregate type. -} element ::- (IsFirstClass a, LLVM.GetValue agg index a) =>+ (IsFirstClass a, LLVM.GetValue agg index,+ LLVM.ValueType agg index ~ a) => index -> T p (Value agg) (Value a) element i = mapSimple (\array -> LLVM.extractvalue array i)@@ -272,10 +283,9 @@ You may also use '(+)' and a 'Sig.constant' signal or a number literal. -} raise ::- (IsArithmetic a, Storable a,- Memory.FirstClass a am, IsSized am amsize,- MakeValueTuple a (Value a), IsSized a size) =>- Param.T p a -> T p (Value a) (Value a)+ (A.Additive al, Storable a,+ MakeValueTuple a, ValueTuple a ~ al, Memory.C al) =>+ Param.T p a -> T p al al raise = map Frame.mix @@ -299,18 +309,16 @@ You may also use '(*)' and a 'Sig.constant' signal or a number literal. -} amplify ::- (IsArithmetic a, Storable a,- Memory.FirstClass a am, IsSized am amsize,- MakeValueTuple a (Value a), IsSized a size) =>- Param.T p a -> T p (Value a) (Value a)+ (A.PseudoRing al, Storable a,+ MakeValueTuple a, ValueTuple a ~ al, Memory.C al) =>+ Param.T p a -> T p al al amplify = map Frame.amplifyMono amplifyStereo ::- (IsArithmetic a, Storable a,- Memory.FirstClass a am, IsSized am amsize,- MakeValueTuple a (Value a), IsSized a size) =>- Param.T p a -> T p (Stereo.T (Value a)) (Stereo.T (Value a))+ (A.PseudoRing al, Storable a,+ MakeValueTuple a, ValueTuple a ~ al, Memory.C al) =>+ Param.T p a -> T p (Stereo.T al) (Stereo.T al) amplifyStereo = map Frame.amplifyStereo @@ -318,8 +326,8 @@ mapLinear :: (IsArithmetic a, Storable a,- Memory.FirstClass a am, IsSized am amsize,- MakeValueTuple a (Value a), IsSized a size) =>+ Memory.FirstClass a, Memory.Stored a ~ am, IsSized a, IsSized am,+ MakeValueTuple a, ValueTuple a ~ (Value a)) => Param.T p a -> Param.T p a -> T p (Value a) (Value a) mapLinear depth center = map@@ -328,8 +336,9 @@ mapExponential :: (Trans.C a, IsFloating a, IsConst a, Storable a,- Memory.FirstClass a am, IsSized am amsize,- MakeValueTuple a (Value a), IsSized a size) =>+ SoV.TranscendentalConstant a,+ Memory.FirstClass a, Memory.Stored a ~ am, IsSized a, IsSized am,+ MakeValueTuple a, ValueTuple a ~ (Value a)) => Param.T p a -> Param.T p a -> T p (Value a) (Value a) mapExponential depth center = map@@ -348,12 +357,12 @@ that shall be used both for an oscillator and a frequency filter. -} quantizeLift ::- (Memory.C b struct, IsSized struct size,+ (Memory.C b, Ring.C c,- IsFloating c, CmpRet c Bool,- Storable c, MakeValueTuple c (Value c),- Memory.FirstClass c cm, IsSized cm cmsize,- IsConst c, IsSized c sc) =>+ IsFloating c, CmpRet c, CmpResult c ~ Bool,+ Storable c, MakeValueTuple c, ValueTuple c ~ (Value c),+ Memory.FirstClass c, Memory.Stored c ~ cm, IsSized c, IsSized cm,+ IsConst c) => Param.T p c -> T p a b -> T p a b@@ -388,7 +397,7 @@ thus we use 'SoV.addToPhase' which supports that. -} osciCore ::- (Memory.FirstClass t tm, IsSized t size, IsSized tm tmsize,+ (Memory.FirstClass t, Memory.Stored t ~ tm, IsSized t, IsSized tm, IsConst t, SoV.Fraction t, Additive.C t) => T p (Value t, Value t) (Value t) osciCore =@@ -404,7 +413,7 @@ -- (loop Additive.zero (arr snd &&& zipWithSimple SoV.incPhase)) osciSimple ::- (Memory.FirstClass t tm, IsSized t size, IsSized tm tmsize,+ (Memory.FirstClass t, Memory.Stored t ~ tm, IsSized t, IsSized tm, IsConst t, SoV.Fraction t, Additive.C t) => (forall r. Value t -> CodeGenFunction r y) -> T p (Value t, Value t) y@@ -412,7 +421,7 @@ mapSimple wave <<< osciCore shapeModOsci ::- (Memory.FirstClass t tm, IsSized t size, IsSized tm tmsize,+ (Memory.FirstClass t, Memory.Stored t ~ tm, IsSized t, IsSized tm, IsConst t, SoV.Fraction t, Additive.C t) => (forall r. c -> Value t -> CodeGenFunction r y) -> T p (c, (Value t, Value t)) y@@ -428,9 +437,8 @@ -} delay :: (Storable a,- MakeValueTuple a al,- Memory.C al ap,- IsSized ap as) =>+ MakeValueTuple a, ValueTuple a ~ al,+ Memory.C al) => Param.T p a -> Param.T p Int -> T p al al delay initial time = mapSimple RingBuffer.oldest@@ -453,9 +461,8 @@ -} delay1 :: (Storable a,- MakeValueTuple a al,- Memory.C al ap,- IsSized ap as) =>+ MakeValueTuple a, ValueTuple a ~ al,+ Memory.C al) => Param.T p a -> T p al al delay1 initial = loop initial (arr swap)@@ -464,9 +471,8 @@ differentiate :: (A.Additive al, Storable a,- MakeValueTuple a al,- Memory.C al ap,- IsSized ap as) =>+ MakeValueTuple a, ValueTuple a ~ al,+ Memory.C al) => Param.T p a -> T p al al differentiate initial = Cat.id - delay1 initial@@ -476,8 +482,8 @@ -} comb :: (Ring.C a, Storable a,- IsArithmetic a, MakeValueTuple a (Value a),- Memory.FirstClass a am, IsSized a asize, IsSized am amsize) =>+ IsArithmetic a, MakeValueTuple a, ValueTuple a ~ (Value a),+ Memory.FirstClass a, Memory.Stored a ~ am, IsSized a, IsSized am) => Param.T p a -> Param.T p Int -> T p (Value a) (Value a) comb gain time =@@ -487,8 +493,8 @@ combStereo :: (Ring.C a, Storable a,- IsArithmetic a, MakeValueTuple a (Value a),- Memory.FirstClass a am, IsSized a asize, IsSized am amsize) =>+ IsArithmetic a, MakeValueTuple a, ValueTuple a ~ (Value a),+ Memory.FirstClass a, Memory.Stored a ~ am, IsSized a, IsSized am) => Param.T p a -> Param.T p Int -> T p (Stereo.T (Value a)) (Stereo.T (Value a)) combStereo gain time =@@ -505,13 +511,13 @@ -} reverb :: (Field.C a, Random a, Storable a,- IsArithmetic a, MakeValueTuple a (Value a),- Memory.FirstClass a am, IsSized a asize, IsSized am amsize,+ IsArithmetic a, MakeValueTuple a, ValueTuple a ~ (Value a),+ Memory.FirstClass a, Memory.Stored a ~ am, IsSized a, IsSized am, RandomGen g) => g -> Int -> (a,a) -> (Int,Int) -> T p (Value a) (Value a) reverb rnd num gainRange timeRange =- amplify (return (recip (fromIntegral num))) <<<+ amplify (return (recip (fromIntegral num) `asTypeOf` fst gainRange)) <<< (foldl (+) Cat.id $ List.take num $ List.map (\(g,t) -> comb $# g $# t) $@@ -548,8 +554,8 @@ then we may add a more sensible initialization. -} pipeline ::- (Vector.Access n a v, Class.Zero v,- Memory.C v vp, IsSized vp s) =>+ (Vector.C v, a ~ Vector.Element v,+ Class.Zero v, Memory.C v) => T p v v -> T p a a pipeline (Cons next start createIOContext deleteIOContext) = Cons (\param a0 (v0,s0) -> do@@ -583,11 +589,11 @@ The shrinking factor must be non-negative. -} frequencyModulationLinear ::- (-- Memory.C a struct, IsSized struct size,+ (-- Memory.C a, Ring.C a,- IsFloating a, CmpRet a Bool,- Storable a, MakeValueTuple a (Value a),- Memory.FirstClass a am, IsSized a asize, IsSized am amsize,+ IsFloating a, CmpRet a, CmpResult a ~ Bool,+ Storable a, MakeValueTuple a, ValueTuple a ~ (Value a),+ Memory.FirstClass a, Memory.Stored a ~ am, IsSized a, IsSized am, IsConst a) => Sig.T p (Value a) -> T p (Value a) (Value a) frequencyModulationLinear@@ -630,8 +636,8 @@ and thus they cannot read lazy Haskell data multiple times. -} trigger ::- (Storable a, MakeValueTuple a al, C.Select al,- Memory.C al as, IsSized as asize) =>+ (Storable a, MakeValueTuple a, ValueTuple a ~ al, C.Select al,+ Memory.C al) => Param.T p a -> Sig.T p al -> T p (Value Bool) al@@ -655,8 +661,8 @@ On each restart the parameters of type @b@ are passed to the signal. triggerParam ::- (MakeValueTuple a al,- MakeValueTuple b bl) =>+ (MakeValueTuple a, ValueTuple a ~ al,+ MakeValueTuple b, ValueTuple b ~ bl) => Param.T p a -> (Param.T p b -> Sig.T p a) -> T p (Value Bool, bl) al@@ -669,8 +675,8 @@ Exec.Importer (Ptr param -> Word32 -> Ptr a -> Ptr b -> IO Word32) runStorable ::- (Storable a, MakeValueTuple a valueA, Memory.C valueA structA,- Storable b, MakeValueTuple b valueB, Memory.C valueB structB) =>+ (Storable a, MakeValueTuple a, ValueTuple a ~ valueA, Memory.C valueA,+ Storable b, MakeValueTuple b, ValueTuple b ~ valueB, Memory.C valueB) => T p valueA valueB -> IO (p -> SV.Vector a -> SV.Vector b) runStorable (Cons next start createIOContext deleteIOContext) = do@@ -690,7 +696,7 @@ ret (pos :: Value Word32) return $ \p as ->- unsafePerformIO $+ Unsafe.performIO $ bracket (createIOContext p) (deleteIOContext . fst) $ \ (_,params) -> SVB.withStartPtr as $ \ aPtr len ->@@ -703,11 +709,11 @@ (Memory.castStorablePtr bPtr) applyStorable ::- (Storable a, MakeValueTuple a valueA, Memory.C valueA structA,- Storable b, MakeValueTuple b valueB, Memory.C valueB structB) =>+ (Storable a, MakeValueTuple a, ValueTuple a ~ valueA, Memory.C valueA,+ Storable b, MakeValueTuple b, ValueTuple b ~ valueB, Memory.C valueB) => T p valueA valueB -> p -> SV.Vector a -> SV.Vector b-applyStorable gen = unsafePerformIO $ runStorable gen+applyStorable gen = Unsafe.performIO $ runStorable gen @@ -717,14 +723,11 @@ compileChunky ::- (Memory.C valueA structA,- Memory.C valueB structB,- Memory.C state stateStruct,- IsSized stateStruct stateSize,- Memory.C startParamValue startParamStruct,- Memory.C nextParamValue nextParamStruct,- IsSized startParamStruct startParamSize,- IsSized nextParamStruct nextParamSize) =>+ (Memory.C valueA, Memory.Struct valueA ~ structA,+ Memory.C valueB, Memory.Struct valueB ~ structB,+ Memory.C state, Memory.Struct state ~ stateStruct,+ Memory.C startParamValue, Memory.Struct startParamValue ~ startParamStruct,+ Memory.C nextParamValue, Memory.Struct nextParamValue ~ nextParamStruct) => (forall r. nextParamValue -> valueA -> state ->@@ -767,18 +770,13 @@ Exec.Importer (Ptr stateStruct -> IO ()) compilePlugged ::- (Memory.C state stateStruct,- IsSized stateStruct stateSize,- Memory.C startParamValue startParamStruct,- Memory.C nextParamValue nextParamStruct,- IsSized startParamStruct startParamSize,- IsSized nextParamStruct nextParamSize,+ (Memory.C state, Memory.Struct state ~ stateStruct,+ Memory.C startParamValue, Memory.Struct startParamValue ~ startParamStruct,+ Memory.C nextParamValue, Memory.Struct nextParamValue ~ nextParamStruct, Undefined stateIn, Phi stateIn, Undefined stateOut, Phi stateOut,- Memory.C paramValueIn paramStructIn,- Memory.C paramValueOut paramStructOut,- IsSized paramStructIn paramSizeIn,- IsSized paramStructOut paramSizeOut) =>+ Memory.C paramValueIn, Memory.Struct paramValueIn ~ paramStructIn,+ Memory.C paramValueOut, Memory.Struct paramValueOut ~ paramStructOut) => (forall r. paramValueIn -> stateIn -> LLVM.CodeGenFunction r (valueA, stateIn)) ->@@ -834,8 +832,8 @@ runStorableChunky ::- (Storable a, MakeValueTuple a valueA, Memory.C valueA structA,- Storable b, MakeValueTuple b valueB, Memory.C valueB structB) =>+ (Storable a, MakeValueTuple a, ValueTuple a ~ valueA, Memory.C valueA,+ Storable b, MakeValueTuple b, ValueTuple b ~ valueB, Memory.C valueB) => T p valueA valueB -> IO (p -> SVL.Vector a -> SVL.Vector b) runStorableChunky proc =@@ -848,8 +846,8 @@ because it does not have the risk of a memory leak. -} runStorableChunkyCont ::- (Storable a, MakeValueTuple a valueA, Memory.C valueA structA,- Storable b, MakeValueTuple b valueB, Memory.C valueB structB) =>+ (Storable a, MakeValueTuple a, ValueTuple a ~ valueA, Memory.C valueA,+ Storable b, MakeValueTuple b, ValueTuple b ~ valueB, Memory.C valueB) => T p valueA valueB -> IO ((SVL.Vector a -> SVL.Vector b) -> p ->@@ -858,7 +856,7 @@ (startFunc, stopFunc, fill) <- compileChunky next start return $ \ procRest p sig ->- SVL.fromChunks $ unsafePerformIO $ do+ SVL.fromChunks $ Unsafe.performIO $ do (ioContext, (nextParam, startParam)) <- createIOContext p when False $ DebugCnt.with DebugSt.dumpCounter $ do@@ -870,7 +868,7 @@ ForeignPtr.new (deleteIOContext ioContext) nextParam let go xt =- unsafeInterleaveIO $+ Unsafe.interleaveIO $ case xt of [] -> return [] x:xs -> SVB.withStartPtr x $ \aPtr size -> do@@ -894,12 +892,12 @@ go (SVL.chunks sig) applyStorableChunky ::- (Storable a, MakeValueTuple a valueA, Memory.C valueA structA,- Storable b, MakeValueTuple b valueB, Memory.C valueB structB) =>+ (Storable a, MakeValueTuple a, ValueTuple a ~ valueA, Memory.C valueA,+ Storable b, MakeValueTuple b, ValueTuple b ~ valueB, Memory.C valueB) => T p valueA valueB -> p -> SVL.Vector a -> SVL.Vector b applyStorableChunky gen =- unsafePerformIO (runStorableChunky gen)+ Unsafe.performIO (runStorableChunky gen) {-@@ -976,8 +974,8 @@ deleteIOContext ioContext) processIO ::- (Cut.Read a, PIn.Default a b, POut.Default c d) =>- T p b c ->+ (Cut.Read a, PIn.Default a, POut.Default d) =>+ T p (PIn.Element a) (POut.Element d) -> IO (p -> PIO.T a d) processIO proc = processIOCore PIn.deflt proc POut.deflt
src/Synthesizer/LLVM/CausalParameterized/ProcessPacked.hs view
@@ -1,11 +1,9 @@ {-# LANGUAGE NoImplicitPrelude #-}-{-# LANGUAGE MultiParamTypeClasses #-}-{-# LANGUAGE FunctionalDependencies #-}-{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE TypeFamilies #-} {-# LANGUAGE FlexibleContexts #-}-{-# LANGUAGE UndecidableInstances #-} {-# LANGUAGE ExistentialQuantification #-} {-# LANGUAGE Rank2Types #-}+{-# LANGUAGE TypeOperators #-} {-# LANGUAGE ForeignFunctionInterface #-} module Synthesizer.LLVM.CausalParameterized.ProcessPacked where @@ -13,7 +11,7 @@ import qualified Synthesizer.LLVM.CausalParameterized.Process as Causal import qualified Synthesizer.LLVM.Parameter as Param import qualified Synthesizer.LLVM.Frame as Frame-import qualified Synthesizer.LLVM.SerialVector as Serial+import qualified Synthesizer.LLVM.Frame.SerialVector as Serial import qualified Synthesizer.LLVM.Frame.Stereo as Stereo import qualified LLVM.Extra.ScalarOrVector as SoV@@ -23,13 +21,17 @@ import qualified LLVM.Extra.Class as Class import qualified LLVM.Extra.Arithmetic as A import qualified LLVM.Extra.Control as C-import LLVM.Extra.Class (MakeValueTuple, Undefined, undefTuple, )+import LLVM.Extra.Class (MakeValueTuple, ValueTuple, Undefined, undefTuple, ) import LLVM.Core as LLVM -import qualified Data.TypeLevel.Num as TypeNum-import Data.TypeLevel.Num.Ops ((:<:), )+import qualified Types.Data.Bool as TypeBool+import qualified Types.Data.Num as TypeNum+import Types.Data.Num.Ops ((:*:), )+import Types.Data.Ord ((:<:), ) +import qualified Control.Monad.Trans.Class as MT+import qualified Control.Monad.Trans.State as MS import qualified Control.Category as Cat import qualified Control.Arrow as Arr import Control.Arrow ((^<<), (<<<), )@@ -52,28 +54,30 @@ then the last chunk is dropped. -} pack ::- (Vector.Access n a va, Vector.Access n b vb) =>+ (Serial.Read va, n ~ Serial.Size va, a ~ Serial.Element va,+ Serial.C vb, n ~ Serial.Size vb, b ~ Serial.Element vb) => T p a b -> T p va vb pack (Cons next start createIOContext deleteIOContext) = Cons (\param a s -> do- ((_,b2),(_,s2)) <-+ r <- Maybe.lift $ Serial.readStart a+ ((_,w2),(_,s2)) <- Maybe.fromBool $ C.whileLoop (valueOf True,- let b = undefTuple- in ((a,b), (valueOf $ (fromIntegral $ Vector.sizeInTuple b :: Word32), s)))- (\(cont,(_ab0,(i0,_s0))) ->+ let w = undefTuple+ in ((r,w), (valueOf $ (fromIntegral $ Serial.sizeOfIterator w :: Word32), s)))+ (\(cont,(_rw0,(i0,_s0))) -> A.and cont =<< A.cmp CmpGT i0 (value LLVM.zero))- (\(_,((a0,b0),(i0,s0))) -> Maybe.toBool $ do- ai <- Maybe.lift $ Vector.extract (valueOf 0) a0+ (\(_,((r0,w0),(i0,s0))) -> Maybe.toBool $ do+ (ai,r1) <- Maybe.lift $ Serial.readNext r0 (bi,s1) <- next param ai s0 Maybe.lift $ do- a1 <- Vector.rotateDown a0- b1 <- fmap snd $ Vector.shiftDown bi b0+ w1 <- Serial.writeNext bi w0 i1 <- A.dec i0- return ((a1,b1),(i1,s1)))- return (b2, s2))+ return ((r1,w1),(i1,s1)))+ b <- Maybe.lift $ Serial.writeStop w2+ return (b, s2)) start createIOContext deleteIOContext@@ -85,20 +89,17 @@ This is efficient only for simple input processes. -} packSmall ::- (Vector.Access n a va, Vector.Access n b vb) =>+ (Serial.Read va, n ~ Serial.Size va, a ~ Serial.Element va,+ Serial.C vb, n ~ Serial.Size vb, b ~ Serial.Element vb) => T p a b -> T p va vb packSmall (Cons next start createIOContext deleteIOContext) = Cons- (\param a s ->- let vundef = Class.undefTuple- in foldr- (\i rest (v0,s0) -> do- ai <- Maybe.lift $ Vector.extract (valueOf i) a- (bi,s1) <- next param ai s0- v1 <- Maybe.lift $ Vector.insert (valueOf i) bi v0- rest (v1,s1))- return- (take (Vector.sizeInTuple vundef) [0..])- (vundef, s))+ (\param a ->+ MS.runStateT $+ (MT.lift . Maybe.lift . Serial.assemble)+ =<<+ mapM (MS.StateT . next param)+ =<<+ (MT.lift $ Maybe.lift $ Serial.extractAll a)) start createIOContext deleteIOContext@@ -111,144 +112,149 @@ In order to stay causal, we have to delay the output by @n@ samples. -} unpack ::- (Vector.Access n a va, Vector.Access n b vb,- Class.Zero va, Class.Undefined b,- Memory.C va vap, IsSized vap vas,- Memory.C vb vbp, IsSized vbp vbs) =>+ (Serial.Zero va, n ~ Serial.Size va, a ~ Serial.Element va,+ Serial.Read vb, n ~ Serial.Size vb, b ~ Serial.Element vb,+ Memory.C (Serial.WriteIt va), Memory.C (Serial.ReadIt vb),+ Memory.C va,+ Memory.C vb) => T p va vb -> T p a b unpack (Cons next start createIOContext deleteIOContext) = Cons- (\param ai ((a0,b0),(i0,s0)) -> do+ (\param ai ((w0,r0),(i0,s0)) -> do endOfVector <- Maybe.lift $ A.cmp CmpEQ i0 (valueOf 0)- ((a2,b2),(i2,s2)) <-+ ((w2,r2),(i2,s2)) <- Maybe.fromBool $- C.ifThen endOfVector (valueOf True, ((a0,b0),(i0,s0))) $ do+ C.ifThen endOfVector (valueOf True, ((w0,r0),(i0,s0))) $ do+ a0 <- Serial.writeStop w0 (cont1, (b1,s1)) <- Maybe.toBool $ next param a0 s0+ r1 <- Serial.readStart b1+ w1 <- Serial.writeStart return (cont1,- ((Class.undefTuple, b1),- (valueOf $ fromIntegral $ Vector.sizeInTuple a0, s1)))+ ((w1, r1),+ (valueOf $ fromIntegral $ Serial.size a0, s1))) Maybe.lift $ do- a3 <- fmap snd $ Vector.shiftDown ai a2- (bi,b3) <- Vector.shiftDown (Class.undefTuple) b2+ w3 <- Serial.writeNext ai w2+ (bi,r3) <- Serial.readNext r2 i3 <- A.dec i2- return (bi, ((a3,b3),(i3,s2))))+ return (bi, ((w3,r3),(i3,s2)))) (\p -> do s <- start p- return ((Class.zeroTuple, Class.undefTuple), (valueOf (0::Word32), s)))+ w <- Serial.writeZero+ return ((w, Class.undefTuple), (valueOf (0::Word32), s))) createIOContext deleteIOContext raise :: (Storable a, IsArithmetic a, IsConst a,- MakeValueTuple a (Value a),- Memory.FirstClass a am,- IsPrimitive a, IsSized a as,- IsPrimitive am, IsSized am amsize,- TypeNum.Mul n as vas, TypeNum.Pos vas,- TypeNum.Mul n amsize vmsize, TypeNum.Pos vmsize,- TypeNum.Pos n) =>+ MakeValueTuple a, ValueTuple a ~ (Value a),+ Memory.FirstClass a, Memory.Stored a ~ am,+ IsPrimitive a, IsSized a, SizeOf a ~ as,+ IsPrimitive am, IsSized am, SizeOf am ~ amsize,+ TypeNum.PositiveT (n :*: as),+ TypeNum.PositiveT (n :*: amsize),+ TypeNum.PositiveT n) => Param.T p a ->- T p (Value (Vector n a)) (Value (Vector n a))+ T p (Serial.Value n a) (Serial.Value n a) raise x = Causal.map Frame.mix (Serial.replicate ^<< x) amplify :: (Storable a, IsArithmetic a, IsConst a,- MakeValueTuple a (Value a),- Memory.FirstClass a am,- IsPrimitive a, IsSized a asize,- IsPrimitive am, IsSized am amsize,- TypeNum.Mul n asize vas, TypeNum.Pos vas,- TypeNum.Mul n amsize vmsize, TypeNum.Pos vmsize,- TypeNum.Pos n) =>+ MakeValueTuple a, ValueTuple a ~ (Value a),+ Memory.FirstClass a, Memory.Stored a ~ am,+ IsPrimitive a, IsSized a, SizeOf a ~ as,+ IsPrimitive am, IsSized am, SizeOf am ~ amsize,+ TypeNum.PositiveT (n :*: as),+ TypeNum.PositiveT (n :*: amsize),+ TypeNum.PositiveT n) => Param.T p a ->- T p (Value (Vector n a)) (Value (Vector n a))+ T p (Serial.Value n a) (Serial.Value n a) amplify p = Causal.map Frame.amplifyMono (Serial.replicate ^<< p) amplifyStereo :: (Storable a, IsArithmetic a, IsConst a,- MakeValueTuple a (Value a),- Memory.FirstClass a am,- IsPrimitive a, IsSized a asize,- IsPrimitive am, IsSized am amsize,- TypeNum.Mul n asize vas, TypeNum.Pos vas,- TypeNum.Mul n amsize vmsize, TypeNum.Pos vmsize,- TypeNum.Pos n) =>+ MakeValueTuple a, ValueTuple a ~ (Value a),+ Memory.FirstClass a, Memory.Stored a ~ am,+ IsPrimitive a, IsSized a, SizeOf a ~ as,+ IsPrimitive am, IsSized am, SizeOf am ~ amsize,+ TypeNum.PositiveT (n :*: as),+ TypeNum.PositiveT (n :*: amsize),+ TypeNum.PositiveT n) => Param.T p a ->- T p (Stereo.T (Value (Vector n a))) (Stereo.T (Value (Vector n a)))+ T p (Stereo.T (Serial.Value n a)) (Stereo.T (Serial.Value n a)) amplifyStereo p = Causal.map Frame.amplifyStereo (Serial.replicate ^<< p) osciCore ::- (Memory.FirstClass t tm, IsSized t size, IsSized tm tmsize,+ (Memory.FirstClass t, Memory.Stored t ~ tm, IsSized t, IsSized tm, SoV.Fraction t, IsConst t, Vector.Real t, IsPrimitive t,- TypeNum.Pos n,+ TypeNum.PositiveT n, Additive.C t) =>- T p (Value (Vector n t), Value (Vector n t)) (Value (Vector n t))+ T p (Serial.Value n t, Serial.Value n t) (Serial.Value n t) osciCore =- Causal.zipWithSimple SoV.addToPhase <<<+ Causal.zipWithSimple A.addToPhase <<< Arr.second (Causal.mapAccumSimple (\a phase0 -> do- (phase1,b1) <- Vector.cumulate phase0 a- phase2 <- SoV.signedFraction phase1+ (phase1,b1) <- Serial.cumulate phase0 a+ phase2 <- A.signedFraction phase1 return (b1,phase2)) (return (valueOf Additive.zero))) osciSimple ::- (Memory.FirstClass t tm, IsSized t size, IsSized tm tmsize,+ (Memory.FirstClass t, Memory.Stored t ~ tm, IsSized t, IsSized tm, SoV.Fraction t, IsConst t, Vector.Real t, IsPrimitive t,- TypeNum.Pos n,+ TypeNum.PositiveT n, Additive.C t) =>- (forall r. Value (Vector n t) -> CodeGenFunction r y) ->- T p (Value (Vector n t), Value (Vector n t)) y+ (forall r. Serial.Value n t -> CodeGenFunction r y) ->+ T p (Serial.Value n t, Serial.Value n t) y osciSimple wave = Causal.mapSimple wave <<< osciCore shapeModOsci ::- (Memory.FirstClass t tm, IsSized t size, IsSized tm tmsize,+ (Memory.FirstClass t, Memory.Stored t ~ tm, IsSized t, IsSized tm, SoV.Fraction t, IsConst t, Vector.Real t, IsPrimitive t,- TypeNum.Pos n,+ TypeNum.PositiveT n, Additive.C t) =>- (forall r. c -> Value (Vector n t) -> CodeGenFunction r y) ->- T p (c, (Value (Vector n t), Value (Vector n t))) y+ (forall r. c -> Serial.Value n t -> CodeGenFunction r y) ->+ T p (c, (Serial.Value n t, Serial.Value n t)) y shapeModOsci wave = Causal.zipWithSimple wave <<< Arr.second osciCore delay1 ::- (Vector.Access n al va,+ (Serial.C va, n ~ Serial.Size va, al ~ Serial.Element va, Storable a,- MakeValueTuple a al,- Memory.C al ap,- IsSized ap as) =>+ MakeValueTuple a, ValueTuple a ~ al,+ Memory.C al) => Param.T p a -> T p va va delay1 initial = Causal.loop initial $- Causal.mapSimple (fmap swap . uncurry Vector.shiftUp . swap)+ Causal.mapSimple (fmap swap . uncurry Serial.shiftUp . swap) differentiate ::- (Vector.Access n al va,+ (Serial.C va, n ~ Serial.Size va, al ~ Serial.Element va, A.Additive va, Storable a,- MakeValueTuple a al,- Memory.C al ap,- IsSized ap as) =>+ MakeValueTuple a, ValueTuple a ~ al,+ Memory.C al) => Param.T p a -> T p va va differentiate initial = Cat.id - delay1 initial arrayElement ::- (IsFirstClass a, SoV.Replicate a v,- LLVM.GetValue (LLVM.Array dim a) index a,- TypeNum.Nat index, TypeNum.Nat dim, index :<: dim) =>- index -> T p (Value (LLVM.Array dim a)) (Value v)+ (IsFirstClass a, LLVM.Value a ~ Serial.Element v, Serial.C v,+ LLVM.GetValue (LLVM.Array dim a) index,+ LLVM.ValueType (LLVM.Array dim a) index ~ a,+ TypeNum.NaturalT index, TypeNum.NaturalT dim,+ (index :<: dim) ~ TypeBool.True) =>+ index -> T p (Value (LLVM.Array dim a)) v arrayElement i =- Causal.mapSimple SoV.replicate <<< Causal.arrayElement i+ Causal.mapSimple Serial.upsample <<< Causal.arrayElement i
src/Synthesizer/LLVM/CausalParameterized/ProcessPrivate.hs view
@@ -1,4 +1,5 @@ {-# LANGUAGE NoImplicitPrelude #-}+{-# LANGUAGE TypeFamilies #-} {-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE ExistentialQuantification #-} {-# LANGUAGE Rank2Types #-}@@ -12,11 +13,9 @@ import qualified LLVM.Extra.Memory as Memory import qualified LLVM.Core as LLVM-import LLVM.Extra.Class (MakeValueTuple, )+import LLVM.Extra.Class (MakeValueTuple, ValueTuple, ) import LLVM.Util.Loop (Phi, )-import LLVM.Core- (Value, valueOf,- IsSized, CodeGenFunction, )+import LLVM.Core (Value, valueOf, CodeGenFunction, ) import qualified Control.Arrow as Arr import qualified Control.Category as Cat@@ -36,51 +35,45 @@ import NumericPrelude.Numeric import NumericPrelude.Base hiding (and, iterate, map, zip, zipWith, take, takeWhile, ) +import qualified Prelude as P + data T p a b =- forall state packed size ioContext- startParamTuple startParamValue startParamPacked startParamSize- nextParamTuple nextParamValue nextParamPacked nextParamSize.+ forall state ioContext startParamTuple nextParamTuple. (Storable startParamTuple, Storable nextParamTuple,- MakeValueTuple startParamTuple startParamValue,- MakeValueTuple nextParamTuple nextParamValue,- Memory.C startParamValue startParamPacked,- Memory.C nextParamValue nextParamPacked,- IsSized startParamPacked startParamSize,- IsSized nextParamPacked nextParamSize,- Memory.C state packed,- IsSized packed size) =>+ MakeValueTuple startParamTuple,+ MakeValueTuple nextParamTuple,+ Memory.C (ValueTuple startParamTuple),+ Memory.C (ValueTuple nextParamTuple),+ Memory.C state) => Cons (forall r c. (Phi c) =>- nextParamValue ->+ ValueTuple nextParamTuple -> a -> state -> Maybe.T r c (b, state)) -- compute next value (forall r.- startParamValue ->+ ValueTuple startParamTuple -> CodeGenFunction r state) -- initial state (p -> IO (ioContext, (nextParamTuple, startParamTuple))) {- initialization from IO monad- This will be run within unsafePerformIO,+ This will be run within Unsafe.performIO, so no observable In/Out actions please! -} (ioContext -> IO ())- -- finalization from IO monad, also run within unsafePerformIO+ -- finalization from IO monad, also run within Unsafe.performIO simple :: (Storable startParamTuple, Storable nextParamTuple,- MakeValueTuple startParamTuple startParamValue,- MakeValueTuple nextParamTuple nextParamValue,- Memory.C startParamValue startParamPacked,- Memory.C nextParamValue nextParamPacked,- IsSized startParamPacked startParamSize,- IsSized nextParamPacked nextParamSize,- Memory.C state packed,- IsSized packed size) =>+ MakeValueTuple startParamTuple, ValueTuple startParamTuple ~ startParamValue,+ MakeValueTuple nextParamTuple, ValueTuple nextParamTuple ~ nextParamValue,+ Memory.C startParamValue,+ Memory.C nextParamValue,+ Memory.C state) => (forall r c. (Phi c) => nextParamValue ->@@ -111,9 +104,9 @@ mapAccum ::- (Storable pnh, MakeValueTuple pnh pnl, Memory.C pnl pnp, IsSized pnp pns,- Storable psh, MakeValueTuple psh psl, Memory.C psl psp, IsSized psp pss,- Memory.C s struct, IsSized struct sa) =>+ (Storable pnh, MakeValueTuple pnh, ValueTuple pnh ~ pnl, Memory.C pnl,+ Storable psh, MakeValueTuple psh, ValueTuple psh ~ psl, Memory.C psl,+ Memory.C s) => (forall r. pnl -> a -> s -> CodeGenFunction r (b,s)) -> (forall r. psl -> CodeGenFunction r s) -> Param.T p pnh ->@@ -127,7 +120,7 @@ map ::- (Storable ph, MakeValueTuple ph pl, Memory.C pl pp, IsSized pp ps) =>+ (Storable ph, MakeValueTuple ph, ValueTuple ph ~ pl, Memory.C pl) => (forall r. pl -> a -> CodeGenFunction r b) -> Param.T p ph -> T p a b@@ -235,6 +228,20 @@ x / y = zipWithSimple A.fdiv <<< x&&&y +instance (A.PseudoRing b, A.Real b, A.IntegerConstant b) => P.Num (T p a b) where+ fromInteger n = pure (A.fromInteger' n)+ negate x = mapSimple A.neg <<< x+ x + y = zipWithSimple A.add <<< x&&&y+ x - y = zipWithSimple A.sub <<< x&&&y+ x * y = zipWithSimple A.mul <<< x&&&y+ abs x = mapSimple A.abs <<< x+ signum x = mapSimple A.signum <<< x++instance (A.Field b, A.Real b, A.RationalConstant b) => P.Fractional (T p a b) where+ fromRational x = pure (A.fromRational' x)+ x / y = zipWithSimple A.fdiv <<< x&&&y++ {- | Not quite the loop of ArrowLoop because we need a delay of one time step@@ -247,9 +254,8 @@ -} loop :: (Storable ch,- MakeValueTuple ch c,- Memory.C c cp,- IsSized cp cs) =>+ MakeValueTuple ch, ValueTuple ch ~ c,+ Memory.C c) => Param.T p ch -> T p (a,c) (b,c) -> T p a b loop initial (Cons next start createIOContext deleteIOContext) = Cons@@ -265,7 +271,7 @@ takeWhile ::- (Storable ph, MakeValueTuple ph pl, Memory.C pl pp, IsSized pp ps) =>+ (Storable ph, MakeValueTuple ph, ValueTuple ph ~ pl, Memory.C pl) => (forall r. pl -> a -> CodeGenFunction r (Value Bool)) -> Param.T p ph -> T p a a@@ -295,7 +301,7 @@ -} integrate :: (Storable a, A.Additive al,- MakeValueTuple a al, Memory.C al as, IsSized as size) =>+ MakeValueTuple a, ValueTuple a ~ al, Memory.C al) => Param.T p a -> T p al al integrate =@@ -303,7 +309,7 @@ integrate0 :: (Storable a, A.Additive al,- MakeValueTuple a al, Memory.C al as, IsSized as size) =>+ MakeValueTuple a, ValueTuple a ~ al, Memory.C al) => Param.T p a -> T p al al integrate0 =
+ src/Synthesizer/LLVM/CausalParameterized/ProcessValue.hs view
@@ -0,0 +1,84 @@+{-# LANGUAGE TypeFamilies #-}+{- |+This module provides functions similar to+"Synthesizer.LLVM.CausalParameterized.Process"+but expects functions that operate on 'Value.T'.+This way you can use common arithmetic operators+instead of LLVM assembly functions.+-}+module Synthesizer.LLVM.CausalParameterized.ProcessValue (+-- simple,+ mapAccum, map, mapSimple,+ ) where++import Synthesizer.LLVM.CausalParameterized.ProcessPrivate (T, )+import qualified Synthesizer.LLVM.CausalParameterized.ProcessPrivate as Causal+import qualified Synthesizer.LLVM.Parameter as Param++import qualified Synthesizer.LLVM.Simple.Value as Value++import qualified LLVM.Extra.Memory as Memory+import LLVM.Extra.Class (MakeValueTuple, ValueTuple, )++import Foreign.Storable.Tuple ()+import Foreign.Storable (Storable, )++import Prelude hiding (map, )+++{-+simple ::+ (Storable startParamTuple,+ Storable nextParamTuple,+ MakeValueTuple startParamTuple, ValueTuple startParamTuple ~ startParamValue,+ MakeValueTuple nextParamTuple, ValueTuple nextParamTuple ~ nextParamValue,+ Memory.C startParamValue,+ Memory.C nextParamValue,+ Memory.C state) =>+ (Value.T nextParamValue ->+ Value.T a -> Value.T state -> Value.Maybe (Value.T b, Value.T state)) ->+ (Value.T startParamValue -> Value.T state) ->+ Param.T p nextParamTuple ->+ Param.T p startParamTuple -> T p a b+simple f start =+ Causal.simple+ (\p a s ->+ Value.flattenMaybe $+ next+ (Value.constantValue p)+ (Value.constantValue a)+ (Value.constantValue s))+ (Value.unlift1 start)+-}++map ::+ (Storable ph, MakeValueTuple ph, ValueTuple ph ~ pl, Memory.C pl) =>+ (Value.T pl -> Value.T a -> Value.T b) ->+ Param.T p ph ->+ T p a b+map f = Causal.map (Value.unlift2 f)++mapSimple ::+ (Value.T a -> Value.T b) ->+ T p a b+mapSimple f =+ Causal.mapSimple (Value.unlift1 f)++mapAccum ::+ (Storable pnh, MakeValueTuple pnh, ValueTuple pnh ~ pnl, Memory.C pnl,+ Storable psh, MakeValueTuple psh, ValueTuple psh ~ psl, Memory.C psl,+ Memory.C s) =>+ (Value.T pnl -> Value.T a -> Value.T s -> (Value.T b, Value.T s)) ->+ (Value.T psl -> Value.T s) ->+ Param.T p pnh ->+ Param.T p psh ->+ T p a b+mapAccum next start =+ Causal.mapAccum+ (\p a s ->+ Value.flatten $+ next+ (Value.constantValue p)+ (Value.constantValue a)+ (Value.constantValue s))+ (Value.unlift1 start)
src/Synthesizer/LLVM/Complex.hs view
@@ -1,7 +1,4 @@-{-# LANGUAGE MultiParamTypeClasses #-}-{-# LANGUAGE UndecidableInstances #-}-{-# LANGUAGE FlexibleContexts #-}-{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE TypeFamilies #-} {-# OPTIONS_GHC -fno-warn-orphans #-} module Synthesizer.LLVM.Complex ( Complex.T(Complex.real, Complex.imag),@@ -17,10 +14,10 @@ import LLVM.Extra.Class (Undefined, undefTuple, ) import qualified LLVM.Core as LLVM-import LLVM.Core (Value, ConstValue, Struct, IsConst, )+import LLVM.Core (Value, ConstValue, IsConst, ) import LLVM.Util.Loop (Phi, phis, addPhis, ) -import qualified Data.TypeLevel.Num as TypeNum+import qualified Types.Data.Num as TypeNum import Control.Applicative (liftA2, ) @@ -31,8 +28,10 @@ import NumericPrelude.Base -} +type Struct a = LLVM.Struct (a, (a, ()))+ constOf :: IsConst a =>- Complex.T a -> ConstValue (Struct (a, (a, ())))+ Complex.T a -> ConstValue (Struct a) constOf x = LLVM.constStruct (LLVM.constOf $ Complex.real x,@@ -40,7 +39,7 @@ ())) unfold ::- Value (Struct (a, (a, ()))) -> Complex.T (Value.T a)+ Value (Struct a) -> Complex.T (Value.T (Value a)) unfold x = Value.lift0 (LLVM.extractvalue x TypeNum.d0) Complex.+:@@ -61,16 +60,15 @@ memory ::- (Memory.C l s, LLVM.IsSized s ss) =>- Memory.Record r (LLVM.Struct (s, (s, ()))) (Complex.T l)+ (Memory.C l) =>+ Memory.Record r (Struct (Memory.Struct l)) (Complex.T l) memory = liftA2 (Complex.+:) (Memory.element Complex.real TypeNum.d0) (Memory.element Complex.imag TypeNum.d1) -instance- (Memory.C l s, LLVM.IsSized s ss) =>- Memory.C (Complex.T l) (LLVM.Struct (s, (s, ()))) where+instance (Memory.C l) => Memory.C (Complex.T l) where+ type Struct (Complex.T l) = Struct (Memory.Struct l) load = Memory.loadRecord memory store = Memory.storeRecord memory decompose = Memory.decomposeRecord memory
src/Synthesizer/LLVM/ConstantPiece.hs view
@@ -1,9 +1,6 @@ {-# LANGUAGE NoImplicitPrelude #-}-{-# LANGUAGE MultiParamTypeClasses #-}-{-# LANGUAGE FunctionalDependencies #-}-{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE TypeFamilies #-} {-# LANGUAGE FlexibleContexts #-}-{-# LANGUAGE UndecidableInstances #-} {- | Data type that allows handling of piecewise constant signals independently from the source.@@ -25,16 +22,18 @@ import qualified LLVM.Extra.Class as Class import qualified LLVM.Extra.Arithmetic as A import LLVM.Extra.Control (whileLoop, )-import LLVM.Extra.Class (MakeValueTuple, Undefined, undefTuple, )+import LLVM.Extra.Class (MakeValueTuple, ValueTuple, Undefined, undefTuple, ) import LLVM.Util.Loop (Phi, phis, addPhis, )-import LLVM.Core as LLVM+import LLVM.Core (Value, valueOf, )+import qualified LLVM.Core as LLVM -import Data.TypeLevel.Num (d0, d1, )+import Types.Data.Num (d0, d1, ) import Data.Word (Word32, ) import Foreign.Storable.Tuple () import Foreign.Storable (Storable, )+import Foreign.Ptr (Ptr, ) import qualified Synthesizer.LLVM.Alloc as Alloc import Control.Applicative (liftA2, )@@ -61,17 +60,18 @@ zeroTuple = Cons Class.zeroTuple Class.zeroTuple +type Struct a = LLVM.Struct (Word32, (a, ()))+ parameterMemory ::- (Memory.C a s, IsSized s ss) =>- Memory.Record r (Struct (Word32, (s, ()))) (T a)+ (Memory.C a) =>+ Memory.Record r (Struct (Memory.Struct a)) (T a) parameterMemory = liftA2 Cons (Memory.element (\(Cons len _y) -> len) d0) (Memory.element (\(Cons _len y) -> y) d1) -instance- (Memory.C a s, IsSized s ss) =>- Memory.C (T a) (Struct (Word32, (s, ()))) where+instance (Memory.C a) => Memory.C (T a) where+ type Struct (T a) = Struct (Memory.Struct a) load = Memory.loadRecord parameterMemory store = Memory.storeRecord parameterMemory decompose = Memory.decomposeRecord parameterMemory@@ -79,7 +79,7 @@ flatten ::- (Memory.C value struct, IsSized struct size) =>+ (Memory.C value) => SigP.T p (T value) -> SigP.T p value flatten (SigP.Cons next start createIOContext deleteIOContext) =@@ -89,7 +89,7 @@ Maybe.fromBool $ whileLoop (valueOf True, state0) (\(cont, (Cons len _y, _s)) ->- LLVM.and cont =<< A.cmp CmpEQ len (valueOf 0))+ LLVM.and cont =<< A.cmp LLVM.CmpEQ len (valueOf 0)) (\(_cont, (Cons _len _y, s)) -> Maybe.toBool $ next nextParam s) length2 <- Maybe.lift (A.dec length1)@@ -101,16 +101,16 @@ piecewiseConstant ::- (Storable a, MakeValueTuple a value, Memory.C value struct, IsSized struct size) =>+ (Storable a, MakeValueTuple a, ValueTuple a ~ value, Memory.C value) => Param.T p (EventList.T NonNeg.Int a) -> SigP.T p (T value) piecewiseConstant evs = SigP.Cons (\(stable, yPtr) () -> do len <- Maybe.lift $ do- nextFn <- staticFunction EventIt.nextCallBack- call nextFn stable yPtr+ nextFn <- LLVM.staticFunction EventIt.nextCallBack+ LLVM.call nextFn stable yPtr Maybe.guard =<<- Maybe.lift (A.cmp CmpNE len (valueOf 0))+ Maybe.lift (A.cmp LLVM.CmpNE len (valueOf 0)) y <- Maybe.lift $ Memory.load yPtr return (Cons len y, ())) return@@ -136,10 +136,10 @@ lazySize size = SigP.Cons (\stable () -> do len <- Maybe.lift $ do- nextFn <- staticFunction SizeIt.nextCallBack- call nextFn stable+ nextFn <- LLVM.staticFunction SizeIt.nextCallBack+ LLVM.call nextFn stable Maybe.guard =<<- Maybe.lift (A.cmp CmpNE len (valueOf 0))+ Maybe.lift (A.cmp LLVM.CmpNE len (valueOf 0)) return (Cons len (), ())) return (\p -> do
src/Synthesizer/LLVM/Debug/Storable.hs view
@@ -3,7 +3,7 @@ import qualified Synthesizer.LLVM.Debug.Counter as Counter -import qualified Data.TypeLevel.Num as TypeNum+import qualified Types.Data.Num as TypeNum import qualified LLVM.Core as LLVM import LLVM.Core (Array, ConstValue, constOf, ) @@ -17,17 +17,18 @@ import Foreign.Storable (Storable, peek, peekByteOff, sizeOf, alignment, ) import Foreign.Ptr (Ptr, castPtr, ) import Data.Word (Word8, Word32, )-import System.IO.Unsafe (unsafePerformIO, )+import qualified System.Unsafe as Unsafe import qualified Control.Monad.Trans.Reader as R import Control.Monad (when, )+import Data.Maybe (fromMaybe, ) data Dump = Dump dumpCounter :: IORef.IORef (Counter.T Dump) dumpCounter =- unsafePerformIO $ Counter.new+ Unsafe.performIO $ Counter.new format :: Storable a => a -> IO String format a =@@ -59,7 +60,7 @@ withConstArray :: Storable a => a ->- (forall n. TypeNum.Nat n => ConstValue (Array n ArrayElem) -> b) ->+ (forall n. TypeNum.NaturalT n => ConstValue (Array n ArrayElem) -> b) -> IO b withConstArray a f = Marshal.with a $ \ptr -> do@@ -67,11 +68,13 @@ mapM (peekByteOff ptr) (takeWhile (< sizeOf a) [0,(sizeOf (undefined :: ArrayElem))..])+ :: IO [ArrayElem] return $- TypeNum.reifyIntegral (length content)+ fromMaybe (error "Debug.Storable.withConstArray: length must always be non-negative") $+ TypeNum.reifyNaturalD (fromIntegral (length content)) (\n -> let makeArray ::- TypeNum.Nat n =>+ TypeNum.NaturalT n => n -> [ConstValue ArrayElem] -> ConstValue (Array n ArrayElem) makeArray _ = LLVM.constArray
src/Synthesizer/LLVM/Execution.hs view
@@ -1,8 +1,4 @@-{-# LANGUAGE MultiParamTypeClasses #-}-{-# LANGUAGE FunctionalDependencies #-}-{-# LANGUAGE TypeSynonymInstances #-}-{-# LANGUAGE FlexibleInstances #-}-{-# LANGUAGE UndecidableInstances #-}+{-# LANGUAGE TypeFamilies #-} module Synthesizer.LLVM.Execution where import qualified LLVM.ExecutionEngine as EE@@ -15,30 +11,30 @@ import Control.Monad (liftM2, liftM3, ) import qualified Data.IORef as IORef-import System.IO.Unsafe (unsafePerformIO, )+import qualified System.Unsafe as Unsafe import qualified Synthesizer.LLVM.Debug.Counter as Counter type Importer f = FunPtr f -> f -class Compile externFunction llvmFunction |- externFunction -> llvmFunction,- llvmFunction -> externFunction where- compile :: llvmFunction -> EE.EngineAccess externFunction+class Compile externFunction where+ type LLVMFunction externFunction :: *+ compile :: LLVMFunction externFunction -> EE.EngineAccess externFunction -instance Compile (FunPtr f) (LLVM.Function f) where+instance Compile (FunPtr f) where+ type LLVMFunction (FunPtr f) = (LLVM.Function f) compile = EE.getPointerToFunction -instance (Compile efa lfa, Compile efb lfb) =>- Compile (efa,efb) (lfa,lfb) where+instance (Compile fa, Compile fb) => Compile (fa,fb) where+ type LLVMFunction (fa,fb) = (LLVMFunction fa, LLVMFunction fb) compile (fa,fb) = liftM2 (,) (compile fa) (compile fb) -instance (Compile efa lfa, Compile efb lfb, Compile efc lfc) =>- Compile (efa,efb,efc) (lfa,lfb,lfc) where+instance (Compile fa, Compile fb, Compile fc) => Compile (fa,fb,fc) where+ type LLVMFunction (fa,fb,fc) = (LLVMFunction fa, LLVMFunction fb, LLVMFunction fc) compile (fa,fb,fc) = liftM3 (,,) (compile fa)@@ -54,7 +50,7 @@ -} counter :: IORef.IORef (Counter.T BitCodeCnt) counter =- unsafePerformIO $ Counter.new+ Unsafe.performIO $ Counter.new {- |@@ -85,8 +81,8 @@ -- this compiles once and is much faster than runFunction compileModule ::- (Compile externFunction llvmFunction) =>- LLVM.CodeGenModule llvmFunction ->+ (Compile externFunction) =>+ LLVM.CodeGenModule (LLVMFunction externFunction) -> IO externFunction compileModule = assembleModule compile
src/Synthesizer/LLVM/Filter/Allpass.hs view
@@ -1,9 +1,7 @@ {-# LANGUAGE NoImplicitPrelude #-}-{-# LANGUAGE MultiParamTypeClasses #-}-{-# LANGUAGE FunctionalDependencies #-}-{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE TypeFamilies #-}+{-# LANGUAGE TypeOperators #-} {-# LANGUAGE FlexibleContexts #-}-{-# LANGUAGE UndecidableInstances #-} {-# LANGUAGE GeneralizedNewtypeDeriving #-} {-# OPTIONS_GHC -fno-warn-orphans #-} module Synthesizer.LLVM.Filter.Allpass (@@ -18,26 +16,24 @@ import qualified Synthesizer.Plain.Filter.Recursive.Allpass as Allpass import qualified Synthesizer.Plain.Filter.Recursive.FirstOrder as Filt1 -import qualified Synthesizer.LLVM.Filter.FirstOrder as Filt1L import qualified Synthesizer.Plain.Modifier as Modifier+import qualified Synthesizer.LLVM.Filter.FirstOrder as Filt1L import qualified Synthesizer.LLVM.CausalParameterized.Process as CausalP-import qualified LLVM.Extra.ScalarOrVector as SoV-import qualified LLVM.Extra.Vector as Vector-import qualified LLVM.Extra.Memory as Memory+import qualified Synthesizer.LLVM.CausalParameterized.Functional as F+import qualified Synthesizer.LLVM.Frame.SerialVector as Serial import qualified Synthesizer.LLVM.Simple.Value as Value +import qualified LLVM.Extra.Vector as Vector+import qualified LLVM.Extra.Memory as Memory import qualified LLVM.Extra.Class as Class import qualified LLVM.Extra.Arithmetic as A import qualified LLVM.Core as LLVM import LLVM.Extra.Class (Undefined, undefTuple, )-import LLVM.Core- (Value, valueOf, Vector,- IsArithmetic, IsPrimitive, IsFloating, IsSized,- CodeGenFunction, )+import LLVM.Core (CodeGenFunction, ) import LLVM.Util.Loop (Phi, phis, addPhis, ) -import qualified Data.TypeLevel.Num as TypeNum+import qualified Types.Data.Num as TypeNum import Foreign.Storable (Storable, ) @@ -66,9 +62,8 @@ instance Class.Zero a => Class.Zero (Parameter a) where zeroTuple = Class.zeroTuplePointed -instance- (Memory.C a s, IsSized s ss) =>- Memory.C (Parameter a) s where+instance (Memory.C a) => Memory.C (Parameter a) where+ type Struct (Parameter a) = Memory.Struct a load = Memory.loadNewtype Parameter store = Memory.storeNewtype (\(Parameter k) -> k) decompose = Memory.decomposeNewtype Parameter@@ -83,31 +78,30 @@ tupleDesc = Class.tupleDescFoldable -} -instance (Class.MakeValueTuple ah al) =>- Class.MakeValueTuple (Parameter ah) (Parameter al) where+instance (Class.MakeValueTuple a) => Class.MakeValueTuple (Parameter a) where+ type ValueTuple (Parameter a) = Parameter (Class.ValueTuple a) valueTupleOf = Class.valueTupleOfFunctor -instance (Value.Flatten ah al) =>- Value.Flatten (Parameter ah) (Parameter al) where+instance (Value.Flatten a) => Value.Flatten (Parameter a) where+ type Registers (Parameter a) = Parameter (Value.Registers a) flatten = Value.flattenTraversable unfold = Value.unfoldFunctor -instance (Vector.ShuffleMatch n v) =>- Vector.ShuffleMatch n (Parameter v) where+instance (Vector.Simple v) => Vector.Simple (Parameter v) where+ type Element (Parameter v) = Parameter (Vector.Element v)+ type Size (Parameter v) = Vector.Size v shuffleMatch = Vector.shuffleMatchTraversable--instance (Vector.Access n a v) =>- Vector.Access n (Parameter a) (Parameter v) where- insert = Vector.insertTraversable extract = Vector.extractTraversable +instance (Vector.C v) => Vector.C (Parameter v) where+ insert = Vector.insertTraversable + parameter ::- (Trans.C a, SoV.RationalConstant a, IsFloating a) =>- Value a -> Value a ->- CodeGenFunction r (Parameter (Value a))+ (A.Transcendental a, A.RationalConstant a) =>+ a -> a -> CodeGenFunction r (Parameter a) parameter phase freq = Value.flatten $ Allpass.parameter@@ -120,9 +114,8 @@ (Phi, Undefined, Class.Zero, Storable, Functor, App.Applicative, Fold.Foldable, Trav.Traversable) -instance- (Memory.C a s, IsSized s ss) =>- Memory.C (CascadeParameter n a) s where+instance (Memory.C a) => Memory.C (CascadeParameter n a) where+ type Struct (CascadeParameter n a) = Memory.Struct a load = Memory.loadNewtype CascadeParameter store = Memory.storeNewtype (\(CascadeParameter k) -> k) decompose = Memory.decomposeNewtype CascadeParameter@@ -137,47 +130,51 @@ tupleDesc = Class.tupleDescFoldable -} -instance (Class.MakeValueTuple ah al) =>- Class.MakeValueTuple (CascadeParameter n ah) (CascadeParameter n al) where+instance (Class.MakeValueTuple a) => Class.MakeValueTuple (CascadeParameter n a) where+ type ValueTuple (CascadeParameter n a) = CascadeParameter n (Class.ValueTuple a) valueTupleOf = Class.valueTupleOfFunctor -instance (Value.Flatten ah al) =>- Value.Flatten (CascadeParameter n ah) (CascadeParameter n al) where+instance (Value.Flatten a) => Value.Flatten (CascadeParameter n a) where+ type Registers (CascadeParameter n a) = CascadeParameter n (Value.Registers a) flatten = Value.flattenTraversable unfold = Value.unfoldFunctor -instance (Vector.ShuffleMatch m v) =>- Vector.ShuffleMatch m (CascadeParameter n v) where+instance (Vector.Simple v) => Vector.Simple (CascadeParameter n v) where+ type Element (CascadeParameter n v) = CascadeParameter n (Vector.Element v)+ type Size (CascadeParameter n v) = Vector.Size v shuffleMatch = Vector.shuffleMatchTraversable+ extract = Vector.extractTraversable -instance (Vector.Access m a v) =>- Vector.Access m (CascadeParameter n a) (CascadeParameter n v) where+instance (Vector.C v) => Vector.C (CascadeParameter n v) where insert = Vector.insertTraversable- extract = Vector.extractTraversable +type instance F.Arguments f (CascadeParameter n a) = f (CascadeParameter n a)+instance F.MakeArguments (CascadeParameter n a) where+ makeArgs = id + flangerParameter ::- (Trans.C a, SoV.RationalConstant a, IsFloating a, TypeNum.Nat n) =>- n -> Value a ->- CodeGenFunction r (CascadeParameter n (Value a))+ (A.Transcendental a, A.RationalConstant a, TypeNum.NaturalT n) =>+ n -> a ->+ CodeGenFunction r (CascadeParameter n a) flangerParameter order freq = Value.flatten $ CascadeParameter $- Allpass.flangerParameter (TypeNum.toInt order) $+ Allpass.flangerParameter (TypeNum.fromIntegerT order) $ Value.constantValue freq flangerParameterPlain ::- (Trans.C a, TypeNum.Nat n) =>+ (Trans.C a, TypeNum.NaturalT n) => n -> a -> CascadeParameter n a flangerParameterPlain order freq = CascadeParameter $- Allpass.flangerParameter (TypeNum.toInt order) freq+ Allpass.flangerParameter (TypeNum.fromIntegerT order) freq modifier ::- (SoV.PseudoModule a v, SoV.IntegerConstant a) =>+ (A.PseudoModule a v, A.IntegerConstant a) => Modifier.Simple -- (Allpass.State (Value.T v)) (Value.T v, Value.T v)@@ -190,57 +187,43 @@ For Allpass cascade you may use the 'CausalP.pipeline' function. -} causalP ::- (SoV.RationalConstant a, IsArithmetic a,- SoV.PseudoModule a v,- Memory.FirstClass a am, IsSized a as, IsSized am ams,- Memory.FirstClass v vm, IsSized v vs, IsSized vm vms) =>- CausalP.T p- (Parameter (Value a), Value v) (Value v)+ (A.RationalConstant a, A.PseudoModule a v, Memory.C v) =>+ CausalP.T p (Parameter a, v) v causalP = CausalP.fromModifier modifier replicateStage ::- (TypeNum.Nat n) =>+ (TypeNum.NaturalT n) => n -> CausalP.T p (Parameter a, b) b -> CausalP.T p (CascadeParameter n a, b) b replicateStage order stg = CausalP.replicateControlled- (TypeNum.toInt order)+ (TypeNum.fromIntegerT order) (stg <<< first (arr (\(CascadeParameter p) -> p))) cascadeP ::- (SoV.RationalConstant a, IsArithmetic a,- SoV.PseudoModule a v,- Memory.FirstClass a am, IsSized a as, IsSized am ams,- Memory.FirstClass v vm, IsSized v vs, IsSized vm vms,- TypeNum.Nat n) =>- CausalP.T p- (CascadeParameter n (Value a), Value v) (Value v)+ (A.RationalConstant a, A.PseudoModule a v, Memory.C v,+ TypeNum.NaturalT n) =>+ CausalP.T p (CascadeParameter n a, v) v cascadeP = replicateStage undefined causalP half ::- (SoV.RationalConstant a, SoV.RationalConstant v,- IsFloating a, IsArithmetic v,- Memory.FirstClass a am, IsSized a as, IsSized am ams,- Memory.FirstClass v vm, IsSized v vs, IsSized vm vms,- TypeNum.Nat n) =>- CausalP.T p- (CascadeParameter n (Value a), Value v) (Value v)+ (A.RationalConstant a, A.PseudoModule a v) =>+ CausalP.T p (param a, v) v half =- CausalP.mapSimple- (\(_p,x) -> A.mul (A.fromRational' 0.5) x)+ let scale :: A.PseudoModule a v => param a -> a -> v -> CodeGenFunction r v+ scale _ = A.scale+ in CausalP.mapSimple+ (\(p,x) -> scale p (A.fromRational' 0.5) x) phaserP ::- (SoV.RationalConstant a, SoV.RationalConstant v,- IsFloating a, SoV.PseudoModule a v,- Memory.FirstClass a am, IsSized a as, IsSized am ams,- Memory.FirstClass v vm, IsSized v vs, IsSized vm vms,- TypeNum.Nat n) =>- CausalP.T p- (CascadeParameter n (Value a), Value v) (Value v)+ (A.RationalConstant a, A.RationalConstant v,+ A.PseudoModule a v, Memory.C v,+ TypeNum.NaturalT n) =>+ CausalP.T p (CascadeParameter n a, v) v phaserP = CausalP.mix <<< cascadeP &&& arr snd <<<@@ -252,13 +235,12 @@ but LLVM-2.6 does not yet do it. -} stage ::- (TypeNum.Pos n, IsPrimitive a,- IsArithmetic a, SoV.IntegerConstant a, SoV.PseudoModule a a,- Memory.FirstClass a am, IsSized a as, IsSized am ams) =>+ (Vector.Canonical n a, Vector.Construct n a ~ v,+ A.PseudoModule a a, A.IntegerConstant a, Memory.C a) => n -> CausalP.T p- (CascadeParameter n (Value (Vector n a)), Value (Vector n a))- (CascadeParameter n (Value (Vector n a)), Value (Vector n a))+ (CascadeParameter n v, v)+ (CascadeParameter n v, v) stage _ = CausalP.vectorize (arr fst &&&@@ -277,73 +259,60 @@ and we get a delay by the number of pipeline stages. -} cascadePipelineP ::- (SoV.RationalConstant a, SoV.PseudoModule a a,--- IsSized (Vector n a) vas,- Memory.FirstClass a am,- IsPrimitive a, IsSized a asize,- IsPrimitive am, IsSized am amsize,- TypeNum.Mul n asize vasize, TypeNum.Pos vasize,- TypeNum.Mul n amsize vmsize, TypeNum.Pos vmsize,- TypeNum.Pos n) =>- CausalP.T p- (CascadeParameter n (Value a), Value a) (Value a)+ (Vector.Canonical n a, Vector.Construct n a ~ v,+ A.PseudoModule a a, A.IntegerConstant a, Memory.C a,+ Class.Zero v, Memory.C v) =>+ CausalP.T p (CascadeParameter n a, a) a cascadePipelineP = withSize $ \order -> snd ^<< CausalP.pipeline (stage order) vectorId ::- (Vector.Access n a v) =>- n -> CausalP.T p v v+ (Vector.Canonical n a) =>+ n -> CausalP.T p (Vector.Construct n a) (Vector.Construct n a) vectorId _ = Cat.id phaserPipelineP ::- (SoV.RationalConstant a, IsFloating a, SoV.PseudoModule a a,- Memory.FirstClass a am,- IsPrimitive a, IsSized a asize,- IsPrimitive am, IsSized am amsize,- TypeNum.Mul n asize vasize, TypeNum.Pos vasize,- TypeNum.Mul n amsize vmsize, TypeNum.Pos vmsize,- TypeNum.Pos n) =>- CausalP.T p- (CascadeParameter n (Value a), Value a) (Value a)+ (Vector.Canonical n a, Vector.Construct n a ~ v,+ A.PseudoModule a a, A.RationalConstant a, Memory.C a,+ Class.Zero v, Memory.C v) =>+ CausalP.T p (CascadeParameter n a, a) a phaserPipelineP = withSize $ \order -> CausalP.mix <<< cascadePipelineP &&& (CausalP.pipeline (vectorId order) <<^ snd) <<<--- (CausalP.delay (const zero) (const $ TypeNum.toInt order) <<^ snd) <<<+-- (CausalP.delay (const zero) (const $ TypeNum.fromIntegerT order) <<^ snd) <<< (arr fst &&& half) causalPackedP, causalNonRecursivePackedP ::- (Memory.FirstClass a am, IsSized a as, IsSized am ams,- SoV.IntegerConstant a, IsArithmetic a,- TypeNum.Pos n, IsPrimitive a) =>- CausalP.T p- (Parameter (Value a), Value (Vector n a)) (Value (Vector n a))+ (Serial.C v, Serial.Element v ~ a,+ Memory.C a, A.IntegerConstant a,+ A.PseudoRing v, A.PseudoRing a) =>+ CausalP.T p (Parameter a, v) v causalPackedP = Filt1L.causalRecursivePackedP <<< (CausalP.mapSimple (\(Parameter k, _) ->- fmap Filt1.Parameter $ LLVM.neg k) &&&+ fmap Filt1.Parameter $ A.neg k) &&& causalNonRecursivePackedP) causalNonRecursivePackedP = CausalP.mapAccumSimple (\(Parameter k, v0) x1 -> do- (_,v1) <- Vector.shiftUp x1 v0- y <- A.add v1 =<< A.mul v0 =<< SoV.replicate k- let size = fromIntegral $ Vector.sizeInTuple v0- u0 <- Vector.extract (valueOf $ size - 1) v0+ (_,v1) <- Serial.shiftUp x1 v0+ y <- A.add v1 =<< A.mul v0 =<< Serial.upsample k+ let size = fromIntegral $ Serial.size v0+ u0 <- Serial.extract (LLVM.valueOf $ size - 1) v0 return (y, u0))- (return (LLVM.value LLVM.zero))+ (return A.zero) cascadePackedP, phaserPackedP ::- (SoV.RationalConstant a, IsArithmetic a,- Memory.FirstClass a am, IsSized a as, IsSized am ams,- TypeNum.Pos m, IsPrimitive a,- TypeNum.Nat n) =>- CausalP.T p- (CascadeParameter n (Value a), Value (Vector m a)) (Value (Vector m a))+ (TypeNum.NaturalT n,+ Serial.C v, Serial.Element v ~ a,+ A.PseudoRing a, A.IntegerConstant a, Memory.C a,+ A.PseudoRing v, A.RationalConstant v) =>+ CausalP.T p (CascadeParameter n a, v) v cascadePackedP = replicateStage undefined causalPackedP
src/Synthesizer/LLVM/Filter/Butterworth.hs view
@@ -1,4 +1,6 @@ {-# LANGUAGE NoImplicitPrelude #-}+{-# LANGUAGE TypeFamilies #-}+{-# LANGUAGE TypeOperators #-} {-# LANGUAGE FlexibleContexts #-} module Synthesizer.LLVM.Filter.Butterworth ( parameter, Cascade.ParameterValue,@@ -22,12 +24,12 @@ import qualified LLVM.Core as LLVM import LLVM.Core (Value, valueOf, constOf,- IsConst, IsFloating, IsSized,+ IsConst, IsFloating, IsSized, SizeOf, CodeGenFunction, ) import Data.Word (Word32, ) -import qualified Data.TypeLevel.Num as TypeNum-import qualified Data.TypeLevel.Num.Sets as TypeSet+import qualified Types.Data.Num as TypeNum+import Types.Data.Num.Ops ((:*:), ) import qualified Algebra.Transcendental as Trans -- import qualified Algebra.Field as Field@@ -39,17 +41,16 @@ parameter, parameterMalloc, _parameterAlloca ::- (Trans.C a, SoV.RationalConstant a, IsFloating a, IsSized a as,- TypeSet.Nat n,- TypeNum.Mul n as sineSize,- TypeSet.Pos sineSize,- IsSized (Cascade.Parameter n a) paramSize) =>+ (Trans.C a, SoV.TranscendentalConstant a, IsFloating a, IsSized a,+ TypeNum.NaturalT n,+ TypeNum.PositiveT (n :*: SizeOf a),+ IsSized (Cascade.ParameterStruct n a)) => n -> Passband -> Value a -> Value a -> CodeGenFunction r (Cascade.ParameterValue n a) parameter = parameterMalloc parameterMalloc n kind ratio freq = do- let order = 2 * TypeNum.toInt n+ let order = 2 * TypeNum.fromIntegerT n partialRatio <- Value.decons (Butterworth.partialRatio order (Value.constantValue ratio)) let sines =@@ -63,7 +64,7 @@ s <- LLVM.getElementPtr0 psine (valueOf (0::Word32), ()) ps <- LLVM.malloc p <- LLVM.getElementPtr0 ps (valueOf (0::Word32), ())- let len = valueOf $ (TypeNum.toNum n :: Word32)+ let len = valueOf $ (TypeNum.fromIntegerT n :: Word32) _ <- U.arrayLoop len p s $ \ptri si -> do sinw <- LLVM.load si flip LLVM.store ptri =<<@@ -82,7 +83,7 @@ return (Cascade.ParameterValue pv) _parameterAlloca n kind ratio freq = do- let order = 2 * TypeNum.toInt n+ let order = 2 * TypeNum.fromIntegerT n partialRatio <- Value.decons (Butterworth.partialRatio order (Value.constantValue ratio)) let sines =@@ -96,7 +97,7 @@ s <- LLVM.getElementPtr0 psine (valueOf (0::Word32), ()) ps <- LLVM.alloca p <- LLVM.getElementPtr0 ps (valueOf (0::Word32), ())- let len = valueOf $ (TypeNum.toNum n :: Word32)+ let len = valueOf $ (TypeNum.fromIntegerT n :: Word32) _ <- U.arrayLoop len p s $ \ptri si -> do sinw <- LLVM.load si flip LLVM.store ptri =<<
src/Synthesizer/LLVM/Filter/Chebyshev.hs view
@@ -1,4 +1,6 @@ {-# LANGUAGE NoImplicitPrelude #-}+{-# LANGUAGE TypeFamilies #-}+{-# LANGUAGE TypeOperators #-} {-# LANGUAGE FlexibleContexts #-} module Synthesizer.LLVM.Filter.Chebyshev ( parameterA, parameterB, Cascade.ParameterValue,@@ -21,11 +23,12 @@ import qualified LLVM.Core as LLVM import LLVM.Core- (Value, valueOf, IsSized, IsFloating, CodeGenFunction, )+ (Value, valueOf, IsSized, SizeOf, IsFloating, CodeGenFunction, ) import Data.Word (Word32, ) -import qualified Data.TypeLevel.Num as TypeNum-import qualified Data.TypeLevel.Num.Sets as TypeSet+import qualified Types.Data.Bool as TypeBool+import qualified Types.Data.Num as TypeNum+import Types.Data.Num.Ops ((:*:), ) import qualified Synthesizer.LLVM.Complex as ComplexL @@ -45,11 +48,11 @@ by the first partial filter. -} parameterA, parameterB ::- (Trans.C a, SoV.RationalConstant a, IsFloating a, IsSized a as,- TypeSet.Pos n, TypeNum.Mul n as sineSize,- TypeSet.Pos sineSize,- IsSized (Cascade.Parameter n a) paramSize,- TypeNum.Mul n LLVM.UnknownSize paramSize, TypeSet.Pos paramSize) =>+ (Trans.C a, SoV.TranscendentalConstant a, IsFloating a, IsSized a,+ TypeNum.PositiveT n, TypeNum.IsNatural n ~ TypeBool.True,+ TypeNum.PositiveT (n :*: SizeOf a),+ IsSized (Cascade.ParameterStruct n a), SizeOf (Cascade.ParameterStruct n a) ~ paramSize,+ (n :*: LLVM.UnknownSize) ~ paramSize, TypeNum.PositiveT paramSize) => n -> Passband -> Value a -> Value a -> CodeGenFunction r (Cascade.ParameterValue n a) parameterA n kind ratio freq = do@@ -71,18 +74,17 @@ parameter ::- (Trans.C a, SoV.RationalConstant a, IsFloating a, IsSized a as,- TypeSet.Pos n,- TypeNum.Mul n as sineSize,- TypeSet.Pos sineSize,- IsSized (Cascade.Parameter n a) paramSize,- TypeNum.Mul n LLVM.UnknownSize paramSize, TypeSet.Pos paramSize) =>- (Int -> Value.T a -> Value.T a ->- Complex.T (Value.T a) -> Filt2Core.Parameter (Value.T a)) ->+ (Trans.C a, SoV.RationalConstant a, IsFloating a, IsSized a,+ TypeNum.PositiveT n, TypeNum.IsNatural n ~ TypeBool.True,+ TypeNum.PositiveT (n :*: SizeOf a),+ IsSized (Cascade.ParameterStruct n a), SizeOf (Cascade.ParameterStruct n a) ~ paramSize,+ (n :*: LLVM.UnknownSize) ~ paramSize, TypeNum.PositiveT paramSize) =>+ (Int -> Value.T (Value a) -> Value.T (Value a) ->+ Complex.T (Value.T (Value a)) -> Filt2Core.Parameter (Value.T (Value a))) -> n -> Passband -> Value a -> Value a ->- CodeGenFunction r (Value (Cascade.Parameter n a))+ CodeGenFunction r (Value (Cascade.ParameterStruct n a)) parameter partialParameter n kind ratio freq = do- let order = 2 * TypeNum.toInt n+ let order = 2 * TypeNum.fromIntegerT n let sines = (flip const :: n -> LLVM.Value (LLVM.Array n a) -> LLVM.Value (LLVM.Array n a)) n $@@ -95,7 +97,7 @@ s <- LLVM.getElementPtr0 psine (valueOf (0::Word32), ()) ps <- LLVM.malloc p <- LLVM.getElementPtr0 ps (valueOf (0::Word32), ())- let len = valueOf $ (TypeNum.toNum n :: Word32)+ let len = valueOf $ (TypeNum.fromIntegerT n :: Word32) _ <- U.arrayLoop len p s $ \ptri si -> do c <- LLVM.load si flip LLVM.store ptri =<<
src/Synthesizer/LLVM/Filter/ComplexFirstOrder.hs view
@@ -1,11 +1,5 @@ {-# LANGUAGE NoImplicitPrelude #-}-{-# LANGUAGE MultiParamTypeClasses #-}-{-# LANGUAGE FunctionalDependencies #-}-{-# LANGUAGE FlexibleInstances #-}-{-# LANGUAGE FlexibleContexts #-}-{-# LANGUAGE UndecidableInstances #-}-{-# LANGUAGE ExistentialQuantification #-}-{-# LANGUAGE Rank2Types #-}+{-# LANGUAGE TypeFamilies #-} module Synthesizer.LLVM.Filter.ComplexFirstOrder ( Parameter, parameter, causal, causalP,@@ -18,28 +12,22 @@ import qualified Synthesizer.LLVM.Frame.Stereo as Stereo import qualified Synthesizer.LLVM.Complex as Complex -import qualified LLVM.Extra.ScalarOrVector as SoV import qualified LLVM.Extra.Arithmetic as A import qualified LLVM.Extra.Memory as Memory import qualified LLVM.Extra.Class as Class import LLVM.Extra.Class (Undefined, undefTuple, ) import qualified LLVM.Core as LLVM-import LLVM.Core- (Value, Struct, value, valueOf,- IsArithmetic, IsFloating, IsSized,- CodeGenFunction, )+import LLVM.Core (CodeGenFunction, ) import LLVM.Util.Loop (Phi, phis, addPhis, ) -import Data.TypeLevel.Num (d0, d1, d2, )+import Types.Data.Num (d0, d1, d2, ) import qualified Control.Applicative as App import qualified Data.Foldable as Fold import qualified Data.Traversable as Trav import Control.Applicative (liftA2, liftA3, (<*>), ) -import qualified Algebra.Transcendental as Trans- import NumericPrelude.Numeric import NumericPrelude.Base @@ -81,31 +69,33 @@ undefTuple = Class.undefTuplePointed +type ParameterStruct a = LLVM.Struct (a, (a, (a, ())))+ parameterMemory ::- (Memory.C l s, IsSized s ss) =>- Memory.Record r (Struct (s, (s, (s, ())))) (Parameter l)+ (Memory.C a) =>+ Memory.Record r (ParameterStruct (Memory.Struct a)) (Parameter a) parameterMemory = liftA3 (\amp kr ki -> Parameter amp (kr Complex.+: ki)) (Memory.element (\(Parameter amp _) -> amp) d0) (Memory.element (\(Parameter _amp k) -> Complex.real k) d1) (Memory.element (\(Parameter _amp k) -> Complex.imag k) d2) -instance (Memory.C l s, IsSized s ss) =>- Memory.C (Parameter l) (Struct (s, (s, (s, ())))) where+instance (Memory.C a) => Memory.C (Parameter a) where+ type Struct (Parameter a) = ParameterStruct (Memory.Struct a) load = Memory.loadRecord parameterMemory store = Memory.storeRecord parameterMemory decompose = Memory.decomposeRecord parameterMemory compose = Memory.composeRecord parameterMemory -instance (Value.Flatten ah al) =>- Value.Flatten (Parameter ah) (Parameter al) where+instance (Value.Flatten a) => Value.Flatten (Parameter a) where+ type Registers (Parameter a) = Parameter (Value.Registers a) flatten = Value.flattenTraversable unfold = Value.unfoldFunctor parameter, _parameter ::- (Trans.C a, IsFloating a, SoV.RationalConstant a) =>- Value a -> Value a -> CodeGenFunction r (Parameter (Value a))+ (A.Transcendental a, A.RationalConstant a) =>+ a -> a -> CodeGenFunction r (Parameter a) parameter reson freq = let amp = recip $ Value.unfold reson in Value.flatten $ Parameter amp $@@ -113,8 +103,8 @@ Value.unfold freq * Value.twoPi _parameter reson freq = do- amp <- A.fdiv (valueOf 1) reson- k <- A.sub (valueOf 1) amp+ amp <- A.fdiv A.one reson+ k <- A.sub A.one amp w <- A.mul freq =<< Value.decons Value.twoPi kr <- A.mul k =<< A.cos w ki <- A.mul k =<< A.sin w@@ -126,13 +116,13 @@ cannot be used directly, because Filt1C has complex amplitude -} next, _next ::- (IsArithmetic a, SoV.IntegerConstant a) =>- (Parameter (Value a), Stereo.T (Value a)) ->- Complex.T (Value a) ->- CodeGenFunction r (Stereo.T (Value a), Complex.T (Value a))+ (A.PseudoRing a, A.IntegerConstant a) =>+ (Parameter a, Stereo.T a) ->+ Complex.T a ->+ CodeGenFunction r (Stereo.T a, Complex.T a) next inp state = let stereoFromComplex ::- Complex.T (Value a) -> Complex.T (Value.T a) ->+ Complex.T a -> Complex.T (Value.T a) -> Stereo.T (Value.T a) stereoFromComplex _ c = Stereo.cons (Complex.real c) (Complex.imag c)@@ -156,27 +146,23 @@ start ::- (LLVM.IsType a, SoV.IntegerConstant a) =>- CodeGenFunction r (Complex.T (Value a))+ (A.Additive a) =>+ CodeGenFunction r (Complex.T a) start =- return (value LLVM.zero Complex.+: value LLVM.zero)+ return (A.zero Complex.+: A.zero) causal ::- (IsSized a sa, SoV.IntegerConstant a,- Memory.FirstClass a am, IsSized am amsize,- IsFloating a) =>+ (A.PseudoRing a, A.IntegerConstant a, Memory.C a) => Causal.T- (Parameter (Value a), Stereo.T (Value a))- (Stereo.T (Value a))+ (Parameter a, Stereo.T a)+ (Stereo.T a) causal = Causal.mapAccum next start causalP ::- (IsSized a sa, SoV.IntegerConstant a,- Memory.FirstClass a am, IsSized am amsize,- IsFloating a) =>+ (A.PseudoRing a, A.IntegerConstant a, Memory.C a) => CausalP.T p- (Parameter (Value a), Stereo.T (Value a))- (Stereo.T (Value a))+ (Parameter a, Stereo.T a)+ (Stereo.T a) causalP = CausalP.mapAccumSimple next start
src/Synthesizer/LLVM/Filter/ComplexFirstOrderPacked.hs view
@@ -1,12 +1,8 @@ {-# LANGUAGE NoImplicitPrelude #-}-{-# LANGUAGE MultiParamTypeClasses #-}-{-# LANGUAGE FunctionalDependencies #-}-{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE TypeFamilies #-}+{-# LANGUAGE TypeOperators #-} {-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE UndecidableInstances #-}-{-# LANGUAGE TypeSynonymInstances #-}-{-# LANGUAGE ExistentialQuantification #-}-{-# LANGUAGE Rank2Types #-} module Synthesizer.LLVM.Filter.ComplexFirstOrderPacked ( Parameter, parameter, causal, causalP,@@ -18,9 +14,10 @@ import qualified Synthesizer.LLVM.Frame.Stereo as Stereo -import qualified LLVM.Extra.Memory as Memory+import qualified LLVM.Extra.ScalarOrVector as SoV import qualified LLVM.Extra.Vector as Vector import qualified LLVM.Extra.Arithmetic as A+import qualified LLVM.Extra.Memory as Memory import LLVM.Extra.Class (Undefined, undefTuple, ) import qualified LLVM.Core as LLVM@@ -28,18 +25,14 @@ (Value, valueOf, value, Struct, IsPrimitive, IsConst, IsFloating, IsSized, Vector, insertelement,- neg, CodeGenFunction, )+ CodeGenFunction, ) import LLVM.Util.Loop (Phi, phis, addPhis, ) -import Data.TypeLevel.Num (D4, d0, d1, )+import qualified Types.Data.Num as TypeNum+import Types.Data.Num (D4, d0, d1, (:*:), ) import Control.Applicative (liftA2, ) -import qualified Algebra.Transcendental as Trans--- import qualified Algebra.Field as Field--- import qualified Algebra.Ring as Ring--- import qualified Algebra.Additive as Additive- import NumericPrelude.Numeric import NumericPrelude.Base @@ -66,8 +59,10 @@ type ParameterStruct a = Struct (Vector D4 a, (Vector D4 a, ())) parameterMemory ::- (Memory.FirstClass a am,- IsPrimitive a, IsPrimitive am) =>+ (Memory.FirstClass a, Memory.Stored a ~ am,+ IsPrimitive a, IsPrimitive am,+ TypeNum.PositiveT (TypeNum.D4 :*: LLVM.SizeOf am),+ IsSized am) => Memory.Record r (ParameterStruct am) (Parameter a) parameterMemory = liftA2 Parameter@@ -85,27 +80,28 @@ Memory.C (Parameter l) (Struct (Vector D4 l, (Vector D4 l, ()))) where -} instance- (Memory.FirstClass a am,+ (Memory.FirstClass a, Memory.Stored a ~ am, IsPrimitive a, IsPrimitive am,- IsSized (ParameterStruct am) s) =>- Memory.C (Parameter a) (ParameterStruct am) where+ IsSized am,+ TypeNum.PositiveT (TypeNum.D4 :*: LLVM.SizeOf am)) =>+ Memory.C (Parameter a) where+ type Struct (Parameter a) = ParameterStruct (Memory.Stored a) load = Memory.loadRecord parameterMemory store = Memory.storeRecord parameterMemory decompose = Memory.decomposeRecord parameterMemory compose = Memory.composeRecord parameterMemory parameter ::- (Trans.C a,- IsPrimitive a, IsConst a, IsFloating a) =>+ (SoV.TranscendentalConstant a, IsFloating a, IsPrimitive a) => Value a -> Value a -> CodeGenFunction r (Parameter a) parameter reson freq = do- amp <- A.fdiv (valueOf 1) reson- k <- A.sub (valueOf 1) amp+ amp <- A.fdiv A.one reson+ k <- A.sub A.one amp w <- A.mul freq =<< Value.decons Value.twoPi kr <- A.mul k =<< A.cos w ki <- A.mul k =<< A.sin w - kin <- neg ki+ kin <- A.neg ki kvr <- Vector.assemble [kr,kin,amp, value LLVM.zero] kvi <- Vector.assemble [ki,kr, amp, value LLVM.zero] return (Parameter kvr kvi)@@ -145,7 +141,7 @@ causal :: (IsConst a, Vector.Arithmetic a,- Memory.C (Value (State a)) struct, IsSized struct size) =>+ Memory.C (Value (State a))) => {- (IsConst a, Vector.Arithmetic a, Memory.FirstClass a am,@@ -162,7 +158,7 @@ causalP :: (IsConst a, Vector.Arithmetic a,- Memory.C (Value (State a)) struct, IsSized struct size) =>+ Memory.C (Value (State a))) => {- (IsConst a, Vector.Arithmetic a, Memory.FirstClass a am,
src/Synthesizer/LLVM/Filter/FirstOrder.hs view
@@ -1,11 +1,5 @@ {-# LANGUAGE NoImplicitPrelude #-}-{-# LANGUAGE MultiParamTypeClasses #-}-{-# LANGUAGE FunctionalDependencies #-}-{-# LANGUAGE FlexibleInstances #-}-{-# LANGUAGE FlexibleContexts #-}-{-# LANGUAGE UndecidableInstances #-}-{-# LANGUAGE ExistentialQuantification #-}-{-# LANGUAGE Rank2Types #-}+{-# LANGUAGE TypeFamilies #-} {-# OPTIONS_GHC -fno-warn-orphans #-} module Synthesizer.LLVM.Filter.FirstOrder ( Result(Result,lowpass_,highpass_), Parameter, parameter,@@ -21,33 +15,20 @@ import qualified Synthesizer.Plain.Modifier as Modifier import qualified Synthesizer.LLVM.CausalParameterized.Process as CausalP+import qualified Synthesizer.LLVM.Frame.SerialVector as Serial import qualified Synthesizer.LLVM.Simple.Value as Value-import qualified LLVM.Extra.Memory as Memory-import qualified LLVM.Extra.ScalarOrVector as SoV-import qualified LLVM.Extra.Vector as Vector +import qualified LLVM.Extra.Memory as Memory import qualified LLVM.Extra.Class as Class import qualified LLVM.Extra.Arithmetic as A import LLVM.Extra.Class (Undefined, undefTuple, ) -import qualified Data.TypeLevel.Num as TypeNum- import qualified LLVM.Core as LLVM-import LLVM.Core- (Value, valueOf, Vector,- IsArithmetic, IsFloating,- IsPrimitive, IsSized,- CodeGenFunction, ) import LLVM.Util.Loop (Phi, phis, addPhis, ) import Control.Arrow (arr, (&&&), (<<<), ) import Control.Monad (liftM2, foldM, ) -import qualified Algebra.Transcendental as Trans--- import qualified Algebra.Field as Field--- import qualified Algebra.Module as Module--- import qualified Algebra.Ring as Ring- import NumericPrelude.Numeric import NumericPrelude.Base @@ -59,16 +40,15 @@ instance Undefined a => Undefined (Parameter a) where undefTuple = Class.undefTuplePointed -instance- (Memory.C a s, IsSized s ss) =>- Memory.C (Parameter a) s where+instance (Memory.C a) => Memory.C (Parameter a) where+ type Struct (Parameter a) = Memory.Struct a load = Memory.loadNewtype Parameter store = Memory.storeNewtype (\(Parameter k) -> k) decompose = Memory.decomposeNewtype Parameter compose = Memory.composeNewtype (\(Parameter k) -> k) -instance (Value.Flatten ah al) =>- Value.Flatten (Parameter ah) (Parameter al) where+instance (Value.Flatten a) => Value.Flatten (Parameter a) where+ type Registers (Parameter a) = Parameter (Value.Registers a) flatten = Value.flattenTraversable unfold = Value.unfoldFunctor @@ -80,15 +60,14 @@ tupleDesc = Class.tupleDescFoldable -} -instance (Class.MakeValueTuple ah al) =>- Class.MakeValueTuple (Parameter ah) (Parameter al) where+instance (Class.MakeValueTuple a) => Class.MakeValueTuple (Parameter a) where+ type ValueTuple (Parameter a) = Parameter (Class.ValueTuple a) valueTupleOf = Class.valueTupleOfFunctor parameter ::- (Trans.C a, SoV.RationalConstant a, IsFloating a) =>- Value a ->- CodeGenFunction r (Parameter (Value a))+ (A.Transcendental a, A.RationalConstant a) =>+ a -> LLVM.CodeGenFunction r (Parameter a) parameter reson = Value.flatten $ FirstOrder.parameter@@ -96,7 +75,7 @@ lowpassModifier, highpassModifier ::- (SoV.PseudoModule a v, SoV.IntegerConstant a) =>+ (A.PseudoModule a v, A.IntegerConstant a) => Modifier.Simple -- (FirstOrder.State (Value.T v)) (Value.T v)@@ -106,11 +85,8 @@ highpassModifier = FirstOrder.highpassModifier causalP ::- (SoV.IntegerConstant a, SoV.PseudoModule a v,- Memory.FirstClass a am, IsSized a as, IsSized am ams,- Memory.FirstClass v vm, IsSized v vs, IsSized vm vms) =>- CausalP.T p- (Parameter (Value a), Value v) (Result (Value v))+ (A.IntegerConstant a, A.PseudoModule a v, Memory.C v) =>+ CausalP.T p (Parameter a, v) (Result v) {- in contrast to CausalP.fromModifier this allows for sharing between lowpass and highpass channel@@ -123,20 +99,16 @@ <<< (lowpassCausalP &&& arr snd) lowpassCausalP, highpassCausalP ::- (SoV.IntegerConstant a, SoV.PseudoModule a v,- Memory.FirstClass a am, IsSized a as, IsSized am ams,- Memory.FirstClass v vm, IsSized v vs, IsSized vm vms) =>- CausalP.T p- (Parameter (Value a), Value v) (Value v)+ (A.IntegerConstant a, A.PseudoModule a v, Memory.C v) =>+ CausalP.T p (Parameter a, v) v lowpassCausalP = CausalP.fromModifier lowpassModifier highpassCausalP = CausalP.fromModifier highpassModifier lowpassCausalPackedP, highpassCausalPackedP, causalRecursivePackedP ::- (Memory.FirstClass a am, IsSized a as, IsSized am ams,- TypeNum.Pos n, -- IsSized (Vector n a) vas,- SoV.IntegerConstant a, IsArithmetic a, IsPrimitive a) =>- CausalP.T p- (Parameter (Value a), Value (Vector n a)) (Value (Vector n a))+ (Serial.C v, Serial.Element v ~ a,+ Memory.C a, A.IntegerConstant a,+ A.PseudoRing v, A.PseudoRing a) =>+ CausalP.T p (Parameter a, v) v highpassCausalPackedP = arr snd - lowpassCausalPackedP lowpassCausalPackedP =@@ -144,7 +116,7 @@ (arr fst &&& CausalP.mapSimple (\(FirstOrder.Parameter k, x) ->- A.mul x =<< SoV.replicate =<< A.sub (A.fromInteger' 1) k))+ A.mul x =<< Serial.upsample =<< A.sub (A.fromInteger' 1) k)) {- x = [x0, x1, x2, x3]@@ -164,16 +136,16 @@ CausalP.mapAccumSimple (\(FirstOrder.Parameter k, xk0) y1 -> do y1k <- A.mul k y1- xk1 <- Vector.modify (valueOf 0) (A.add y1k) xk0- let size = Vector.sizeInTuple xk0- kv <- SoV.replicate k+ xk1 <- Serial.modify (LLVM.valueOf 0) (A.add y1k) xk0+ let size = Serial.size xk0+ kv <- Serial.upsample k xk2 <- fmap fst $ foldM (\(y,k0) d -> liftM2 (,) (A.add y =<<- Vector.shiftUpMultiZero d =<<+ Serial.shiftUpMultiZero d =<< A.mul y k0) (A.mul k0 k0)) (xk1,kv)@@ -185,16 +157,16 @@ (\(y,k0) d -> liftM2 (,) (A.add y =<<- Vector.shiftUpMultiZero d =<<+ Serial.shiftUpMultiZero d =<< A.mul y =<<- SoV.replicate k0)+ Serial.upsample k0) (A.mul k0 k0)) (xk1,k) (takeWhile (< size) $ iterate (2*) 1) -}- y0 <- Vector.extract (valueOf $ fromIntegral $ size - 1) xk2+ y0 <- Serial.extract (LLVM.valueOf $ fromIntegral $ size - 1) xk2 return (xk2, y0))- (return (LLVM.value LLVM.zero))+ (return A.zero) {- We can also optimize filtering with time-varying filter parameter.@@ -237,12 +209,10 @@ causalPackedP ::- (SoV.IntegerConstant a, IsArithmetic a, IsPrimitive a,- Memory.FirstClass a am, IsSized a as, IsSized am ams,- TypeNum.Pos n) =>- CausalP.T p- (Parameter (Value a), Value (Vector n a))- (Result (Value (Vector n a)))+ (Serial.C v, Serial.Element v ~ a,+ Memory.C a, A.IntegerConstant a,+ A.PseudoRing v, A.PseudoRing a) =>+ CausalP.T p (Parameter a, v) (Result v) causalPackedP = CausalP.mapSimple (\(l,x) -> do h <- A.sub x l
src/Synthesizer/LLVM/Filter/Moog.hs view
@@ -1,13 +1,11 @@ {-# LANGUAGE NoImplicitPrelude #-}-{-# LANGUAGE MultiParamTypeClasses #-}-{-# LANGUAGE FunctionalDependencies #-}-{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE TypeFamilies #-} {-# LANGUAGE FlexibleContexts #-}-{-# LANGUAGE UndecidableInstances #-} {-# LANGUAGE GeneralizedNewtypeDeriving #-} module Synthesizer.LLVM.Filter.Moog (Parameter, parameter, causalP,+ causalInitP, ) where import qualified Synthesizer.LLVM.Filter.FirstOrder as Filt1@@ -18,23 +16,23 @@ import qualified Synthesizer.LLVM.CausalParameterized.Process as CausalP import qualified Synthesizer.LLVM.Simple.Value as Value+import qualified Synthesizer.LLVM.Parameter as Param import Foreign.Storable (Storable, ) import qualified LLVM.Extra.ScalarOrVector as SoV import qualified LLVM.Extra.Vector as Vector import qualified LLVM.Extra.Memory as Memory+import qualified LLVM.Extra.Arithmetic as A import qualified LLVM.Extra.Class as Class-import LLVM.Extra.Class (Undefined, undefTuple, )+import LLVM.Extra.Class (MakeValueTuple, ValueTuple, Undefined, undefTuple, ) -import LLVM.Core- (valueOf, Value, Struct,- IsConst, IsFloating, IsSized,- CodeGenFunction, )+import qualified LLVM.Core as LLVM+import LLVM.Core (Value, IsConst, IsSized, CodeGenFunction, ) import LLVM.Util.Loop (Phi, phis, addPhis, ) -import qualified Data.TypeLevel.Num as TypeNum-import Data.TypeLevel.Num (d0, d1, )+import qualified Types.Data.Num as TypeNum+import Types.Data.Num (d0, d1, ) import qualified Control.Arrow as Arrow import qualified Control.Applicative as App@@ -43,9 +41,6 @@ import Control.Arrow ((>>>), (&&&), ) import Control.Applicative (liftA2, ) -import qualified Algebra.Transcendental as Trans--- import qualified Algebra.Field as Field--- import qualified Algebra.Module as Module import qualified Algebra.Additive as Additive import NumericPrelude.Numeric@@ -56,59 +51,63 @@ deriving (Functor, App.Applicative, Fold.Foldable, Trav.Traversable) -instance (Phi a, TypeNum.Nat n) =>+instance (Phi a, TypeNum.NaturalT n) => Phi (Parameter n a) where phis = Class.phisTraversable addPhis = Class.addPhisFoldable -instance (Undefined a, TypeNum.Nat n) =>+instance (Undefined a, TypeNum.NaturalT n) => Undefined (Parameter n a) where undefTuple = Class.undefTuplePointed -instance (Class.Zero a, TypeNum.Nat n) =>+instance (Class.Zero a, TypeNum.NaturalT n) => Class.Zero (Parameter n a) where zeroTuple = Class.zeroTuplePointed ++type ParameterStruct a = LLVM.Struct (a, (a, ()))+ parameterMemory ::- (Memory.C a s, IsSized s ss, TypeNum.Nat n) =>- Memory.Record r (Struct (s, (s, ()))) (Parameter n a)+ (Memory.C a, TypeNum.NaturalT n) =>+ Memory.Record r (ParameterStruct (Memory.Struct a)) (Parameter n a) parameterMemory = liftA2 (\f k -> Parameter (Moog.Parameter f k)) (Memory.element (Moog.feedback . getParam) d0) (Memory.element (Moog.lowpassParam . getParam) d1) instance- (Memory.C a s, IsSized s ss, TypeNum.Nat n) =>- Memory.C (Parameter n a) (Struct (s, (s, ()))) where+ (Memory.C a, TypeNum.NaturalT n) =>+ Memory.C (Parameter n a) where+ type Struct (Parameter n a) = ParameterStruct (Memory.Struct a) load = Memory.loadRecord parameterMemory store = Memory.storeRecord parameterMemory decompose = Memory.decomposeRecord parameterMemory compose = Memory.composeRecord parameterMemory -instance (Value.Flatten ah al, TypeNum.Nat n) =>- Value.Flatten (Parameter n ah) (Parameter n al) where+instance (Value.Flatten a, TypeNum.NaturalT n) => Value.Flatten (Parameter n a) where+ type Registers (Parameter n a) = Parameter n (Value.Registers a) flatten = Value.flattenTraversable unfold = Value.unfoldFunctor -instance (Vector.ShuffleMatch m v, TypeNum.Nat n) =>- Vector.ShuffleMatch m (Parameter n v) where+instance (Vector.Simple v, TypeNum.NaturalT n) => Vector.Simple (Parameter n v) where+ type Element (Parameter n v) = Parameter n (Vector.Element v)+ type Size (Parameter n v) = Vector.Size v shuffleMatch = Vector.shuffleMatchTraversable--instance (Vector.Access m a v, TypeNum.Nat n) =>- Vector.Access m (Parameter n a) (Parameter n v) where- insert = Vector.insertTraversable extract = Vector.extractTraversable +instance (Vector.C v, TypeNum.NaturalT n) => Vector.C (Parameter n v) where+ insert = Vector.insertTraversable + parameter ::- (Trans.C a, SoV.RationalConstant a, IsFloating a, TypeNum.Nat n) =>- n -> Value a -> Value a ->- CodeGenFunction r (Parameter n (Value a))+ (A.Transcendental a, A.RationalConstant a, TypeNum.NaturalT n) =>+ n -> a -> a ->+ CodeGenFunction r (Parameter n a) parameter order reson freq = Value.flatten $- Parameter $ Moog.parameter (TypeNum.toInt order)+ Parameter $ Moog.parameter (TypeNum.fromIntegerT order) (Pole (Value.constantValue reson) (Value.constantValue freq)) {-@@ -128,21 +127,19 @@ -} merge ::- (SoV.PseudoModule a v, SoV.IntegerConstant a,- Class.MakeValueTuple v (Value v),- Class.MakeValueTuple a (Value a)) =>- (Parameter n (Value a), Value v) -> Value v ->- CodeGenFunction r (FirstOrder.Parameter (Value a), Value v)+ (A.PseudoModule a v, A.IntegerConstant a) =>+ (Parameter n a, v) -> v ->+ CodeGenFunction r (FirstOrder.Parameter a, v) merge (Parameter (Moog.Parameter f k), x) y0 =- let c :: (Class.MakeValueTuple a (Value a)) => Value a -> Value.T a+ let c :: a -> Value.T a c = Value.constantValue in Value.flatten (fmap c k, c x - c f *> c y0) amplify ::- (SoV.PseudoModule a v, SoV.IntegerConstant a) =>- Parameter n (Value a) ->- Value v ->- CodeGenFunction r (Value v)+ (A.PseudoModule a v, A.IntegerConstant a) =>+ Parameter n a ->+ v ->+ CodeGenFunction r v amplify (Parameter (Moog.Parameter f _k)) y1 = Value.decons $ (1 + Value.constantValue f) *> Value.constantValue y1@@ -151,36 +148,45 @@ (SoV.PseudoModule a v, SoV.IntegerConstant a, IsConst v, Additive.C v, Storable v,- Class.MakeValueTuple v (Value v),- Class.MakeValueTuple a (Value a),- Memory.FirstClass a am, IsSized a as, IsSized am ams,- Memory.FirstClass v vm, IsSized v vs, IsSized vm vms,- TypeNum.Nat n) =>- CausalP.T p- (Parameter n (Value a), Value v) (Value v)+ MakeValueTuple v, ValueTuple v ~ (Value v),+ MakeValueTuple a, ValueTuple a ~ (Value a),+ Memory.FirstClass a, Memory.Stored a ~ am, IsSized a, IsSized am,+ Memory.FirstClass v, Memory.Stored v ~ vm, IsSized v, IsSized vm,+ TypeNum.NaturalT n) =>+ CausalP.T p (Parameter n (Value a), Value v) (Value v) causalP =- causalPSize undefined+ let withZero ::+ (Additive.C v) =>+ (Param.T p v ->+ CausalP.T p (Parameter n (Value a), Value v) (Value v)) ->+ CausalP.T p (Parameter n (Value a), Value v) (Value v)+ withZero proc = proc zero+ in withZero causalInitP -causalPSize ::- (SoV.PseudoModule a v, SoV.IntegerConstant a,- IsConst v, Additive.C v,- Storable v,- Class.MakeValueTuple v (Value v),- Class.MakeValueTuple a (Value a),- Memory.FirstClass a am, IsSized a as, IsSized am ams,- Memory.FirstClass v vm, IsSized v vs, IsSized vm vms,- TypeNum.Nat n) =>- n ->- CausalP.T p- (Parameter n (Value a), Value v) (Value v)-causalPSize n =- let order = TypeNum.toInt n- feedZero = zero- selectOutput = snd `asTypeOf` const (valueOf feedZero)++causalInitP ::+ (A.PseudoModule a v, A.IntegerConstant a,+ Storable vh, Class.MakeValueTuple vh, v ~ Class.ValueTuple vh,+ Memory.C v,+ TypeNum.NaturalT n) =>+ Param.T p vh -> CausalP.T p (Parameter n a, v) v+causalInitP =+ causalInitPSize undefined++causalInitPSize ::+ (A.PseudoModule a v, A.IntegerConstant a,+ Storable vh, Class.MakeValueTuple vh, v ~ Class.ValueTuple vh,+ Memory.C v,+ TypeNum.NaturalT n) =>+ n -> Param.T p vh -> CausalP.T p (Parameter n a, v) v+causalInitPSize n initial =+ let order = TypeNum.fromIntegerT n+ selectOutput :: Param.T p vh -> (b, Class.ValueTuple vh) -> Class.ValueTuple vh+ selectOutput _ = snd in Arrow.arr fst &&& CausalP.feedbackControlled- (return feedZero)+ initial (CausalP.zipWithSimple merge >>> CausalP.replicateControlled order Filt1.lowpassCausalP)- (Arrow.arr selectOutput)+ (Arrow.arr (selectOutput initial)) >>> CausalP.zipWithSimple amplify
src/Synthesizer/LLVM/Filter/SecondOrder.hs view
@@ -1,11 +1,12 @@ {-# LANGUAGE NoImplicitPrelude #-}-{-# LANGUAGE MultiParamTypeClasses #-}-{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE TypeFamilies #-}+{-# LANGUAGE TypeOperators #-} {-# LANGUAGE FlexibleContexts #-}-{-# LANGUAGE UndecidableInstances #-} {-# OPTIONS_GHC -fno-warn-orphans #-} module Synthesizer.LLVM.Filter.SecondOrder (- Parameter, bandpassParameter,+ Parameter(Parameter),+ Filt2.c0, Filt2.c1, Filt2.c2, Filt2.d1, Filt2.d2,+ bandpassParameter, ParameterStruct, composeParameter, decomposeParameter, -- for cascade causalP, causalPackedP, ) where@@ -16,38 +17,27 @@ import qualified Synthesizer.Plain.Modifier as Modifier import qualified Synthesizer.LLVM.CausalParameterized.Process as CausalP+import qualified Synthesizer.LLVM.Frame.SerialVector as Serial import qualified Synthesizer.LLVM.Simple.Value as Value import qualified LLVM.Extra.Memory as Memory-import qualified LLVM.Extra.ScalarOrVector as SoV-import qualified LLVM.Extra.Vector as Vector- import qualified LLVM.Extra.Class as Class import qualified LLVM.Extra.Arithmetic as A import qualified LLVM.Extra.Monad as M import LLVM.Extra.Class (Undefined, undefTuple, ) import qualified LLVM.Core as LLVM-import LLVM.Core- (Value, valueOf, Struct,- IsConst, IsArithmetic, IsFloating,- Vector, IsPrimitive, IsSized,- CodeGenFunction, )+import LLVM.Core (CodeGenFunction, valueOf, ) import LLVM.Util.Loop (Phi, phis, addPhis, ) -import Data.TypeLevel.Num (d0, d1, d2, d3, d4, )-import qualified Data.TypeLevel.Num as TypeNum+import qualified Types.Data.Num as TypeNum+import Types.Data.Num (d0, d1, d2, d3, d4, ) import Control.Arrow (arr, (<<<), (&&&), ) import Control.Monad (liftM2, foldM, ) import Control.Applicative (pure, (<*>), ) import Synthesizer.ApplicativeUtility (liftA4, liftA5, ) -import qualified Algebra.Transcendental as Trans--- import qualified Algebra.Field as Field--- import qualified Algebra.Module as Module--- import qualified Algebra.Ring as Ring- import NumericPrelude.Numeric import NumericPrelude.Base @@ -67,16 +57,16 @@ tupleDesc = Class.tupleDescFoldable -} -instance Class.MakeValueTuple h l =>- Class.MakeValueTuple (Parameter h) (Parameter l) where+instance (Class.MakeValueTuple a) => Class.MakeValueTuple (Parameter a) where+ type ValueTuple (Parameter a) = Parameter (Class.ValueTuple a) valueTupleOf = Class.valueTupleOfFunctor -type ParameterStruct a = Struct (a, (a, (a, (a, (a, ())))))+type ParameterStruct a = LLVM.Struct (a, (a, (a, (a, (a, ()))))) parameterMemory ::- (Memory.C a s, IsSized s ss) =>- Memory.Record r (ParameterStruct s) (Parameter a)+ (Memory.C a) =>+ Memory.Record r (ParameterStruct (Memory.Struct a)) (Parameter a) parameterMemory = liftA5 Parameter (Memory.element Filt2.c0 d0)@@ -86,8 +76,8 @@ (Memory.element Filt2.d2 d4) decomposeParameter ::- Value (ParameterStruct a) ->- CodeGenFunction r (Filt2.Parameter (Value a))+ LLVM.Value (ParameterStruct a) ->+ CodeGenFunction r (Filt2.Parameter (LLVM.Value a)) decomposeParameter param = pure Filt2.Parameter <*> LLVM.extractvalue param TypeNum.d0@@ -97,9 +87,9 @@ <*> LLVM.extractvalue param TypeNum.d4 composeParameter ::- (IsSized a size) =>- Filt2.Parameter (Value a) ->- CodeGenFunction r (Value (ParameterStruct a))+ (LLVM.IsSized a) =>+ Filt2.Parameter (LLVM.Value a) ->+ CodeGenFunction r (LLVM.Value (ParameterStruct a)) composeParameter (Filt2.Parameter c0_ c1_ c2_ d1_ d2_) = (\param -> LLVM.insertvalue param c0_ TypeNum.d0) =<< (\param -> LLVM.insertvalue param c1_ TypeNum.d1) =<<@@ -108,17 +98,16 @@ (\param -> LLVM.insertvalue param d2_ TypeNum.d4) =<< return (LLVM.value LLVM.undef) -instance- (Memory.C a s, IsSized s ss) =>- Memory.C (Parameter a) (Struct (s, (s, (s, (s, (s, ())))))) where+instance (Memory.C a) => Memory.C (Parameter a) where+ type Struct (Parameter a) = ParameterStruct (Memory.Struct a) load = Memory.loadRecord parameterMemory store = Memory.storeRecord parameterMemory decompose = Memory.decomposeRecord parameterMemory compose = Memory.composeRecord parameterMemory -instance (Value.Flatten ah al) =>- Value.Flatten (Parameter ah) (Parameter al) where+instance (Value.Flatten a) => Value.Flatten (Parameter a) where+ type Registers (Parameter a) = Parameter (Value.Registers a) flatten = Value.flattenTraversable unfold = Value.unfoldFunctor @@ -131,9 +120,12 @@ instance Undefined a => Undefined (Filt2.State a) where undefTuple = Class.undefTuplePointed ++type StateStruct a = LLVM.Struct (a, (a, (a, (a, (a, ())))))+ stateMemory ::- (Memory.C a s, IsSized s ss) =>- Memory.Record r (Struct (s, (s, (s, (s, (s, ())))))) (Filt2.State a)+ (Memory.C a) =>+ Memory.Record r (StateStruct (Memory.Struct a)) (Filt2.State a) stateMemory = liftA4 Filt2.State (Memory.element Filt2.u1 d0)@@ -142,41 +134,39 @@ (Memory.element Filt2.y2 d3) -instance- (Memory.C a s, IsSized s ss) =>- Memory.C (Filt2.State a) (Struct (s, (s, (s, (s, (s, ())))))) where+instance (Memory.C a) => Memory.C (Filt2.State a) where+ type Struct (Filt2.State a) = StateStruct (Memory.Struct a) load = Memory.loadRecord stateMemory store = Memory.storeRecord stateMemory decompose = Memory.decomposeRecord stateMemory compose = Memory.composeRecord stateMemory -instance (Value.Flatten ah al) =>- Value.Flatten (Filt2.State ah) (Filt2.State al) where+instance (Value.Flatten a) => Value.Flatten (Filt2.State a) where+ type Registers (Filt2.State a) = Filt2.State (Value.Registers a) flatten = Value.flattenTraversable unfold = Value.unfoldFunctor {-# DEPRECATED bandpassParameter "only for testing, use Universal or Moog filter for production code" #-} bandpassParameter ::- (Trans.C a, IsFloating a, IsConst a) =>- Value a ->- Value a ->- CodeGenFunction r (Parameter (Value a))+ (A.Transcendental a, A.RationalConstant a) =>+ a -> a ->+ CodeGenFunction r (Parameter a) bandpassParameter reson cutoff = do- rreson <- A.fdiv (valueOf 1) reson- k <- A.sub (valueOf 1) rreson- k2 <- LLVM.neg =<< A.mul k k+ rreson <- A.fdiv A.one reson+ k <- A.sub A.one rreson+ k2 <- A.neg =<< A.mul k k kcos <-- A.mul (valueOf 2) =<< A.mul k =<<+ A.mul (A.fromInteger' 2) =<< A.mul k =<< A.cos =<< A.mul cutoff =<< Value.decons Value.twoPi return $ Filt2.Parameter- rreson (valueOf zero) (valueOf zero)+ rreson A.zero A.zero kcos k2 modifier ::- (SoV.PseudoModule a v, SoV.IntegerConstant a) =>+ (A.PseudoModule a v, A.IntegerConstant a) => Modifier.Simple (Filt2.State (Value.T v)) (Parameter (Value.T a))@@ -185,11 +175,8 @@ Filt2.modifier causalP ::- (SoV.PseudoModule a v, SoV.IntegerConstant a,- Memory.FirstClass a am, IsSized a as, IsSized am ams,- Memory.FirstClass v vm, IsSized v vs, IsSized vm vms) =>- CausalP.T p- (Parameter (Value a), Value v) (Value v)+ (A.PseudoModule a v, A.IntegerConstant a, Memory.C v) =>+ CausalP.T p (Parameter a, v) v causalP = CausalP.fromModifier modifier @@ -199,45 +186,31 @@ -} causalPackedP, causalRecursivePackedP ::- (IsArithmetic a, SoV.IntegerConstant a,- Memory.FirstClass a am,- IsPrimitive a, IsSized a asize,- IsPrimitive am, IsSized am amsize,- TypeNum.Mul n asize vasize, TypeNum.Pos vasize,- TypeNum.Mul n amsize vmsize, TypeNum.Pos vmsize,- TypeNum.Pos n) =>--- TypeNum.Pos n, IsPrimitive a, IsSized (Vector n a) as) =>- CausalP.T p- (Parameter (Value a), Value (Vector n a)) (Value (Vector n a))+ (Serial.C v, Serial.Element v ~ a,+ Memory.C v, Memory.C a, A.IntegerConstant v, A.IntegerConstant a,+ A.PseudoRing v, A.PseudoRing a) =>+ CausalP.T p (Parameter a, v) v causalPackedP = causalRecursivePackedP <<< (arr fst &&& causalNonRecursivePackedP) _causalRecursivePackedPAlt, causalNonRecursivePackedP ::- (IsArithmetic a, SoV.IntegerConstant a,- Memory.FirstClass a am,- IsPrimitive a, IsSized a asize,- IsPrimitive am, IsSized am amsize,- TypeNum.Mul n asize vasize, TypeNum.Pos vasize,- TypeNum.Mul n amsize vmsize, TypeNum.Pos vmsize,- TypeNum.Pos n) =>- CausalP.T p- (Parameter (Value a), Value (Vector n a)) (Value (Vector n a))+ (Serial.C v, Serial.Element v ~ a,+ Memory.C a, A.IntegerConstant v, A.IntegerConstant a,+ A.PseudoRing v, A.PseudoRing a) =>+ CausalP.T p (Parameter a, v) v causalNonRecursivePackedP = CausalP.mapAccumSimple (\(p, v0) (x1,x2) -> do- (_,v1) <- Vector.shiftUp x1 v0- (_,v2) <- Vector.shiftUp x2 v1- w0 <- A.mul v0 =<< SoV.replicate (Filt2.c0 p)- w1 <- A.mul v1 =<< SoV.replicate (Filt2.c1 p)- w2 <- A.mul v2 =<< SoV.replicate (Filt2.c2 p)+ (u1n,v1) <- Serial.shiftUp x1 v0+ (u2n,v2) <- Serial.shiftUp x2 v1+ w0 <- A.mul v0 =<< Serial.upsample (Filt2.c0 p)+ w1 <- A.mul v1 =<< Serial.upsample (Filt2.c1 p)+ w2 <- A.mul v2 =<< Serial.upsample (Filt2.c2 p) y <- A.add w0 =<< A.add w1 w2- let size = fromIntegral $ Vector.sizeInTuple v0- u0 <- Vector.extract (valueOf $ size - 1) v0- u1 <- Vector.extract (valueOf $ size - 2) v0- return (y, (u0,u1)))- (return (LLVM.value LLVM.zero, LLVM.value LLVM.zero))+ return (y, (u1n,u2n)))+ (return (A.zero, A.zero)) {- A filter of second order can be considered@@ -273,18 +246,18 @@ causalRecursivePackedP = CausalP.mapAccumSimple (\(p, x0) y1v -> do- let size = Vector.sizeInTuple x0+ let size = Serial.size x0 - d1v <- SoV.replicate (Filt2.d1 p)- d2v <- SoV.replicate (Filt2.d2 p)- d2vn <- LLVM.neg d2v+ d1v <- Serial.upsample (Filt2.d1 p)+ d2v <- Serial.upsample (Filt2.d2 p)+ d2vn <- A.neg d2v - y1 <- Vector.extract (valueOf $ fromIntegral size - 1) y1v+ y1 <- Serial.extract (valueOf $ fromIntegral size - 1) y1v xk1 <-- Vector.modify (valueOf 0)+ Serial.modify (valueOf 0) (\u0 -> A.add u0 =<< A.mul (Filt2.d1 p) y1) =<< A.add x0 =<< A.mul d2v =<<- Vector.shiftDownMultiZero (size - 2) y1v+ Serial.shiftDownMultiZero (size - 2) y1v -- let xk2 = xk1 xk2 <-@@ -301,8 +274,8 @@ and the first operand could be merged with the second operand of the previous step. -}- (Vector.shiftUpMultiZero d =<< A.mul y a)- (Vector.shiftUpMultiZero (2*d) =<< A.mul y b)) $+ (Serial.shiftUpMultiZero d =<< A.mul y a)+ (Serial.shiftUpMultiZero (2*d) =<< A.mul y b)) $ liftM2 (,) (M.liftR2 A.sub (A.mul a a)@@ -312,25 +285,25 @@ (takeWhile (< size) $ iterate (2*) 1) return (xk2, xk2))- (return (LLVM.value LLVM.zero))+ (return A.zero) _causalRecursivePackedPAlt = CausalP.mapAccumSimple (\(p, x0) (x1,x2) -> do- let size = Vector.sizeInTuple x0+ let size = Serial.size x0 -- let xk1 = x0 xk1 <-- Vector.modify (valueOf 0)+ Serial.modify (valueOf 0) (\u0 -> A.add u0 =<< M.liftR2 A.add (A.mul (Filt2.d2 p) x2) (A.mul (Filt2.d1 p) x1)) =<<- Vector.modify (valueOf 1)+ Serial.modify (valueOf 1) (\u1 -> A.add u1 =<< A.mul (Filt2.d2 p) x1) x0 -- let xk2 = xk1- d1v <- SoV.replicate (Filt2.d1 p)- d2v <- SoV.replicate =<< LLVM.neg (Filt2.d2 p)+ d1v <- Serial.upsample (Filt2.d1 p)+ d2v <- Serial.upsample =<< A.neg (Filt2.d2 p) xk2 <- fmap fst $ foldM@@ -338,8 +311,8 @@ liftM2 (,) (A.add y =<< M.liftR2 A.add- (Vector.shiftUpMultiZero d =<< A.mul y a)- (Vector.shiftUpMultiZero (2*d) =<< A.mul y b)) $+ (Serial.shiftUpMultiZero d =<< A.mul y a)+ (Serial.shiftUpMultiZero (2*d) =<< A.mul y b)) $ liftM2 (,) (M.liftR2 A.sub (A.mul a a)@@ -348,10 +321,10 @@ (xk1,(d1v,d2v)) (takeWhile (< size) $ iterate (2*) 1) - y0 <- Vector.extract (valueOf $ fromIntegral size - 1) xk2- y1 <- Vector.extract (valueOf $ fromIntegral size - 2) xk2+ y0 <- Serial.extract (valueOf $ fromIntegral size - 1) xk2+ y1 <- Serial.extract (valueOf $ fromIntegral size - 2) xk2 return (xk2, (y0,y1)))- (return (LLVM.value LLVM.zero, LLVM.value LLVM.zero))+ (return (A.zero, A.zero)) {- A filter of second order can also be represented
src/Synthesizer/LLVM/Filter/SecondOrderCascade.hs view
@@ -1,9 +1,8 @@ {-# LANGUAGE NoImplicitPrelude #-}-{-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE TypeFamilies #-}+{-# LANGUAGE TypeOperators #-} {-# LANGUAGE FlexibleContexts #-}-{-# LANGUAGE FlexibleInstances #-} {-# LANGUAGE UndecidableInstances #-}-{-# LANGUAGE TypeSynonymInstances #-} module Synthesizer.LLVM.Filter.SecondOrderCascade where import qualified Synthesizer.LLVM.Filter.SecondOrder as Filt2@@ -11,6 +10,9 @@ import qualified Synthesizer.LLVM.CausalParameterized.Process as CausalP +import qualified Synthesizer.LLVM.Frame.SerialVector as Serial++import qualified LLVM.Extra.Arithmetic as A import qualified LLVM.Extra.Class as Class import qualified LLVM.Extra.ScalarOrVector as SoV import qualified LLVM.Extra.Memory as Memory@@ -19,12 +21,13 @@ import qualified LLVM.Core as LLVM import LLVM.Util.Loop (Phi, phis, addPhis, ) import LLVM.Core- (Value, valueOf, Vector,- IsArithmetic, IsPrimitive, IsSized,+ (Value, valueOf,+ IsArithmetic, IsSized, CodeGenFunction, ) -import qualified Data.TypeLevel.Num as TypeNum-import qualified Data.TypeLevel.Num.Sets as TypeSet+import qualified Types.Data.Bool as TypeBool+import qualified Types.Data.Num as TypeNum+import Types.Data.Num.Ops ((:*:), ) import Data.Word (Word32, ) @@ -40,10 +43,10 @@ import NumericPrelude.Base -type Parameter n a = LLVM.Array n (Filt2.ParameterStruct a)+type ParameterStruct n a = LLVM.Array n (Filt2.ParameterStruct a) newtype ParameterValue n a =- ParameterValue {parameterValue :: Value (Parameter n a)}+ ParameterValue {parameterValue :: Value (ParameterStruct n a)} {- Automatic deriving is not allowed even with GeneralizedNewtypeDeriving because of IsSized constraint@@ -53,7 +56,7 @@ Functor, App.Applicative, Fold.Foldable, Trav.Traversable) -} -instance (TypeNum.Nat n, IsSized a s) =>+instance (TypeNum.NaturalT n, IsSized a) => Phi (ParameterValue n a) where phis bb (ParameterValue r) = fmap ParameterValue $ phis bb r@@ -62,17 +65,19 @@ (ParameterValue r') = addPhis bb r r' -instance (TypeNum.Nat n, IsSized a s) =>+instance (TypeNum.NaturalT n, IsSized a) => Class.Undefined (ParameterValue n a) where undefTuple = ParameterValue Class.undefTuple -instance (TypeNum.Nat n, IsSized a s) =>+instance (TypeNum.NaturalT n, IsSized a) => Class.Zero (ParameterValue n a) where zeroTuple = ParameterValue Class.zeroTuple -instance- (TypeNum.Nat n, Memory.FirstClass a am, IsSized a s, IsSized am ams) =>- Memory.C (ParameterValue n a) (Parameter n am) where+instance (TypeNum.IntegerT n, TypeNum.IsNatural n ~ TypeBool.True,+ Memory.FirstClass a, Memory.Stored a ~ am, IsSized a, IsSized am,+ TypeNum.PositiveT (n :*: LLVM.UnknownSize)) =>+ Memory.C (ParameterValue n a) where+ type Struct (ParameterValue n a) = ParameterStruct n (Memory.Stored a) load = Memory.loadNewtype ParameterValue store = Memory.storeNewtype (\(ParameterValue k) -> k) decompose = Memory.decomposeNewtype ParameterValue@@ -92,12 +97,12 @@ fixSize _n = id causalP ::- (SoV.PseudoModule a v, SoV.IntegerConstant a,- Memory.FirstClass a am, IsSized a as, IsSized am ams,- Memory.FirstClass v vm, IsSized v vs, IsSized vm vms,- IsArithmetic a, TypeSet.Nat n,- TypeNum.Mul n LLVM.UnknownSize paramSize, TypeSet.Pos paramSize) =>- CausalP.T p (ParameterValue n a, Value v) (Value v)+ (A.PseudoModule (LLVM.Value a) v,+ Memory.FirstClass a, Memory.Stored a ~ am, IsSized a, IsSized am,+ Memory.C v,+ IsArithmetic a, SoV.IntegerConstant a, TypeNum.NaturalT n,+ TypeNum.PositiveT (n :*: LLVM.UnknownSize)) =>+ CausalP.T p (ParameterValue n a, v) v causalP = withSize $ \n -> foldl (\x y -> (arr fst &&& x) >>> y) (arr snd) $@@ -106,20 +111,19 @@ Filt2.causalP <<< Arrow.first (CausalP.mapSimple (\ps -> getStageParameter ps k)))- (take (TypeNum.toInt n) [0..])+ (take (TypeNum.fromIntegerT n) [0..]) causalPackedP ::- (IsArithmetic a, SoV.IntegerConstant a,- Memory.FirstClass a am,- IsPrimitive a, IsSized a asize,- IsPrimitive am, IsSized am amsize,- TypeNum.Mul d asize vasize, TypeNum.Pos vasize,- TypeNum.Mul d amsize vmsize, TypeNum.Pos vmsize,- TypeNum.Pos d,- TypeNum.Mul n LLVM.UnknownSize paramSize, TypeSet.Pos paramSize,- TypeSet.Nat n) =>- CausalP.T p- (ParameterValue n a, Value (Vector d a)) (Value (Vector d a))+ (A.PseudoModule (LLVM.Value a) v,+ Serial.C v, Serial.Element v ~ LLVM.Value a,+ SoV.IntegerConstant a,+ A.PseudoRing v, A.IntegerConstant v, Memory.C v,+ Memory.FirstClass a, Memory.Stored a ~ am, IsSized a, IsSized am,+ LLVM.IsPrimitive a,+ LLVM.IsPrimitive am,+ TypeNum.PositiveT (n :*: LLVM.UnknownSize),+ TypeNum.NaturalT n) =>+ CausalP.T p (ParameterValue n a, v) v causalPackedP = withSize $ \n -> foldl (\x y -> (arr fst &&& x) >>> y) (arr snd) $@@ -128,11 +132,11 @@ Filt2.causalPackedP <<< Arrow.first (CausalP.mapSimple (\ps -> getStageParameter ps k)))- (take (TypeNum.toInt n) [0..])+ (take (TypeNum.fromIntegerT n) [0..]) getStageParameter, getStageParameterMalloc, getStageParameterAlloca ::- (LLVM.IsFirstClass a, IsSized a as, SoV.IntegerConstant a,- TypeSet.Nat n, TypeNum.Mul n LLVM.UnknownSize s, TypeSet.Pos s) =>+ (LLVM.IsFirstClass a, IsSized a, SoV.IntegerConstant a,+ TypeNum.NaturalT n, TypeNum.PositiveT (n :*: LLVM.UnknownSize)) => ParameterValue n a -> Word32 -> CodeGenFunction r (Filt2Core.Parameter (Value a))
src/Synthesizer/LLVM/Filter/SecondOrderPacked.hs view
@@ -1,9 +1,8 @@ {-# LANGUAGE NoImplicitPrelude #-}-{-# LANGUAGE MultiParamTypeClasses #-}-{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE TypeFamilies #-}+{-# LANGUAGE TypeOperators #-} {-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE UndecidableInstances #-}-{-# LANGUAGE TypeSynonymInstances #-} module Synthesizer.LLVM.Filter.SecondOrderPacked ( Parameter, bandpassParameter, State, causalP, ) where@@ -12,20 +11,22 @@ import qualified Synthesizer.Plain.Filter.Recursive.SecondOrder as Filt2 import qualified Synthesizer.LLVM.CausalParameterized.Process as CausalP-import qualified LLVM.Extra.Memory as Memory+import qualified LLVM.Extra.ScalarOrVector as SoV import qualified LLVM.Extra.Vector as Vector+import qualified LLVM.Extra.Memory as Memory import qualified LLVM.Extra.Arithmetic as A import LLVM.Extra.Class (Undefined, undefTuple, ) import qualified LLVM.Core as LLVM import LLVM.Core (Value, valueOf, Struct,- IsFirstClass, IsConst, IsFloating,+ IsFirstClass, IsFloating, Vector, IsPrimitive, IsSized, CodeGenFunction, ) import LLVM.Util.Loop (Phi, phis, addPhis, ) -import Data.TypeLevel.Num (D4, d0, d1, )+import qualified Types.Data.Num as TypeNum+import Types.Data.Num (D4, d0, d1, (:*:), ) import Control.Applicative (liftA2, ) @@ -64,9 +65,9 @@ type ParameterStruct a = Struct (a, (Vector D4 a, ())) parameterMemory ::- (Memory.FirstClass a am,- IsSized a s, IsPrimitive a,- IsSized am ams, IsPrimitive am) =>+ (Memory.FirstClass a, Memory.Stored a ~ am, IsSized a, IsSized am,+ IsPrimitive a, IsPrimitive am,+ TypeNum.PositiveT (D4 :*: LLVM.SizeOf am)) => Memory.Record r (ParameterStruct am) (Parameter a) parameterMemory = liftA2 Parameter@@ -74,11 +75,11 @@ (Memory.element (\(Parameter _ cd) -> cd) d1) instance- (Memory.FirstClass a am,- IsSized a s, IsPrimitive a,- IsSized am ms, IsPrimitive am,- IsSized (ParameterStruct am) sms) =>- Memory.C (Parameter a) (ParameterStruct am) where+ (Memory.FirstClass a, Memory.Stored a ~ am, IsSized a, IsSized am,+ IsPrimitive a, IsPrimitive am,+ TypeNum.PositiveT (D4 :*: LLVM.SizeOf am)) =>+ Memory.C (Parameter a) where+ type Struct (Parameter a) = ParameterStruct (Memory.Stored a) load = Memory.loadRecord parameterMemory store = Memory.storeRecord parameterMemory decompose = Memory.decomposeRecord parameterMemory@@ -90,7 +91,7 @@ {-# DEPRECATED bandpassParameter "only for testing, use Universal or Moog filter for production code" #-} bandpassParameter ::- (Trans.C a, IsFloating a, IsConst a, IsPrimitive a) =>+ (Trans.C a, IsFloating a, SoV.TranscendentalConstant a, IsPrimitive a) => Value a -> Value a -> CodeGenFunction r (Parameter a)@@ -116,7 +117,7 @@ causalP :: (Vector.Arithmetic a,- Memory.C (Value (State a)) struct, IsSized struct size) =>+ Memory.C (Value (State a))) => {- (Vector.Arithmetic a, IsPrimitive am, Memory.FirstClass a am,
src/Synthesizer/LLVM/Filter/Universal.hs view
@@ -1,10 +1,4 @@-{-# LANGUAGE MultiParamTypeClasses #-}-{-# LANGUAGE FunctionalDependencies #-}-{-# LANGUAGE FlexibleInstances #-}-{-# LANGUAGE FlexibleContexts #-}-{-# LANGUAGE UndecidableInstances #-}-{-# LANGUAGE ExistentialQuantification #-}-{-# LANGUAGE Rank2Types #-}+{-# LANGUAGE TypeFamilies #-} {-# OPTIONS_GHC -fno-warn-orphans #-} module Synthesizer.LLVM.Filter.Universal ( Result(Result, lowpass, highpass, bandpass, bandlimit),@@ -19,28 +13,24 @@ import qualified Synthesizer.Plain.Modifier as Modifier import qualified Synthesizer.LLVM.CausalParameterized.Process as CausalP+import qualified Synthesizer.LLVM.Frame.SerialVector as Serial import qualified Synthesizer.LLVM.Simple.Value as Value import qualified LLVM.Extra.Memory as Memory import qualified LLVM.Extra.Class as Class-import qualified LLVM.Extra.ScalarOrVector as SoV import qualified LLVM.Extra.Vector as Vector+import qualified LLVM.Extra.Arithmetic as A import LLVM.Extra.Class (Undefined, undefTuple, ) -import LLVM.Core- (Value, Struct, IsFloating, IsSized, CodeGenFunction, )+import qualified LLVM.Core as LLVM+import LLVM.Core (CodeGenFunction, ) import LLVM.Util.Loop (Phi, phis, addPhis, ) -import Data.TypeLevel.Num (d0, d1, d2, d3, d4, d5, )+import Types.Data.Num (d0, d1, d2, d3, d4, d5, ) import Synthesizer.ApplicativeUtility (liftA6, ) -import qualified Algebra.Transcendental as Trans--- import qualified Algebra.Field as Field--- import qualified Algebra.Module as Module--- import qualified Algebra.Ring as Ring - instance (Phi a) => Phi (Parameter a) where phis = Class.phisTraversable addPhis = Class.addPhisFoldable@@ -48,9 +38,12 @@ instance Undefined a => Undefined (Parameter a) where undefTuple = Class.undefTuplePointed ++type ParameterStruct a = LLVM.Struct (a, (a, (a, (a, (a, (a, ()))))))+ parameterMemory ::- (Memory.C a s, IsSized s ss) =>- Memory.Record r (Struct (s, (s, (s, (s, (s, (s, ()))))))) (Parameter a)+ (Memory.C a) =>+ Memory.Record r (ParameterStruct (Memory.Struct a)) (Parameter a) parameterMemory = liftA6 Parameter (Memory.element Universal.k1 d0)@@ -61,9 +54,8 @@ (Memory.element Universal.ampLimit d5) -instance- (Memory.C a s, IsSized s ss) =>- Memory.C (Parameter a) (Struct (s, (s, (s, (s, (s, (s, ()))))))) where+instance (Memory.C a) => Memory.C (Parameter a) where+ type Struct (Parameter a) = ParameterStruct (Memory.Struct a) load = Memory.loadRecord parameterMemory store = Memory.storeRecord parameterMemory decompose = Memory.decomposeRecord parameterMemory@@ -77,12 +69,12 @@ tupleDesc = Class.tupleDescFoldable -} -instance (Class.MakeValueTuple ah al) =>- Class.MakeValueTuple (Result ah) (Result al) where+instance (Class.MakeValueTuple a) => Class.MakeValueTuple (Result a) where+ type ValueTuple (Result a) = Result (Class.ValueTuple a) valueTupleOf = Class.valueTupleOfFunctor -instance (Value.Flatten ah al) =>- Value.Flatten (Result ah) (Result al) where+instance (Value.Flatten a) => Value.Flatten (Result a) where+ type Registers (Result a) = Result (Value.Registers a) flatten = Value.flattenTraversable unfold = Value.unfoldFunctor @@ -95,26 +87,26 @@ tupleDesc = Class.tupleDescFoldable -} -instance (Class.MakeValueTuple ah al) =>- Class.MakeValueTuple (Parameter ah) (Parameter al) where+instance (Class.MakeValueTuple a) => Class.MakeValueTuple (Parameter a) where+ type ValueTuple (Parameter a) = Parameter (Class.ValueTuple a) valueTupleOf = Class.valueTupleOfFunctor -instance (Value.Flatten ah al) =>- Value.Flatten (Parameter ah) (Parameter al) where+instance (Value.Flatten a) => Value.Flatten (Parameter a) where+ type Registers (Parameter a) = Parameter (Value.Registers a) flatten = Value.flattenTraversable unfold = Value.unfoldFunctor -instance (Vector.ShuffleMatch d v) =>- Vector.ShuffleMatch d (Parameter v) where+instance (Vector.Simple v) => Vector.Simple (Parameter v) where+ type Element (Parameter v) = Parameter (Vector.Element v)+ type Size (Parameter v) = Vector.Size v shuffleMatch = Vector.shuffleMatchTraversable--instance (Vector.Access d a v) =>- Vector.Access d (Parameter a) (Parameter v) where- insert = Vector.insertTraversable extract = Vector.extractTraversable +instance (Vector.C v) => Vector.C (Parameter v) where+ insert = Vector.insertTraversable + instance (Phi a) => Phi (Result a) where phis = Class.phisTraversable addPhis = Class.addPhisFoldable@@ -122,20 +114,36 @@ instance Undefined a => Undefined (Result a) where undefTuple = Class.undefTuplePointed -instance (Vector.ShuffleMatch d v) =>- Vector.ShuffleMatch d (Result v) where+instance (Vector.Simple v) => Vector.Simple (Result v) where+ type Element (Result v) = Result (Vector.Element v)+ type Size (Result v) = Vector.Size v shuffleMatch = Vector.shuffleMatchTraversable+ extract = Vector.extractTraversable -instance (Vector.Access d a v) =>- Vector.Access d (Result a) (Result v) where+instance (Vector.C v) => Vector.C (Result v) where insert = Vector.insertTraversable- extract = Vector.extractTraversable +instance (Serial.Sized v) => Serial.Sized (Result v) where+ type Size (Result v) = Serial.Size v +instance (Serial.Read v) => Serial.Read (Result v) where+ type Element (Result v) = Result (Serial.Element v)+ type ReadIt (Result v) = Result (Serial.ReadIt v)+ extract = Serial.extractTraversable+ readStart = Serial.readStartTraversable+ readNext = Serial.readNextTraversable++instance (Serial.C v) => Serial.C (Result v) where+ type WriteIt (Result v) = Result (Serial.WriteIt v)+ insert = Serial.insertTraversable+ writeStart = Serial.writeStartTraversable+ writeNext = Serial.writeNextTraversable+ writeStop = Serial.writeStopTraversable++ parameter ::- (Trans.C a, SoV.RationalConstant a, IsFloating a) =>- Value a -> Value a ->- CodeGenFunction r (Parameter (Value a))+ (A.Transcendental a, A.RationalConstant a) =>+ a -> a -> CodeGenFunction r (Parameter a) parameter reson freq = Value.flatten $ Universal.parameter@@ -144,7 +152,7 @@ modifier ::- (SoV.PseudoModule a v, SoV.IntegerConstant a) =>+ (A.PseudoModule a v, A.IntegerConstant a) => Modifier.Simple (Universal.State (Value.T v)) (Parameter (Value.T a))@@ -153,11 +161,8 @@ Universal.modifier causalP ::- (SoV.PseudoModule a v, SoV.IntegerConstant a,- Memory.FirstClass a am, IsSized a as, IsSized am ams,- Memory.FirstClass v vm, IsSized v vs, IsSized vm vms) =>- CausalP.T p- (Parameter (Value a), Value v) (Result (Value v))+ (A.PseudoModule a v, A.IntegerConstant a, Memory.C v) =>+ CausalP.T p (Parameter a, v) (Result v) causalP = CausalP.fromModifier modifier
src/Synthesizer/LLVM/Frame.hs view
@@ -1,14 +1,11 @@ {-# LANGUAGE NoImplicitPrelude #-}+{-# LANGUAGE TypeFamilies #-} {-# LANGUAGE FlexibleContexts #-}-{-# LANGUAGE UndecidableInstances #-} module Synthesizer.LLVM.Frame where import qualified Synthesizer.LLVM.Frame.Stereo as Stereo -import qualified LLVM.Extra.ScalarOrVector as SoV import qualified LLVM.Extra.Vector as Vector-import qualified LLVM.Extra.Class as Class-import qualified LLVM.Extra.Control as C import qualified LLVM.Extra.Arithmetic as A import qualified LLVM.Core as LLVM@@ -16,14 +13,13 @@ (CodeGenFunction, Value, Vector, IsPrimitive, IsArithmetic, ) -import qualified Data.TypeLevel.Num as TypeNum-import Data.TypeLevel.Num (D2, D4, )+import qualified Types.Data.Num as TypeNum+import Types.Data.Num (D2, D4, ) import Foreign.Storable.Tuple () -import Data.Word (Word32, )- import qualified Data.Traversable as Trav+import qualified Data.Foldable as Fold import NumericPrelude.Numeric hiding (zero, one, div, signum, ) import NumericPrelude.Base@@ -56,7 +52,7 @@ Stereo.T (Value a) -> CodeGenFunction r (Value (Vector D2 a)) vectorFromStereo =- Vector.assemble . listFromStereo+ Vector.assemble . Fold.toList quadroFromVector ::@@ -73,11 +69,7 @@ CodeGenFunction r (Value (Vector D4 a)) vectorFromQuadro = Vector.assemble .- concatMap listFromStereo . listFromStereo--listFromStereo :: Stereo.T a -> [a]-listFromStereo s =- [Stereo.left s, Stereo.right s]+ concatMap Fold.toList . Fold.toList mix ::@@ -99,13 +91,13 @@ stereoFromVector =<< A.add xv yv mixVector ::- (Vector.Arithmetic a, TypeNum.Pos n) =>+ (Vector.Arithmetic a, TypeNum.PositiveT n) => Value (Vector n a) -> CodeGenFunction r (Value a) mixVector = Vector.sum mixVectorToStereo ::- (Vector.Arithmetic a, TypeNum.Pos n) =>+ (Vector.Arithmetic a, TypeNum.PositiveT n) => Value (Vector n a) -> CodeGenFunction r (Stereo.T (Value a)) mixVectorToStereo =@@ -117,7 +109,7 @@ and components with odd index to the right channel. -} mixInterleavedVectorToStereo ::- (Vector.Arithmetic a, TypeNum.Pos n) =>+ (Vector.Arithmetic a, TypeNum.PositiveT n) => Value (Vector n a) -> CodeGenFunction r (Stereo.T (Value a)) mixInterleavedVectorToStereo =@@ -135,22 +127,3 @@ a -> Stereo.T a -> CodeGenFunction r (Stereo.T a) amplifyStereo x = Trav.mapM (A.mul x)---subsampleVector ::- (Vector.Access n a v) =>- v -> CodeGenFunction r a-subsampleVector =- Vector.extract (LLVM.value LLVM.zero :: Value Word32)---signum ::- (SoV.IntegerConstant a,- LLVM.IsFirstClass a,- LLVM.CmpRet a Bool) =>- Value a -> CodeGenFunction r (Value a)-signum x = do- negative <- A.cmp LLVM.CmpLT x Class.zeroTuple- positive <- A.cmp LLVM.CmpGT x Class.zeroTuple- C.select negative (A.fromInteger' (-1))- =<< C.select positive (A.fromInteger' 1) (A.fromInteger' 0)
+ src/Synthesizer/LLVM/Frame/SerialVector.hs view
@@ -0,0 +1,588 @@+{-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE TypeFamilies #-}+{-# LANGUAGE EmptyDataDecls #-}+{-# LANGUAGE GeneralizedNewtypeDeriving #-}+{- |+A special vector type that represents a time-sequence of samples.+This way we can distinguish safely between LLVM vectors+used for parallel signals and pipelines and+those used for chunky processing of scalar signals.+For the chunky processing this data type allows us+to derive the factor from the type+that time constants have to be multiplied with.+-}+module Synthesizer.LLVM.Frame.SerialVector (+ T(Cons),+ Plain, Value,+ plain, value, constant,++ Read, Element, ReadIt, extract, readStart, readNext,+ C, WriteIt, insert, writeStart, writeNext, writeStop,+ Zero, writeZero,+ Iterator(Iterator), ReadIterator, WriteIterator, ReadMode, WriteMode,++ Sized, Size, size, sizeOfIterator,++ insertTraversable, extractTraversable,+ readStartTraversable, readNextTraversable,+ writeStartTraversable, writeNextTraversable, writeStopTraversable,++ extractAll, assemble, modify,+ upsample, subsample,+ cumulate, iterate, reverse,+ shiftUp, shiftUpMultiZero, shiftDownMultiZero,+ replicate, replicateOf, fromList,+ mapV, zipV,+ ) where++import qualified Synthesizer.LLVM.Frame.Stereo as Stereo+import qualified Synthesizer.LLVM.CausalParameterized.Functional as F++import qualified LLVM.Extra.Vector as Vector+import qualified LLVM.Extra.Arithmetic as A+import qualified LLVM.Extra.Class as Class+import qualified LLVM.Extra.Memory as Memory+import qualified LLVM.Core as LLVM+import LLVM.Extra.Class+ (MakeValueTuple, valueTupleOf, )+import LLVM.Util.Loop (Phi, )++import qualified Types.Data.Num as TypeNum++import qualified Foreign.Storable as St+import Data.Word (Word32, )++import Control.Monad (liftM2, liftM3, foldM, replicateM, (<=<), )+import Control.Applicative (liftA2, )+import qualified Control.Monad.Trans.State as MS+import qualified Control.Applicative as App+import qualified Data.Traversable as Trav++import qualified Data.List.HT as ListHT+import qualified Data.List as List+import Data.Tuple.HT (mapSnd, fst3, snd3, thd3, )++import Prelude hiding (Read, replicate, reverse, iterate, )+++{-+This datatype can be used for both Haskell vector and LLVM.Value Vector.+It should not contain tuples of vectors,+since the interpretation is:+"Everything inside Cons will be virtually concatenated."++We tried to use distinct types (T n a) and (Value n a)+for Haskell and LLVM objects, respectively,+but then GHC-6.12.3 to GHC-7.4.1 could not perform the GeneralizedNewtypeDeriving,+because it was not able to add a (IsPositive n ~ True) constraint+to the instances.++The disadvantage of this approach is,+that we cannot have a type that contains both parallel and serial data.+-}+newtype T v = Cons v+ deriving (+ Eq, St.Storable,+ Class.Zero, Class.Undefined, Phi,+ A.Additive, A.PseudoRing, A.Field, A.Real, A.Fraction,+ A.Algebraic, A.Transcendental,+ A.IntegerConstant, A.RationalConstant, Num)+-- SoV.IntegerConstant, SoV.RationalConstant, SoV.TranscendentalConstant)++instance (A.PseudoModule a v) => A.PseudoModule a (T v) where+ scale a (Cons v) = fmap Cons $ A.scale a v++type instance F.Arguments f (T v) = f (T v)+instance F.MakeArguments (T v) where+ makeArgs = id+++type Plain n a = T (LLVM.Vector n a)+type Value n a = T (LLVM.Value (LLVM.Vector n a))+++plain :: LLVM.Vector n a -> Plain n a+plain = Cons++value :: LLVM.Value (LLVM.Vector n a) -> Value n a+value = Cons+++replicate :: (TypeNum.PositiveT n) => a -> Plain n a+replicate x = Cons $ LLVM.vector [x]++replicateOf :: (TypeNum.PositiveT n, LLVM.IsPrimitive a, LLVM.IsConst a) => a -> Value n a+replicateOf x = Cons $ LLVM.valueOf $ LLVM.vector [x]++fromList :: (TypeNum.PositiveT n) => [a] -> Plain n a+fromList = Cons . LLVM.vector++constant :: (TypeNum.PositiveT n) => a -> T (Vector.Constant n a)+constant = Cons . Vector.constant+++newtype Iterator mode it v = Iterator {unIterator :: it}+ deriving (Class.Undefined, Phi)++type ReadIterator = Iterator ReadMode+type WriteIterator = Iterator WriteMode++data ReadMode+data WriteMode+++instance (Memory.C it) => Memory.C (Iterator mode it v) where+ type Struct (Iterator mode it v) = Memory.Struct it+ load = Memory.loadNewtype Iterator+ store = Memory.storeNewtype (\(Iterator v) -> v)+ decompose = Memory.decomposeNewtype Iterator+ compose = Memory.composeNewtype (\(Iterator v) -> v)+++fmapIt ::+ (ita -> itb) -> (va -> vb) ->+ Iterator mode ita va -> Iterator mode itb vb+fmapIt f _ (Iterator a) = Iterator (f a)+++combineIt2 :: Iterator mode xa va -> Iterator mode xb vb -> Iterator mode (xa,xb) (va,vb)+combineIt2 (Iterator va) (Iterator vb) = Iterator (va,vb)++combineIt3 :: Iterator mode xa va -> Iterator mode xb vb -> Iterator mode xc vc -> Iterator mode (xa,xb,xc) (va,vb,vc)+combineIt3 (Iterator va) (Iterator vb) (Iterator vc) = Iterator (va,vb,vc)++combineItFunctor ::+ (Functor f) =>+ f (Iterator mode x v) -> Iterator mode (f x) (f v)+combineItFunctor =+ Iterator . fmap unIterator++sequenceItFunctor ::+ (Functor f) =>+ Iterator mode (f it) (f v) ->+ f (Iterator mode it v)+sequenceItFunctor =+ fmap Iterator . unIterator+++class+ (TypeNum.PositiveT (Size v), Sized v,+ Phi (ReadIt v), Class.Undefined (ReadIt v),+ Phi v, Class.Undefined v) =>+ Read v where++ type Element v :: *+ type ReadIt v :: *++ extract :: LLVM.Value Word32 -> v -> LLVM.CodeGenFunction r (Element v)++ extractAll :: v -> LLVM.CodeGenFunction r [Element v]+ extractAll x =+ mapM+ (flip extract x . LLVM.valueOf)+ (take (size x) [0..])++ readStart :: v -> LLVM.CodeGenFunction r (ReadIterator (ReadIt v) v)+ readNext ::+ ReadIterator (ReadIt v) v ->+ LLVM.CodeGenFunction r (Element v, ReadIterator (ReadIt v) v)++class (Read v, Phi (WriteIt v), Class.Undefined (WriteIt v)) => C v where+ type WriteIt v :: *++ insert :: LLVM.Value Word32 -> Element v -> v -> LLVM.CodeGenFunction r v++ assemble :: [Element v] -> LLVM.CodeGenFunction r v+ assemble =+ foldM (\v (k,x) -> insert (LLVM.valueOf k) x v) Class.undefTuple .+ zip [0..]++ writeStart :: LLVM.CodeGenFunction r (WriteIterator (WriteIt v) v)+ writeNext ::+ Element v -> WriteIterator (WriteIt v) v ->+ LLVM.CodeGenFunction r (WriteIterator (WriteIt v) v)+ writeStop :: WriteIterator (WriteIt v) v -> LLVM.CodeGenFunction r v++class (C v, Phi (WriteIt v), Class.Zero (WriteIt v)) => Zero v where+ -- initializes the target with zeros+ -- you may only call 'writeStop' on the result of 'writeZero'+ writeZero :: LLVM.CodeGenFunction r (WriteIterator (WriteIt v) v)++instance (Vector.Simple v) => Sized (T v) where+ type Size (T v) = Vector.Size v++{- |+This instance also allows to wrap tuples of vectors,+but you cannot reasonably use them,+because it would mean to serialize vectors with different element types.+-}+instance (Vector.Simple v) => Read (T v) where++ type Element (T v) = Vector.Element v+ type ReadIt (T v) = v++ extract k (Cons v) = Vector.extract k v++ readStart (Cons v) = return $ Iterator v+ readNext (Iterator v0) = do+ x <- Vector.extract (LLVM.valueOf 0) v0+ v1 <- Vector.rotateDown v0+ return (x, Iterator v1)+++instance (Vector.C v) => C (T v) where+ type WriteIt (T v) = v++ insert k a (Cons v) = fmap Cons $ Vector.insert k a v++ writeStart = return (Iterator Class.undefTuple)+ writeNext x (Iterator v0) = do+ v1 <- fmap snd $ Vector.shiftDown x v0+ return (Iterator v1)+ writeStop (Iterator v0) = return (Cons v0)++instance (Vector.C v, Class.Zero v) => Zero (T v) where+ writeZero = return (Iterator Class.zeroTuple)+++instance+ (Read va, Read vb, Size va ~ Size vb) =>+ Read (va, vb) where++ type Element (va, vb) = (Element va, Element vb)+ type ReadIt (va, vb) = (ReadIt va, ReadIt vb)++ extract k (va,vb) =+ liftM2 (,)+ (extract k va)+ (extract k vb)++ readStart (va,vb) =+ liftM2 combineIt2 (readStart va) (readStart vb)+ readNext it = do+ (a, ita) <- readNext $ fmapIt fst fst it+ (b, itb) <- readNext $ fmapIt snd snd it+ return ((a,b), combineIt2 ita itb)++instance+ (C va, C vb, Size va ~ Size vb) =>+ C (va, vb) where++ type WriteIt (va, vb) = (WriteIt va, WriteIt vb)++ insert k (a,b) (va,vb) =+ liftM2 (,)+ (insert k a va)+ (insert k b vb)++ writeStart =+ liftM2 combineIt2 writeStart writeStart+ writeNext (a,b) it =+ liftM2 combineIt2+ (writeNext a $ fmapIt fst fst it)+ (writeNext b $ fmapIt snd snd it)+ writeStop it =+ liftM2 (,)+ (writeStop (fmapIt fst fst it))+ (writeStop (fmapIt snd snd it))++instance+ (Zero va, Zero vb, Size va ~ Size vb) =>+ Zero (va, vb) where++ writeZero =+ liftM2 combineIt2 writeZero writeZero+++instance+ (Read va, Read vb, Read vc,+ Size va ~ Size vb,+ Size vb ~ Size vc) =>+ Read (va, vb, vc) where++ type Element (va, vb, vc) = (Element va, Element vb, Element vc)+ type ReadIt (va, vb, vc) = (ReadIt va, ReadIt vb, ReadIt vc)++ extract k (va,vb,vc) =+ liftM3 (,,)+ (extract k va)+ (extract k vb)+ (extract k vc)++ readStart (va,vb,vc) =+ liftM3 combineIt3 (readStart va) (readStart vb) (readStart vc)+ readNext it = do+ (a, ita) <- readNext $ fmapIt fst3 fst3 it+ (b, itb) <- readNext $ fmapIt snd3 snd3 it+ (c, itc) <- readNext $ fmapIt thd3 thd3 it+ return ((a,b,c), combineIt3 ita itb itc)+++instance+ (C va, C vb, C vc,+ Size va ~ Size vb,+ Size vb ~ Size vc) =>+ C (va, vb, vc) where++ type WriteIt (va, vb, vc) = (WriteIt va, WriteIt vb, WriteIt vc)++ insert k (a,b,c) (va,vb,vc) =+ liftM3 (,,)+ (insert k a va)+ (insert k b vb)+ (insert k c vc)++ writeStart =+ liftM3 combineIt3 writeStart writeStart writeStart+ writeNext (a,b,c) it =+ liftM3 combineIt3+ (writeNext a $ fmapIt fst3 fst3 it)+ (writeNext b $ fmapIt snd3 snd3 it)+ (writeNext c $ fmapIt thd3 thd3 it)+ writeStop it =+ liftM3 (,,)+ (writeStop (fmapIt fst3 fst3 it))+ (writeStop (fmapIt snd3 snd3 it))+ (writeStop (fmapIt thd3 thd3 it))++instance+ (Zero va, Zero vb, Zero vc,+ Size va ~ Size vb,+ Size vb ~ Size vc) =>+ Zero (va, vb, vc) where++ writeZero =+ liftM3 combineIt3 writeZero writeZero writeZero+++instance (Read v) => Read (Stereo.T v) where++ type Element (Stereo.T v) = Stereo.T (Element v)+ type ReadIt (Stereo.T v) = Stereo.T (ReadIt v)++ extract = extractTraversable++ readStart = readStartTraversable+ readNext = readNextTraversable++instance (C v) => C (Stereo.T v) where++ type WriteIt (Stereo.T v) = Stereo.T (WriteIt v)++ insert = insertTraversable++ writeStart = writeStartTraversable+ writeNext = writeNextTraversable+ writeStop = writeStopTraversable++instance (Zero v) => Zero (Stereo.T v) where++ writeZero =+ fmap combineItFunctor $ Trav.sequence $ App.pure writeZero+++modify ::+ (C v) =>+ LLVM.Value Word32 ->+ (Element v -> LLVM.CodeGenFunction r (Element v)) ->+ v -> LLVM.CodeGenFunction r v+modify k f v = do+ flip (insert k) v =<< f =<< extract k v+++subsample ::+ (Read v) =>+ v -> LLVM.CodeGenFunction r (Element v)+subsample v =+ extract (LLVM.value LLVM.zero :: LLVM.Value Word32) v++-- this will be translated to an efficient pshufd+upsample ::+ (C v) =>+ Element v -> LLVM.CodeGenFunction r v+upsample x =+ withSize $ \n -> assemble $ List.replicate n x+++cumulate ::+ (Vector.Arithmetic a, TypeNum.PositiveT n) =>+ LLVM.Value a -> Value n a ->+ LLVM.CodeGenFunction r (LLVM.Value a, Value n a)+cumulate x (Cons v) =+ fmap (mapSnd Cons) $ Vector.cumulate x v+++iterate ::+ (C v) =>+ (Element v -> LLVM.CodeGenFunction r (Element v)) ->+ Element v -> LLVM.CodeGenFunction r v+iterate f x =+ withSize $ \n ->+ assemble =<<+ (flip MS.evalStateT x $+ replicateM n $+ MS.StateT $ \x0 -> do x1 <- f x0; return (x0,x1))++reverse ::+ (C v) =>+ v -> LLVM.CodeGenFunction r v+reverse =+ assemble . List.reverse <=< extractAll++shiftUp ::+ (C v) =>+ Element v -> v -> LLVM.CodeGenFunction r (Element v, v)+shiftUp x v =+ ListHT.switchR+ (return (x,v))+ (\ys0 y -> fmap ((,) y) $ assemble (x:ys0))+ =<<+ extractAll v+++shiftUpMultiZero ::+ (C v, A.Additive (Element v)) =>+ Int -> v -> LLVM.CodeGenFunction r v+shiftUpMultiZero n v =+ assemble . take (size v) . (List.replicate n A.zero ++) =<< extractAll v++shiftDownMultiZero ::+ (C v, A.Additive (Element v)) =>+ Int -> v -> LLVM.CodeGenFunction r v+shiftDownMultiZero n v =+ assemble . take (size v) . (++ List.repeat A.zero) . List.drop n+ =<< extractAll v+++insertTraversable ::+ (C v, Trav.Traversable f, App.Applicative f) =>+ LLVM.Value Word32 -> f (Element v) -> f v -> LLVM.CodeGenFunction r (f v)+insertTraversable n a v =+ Trav.sequence (liftA2 (insert n) a v)++extractTraversable ::+ (Read v, Trav.Traversable f) =>+ LLVM.Value Word32 -> f v -> LLVM.CodeGenFunction r (f (Element v))+extractTraversable n v =+ Trav.mapM (extract n) v+++readStartTraversable ::+ (Trav.Traversable f, App.Applicative f, Read v) =>+ f v -> LLVM.CodeGenFunction r (ReadIterator (f (ReadIt v)) (f v))+readNextTraversable ::+ (Trav.Traversable f, App.Applicative f, Read v) =>+ ReadIterator (f (ReadIt v)) (f v) ->+ LLVM.CodeGenFunction r (f (Element v), ReadIterator (f (ReadIt v)) (f v))++readStartTraversable v =+ fmap combineItFunctor $ Trav.mapM readStart v++readNextTraversable it = do+ st <- Trav.mapM readNext $ sequenceItFunctor it+ return (fmap fst st, combineItFunctor $ fmap snd st)+++writeStartTraversable ::+ (Trav.Traversable f, App.Applicative f, C v) =>+ LLVM.CodeGenFunction r (WriteIterator (f (WriteIt v)) (f v))+writeNextTraversable ::+ (Trav.Traversable f, App.Applicative f, C v) =>+ f (Element v) -> WriteIterator (f (WriteIt v)) (f v) ->+ LLVM.CodeGenFunction r (WriteIterator (f (WriteIt v)) (f v))+writeStopTraversable ::+ (Trav.Traversable f, App.Applicative f, C v) =>+ WriteIterator (f (WriteIt v)) (f v) -> LLVM.CodeGenFunction r (f v)++writeStartTraversable =+ fmap combineItFunctor $ Trav.sequence $ App.pure writeStart++writeNextTraversable x it =+ fmap combineItFunctor $ Trav.sequence $+ liftA2 writeNext x $ sequenceItFunctor it++writeStopTraversable = Trav.mapM writeStop . sequenceItFunctor+++instance (MakeValueTuple v) => MakeValueTuple (T v) where+ type ValueTuple (T v) = T (Class.ValueTuple v)+ valueTupleOf (Cons v) = Cons (Class.valueTupleOf v)++instance (Memory.C v) => Memory.C (T v) where+ type Struct (T v) = Memory.Struct v+ load = Memory.loadNewtype Cons+ store = Memory.storeNewtype (\(Cons v) -> v)+ decompose = Memory.decomposeNewtype Cons+ compose = Memory.composeNewtype (\(Cons v) -> v)+++mapV :: (Functor m) =>+ (LLVM.Value (LLVM.Vector n a) -> m (LLVM.Value (LLVM.Vector n b))) ->+ Value n a -> m (Value n b)+mapV f (Cons x) = fmap Cons (f x)++zipV :: (Functor m) =>+ (c -> d) ->+ (LLVM.Value (LLVM.Vector n a) ->+ LLVM.Value (LLVM.Vector n b) ->+ m c) ->+ Value n a ->+ Value n b ->+ m d+zipV g f (Cons x) (Cons y) =+ fmap g (f x y)++++withSize :: Sized v => (Int -> m v) -> m v+withSize =+ let sz :: (Sized v) => Size v -> (Int -> m v) -> m v+ sz n f = f (TypeNum.fromIntegerT n)+ in sz undefined++size :: Sized v => v -> Int+size =+ let sz :: (Sized v) => Size v -> v -> Int+ sz n _ = TypeNum.fromIntegerT n+ in sz undefined++sizeOfIterator :: Sized v => Iterator mode it v -> Int+sizeOfIterator =+ let sz :: Sized v => v -> Iterator mode it v -> Int+ sz v _ = fromIntegral $ size v+ in sz undefined+++{- |+The type parameter @value@ shall be a virtual LLVM register+or a wrapper around one or more virtual LLVM registers.+-}+class (TypeNum.PositiveT (Size valueTuple)) => Sized valueTuple where+ type Size valueTuple :: *+ serialSize :: valueTuple -> Size valueTuple+ serialSize _ = error "serial size is a type number and has no value"++{- |+Basic LLVM types are all counted as scalar values, even LLVM Vectors.+This means that an LLVM Vector can be used for parallel handling of data.+-}+instance Sized (LLVM.Value a) where+ type Size (LLVM.Value a) = TypeNum.D1++instance (Sized value) => Sized (Stereo.T value) where+ type Size (Stereo.T value) = Size value++instance+ (Sized value0, Sized value1,+ Size value0 ~ Size value1) =>+ Sized (value0, value1) where+ type Size (value0, value1) = Size value0++instance+ (Sized value0, Sized value1, Sized value2,+ Size value0 ~ Size value1,+ Size value1 ~ Size value2) =>+ Sized (value0, value1, value2) where+ type Size (value0, value1, value2) = Size value0
src/Synthesizer/LLVM/Frame/Stereo.hs view
@@ -1,7 +1,4 @@-{-# LANGUAGE MultiParamTypeClasses #-}-{-# LANGUAGE FunctionalDependencies #-}-{-# LANGUAGE UndecidableInstances #-}-{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE TypeFamilies #-} {-# OPTIONS_GHC -fno-warn-orphans #-} {- | Re-export functions from "Sound.Frame.Stereo"@@ -16,6 +13,8 @@ Stereo.arrowFromMonoControlled, Stereo.arrowFromChannels, interleave,+ sequence,+ liftApplicative, ) where import qualified Synthesizer.Frame.Stereo as Stereo@@ -28,24 +27,36 @@ import qualified LLVM.Core as LLVM import LLVM.Extra.Class (Undefined, undefTuple,- MakeValueTuple, valueTupleOf, )+ MakeValueTuple, ValueTuple, valueTupleOf, ) import LLVM.Util.Loop (Phi, phis, addPhis, ) -import Data.TypeLevel.Num (d0, d1, )+import Types.Data.Num (d0, d1, ) import Control.Monad (liftM2, )-import Control.Applicative (liftA2, )+import Control.Applicative (Applicative, liftA2, ) import qualified Data.Traversable as Trav +import Prelude hiding (sequence, ) + -- if it turns out to be useful, we may move it to sample-frame package interleave :: (Stereo.T a, Stereo.T b) -> Stereo.T (a,b)-interleave (p,f) =+interleave = uncurry (liftA2 (,))++-- if it turns out to be useful, we may move it to sample-frame package+sequence :: (Functor f) => f (Stereo.T a) -> Stereo.T (f a)+sequence x = Stereo.cons- (Stereo.left p, Stereo.left f)- (Stereo.right p, Stereo.right f)+ (fmap Stereo.left x)+ (fmap Stereo.right x) +liftApplicative ::+ (Applicative f) =>+ (f a -> f b) -> f (Stereo.T a) -> f (Stereo.T b)+liftApplicative proc =+ Trav.sequenceA . fmap proc . sequence + instance (Class.Zero a) => Class.Zero (Stereo.T a) where zeroTuple = Stereo.cons Class.zeroTuple Class.zeroTuple @@ -56,11 +67,11 @@ select = C.selectTraversable {--instance LLVM.CmpRet a b => LLVM.CmpRet (Stereo.T a) (Stereo.T b) where+instance LLVM.CmpRet a, LLVM.CmpResult a ~ b => LLVM.CmpRet (Stereo.T a) (Stereo.T b) where -} -instance MakeValueTuple h l =>- MakeValueTuple (Stereo.T h) (Stereo.T l) where+instance (MakeValueTuple h) => MakeValueTuple (Stereo.T h) where+ type ValueTuple (Stereo.T h) = Stereo.T (ValueTuple h) valueTupleOf s = Stereo.cons (Class.valueTupleOf $ Stereo.left s)@@ -87,25 +98,28 @@ addPhis bb (Stereo.right x) (Stereo.right y) -instance (Vector.ShuffleMatch n v) => Vector.ShuffleMatch n (Stereo.T v) where+instance (Vector.Simple v) => Vector.Simple (Stereo.T v) where+ type Element (Stereo.T v) = Stereo.T (Vector.Element v)+ type Size (Stereo.T v) = Vector.Size v shuffleMatch = Vector.shuffleMatchTraversable--instance (Vector.Access n a v) => Vector.Access n (Stereo.T a) (Stereo.T v) where- insert = Vector.insertTraversable extract = Vector.extractTraversable +instance (Vector.C v) => Vector.C (Stereo.T v) where+ insert = Vector.insertTraversable ++type Struct a = LLVM.Struct (a, (a, ()))+ memory ::- (Memory.C l s, LLVM.IsSized s ss) =>- Memory.Record r (LLVM.Struct (s, (s, ()))) (Stereo.T l)+ (Memory.C l) =>+ Memory.Record r (Struct (Memory.Struct l)) (Stereo.T l) memory = liftA2 Stereo.cons (Memory.element Stereo.left d0) (Memory.element Stereo.right d1) -instance- (Memory.C l s, LLVM.IsSized s ss) =>- Memory.C (Stereo.T l) (LLVM.Struct (s, (s, ()))) where+instance (Memory.C l) => Memory.C (Stereo.T l) where+ type Struct (Stereo.T l) = Struct (Memory.Struct l) load = Memory.loadRecord memory store = Memory.storeRecord memory decompose = Memory.decomposeRecord memory
src/Synthesizer/LLVM/Frame/StereoInterleaved.hs view
@@ -1,7 +1,7 @@-{-# LANGUAGE MultiParamTypeClasses #-}-{-# LANGUAGE FunctionalDependencies #-}+{-# LANGUAGE TypeOperators #-}+{-# LANGUAGE TypeFamilies #-} {-# LANGUAGE UndecidableInstances #-}-{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE FlexibleContexts #-} {-# OPTIONS_GHC -fno-warn-orphans #-} {- | Represent a vector of Stereo values in two vectors@@ -23,33 +23,37 @@ -} module Synthesizer.LLVM.Frame.StereoInterleaved ( T,- Value,+ Value(Value), interleave, deinterleave,+ assemble, extractAll,+ amplify, ) where import qualified Synthesizer.LLVM.Frame.Stereo as Stereo+import qualified Synthesizer.LLVM.Frame.SerialVector as Serial import qualified LLVM.Extra.Arithmetic as A+import qualified LLVM.Extra.Control as C import qualified LLVM.Extra.Class as Class+import qualified LLVM.Extra.Memory as Memory+import qualified LLVM.Extra.ScalarOrVector as SoV+import qualified LLVM.Extra.Vector as Vector import qualified LLVM.Core as LLVM import LLVM.Extra.Class (Undefined, undefTuple, MakeValueTuple, valueTupleOf, ) import LLVM.Core- (Vector, Struct, IsSized, )+ (Vector, IsSized, SizeOf, ) import LLVM.Util.Loop (Phi, phis, addPhis, ) -import qualified LLVM.Extra.Memory as Memory--- import qualified LLVM.Extra.Control as C--- import qualified LLVM.Extra.Arithmetic as A-import qualified LLVM.Extra.Vector as Vector-import qualified Data.TypeLevel.Num as TypeNum+import qualified Types.Data.Num as TypeNum import Foreign.Ptr (castPtr, ) import qualified Foreign.Storable as St -- import Data.Word (Word32, ) +import qualified Data.Foldable as Fold import Control.Monad (liftM2, ) import Control.Applicative (liftA2, ) @@ -61,34 +65,53 @@ data Value n a = Value (LLVM.Value (Vector n a)) (LLVM.Value (Vector n a)) +withSize :: (TypeNum.IntegerT n) => (Int -> m (Value n a)) -> m (Value n a)+withSize =+ let sz :: (TypeNum.IntegerT n) => n -> (Int -> m (Value n a)) -> m (Value n a)+ sz n f = f (TypeNum.fromIntegerT n)+ in sz undefined++ interleave ::- (LLVM.IsPrimitive a, TypeNum.Pos n) =>- Stereo.T (LLVM.Value (Vector n a)) ->+ (LLVM.IsPrimitive a, TypeNum.PositiveT n) =>+ Stereo.T (Serial.Value n a) -> LLVM.CodeGenFunction r (Value n a) interleave x =- uncurry (liftM2 Value) .- mapPair (Vector.assemble, Vector.assemble) .- splitAt (Vector.sizeInTuple x) .- concatMap (\s -> [Stereo.left s, Stereo.right s]) =<<- Vector.extractAll x+ assemble =<< Serial.extractAll x deinterleave ::- (LLVM.IsPrimitive a, TypeNum.Pos n) =>+ (LLVM.IsPrimitive a, TypeNum.PositiveT n) => Value n a ->- LLVM.CodeGenFunction r (Stereo.T (LLVM.Value (Vector n a)))-deinterleave (Value v0 v1) =- Vector.assemble .- (let aux (l:r:xs) = Stereo.cons l r : aux xs- aux [] = []- aux _ = error "odd number of stereo elements"- in aux) =<<+ LLVM.CodeGenFunction r (Stereo.T (Serial.Value n a))+deinterleave v =+ Serial.assemble =<< extractAll v++assemble ::+ (LLVM.IsPrimitive a, TypeNum.IntegerT n, TypeNum.PositiveT n) =>+ [Stereo.T (LLVM.Value a)] -> LLVM.CodeGenFunction r (Value n a)+assemble x =+ withSize $ \n ->+ uncurry (liftM2 Value) .+ mapPair (Vector.assemble, Vector.assemble) .+ splitAt n .+ concatMap Fold.toList $ x++extractAll ::+ (LLVM.IsPrimitive a, TypeNum.IntegerT n, TypeNum.PositiveT n) =>+ Value n a -> LLVM.CodeGenFunction r [Stereo.T (LLVM.Value a)]+extractAll (Value v0 v1) =+ fmap+ (let aux (l:r:xs) = Stereo.cons l r : aux xs+ aux [] = []+ aux _ = error "odd number of stereo elements"+ in aux) $ liftM2 (++) (Vector.extractAll v0) (Vector.extractAll v1) instance- (TypeNum.Pos n, LLVM.IsPrimitive a, St.Storable a) =>+ (TypeNum.PositiveT n, LLVM.IsPrimitive a, St.Storable a) => St.Storable (T n a) where sizeOf ~(Cons v0 v1) = St.sizeOf v0 + St.sizeOf v1 alignment ~(Cons v _) = St.alignment v@@ -102,96 +125,124 @@ in St.pokeElemOff p 0 v0 >> St.pokeElemOff p 1 v1 -instance (TypeNum.Pos n, LLVM.IsPrimitive a) => Class.Zero (Value n a) where+instance (TypeNum.PositiveT n, LLVM.IsPrimitive a) => Class.Zero (Value n a) where zeroTuple = Value (LLVM.value LLVM.zero) (LLVM.value LLVM.zero) -instance (TypeNum.Pos n, LLVM.IsPrimitive a) => Undefined (Value n a) where+instance (TypeNum.PositiveT n, LLVM.IsPrimitive a) => Undefined (Value n a) where undefTuple = Value (LLVM.value LLVM.undef) (LLVM.value LLVM.undef) {- Can only be implemented by ifThenElse since the atomic 'select' command wants a bool vector. -instance (TypeNum.Pos n, LLVM.IsPrimitive a, Phi a) => C.Select (Value n a) where+instance (TypeNum.PositiveT n, LLVM.IsPrimitive a, Phi a) => C.Select (Value n a) where select b (Value x0 x1) (Value y0 y1) = liftM2 Value (C.select b x0 y0) (C.select b x1 y1) -instance LLVM.CmpRet a b => LLVM.CmpRet (Stereo.T a) (Stereo.T b) where+instance LLVM.CmpRet a, LLVM.CmpResult a ~ b => LLVM.CmpRet (Stereo.T a) (Stereo.T b) where -} -instance (TypeNum.Pos n, LLVM.IsPrimitive a, LLVM.IsConst a) =>- MakeValueTuple (T n a) (Value n a) where+instance (TypeNum.PositiveT n, LLVM.IsPrimitive a, LLVM.IsConst a) =>+ MakeValueTuple (T n a) where+ type ValueTuple (T n a) = Value n a valueTupleOf (Cons v0 v1) = Value (LLVM.valueOf v0) (LLVM.valueOf v1) -instance (TypeNum.Pos n, LLVM.IsPrimitive a) => Phi (Value n a) where+instance (TypeNum.PositiveT n, LLVM.IsPrimitive a) => Phi (Value n a) where phis bb = mapV (phis bb) addPhis bb = zipV (\_ _ -> ()) (addPhis bb) -{--instance Vector.ShuffleMatch n (Value n a) where- shuffleMatch = Vector.shuffleMatchAccess--} -{--We cannot make an instance of Vector.Access,-since we defined the functional dependencies in a way,-that vector size and element type uniquely defines the vector type.+instance (TypeNum.PositiveT n) => Serial.Sized (Value n a) where+ type Size (Value n a) = n -instance Vector.Access n (Stereo.T a) (Value n a) where+{- |+The implementation of 'extract' may need to perform+arithmetics at run-time and is thus a bit inefficient.+-}+instance (TypeNum.PositiveT n, LLVM.IsPrimitive a, LLVM.IsFirstClass a) => Serial.Read (Value n a) where+ type Element (Value n a) = Stereo.T (LLVM.Value a)+ type ReadIt (Value n a) = Value n a -insert ::- LLVM.Value Word32 ->- LLVM.Value a ->- Value n a ->- LLVM.CodeGenFunction r (Value n a)-insert k a (Value v0 v1) = do- k20 <- A.add k k- k21 <- A.inc k20- select (k20<Vector.size v0) ...- Vector.insert k20 (Stereo.left a) v >>=- Vector.insert k21 (Stereo.right a)+ extract k (Value v0 v1) =+ let size = LLVM.valueOf $ fromIntegral $ Vector.sizeInTuple v0+ ext j = do+ b <- A.cmp LLVM.CmpLT j size+ C.ifThenElse b+ (Vector.extract j v0)+ (do j1 <- A.sub j size+ Vector.extract j1 v1)+ in do+ k20 <- A.add k k+ k21 <- A.inc k20+ liftM2 Stereo.cons (ext k20) (ext k21) -extract ::- LLVM.Value Word32 ->- Value n a ->- LLVM.CodeGenFunction r (LLVM.Value a)-extract k (Value v0 v1) = do- k20 <- A.add k k- k21 <- A.inc k20- liftM2 Value- (Vector.extract k20 v)- (Vector.extract k21 v)+ extractAll = extractAll + readStart = return . Serial.Iterator+ readNext (Serial.Iterator v) = do+ xt <- extractAll v+ case xt of+ x:xs -> fmap ((,) x . Serial.Iterator) $ assemble xs+ [] -> error "StereoInterleaved.readNext: size zero" -With this instance,-both 'interleave' and 'deinterleave' could then be written this way: - Vector.assemble =<<- mapM (flip Vector.extract x) (take (Vector.size x) [0..])+{- |+The implementation of 'insert' may need to perform+arithmetics at run-time and is thus a bit inefficient. -}+instance (TypeNum.PositiveT n, LLVM.IsPrimitive a, LLVM.IsFirstClass a) => Serial.C (Value n a) where+ type WriteIt (Value n a) = Value n a + insert k x v =+ let size = LLVM.valueOf $ fromIntegral $ Serial.size v+ ins j c (Value v0 v1) = do+ b <- A.cmp LLVM.CmpLT j size+ C.ifThenElse b+ (do w0 <- Vector.insert j c v0+ return $ Value w0 v1)+ (do j1 <- A.sub j size+ w1 <- Vector.insert j1 c v1+ return $ Value v0 w1)+ in do+ k20 <- A.add k k+ k21 <- A.inc k20+ ins k21 (Stereo.right x) =<< ins k20 (Stereo.left x) v++ assemble = assemble++ writeStart = return (Serial.Iterator Class.undefTuple)+ writeNext x (Serial.Iterator v) = do+ xs <- extractAll v+ fmap Serial.Iterator $ assemble $ tail xs ++ [x]+ writeStop (Serial.Iterator v) = return v+++type Struct n a = LLVM.Struct (Vector n a, (Vector n a, ()))+ memory ::- (TypeNum.Pos n, LLVM.IsPrimitive a, LLVM.IsPrimitive am,- Memory.FirstClass a am) =>- Memory.Record r (Struct (Vector n am, (Vector n am, ()))) (Value n a)+ (TypeNum.PositiveT n, LLVM.IsPrimitive a, LLVM.IsPrimitive am,+ Memory.FirstClass a, Memory.Stored a ~ am,+ IsSized am, TypeNum.PositiveT (n TypeNum.:*: SizeOf am)) =>+ Memory.Record r (Struct n am) (Value n a) memory = liftA2 Value (Memory.element (\(Value v _) -> v) TypeNum.d0) (Memory.element (\(Value _ v) -> v) TypeNum.d1) instance- (TypeNum.Pos n,- Memory.FirstClass a am,- LLVM.IsPrimitive a, IsSized a as,- TypeNum.Mul n as vs, TypeNum.Pos vs,- LLVM.IsPrimitive am, IsSized am amsize,- TypeNum.Mul n amsize vmsize, TypeNum.Pos vmsize) =>- Memory.C (Value n a) (Struct (Vector n am, (Vector n am, ()))) where+ (TypeNum.PositiveT n,+ Memory.FirstClass a, Memory.Stored a ~ am,+ LLVM.IsPrimitive a, IsSized a,+ TypeNum.PositiveT (n TypeNum.:*: SizeOf a),+ LLVM.IsPrimitive am, IsSized am,+ TypeNum.PositiveT (n TypeNum.:*: SizeOf am)) =>+ Memory.C (Value n a) where+ type Struct (Value n a) = Struct n (Memory.Stored a) load = Memory.loadRecord memory store = Memory.storeRecord memory decompose = Memory.decomposeRecord memory@@ -201,12 +252,25 @@ This instance allows to run @arrange@ on interleaved stereo vectors. -} instance- (TypeNum.Pos n, LLVM.IsPrimitive a, LLVM.IsArithmetic a) =>+ (TypeNum.PositiveT n, LLVM.IsPrimitive a, LLVM.IsArithmetic a) => A.Additive (Value n a) where zero = Value A.zero A.zero add = zipV Value A.add sub = zipV Value A.sub neg = mapV A.neg+++scale ::+ (TypeNum.PositiveT n, LLVM.IsPrimitive a, LLVM.IsArithmetic a) =>+ LLVM.Value a -> Value n a -> LLVM.CodeGenFunction r (Value n a)+scale a v = do+ av <- SoV.replicate a+ mapV (A.mul av) v++amplify ::+ (TypeNum.PositiveT n, LLVM.IsPrimitive a, LLVM.IsArithmetic a, LLVM.IsConst a) =>+ a -> Value n a -> LLVM.CodeGenFunction r (Value n a)+amplify a = scale (LLVM.valueOf a) mapV :: (Monad m) =>
src/Synthesizer/LLVM/Generator/Exponential2.hs view
@@ -1,9 +1,7 @@ {-# LANGUAGE NoImplicitPrelude #-}-{-# LANGUAGE MultiParamTypeClasses #-}-{-# LANGUAGE FunctionalDependencies #-}-{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE TypeFamilies #-}+{-# LANGUAGE TypeOperators #-} {-# LANGUAGE FlexibleContexts #-}-{-# LANGUAGE UndecidableInstances #-} {-# LANGUAGE GeneralizedNewtypeDeriving #-} {- | Exponential curve with controllable delay.@@ -23,23 +21,24 @@ import qualified Synthesizer.LLVM.CausalParameterized.Process as CausalP import qualified Synthesizer.LLVM.Simple.Value as Value import qualified Synthesizer.LLVM.Parameter as Param-import qualified Synthesizer.LLVM.SerialVector as Serial+import qualified Synthesizer.LLVM.Frame.SerialVector as Serial+import qualified Synthesizer.LLVM.CausalParameterized.Functional as F import qualified LLVM.Extra.ScalarOrVector as SoV import qualified LLVM.Extra.Vector as Vector import qualified LLVM.Extra.Memory as Memory import qualified LLVM.Extra.Class as Class import qualified LLVM.Extra.Arithmetic as A-import LLVM.Extra.Class (Undefined, undefTuple, )+import LLVM.Extra.Class (MakeValueTuple, ValueTuple, Undefined, undefTuple, ) import qualified LLVM.Core as LLVM import LLVM.Core- (Value, valueOf, Vector,- IsArithmetic, IsPrimitive, IsFloating, IsSized,+ (Value, IsArithmetic, IsPrimitive, IsFloating, IsSized, SizeOf, CodeGenFunction, ) import LLVM.Util.Loop (Phi, phis, addPhis, ) -import qualified Data.TypeLevel.Num as TypeNum+import qualified Types.Data.Num as TypeNum+import Types.Data.Num.Ops ((:*:), ) import Foreign.Storable (Storable, ) import qualified Foreign.Storable@@ -96,9 +95,8 @@ instance Class.Zero a => Class.Zero (Parameter a) where zeroTuple = Class.zeroTuplePointed -instance- (Memory.C a s, IsSized s ss) =>- Memory.C (Parameter a) s where+instance (Memory.C a) => Memory.C (Parameter a) where+ type Struct (Parameter a) = Memory.Struct a load = Memory.loadNewtype Parameter store = Memory.storeNewtype (\(Parameter k) -> k) decompose = Memory.decomposeNewtype Parameter@@ -113,29 +111,29 @@ tupleDesc = Class.tupleDescFoldable -} -instance (Class.MakeValueTuple ah al) =>- Class.MakeValueTuple (Parameter ah) (Parameter al) where+instance (MakeValueTuple a) => MakeValueTuple (Parameter a) where+ type ValueTuple (Parameter a) = Parameter (Class.ValueTuple a) valueTupleOf = Class.valueTupleOfFunctor -instance (Value.Flatten ah al) =>- Value.Flatten (Parameter ah) (Parameter al) where+instance (Value.Flatten a) => Value.Flatten (Parameter a) where+ type Registers (Parameter a) = Parameter (Value.Registers a) flatten = Value.flattenTraversable unfold = Value.unfoldFunctor -instance (Vector.ShuffleMatch n v) =>- Vector.ShuffleMatch n (Parameter v) where+instance (Vector.Simple v) => Vector.Simple (Parameter v) where+ type Element (Parameter v) = Parameter (Vector.Element v)+ type Size (Parameter v) = Vector.Size v shuffleMatch = Vector.shuffleMatchTraversable+ extract = Vector.extractTraversable -instance (Vector.Access n a v) =>- Vector.Access n (Parameter a) (Parameter v) where+instance (Vector.C v) => Vector.C (Parameter v) where insert = Vector.insertTraversable- extract = Vector.extractTraversable parameter ::- (Trans.C a, SoV.RationalConstant a, IsFloating a) =>+ (Trans.C a, SoV.TranscendentalConstant a, IsFloating a) => Value a -> CodeGenFunction r (Parameter (Value a)) parameter halfLife =@@ -150,11 +148,10 @@ causalP ::- (Memory.FirstClass a am, IsSized a as, IsSized am ams, SoV.IntegerConstant a,- IsArithmetic a,- Storable a, Class.MakeValueTuple a (Value a)) =>+ (Storable a, MakeValueTuple a, ValueTuple a ~ al,+ Memory.C al, A.PseudoRing al) => Param.T p a ->- CausalP.T p (Parameter (Value a)) (Value a)+ CausalP.T p (Parameter al) al causalP initial = CausalP.loop initial (arr snd &&& CausalP.zipWithSimple (\(Parameter a) -> A.mul a))@@ -222,17 +219,18 @@ poke = Store.poke +type ParameterPackedStruct a = LLVM.Struct (a, (a, ()))+ memory ::- (Memory.C l s, IsSized s ss) =>- Memory.Record r (LLVM.Struct (s, (s, ()))) (ParameterPacked l)+ (Memory.C a) =>+ Memory.Record r (ParameterPackedStruct (Memory.Struct a)) (ParameterPacked a) memory = liftA2 ParameterPacked (Memory.element ppFeedback TypeNum.d0) (Memory.element ppCurrent TypeNum.d1) -instance- (Memory.C l s, IsSized s ss) =>- Memory.C (ParameterPacked l) (LLVM.Struct (s, (s, ()))) where+instance (Memory.C a) => Memory.C (ParameterPacked a) where+ type Struct (ParameterPacked a) = ParameterPackedStruct (Memory.Struct a) load = Memory.loadRecord memory store = Memory.storeRecord memory decompose = Memory.decomposeRecord memory@@ -247,48 +245,43 @@ tupleDesc = Class.tupleDescFoldable -} -instance (Class.MakeValueTuple ah al) =>- Class.MakeValueTuple (ParameterPacked ah) (ParameterPacked al) where+instance (MakeValueTuple a) => MakeValueTuple (ParameterPacked a) where+ type ValueTuple (ParameterPacked a) = ParameterPacked (Class.ValueTuple a) valueTupleOf = Class.valueTupleOfFunctor -instance (Value.Flatten ah al) =>- Value.Flatten (ParameterPacked ah) (ParameterPacked al) where+instance (Value.Flatten a) => Value.Flatten (ParameterPacked a) where+ type Registers (ParameterPacked a) = ParameterPacked (Value.Registers a) flatten = Value.flattenTraversable unfold = Value.unfoldFunctor --instance (Vector.ShuffleMatch m v) =>- Vector.ShuffleMatch m (ParameterPacked v) where- shuffleMatch = Vector.shuffleMatchTraversable--instance (Vector.Access m a v) =>- Vector.Access m (ParameterPacked a) (ParameterPacked v) where- insert = Vector.insertTraversable- extract = Vector.extractTraversable+type instance F.Arguments f (ParameterPacked a) = f (ParameterPacked a)+instance F.MakeArguments (ParameterPacked a) where+ makeArgs = id withSize ::- (n -> m (param (Value (Vector n a)))) ->- m (param (Value (Vector n a)))+ (Serial.C v, Serial.Size v ~ n, TypeNum.PositiveT n) =>+ (n -> m (param v)) ->+ m (param v) withSize f = f undefined parameterPacked ::- (Trans.C a, SoV.RationalConstant a, IsFloating a,- IsPrimitive a, TypeNum.Pos n) =>- Value a ->- CodeGenFunction r (ParameterPacked (Value (Vector n a)))+ (Serial.C v, Serial.Element v ~ a,+ A.PseudoRing v, A.RationalConstant v,+ A.Transcendental a, A.RationalConstant a) =>+ a -> CodeGenFunction r (ParameterPacked v) parameterPacked halfLife = withSize $ \n -> do feedback <-- SoV.replicate =<<- A.pow (valueOf 0.5) =<<- A.fdiv (valueOf $ fromIntegral $ TypeNum.toInt n) halfLife+ Serial.upsample =<<+ A.pow (A.fromRational' 0.5) =<<+ A.fdiv (A.fromInteger' $ TypeNum.fromIntegerT n) halfLife k <-- A.pow (valueOf 0.5) =<<- A.fdiv (valueOf 1) halfLife+ A.pow (A.fromRational' 0.5) =<<+ A.fdiv (A.fromInteger' 1) halfLife current <-- Vector.iterate (A.mul k) (valueOf 1)+ Serial.iterate (A.mul k) (A.fromInteger' 1) return $ ParameterPacked feedback current {- Value.flatten $ parameterPackedPlain $@@ -296,29 +289,31 @@ -} withSizePlain ::- (n -> param (Vector n a)) ->- param (Vector n a)+ (n -> param (Serial.Plain n a)) ->+ param (Serial.Plain n a) withSizePlain f = f undefined parameterPackedPlain :: (Trans.C a,- TypeNum.Pos n) =>- a -> ParameterPacked (Vector n a)+ TypeNum.PositiveT n) =>+ a -> ParameterPacked (Serial.Plain n a) parameterPackedPlain halfLife = withSizePlain $ \n -> ParameterPacked- (Serial.replicate (0.5 ** (fromIntegral (TypeNum.toInt n) / halfLife)))- (LLVM.vector $ iterate (0.5 ** recip halfLife *) one)+ (Serial.replicate (0.5 ** (fromInteger (TypeNum.fromIntegerT n) / halfLife)))+ (Serial.fromList $ iterate (0.5 ** recip halfLife *) one) causalPackedP ::- (Memory.FirstClass a am, IsSized a as, IsSized am ams, SoV.IntegerConstant a,- Storable a, Class.MakeValueTuple a (Value a),- IsArithmetic a, TypeNum.Pos n,- IsPrimitive a, TypeNum.Mul n as vs, TypeNum.Pos vs,- IsPrimitive am, TypeNum.Mul n ams vms, TypeNum.Pos vms) =>+ (IsArithmetic a, SoV.IntegerConstant a,+ Storable a, MakeValueTuple a, ValueTuple a ~ (Value a),+ Memory.FirstClass a, Memory.Stored a ~ am, IsSized a, IsSized am,+ IsPrimitive a, IsPrimitive am,+ TypeNum.PositiveT (n :*: SizeOf a),+ TypeNum.PositiveT (n :*: SizeOf am),+ TypeNum.PositiveT n) => Param.T p a ->- CausalP.T p (ParameterPacked (Value (Vector n a))) (Value (Vector n a))+ CausalP.T p (ParameterPacked (Serial.Value n a)) (Serial.Value n a) causalPackedP initial = CausalP.loop (Serial.replicate ^<< initial)
− src/Synthesizer/LLVM/LAC2011.hs
@@ -1,328 +0,0 @@-{-# LANGUAGE NoImplicitPrelude #-}-{-# OPTIONS_GHC -fno-warn-unused-imports #-}-module Synthesizer.LLVM.LAC2011 where--import qualified Synthesizer.LLVM.Filter.ComplexFirstOrderPacked as BandPass-import qualified Synthesizer.LLVM.Filter.Allpass as Allpass-import qualified Synthesizer.LLVM.Filter.Butterworth as Butterworth-import qualified Synthesizer.LLVM.Filter.Chebyshev as Chebyshev-import qualified Synthesizer.LLVM.Filter.FirstOrder as Filt1-import qualified Synthesizer.LLVM.Filter.SecondOrder as Filt2-import qualified Synthesizer.LLVM.Filter.SecondOrderPacked as Filt2P-import qualified Synthesizer.LLVM.Filter.Moog as Moog-import qualified Synthesizer.LLVM.Filter.Universal as UniFilter-import qualified Synthesizer.LLVM.CausalParameterized.Controlled as CtrlP-import qualified Synthesizer.LLVM.CausalParameterized.ControlledPacked as CtrlPS-import qualified Synthesizer.LLVM.CausalParameterized.ProcessPacked as CausalPS-import qualified Synthesizer.LLVM.CausalParameterized.Process as CausalP-import qualified Synthesizer.LLVM.Causal.Process as Causal-import qualified Synthesizer.LLVM.Simple.Signal as Gen-import qualified Synthesizer.LLVM.Storable.Signal as SigStL-import qualified Synthesizer.LLVM.Frame as Frame-import qualified Synthesizer.LLVM.Wave as Wave-import qualified Synthesizer.LLVM.Parameter as Param--import qualified LLVM.Extra.ScalarOrVector as SoV-import qualified LLVM.Extra.Memory as Memory-import qualified LLVM.Extra.Arithmetic as A-import qualified LLVM.Extra.Class as C-import LLVM.Core (Value, value, valueOf, Vector, constVector, constOf, )-import LLVM.Util.Arithmetic () -- Floating instance for TValue-import qualified LLVM.Core as LLVM-import Data.TypeLevel.Num (D4, D8, D16, d0, d1, d2, d3, d4, d5, d6, d7, d8, )-import qualified Data.TypeLevel.Num as TypeNum--import qualified Synthesizer.LLVM.Parameterized.SignalPacked as GenPS-import qualified Synthesizer.LLVM.Parameterized.Signal as GenP-import Synthesizer.LLVM.CausalParameterized.Process (($<), ($*), ($*#), )-import Synthesizer.LLVM.Parameterized.Signal (($#), )--import qualified Synthesizer.Plain.Filter.Recursive as FiltR-import qualified Synthesizer.Plain.Filter.Recursive.FirstOrder as Filt1Core-import qualified Synthesizer.Plain.Filter.Recursive.SecondOrder as Filt2Core--import Control.Arrow (Arrow, arr, (&&&), (^<<), )-import Control.Category ((<<<), (.), id, )-import Control.Monad ((<=<), )-import Control.Applicative (liftA2, pure, )-import Data.Traversable (traverse, )--import Foreign.Storable (Storable, )-import qualified Data.StorableVector.Lazy as SVL-import qualified Data.StorableVector as SV--import qualified Data.EventList.Relative.TimeBody as EventList-import qualified Data.EventList.Relative.BodyTime as EventListBT-import qualified Data.EventList.Relative.MixedTime as EventListMT-import qualified Data.EventList.Relative.TimeMixed as EventListTM-import qualified Numeric.NonNegative.Wrapper as NonNeg--import qualified Synthesizer.LLVM.Frame.Stereo as Stereo--import qualified Sound.Sox.Option.Format as SoxOption-import qualified Sound.Sox.Frame as SoxFrame-import qualified Sound.Sox.Play as SoxPlay--import qualified Sound.ALSA.PCM as ALSA-import qualified Synthesizer.Storable.ALSA.Play as Play--import Data.Word (Word32, )--- import qualified Data.Function.HT as F-import Data.List (genericLength, )-import System.Random (randomRs, mkStdGen, )--import qualified System.IO as IO--- import System.Exit (ExitCode, )--import qualified Algebra.Field as Field-import qualified Algebra.Ring as Ring-import qualified Algebra.Additive as Additive--import NumericPrelude.Numeric-import NumericPrelude.Base hiding (fst, snd, id, (.), )-import qualified NumericPrelude.Base as P---asMono :: vector Float -> vector Float-asMono = id--asStereo :: vector (Stereo.T Float) -> vector (Stereo.T Float)-asStereo = id--asMonoPacked :: vector (LLVM.Vector D4 Float) -> vector (LLVM.Vector D4 Float)-asMonoPacked = id--asMonoPacked16 :: vector (LLVM.Vector D16 Float) -> vector (LLVM.Vector D16 Float)-asMonoPacked16 = id--asWord32 :: vector Word32 -> vector Word32-asWord32 = id--asWord32Packed :: vector (LLVM.Vector D4 Word32) -> vector (LLVM.Vector D4 Word32)-asWord32Packed = id---playStereo :: Gen.T (Stereo.T (Value Float)) -> IO ()-playStereo =- playStereoStream .- Gen.renderChunky (SVL.chunkSize 100000)--playStereoStream :: SVL.Vector (Stereo.T Float) -> IO ()-playStereoStream = playStreamSox--playMono :: Gen.T (Value Float) -> IO ()-playMono =- playMonoStream .- Gen.renderChunky (SVL.chunkSize 100000)--playMonoParam :: GenP.T () (Value Float) -> IO ()-playMonoParam =- playMonoStream .- ($ ()) .- ($ SVL.chunkSize 100000) <=<- GenP.runChunky--playMonoPacked :: GenP.T () (Value (Vector D4 Float)) -> IO ()-playMonoPacked =- playMonoStream .- SigStL.unpack .- ($ ()) .- ($ SVL.chunkSize 100000) <=<- GenP.runChunky--playMonoStream :: SVL.Vector Float -> IO ()-playMonoStream = playStreamSox---{--play ::- (C.MakeValueTuple y a, Memory.C a struct) =>- Gen.T a -> IO ()-play =- playStreamSox .- Gen.renderChunky (SVL.chunkSize 100000)--}--playStreamALSA ::- (Additive.C y, ALSA.SampleFmt y) =>- SVL.Vector y -> IO ()-playStreamALSA =- Play.auto (Play.makeSink Play.defaultDevice (0.05::Double) sampleRate)---- reacts faster to CTRL-C-playStreamSox ::- (Storable y, SoxFrame.C y) =>- SVL.Vector y -> IO ()-playStreamSox =- fmap (const ()) .- SoxPlay.simple SVL.hPut SoxOption.none 44100---sampleRate :: Ring.C a => a-sampleRate = 44100--intSecond :: Ring.C a => Float -> a-intSecond t = fromInteger $ round $ t * sampleRate--second :: Field.C a => a -> a-second t = t * sampleRate--hertz :: Field.C a => a -> a-hertz f = f / sampleRate--{--second :: Float -> Param.T p Float-second t = return (t * sampleRate)--hertz :: Float -> Param.T p Float-hertz f = return (f / sampleRate)--}--sine :: IO ()-sine =- playMono (0.99 * Gen.osci Wave.sine 0 (hertz 440))--ping :: IO ()-ping =- playMono (Gen.exponential2 (second 1) 1 * Gen.osci Wave.triangle 0 (hertz 440))--tremolo :: IO ()-tremolo =- playMono (Gen.osci Wave.sine 0 (hertz 0.3) * Gen.osci Wave.triangle 0 (hertz 440))---stereo :: IO ()-stereo =- playStereo (liftA2 Stereo.cons (Gen.osci Wave.triangle 0 (hertz 439)) (Gen.osci Wave.triangle 0 (hertz 441)))--stereoFancy :: IO ()-stereoFancy =- playStereo (traverse (Gen.osci Wave.triangle 0 . hertz) (Stereo.cons 439 441))---fst :: Arrow arrow => arrow (a,b) a-fst = arr P.fst--snd :: Arrow arrow => arrow (a,b) b-snd = arr P.snd---pingParam :: IO (Float -> SVL.Vector Float)-pingParam =- fmap ($ SVL.chunkSize 1024) $- GenP.runChunky $- GenP.exponential2 (second 0.3) 1 * GenP.osciSimple Wave.triangle 0 id--playPingParam :: IO ()-playPingParam = do- png <- pingParam- playMonoStream (SVL.take (intSecond 1) $ png (hertz 880))--melody :: IO (SVL.Vector Float)-melody = do- png <- pingParam- return $ SVL.concat $ map (SVL.take (intSecond 0.2) . png . hertz) $ cycle [440, 550, 660, 880]--playMelody :: IO ()-playMelody = do- mel <- melody- playMonoStream mel--pingParam2 :: IO ((Float, Float) -> SVL.Vector Float)-pingParam2 =- fmap ($ SVL.chunkSize 1024) $- GenP.runChunky $- GenP.exponential2 (second 0.3) fst * GenP.osciSimple Wave.triangle 0 snd--playMelody2 :: IO ()-playMelody2 = do- png <- pingParam2- playMonoStream $ SVL.concat $ map (SVL.take (intSecond 0.2) . png) $ zip (map sin $ [0,0.1..]) (cycle $ map hertz [440, 550, 660, 880])---retard :: GenP.T p (Value Float) -> GenP.T p (Value Float)-retard xs =- CausalP.frequencyModulationLinear xs .- CausalP.mapSimple (A.fdiv (LLVM.valueOf 1)) $*- GenP.rampCore (1 / second 10) 1--playRetarded :: IO ()-playRetarded = do- mel <- melody- playMonoParam $ retard $ GenP.fromStorableVectorLazy $ pure $ mel----pingGen :: GenP.T p (Value Float)-pingGen =- GenP.exponential2 (second 0.5) 0.7 *- GenP.osciSimple Wave.triangle 0 (hertz 440)--zerop :: Param.T p Float-zerop = pure zero--delayp :: Param.T p Int -> CausalP.T p (Value Float) (Value Float)-delayp = CausalP.delay zerop--delay :: IO ()-delay =- playMonoParam $- pingGen + 0.7 * (delayp (intSecond 0.5) $* pingGen)--delayArrow :: IO ()-delayArrow =- playMonoParam- ((id + 0.7 * delayp (intSecond 0.5)) $* pingGen)--comb :: IO ()-comb =- playMonoParam $- (CausalP.loop zerop- (id &&& 0.7 * delayp (intSecond 0.5)- <<< CausalP.mix) $*- pingGen)---lfoSine ::- Param.T p Float ->- GenP.T p (Moog.Parameter D8 (Value Float))-lfoSine reduct =- CausalP.mapSimple (Moog.parameter d8 (valueOf (30::Float))) .- CausalP.mapExponential 2 (hertz 700) $*- GenP.osciSimple Wave.sine 0 (reduct * hertz 0.1)--filterSweep :: IO ()-filterSweep =- playMonoParam $- (0.2 * CtrlP.processCtrlRate 128 lfoSine- $* GenP.noise 0 0.3)---pingPacked :: IO ()-pingPacked =- playMonoPacked (GenPS.exponential2 (second 1) 1 * GenPS.osciSimple Wave.triangle 0 (hertz 440))----{--Module can be loaded into GHCi only when synthesizer-llvm was installed with-$ cabal install --enable-shared--In contrast to that, you have to install with-$ cabal install -fbuildTests -fbuildExamples --enable-shared --disable-library-profiling --ghc-option=-dynamic-for build the executables.-But then GHCi complains:--$ ghci-GHCi, version 6.12.3: http://www.haskell.org/ghc/ :? for help-Loading package ghc-prim ... linking ... done.-Loading package integer-gmp ... linking ... done.-Loading package base ... linking ... done.-Loading package ffi-1.0 ... linking ... done.-[1 of 1] Compiling Main ( src/Synthesizer/LLVM/Test.hs, interpreted )--src/Synthesizer/LLVM/Test.hs:4:0:- Bad interface file: /home/thielema/.cabal/lib/synthesizer-llvm-0.3/ghc-6.12.3/Synthesizer/LLVM/Filter/ComplexFirstOrderPacked.hi- mismatched interface file ways (wanted "", got "dyn")-Failed, modules loaded: none.--}
− src/Synthesizer/LLVM/LNdW2011.hs
@@ -1,543 +0,0 @@-{-# LANGUAGE NoImplicitPrelude #-}-{-# OPTIONS_GHC -fno-warn-unused-imports #-}-module Synthesizer.LLVM.LNdW2011 where--import qualified Synthesizer.LLVM.Plug.Input as PIn-import qualified Synthesizer.LLVM.Plug.Output as POut-import qualified Synthesizer.PiecewiseConstant.ALSA.MIDIControllerSet as PCS-import qualified Synthesizer.CausalIO.ALSA.MIDIControllerSelection as MCS-import qualified Synthesizer.CausalIO.ALSA.Process as PALSA-import qualified Synthesizer.CausalIO.Process as PIO-import qualified Synthesizer.MIDIValue as MV-import qualified Synthesizer.Zip as Zip-import Synthesizer.EventList.ALSA.MIDI (ClientName(ClientName))--import qualified Sound.MIDI.Controller as Ctrl-import qualified Sound.MIDI.Message.Channel as ChannelMsg--import qualified Synthesizer.LLVM.Filter.ComplexFirstOrderPacked as BandPass-import qualified Synthesizer.LLVM.Filter.Allpass as Allpass-import qualified Synthesizer.LLVM.Filter.Butterworth as Butterworth-import qualified Synthesizer.LLVM.Filter.Chebyshev as Chebyshev-import qualified Synthesizer.LLVM.Filter.FirstOrder as Filt1-import qualified Synthesizer.LLVM.Filter.SecondOrder as Filt2-import qualified Synthesizer.LLVM.Filter.SecondOrderPacked as Filt2P-import qualified Synthesizer.LLVM.Filter.Moog as Moog-import qualified Synthesizer.LLVM.Filter.Universal as UniFilter-import qualified Synthesizer.LLVM.CausalParameterized.Controlled as CtrlP-import qualified Synthesizer.LLVM.CausalParameterized.ControlledPacked as CtrlPS-import qualified Synthesizer.LLVM.CausalParameterized.ProcessPacked as CausalPS-import qualified Synthesizer.LLVM.CausalParameterized.Process as CausalP-import qualified Synthesizer.LLVM.Causal.Process as Causal-import qualified Synthesizer.LLVM.Simple.Signal as Gen-import qualified Synthesizer.LLVM.Simple.Value as Value-import qualified Synthesizer.LLVM.Storable.Signal as SigStL-import qualified Synthesizer.LLVM.Frame as Frame-import qualified Synthesizer.LLVM.Wave as Wave-import qualified Synthesizer.LLVM.Parameter as Param--import qualified LLVM.Extra.ScalarOrVector as SoV-import qualified LLVM.Extra.Memory as Memory-import qualified LLVM.Extra.Arithmetic as A-import qualified LLVM.Extra.Class as C-import LLVM.Core (Value, value, valueOf, constVector, constOf, )-import LLVM.Util.Arithmetic () -- Floating instance for TValue-import qualified LLVM.Core as LLVM-import Data.TypeLevel.Num (D4, D8, D16, d0, d1, d2, d3, d4, d5, d6, d7, d8, )-import qualified Data.TypeLevel.Num as TypeNum--import qualified Synthesizer.LLVM.Parameterized.SignalPacked as GenPS-import qualified Synthesizer.LLVM.Parameterized.Signal as GenP-import Synthesizer.LLVM.CausalParameterized.Process (($<), ($*), ($*#), ($<#), )-import Synthesizer.LLVM.Parameterized.Signal (($#), )--import qualified Synthesizer.Plain.Filter.Recursive as FiltR-import qualified Synthesizer.Plain.Filter.Recursive.FirstOrder as Filt1Core-import qualified Synthesizer.Plain.Filter.Recursive.SecondOrder as Filt2Core--import qualified Synthesizer.Causal.Spatial as Spatial--import qualified Control.Arrow as Arr-import Control.Arrow (Arrow, arr, (&&&), (^<<), )-import Control.Category ((<<<), (.), id, (>>>), )-import Control.Monad ((<=<), )-import Control.Applicative (liftA2, pure, )-import Data.Traversable (traverse, )--import Foreign.Storable (Storable, )-import qualified Data.StorableVector.Lazy as SVL-import qualified Data.StorableVector as SV--import qualified Data.EventList.Relative.TimeBody as EventList-import qualified Data.EventList.Relative.BodyTime as EventListBT-import qualified Data.EventList.Relative.MixedTime as EventListMT-import qualified Data.EventList.Relative.TimeMixed as EventListTM-import qualified Data.EventList.Relative.TimeTime as EventListTT-import qualified Numeric.NonNegative.Wrapper as NonNegW-import qualified Numeric.NonNegative.Class as NonNeg--import qualified Control.Monad.Trans.State as State--import qualified Synthesizer.LLVM.Frame.Stereo as Stereo-import qualified Synthesizer.LLVM.Frame.StereoInterleaved as StereoInt--import qualified Sound.Sox.Option.Format as SoxOption-import qualified Sound.Sox.Frame as SoxFrame-import qualified Sound.Sox.Play as SoxPlay--import qualified Sound.ALSA.PCM as ALSA-import qualified Synthesizer.Storable.ALSA.Play as Play--import Data.Word (Word32, )--- import qualified Data.Function.HT as F-import Data.List (genericLength, )-import System.Random (randomRs, mkStdGen, )--import qualified System.IO as IO--- import System.Exit (ExitCode, )--import qualified Algebra.NormedSpace.Euclidean as NormedEuc-import qualified Algebra.Field as Field-import qualified Algebra.Ring as Ring-import qualified Algebra.Additive as Additive-import qualified Algebra.IntegralDomain as Integral--import NumericPrelude.Numeric-import NumericPrelude.Base hiding (fst, snd, id, (.), )-import qualified NumericPrelude.Base as P---asMono :: vector Float -> vector Float-asMono = id--asStereo :: vector (Stereo.T Float) -> vector (Stereo.T Float)-asStereo = id--asMonoPacked :: vector Vector -> vector Vector-asMonoPacked = id--asMonoPacked16 :: vector (LLVM.Vector D16 Float) -> vector (LLVM.Vector D16 Float)-asMonoPacked16 = id--asWord32 :: vector Word32 -> vector Word32-asWord32 = id--asWord32Packed :: vector (LLVM.Vector D4 Word32) -> vector (LLVM.Vector D4 Word32)-asWord32Packed = id---playStereo :: Gen.T (Stereo.T (Value Float)) -> IO ()-playStereo =- playStereoStream .- Gen.renderChunky (SVL.chunkSize 100000)--playStereoStream :: SVL.Vector (Stereo.T Float) -> IO ()-playStereoStream = playStreamSox--playMono :: Gen.T (Value Float) -> IO ()-playMono =- playMonoStream .- Gen.renderChunky (SVL.chunkSize 100000)--playMonoParam :: GenP.T () (Value Float) -> IO ()-playMonoParam =- playMonoStream .- ($ ()) .- ($ SVL.chunkSize 100000) <=<- GenP.runChunky--playMonoPacked :: GenP.T () (Value Vector) -> IO ()-playMonoPacked =- playMonoStream .- SigStL.unpack .- ($ ()) .- ($ SVL.chunkSize 100000) <=<- GenP.runChunky--playMonoStream :: SVL.Vector Float -> IO ()-playMonoStream = playStreamSox---playStreamALSA ::- (Additive.C y, ALSA.SampleFmt y) =>- SVL.Vector y -> IO ()-playStreamALSA =- Play.auto (Play.makeSink Play.defaultDevice (0.05::Double) sampleRate)---- reacts faster to CTRL-C-playStreamSox ::- (Storable y, SoxFrame.C y) =>- SVL.Vector y -> IO ()-playStreamSox =- fmap (const ()) .- SoxPlay.simple SVL.hPut SoxOption.none 44100---sampleRate :: Ring.C a => a-sampleRate = 44100--type Vector = LLVM.Vector VectorSize Float-type VectorSize = TypeNum.D4--vectorSize :: Int-vectorSize = TypeNum.toInt (undefined :: VectorSize)--vectorRate :: Field.C a => a-vectorRate = sampleRate / fromIntegral vectorSize----intSecond :: Ring.C a => Float -> a-intSecond t = fromInteger $ round $ t * sampleRate--second :: Field.C a => a -> a-second t = t * sampleRate--hertz :: Field.C a => a -> a-hertz f = f / sampleRate----fst :: Arrow arrow => arrow (a,b) a-fst = arr P.fst--snd :: Arrow arrow => arrow (a,b) b-snd = arr P.snd---playFromEvents ::- (ALSA.SampleFmt a, Additive.C a) =>- Double ->- Double ->- PIO.T PALSA.Events (SV.Vector a) ->- IO ()-playFromEvents latency period =- PALSA.playFromEvents- Play.defaultDevice (ClientName "Haskell-LLVM-demo")- latency period sampleRate---modulation :: IO ()-modulation = do- proc <-- CausalP.processIO- (0.95 * (CausalP.osciSimple Wave.approxSine4 $< 0))- playFromEvents 0.01 (0.015::Double)- ((proc () :: PIO.T (EventListBT.T NonNegW.Int Float) (SV.Vector Float))- .- PALSA.controllerExponential- (ChannelMsg.toChannel 0)- Ctrl.modulation- (hertz 500, hertz 2000) (hertz 1000))---vectorBlockSize :: Double-vectorBlockSize = fromIntegral $ 150*vectorSize--subsample :: (Integral.C t) => t -> t -> State.State t t-subsample step t =- State.state $ \r -> divMod (r+t) step-{-- do modify (t+)- (q,r) <- gets (flip divMod step)- put r- return q--}--subsampleBT :: EventListBT.T NonNegW.Int a -> EventListBT.T NonNegW.Int a-subsampleBT =- flip State.evalState NonNeg.zero .- EventListBT.mapTimeM (subsample (NonNegW.fromNumberMsg "vectorSize" vectorSize))--modulationPacked :: IO ()-modulationPacked = do- proc <-- CausalP.processIO- (0.95 * (CausalPS.osciSimple Wave.approxSine4 $< 0)- .- CausalP.mapSimple SoV.replicate)- playFromEvents 0.01 (vectorBlockSize/sampleRate)- (arr SigStL.unpackStrict- .- (proc () :: PIO.T (EventListBT.T NonNegW.Int Float) (SV.Vector Vector))- .- arr subsampleBT- .- PALSA.controllerExponential- (ChannelMsg.toChannel 0)- Ctrl.modulation- (hertz 500, hertz 2000) (hertz 1000))---bubbles :: IO ()-bubbles = do- proc <-- CausalP.processIO- (0.95 * (CausalP.osciSimple Wave.sine $< 0)- .- (fst.fst * (1 + snd.fst * snd))- .- Arr.second (CausalP.osciSimple Wave.saw $< 0))- playFromEvents 0.01 (0.015::Double)- ((proc () ::- PIO.T- (Zip.T- (Zip.T- (EventListBT.T NonNegW.Int Float)- (EventListBT.T NonNegW.Int Float))- (EventListBT.T NonNegW.Int Float))- (SV.Vector Float))- .- PIO.zip- (PIO.zip- (PALSA.controllerExponential- (ChannelMsg.toChannel 0)- Ctrl.modulation- (hertz 500, hertz 2000) (hertz 1000))- (PALSA.controllerLinear- (ChannelMsg.toChannel 0)- Ctrl.timbre- (-1, 1) (-0.1)))- (PALSA.controllerExponential- (ChannelMsg.toChannel 0)- Ctrl.soundVariation- (hertz 1, hertz 10) (hertz 1)))--bubblesSet :: IO ()-bubblesSet = do- proc <-- CausalP.processIOCore- (PIn.controllerSet d6)- (CausalP.arrayElement d0 *- (CausalP.osciSimple Wave.sine $< 0)- .- (CausalP.arrayElement d1- *- (1 - CausalP.arrayElement d2 *- (CausalP.osciSimple Wave.saw $< 0) .- CausalP.arrayElement d3)- *- (1 - CausalP.arrayElement d4 *- (CausalP.osciSimple Wave.saw $< 0) .- CausalP.arrayElement d5)))- POut.storableVector- playFromEvents 0.01 (0.015::Double)- ((proc () :: PIO.T (PCS.T Int Float) (SV.Vector Float))- .- MCS.filter [- MCS.controllerExponential Ctrl.volume (0.001, 0.99) 0.5,- MCS.controllerExponential Ctrl.modulation (hertz 500, hertz 2000) (hertz 1000),- MCS.controllerLinear Ctrl.soundVariation (-1, 1) 0.7,- MCS.controllerExponential Ctrl.timbre (hertz 0.2, hertz 5) (hertz 1),- MCS.controllerLinear Ctrl.soundController5 (-1, 1) 0.5,- MCS.controllerExponential Ctrl.soundController7 (hertz 2, hertz 20) (hertz 10)]- .- MCS.fromChannel (ChannelMsg.toChannel 0))---subsamplePCS :: PCS.T key a -> PCS.T key a-subsamplePCS =- PCS.mapStream $- flip State.evalState NonNeg.zero .- EventListTT.mapTimeM (subsample (NonNegW.fromNumberMsg "vectorSize" $ fromIntegral vectorSize))--bubblesPacked :: IO ()-bubblesPacked = do- proc <-- CausalP.processIOCore- (PIn.controllerSet d6)- (CausalPS.arrayElement d0 *- (CausalPS.osciSimple Wave.approxSine4 $< 0)- .- (CausalPS.arrayElement d1- *- (1 - CausalPS.arrayElement d2 *- (CausalPS.osciSimple Wave.saw $< 0) .- CausalPS.arrayElement d3)- *- (1 - CausalPS.arrayElement d4 *- (CausalPS.osciSimple Wave.saw $< 0) .- CausalPS.arrayElement d5)))- POut.storableVector- playFromEvents 0.01 (vectorBlockSize/sampleRate)- (arr SigStL.unpackStrict- .- (proc () :: PIO.T (PCS.T Int Float) (SV.Vector Vector))- .- arr subsamplePCS- .- MCS.filter [- MCS.controllerExponential Ctrl.volume (0.001, 0.99) 0.5,- MCS.controllerExponential Ctrl.modulation (hertz 500, hertz 2000) (hertz 1000),- MCS.controllerLinear Ctrl.soundVariation (-1, 1) 0.7,- MCS.controllerExponential Ctrl.timbre (hertz 0.2, hertz 5) (hertz 1),- MCS.controllerLinear Ctrl.soundController5 (-1, 1) 0.5,- MCS.controllerExponential Ctrl.soundController7 (hertz 2, hertz 20) (hertz 10)]- .- MCS.fromChannel (ChannelMsg.toChannel 0))---moveAround2dFloat ::- Float -> Float -> (Float, Float) ->- CausalP.T p- (Value Float, Value Float)- (Value Float, Value Float)-moveAround2dFloat att sonicDelay (earX,earY) =- CausalP.mapSimple- (Value.flatten .- Spatial.moveAround- (Value.constant att) (Value.constant sonicDelay)- (Value.constant earX, Value.constant earY) .- Value.unfold)--moveAround2d ::- (Ring.C a, LLVM.IsConst a, SoV.Replicate a v, LLVM.IsFloating v) =>- a -> a -> (a, a) ->- CausalP.T p- (Value v, Value v)- (Value v, Value v)-moveAround2d att sonicDelay (earX,earY) =--- (\dist -> (sonicDelay*dist, 1/(att+dist)^2)) . Euc.norm . subtract ear- CausalP.mapSimple $ \(objX,objY) -> do- dist <-- euclideanNorm2d =<< liftA2 (,)- (A.sub objX (SoV.replicateOf earX))- (A.sub objY (SoV.replicateOf earY))- delay <- A.mul dist (SoV.replicateOf sonicDelay)- volume <- A.fdiv (SoV.replicateOf Ring.one)- =<< A.square =<< A.add dist (SoV.replicateOf att)- return (delay, volume)--euclideanNorm2d ::- (LLVM.IsFloating a) =>- (Value a, Value a) ->- LLVM.CodeGenFunction r (Value a)-euclideanNorm2d (x,y) = do- x2 <- A.square x- y2 <- A.square y- A.sqrt =<< A.add x2 y2--flyChannel ::- (Float, Float) ->- CausalP.T p (Value Float, Value Float) (Value Float)-flyChannel ear =- ((moveAround2d 1 0.1 ear >>> Arr.first (negate id))- &&&- (250/sampleRate +- 2 * (CausalP.mapSimple euclideanNorm2d <<< (CausalP.differentiate $# (0::Float, 0::Float)))))- >>>- arr (\((phase,volume), speed) -> (volume, (phase,speed)))- >>>- Arr.second (CausalP.osciSimple Wave.saw)- >>>- CausalP.envelope- >>>- CausalP.amplify 10--fly :: IO ()-fly = do- let slow =- Filt1.lowpassCausalP $<#- Filt1Core.parameter (1/sampleRate::Float)- let fast =- Filt1.lowpassCausalP $<#- Filt1Core.parameter (30/sampleRate::Float)- proc <-- CausalP.processIOCore- (PIn.controllerSet d4)- ((CausalP.arrayElement d0 &&&- (liftA2 (,)- ((CausalP.arrayElement d2 >>> slow)- +- CausalP.arrayElement d1 *- (CausalP.fromSignal (GenP.noise 366210 0.3) >>> fast >>> fast))- ((CausalP.arrayElement d3 >>> slow)- +- CausalP.arrayElement d1 *- (CausalP.fromSignal (GenP.noise 234298 0.3) >>> fast >>> fast))- >>>- liftA2 Stereo.cons- (flyChannel (-1,0))- (flyChannel ( 1,0))))- >>>- CausalP.envelopeStereo)- POut.storableVector- playFromEvents 0.01 (0.015::Double)- ((proc () :: PIO.T (PCS.T Int Float) (SV.Vector (Stereo.T Float)))- .- MCS.filter [- MCS.controllerExponential Ctrl.volume (0.001, 0.99) 0.2,- MCS.controllerLinear Ctrl.modulation (0, 5) 2,-{-- MCS.pitchBend (hertz 500, hertz 2000) (hertz 1000),--}- MCS.controllerLinear Ctrl.vectorX (-10, 10) 0,- MCS.controllerLinear Ctrl.vectorY (-10, 10) 0]- .- MCS.fromChannel (ChannelMsg.toChannel 0))---flyChannelPacked ::- (Float, Float) ->- CausalP.T p (Value Vector, Value Vector) (Value Vector)-flyChannelPacked ear =- ((moveAround2d 1 0.1 ear >>> Arr.first (negate id))- &&&- (250/sampleRate +- 2 * (CausalP.mapSimple euclideanNorm2d <<< (CausalPS.differentiate $# (0::Float, 0::Float)))))- >>>- arr (\((phase,volume), speed) -> (volume, (phase,speed)))- >>>- Arr.second (CausalPS.osciSimple Wave.saw)- >>>- CausalP.envelope- >>>- CausalPS.amplify 10--flyPacked :: IO ()-flyPacked = do- let slow =- Filt1.lowpassCausalPackedP $<#- Filt1Core.parameter (1/sampleRate::Float)- let fast =- Filt1.lowpassCausalPackedP $<#- Filt1Core.parameter (30/sampleRate::Float)- proc <-- CausalP.processIOCore- (PIn.controllerSet d4)- ((CausalPS.arrayElement d0 &&&- (liftA2 (,)- ((CausalPS.arrayElement d2 >>> slow)- +- CausalPS.arrayElement d1 *- (CausalP.fromSignal (GenPS.noise 366210 0.3) >>> fast >>> fast))- ((CausalPS.arrayElement d3 >>> slow)- +- CausalPS.arrayElement d1 *- (CausalP.fromSignal (GenPS.noise 234298 0.3) >>> fast >>> fast))- >>>- liftA2 Stereo.cons- (flyChannelPacked (-1,0))- (flyChannelPacked ( 1,0))))- >>>- CausalP.envelopeStereo- >>>- CausalP.mapSimple StereoInt.interleave)- POut.storableVector- playFromEvents 0.01 (vectorBlockSize/sampleRate)- (arr SigStL.unpackStereoStrict- .- (proc () :: PIO.T (PCS.T Int Float) (SV.Vector (StereoInt.T VectorSize Float)))- .- arr subsamplePCS- .- MCS.filter [- MCS.controllerExponential Ctrl.volume (0.001, 0.99) 0.2,- MCS.controllerLinear Ctrl.modulation (0, 5) 2,-{-- MCS.pitchBend (hertz 500, hertz 2000) (hertz 1000),--}- MCS.controllerLinear Ctrl.vectorX (-10, 10) 0,- MCS.controllerLinear Ctrl.vectorY (-10, 10) 0]- .- MCS.fromChannel (ChannelMsg.toChannel 0))
+ src/Synthesizer/LLVM/MIDI.hs view
@@ -0,0 +1,177 @@+{-# LANGUAGE NoImplicitPrelude #-}+{-# LANGUAGE TypeFamilies #-}+{-# LANGUAGE TypeOperators #-}+{-# LANGUAGE FlexibleContexts #-}+{- |+Convert MIDI events of a MIDI controller to a control signal.+-}+module Synthesizer.LLVM.MIDI (+ module Synthesizer.LLVM.MIDI,+ Gen.applyModulation,+ ) where++import qualified Synthesizer.MIDI.Generic as Gen+import qualified Synthesizer.LLVM.MIDI.BendModulation as BM+import qualified Synthesizer.LLVM.Frame.SerialVector as Serial++import Synthesizer.LLVM.CausalParameterized.Process (($>), )+import qualified Synthesizer.LLVM.Parameterized.SignalPacked as SigPS+import qualified Synthesizer.LLVM.CausalParameterized.Process as CausalP+import qualified Synthesizer.LLVM.Parameterized.Signal as SigP+import qualified Synthesizer.LLVM.Parameter as Param+import qualified Synthesizer.LLVM.Wave as Wave++import qualified LLVM.Extra.ScalarOrVector as SoV+import qualified LLVM.Extra.Vector as Vector+import qualified LLVM.Extra.Memory as Memory+import qualified LLVM.Extra.Arithmetic as A+import qualified LLVM.Extra.Class as Class+import qualified LLVM.Core as LLVM+import LLVM.Core (IsSized, SizeOf, )++import qualified Types.Data.Bool as TypeBool+import qualified Types.Data.Num as TypeNum+import Types.Data.Num.Ops ((:*:), )++import Foreign.Storable (Storable, )++import qualified Algebra.RealField as RealField+import qualified Algebra.Additive as Additive++import Control.Arrow (second, (<<<), (<<^), )+import Control.Monad ({- liftM, -} liftM2, )++-- import NumericPrelude.Base+import NumericPrelude.Numeric+import Prelude ()+++{-+{-# INLINE piecewiseConstantInit #-}+piecewiseConstantInit ::+ (Storable y, Class.MakeValueTuple y, Class.ValueTuple y ~ yl,+ Memory.C yl ym, LLVM.IsSized ym ys) =>+ y -> EventListTT.T LazyTime y -> SigP.T p yl+piecewiseConstantInit initial evs =+ SigP.piecewiseConstant $#+ (PC.subdivideInt $+ EventListMT.consBody initial evs)+++{-# INLINE controllerLinear #-}+controllerLinear ::+ (Field.C y, Storable y, Class.MakeValueTuple y, Class.ValueTuple y ~ yl,+ Memory.C yl ym, LLVM.IsSized ym ys) =>+ Channel -> Controller ->+ (y,y) -> y ->+ Filter (SigP.T p yl)+controllerLinear chan ctrl bnd initial =+ liftM (piecewiseConstantInit initial .+ EventListTT.mapBody (MV.controllerLinear bnd)) $+ getControllerEvents chan ctrl+++{-# INLINE controllerExponential #-}+controllerExponential ::+ (Trans.C y, Storable y, Class.MakeValueTuple y, Class.ValueTuple y ~ yl,+ Memory.C yl ym, LLVM.IsSized ym ys) =>+ Channel -> Controller ->+ (y,y) -> y ->+ Filter (SigP.T p yl)+controllerExponential chan ctrl bnd initial =+ liftM (piecewiseConstantInit initial .+ EventListTT.mapBody (MV.controllerExponential bnd)) $+ getControllerEvents chan ctrl+++{- |+@pitchBend channel range center@:+emits frequencies on an exponential scale from+@center/range@ to @center*range@.+-}+{-# INLINE pitchBend #-}+pitchBend ::+ (Trans.C y, Storable y, Class.MakeValueTuple y, Class.ValueTuple y ~ yl,+ Memory.C yl ym, LLVM.IsSized ym ys) =>+ Channel ->+ y -> y ->+ Filter (SigP.T p yl)+pitchBend chan range center =+ liftM (piecewiseConstantInit center .+ EventListTT.mapBody (MV.pitchBend range center)) $+ getSlice (maybePitchBend chan)+-- getPitchBendEvents chan++{-# INLINE channelPressure #-}+channelPressure ::+ (Trans.C y, Storable y, Class.MakeValueTuple y, Class.ValueTuple y ~ yl,+ Memory.C yl ym, LLVM.IsSized ym ys) =>+ Channel ->+ y -> y ->+ Filter (SigP.T p yl)+channelPressure chan maxVal initVal =+ liftM (piecewiseConstantInit initVal .+ EventListTT.mapBody (MV.controllerLinear (0,maxVal))) $+ getSlice (maybeChannelPressure chan)+++{-# INLINE bendWheelPressure #-}+bendWheelPressure ::+ (Ring.C a, LLVM.IsConst a,+ RealField.C y, Trans.C y,+ LLVM.IsConst y, SoV.Fraction y, a ~ SoV.Scalar y, SoV.Replicate y,+ Storable y, Class.MakeValueTuple y (LLVM.Value y), LLVM.IsSized y ys) =>+ Channel ->+ Int -> y -> y -> y ->+ Filter (SigP.T p (LLVM.Value y))+bendWheelPressure chan+ pitchRange speed wheelDepth pressDepth =+ do bend <- pitchBend chan+ (2^?(fromIntegral pitchRange/12) `asTypeOf` speed) 1+ fm <- controllerLinear chan VoiceMsg.modulation (0,wheelDepth) 0+ press <- channelPressure chan pressDepth 0+ return $+ SigP.envelope bend $+ SigP.mapSimple (A.add (LLVM.valueOf 1)) $+ SigP.envelope+ (SigP.mix fm press)+ (SigP.osciSimple Wave.approxSine2 zero $# speed)+-}+++frequencyFromBendModulation ::+ (Additive.C y, Storable y, Class.MakeValueTuple y, Class.ValueTuple y ~ yl,+ A.PseudoRing yl, A.Fraction yl, A.IntegerConstant yl, Memory.C yl) =>+ Param.T p y ->+ CausalP.T p (BM.T yl) yl+frequencyFromBendModulation speed =+ CausalP.envelope+ <<<+ second+ (CausalP.mapSimple (A.add (A.fromInteger' 1)) <<< CausalP.envelope+ $> SigP.osciSimple Wave.approxSine2 zero speed)+ <<^+ (\(BM.Cons b m) -> (b,m))+++frequencyFromBendModulationPacked ::+ (RealField.C a, LLVM.IsConst a, LLVM.IsFloating a,+ Memory.FirstClass a, Memory.Stored a ~ am, IsSized a, IsSized am,+ LLVM.IsPrimitive am,+ Storable a, Class.MakeValueTuple a, Class.ValueTuple a ~ (LLVM.Value a),+ Vector.Real a, SoV.IntegerConstant a,+ TypeNum.PositiveT n, TypeNum.IsPositive n ~ TypeBool.True,+ TypeNum.PositiveT (n :*: SizeOf a),+ TypeNum.PositiveT (n :*: SizeOf am)) =>+ Param.T p a ->+ CausalP.T p (BM.T (LLVM.Value a)) (Serial.Value n a)+frequencyFromBendModulationPacked speed =+ CausalP.envelope+ <<<+ second+ (CausalP.mapSimple (A.add (A.fromInteger' 1)) <<< CausalP.envelope+ $> SigPS.osciSimple Wave.approxSine2 zero speed)+ <<<+ CausalP.mapSimple+ (\(BM.Cons b m) ->+ liftM2 (,) (Serial.upsample b) (Serial.upsample m))
+ src/Synthesizer/LLVM/MIDI/BendModulation.hs view
@@ -0,0 +1,91 @@+{-# LANGUAGE TypeFamilies #-}+{-# OPTIONS_GHC -fno-warn-orphans #-}+{- |+Various LLVM related instances of the BM.T type.+I have setup a separate module since these instances are orphan+and need several language extensions.+-}+module Synthesizer.LLVM.MIDI.BendModulation (+ BM.T(..),+ BM.deflt,+ BM.shift,+ ) where++import qualified Synthesizer.MIDI.Value.BendModulation as BM+import qualified Synthesizer.LLVM.CausalParameterized.Functional as F++import qualified LLVM.Extra.Vector as Vector+import qualified LLVM.Extra.Class as Class+import qualified LLVM.Extra.Memory as Memory+import qualified LLVM.Extra.Control as C+import qualified LLVM.Util.Loop as Loop+import qualified LLVM.Core as LLVM++import Control.Applicative (liftA2, )+import qualified Types.Data.Num as TypeNum+++instance (Class.Zero a) => Class.Zero (BM.T a) where+ zeroTuple = Class.zeroTuplePointed++{-+instance (LLVM.ValueTuple a) => LLVM.ValueTuple (BM.T a) where+ buildTuple f = Class.buildTupleTraversable (LLVM.buildTuple f)++instance LLVM.IsTuple a => LLVM.IsTuple (BM.T a) where+ tupleDesc = Class.tupleDescFoldable+-}++instance (Class.Undefined a) => Class.Undefined (BM.T a) where+ undefTuple = Class.undefTuplePointed++instance (C.Select a) => C.Select (BM.T a) where+ select = C.selectTraversable++{-+instance LLVM.CmpRet a, LLVM.CmpResult a ~ b =>+ LLVM.CmpRet (BM.T a) (BM.T b) where+-}++instance Class.MakeValueTuple h =>+ Class.MakeValueTuple (BM.T h) where+ type ValueTuple (BM.T h) = BM.T (Class.ValueTuple h)+ valueTupleOf = Class.valueTupleOfFunctor+++type Struct a = LLVM.Struct (a, (a, ()))++memory ::+ (Memory.C l) =>+ Memory.Record r (Struct (Memory.Struct l)) (BM.T l)+memory =+ liftA2 BM.Cons+ (Memory.element BM.bend TypeNum.d0)+ (Memory.element BM.depth TypeNum.d1)++instance (Memory.C l) => Memory.C (BM.T l) where+ type Struct (BM.T l) = Struct (Memory.Struct l)+ load = Memory.loadRecord memory+ store = Memory.storeRecord memory+ decompose = Memory.decomposeRecord memory+ compose = Memory.composeRecord memory+++instance (Loop.Phi a) => Loop.Phi (BM.T a) where+ phis = Class.phisTraversable+ addPhis = Class.addPhisFoldable+++instance (Vector.Simple v) => Vector.Simple (BM.T v) where+ type Element (BM.T v) = BM.T (Vector.Element v)+ type Size (BM.T v) = Vector.Size v+ shuffleMatch = Vector.shuffleMatchTraversable+ extract = Vector.extractTraversable++instance (Vector.C v) => Vector.C (BM.T v) where+ insert = Vector.insertTraversable+++type instance F.Arguments f (BM.T a) = f (BM.T a)+instance F.MakeArguments (BM.T a) where+ makeArgs = id
src/Synthesizer/LLVM/Parameter.hs view
@@ -1,4 +1,5 @@ {-# LANGUAGE NoImplicitPrelude #-}+{-# LANGUAGE TypeFamilies #-} module Synthesizer.LLVM.Parameter where import qualified LLVM.Extra.Class as Class@@ -68,7 +69,7 @@ For small loop counts and simple loop bodies the loop might get unrolled. -} value ::- Class.MakeValueTuple tuple value =>+ (Class.MakeValueTuple tuple, Class.ValueTuple tuple ~ value) => T p tuple -> value -> value value (Constant a) _ = Class.valueTupleOf a value (Variable _) v = v
src/Synthesizer/LLVM/Parameterized/Signal.hs view
@@ -1,7 +1,7 @@ {-# LANGUAGE NoImplicitPrelude #-}+{-# LANGUAGE TypeFamilies #-} {-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE ScopedTypeVariables #-}-{-# LANGUAGE ExistentialQuantification #-} {-# LANGUAGE Rank2Types #-} {-# LANGUAGE ForeignFunctionInterface #-} module Synthesizer.LLVM.Parameterized.Signal (@@ -39,16 +39,17 @@ import qualified LLVM.Extra.Arithmetic as A import qualified LLVM.Extra.ScalarOrVector as SoV import LLVM.Extra.Arithmetic (advanceArrayElementPtr, )-import LLVM.Extra.Class (MakeValueTuple, Undefined, undefTuple, )+import LLVM.Extra.Class (MakeValueTuple, ValueTuple, Undefined, undefTuple, ) import LLVM.Core as LLVM import qualified LLVM.Util.Loop as Loop-import qualified Data.TypeLevel.Num as TypeNum+import qualified Types.Data.Num as TypeNum import Control.Monad.HT ((<=<), ) import Control.Monad (liftM2, liftM3, when, ) import Control.Arrow ((^<<), ) import Control.Applicative (liftA2, )+import Control.Functor.HT (void, ) import qualified Algebra.Transcendental as Trans import qualified Algebra.RealField as RealField@@ -63,11 +64,10 @@ import Foreign.Storable (Storable, ) import Foreign.Marshal.Array (advancePtr, ) import qualified Synthesizer.LLVM.Alloc as Alloc-import Foreign.ForeignPtr- (unsafeForeignPtrToPtr, touchForeignPtr, withForeignPtr, )+import Foreign.ForeignPtr (touchForeignPtr, withForeignPtr, ) import Foreign.Ptr (FunPtr, nullPtr, ) import Control.Exception (bracket, )-import System.IO.Unsafe (unsafePerformIO, unsafeInterleaveIO, )+import qualified System.Unsafe as Unsafe import qualified Synthesizer.LLVM.Debug.Storable as DebugSt import qualified Synthesizer.LLVM.Debug.Counter as Counter@@ -86,9 +86,9 @@ mapAccum ::- (Storable pnh, MakeValueTuple pnh pnl, Memory.C pnl pnp, IsSized pnp pns,- Storable psh, MakeValueTuple psh psl, Memory.C psl psp, IsSized psp pss,- Memory.C s struct, IsSized struct sa) =>+ (Storable pnh, MakeValueTuple pnh, ValueTuple pnh ~ pnl, Memory.C pnl,+ Storable psh, MakeValueTuple psh, ValueTuple psh ~ psl, Memory.C psl,+ Memory.C s) => (forall r. pnl -> a -> s -> CodeGenFunction r (b,s)) -> (forall r. psl -> CodeGenFunction r s) -> Param.T p pnh ->@@ -216,11 +216,11 @@ or if the input value differs from the last processed one by a certain amount. -} interpolateConstant ::- (Memory.C a struct, IsSized struct size,+ (Memory.C a, Ring.C b,- IsFloating b, CmpRet b Bool,- Storable b, MakeValueTuple b (Value b), IsConst b,- Memory.FirstClass b bm, IsSized b bsize, IsSized bm bmsize) =>+ IsFloating b, CmpRet b, CmpResult b ~ Bool,+ Storable b, MakeValueTuple b, ValueTuple b ~ (Value b), IsConst b,+ Memory.FirstClass b, IsSized b, IsSized (Memory.Stored b)) => Param.T p b -> T p a -> T p a interpolateConstant k (Cons next start createIOContext deleteIOContext) =@@ -274,14 +274,14 @@ amplify :: (A.PseudoRing al, Storable a,- MakeValueTuple a al, Memory.C al am, IsSized am as) =>+ MakeValueTuple a, ValueTuple a ~ al, Memory.C al) => Param.T p a -> T p al -> T p al amplify = map Frame.amplifyMono amplifyStereo :: (A.PseudoRing al, Storable a,- MakeValueTuple a al, Memory.C al am, IsSized am as) =>+ MakeValueTuple a, ValueTuple a ~ al, Memory.C al) => Param.T p a -> T p (Stereo.T al) -> T p (Stereo.T al) amplifyStereo = map Frame.amplifyStereo@@ -290,8 +290,8 @@ -- * signal generators constant ::- (Storable a, MakeValueTuple a al,- Memory.C al packed, IsSized packed s) =>+ (Storable a, MakeValueTuple a, ValueTuple a ~ al,+ Memory.C al) => Param.T p a -> T p al constant x = simple@@ -302,15 +302,15 @@ exponentialCore ::- (Storable a, MakeValueTuple a al,- Memory.C al am, IsSized am as, A.PseudoRing al) =>+ (Storable a, MakeValueTuple a, ValueTuple a ~ al,+ Memory.C al, A.PseudoRing al) => Param.T p a -> Param.T p a -> T p al exponentialCore = iterate A.mul exponential2 ::- (Trans.C a, Storable a, MakeValueTuple a (Value a),- Memory.FirstClass a am, IsSized a s, IsSized am amsize,+ (Trans.C a, Storable a, MakeValueTuple a, ValueTuple a ~ (Value a),+ Memory.FirstClass a, IsSized a, IsSized (Memory.Stored a), IsArithmetic a, IsConst a) => Param.T p a -> Param.T p a -> T p (Value a) exponential2 halfLife =@@ -318,8 +318,8 @@ exponentialBoundedCore ::- (Storable a, MakeValueTuple a al,- Memory.C al am, IsSized am as, A.PseudoRing al, A.Real al) =>+ (Storable a, MakeValueTuple a, ValueTuple a ~ al,+ Memory.C al, A.PseudoRing al, A.Real al) => Param.T p a -> Param.T p a -> Param.T p a -> T p al exponentialBoundedCore bound decay =@@ -334,8 +334,8 @@ The initial value and the bound value must be positive. -} exponentialBounded2 ::- (Trans.C a, Storable a, MakeValueTuple a (Value a),- Memory.FirstClass a am, IsSized a s, IsSized am amsize,+ (Trans.C a, Storable a, MakeValueTuple a, ValueTuple a ~ (Value a),+ Memory.FirstClass a, IsSized a, IsSized (Memory.Stored a), SoV.Real a, IsConst a) => Param.T p a -> Param.T p a -> Param.T p a -> T p (Value a)@@ -344,19 +344,18 @@ osciCore ::- (Storable t, MakeValueTuple t tl,- Memory.C tl tm, IsSized tm ts, A.Fraction tl) =>+ (Storable t, MakeValueTuple t, ValueTuple t ~ tl,+ Memory.C tl, A.Fraction tl) => Param.T p t -> Param.T p t -> T p tl osciCore phase freq = iterate A.incPhase freq phase osci ::- (Storable t, MakeValueTuple t (Value t),- Storable c, MakeValueTuple c cl,- Memory.FirstClass t tm, IsSized t tsize, IsSized tm tmsize,- Memory.C cl cp, IsSized cp cs,- SoV.Fraction t, IsConst t) =>- (forall r. cl -> Value t -> CodeGenFunction r y) ->+ (Storable t, MakeValueTuple t, ValueTuple t ~ tl,+ Storable c, MakeValueTuple c, ValueTuple c ~ cl,+ Memory.C cl,+ Memory.C tl, A.Fraction tl, A.IntegerConstant tl) =>+ (forall r. cl -> tl -> CodeGenFunction r y) -> Param.T p c -> Param.T p t -> Param.T p t -> T p y osci wave waveParam phase freq =@@ -364,37 +363,32 @@ osciCore phase freq osciSimple ::- (Storable t, MakeValueTuple t (Value t),- Memory.FirstClass t tm, IsSized t tsize, IsSized tm tmsize,- SoV.Fraction t, IsConst t) =>- (forall r. Value t -> CodeGenFunction r y) ->+ (Storable t, MakeValueTuple t, ValueTuple t ~ tl,+ Memory.C tl, A.Fraction tl, A.IntegerConstant tl) =>+ (forall r. tl -> CodeGenFunction r y) -> Param.T p t -> Param.T p t -> T p y osciSimple wave = osci (const wave) (return ()) osciSaw ::- (Ring.C a0, IsConst a0, SoV.Replicate a0 a,- Storable a, MakeValueTuple a (Value a),- Memory.FirstClass a am, IsSized a asize, IsSized am amsize,- SoV.Fraction a, IsPrimitive a, IsConst a) =>- Param.T p a -> Param.T p a -> T p (Value a)+ (Storable a, MakeValueTuple a, ValueTuple a ~ al,+ Memory.C al, A.PseudoRing al, A.Fraction al, A.IntegerConstant al) =>+ Param.T p a -> Param.T p a -> T p al osciSaw = osciSimple Wave.saw rampCore ::- (Storable a, MakeValueTuple a (Value a),- Memory.FirstClass a am, IsSized a asize, IsSized am amsize,- IsArithmetic a, IsConst a) =>- Param.T p a -> Param.T p a -> T p (Value a)+ (Storable a, MakeValueTuple a, ValueTuple a ~ al,+ Memory.C al, A.Additive al, A.IntegerConstant al) =>+ Param.T p a -> Param.T p a -> T p al rampCore = iterate A.add parabolaCore ::- (Storable a, MakeValueTuple a (Value a),- Memory.FirstClass a am, IsSized a asize, IsSized am amsize,- IsArithmetic a, IsConst a) =>- Param.T p a -> Param.T p a -> Param.T p a -> T p (Value a)+ (Storable a, MakeValueTuple a, ValueTuple a ~ al,+ Memory.C al, A.Additive al, A.IntegerConstant al) =>+ Param.T p a -> Param.T p a -> Param.T p a -> T p al parabolaCore d2 d1 start = Causal.apply (Causal.integrate start) $ rampCore d2 d1@@ -403,10 +397,9 @@ rampInf, rampSlope, parabolaFadeInInf, parabolaFadeOutInf ::- (Field.C a, Storable a, MakeValueTuple a (Value a),- Memory.FirstClass a am, IsSized a asize, IsSized am amsize,- IsArithmetic a, IsConst a) =>- Param.T p a -> T p (Value a)+ (Field.C a, Storable a, MakeValueTuple a, ValueTuple a ~ al,+ Memory.C al, A.Additive al, A.IntegerConstant al) =>+ Param.T p a -> T p al rampSlope slope = rampCore slope Additive.zero rampInf dur = rampSlope (recip dur) @@ -439,10 +432,9 @@ ramp, parabolaFadeIn, parabolaFadeOut, parabolaFadeInMap, parabolaFadeOutMap ::- (RealField.C a, Storable a, MakeValueTuple a (Value a),- Memory.FirstClass a am, IsSized a asize, IsSized am amsize,- IsArithmetic a, IsConst a) =>- Param.T p a -> T p (Value a)+ (RealField.C a, Storable a, MakeValueTuple a, ValueTuple a ~ al,+ Memory.C al, A.PseudoRing al, A.IntegerConstant al) =>+ Param.T p a -> T p al ramp dur = Causal.apply (Causal.take (fmap round dur)) $@@ -458,12 +450,12 @@ parabolaFadeInMap dur = -- t*(2-t)- Causal.apply (Causal.mapSimple (\t -> A.mul t =<< A.sub (valueOf 2) t)) $+ Causal.apply (Causal.mapSimple (\t -> A.mul t =<< A.sub (A.fromInteger' 2) t)) $ ramp dur parabolaFadeOutMap dur = -- 1-t^2- Causal.apply (Causal.mapSimple (\t -> A.sub (valueOf 1) =<< A.mul t t)) $+ Causal.apply (Causal.mapSimple (\t -> A.sub (A.fromInteger' 1) =<< A.mul t t)) $ ramp dur @@ -486,9 +478,9 @@ -} noise :: (Algebraic.C a, IsFloating a, IsConst a,- NumberOfElements TypeNum.D1 a,- Memory.C (Value a) as, IsSized as sas,- IsSized a ps, MakeValueTuple a (Value a), Storable a) =>+ NumberOfElements a ~ TypeNum.D1,+ Memory.C (Value a),+ IsSized a, MakeValueTuple a, ValueTuple a ~ (Value a), Storable a) => Param.T p Word32 -> Param.T p a -> T p (Value a)@@ -506,11 +498,11 @@ and thus we use it, since the arguments are below 2^31. -} int31tofp ::- (IsFloating a, LLVM.NumberOfElements TypeNum.D1 a) =>+ (IsFloating a, LLVM.NumberOfElements a ~ TypeNum.D1) => Value Word32 -> CodeGenFunction r (Value a) int31tofp = LLVM.inttofp <=<- (LLVM.bitcastUnify ::+ (LLVM.bitcast :: Value Word32 -> CodeGenFunction r (Value Int32)) noiseCore, noiseCoreAlt ::@@ -528,7 +520,7 @@ -- * conversion from and to storable vectors fromStorableVector ::- (Storable a, MakeValueTuple a value, Memory.C value struct) =>+ (Storable a, MakeValueTuple a, ValueTuple a ~ value, Memory.C value) => Param.T p (SV.Vector a) -> T p value fromStorableVector selectVec =@@ -545,7 +537,7 @@ let (fp,s,l) = SVB.toForeignPtr $ Param.get selectVec p in return (fp, ((),- (Memory.castStorablePtr $ unsafeForeignPtrToPtr fp `advancePtr` s,+ (Memory.castStorablePtr $ Unsafe.foreignPtrToPtr fp `advancePtr` s, fromIntegral l :: Word32)))) -- keep the foreign ptr alive touchForeignPtr@@ -556,7 +548,7 @@ and advances to the next chunk in the sequence. -} fromStorableVectorLazy ::- (Storable a, MakeValueTuple a value, Memory.C value struct) =>+ (Storable a, MakeValueTuple a, ValueTuple a ~ value, Memory.C value) => Param.T p (SVL.Vector a) -> T p value fromStorableVectorLazy sig =@@ -586,7 +578,7 @@ piecewiseConstant ::- (Storable a, MakeValueTuple a value, Memory.C value struct, IsSized struct size) =>+ (Storable a, MakeValueTuple a, ValueTuple a ~ value, Memory.C value) => Param.T p (EventList.T NonNeg.Int a) -> T p value piecewiseConstant =@@ -610,7 +602,7 @@ Exec.Importer (Ptr param -> Word32 -> Ptr a -> IO Word32) run ::- (Storable a, MakeValueTuple a value, Memory.C value struct) =>+ (Storable a, MakeValueTuple a, ValueTuple a ~ value, Memory.C value) => T p value -> IO (Int -> p -> SV.Vector a) run (Cons next start createIOContext deleteIOContext) =@@ -629,7 +621,7 @@ ret (pos :: Value Word32) return $ \len p ->- unsafePerformIO $+ Unsafe.performIO $ bracket (createIOContext p) (deleteIOContext . fst) $ \ (_,params) -> SVB.createAndTrim len $ \ ptr ->@@ -642,9 +634,9 @@ This is not really a function, see 'renderChunky'. -} render ::- (Storable a, MakeValueTuple a value, Memory.C value struct) =>+ (Storable a, MakeValueTuple a, ValueTuple a ~ value, Memory.C value) => T p value -> Int -> p -> SV.Vector a-render gen = unsafePerformIO $ run gen+render gen = Unsafe.performIO $ run gen foreign import ccall safe "dynamic" derefChunkPtr ::@@ -652,13 +644,10 @@ moduleChunky ::- (Memory.C value struct,- Memory.C state stateStruct,- IsSized stateStruct stateSize,- Memory.C startParamValue startParamStruct,- Memory.C nextParamValue nextParamStruct,- IsSized startParamStruct startParamSize,- IsSized nextParamStruct nextParamSize) =>+ (Memory.C value, Memory.Struct value ~ struct,+ Memory.C state, Memory.Struct state ~ stateStruct,+ Memory.C startParamValue, Memory.Struct startParamValue ~ startParamStruct,+ Memory.C nextParamValue, Memory.Struct nextParamValue ~ nextParamStruct) => (forall r. nextParamValue -> state -> Maybe.T r (Value Bool, state) (value, state)) ->@@ -689,13 +678,10 @@ ret (pos :: Value Word32)) compileChunky ::- (Memory.C value struct,- Memory.C state stateStruct,- IsSized stateStruct stateSize,- Memory.C startParamValue startParamStruct,- Memory.C nextParamValue nextParamStruct,- IsSized startParamStruct startParamSize,- IsSized nextParamStruct nextParamSize) =>+ (Memory.C value, Memory.Struct value ~ struct,+ Memory.C state, Memory.Struct state ~ stateStruct,+ Memory.C startParamValue, Memory.Struct startParamValue ~ startParamStruct,+ Memory.C nextParamValue, Memory.Struct nextParamValue ~ nextParamStruct) => (forall r. nextParamValue -> state -> Maybe.T r (Value Bool, state) (value, state)) ->@@ -711,16 +697,16 @@ debugMain :: forall struct stateStruct- startParamValue startParamStruct startParamSize- nextParamValue nextParamStruct nextParamSize.+ startParamValue startParamStruct+ nextParamValue nextParamStruct. (Storable startParamValue, Storable nextParamValue, LLVM.IsType struct, LLVM.IsType stateStruct, LLVM.IsType startParamStruct, LLVM.IsType nextParamStruct,- IsSized startParamStruct startParamSize,- IsSized nextParamStruct nextParamSize) =>+ IsSized startParamStruct,+ IsSized nextParamStruct) => CodeGenModule (Function (Ptr startParamStruct -> IO (Ptr stateStruct)), Function (Ptr stateStruct -> IO ()),@@ -735,17 +721,17 @@ DebugSt.withConstArray nextParam (\arr -> do ptr <- LLVM.alloca LLVM.store (value arr) ptr- LLVM.bitcastUnify ptr)+ LLVM.bitcast ptr) -} nextArray <- DebugSt.withConstArray nextParam (\arr -> do ptr <- LLVM.alloca- LLVM.store (value arr) =<< LLVM.bitcastUnify ptr+ LLVM.store (value arr) =<< LLVM.bitcast ptr return ptr) startArray <- DebugSt.withConstArray startParam (\arr -> do ptr <- LLVM.alloca- LLVM.store (value arr) =<< LLVM.bitcastUnify ptr+ LLVM.store (value arr) =<< LLVM.bitcast ptr return ptr) m <- LLVM.newModule@@ -760,7 +746,7 @@ basePtr = LLVM.valueOf nullPtr buffer <- LLVM.call mallocBytes =<<- LLVM.bitcastUnify =<<+ LLVM.bitcast =<< LLVM.getElementPtr basePtr (chunkSize, ()) nextPtr <- nextArray _done <-@@ -781,13 +767,13 @@ this means that the signal is shortened. -} runChunkyPattern ::- (Storable a, MakeValueTuple a value, Memory.C value struct) =>+ (Storable a, MakeValueTuple a, ValueTuple a ~ value, Memory.C value) => T p value -> IO (SVP.LazySize -> p -> SVL.Vector a) runChunkyPattern (Cons next start createIOContext deleteIOContext) = do (startFunc, stopFunc, fill) <- compileChunky next start return $- \ lazysize p -> SVL.fromChunks $ unsafePerformIO $ do+ \ lazysize p -> SVL.fromChunks $ Unsafe.performIO $ do (ioContext, (nextParam, startParam)) <- createIOContext p {-@@ -798,14 +784,14 @@ DebugSt.dump "next-param" nextParam DebugSt.dump "start-param" startParam - when False $ fmap (const ()) $+ when False $ void $ debugMain (moduleChunky next start) (nextParam, startParam) statePtr <- ForeignPtr.newParam stopFunc startFunc startParam nextParamPtr <- ForeignPtr.new (deleteIOContext ioContext) nextParam let go cs =- unsafeInterleaveIO $+ Unsafe.interleaveIO $ case cs of [] -> return [] SVL.ChunkSize size : rest -> do@@ -825,7 +811,7 @@ go (Chunky.toChunks lazysize) runChunky ::- (Storable a, MakeValueTuple a value, Memory.C value struct) =>+ (Storable a, MakeValueTuple a, ValueTuple a ~ value, Memory.C value) => T p value -> IO (SVL.ChunkSize -> p -> SVL.Vector a) runChunky sig =@@ -843,8 +829,8 @@ and I assume that you use this package exclusively for performance reasons. -} renderChunky ::- (Storable a, MakeValueTuple a value, Memory.C value struct) =>+ (Storable a, MakeValueTuple a, ValueTuple a ~ value, Memory.C value) => SVL.ChunkSize -> T p value -> p -> SVL.Vector a renderChunky size gen =- unsafePerformIO (runChunky gen) size+ Unsafe.performIO (runChunky gen) size
src/Synthesizer/LLVM/Parameterized/SignalPacked.hs view
@@ -1,9 +1,7 @@ {-# LANGUAGE NoImplicitPrelude #-}-{-# LANGUAGE MultiParamTypeClasses #-}-{-# LANGUAGE FunctionalDependencies #-}-{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE TypeFamilies #-}+{-# LANGUAGE TypeOperators #-} {-# LANGUAGE FlexibleContexts #-}-{-# LANGUAGE UndecidableInstances #-} {-# LANGUAGE ExistentialQuantification #-} {-# LANGUAGE Rank2Types #-} {-# LANGUAGE ForeignFunctionInterface #-}@@ -28,7 +26,7 @@ import Synthesizer.LLVM.Parameterized.Signal (T(Cons), ) import qualified Synthesizer.LLVM.Parameterized.Signal as Sig import qualified Synthesizer.LLVM.Parameter as Param-import qualified Synthesizer.LLVM.SerialVector as Serial+import qualified Synthesizer.LLVM.Frame.SerialVector as Serial import qualified Synthesizer.LLVM.Random as Rnd import qualified LLVM.Extra.Memory as Memory@@ -36,15 +34,19 @@ import qualified LLVM.Extra.Vector as Vector import qualified LLVM.Extra.MaybeContinuation as Maybe import qualified LLVM.Extra.Control as U-import qualified LLVM.Extra.Class as Class import qualified LLVM.Extra.Arithmetic as A-import LLVM.Extra.Class (MakeValueTuple, Undefined, undefTuple, )+import LLVM.Extra.Class (MakeValueTuple, ValueTuple, Undefined, undefTuple, ) -import qualified Data.TypeLevel.Num as TypeNum+import qualified Types.Data.Bool as TypeBool+import qualified Types.Data.Num as TypeNum+import Types.Data.Num ((:*:), ) import LLVM.Core as LLVM +import qualified Control.Monad.Trans.Class as MT+import qualified Control.Monad.Trans.State as MS import Control.Monad.HT ((<=<), )+import Control.Monad (replicateM, ) -- we can also use <$> for parameters import Control.Arrow ((^<<), ) import Control.Applicative (liftA2, )@@ -70,33 +72,45 @@ If the signal length is not divisible by the chunk size, then the last chunk is dropped. -}-pack, packRotate, packIndex ::- (Vector.Access n a v) =>+pack, packRotate ::+ (Serial.C v, a ~ Serial.Element v) => T p a -> T p v pack = packRotate packRotate (Cons next start createIOContext deleteIOContext) = Cons (\param s -> do- (v2,_,s2) <-+ wInit <- Maybe.lift $ Serial.writeStart+ (w2,_,s2) <- Maybe.fromBool $ U.whileLoop (valueOf True,- let v = undefTuple- in (v, valueOf $ (fromIntegral $ Vector.sizeInTuple v :: Word32), s))- (\(cont,(_v0,i0,_s0)) ->+ (wInit,+ valueOf $ (fromIntegral $ Serial.sizeOfIterator wInit :: Word32),+ s))+ (\(cont,(_w0,i0,_s0)) -> A.and cont =<< A.cmp CmpGT i0 (value LLVM.zero))- (\(_,(v0,i0,s0)) -> Maybe.toBool $ do+ (\(_,(w0,i0,s0)) -> Maybe.toBool $ do (a,s1) <- next param s0 Maybe.lift $ do- v1 <- fmap snd $ Vector.shiftDown a v0+ w1 <- Serial.writeNext a w0 i1 <- A.dec i0- return (v1,i1,s1))- return (v2, s2))+ return (w1,i1,s1))+ v <- Maybe.lift $ Serial.writeStop w2+ return (v, s2)) start createIOContext deleteIOContext +{-+We could reformulate it in terms of WriteIterator+that accesses elements using LLVM.extract.+We might move the loop counter into the Iterator,+but we have to assert that the counter is not duplicated.++packIndex ::+ (Serial.C v, a ~ Serial.Element v) =>+ T p a -> T p v packIndex (Cons next start createIOContext deleteIOContext) = Cons (\param s -> do (v2,_,s2) <-@@ -106,7 +120,7 @@ (\(cont,(v0,i0,_s0)) -> A.and cont =<< A.cmp CmpLT i0- (valueOf $ fromIntegral $ Vector.sizeInTuple v0))+ (valueOf $ fromIntegral $ Serial.size v0)) (\(_,(v0,i0,s0)) -> Maybe.toBool $ do (a,s1) <- next param s0 Maybe.lift $ do@@ -117,6 +131,7 @@ start createIOContext deleteIOContext+-} {- |@@ -126,54 +141,62 @@ This is efficient only for simple input generators. -} packSmall ::- (Vector.Access n a v, Class.Zero v) =>+ (Serial.C v, a ~ Serial.Element v) => T p a -> T p v packSmall (Cons next start createIOContext deleteIOContext) = Cons- (\param s ->- let vundef = undefTuple- in foldr- (\i rest (v0,s0) -> do- (a,s1) <- next param s0- v1 <- Maybe.lift $ Vector.insert (valueOf i) a v0- rest (v1,s1))- return- (take (Vector.sizeInTuple vundef) [0..])- (vundef, s))+ (\param ->+ MS.runStateT $+ case undefined of+ vundef ->+ fmap (flip asTypeOf vundef) .+ MT.lift . Maybe.lift . Serial.assemble+ =<<+ replicateM (Serial.size vundef) (MS.StateT $ next param)) start createIOContext deleteIOContext -unpack, unpackRotate, unpackIndex ::- (Vector.Access n a v, Memory.C v vp, IsSized vp vs) =>+unpack, unpackRotate ::+ (Serial.Read v, a ~ Serial.Element v, Memory.C (Serial.ReadIt v)) => T p v -> T p a unpack = unpackRotate unpackRotate (Cons next start createIOContext deleteIOContext) = Cons- (\param (i0,v0,s0) -> do+ (\param (i0,r0,s0) -> do endOfVector <-- Maybe.lift $ A.cmp CmpEQ i0 (valueOf 0)- (i2,v2,s2) <-+ Maybe.lift $ A.cmp CmpEQ i0 (valueOf (0::Word32))+ (i2,r2,s2) <- Maybe.fromBool $- U.ifThen endOfVector (valueOf True, (i0,v0,s0)) $ do+ U.ifThen endOfVector (valueOf True, (i0,r0,s0)) $ do (cont1, (v1,s1)) <- Maybe.toBool $ next param s0- return (cont1, (valueOf $ fromIntegral $ Vector.sizeInTuple v0, v1, s1))+ r1 <- Serial.readStart v1+ return (cont1, (valueOf $ fromIntegral $ Serial.size v1, r1, s1)) Maybe.lift $ do- a <- Vector.extract (valueOf 0 `asTypeOf` i0) v2- v3 <- Vector.rotateDown v2+ (a,r3) <- Serial.readNext r2 i3 <- A.dec i2- return (a, (i3,v3,s2)))+ return (a, (i3,r3,s2))) (\p -> do s <- start p return (valueOf 0, undefTuple, s)) createIOContext deleteIOContext ++{-+We could reformulate it in terms of ReadIterator+that accesses elements using LLVM.extract.+We might move the loop counter into the Iterator,+but we have to assert that the counter is not duplicated.++unpackIndex ::+ (Serial.C v, a ~ Serial.Element v, Memory.C v) =>+ T p v -> T p a unpackIndex (Cons next start createIOContext deleteIOContext) = Cons (\param (i0,v0,s0) -> do endOfVector <- Maybe.lift $ A.cmp CmpGE i0- (valueOf $ fromIntegral $ Vector.sizeInTuple v0)+ (valueOf $ fromIntegral $ Serial.size v0) (i2,v2,s2) <- Maybe.fromBool $ U.ifThen endOfVector (valueOf True, (i0,v0,s0)) $ do@@ -186,106 +209,107 @@ (\p -> do s <- start p let v = undefTuple- return (valueOf $ fromIntegral $ Vector.sizeInTuple v, v, s))+ return (valueOf $ fromIntegral $ Serial.size v, v, s)) createIOContext deleteIOContext+-} withSize ::- (n -> T p (Value (Vector n a))) ->- T p (Value (Vector n a))+ (n -> T p (Serial.Value n a)) ->+ T p (Serial.Value n a) withSize f = f undefined withSizeRing ::- (Ring.C b, TypeNum.Nat n) =>- (b -> T p (Value (Vector n a))) ->- T p (Value (Vector n a))+ (Ring.C b, TypeNum.IntegerT n, TypeNum.IsPositive n ~ TypeBool.True) =>+ (b -> T p (Serial.Value n a)) ->+ T p (Serial.Value n a) withSizeRing f =- withSize $ \n -> f (fromIntegral $ TypeNum.toInt n)+ withSize $ \n -> f (fromInteger $ TypeNum.fromIntegerT n) constant ::- (Storable a, MakeValueTuple a (Value a),+ (Storable a, MakeValueTuple a, ValueTuple a ~ (Value a), IsConst a,- Memory.FirstClass a am,- IsPrimitive a, IsSized a as,- IsPrimitive am, IsSized am amsize,- TypeNum.Mul n as vas, TypeNum.Pos vas,- TypeNum.Mul n amsize vmsize, TypeNum.Pos vmsize,- TypeNum.Pos n) =>- Param.T p a -> T p (Value (Vector n a))+ Memory.FirstClass a, Memory.Stored a ~ am,+ IsPrimitive a, IsSized a, SizeOf a ~ as,+ IsPrimitive am, IsSized am, SizeOf am ~ amsize,+ TypeNum.PositiveT (n :*: as),+ TypeNum.PositiveT (n :*: amsize),+ TypeNum.IntegerT n, TypeNum.IsPositive n ~ TypeBool.True) =>+ Param.T p a -> T p (Serial.Value n a) constant x = Sig.constant (Serial.replicate ^<< x) exponential2 ::- (Trans.C a, Storable a, MakeValueTuple a (Value a),+ (Trans.C a, Storable a, MakeValueTuple a, ValueTuple a ~ (Value a), IsArithmetic a, IsConst a,- Memory.FirstClass a am,- IsPrimitive a, IsSized a as,- IsPrimitive am, IsSized am amsize,- TypeNum.Mul n as vas, TypeNum.Pos vas,- TypeNum.Mul n amsize vmsize, TypeNum.Pos vmsize,- TypeNum.Pos n) =>- Param.T p a -> Param.T p a -> T p (Value (Vector n a))+ Memory.FirstClass a, Memory.Stored a ~ am,+ IsPrimitive a, IsSized a, SizeOf a ~ as,+ IsPrimitive am, IsSized am, SizeOf am ~ amsize,+ TypeNum.PositiveT (n :*: as),+ TypeNum.PositiveT (n :*: amsize),+ TypeNum.IntegerT n, TypeNum.IsPositive n ~ TypeBool.True) =>+ Param.T p a -> Param.T p a -> T p (Serial.Value n a) exponential2 halfLife start = withSizeRing $ \n -> Sig.exponentialCore (Serial.replicate ^<< 0.5 ** (n / halfLife)) (liftA2- (\h -> LLVM.vector . List.iterate (0.5 ** recip h *))+ (\h -> Serial.fromList . List.iterate (0.5 ** recip h *)) halfLife start) exponentialBounded2 ::- (Trans.C a, Storable a, MakeValueTuple a (Value a),+ (Trans.C a, Storable a, MakeValueTuple a, ValueTuple a ~ (Value a), Vector.Real a, IsConst a,- Memory.FirstClass a am,- IsPrimitive a, IsSized a as,- IsPrimitive am, IsSized am amsize,- TypeNum.Mul n as vas, TypeNum.Pos vas,- TypeNum.Mul n amsize vmsize, TypeNum.Pos vmsize,- TypeNum.Pos n) =>+ Memory.FirstClass a, Memory.Stored a ~ am,+ IsPrimitive a, IsSized a, SizeOf a ~ as,+ IsPrimitive am, IsSized am, SizeOf am ~ amsize,+ TypeNum.PositiveT (n :*: as),+ TypeNum.PositiveT (n :*: amsize),+ TypeNum.IntegerT n, TypeNum.IsPositive n ~ TypeBool.True) => Param.T p a -> Param.T p a -> Param.T p a ->- T p (Value (Vector n a))+ T p (Serial.Value n a) exponentialBounded2 bound halfLife start = withSizeRing $ \n -> Sig.exponentialBoundedCore (fmap (Serial.replicate) bound) (Serial.replicate ^<< 0.5 ** (n / halfLife)) (liftA2- (\h -> LLVM.vector . List.iterate (0.5 ** recip h *))+ (\h -> Serial.fromList . List.iterate (0.5 ** recip h *)) halfLife start) osciCore ::- (Storable t, MakeValueTuple t (Value t),- Memory.FirstClass t tm,- IsPrimitive t, IsSized t tsize,- IsPrimitive tm, IsSized tm tmsize,- TypeNum.Mul n tsize vtsize, TypeNum.Pos vtsize,- TypeNum.Mul n tmsize vmsize, TypeNum.Pos vmsize,+ (Storable t, MakeValueTuple t, ValueTuple t ~ (Value t),+ Memory.FirstClass t, Memory.Stored t ~ tm,+ IsPrimitive t, IsSized t, SizeOf t ~ tsize,+ IsPrimitive tm, IsSized tm, SizeOf tm ~ tmsize,+ TypeNum.PositiveT (n :*: tsize),+ TypeNum.PositiveT (n :*: tmsize), Vector.Real t, IsFloating t, RealField.C t, IsConst t,- TypeNum.Pos n) =>- Param.T p t -> Param.T p t -> T p (Value (Vector n t))+ TypeNum.IntegerT n, TypeNum.IsPositive n ~ TypeBool.True) =>+ Param.T p t -> Param.T p t -> T p (Serial.Value n t) osciCore phase freq = withSizeRing $ \n -> Sig.osciCore (liftA2- (\f -> LLVM.vector . List.iterate (fraction . (f +)))+ (\f -> Serial.fromList . List.iterate (fraction . (f +))) freq phase) (fmap- (\f -> LLVM.vector [fraction (n * f)])+ (\f -> Serial.replicate (fraction (n * f))) freq) osci ::- (Storable t, MakeValueTuple t (Value t),- Storable c, MakeValueTuple c cl,- Memory.FirstClass t tm,- IsPrimitive t, IsSized t tsize,- IsPrimitive tm, IsSized tm tmsize,- TypeNum.Mul n tsize vtsize, TypeNum.Pos vtsize,- TypeNum.Mul n tmsize vmsize, TypeNum.Pos vmsize,- Memory.C cl cp, IsSized cp cs,+ (Storable t, MakeValueTuple t, ValueTuple t ~ (Value t),+ Storable c, MakeValueTuple c, ValueTuple c ~ cl,+ Memory.FirstClass t, Memory.Stored t ~ tm,+ IsPrimitive t, IsSized t, SizeOf t ~ tsize,+ IsPrimitive tm, IsSized tm, SizeOf tm ~ tmsize,+ TypeNum.PositiveT (n :*: tsize),+ TypeNum.PositiveT (n :*: tmsize),+ Memory.C cl, Vector.Real t, IsFloating t, RealField.C t, IsConst t,- TypeNum.Pos n) =>- (forall r. cl -> Value (Vector n t) -> CodeGenFunction r y) ->+ TypeNum.IntegerT n, TypeNum.IsPositive n ~ TypeBool.True) =>+ (forall r. cl -> Serial.Value n t -> CodeGenFunction r y) -> Param.T p c -> Param.T p t -> Param.T p t -> T p y osci wave waveParam phase freq =@@ -293,15 +317,15 @@ osciCore phase freq osciSimple ::- (Storable t, MakeValueTuple t (Value t),- Memory.FirstClass t tm,- IsPrimitive t, IsSized t tsize,- IsPrimitive tm, IsSized tm tmsize,- TypeNum.Mul n tsize vtsize, TypeNum.Pos vtsize,- TypeNum.Mul n tmsize vmsize, TypeNum.Pos vmsize,+ (Storable t, MakeValueTuple t, ValueTuple t ~ (Value t),+ Memory.FirstClass t, Memory.Stored t ~ tm,+ IsPrimitive t, IsSized t, SizeOf t ~ tsize,+ IsPrimitive tm, IsSized tm, SizeOf tm ~ tmsize,+ TypeNum.PositiveT (n :*: tsize),+ TypeNum.PositiveT (n :*: tmsize), Vector.Real t, IsFloating t, RealField.C t, IsConst t,- TypeNum.Pos n) =>- (forall r. Value (Vector n t) -> CodeGenFunction r y) ->+ TypeNum.IntegerT n, TypeNum.IsPositive n ~ TypeBool.True) =>+ (forall r. Serial.Value n t -> CodeGenFunction r y) -> Param.T p t -> Param.T p t -> T p y osciSimple wave = osci (const wave) (return ())@@ -309,18 +333,19 @@ rampInf, rampSlope, parabolaFadeInInf, parabolaFadeOutInf ::- (RealField.C a, Storable a, MakeValueTuple a (Value a),- Memory.FirstClass a am,- IsPrimitive a, IsSized a as,- IsPrimitive am, IsSized am amsize,- TypeNum.Mul n as vas, TypeNum.Pos vas,- TypeNum.Mul n amsize vmsize, TypeNum.Pos vmsize,- IsArithmetic a, IsConst a, TypeNum.Pos n) =>- Param.T p a -> T p (Value (Vector n a))+ (RealField.C a, Storable a, MakeValueTuple a, ValueTuple a ~ (Value a),+ Memory.FirstClass a, Memory.Stored a ~ am,+ IsPrimitive a, IsSized a, SizeOf a ~ as,+ IsPrimitive am, IsSized am, SizeOf am ~ amsize,+ TypeNum.PositiveT (n :*: as),+ TypeNum.PositiveT (n :*: amsize),+ IsArithmetic a, SoV.IntegerConstant a,+ TypeNum.IntegerT n, TypeNum.IsPositive n ~ TypeBool.True) =>+ Param.T p a -> T p (Serial.Value n a) rampSlope slope = withSizeRing $ \n -> Sig.rampCore- (fmap (\s -> LLVM.vector [n * s]) slope)- (fmap (\s -> LLVM.vector (List.iterate (s +) 0)) slope)+ (fmap (\s -> Serial.replicate (n * s)) slope)+ (fmap (\s -> Serial.fromList (List.iterate (s +) 0)) slope) rampInf dur = rampSlope (recip dur) parabolaFadeInInf dur = withSizeRing $ \n ->@@ -328,15 +353,15 @@ (fmap (\dr -> let d = n / dr- in LLVM.vector [-2*d*d]) dur)+ in Serial.replicate (-2*d*d)) dur) (fmap (\dr -> let d = n / dr- in LLVM.vector $ List.iterate (subtract $ 2 / dr ^ 2) (d*(2-d)))+ in Serial.fromList $ List.iterate (subtract $ 2 / dr ^ 2) (d*(2-d))) dur) (fmap (\dr ->- LLVM.vector $ List.map (\t -> t*(2-t)) $ List.iterate (recip dr +) 0)+ Serial.fromList $ List.map (\t -> t*(2-t)) $ List.iterate (recip dr +) 0) dur) parabolaFadeOutInf dur = withSizeRing $ \n ->@@ -344,15 +369,15 @@ (fmap (\dr -> let d = n / dr- in LLVM.vector [-2*d*d]) dur)+ in Serial.replicate (-2*d*d)) dur) (fmap (\dr -> let d = n / dr- in LLVM.vector $ List.iterate (subtract $ 2 / dr ^ 2) (-d*d))+ in Serial.fromList $ List.iterate (subtract $ 2 / dr ^ 2) (-d*d)) dur) (fmap (\dr ->- LLVM.vector $ List.map (\t -> 1-t*t) $ List.iterate (recip dr +) 0)+ Serial.fromList $ List.map (\t -> 1-t*t) $ List.iterate (recip dr +) 0) dur) @@ -360,24 +385,26 @@ For the mysterious rate parameter see 'Sig.noise'. -} noise ::- (Algebraic.C a, IsFloating a, IsConst a,- TypeNum.Pos n, TypeNum.Mul n TypeNum.D32 s, TypeNum.Pos s,- Memory.FirstClass a am,- IsPrimitive a, IsSized a as,- IsPrimitive am, IsSized am amsize,- TypeNum.Mul n as vas, TypeNum.Pos vas,- TypeNum.Mul n amsize vmsize, TypeNum.Pos vmsize,- MakeValueTuple a (Value a), Storable a) =>+ (Algebraic.C a, IsFloating a, SoV.IntegerConstant a,+ TypeNum.IntegerT n, TypeNum.IsPositive n ~ TypeBool.True,+ TypeNum.PositiveT (n :*: TypeNum.D32),+ Memory.FirstClass a, Memory.Stored a ~ am,+ IsPrimitive a, IsSized a, SizeOf a ~ as,+ IsPrimitive am, IsSized am, SizeOf am ~ amsize,+ TypeNum.PositiveT (n :*: as),+ TypeNum.PositiveT (n :*: amsize),+ MakeValueTuple a, ValueTuple a ~ (Value a), Storable a) => Param.T p Word32 -> Param.T p a ->- T p (Value (Vector n a))+ T p (Serial.Value n a) noise seed rate =- let m2 = fromInteger $ div Rnd.modulus 2- in Sig.map (\r y ->- A.mul r- =<< flip A.sub (SoV.replicateOf $ m2+1)- =<< int31tofp y)- (Serial.replicate ^<< sqrt (3 * rate) / return m2) $+ let m2 = div Rnd.modulus 2+ in Sig.map+ (\r y ->+ A.mul r+ =<< flip A.sub (A.fromInteger' $ m2+1)+ =<< int31tofp y)+ (Serial.replicate ^<< sqrt (3 * rate) / return (fromInteger m2)) $ noiseCore seed {-@@ -386,25 +413,29 @@ -} int31tofp :: (IsFloating a, IsPrimitive a,- TypeNum.Pos n, TypeNum.Mul n TypeNum.D32 s, TypeNum.Pos s) =>- Value (Vector n Word32) -> CodeGenFunction r (Value (Vector n a))+ TypeNum.PositiveT n, TypeNum.PositiveT (n :*: TypeNum.D32)) =>+ Serial.Value n Word32 -> CodeGenFunction r (Serial.Value n a) int31tofp =+ Serial.mapV $ LLVM.inttofp <=<- (LLVM.bitcastUnify ::- (TypeNum.Pos n, TypeNum.Mul n TypeNum.D32 s, TypeNum.Pos s) =>+ (LLVM.bitcast ::+ (TypeNum.PositiveT n, TypeNum.PositiveT (n :*: TypeNum.D32)) => Value (Vector n Word32) -> CodeGenFunction r (Value (Vector n Int32))) noiseCore, noiseCoreAlt ::- (TypeNum.Pos n, TypeNum.Mul n TypeNum.D32 s, TypeNum.Pos s) =>+ (TypeNum.IntegerT n, TypeNum.IsPositive n ~ TypeBool.True,+ TypeNum.PositiveT (n :*: TypeNum.D32)) => Param.T p Word32 ->- T p (Value (Vector n Word32))+ T p (Serial.Value n Word32) noiseCore seed =+ fmap Serial.value $ Sig.iterate (const Rnd.nextVector) (return ()) (Rnd.vectorSeed . (+1) . flip mod (Rnd.modulus-1) ^<< seed) noiseCoreAlt seed =+ fmap Serial.value $ Sig.iterate (const Rnd.nextVector64) (return ()) (Rnd.vectorSeed . (+1) . flip mod (Rnd.modulus-1) ^<< seed)
src/Synthesizer/LLVM/Parameterized/SignalPrivate.hs view
@@ -1,4 +1,6 @@ {-# LANGUAGE NoImplicitPrelude #-}+{-# LANGUAGE TypeFamilies #-}+{-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE ExistentialQuantification #-} {-# LANGUAGE Rank2Types #-} module Synthesizer.LLVM.Parameterized.SignalPrivate where@@ -8,8 +10,8 @@ import qualified LLVM.Extra.Memory as Memory import qualified LLVM.Extra.Arithmetic as A -import LLVM.Extra.Class (MakeValueTuple, )-import LLVM.Core (IsSized, CodeGenFunction, )+import LLVM.Extra.Class (MakeValueTuple, ValueTuple, )+import LLVM.Core (CodeGenFunction, ) import LLVM.Util.Loop (Phi, ) import Control.Arrow ((&&&), )@@ -26,7 +28,9 @@ import NumericPrelude.Base hiding (and, iterate, map, zip, zipWith, ) +import qualified Prelude as P + {- In this attempt we use a Haskell value as parameter supply. This is okay, since the Haskell value will be converted to internal parameters@@ -55,48 +59,42 @@ Consider a signal algorithm, where the LFO frequency is a parameter. -} data T p a =- forall state packed size ioContext- startParamTuple startParamValue startParamPacked startParamSize- nextParamTuple nextParamValue nextParamPacked nextParamSize.+ forall state ioContext startParamTuple nextParamTuple. (Storable startParamTuple, Storable nextParamTuple,- MakeValueTuple startParamTuple startParamValue,- MakeValueTuple nextParamTuple nextParamValue,- Memory.C startParamValue startParamPacked,- Memory.C nextParamValue nextParamPacked,- IsSized startParamPacked startParamSize,- IsSized nextParamPacked nextParamSize,- Memory.C state packed,- IsSized packed size) =>+ MakeValueTuple startParamTuple,+ MakeValueTuple nextParamTuple,+ Memory.C (ValueTuple startParamTuple),+ Memory.C (ValueTuple nextParamTuple),+ Memory.C state) => Cons (forall r c. (Phi c) =>- nextParamValue ->+ ValueTuple nextParamTuple -> state -> Maybe.T r c (a, state)) -- compute next value (forall r.- startParamValue ->+ ValueTuple startParamTuple -> CodeGenFunction r state) -- initial state (p -> IO (ioContext, (nextParamTuple, startParamTuple))) {- initialization from IO monad- This will be run within unsafePerformIO,+ This will be run within Unsafe.performIO, so no observable In/Out actions please! -} (ioContext -> IO ())- -- finalization from IO monad, also run within unsafePerformIO+ -- finalization from IO monad, also run within Unsafe.performIO simple :: (Storable startParamTuple, Storable nextParamTuple,- MakeValueTuple startParamTuple startParamValue,- MakeValueTuple nextParamTuple nextParamValue,- Memory.C startParamValue startParamPacked,- Memory.C nextParamValue nextParamPacked,- IsSized startParamPacked startParamSize,- IsSized nextParamPacked nextParamSize,- Memory.C state packed,- IsSized packed size) =>+ MakeValueTuple startParamTuple,+ MakeValueTuple nextParamTuple,+ ValueTuple startParamTuple ~ startParamValue,+ ValueTuple nextParamTuple ~ nextParamValue,+ Memory.C startParamValue,+ Memory.C nextParamValue,+ Memory.C state) => (forall r c. (Phi c) => nextParamValue ->@@ -114,7 +112,7 @@ map ::- (Storable ph, MakeValueTuple ph pl, Memory.C pl pp, IsSized pp ps) =>+ (Storable ph, MakeValueTuple ph, ValueTuple ph ~ pl, Memory.C pl) => (forall r. pl -> a -> CodeGenFunction r b) -> Param.T p ph -> T p a -> T p b@@ -138,7 +136,7 @@ zipWith ::- (Storable ph, MakeValueTuple ph pl, Memory.C pl pp, IsSized pp ps) =>+ (Storable ph, MakeValueTuple ph, ValueTuple ph ~ pl, Memory.C pl) => (forall r. pl -> a -> b -> CodeGenFunction r c) -> Param.T p ph -> T p a -> T p b -> T p c@@ -204,11 +202,23 @@ (/) = zipWithSimple A.fdiv +instance (A.PseudoRing a, A.Real a, A.IntegerConstant a) => P.Num (T p a) where+ fromInteger n = pure (A.fromInteger' n)+ negate = mapSimple A.neg+ (+) = zipWithSimple A.add+ (-) = zipWithSimple A.sub+ (*) = zipWithSimple A.mul+ abs = mapSimple A.abs+ signum = mapSimple A.signum++instance (A.Field a, A.Real a, A.RationalConstant a) => P.Fractional (T p a) where+ fromRational x = pure (A.fromRational' x)+ (/) = zipWithSimple A.fdiv++ iterate ::- (Storable ph, MakeValueTuple ph pl,- Memory.C pl pp, IsSized pp ps,- Storable a, MakeValueTuple a al,- Memory.C al packed, IsSized packed s) =>+ (Storable ph, MakeValueTuple ph, ValueTuple ph ~ pl, Memory.C pl,+ Storable a, MakeValueTuple a, ValueTuple a ~ al, Memory.C al) => (forall r. pl -> al -> CodeGenFunction r al) -> Param.T p ph -> Param.T p a -> T p al
src/Synthesizer/LLVM/Plug/Input.hs view
@@ -1,8 +1,7 @@ {-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE ExistentialQuantification #-} {-# LANGUAGE Rank2Types #-}-{-# LANGUAGE MultiParamTypeClasses #-}-{-# LANGUAGE FunctionalDependencies #-}+{-# LANGUAGE TypeFamilies #-} {-# LANGUAGE FlexibleInstances #-} {-# LANGUAGE UndecidableInstances #-} module Synthesizer.LLVM.Plug.Input where@@ -17,9 +16,9 @@ import qualified LLVM.Extra.Control as C import qualified LLVM.Core as LLVM-import LLVM.Extra.Class (MakeValueTuple, )+import LLVM.Extra.Class (MakeValueTuple, ValueTuple, ) -import qualified Data.TypeLevel.Num as TypeNum+import qualified Types.Data.Num as TypeNum import Control.Applicative (liftA2, ) @@ -27,7 +26,7 @@ import Data.Tuple.HT (mapFst, mapPair, swap, ) -import qualified Synthesizer.PiecewiseConstant.ALSA.MIDIControllerSet as PCS+import qualified Synthesizer.MIDI.PiecewiseConstant.ControllerSet as PCS import qualified Synthesizer.Generic.Signal as SigG import qualified Data.EventList.Relative.BodyTime as EventListBT import qualified Data.EventList.Relative.MixedTime as EventListMT@@ -43,6 +42,8 @@ import qualified Foreign.ForeignPtr as FPtr import Foreign.Storable (Storable, pokeElemOff, ) +import qualified System.Unsafe as Unsafe+ import Data.Word (Word32, ) @@ -54,32 +55,29 @@ via an instance of 'Synthesizer.Generic.Cut.Read'. -} data T a b =- forall state packed size ioContext- paramTuple paramValue paramPacked paramSize.+ forall state ioContext paramTuple. (Storable paramTuple,- MakeValueTuple paramTuple paramValue,- Memory.C paramValue paramPacked,- LLVM.IsSized paramPacked paramSize,- Memory.C state packed,- LLVM.IsSized packed size) =>+ MakeValueTuple paramTuple,+ Memory.C (ValueTuple paramTuple),+ Memory.C state) => Cons (forall r.- paramValue ->+ ValueTuple paramTuple -> state -> LLVM.CodeGenFunction r (b, state)) -- compute next value (forall r.- paramValue ->+ ValueTuple paramTuple -> LLVM.CodeGenFunction r state) -- initial state (a -> IO (ioContext, paramTuple)) {- initialization from IO monad This is called once input chunk.- This will be run within unsafePerformIO,+ This will be run within Unsafe.performIO, so no observable In/Out actions please! -} (ioContext -> IO ()) {-- finalization from IO monad, also run within unsafePerformIO+ finalization from IO monad, also run within Unsafe.performIO -} @@ -88,20 +86,22 @@ Cons (\p s -> fmap (mapFst f) $ next p s) start create delete -class Default a b | a -> b where- deflt :: T a b+class Default a where+ type Element a :: *+ deflt :: T a (Element a) -instance- (Default a c, Default b d) =>- Default (Zip.T a b) (c,d) where+instance (Default a, Default b) => Default (Zip.T a b) where+ type Element (Zip.T a b) = (Element a, Element b) deflt = split deflt deflt -instance Default SigG.LazySize () where+instance Default SigG.LazySize where+ type Element SigG.LazySize = () deflt = lazySize instance- (Storable a, MakeValueTuple a value, Memory.C value struct) =>- Default (SV.Vector a) value where+ (Storable a, MakeValueTuple a, Memory.C (Class.ValueTuple a)) =>+ Default (SV.Vector a) where+ type Element (SV.Vector a) = Class.ValueTuple a deflt = storableVector @@ -112,9 +112,9 @@ see the versioning history for an according hack. -} instance- (Storable a, MakeValueTuple a value,- Memory.C value struct, LLVM.IsSized struct size) =>- Default (EventListBT.T NonNegW.Int a) value where+ (Storable a, MakeValueTuple a, Memory.C (ValueTuple a)) =>+ Default (EventListBT.T NonNegW.Int a) where+ type Element (EventListBT.T NonNegW.Int a) = ValueTuple a deflt = piecewiseConstant @@ -143,17 +143,22 @@ deleteA ca >> deleteB cb) -lazySize ::- T SigG.LazySize ()-lazySize =+fanout :: T a b -> T a c -> T a (b,c)+fanout f g = rmap (\a -> Zip.Cons a a) $ split f g++lazySize :: T SigG.LazySize ()+lazySize = ignore++ignore :: T a ()+ignore = Cons (\ _ _ -> return ((), ())) return- (\ _lazySize -> return ((), ()))+ (\ _a -> return ((), ())) (const $ return ()) storableVector ::- (Storable a, MakeValueTuple a value, Memory.C value struct) =>+ (Storable a, MakeValueTuple a, ValueTuple a ~ value, Memory.C value) => T (SV.Vector a) value storableVector = Cons@@ -166,7 +171,7 @@ let (fp,s,_l) = SVB.toForeignPtr vec in return (fp, Memory.castStorablePtr $- FPtr.unsafeForeignPtrToPtr fp `Array.advancePtr` s))+ Unsafe.foreignPtrToPtr fp `Array.advancePtr` s)) -- keep the foreign ptr alive FPtr.touchForeignPtr @@ -176,8 +181,8 @@ but here we do not accept early exit. -} piecewiseConstant ::- (Storable a, MakeValueTuple a value,- Memory.C value struct, LLVM.IsSized struct size) =>+ (Storable a, MakeValueTuple a, ValueTuple a ~ value,+ Memory.C value) => T (EventListBT.T NonNegW.Int a) value piecewiseConstant = case rmap (uncurry Zip.Cons .@@ -207,10 +212,9 @@ in order to forbid writing to the array. -} controllerSet ::- (TypeNum.Nat n, Memory.FirstClass a b,- Storable a, MakeValueTuple a (LLVM.Value a),- LLVM.IsSized a asize,- LLVM.IsSized b bsize) =>+ (TypeNum.NaturalT n,+ Storable a, MakeValueTuple a, ValueTuple a ~ LLVM.Value a,+ Memory.FirstClass a, LLVM.IsSized a, LLVM.IsSized (Memory.Stored a)) => n -> T (PCS.T Int a) (LLVM.Value (LLVM.Array n a)) controllerSet n = case storableVector of@@ -225,7 +229,7 @@ LLVM.getElementPtr arrPtr (i, ()) return (len1, s1))) length3 <- A.dec length2- arr <- LLVM.load =<< LLVM.bitcastUnify arrPtr+ arr <- LLVM.load =<< LLVM.bitcast arrPtr return (arr, (length3, s2))) (\((_, initialTime), param) -> do state <- start param@@ -244,9 +248,9 @@ bt) -- FIXME: handle memory exhaustion- arr <- Array.mallocArray (TypeNum.toInt n)+ arr <- Array.mallocArray (TypeNum.fromIntegerT n) flip mapM_ (Map.toList $ PCS.initial pcs) $ \(i,a) ->- if i >= TypeNum.toInt n+ if i >= TypeNum.fromIntegerT n then error "Plug.Input.controllerSet: array too small" else pokeElemOff arr i a
src/Synthesizer/LLVM/Plug/Output.hs view
@@ -1,20 +1,18 @@ {-# LANGUAGE NoImplicitPrelude #-}-{-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE ExistentialQuantification #-} {-# LANGUAGE Rank2Types #-}-{-# LANGUAGE MultiParamTypeClasses #-}-{-# LANGUAGE FunctionalDependencies #-}-{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE TypeFamilies #-}+{-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE UndecidableInstances #-} module Synthesizer.LLVM.Plug.Output where import qualified Synthesizer.Zip as Zip import qualified LLVM.Extra.Memory as Memory+import qualified LLVM.Extra.Class as Class import qualified LLVM.Extra.Arithmetic as A import qualified LLVM.Core as LLVM-import LLVM.Extra.Class (MakeValueTuple, ) import Control.Monad (liftM2, ) @@ -26,26 +24,25 @@ import Foreign.Storable.Tuple () import Foreign.Storable (Storable, ) +import qualified System.Unsafe as Unsafe+ import NumericPrelude.Numeric import NumericPrelude.Base hiding (and, iterate, map, zip, zipWith, take, takeWhile, ) data T a b =- forall state packed size ioContext- paramTuple paramValue paramPacked paramSize.+ forall state ioContext paramTuple. (Storable paramTuple,- MakeValueTuple paramTuple paramValue,- Memory.C paramValue paramPacked,- LLVM.IsSized paramPacked paramSize,- Memory.C state packed,- LLVM.IsSized packed size) =>+ Class.MakeValueTuple paramTuple,+ Memory.C (Class.ValueTuple paramTuple),+ Memory.C state) => Cons (forall r.- paramValue ->+ Class.ValueTuple paramTuple -> a -> state -> LLVM.CodeGenFunction r state) -- compute next value (forall r.- paramValue ->+ Class.ValueTuple paramTuple -> LLVM.CodeGenFunction r state) -- initial state (Int -> IO (ioContext, paramTuple))@@ -53,28 +50,29 @@ This is called once per output chunk with the number of input samples. This number is also the maximum possible number of output samples.- This will be run within unsafePerformIO,+ This will be run within Unsafe.performIO, so no observable In/Out actions please! -} (Int -> ioContext -> IO b) {-- finalization from IO monad, also run within unsafePerformIO+ finalization from IO monad, also run within Unsafe.performIO The integer argument is the actually produced size of data. We must clip the allocated output vectors accordingly. -} -class Default a b | b -> a where- deflt :: T a b+class Default b where+ type Element b :: *+ deflt :: T (Element b) b -instance- (Default a c, Default b d) =>- Default (a,b) (Zip.T c d) where+instance (Default c, Default d) => Default (Zip.T c d) where+ type Element (Zip.T c d) = (Element c, Element d) deflt = split deflt deflt instance- (Storable a, MakeValueTuple a value, Memory.C value struct) =>- Default value (SV.Vector a) where+ (Storable a, Class.MakeValueTuple a, Memory.C (Class.ValueTuple a)) =>+ Default (SV.Vector a) where+ type Element (SV.Vector a) = Class.ValueTuple a deflt = storableVector @@ -100,7 +98,8 @@ storableVector ::- (Storable a, MakeValueTuple a value, Memory.C value struct) =>+ (Class.MakeValueTuple a, value ~ Class.ValueTuple a,+ Memory.C value, Storable a) => T value (SV.Vector a) storableVector = Cons (\ _ a p ->@@ -112,7 +111,7 @@ let (fp,s,_l) = SVB.toForeignPtr vec return (vec, Memory.castStorablePtr $- FPtr.unsafeForeignPtrToPtr fp `Array.advancePtr` s))+ Unsafe.foreignPtrToPtr fp `Array.advancePtr` s)) (\len vec -> do let (fp,_s,_l) = SVB.toForeignPtr vec -- keep the foreign ptr alive
src/Synthesizer/LLVM/Random.hs view
@@ -1,3 +1,4 @@+{-# LANGUAGE TypeFamilies #-} {- | Very simple random number generator according to Knuth which should be fast and should suffice for generating just noise.@@ -18,7 +19,8 @@ zext, trunc, lshr, value, valueOf, vector, undef, constOf, constVector, bitcast, ) import qualified LLVM.Core as LLVM-import qualified Data.TypeLevel.Num as TypeNum+import qualified Types.Data.Bool as TypeBool+import qualified Types.Data.Num as TypeNum import Data.Function.HT (nest, ) @@ -119,7 +121,7 @@ fromIntegral $ nest n next 1 vectorSeed ::- (TypeNum.Pos n) =>+ (TypeNum.IntegerT n, TypeNum.IsPositive n ~ TypeBool.True) => Word32 -> Vector n Word32 vectorSeed seed = let n = Vector.size $ valueOf v@@ -130,7 +132,7 @@ vector64 = id nextVector ::- (TypeNum.Pos n) =>+ (TypeNum.PositiveT n) => Value (Vector n Word32) -> CodeGenFunction r (Value (Vector n Word32)) nextVector s =@@ -261,7 +263,7 @@ (constVector $ map constOf [0,2]) splitVector31to64 ::- (TypeNum.Pos n) =>+ (TypeNum.PositiveT n) => Value (Vector n Word64) -> CodeGenFunction r (Value (Vector n Word64), Value (Vector n Word64)) splitVector31to64 x = do@@ -313,7 +315,7 @@ as in the approach that is implemented here. -} nextVectorGeneric ::- (TypeNum.Pos n) =>+ (TypeNum.PositiveT n) => Value (Vector n Word32) -> CodeGenFunction r (Value (Vector n Word32)) nextVectorGeneric s = do@@ -362,7 +364,7 @@ otherwise select corresponding elements from the second vector. -} selectNonNegativeGeneric ::- (TypeNum.Pos n) =>+ (TypeNum.PositiveT n) => Value (Vector n Int32) -> Value (Vector n Int32) -> CodeGenFunction r (Value (Vector n Int32))@@ -372,7 +374,7 @@ splitVector31 ::- (TypeNum.Pos n) =>+ (TypeNum.PositiveT n) => Value (Vector n Word64) -> CodeGenFunction r (Value (Vector n Word32), Value (Vector n Word32)) splitVector31 x = do@@ -385,7 +387,7 @@ but unfortunately calls the expensive __umoddi3. -} nextVector64 ::- (TypeNum.Pos n) =>+ (TypeNum.PositiveT n) => Value (Vector n Word32) -> CodeGenFunction r (Value (Vector n Word32)) nextVector64 s =
src/Synthesizer/LLVM/RingBuffer.hs view
@@ -1,4 +1,5 @@ {-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE TypeFamilies #-} module Synthesizer.LLVM.RingBuffer ( T, track, index, oldest,@@ -14,7 +15,7 @@ import qualified LLVM.Extra.Class as Class import qualified LLVM.Core as LLVM-import LLVM.Core (CodeGenFunction, Value, IsSized, )+import LLVM.Core (CodeGenFunction, Value, ) import Data.Word (Word32, ) import Foreign.Storable.Tuple ()@@ -39,9 +40,8 @@ then the minimum index is zero and the maximum index is @time@. -} index ::- (Memory.C al ap,- IsSized ap as) =>- Value Word32 -> T ap -> CodeGenFunction r al+ (Memory.C a) =>+ Value Word32 -> T (Memory.Struct a) -> CodeGenFunction r a index i rb = do k <- flip A.irem (length rb) =<< A.add (current rb) i Memory.load =<< LLVM.getElementPtr (buffer rb) (k, ())@@ -52,9 +52,8 @@ this is equivalent to @index time@ but more efficient. -} oldest ::- (Memory.C al ap,- IsSized ap as) =>- T ap -> CodeGenFunction r al+ (Memory.C a) =>+ T (Memory.Struct a) -> CodeGenFunction r a oldest rb = Memory.load =<< LLVM.getElementPtr (buffer rb) (oldest_ rb, ()) @@ -72,10 +71,9 @@ -} track :: (Storable a,- Class.MakeValueTuple a al,- Memory.C al ap,- IsSized ap as) =>- Param.T p a -> Param.T p Int -> CausalP.T p al (T ap)+ Class.MakeValueTuple a, Class.ValueTuple a ~ al,+ Memory.C al) =>+ Param.T p a -> Param.T p Int -> CausalP.T p al (T (Memory.Struct al)) track initial time = let time32 = fmap (fromIntegral :: Int -> Word32) time in CausalP.Cons
− src/Synthesizer/LLVM/SerialVector.hs
@@ -1,17 +0,0 @@-{- |-A special vector type that represents a time-sequence of samples.-This way we can distinguish safely between LLVM vectors-used for parallel signals and pipelines and-those used for chunky processing of scalar signals.-For the chunky processing this data type allows us-to derive the factor from the type-that time constants have to be multiplied with.--}-module Synthesizer.LLVM.SerialVector where--import qualified Data.TypeLevel.Num.Sets as TypeSet-import qualified LLVM.Core as LLVM---replicate :: (TypeSet.Pos n) => a -> LLVM.Vector n a-replicate x = LLVM.vector [x]
− src/Synthesizer/LLVM/Server.hs
@@ -1,69 +0,0 @@-module Main where--import qualified Synthesizer.LLVM.Server.CausalPacked.Test as ServerCausalTest-import qualified Synthesizer.LLVM.Server.CausalPacked.Run as ServerCausal-import qualified Synthesizer.LLVM.Server.Packed.Test as ServerPackedTest-import qualified Synthesizer.LLVM.Server.Packed.Run as ServerPacked-import qualified Synthesizer.LLVM.Server.Scalar.Test as ServerScalarTest-import qualified Synthesizer.LLVM.Server.Scalar.Run as ServerScalar--import qualified LLVM.Core as LLVM---part :: Int-part = 106--main :: IO ()-main =- LLVM.initializeNativeTarget >>- case part of- 000 -> ServerScalar.pitchBend- 001 -> ServerScalar.frequencyModulation- 002 -> ServerScalar.keyboard- 003 -> ServerScalar.keyboardStereo- 004 -> ServerScalar.keyboardMulti- 005 -> ServerScalar.keyboardStereoMulti- 100 -> ServerPacked.frequencyModulation- 101 -> ServerPacked.keyboard- 102 -> ServerPacked.keyboardStereo- 103 -> ServerPacked.keyboardFM- 104 -> ServerPacked.keyboardFMMulti- 105 -> ServerPacked.keyboardDetuneFM- 106 -> ServerPacked.keyboardFilter -- there is still a leak when playing for a long time with arcStrings- 150 -> ServerCausal.keyboard- 151 -> ServerCausal.keyboardFM- 152 -> ServerCausal.keyboardDetuneFM- 153 -> ServerCausal.keyboardMultiChannel- 200 -> ServerScalarTest.pitchBend0- 201 -> ServerScalarTest.pitchBend1- 202 -> ServerScalarTest.pitchBend2- 203 -> ServerScalarTest.sequencePress- 300 -> ServerPackedTest.adsr- 301 -> ServerPackedTest.sequencePlain- 302 -> ServerPackedTest.sequenceLLVM- 303 -> ServerPackedTest.sequencePitchBendCycle- 304 -> ServerPackedTest.sequencePitchBendSimple- 305 -> ServerPackedTest.sequencePitchBend- 306 -> ServerPackedTest.sequenceModulated- 307 -> ServerPackedTest.sequencePress- 308 -> ServerPackedTest.sequenceModulatedLong- 309 -> ServerPackedTest.sequenceModulatedLongFM- 310 -> ServerPackedTest.sequenceModulatedRepeat- 311 -> ServerPackedTest.sequenceSample- 312 -> ServerPackedTest.sequenceSample1 -- leak--- 313 -> ServerPackedTest.testSequenceSample1a -- leak- 320 -> ServerPackedTest.sequenceSample2 -- leak- 321 -> ServerPackedTest.sequenceSample3 -- leak- 322 -> ServerPackedTest.sequenceSample4 -- leak- 323 -> ServerPackedTest.sequenceFM1 -- leak- 324 -> ServerPackedTest.bellNoiseStereoTest- 400 -> ServerCausalTest.render- 401 -> ServerCausalTest.sequenceNothing- 402 -> ServerCausalTest.sequenceSingleLong- 403 -> ServerCausalTest.sequenceSingleShort- 404 -> ServerCausalTest.sequenceLoop- 405 -> ServerCausalTest.sequenceStaccato- 406 -> ServerCausalTest.sequenceControlled- 407 -> ServerCausalTest.sequenceControlledModulated- 408 -> ServerCausalTest.sampledSound- _ -> error "not implemented server part"
+ src/Synthesizer/LLVM/Server/CausalPacked/Arrange.hs view
@@ -0,0 +1,427 @@+module Synthesizer.LLVM.Server.CausalPacked.Arrange where++import Synthesizer.LLVM.Server.CommonPacked (VectorSize, Vector, VectorValue, stair, )++import qualified Sound.MIDI.Controller as Ctrl++import qualified Synthesizer.LLVM.Server.CausalPacked.Speech as Speech+import qualified Synthesizer.LLVM.Server.CausalPacked.Instrument as Instr+import qualified Synthesizer.LLVM.Server.SampledSound as Sample+import Synthesizer.LLVM.Server.Common++import qualified Synthesizer.MIDI.CausalIO.ControllerSet as MCS+import qualified Synthesizer.MIDI.CausalIO.Process as MIO+import qualified Synthesizer.CausalIO.Process as PIO+import qualified Synthesizer.PiecewiseConstant.Signal as PC++import qualified Synthesizer.LLVM.Plug.Output as POut+import qualified Synthesizer.LLVM.CausalParameterized.Process as CausalP+import qualified Synthesizer.LLVM.CausalParameterized.ProcessPacked as CausalPS+import qualified Synthesizer.LLVM.Storable.Process as CausalSt++import qualified Synthesizer.LLVM.Frame.StereoInterleaved as StereoInt+import qualified Synthesizer.LLVM.Frame.Stereo as Stereo+import qualified Synthesizer.LLVM.Frame.SerialVector as Serial++import qualified Data.EventList.Relative.TimeTime as EventListTT++import qualified Data.StorableVector as SV++import qualified Synthesizer.Zip as Zip++import qualified Synthesizer.MIDI.Dimensional.ValuePlain as MV+import qualified Sound.MIDI.Message.Channel.Voice as VoiceMsg+import qualified Sound.MIDI.Message.Channel as ChannelMsg+import qualified Sound.MIDI.Message.Class.Check as Check++import Control.Arrow (Arrow, (<<<), (<<^), (^<<), arr, first, )+import Control.Category (id, )+import Control.Monad (guard, )++import qualified Data.List.HT as ListHT++import qualified Data.Map as Map++import qualified Number.DimensionTerm as DN+import qualified Algebra.DimensionTerm as Dim++import qualified Algebra.Transcendental as Trans++{-+import qualified Numeric.NonNegative.Chunky as NonNegChunky+import qualified Numeric.NonNegative.Class as NonNeg+-}+import qualified Numeric.NonNegative.Wrapper as NonNegW++import Prelude hiding (Real, id, )++++type StereoVector = StereoInt.T VectorSize Real+++keyboard ::+ (Check.C msg) =>+ IO (ChannelMsg.Channel ->+ SampleRate Real ->+ PIO.T (MIO.Events msg) (SV.Vector Vector))+keyboard = do+ arrange <- CausalSt.makeArranger+ amp <- CausalP.processIO (CausalPS.amplify 0.2)++ ping <- Instr.pingRelease++ return $ \ chan sampleRate ->+ amp ()+ <<<+ arrange+ <<<+ arr shortTime+ <<<+ MIO.sequenceCore chan+ (\ _pgm -> ping 0.8 0.1 sampleRate)+++infixr 3 &+&++(&+&) ::+ (Arrow arrow) =>+ arrow a b -> arrow a c -> arrow a (Zip.T b c)+(&+&) = Zip.arrowFanout+++controllerExponentialDirect ::+ (Check.C msg, Trans.C y, Dim.C v) =>+ ChannelMsg.Channel ->+ VoiceMsg.Controller ->+ (DN.T v y, DN.T v y) ->+ DN.T v y ->+ PIO.T (MIO.Events msg) (Instr.Control (DN.T v y))+controllerExponentialDirect chan ctrl bnds initial =+ MIO.slice+ (Check.controller chan ctrl)+ (MV.controllerExponential bnds)+ initial++shortTime ::+ EventListTT.T PC.StrictTime body ->+ EventListTT.T PC.ShortStrictTime body+shortTime =+ EventListTT.mapTime+ (NonNegW.fromNumberUnsafe . fromInteger . NonNegW.toNumber)++keyboardFM ::+ (Check.C msg, POut.Default b) =>+ CausalP.T () (Stereo.T VectorValue) (POut.Element b) ->+ ChannelMsg.Channel ->+ IO (SampleRate Real -> PIO.T (MIO.Events msg) b)+keyboardFM emitStereo chan = do+ arrange <- CausalSt.makeArranger+ amp <-+ CausalP.processIO+ (emitStereo <<< CausalPS.amplifyStereo 0.2)++ ping <- Instr.pingStereoReleaseFM++ return $ \ sampleRate ->+ amp ()+ <<<+ arrange+ <<<+ arr shortTime+ <<<+ -- ToDo: fetch parameters from controllers+ MIO.sequenceModulated chan+ (\ _pgm -> ping sampleRate)+ <<<+ id &+&+ ((controllerExponentialDirect chan+ Ctrl.attackTime (DN.time 0.25, DN.time 2.5) (DN.time 0.8)+ &+&+ controllerExponentialDirect chan+ Ctrl.releaseTime (DN.time 0.03, DN.time 0.3) (DN.time 0.1))+ &+&+ ((MIO.controllerExponential chan controllerTimbre0 (1/pi,0.01) 0.05+ &+&+ controllerExponentialDirect chan controllerTimbre1+ (DN.time 0.01, DN.time 10)+ (DN.time 5))+ &+&+ ((MIO.controllerLinear chan Ctrl.soundController5 (0,2) 1+ &+&+ controllerExponentialDirect chan Ctrl.soundController7+ (DN.time 0.25, DN.time 2.5)+ (DN.time 0.8))+ &+&+ (MIO.controllerLinear chan controllerDetune (0,0.005) 0.001+ &+&+ MIO.bendWheelPressure chan 2 0.04 0.03))))+++controllerExponentialDim ::+ (Arrow arrow,+ Trans.C y, Dim.C v) =>+ VoiceMsg.Controller ->+ (DN.T v y, DN.T v y) ->+ DN.T v y ->+ MCS.T arrow (DN.T v y)+controllerExponentialDim ctrl bnds initial =+ MCS.slice+ (MCS.Controller ctrl)+ (MV.controllerExponential bnds)+ initial+++keyboardDetuneFMCore ::+ (Check.C msg, POut.Default b) =>+ CausalP.T () (Stereo.T VectorValue) (POut.Element b) ->+ FilePath ->+ IO (ChannelMsg.Channel -> VoiceMsg.Program ->+ SampleRate Real -> PIO.T (MIO.Events msg) b)+keyboardDetuneFMCore emitStereo smpDir = do+ arrange <- CausalSt.makeArranger+ amp <-+ CausalP.processIO+ (emitStereo <<<+ CausalP.envelopeStereo <<<+ first (CausalP.mapSimple Serial.upsample))++ tine <- Instr.tineStereoFM+ ping <- Instr.pingStereoReleaseFM+ filterSaw <- Instr.filterSawStereoFM+ bellNoise <- Instr.bellNoiseStereoFM++ wind <- Instr.wind+ windPhaser <- Instr.windPhaser+ string <- Instr.softStringShapeFM+ fmString <- Instr.fmStringStereoFM+ arcs <- sequence $+ Instr.cosineStringStereoFM :+ Instr.arcSawStringStereoFM :+ Instr.arcSineStringStereoFM :+ Instr.arcSquareStringStereoFM :+ Instr.arcTriangleStringStereoFM :+ []++ tmt0 <- Instr.makeSampledSounds smpDir Sample.tomatensalat+ hal0 <- Instr.makeSampledSounds smpDir Sample.hal+ grp0 <- Instr.makeSampledSounds smpDir Sample.graphentheorie++ let timeControlPercussive =+ controllerExponentialDim Ctrl.attackTime+ (DN.time 0.1, DN.time 2.5) (DN.time 0.8)+ &+&+ controllerExponentialDim Ctrl.releaseTime+ (DN.time 0.03, DN.time 0.3) (DN.time 0.1)++ timeControlString =+ controllerExponentialDim Ctrl.attackTime+ (DN.time 0.005, DN.time 0.1) (DN.time 0.1)+ &+&+ controllerExponentialDim Ctrl.releaseTime+ (DN.time 0.03, DN.time 0.3) (DN.time 0.2)++ frequencyControlPercussive =+ MCS.controllerLinear controllerDetune (0,0.005) 0.001+ &+&+ MCS.bendWheelPressure 2 0.04 0.03++ frequencyControlString =+ MCS.controllerLinear controllerDetune (0,0.01) 0.005+ &+&+ MCS.bendWheelPressure 2 0.04 0.03++ let tineProc rate vel freq =+ tine rate vel freq+ <<<+ Zip.arrowSecond+ (timeControlPercussive+ &+&+ (((fmap stair ^<<+ MCS.controllerLinear controllerTimbre0 (0.5,6.5) 2)+ &+&+ MCS.controllerLinear controllerTimbre1 (0,1.5) 1)+ &+&+ frequencyControlPercussive))++ pingProc rate vel freq =+ ping rate vel freq+ <<<+ Zip.arrowSecond+ (timeControlPercussive+ &+&+ ((MCS.controllerExponential controllerTimbre0 (1/pi,10) 0.05+ &+&+ controllerExponentialDim controllerTimbre1+ (DN.time 0.01, DN.time 10) (DN.time 5))+ &+&+ ((MCS.controllerLinear Ctrl.soundController5 (0,10) 2+ &+&+ controllerExponentialDim Ctrl.soundController7+ (DN.time 0.03, DN.time 1) (DN.time 0.5))+ &+&+ frequencyControlPercussive)))++ filterSawProc rate vel freq =+ filterSaw rate vel freq+ <<<+ Zip.arrowSecond+ (timeControlPercussive+ &+&+ ((controllerExponentialDim controllerTimbre0+ (DN.frequency 100, DN.frequency 10000)+ (DN.frequency 1000)+ &+&+ controllerExponentialDim controllerTimbre1+ (DN.time 0.1, DN.time 1)+ (DN.time 0.6))+ &+&+ frequencyControlPercussive))++ bellNoiseProc rate vel freq =+ bellNoise rate vel freq+ <<<+ Zip.arrowSecond+ (timeControlPercussive+ &+&+ ((MCS.controllerLinear controllerTimbre0 (0,1) 0.3+ &+&+ MCS.controllerExponential controllerTimbre1 (1,1000) 100)+ &+&+ frequencyControlPercussive))++ windProc rate vel freq =+ wind rate vel freq+ <<<+ Zip.arrowSecond+ (timeControlString+ &+&+ (MCS.controllerExponential controllerTimbre1 (1,1000) 100+ &+&+ MCS.bendWheelPressure 12 0.8 0))++ windPhaserProc rate vel freq =+ windPhaser rate vel freq+ <<<+ Zip.arrowSecond+ (timeControlString+ &+&+ (MCS.controllerLinear controllerTimbre0 (0,1) 0.5+ &+&+ (controllerExponentialDim controllerDetune+ (DN.frequency 50, DN.frequency 5000) (DN.frequency 500)+ &+&+ (MCS.controllerExponential controllerTimbre1 (1,1000) 100+ &+&+ MCS.bendWheelPressure 12 0.8 0))))++ stringProc rate vel freq =+ string rate vel freq+ <<<+ Zip.arrowSecond+ (timeControlString+ &+&+ (MCS.controllerExponential controllerTimbre0 (1/pi,10) 0.05+ &+&+ frequencyControlString))++ fmStringProc rate vel freq =+ fmString rate vel freq+ <<<+ Zip.arrowSecond+ (timeControlString+ &+&+ ((MCS.controllerLinear controllerTimbre0 (0,0.5) 0.2+ &+&+ MCS.controllerExponential controllerTimbre1 (1/pi,10) 0.05)+ &+&+ frequencyControlString))++ makeArc proc rate vel freq =+ proc rate vel freq+ <<<+ Zip.arrowSecond+ (timeControlString+ &+&+ (MCS.controllerLinear controllerTimbre0 (0.5,9.5) 1.5+ &+&+ frequencyControlString))++ sampled smp rate vel freq =+ smp rate vel freq+ <<<+ Zip.arrowSecond frequencyControlPercussive++ bank =+ Map.fromAscList $ zip [VoiceMsg.toProgram 0 ..] $+ [tineProc, pingProc, filterSawProc, bellNoiseProc,+ stringProc, fmStringProc] +++ map makeArc arcs ++ windProc : windPhaserProc :+ map sampled (tmt0 ++ hal0 ++ grp0)++ return $ \chan initPgm rate ->+ amp ()+ <<<+ (MCS.controllerExponential controllerVolume (0.001, 1) (0.2::Float)+ <<^ Zip.second)+ &+&+ (arrange+ <<<+ arr shortTime+ <<<+ MIO.sequenceModulatedMultiProgram chan initPgm+ (\pgm -> Map.findWithDefault pingProc pgm bank rate))+ <<<+ id &+& MCS.fromChannel chan+++data Phoneme = Phoneme Bool VoiceMsg.Pitch++instance Check.C Phoneme where+ note _chan (Phoneme on p) =+ Just (VoiceMsg.normalVelocity, p, on)+++voderSplit ::+ (Check.C msg, Arrow arrow) =>+ ChannelMsg.Channel ->+ arrow+ (MIO.Events msg)+ (Zip.T+ (MIO.Events Phoneme)+ (MIO.Events msg))+voderSplit chan =+ arr $+ uncurry Zip.Cons .+ EventListTT.unzip .+ fmap (ListHT.partitionMaybe $ \ev -> do+ (_v,p,b) <- Check.note chan ev+ guard $ p < VoiceMsg.toPitch 53+ return $ Phoneme b p)++voder ::+ (Check.C msg, POut.Default b) =>+ CausalP.T () (Stereo.T VectorValue) (POut.Element b) ->+ FilePath ->+ IO (ChannelMsg.Channel -> VoiceMsg.Program ->+ SampleRate Real -> PIO.T (MIO.Events msg) b)+voder emitStereo smpDir = do+ carrier <- keyboardDetuneFMCore id smpDir+ voice <- Speech.phoneme+ arrange <- CausalSt.makeArranger+ interleave <- CausalP.processIO emitStereo++ return $ \chan initPgm sampleRate ->+ interleave ()+ <<<+ arrange+ <<<+ arr shortTime+ <<<+ MIO.sequenceModulatedMultiProgramVelocityPitch+ chan (VoiceMsg.toProgram 0)+ (\ _pgm _vel -> voice sampleRate)+ <<<+ Zip.arrowSecond (carrier chan initPgm sampleRate)+ <<<+ voderSplit chan
src/Synthesizer/LLVM/Server/CausalPacked/Instrument.hs view
@@ -1,17 +1,24 @@ {-# LANGUAGE NoImplicitPrelude #-} {-# LANGUAGE Rank2Types #-}+{- |+This module contains some instruments with Causal arrow interface.+The interface is a bit low-level+since you have to write the transformations of the Haskell-side+separately from the computations on the LLVM side.+A nicer integration is used in+"Synthesizer.LLVM.Server.CausalPacked.InstrumentPlug".+However, we preserve this module in order to show+how things work internally.+-} module Synthesizer.LLVM.Server.CausalPacked.Instrument where -import Synthesizer.LLVM.Server.Packed.Instrument- (Vector, vectorTime, vectorSize,- SampleInfo, SampledSound(..), loadSound,- sampleStart, sampleLength,- sampleLoopStart, sampleLoopLength,- stereoNoise, noiseReference, sumNested, )+import Synthesizer.LLVM.Server.Packed.Instrument (stereoNoise, )+import Synthesizer.LLVM.Server.CommonPacked import Synthesizer.LLVM.Server.Common hiding (Instrument, ) +import qualified Synthesizer.LLVM.Server.SampledSound as Sample import qualified Synthesizer.LLVM.Storable.Process as PSt-import qualified Synthesizer.CausalIO.ALSA.Process as PAlsa+import qualified Synthesizer.MIDI.CausalIO.Process as MIO import qualified Synthesizer.CausalIO.Gate as Gate import qualified Synthesizer.CausalIO.Process as PIO @@ -22,6 +29,7 @@ import qualified Synthesizer.LLVM.Generator.Exponential2 as Exp import qualified Synthesizer.LLVM.Frame.Stereo as Stereo import qualified Synthesizer.LLVM.Frame as Frame+import qualified Synthesizer.LLVM.Frame.SerialVector as Serial import qualified Synthesizer.LLVM.CausalParameterized.Functional as F import qualified Synthesizer.LLVM.CausalParameterized.ControlledPacked as CtrlPS import qualified Synthesizer.LLVM.CausalParameterized.ProcessPacked as CausalPS@@ -31,8 +39,8 @@ import qualified Synthesizer.LLVM.Parameter as Param import qualified Synthesizer.LLVM.Wave as WaveL -import qualified Synthesizer.LLVM.ALSA.BendModulation as BM-import qualified Synthesizer.LLVM.ALSA.MIDI as MIDIL+import qualified Synthesizer.LLVM.MIDI.BendModulation as BM+import qualified Synthesizer.LLVM.MIDI as MIDIL import qualified Synthesizer.PiecewiseConstant.Signal as PC import qualified Synthesizer.Generic.Cut as CutG import qualified Synthesizer.Zip as Zip@@ -44,61 +52,50 @@ import System.FilePath ((</>), ) -import qualified LLVM.Extra.ScalarOrVector as SoV import qualified LLVM.Extra.Arithmetic as A import qualified LLVM.Extra.Monad as LM import qualified LLVM.Core as LLVM -import qualified Data.TypeLevel.Num as TypeNum+import qualified Types.Data.Num as TypeNum import qualified Data.Traversable as Trav-import Control.Arrow (Arrow, arr, first, second, (&&&), (***), (<<^), (^<<), )+import Control.Arrow (Arrow, arr, first, second, (&&&), (<<^), (^<<), ) import Control.Category (id, (.), ) import Control.Monad (liftM2, liftM3, (<=<), )-import Control.Applicative (Applicative, pure, liftA2, liftA3, )+import Control.Applicative (pure, liftA2, liftA3, ) import Data.Monoid (mappend, )-import Data.Tuple.HT (swap, mapPair, ) import qualified Number.DimensionTerm as DN -{--import qualified Numeric.NonNegative.Class as NonNeg-import qualified Numeric.NonNegative.Wrapper as NonNegW-import qualified Numeric.NonNegative.Chunky as NonNegChunky--}-import qualified Algebra.Additive as Additive- import NumericPrelude.Numeric import NumericPrelude.Base hiding (id, (.), ) -type Param p = Param.T (SampleRate Real, p)-type CausalP p = CausalP.T (SampleRate Real, p)--type Instrument a sig = SampleRate a -> PAlsa.Instrument a sig+type Instrument a sig = SampleRate a -> MIO.Instrument a sig type Control = EventListBT.T PC.ShortStrictTime type Time = DN.Time Real type Frequency = DN.Frequency Real +type BendModControl = Control (BM.T Real)+type DetuneBendModControl = Zip.T (Control Real) (Control (BM.T Real)) +type PIOId a = PIO.T a a++ stereoFrequenciesFromDetuneBendModulation :: Param p Real ->- CausalP p- (LLVM.Value Real, BM.T (LLVM.Value Real))- (Stereo.T (LLVM.Value Vector))-stereoFrequenciesFromDetuneBendModulation speed =- CausalP.envelopeStereo- .- (MIDIL.frequencyFromBendModulationPacked speed- ***- CausalP.mapSimple (Trav.mapM SoV.replicate)- .- liftA2 Stereo.cons (one + id) (one - id))- .- arr swap+ (FuncP p inp (LLVM.Value Real),+ FuncP p inp (BM.T (LLVM.Value Real))) ->+ FuncP p inp (Stereo.T VectorValue)+stereoFrequenciesFromDetuneBendModulation speed (detune, freq) =+ CausalP.envelopeStereo $&+ (MIDIL.frequencyFromBendModulationPacked speed $& freq)+ &|&+ (CausalP.mapSimple (Trav.mapM Serial.upsample) $&+ liftA2 Stereo.cons (one + detune) (one - detune)) frequencyFromSampleRate :: SampleRate a -> DN.Frequency a@@ -123,21 +120,13 @@ takeThreshold :: Param.T p Real ->- CausalP.T p (LLVM.Value Vector) (LLVM.Value Vector)+ CausalP.T p VectorValue VectorValue takeThreshold = CausalP.takeWhile (\threshold y ->- A.cmp LLVM.CmpLE threshold =<< Frame.subsampleVector y)+ A.cmp LLVM.CmpLE threshold =<< Serial.subsample y) -liftStereo ::- (Applicative f) =>- (f a -> f b) -> f (Stereo.T a) -> f (Stereo.T b)-liftStereo proc freqs =- liftA2 Stereo.cons- (proc $ fmap Stereo.left freqs)- (proc $ fmap Stereo.right freqs)- fanoutShorten :: (CutG.Transform a, CutG.Transform b, CutG.Transform c) => PIO.T a b -> PIO.T a c -> PIO.T a (Zip.T b c)@@ -146,22 +135,28 @@ Zip.arrowSecondShorten b . arr (\x -> Zip.Cons x x) ++type EnvelopeControl =+ Zip.T MIO.GateChunk+ (Zip.T (Control Time) (Control Time))++type WithEnvelopeControl remainder =+ Zip.T MIO.GateChunk+ (Zip.T+ (Zip.T (Control Time) (Control Time))+ remainder)+ reorderEnvelopeControl :: (Arrow arrow, CutG.Read remainder) => arrow- (Zip.T PAlsa.GateChunk- (Zip.T- (Zip.T (Control Time) (Control Time))- remainder))- (Zip.T- (Zip.T PAlsa.GateChunk- (Zip.T (Control Time) (Control Time)))- remainder)+ (WithEnvelopeControl remainder)+ (Zip.T EnvelopeControl remainder) reorderEnvelopeControl = arr $ \(Zip.Cons gate (Zip.Cons times ctrl)) -> Zip.consChecked "ping gate ctrl" (Zip.consChecked "ping gate times" gate times) ctrl + ping :: IO (Instrument Real (SV.Vector Vector)) ping = fmap (\proc sampleRate vel freq ->@@ -180,7 +175,7 @@ pingReleaseEnvelope :: IO (Real -> Real -> SampleRate Real -> Real ->- PIO.T PAlsa.GateChunk (SV.Vector Vector))+ PIO.T MIO.GateChunk (SV.Vector Vector)) pingReleaseEnvelope = liftM2 (\sustain release dec rel sr vel ->@@ -227,8 +222,7 @@ Maybe Real -> IO (SampleRate Real -> Real -> PIO.T- (Zip.T PAlsa.GateChunk- (Zip.T (Control Time) (Control Time)))+ EnvelopeControl (SV.Vector Vector)) pingControlledEnvelope threshold = liftM2@@ -258,31 +252,26 @@ pingStereoReleaseFM :: IO (SampleRate Real -> Real -> Real -> PIO.T- (Zip.T PAlsa.GateChunk+ (WithEnvelopeControl (Zip.T- (Zip.T (Control Time) (Control Time))+ (Zip.T (Control Real) (Control Time)) (Zip.T (Zip.T (Control Real) (Control Time))- (Zip.T- (Zip.T (Control Real) (Control Time))- (Zip.T (Control Real) (Control (BM.T Real)))))))+ DetuneBendModControl))) (SV.Vector (Stereo.T Vector))) pingStereoReleaseFM = liftA2 (\osc env sr vel freq -> osc (sr, ()) .- (Zip.arrowSecond $ Zip.arrowSecond $- Zip.arrowSecond $ Zip.arrowSecond $- arr $ transposeModulation sr freq)- .- (Zip.arrowSecond $ Zip.arrowSecond $- Zip.arrowFirst $ Zip.arrowSecond $- arr $ halfLifeControl sr)- .- (Zip.arrowSecond $- Zip.arrowFirst $ Zip.arrowSecond $- arr $ halfLifeControl sr)+ Zip.arrowSecond+ (Zip.arrowSplit+ (Zip.arrowSecond $ arr $ halfLifeControl sr)+ ((Zip.arrowSecond $ Zip.arrowSecond $+ arr $ transposeModulation sr freq)+ .+ (Zip.arrowFirst $ Zip.arrowSecond $+ arr $ halfLifeControl sr))) . Zip.arrowFirstShorten (env sr vel) .@@ -291,25 +280,21 @@ (CausalP.envelopeStereo . second- (let fm = F.lift (arr (snd.snd))- shape = F.lift (CausalP.mapSimple SoV.replicate . arr (fst.fst))- shapeDecay = F.lift (arr (snd.fst))+ (F.withArgs $ \((shape0,shapeDecay),((phase,phaseDecay),fm)) ->+ let shape = CausalP.mapSimple Serial.upsample $& shape0 shapeCtrl =- 1/3.14 + (shape-1/3.14) *+ 1/pi + (shape-1/pi) * (Exp.causalPackedP (1::Param.T p Real) $& shapeDecay) freqs = stereoFrequenciesFromDetuneBendModulation- (frequencyConst 10) $& fm- phase = F.lift (arr (fst.fst.snd))- phaseDecay = F.lift (arr (snd.fst.snd))+ (frequencyConst 10) fm expo =- (CausalP.mapSimple SoV.replicate $& phase) *+ (CausalP.mapSimple Serial.upsample $& phase) * (Exp.causalPackedP (1::Param.T p Real) $& phaseDecay) osci = CausalPS.shapeModOsci WaveL.rationalApproxSine1- in F.compile $- liftA2 Stereo.cons+ in liftA2 Stereo.cons (osci $& shapeCtrl &|& (expo &|& fmap Stereo.left freqs))- (osci $& shapeCtrl &|& (Additive.negate expo &|& fmap Stereo.right freqs)))))+ (osci $& shapeCtrl &|& (negate expo &|& fmap Stereo.right freqs))))) (pingControlledEnvelope (Just 0.01)) @@ -317,29 +302,23 @@ filterSawStereoFM :: IO (SampleRate Real -> Real -> Real -> PIO.T- (Zip.T PAlsa.GateChunk+ (WithEnvelopeControl (Zip.T- (Zip.T (Control Time) (Control Time))- (Zip.T- (Zip.T (Control Frequency) (Control Time))- (Zip.T (Control Real) (Control (BM.T Real))))))+ (Zip.T (Control Frequency) (Control Time))+ DetuneBendModControl)) (SV.Vector (Stereo.T Vector))) filterSawStereoFM = liftA2 (\osc env sr vel freq -> osc (sr, ()) .- (Zip.arrowSecond $ Zip.arrowSecond $- Zip.arrowSecond $- arr $ transposeModulation sr freq)- .- (Zip.arrowSecond $- Zip.arrowFirst $ Zip.arrowSecond $- arr $ halfLifeControl sr)- .- (Zip.arrowSecond $- Zip.arrowFirst $ Zip.arrowFirst $- arr $ frequencyControl sr)+ Zip.arrowSecond+ (Zip.arrowSplit+ (Zip.arrowSplit+ (arr $ frequencyControl sr)+ (arr $ halfLifeControl sr))+ (Zip.arrowSecond $+ arr $ transposeModulation sr freq)) . Zip.arrowFirstShorten (env sr vel) .@@ -348,27 +327,24 @@ (CausalP.envelopeStereo . second- (let fm = F.lift (arr snd)- cutoff = F.lift (CausalP.mapSimple SoV.replicate . arr (fst.fst))- cutoffDecay = F.lift (arr (snd.fst))- freqs =+ (F.withArgs $ \((cutoff,cutoffDecay),fm) ->+ let freqs = stereoFrequenciesFromDetuneBendModulation- (frequencyConst 10) $& fm+ (frequencyConst 10) fm {- bound control in order to avoid too low resonant frequency, which makes the filter instable -} expo = takeThreshold (frequencyConst 100) $&- (CausalP.mapSimple SoV.replicate $& cutoff) *+ (CausalP.mapSimple Serial.upsample $& cutoff) * (Exp.causalPackedP (1::Param.T p Real) $& cutoffDecay)- in F.compile $- CausalP.stereoFromMonoControlled+ in CausalP.stereoFromMonoControlled (UniFilter.lowpass ^<< CtrlPS.process) $& (CausalP.quantizeLift (100 / fromIntegral vectorSize :: Param.T p Real) (CausalP.mapSimple (UniFilter.parameter (LLVM.valueOf 10) <=<- Frame.subsampleVector))+ Serial.subsample)) $& expo) &|&@@ -380,12 +356,10 @@ tineStereoFM :: IO (SampleRate Real -> Real -> Real -> PIO.T- (Zip.T PAlsa.GateChunk+ (WithEnvelopeControl (Zip.T- (Zip.T (Control Time) (Control Time))- (Zip.T- (Zip.T (Control Real) (Control Real))- (Zip.T (Control Real) (Control (BM.T Real))))))+ (Zip.T (Control Real) (Control Real))+ DetuneBendModControl)) (SV.Vector (Stereo.T Vector))) tineStereoFM = liftA2@@ -403,13 +377,13 @@ (CausalP.envelopeStereo . second- (let vel = number id- fm = F.lift (arr snd)+ (F.withArgs $ \((index0,depth0), fm) ->+ let vel = number id freqs = stereoFrequenciesFromDetuneBendModulation- (frequencyConst 5) $& fm- index = F.lift (CausalP.mapSimple SoV.replicate . arr (fst.fst))- depth = F.lift (CausalP.mapSimple SoV.replicate . arr (snd.fst))+ (frequencyConst 5) fm+ index = CausalP.mapSimple Serial.upsample $& index0+ depth = CausalP.mapSimple Serial.upsample $& depth0 expo = F.lift $ CausalP.fromSignal $ SigPS.exponential2 (timeConst 1) (1 + vel)@@ -420,19 +394,17 @@ $& zero &|& index*freq) &|& freq- in F.compile $ liftStereo osci freqs)))+ in Stereo.liftApplicative osci freqs))) (pingControlledEnvelope (Just 0.01)) bellNoiseStereoFM :: IO (SampleRate Real -> Real -> Real -> PIO.T- (Zip.T PAlsa.GateChunk+ (WithEnvelopeControl (Zip.T- (Zip.T (Control Time) (Control Time))- (Zip.T- (Zip.T (Control Real) (Control Real))- (Zip.T (Control Real) (Control (BM.T Real))))))+ (Zip.T (Control Real) (Control Real))+ DetuneBendModControl)) (SV.Vector (Stereo.T Vector))) bellNoiseStereoFM = liftA3@@ -448,9 +420,7 @@ (env sr (vel*0.5)) (let shortenTimes :: Real ->- PIO.T- (Zip.T (Control Time) (Control Time))- (Zip.T (Control Time) (Control Time))+ PIOId (Zip.T (Control Time) (Control Time)) shortenTimes n = let rn = recip n in (Zip.arrowFirst $ arr $ fmap $ DN.scale rn)@@ -466,12 +436,8 @@ . reorderEnvelopeControl) (CausalP.processIO- (let env1 = F.lift (arr (fst.fst))- env4 = F.lift (arr (fst.snd.fst))- env7 = F.lift (arr (snd.snd.fst))- fm = F.lift (arr (snd.snd))- noiseAmp = F.lift (CausalP.mapSimple SoV.replicate . arr (fst.fst.snd))- noiseReson = F.lift (arr (snd.fst.snd))+ (F.withArgs $ \((env1,(env4,env7)),((noiseAmp0,noiseReson),fm)) ->+ let noiseAmp = CausalP.mapSimple Serial.upsample $& noiseAmp0 noiseParam = CausalP.quantizeLift (100 / fromIntegral vectorSize :: Param.T p Real)@@ -482,7 +448,7 @@ (SigPS.noise 12 (noiseReference 20000))) freqs = stereoFrequenciesFromDetuneBendModulation- (frequencyConst 5) $& fm+ (frequencyConst 5) fm osci amp env n = CausalPS.amplifyStereo amp $& CausalP.envelopeStereo $&@@ -494,15 +460,14 @@ CausalPS.amplifyStereo n $& freqs)- in F.compile $- (CausalP.envelopeStereo $&+ in (CausalP.envelopeStereo $& (noiseAmp * env1) &|&- liftStereo+ Stereo.liftApplicative (\freq -> CtrlPS.process $& (noiseParam $& noiseReson &|&- (CausalP.mapSimple Frame.subsampleVector $& freq))+ (CausalP.mapSimple Serial.subsample $& freq)) &|& noise) freqs)@@ -516,10 +481,7 @@ stringControlledEnvelope :: IO (SampleRate Real -> Real ->- PIO.T- (Zip.T PAlsa.GateChunk- (Zip.T (Control Time) (Control Time)))- (SV.Vector Vector))+ PIO.T EnvelopeControl (SV.Vector Vector)) stringControlledEnvelope = liftM3 (\attack sustain release sr vel ->@@ -558,11 +520,11 @@ windCore :: F.T (SampleRate Real, p) a (LLVM.Value Real) -> F.T (SampleRate Real, p) a (BM.T (LLVM.Value Real)) ->- F.T (SampleRate Real, p) a (Stereo.T (LLVM.Value Vector))+ F.T (SampleRate Real, p) a (Stereo.T VectorValue) windCore reson fm = let modu =- CausalP.mapSimple Frame.subsampleVector $&- (fmap (`asTypeOf` (undefined :: LLVM.Value Vector)) $+ CausalP.mapSimple Serial.subsample $&+ (fmap (`asTypeOf` (undefined :: VectorValue)) $ (MIDIL.frequencyFromBendModulationPacked (frequencyConst 0.2) $& fm)) in CausalP.stereoFromMonoControlled CtrlPS.process $&@@ -575,10 +537,7 @@ wind :: IO (SampleRate Real -> Real -> Real -> PIO.T- (Zip.T PAlsa.GateChunk- (Zip.T- (Zip.T (Control Time) (Control Time))- (Zip.T (Control Real) (Control (BM.T Real)))))+ (WithEnvelopeControl DetuneBendModControl) (SV.Vector (Stereo.T Vector))) wind = liftA2@@ -592,11 +551,7 @@ . reorderEnvelopeControl) (CausalP.processIO- (let env = F.lift (arr fst)- reson = F.lift (arr (fst.snd))- fm = F.lift (arr (snd.snd))-- in F.compile $+ (F.withArgs $ \(env,(reson,fm)) -> CausalP.envelopeStereo $& env &|& windCore reson fm))@@ -606,12 +561,9 @@ windPhaser :: IO (SampleRate Real -> Real -> Real -> PIO.T- (Zip.T PAlsa.GateChunk- (Zip.T- (Zip.T (Control Time) (Control Time))- (Zip.T (Control Real)- (Zip.T (Control Frequency)- (Zip.T (Control Real) (Control (BM.T Real)))))))+ (WithEnvelopeControl+ (Zip.T (Control Real)+ (Zip.T (Control Frequency) DetuneBendModControl))) (SV.Vector (Stereo.T Vector))) windPhaser = liftA2@@ -619,28 +571,21 @@ osc (sr, ()) . (Zip.arrowSecond $ Zip.arrowSecond $- Zip.arrowSecond $ Zip.arrowSecond $- arr $ transposeModulation sr freq)- .- (Zip.arrowSecond $ Zip.arrowSecond $- Zip.arrowFirst $- arr $ fmap (Allpass.flangerParameterPlain TypeNum.d8) .- frequencyControl sr)+ Zip.arrowSplit+ (arr $ fmap (Allpass.flangerParameterPlain TypeNum.d8) .+ frequencyControl sr)+ (Zip.arrowSecond $+ arr $ transposeModulation sr freq)) . Zip.arrowFirstShorten (env sr vel) . reorderEnvelopeControl) (CausalP.processIO- (let env = F.lift (arr fst)- phaserMix =- F.lift (CausalP.mapSimple SoV.replicate . arr (fst.snd))- phaserFreq = F.lift (arr (fst.snd.snd))- reson = F.lift (arr (fst.snd.snd.snd))- fm = F.lift (arr (snd.snd.snd.snd))+ (F.withArgs $ \(env,(phaserMix0,(phaserFreq,(reson,fm)))) ->+ let phaserMix = CausalP.mapSimple Serial.upsample $& phaserMix0 noise = windCore reson fm - in F.compile $- CausalP.envelopeStereo $&+ in CausalP.envelopeStereo $& env &|& ((CausalP.envelopeStereo $& (1 - phaserMix) &|& noise) +@@ -652,8 +597,8 @@ phaserOsci ::- (Param.T p Real -> Param.T p Real -> CausalP.T p a (LLVM.Value Vector)) ->- CausalP.T p a (Stereo.T (LLVM.Value Vector))+ (Param.T p Real -> Param.T p Real -> CausalP.T p a VectorValue) ->+ CausalP.T p a (Stereo.T VectorValue) phaserOsci osci = CausalPS.amplifyStereo 0.25 .@@ -667,19 +612,15 @@ StringInstrument = SampleRate Real -> Real -> Real -> PIO.T- (Zip.T PAlsa.GateChunk- (Zip.T- (Zip.T (Control Time) (Control Time))- (Zip.T- (Control Real)- (Zip.T (Control Real) (Control (BM.T Real))))))+ (WithEnvelopeControl+ (Zip.T (Control Real) DetuneBendModControl)) (SV.Vector (Stereo.T Vector)) softStringShapeCore :: (forall r.- LLVM.Value Vector ->- LLVM.Value Vector ->- LLVM.CodeGenFunction r (LLVM.Value Vector)) ->+ VectorValue ->+ VectorValue ->+ LLVM.CodeGenFunction r VectorValue) -> IO StringInstrument softStringShapeCore wave = liftA2@@ -697,9 +638,9 @@ (CausalP.envelopeStereo . second- (let fm = F.lift (arr (snd.snd))- det = F.lift (CausalP.mapSimple SoV.replicate . arr (fst.snd))- shape = F.lift (CausalP.mapSimple SoV.replicate . arr fst)+ (F.withArgs $ \(shape0,(det0,fm)) ->+ let det = CausalP.mapSimple Serial.upsample $& det0+ shape = CausalP.mapSimple Serial.upsample $& shape0 modu = MIDIL.frequencyFromBendModulationPacked (frequencyConst 5) $& fm@@ -707,11 +648,11 @@ Param.T (mod,fm) Real -> Param.T (mod,fm) Real -> CausalP.T (mod,fm)- (LLVM.Value Vector,+ (VectorValue, {- wave shape parameter -}- (LLVM.Value Vector, LLVM.Value Vector)+ (VectorValue, VectorValue) {- detune, frequency modulation -})- (LLVM.Value Vector)+ VectorValue osci p d = CausalPS.shapeModOsci wave .@@ -722,14 +663,13 @@ . first (one + CausalPS.amplify d)) - in F.compile $- phaserOsci osci $& shape &|& det &|& modu)))+ in phaserOsci osci $& shape &|& det &|& modu))) stringControlledEnvelope arcStringStereoFM :: (forall r.- LLVM.Value Vector ->- LLVM.CodeGenFunction r (LLVM.Value Vector)) ->+ VectorValue ->+ LLVM.CodeGenFunction r VectorValue) -> IO StringInstrument arcStringStereoFM wave = softStringShapeCore@@ -756,12 +696,10 @@ fmStringStereoFM :: IO (SampleRate Real -> Real -> Real -> PIO.T- (Zip.T PAlsa.GateChunk+ (WithEnvelopeControl (Zip.T- (Zip.T (Control Time) (Control Time))- (Zip.T- (Zip.T (Control Real) (Control Real))- (Zip.T (Control Real) (Control (BM.T Real))))))+ (Zip.T (Control Real) (Control Real))+ DetuneBendModControl)) (SV.Vector (Stereo.T Vector))) fmStringStereoFM = liftA2@@ -776,14 +714,13 @@ . reorderEnvelopeControl) (CausalP.processIO- (let env = F.lift (arr fst)- fm = F.lift (arr (snd.snd.snd))- det = F.lift (CausalP.mapSimple SoV.replicate . arr (fst.snd.snd))- shape = F.lift (CausalP.mapSimple SoV.replicate . arr (snd.fst.snd))+ (F.withArgs $ \(env,((depth0,shape0),(det0,fm))) ->+ let det = CausalP.mapSimple Serial.upsample $& det0+ shape = CausalP.mapSimple Serial.upsample $& shape0 depth = CausalP.envelope $& env &|&- F.lift (CausalP.mapSimple SoV.replicate . arr (fst.fst.snd))+ (CausalP.mapSimple Serial.upsample $& depth0) modu = MIDIL.frequencyFromBendModulationPacked (frequencyConst 5) $& fm@@ -792,11 +729,11 @@ Param.T (mod,fm) Real -> Param.T (mod,fm) Real -> CausalP.T (mod,fm)- ((LLVM.Value Vector, LLVM.Value Vector)+ ((VectorValue, VectorValue) {- phase modulation depth, modulator distortion -},- (LLVM.Value Vector, LLVM.Value Vector)+ (VectorValue, VectorValue) {- detune, frequency modulation -})- (LLVM.Value Vector)+ VectorValue osci p d = CausalPS.osciSimple WaveL.approxSine2 .@@ -813,8 +750,7 @@ (CausalP.envelope . first (one + CausalPS.amplify d)) - in F.compile $- CausalP.envelopeStereo $&+ in CausalP.envelopeStereo $& env &|& (phaserOsci osci $& (depth &|& shape) &|& (det &|& modu)))) stringControlledEnvelope@@ -822,11 +758,10 @@ sampledSound ::- IO (SampledSound ->+ IO (Sample.T -> SampleRate Real -> Real -> Real -> PIO.T- (Zip.T PAlsa.GateChunk- (Zip.T (Control Real) (Control (BM.T Real))))+ (Zip.T MIO.GateChunk DetuneBendModControl) (SV.Vector (Stereo.T Vector))) sampledSound = liftA2@@ -837,36 +772,25 @@ Without (periodic) frequency modulation we could just split the piecewise constant control curve @fm@. -}- let pos = samplePositions smp+ let pos = Sample.positions smp amp = 2 * amplitudeFromVelocity vel- (attack,sustain) =- mapPair- (SigSt.drop (sampleStart pos),- SigSt.take (sampleLoopLength pos)) $- SigSt.splitAt (sampleLoopStart pos) $- sampleData smp- release =- SigSt.drop (sampleLoopStart pos + sampleLoopLength pos) $- SigSt.take (sampleStart pos + sampleLength pos) $- sampleData smp+ (attack, sustain, release) = Sample.parts smp osci smpBody = osc (sr, (amp, smpBody)) in mappend (osci (attack `SigSt.append`- SVL.cycle (SigSt.take (sampleLoopLength pos) sustain))+ SVL.cycle (SigSt.take (Sample.loopLength pos) sustain)) . Gate.shorten) (osci release <<^ Zip.second) . Zip.arrowSecond- ((id :: PIO.T- (SV.Vector (Stereo.T Vector))- (SV.Vector (Stereo.T Vector)))+ ((id :: PIOId (SV.Vector (Stereo.T Vector))) . freqMod (sr, ()) . (Zip.arrowSecond $ arr $- transposeModulation sr (freq * samplePeriod smp))))+ transposeModulation sr (freq * Sample.period smp)))) (CausalP.processIO (let amp = number fst smp = signal snd@@ -882,20 +806,87 @@ (SigP.fromStorableVectorLazy smp) {- (SigP.osciSimple WaveL.saw 0 (1 / 324 {- samplePeriod smp -})) -})))) (CausalP.processIO- (stereoFrequenciesFromDetuneBendModulation (frequencyConst 3)))+ (F.withArgs $ stereoFrequenciesFromDetuneBendModulation (frequencyConst 3))) makeSampledSounds :: FilePath ->- SampleInfo ->+ Sample.Info -> IO [SampleRate Real -> Real -> Real -> PIO.T- (Zip.T PAlsa.GateChunk- (Zip.T (Control Real) (Control (BM.T Real))))+ (Zip.T MIO.GateChunk DetuneBendModControl) (SV.Vector (Stereo.T Vector))] makeSampledSounds dir (file, positions, period) = do liftA2 (\makeSmp smp ->- map (\pos -> makeSmp (SampledSound smp pos period))+ map (\pos -> makeSmp (Sample.Cons smp pos period)) positions) sampledSound- (loadSound (dir </> file))+ (Sample.load (dir </> file))+++{- |+mainly for testing purposes+-}+sampledSoundMono ::+ IO (Sample.T ->+ SampleRate Real -> Real -> Real ->+ PIO.T+ (Zip.T MIO.GateChunk BendModControl)+ (SV.Vector Vector))+sampledSoundMono =+ liftA2+ (\osc freqMod smp sr vel freq ->+ {-+ We split the frequency modulation signal+ in order to get a smooth frequency modulation curve.+ Without (periodic) frequency modulation+ we could just split the piecewise constant control curve @fm@.+ -}+ let pos = Sample.positions smp+ amp = 2 * amplitudeFromVelocity vel+ (attack, sustain, release) = Sample.parts smp+ osci smpBody = osc (sr, (amp, smpBody))+ in mappend+ (osci+ (attack `SigSt.append`+ SVL.cycle (SigSt.take (Sample.loopLength pos) sustain))+ .+ Gate.shorten)+ (osci release <<^ Zip.second)+ .+ Zip.arrowSecond+ ((id :: PIOId (SV.Vector Vector))+ .+ freqMod (sr, ())+ .+ (arr $ transposeModulation sr (freq * Sample.period smp))))+ (CausalP.processIO+ (let amp = number fst+ smp = signal snd+ in CausalPS.amplify amp+ .+ CausalPS.pack+ (CausalP.frequencyModulationLinear+ {-+ (SigP.fromStorableVector $+ fmap (SV.concat . SVL.chunks . SVL.take 1000000) smp)+ -}+ (SigP.fromStorableVectorLazy smp)+ {- (SigP.osciSimple WaveL.saw 0 (1 / 324 {- samplePeriod smp -})) -})))+ (CausalP.processIO+ (MIDIL.frequencyFromBendModulationPacked (frequencyConst 3)))++makeSampledSoundsMono ::+ FilePath ->+ Sample.Info ->+ IO [SampleRate Real -> Real -> Real ->+ PIO.T+ (Zip.T MIO.GateChunk BendModControl)+ (SV.Vector Vector)]+makeSampledSoundsMono dir (file, positions, period) = do+ liftA2+ (\makeSmp smp ->+ map (\pos -> makeSmp (Sample.Cons smp pos period))+ positions)+ sampledSoundMono+ (Sample.load (dir </> file))
+ src/Synthesizer/LLVM/Server/CausalPacked/InstrumentPlug.hs view
@@ -0,0 +1,102 @@+{-# LANGUAGE NoImplicitPrelude #-}+{-# LANGUAGE Rank2Types #-}+{- |+The Instruments in this module have the same causal arrow interface+as the ones in "Synthesizer.LLVM.Server.CausalPacked.Instrument",+but here we use the higher level interface+of the "Synthesizer.LLVM.CausalParameterized.FunctionalPlug" module.+-}+module Synthesizer.LLVM.Server.CausalPacked.InstrumentPlug where++import Synthesizer.LLVM.Server.CausalPacked.Instrument (+ Control, DetuneBendModControl,+ WithEnvelopeControl,+ pingControlledEnvelope,+ reorderEnvelopeControl, )+import Synthesizer.LLVM.Server.CommonPacked (+ Param, Vector, VectorValue, )+import Synthesizer.LLVM.Server.Common (+ SampleRate, Real,+ frequencyConst, timeConst,+ number, transposeModulation, )++import qualified Synthesizer.CausalIO.Process as PIO++import Synthesizer.LLVM.CausalParameterized.FunctionalPlug (($&), (&|&), )+import qualified Synthesizer.LLVM.Frame.Stereo as Stereo+import qualified Synthesizer.LLVM.Frame.SerialVector as Serial+import qualified Synthesizer.LLVM.CausalParameterized.FunctionalPlug as FP+import qualified Synthesizer.LLVM.CausalParameterized.ProcessPacked as CausalPS+import qualified Synthesizer.LLVM.CausalParameterized.Process as CausalP+import qualified Synthesizer.LLVM.Parameterized.SignalPacked as SigPS+import qualified Synthesizer.LLVM.Wave as WaveL++import qualified Synthesizer.LLVM.MIDI.BendModulation as BM+import qualified Synthesizer.LLVM.MIDI as MIDIL+import qualified Synthesizer.Zip as Zip++import qualified Data.StorableVector as SV++import qualified LLVM.Core as LLVM++import qualified Data.Traversable as Trav+import Control.Category (id, (.), )+import Control.Applicative (liftA2, )++import NumericPrelude.Numeric+import NumericPrelude.Base hiding (id, (.), )+++type FuncP pp pl = FP.T pp (SampleRate Real, pl)+++stereoFrequenciesFromDetuneBendModulation ::+ Param pl Real ->+ (FuncP pp pl inp (LLVM.Value Real),+ FuncP pp pl inp (BM.T (LLVM.Value Real))) ->+ FuncP pp pl inp (Stereo.T VectorValue)+stereoFrequenciesFromDetuneBendModulation speed (detune, freq) =+ CausalP.envelopeStereo $&+ (MIDIL.frequencyFromBendModulationPacked speed $& freq)+ &|&+ (CausalP.mapSimple (Trav.mapM Serial.upsample) $&+ liftA2 Stereo.cons (one + detune) (one - detune))++tineStereoFM ::+ IO (SampleRate Real -> Real -> Real ->+ PIO.T+ (WithEnvelopeControl+ (Zip.T+ (Zip.T (Control Real) (Control Real))+ DetuneBendModControl))+ (SV.Vector (Stereo.T Vector)))+tineStereoFM =+ liftA2+ (\osc env sr vel freq ->+ osc (sr, freq) (sr, vel)+ .+ Zip.arrowFirstShorten (env sr vel)+ .+ reorderEnvelopeControl)+ (FP.withArgs $ \(env, ((index0,depth0), (detune,fm))) ->+ let vel = number id+ freqs =+ stereoFrequenciesFromDetuneBendModulation+ (frequencyConst 5)+ (FP.plug detune,+ FP.plug $ liftA2 (uncurry transposeModulation) FP.askParameter fm)+ index = CausalP.mapSimple Serial.upsample $& FP.plug index0+ depth = CausalP.mapSimple Serial.upsample $& FP.plug depth0+ expo =+ FP.fromSignal $+ SigPS.exponential2 (timeConst 1) (1 + vel)+ osci freq =+ CausalPS.osciSimple WaveL.approxSine2 $&+ expo * depth *+ (CausalPS.osciSimple WaveL.approxSine2+ $& zero &|& index*freq)+ &|&+ freq+ in CausalP.envelopeStereo $&+ FP.plug env &|& Stereo.liftApplicative osci freqs)+ (pingControlledEnvelope (Just 0.01))
− src/Synthesizer/LLVM/Server/CausalPacked/Run.hs
@@ -1,424 +0,0 @@-module Synthesizer.LLVM.Server.CausalPacked.Run where--import Synthesizer.LLVM.Server.Packed.Run- (StereoVector,- controllerVolume, controllerDetune,- controllerTimbre0, controllerTimbre1, )-import qualified Sound.MIDI.Controller as Ctrl--import qualified Synthesizer.LLVM.Server.CausalPacked.Instrument as Instr-import qualified Synthesizer.LLVM.Server.Packed.Instrument as InstrP-import qualified Synthesizer.LLVM.Server.Packed.Run as RunP-import qualified Synthesizer.LLVM.Server.Option as Option-import Synthesizer.LLVM.Server.Common--import qualified Sound.ALSA.Sequencer.Event as Event-import qualified Synthesizer.EventList.ALSA.MIDI as Ev--import qualified Synthesizer.CausalIO.ALSA.MIDIControllerSet as MCS-import qualified Synthesizer.CausalIO.ALSA.Process as PAlsa-import qualified Synthesizer.CausalIO.Process as PIO--import qualified Synthesizer.LLVM.CausalParameterized.ProcessPacked as CausalPS-import qualified Synthesizer.LLVM.CausalParameterized.Process as CausalP-import qualified Synthesizer.LLVM.Storable.Process as CausalSt-import qualified Synthesizer.LLVM.Storable.Signal as SigStL-import Synthesizer.LLVM.Parameterized.Signal (($#), )--import qualified Synthesizer.LLVM.Frame.StereoInterleaved as StereoInt--import qualified LLVM.Extra.ScalarOrVector as SoV--import qualified Data.StorableVector as SV--import qualified Data.EventList.Relative.TimeTime as EventListTT---- import qualified Synthesizer.LLVM.ALSA.BendModulation as BM-import qualified Synthesizer.Zip as Zip--import qualified Sound.ALSA.PCM as PCM--import qualified Synthesizer.Dimensional.MIDIValuePlain as MV-import qualified Sound.MIDI.Message.Channel.Voice as VoiceMsg-import qualified Sound.MIDI.Message.Channel as ChannelMsg-import qualified Sound.MIDI.ALSA.Check as Check--import Control.Arrow (Arrow, (<<<), (<<^), (^<<), (***), arr, first, )-import Control.Category (id, )--import qualified Data.Map as Map-{--import Data.Tuple.HT (mapPair, fst3, snd3, thd3, )--}--import qualified Number.DimensionTerm as DN-import qualified Algebra.DimensionTerm as Dim--import qualified Algebra.Transcendental as Trans-import qualified Algebra.Additive as Additive--{--import qualified Numeric.NonNegative.Class as NonNeg-import qualified Numeric.NonNegative.Chunky as NonNegChunky--}-import qualified Numeric.NonNegative.Wrapper as NonNegW--import Prelude hiding (Real, id, )-----playFromEvents ::- (PCM.SampleFmt a, Additive.C a) =>- Option.T ->- PIO.T (EventListTT.T Ev.StrictTime [Event.T]) (SV.Vector a) ->- IO ()-playFromEvents opt =- PAlsa.playFromEvents- (Option.device opt)- (Option.clientName opt)- 0.01- (Option.periodTime opt::Double)- (case Option.sampleRate opt of- SampleRate sr -> fromInteger sr)--keyboard :: IO ()-keyboard = do- opt <- Option.get- arrange <- CausalSt.makeArranger- amp <- CausalP.processIO (CausalPS.amplify $# 0.2)-- ping <- Instr.pingRelease-- playFromEvents opt $- arr SigStL.unpackStrict- <<<- amp ()- <<<- arrange- <<<- arr (EventListTT.mapTime- (NonNegW.fromNumberUnsafe . fromInteger . NonNegW.toNumber))- <<<- PAlsa.sequenceCore- (Option.channel opt)- (\ _pgm -> ping 0.8 0.1 (Option.sampleRate opt))---infixr 3 &+&--(&+&) ::- (Arrow arrow) =>- arrow a b -> arrow a c -> arrow a (Zip.T b c)-(&+&) = Zip.arrowFanout--controllerExponentialDirect ::- (Trans.C y, Dim.C v) =>- Option.T ->- VoiceMsg.Controller ->- (DN.T v y, DN.T v y) ->- DN.T v y ->- PIO.T PAlsa.Events (Instr.Control (DN.T v y))-controllerExponentialDirect opt ctrl bnds initial =- PAlsa.slice- (Check.controller (Option.channel opt) ctrl)- (MV.controllerExponential bnds)- initial--keyboardFM :: IO ()-keyboardFM = do- opt <- Option.get- arrange <- CausalSt.makeArranger- amp <-- CausalP.processIO- (CausalP.mapSimple StereoInt.interleave <<<- (CausalPS.amplifyStereo $# 0.2))-- ping <- Instr.pingStereoReleaseFM-- playFromEvents opt $- arr SigStL.unpackStereoStrict- <<<- amp ()- <<<- arrange- <<<- arr (EventListTT.mapTime- (NonNegW.fromNumberUnsafe . fromInteger . NonNegW.toNumber))- <<<- -- ToDo: fetch parameters from controllers- PAlsa.sequenceModulated- (Option.channel opt)- (\ _pgm -> ping (Option.sampleRate opt))- <<<- id &+&- ((controllerExponentialDirect opt- Ctrl.attackTime (DN.time 0.25, DN.time 2.5) (DN.time 0.8)- &+&- controllerExponentialDirect opt- Ctrl.releaseTime (DN.time 0.03, DN.time 0.3) (DN.time 0.1))- &+&- ((PAlsa.controllerExponential (Option.channel opt) controllerTimbre0 (1/pi,0.01) 0.05- &+&- controllerExponentialDirect opt controllerTimbre1- (DN.time 0.01, DN.time 10)- (DN.time 5))- &+&- ((PAlsa.controllerLinear (Option.channel opt) Ctrl.soundController5 (0,2) 1- &+&- controllerExponentialDirect opt Ctrl.soundController7- (DN.time 0.25, DN.time 2.5)- (DN.time 0.8))- &+&- (PAlsa.controllerLinear (Option.channel opt) controllerDetune (0,0.005) 0.001- &+&- PAlsa.bendWheelPressure (Option.channel opt) 2 0.04 0.03))))---controllerExponentialDim ::- (Arrow arrow,- Trans.C y, Dim.C v) =>- VoiceMsg.Controller ->- (DN.T v y, DN.T v y) ->- DN.T v y ->- MCS.T arrow (DN.T v y)-controllerExponentialDim ctrl bnds initial =- MCS.slice- (MCS.Controller ctrl)- (MV.controllerExponential bnds)- initial--keyboardDetuneFMCore ::- FilePath ->- IO (ChannelMsg.Channel -> VoiceMsg.Program ->- SampleRate Real ->- PIO.T- (EventListTT.T Ev.StrictTime [Event.T])- (SV.Vector StereoVector))-keyboardDetuneFMCore smpDir = do- arrange <- CausalSt.makeArranger- amp <-- CausalP.processIO- (CausalP.mapSimple StereoInt.interleave <<<- CausalP.envelopeStereo <<<- first (CausalP.mapSimple SoV.replicate))-- tine <- Instr.tineStereoFM- ping <- Instr.pingStereoReleaseFM- filterSaw <- Instr.filterSawStereoFM- bellNoise <- Instr.bellNoiseStereoFM-- wind <- Instr.wind- windPhaser <- Instr.windPhaser- string <- Instr.softStringShapeFM- fmString <- Instr.fmStringStereoFM- arcs <- sequence $- Instr.cosineStringStereoFM :- Instr.arcSawStringStereoFM :- Instr.arcSineStringStereoFM :- Instr.arcSquareStringStereoFM :- Instr.arcTriangleStringStereoFM :- []-- tmt0 <- Instr.makeSampledSounds smpDir InstrP.tomatensalat- hal0 <- Instr.makeSampledSounds smpDir InstrP.hal- grp0 <- Instr.makeSampledSounds smpDir InstrP.graphentheorie-- let timeControlPercussive =- controllerExponentialDim Ctrl.attackTime- (DN.time 0.1, DN.time 2.5) (DN.time 0.8)- &+&- controllerExponentialDim Ctrl.releaseTime- (DN.time 0.03, DN.time 0.3) (DN.time 0.1)-- timeControlString =- controllerExponentialDim Ctrl.attackTime- (DN.time 0.005, DN.time 0.1) (DN.time 0.1)- &+&- controllerExponentialDim Ctrl.releaseTime- (DN.time 0.03, DN.time 0.3) (DN.time 0.2)-- frequencyControlPercussive =- MCS.controllerLinear controllerDetune (0,0.005) 0.001- &+&- MCS.bendWheelPressure 2 0.04 0.03-- frequencyControlString =- MCS.controllerLinear controllerDetune (0,0.01) 0.005- &+&- MCS.bendWheelPressure 2 0.04 0.03-- let tineProc rate vel freq =- tine rate vel freq- <<<- Zip.arrowSecond- (timeControlPercussive- &+&- (((fmap RunP.stair ^<<- MCS.controllerLinear controllerTimbre0 (0.5,6.5) 2)- &+&- MCS.controllerLinear controllerTimbre1 (0,1.5) 1)- &+&- frequencyControlPercussive))-- pingProc rate vel freq =- ping rate vel freq- <<<- Zip.arrowSecond- (timeControlPercussive- &+&- ((MCS.controllerExponential controllerTimbre0 (1/pi,10) 0.05- &+&- controllerExponentialDim controllerTimbre1- (DN.time 0.01, DN.time 10) (DN.time 5))- &+&- ((MCS.controllerLinear Ctrl.soundController5 (0,10) 2- &+&- controllerExponentialDim Ctrl.soundController7- (DN.time 0.03, DN.time 1) (DN.time 0.5))- &+&- frequencyControlPercussive)))-- filterSawProc rate vel freq =- filterSaw rate vel freq- <<<- Zip.arrowSecond- (timeControlPercussive- &+&- ((controllerExponentialDim controllerTimbre0- (DN.frequency 100, DN.frequency 10000)- (DN.frequency 1000)- &+&- controllerExponentialDim controllerTimbre1- (DN.time 0.1, DN.time 1)- (DN.time 0.6))- &+&- frequencyControlPercussive))-- bellNoiseProc rate vel freq =- bellNoise rate vel freq- <<<- Zip.arrowSecond- (timeControlPercussive- &+&- ((MCS.controllerLinear controllerTimbre0 (0,1) 0.3- &+&- MCS.controllerExponential controllerTimbre1 (1,1000) 100)- &+&- frequencyControlPercussive))-- windProc rate vel freq =- wind rate vel freq- <<<- Zip.arrowSecond- (timeControlString- &+&- (MCS.controllerExponential controllerTimbre1 (1,1000) 100- &+&- MCS.bendWheelPressure 12 0.8 0))-- windPhaserProc rate vel freq =- windPhaser rate vel freq- <<<- Zip.arrowSecond- (timeControlString- &+&- (MCS.controllerLinear controllerTimbre0 (0,1) 0.5- &+&- (controllerExponentialDim controllerDetune- (DN.frequency 50, DN.frequency 5000) (DN.frequency 500)- &+&- (MCS.controllerExponential controllerTimbre1 (1,1000) 100- &+&- MCS.bendWheelPressure 12 0.8 0))))-- stringProc rate vel freq =- string rate vel freq- <<<- Zip.arrowSecond- (timeControlString- &+&- (MCS.controllerExponential controllerTimbre0 (1/pi,10) 0.05- &+&- frequencyControlString))-- fmStringProc rate vel freq =- fmString rate vel freq- <<<- Zip.arrowSecond- (timeControlString- &+&- ((MCS.controllerLinear controllerTimbre0 (0,0.5) 0.2- &+&- MCS.controllerExponential controllerTimbre1 (1/pi,10) 0.05)- &+&- frequencyControlString))-- makeArc proc rate vel freq =- proc rate vel freq- <<<- Zip.arrowSecond- (timeControlString- &+&- (MCS.controllerLinear controllerTimbre0 (0.5,9.5) 1.5- &+&- frequencyControlString))-- sampled smp rate vel freq =- smp rate vel freq- <<<- Zip.arrowSecond frequencyControlPercussive-- bank =- Map.fromAscList $ zip [VoiceMsg.toProgram 0 ..] $- [tineProc, pingProc, filterSawProc, bellNoiseProc,- stringProc, fmStringProc] ++- map makeArc arcs ++ windProc : windPhaserProc :- map sampled (tmt0 ++ hal0 ++ grp0)-- return $ \chan initPgm rate ->- amp ()- <<<- (MCS.controllerExponential controllerVolume (0.001, 1) (0.2::Float)- <<^ Zip.second)- &+&- (arrange- <<<- arr (EventListTT.mapTime- (NonNegW.fromNumberUnsafe . fromInteger . NonNegW.toNumber))- <<<- PAlsa.sequenceModulatedMultiProgram chan initPgm- (\pgm -> Map.findWithDefault pingProc pgm bank rate))- <<<- id &+& MCS.fromChannel chan--keyboardDetuneFM :: IO ()-keyboardDetuneFM = do- opt <- Option.get- proc <- keyboardDetuneFMCore (Option.sampleDirectory opt)- playFromEvents opt $- arr SigStL.unpackStereoStrict- <<<- proc (Option.channel opt) (VoiceMsg.toProgram 0) (Option.sampleRate opt)--keyboardMultiChannel :: IO ()-keyboardMultiChannel = do- opt <- Option.get- proc <- keyboardDetuneFMCore (Option.sampleDirectory opt)- mix <-- CausalP.processIO $- CausalP.mapSimple StereoInt.interleave <<<- CausalP.mix <<<- CausalP.mapSimple StereoInt.deinterleave ***- CausalP.mapSimple StereoInt.deinterleave-- playFromEvents opt $- arr SigStL.unpackStereoStrict- <<<- foldl1- (\x y -> mix () <<< Zip.arrowFanout x y)- (map- (\chan ->- proc (ChannelMsg.toChannel chan) (VoiceMsg.toProgram 0)- (Option.sampleRate opt))- [0 .. 3])
+ src/Synthesizer/LLVM/Server/CausalPacked/Speech.hs view
@@ -0,0 +1,162 @@+{-# LANGUAGE NoImplicitPrelude #-}+module Synthesizer.LLVM.Server.CausalPacked.Speech where++import Synthesizer.LLVM.Server.CausalPacked.Instrument+ (Control, Frequency, frequencyControl, )+import Synthesizer.LLVM.Server.CommonPacked (Vector, VectorValue, )+import Synthesizer.LLVM.Server.Common (SampleRate, Real, frequency, )++import qualified Synthesizer.MIDI.CausalIO.Process as MIO+import qualified Synthesizer.CausalIO.Gate as Gate+import qualified Synthesizer.CausalIO.Process as PIO++import Synthesizer.LLVM.CausalParameterized.Process (($<), )+import Synthesizer.LLVM.CausalParameterized.FunctionalPlug (($&), (&|&), )+import qualified Synthesizer.LLVM.Frame.Stereo as Stereo+import qualified Synthesizer.LLVM.Frame.SerialVector as Serial+import qualified Synthesizer.LLVM.CausalParameterized.FunctionalPlug as FP+import qualified Synthesizer.LLVM.CausalParameterized.ControlledPacked as CtrlPS+import qualified Synthesizer.LLVM.CausalParameterized.Process as CausalP+import qualified Synthesizer.LLVM.Parameterized.Signal as SigP++import qualified Synthesizer.Zip as Zip+import qualified Sound.MIDI.Message.Channel.Voice as VoiceMsg++import qualified Synthesizer.PiecewiseConstant.Signal as PC++import qualified Synthesizer.Plain.Filter.Recursive.Universal as UniFilter+import Synthesizer.Plain.Filter.Recursive (Pole(Pole))++import qualified Data.StorableVector as SV++import qualified LLVM.Core as LLVM++import Control.Arrow (Arrow, arr, (^<<), )+import Control.Category ((.), )+import Control.Applicative (liftA, liftA3, )++import NumericPrelude.Numeric+import NumericPrelude.Base hiding (id, (.), )+++{-+stimmhaft+a, e, i, o, u, ä, ö, ü+l, m, n, ng++Diphtong+ai, oi, au, ui, ei++stimmlos/Zischlaute+f, h, w, s, sch, th, ch (weich), ch (kochen), r++explosiv+b, p, g, k, d, t+-}++{-+Formanten:+a - 700 Hz+i - 400 Hz, 2200 Hz+o - 600 Hz, 3000 Hz+f - white noise+sch - highpass cutoff 1500 Hz+-}++phoneme ::+ IO (SampleRate Real -> VoiceMsg.Pitch ->+ PIO.T (Zip.T MIO.GateChunk (SV.Vector (Stereo.T Vector)))+ (SV.Vector (Stereo.T Vector)))+phoneme =+ liftA+ (\osc sr p ->+ case formants p of+ Nothing -> arr $ const SV.empty+ Just fs ->+ osc (sr, fs)+ .+ Gate.shorten)+ (CausalP.processIO+ (CausalP.stereoFromMono+ (let lowpass q f =+ UniFilter.bandpass+ ^<<+ CtrlPS.process+ $<+ SigP.constant+ (UniFilter.parameter . Pole q ^<< frequency f)+ in lowpass 100 fst + lowpass 20 snd)))++formants :: VoiceMsg.Pitch -> Maybe (Real, Real)+formants p =+ case VoiceMsg.fromPitch p - 36 of+ 00 -> Just ( 320, 800) -- u+ 02 -> Just ( 500, 1000) -- o+ 04 -> Just (1000, 1400) -- a+ 05 -> Just (1500, 500) -- oe+ 07 -> Just (1650, 320) -- ue+ 09 -> Just (1800, 700) -- ae+ 11 -> Just (2300, 500) -- e+ 12 -> Just (3200, 320) -- i+ _ -> Nothing+++type Input a = FP.Input (SampleRate Real) a++plugUniFilterParameter ::+ Input a (Control Real) ->+ Input a (Control Frequency) ->+ FP.T (SampleRate Real) pl a (UniFilter.Parameter (LLVM.Value Real))+plugUniFilterParameter reson freq =+ FP.plug $+ liftA3+ (\resonChunk freqChunk sr ->+ PC.zipWith+ (\ r f -> UniFilter.parameter $ Pole r f)+ resonChunk $ frequencyControl sr freqChunk)+ reson freq FP.askParameter+++type FormantControl =+ Zip.T (Control Real)+ (Zip.T (Control Real) (Control Frequency))++singleFormant ::+ (Input inp (Control Real),+ (Input inp (Control Real), Input inp (Control Frequency))) ->+ Input inp (SV.Vector (Stereo.T Vector)) ->+ FP.T (SampleRate Real) pl inp (Stereo.T VectorValue)+singleFormant (amp, (reson, freq)) x =+ CausalP.envelopeStereo $&+ (CausalP.mapSimple Serial.upsample $& FP.plug amp)+ &|&+ (CausalP.stereoFromMonoControlled+ (UniFilter.bandpass ^<< CtrlPS.process) $&+ plugUniFilterParameter reson freq+ &|&+ FP.plug x)++filterFormant ::+ IO (SampleRate Real ->+ PIO.T+ (Zip.T FormantControl (SV.Vector (Stereo.T Vector)))+ (SV.Vector (Stereo.T Vector)))+filterFormant =+ liftA+ (\filt sr -> filt sr (sr, ()))+ (FP.withArgs $ \(fmt, x) -> singleFormant fmt x)++filterFormants ::+ IO (SampleRate Real ->+ PIO.T (Zip.T+ (Zip.T FormantControl+ (Zip.T FormantControl+ (Zip.T FormantControl+ (Zip.T FormantControl FormantControl))))+ (SV.Vector (Stereo.T Vector)))+ (SV.Vector (Stereo.T Vector)))+filterFormants =+ liftA+ (\filt sr -> filt sr (sr, ()))+ (FP.withArgs $ \((fmt0, (fmt1, (fmt2, (fmt3, fmt4)))), x) ->+ foldl1 (+) $ map (flip singleFormant x) [fmt0, fmt1, fmt2, fmt3, fmt4])
− src/Synthesizer/LLVM/Server/CausalPacked/Test.hs
@@ -1,346 +0,0 @@-module Synthesizer.LLVM.Server.CausalPacked.Test where--import qualified Synthesizer.LLVM.Server.CausalPacked.Instrument as Instr-import qualified Synthesizer.LLVM.Server.CausalPacked.Run as Run-import qualified Synthesizer.LLVM.Server.Packed.Instrument as InstrP-import qualified Synthesizer.LLVM.Server.Option as Option-import Synthesizer.LLVM.Server.Packed.Instrument- (vectorSize, )-import Synthesizer.LLVM.Server.Packed.Run- (controllerVolume, controllerDetune,- controllerTimbre0, controllerTimbre1, )-import Synthesizer.LLVM.Server.CausalPacked.Run ((&+&), )-import Synthesizer.LLVM.Server.Common hiding- (Instrument, )--import qualified Sound.ALSA.Sequencer.Event as Event--- import qualified Sound.ALSA.Sequencer.Connect as Connect-import qualified Sound.ALSA.Sequencer.Address as Addr-import qualified Synthesizer.Generic.ALSA.MIDI as Gen--import qualified Synthesizer.LLVM.Frame.StereoInterleaved as StereoInt--import qualified Sound.MIDI.Controller as Ctrl--import qualified Synthesizer.CausalIO.Gate as Gate-import qualified Synthesizer.Zip as Zip--import qualified Synthesizer.Storable.ALSA.Play as Play-import Synthesizer.Storable.ALSA.MIDI (Instrument, )--import qualified Synthesizer.PiecewiseConstant.ALSA.MIDIControllerSet as PCS-import qualified Synthesizer.CausalIO.ALSA.MIDIControllerSet as MCS-import qualified Synthesizer.CausalIO.ALSA.Process as PAlsa-import qualified Synthesizer.CausalIO.Process as PIO--import qualified Synthesizer.LLVM.CausalParameterized.Process as CausalP-import qualified Synthesizer.LLVM.Storable.Process as CausalSt-import qualified Synthesizer.LLVM.Storable.Signal as SigStL--import qualified LLVM.Extra.ScalarOrVector as SoV--import qualified Synthesizer.Storable.Cut as CutSt-import qualified Data.StorableVector.Lazy as SVL-import qualified Data.StorableVector as SV--import qualified Data.EventList.Relative.TimeBody as EventList-import qualified Data.EventList.Relative.TimeTime as EventListTT-import qualified Data.EventList.Relative.TimeMixed as EventListTM--import Control.Arrow ((<<<), (<<^), arr, first, )-import Control.Category (id, )-import Control.Monad.Trans.State (evalState, )--import qualified Data.Map as Map--import qualified Numeric.NonNegative.Class as NonNeg-import qualified Numeric.NonNegative.Wrapper as NonNegW--- import qualified Numeric.NonNegative.Chunky as NonNegChunky--import qualified Number.DimensionTerm as DN--import Algebra.IntegralDomain (divUp, )-{--import qualified Algebra.RealRing as RealRing-import qualified Algebra.Additive as Additive--}--import Data.Word (Word8, Word32, )-import Data.Int (Int32, )--import Foreign.Storable (Storable, )-import qualified System.IO as IO-import Control.Exception (bracket, )---- import NumericPrelude.Numeric (zero, round, (^?), )-import Prelude hiding (Real, round, break, id, )---vectorChunkSize :: SVL.ChunkSize-vectorChunkSize =- case Play.defaultChunkSize of- SVL.ChunkSize size ->- SVL.ChunkSize (divUp size vectorSize)--sampleRatePlain :: Num a => a-sampleRatePlain = Option.defaultSampleRate--sampleRate :: Option.SampleRate Real-sampleRate = Option.SampleRate Option.defaultSampleRate--{- |-try to reproduce a space leak--}-sequencePlain :: IO ()-sequencePlain =- SVL.writeFile "/tmp/test.f32" $--- print $ last $ SVL.chunks $- CutSt.arrange Option.defaultChunkSize $- evalState (Gen.sequence Option.defaultChannel (error "no sound" :: Instrument Real Real)) $- let evs = EventList.cons 10 [] evs- in evs---chopEvents ::- (NonNeg.C time, Num time) =>- time ->- EventListTT.T time body ->- [EventListTT.T time body]-chopEvents chunkSize =- let go evs =- let (chunk,rest) = EventListTT.splitAtTime chunkSize evs- in if EventListTT.duration chunk == 0- then []- else chunk : go rest- in go---- see playFromEvents-writeTest ::- (Storable a) =>- PIO.T t (SV.Vector a) -> [t] -> IO ()-writeTest (PIO.Cons next create delete) evsChunky =- IO.withFile "/tmp/test.f32" IO.WriteMode $ \h ->- bracket create delete $- let loop evs s0 =- case evs of- [] -> return ()- chunk : rest -> do- (pcm, s1) <- next chunk s0- SV.hPut h pcm- loop rest s1- in loop evsChunky--render :: IO ()-render = do- ping <- Instr.pingRelease $/ 1 $/ 0.1 -- leaky--- ping <- Instr.ping -- not leaky-- writeTest (ping sampleRate 10 440) $- replicate 10000 $ Gate.chunk 512 Nothing--sequenceEvents :: [PAlsa.Events] -> IO ()-sequenceEvents evs = do- arrange <- CausalSt.makeArranger-- ping <- Instr.pingRelease $/ 1 $/ 0.1 -- leaky--- ping <- Instr.ping -- not leaky-- let proc =- arrange- <<<- arr (EventListTT.mapTime- (NonNegW.fromNumberUnsafe . fromInteger . NonNegW.toNumber))- <<<- PAlsa.sequenceCore- Option.defaultChannel- (\ _pgm -> ping sampleRate)-- writeTest proc evs--sequenceNothing :: IO ()-sequenceNothing =- sequenceEvents $- let evs = EventList.cons 10 [] evs- in chopEvents 512 $ EventListTM.takeTime (10^(7::Int)) evs---noteEvent ::- Event.NoteEv ->- Word8 ->- Word8 ->- Word8 ->- Event.T-noteEvent mode chan pitch velocity =- -- Event.simple (Connect.toSubscribers Addr.subscribers) $- Event.simple Addr.subscribers $- Event.NoteEv mode $ Event.simpleNote chan pitch velocity--ctrlEvent ::- Word8 ->- Word32 ->- Int32 ->- Event.T-ctrlEvent chan cc cval =- -- Event.simple (Connect.toSubscribers Addr.subscribers) $- Event.simple Addr.subscribers $- Event.CtrlEv Event.Controller $- Event.Ctrl chan cc cval--sequenceSingleLong :: IO ()-sequenceSingleLong = do- sequenceEvents $- let evs = EventList.cons 10 [] evs- in chopEvents 512 $- EventListTM.takeTime (10^(7::Int)) $- EventList.cons 0 [noteEvent Event.NoteOn 0 60 64] evs--sequenceSingleShort :: IO ()-sequenceSingleShort = do- sequenceEvents $- let evs = EventList.cons 10 [] evs- in chopEvents 512 $- EventListTM.takeTime (10^(7::Int)) $- EventList.cons 0 [noteEvent Event.NoteOn 0 60 64] $- EventList.cons 10 [noteEvent Event.NoteOff 0 60 64] evs--{--Although it consumes constant memory,-the memory usage is quite high,-e.g. 40MB for chunk size 100000 and peiod 1100.-This might be caused by the large overlapping in the release phases.-You need only 6MB heap for the same chunksize and period 11000.--}-sequenceLoop :: IO ()-sequenceLoop = do- sequenceEvents $- let evs =- EventList.cons 11001- [noteEvent Event.NoteOff 0 60 50,- noteEvent Event.NoteOn 0 60 50] evs- in chopEvents 100000 $- EventListTM.takeTime (10^(7::Int)) $- EventList.cons 0 [noteEvent Event.NoteOn 0 60 50] evs--sequenceStaccato :: IO ()-sequenceStaccato = do- sequenceEvents $- let evs =- EventList.cons 551 [noteEvent Event.NoteOff 0 60 50] $- EventList.cons 550 [noteEvent Event.NoteOn 0 60 50] evs- in chopEvents 100000 $- EventListTM.takeTime (10^(7::Int)) $- EventList.cons 0 [noteEvent Event.NoteOn 0 60 50] evs----sequenceControlledEvents :: [PAlsa.Events] -> IO ()-sequenceControlledEvents chunkedEvents = do- opt <- Option.get- arrange <- CausalSt.makeArranger- amp <-- CausalP.processIO- (CausalP.mapSimple StereoInt.interleave <<<- CausalP.envelopeStereo <<<- first (CausalP.mapSimple SoV.replicate))-- ping <- Instr.pingStereoReleaseFM-- let timeControlPercussive =- Run.controllerExponentialDim Ctrl.attackTime- (DN.time 0.1, DN.time 2.5) (DN.time 0.8)- &+&- Run.controllerExponentialDim Ctrl.releaseTime- (DN.time 0.03, DN.time 0.3) (DN.time 0.1)-- frequencyControlPercussive =- MCS.controllerLinear controllerDetune (0,0.005) 0.001- &+&- MCS.bendWheelPressure 2 0.04 0.03-- pingProc vel freq =- ping (Option.sampleRate opt) vel freq- <<<- Zip.arrowSecond- (timeControlPercussive- &+&- ((MCS.controllerExponential controllerTimbre0 (0.3,10) 0.05- &+&- Run.controllerExponentialDim controllerTimbre1- (DN.time 0.01, DN.time 10) (DN.time 5))- &+&- ((MCS.controllerLinear Ctrl.soundController5 (0,10) 2- &+&- Run.controllerExponentialDim Ctrl.soundController7- (DN.time 0.03, DN.time 1) (DN.time 0.5))- &+&- frequencyControlPercussive)))-- let proc =- arr SigStL.unpackStereoStrict- <<<- amp ()- <<<- (MCS.controllerExponential controllerVolume (0.001, 1) (0.2::Float)- <<^ Zip.second)- &+&- (arrange- <<<- arr (EventListTT.mapTime- (NonNegW.fromNumberUnsafe . fromInteger . NonNegW.toNumber))- <<<- PAlsa.sequenceModulated- (Option.channel opt) (\ _pgm -> pingProc))- <<<- id &+& MCS.fromChannel (Option.channel opt)-- writeTest proc chunkedEvents---sequenceControlled :: IO ()-sequenceControlled =- sequenceControlledEvents $- let evs = EventList.cons 10 [] evs- in chopEvents 512 $- EventListTM.takeTime (10^(7::Int)) $- EventList.cons 0 [noteEvent Event.NoteOn 0 60 64] evs--sequenceControlledModulated :: IO ()-sequenceControlledModulated =- sequenceControlledEvents $- chopEvents 512 $- EventListTM.takeTime (10^(7::Int)) $- EventList.cons 0 [noteEvent Event.NoteOn 0 60 64] $- EventList.fromPairList $- map (\ev -> (10,[ev])) $ cycle $- map (ctrlEvent 0 1) [0..127]---sampledSound :: IO ()-sampledSound = do- opt <- Option.get-- amp <-- CausalP.processIO- (CausalP.mapSimple StereoInt.interleave)-- tomatoSmps <-- Instr.makeSampledSounds (Option.sampleDirectory opt) InstrP.tomatensalat-- let tomato smp vel freq =- smp sampleRate vel freq- <<<- Zip.arrowSecond- (MCS.controllerLinear controllerDetune (0,0.005) 0.001- &+&- MCS.bendWheelPressure 2 0.04 0.03)-- writeTest- (arr SigStL.unpackStereoStrict- <<<- amp ()- <<<- tomato (head tomatoSmps) 0 440) $- replicate 20 $- Zip.consChecked "Test.sampledSound"- (Gate.chunk 512 Nothing)- (PCS.Cons Map.empty (EventListTT.pause 512))
src/Synthesizer/LLVM/Server/Common.hs view
@@ -1,3 +1,4 @@+{-# LANGUAGE TypeFamilies #-} module Synthesizer.LLVM.Server.Common ( Real, SampleRate(SampleRate),@@ -5,55 +6,54 @@ frequency, time, number, control, signal, parameter, frequencyConst, timeConst, ($/),- play,- startMessage,++ chopEvents, piecewiseConstant, transposeModulation, amplitudeFromVelocity,- makeNote,- ) where -import qualified Synthesizer.LLVM.Server.Option as Option-import Synthesizer.LLVM.Server.Option (SampleRate(SampleRate), )+ controllerAttack, controllerDetune, controllerTimbre0, controllerTimbre1,+ controllerFilterCutoff, controllerFilterResonance,+ controllerVolume,+ ) where -import qualified Sound.ALSA.Sequencer.Event as Event-import qualified Sound.ALSA.Sequencer.Address as Addr-import qualified Sound.ALSA.Sequencer.Client as Client-import qualified Sound.ALSA.Sequencer.Port as Port-import qualified Sound.ALSA.Sequencer.Queue as Queue-import qualified Sound.ALSA.Sequencer.RealTime as RealTime+import qualified Sound.MIDI.Controller as Ctrl+import qualified Sound.MIDI.Message.Channel.Voice as VoiceMsg -import qualified Sound.ALSA.PCM as ALSA-import qualified Synthesizer.Storable.ALSA.Play as Play-import qualified Synthesizer.Storable.ALSA.MIDI as AlsaSt+import qualified Synthesizer.MIDI.Storable as MidiSt import qualified Synthesizer.PiecewiseConstant.Signal as PC-import qualified Synthesizer.LLVM.ALSA.BendModulation as BM+import qualified Synthesizer.LLVM.MIDI.BendModulation as BM import qualified Synthesizer.LLVM.Parameterized.Signal as SigP import qualified Synthesizer.LLVM.Parameter as Param import qualified LLVM.Extra.Memory as Memory import qualified LLVM.Extra.Class as Class-import qualified LLVM.Core as LLVM -import qualified Synthesizer.Storable.Signal as SigSt+import qualified Synthesizer.Storable.Signal as SigSt +import qualified Data.EventList.Relative.TimeTime as EventListTT++import qualified Numeric.NonNegative.Class as NonNeg+ import Foreign.Storable (Storable, ) import Control.Arrow (arr, (^<<), ) -import qualified Algebra.Additive as Additive+import Prelude hiding (Real, ) -import Data.Word (Word8, ) -import NumericPrelude.Numeric (zero, round, )-import Prelude hiding (Real, round, break, ) +newtype SampleRate a = SampleRate a+ deriving (Show) +instance Functor SampleRate where+ fmap f (SampleRate sr) = SampleRate (f sr) + type Real = Float -type Instrument a sig = SampleRate a -> AlsaSt.Instrument a sig+type Instrument a sig = SampleRate a -> MidiSt.Instrument a sig frequency :: (p -> Real) -> Param.T (SampleRate Real, p) Real@@ -91,29 +91,25 @@ f $/ x = fmap ($x) f --- ToDo: do not record the empty chunk that is inserted for latency-{-# INLINE play #-}-play ::- (Additive.C y, ALSA.SampleFmt y) =>- Option.T -> Double -> SigSt.T y -> IO ()-play opts rate =- Play.auto (Play.makeSink- (Option.device opts) (Option.periodTime opts) (round rate)) .- SigSt.append (SigSt.replicate (Option.chunkSize opts) (Option.latency opts) zero)--- FiltG.delayPosLazySize (Option.chunkSize opts) (Option.latency opts)--- FiltG.delayPos (Option.latency opts)---startMessage :: String-startMessage =- "run 'aconnect' to connect to the MIDI controller"+-- might be moved to event-list package+chopEvents ::+ (NonNeg.C time, Num time) =>+ time ->+ EventListTT.T time body ->+ [EventListTT.T time body]+chopEvents chunkSize =+ let go evs =+ let (chunk,rest) = EventListTT.splitAtTime chunkSize evs+ in if EventListTT.duration chunk == 0+ then []+ else chunk : go rest+ in go piecewiseConstant :: (Storable a,- Class.MakeValueTuple a al,- Memory.C al am,- LLVM.IsSized am as) =>+ Class.MakeValueTuple a, Class.ValueTuple a ~ al,+ Memory.C al) => Param.T p (PC.T a) -> SigP.T p al piecewiseConstant pc = SigP.piecewiseConstant@@ -134,24 +130,13 @@ amplitudeFromVelocity vel = 4**vel --- cf. synthesizer-alsa:Synthesizer.Storable.ALSA.Server.Test-makeNote :: Event.NoteEv -> Word8 -> Event.T-makeNote typ pit =- Event.Cons- { Event.highPriority = False- , Event.tag = 0- , Event.queue = Queue.direct- , Event.timestamp =- Event.RealTime $ RealTime.fromInteger 0- , Event.source = Addr.Cons {- Addr.client = Client.subscribers,- Addr.port = Port.unknown- }- , Event.dest = Addr.Cons {- Addr.client = Client.subscribers,- Addr.port = Port.unknown- }- , Event.body =- Event.NoteEv typ- (Event.simpleNote 0 pit 64)- }+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
+ src/Synthesizer/LLVM/Server/CommonPacked.hs view
@@ -0,0 +1,69 @@+module Synthesizer.LLVM.Server.CommonPacked where++import Synthesizer.LLVM.Server.Common++import qualified Synthesizer.LLVM.Frame.SerialVector as Serial++import qualified Synthesizer.LLVM.CausalParameterized.Process as CausalP+import qualified Synthesizer.LLVM.CausalParameterized.Functional as F+import qualified Synthesizer.LLVM.Parameterized.Signal as SigP+import qualified Synthesizer.LLVM.Parameter as Param++import qualified Data.List.Match as Match++import qualified Algebra.Additive as Additive++import qualified Types.Data.Num as TypeNum++import Control.Arrow (arr, )++import NumericPrelude.Numeric ((+), (-), (*), )+import Prelude hiding (Real, (+), (-), (*), )+++sumNested :: (Additive.C a) => [a] -> a+sumNested [] = Additive.zero+sumNested xs@(_:rs) =+ let ys = xs ++ Match.take rs (sum2 ys)+ in last ys++sum2 :: (Additive.C a) => [a] -> [a]+sum2 (x:y:rest) = (x+y) : sum2 rest+sum2 xs = xs+++-- 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+++type Param p = Param.T (SampleRate Real, p)+type SigP p = SigP.T (SampleRate Real, p)+type CausalP p = CausalP.T (SampleRate Real, p)+type FuncP p = F.T (SampleRate Real, p)+++type Vector = Serial.Plain VectorSize Real+type VectorValue = Serial.Value VectorSize Real+type VectorSize = TypeNum.D4+++vectorSize :: Int+vectorSize = TypeNum.fromIntegerT (undefined :: VectorSize)++vectorRate :: Fractional a => SampleRate a -> a+vectorRate (SampleRate sampleRate) =+ sampleRate / fromIntegral vectorSize+++vectorTime :: (p -> Real) -> Param p Real+vectorTime param =+ arr (\(SampleRate sampleRate, p) ->+ param p * sampleRate / fromIntegral vectorSize)++noiseReference :: Real -> Param p Real+noiseReference freq =+ arr (\(SampleRate sampleRate, _p) -> sampleRate/freq)
− src/Synthesizer/LLVM/Server/Option.hs
@@ -1,196 +0,0 @@-module Synthesizer.LLVM.Server.Option (- T(..),- get,- defaultChannel,- Play.defaultChunkSize,- defaultSampleRate,- defaultLatency,- SampleRate(SampleRate),- sampleRate,- ) where--import qualified Synthesizer.Storable.ALSA.Play as Play-import qualified Synthesizer.Generic.Signal as SigG-import qualified Data.StorableVector.Lazy as SVL-import Synthesizer.EventList.ALSA.MIDI (ClientName(ClientName))--import qualified Sound.MIDI.Message.Channel as ChannelMsg--import System.Console.GetOpt- (getOpt, ArgOrder(..), OptDescr(..), ArgDescr(..), usageInfo, )-import System.Environment (getArgs, getProgName, )-import System.Exit (exitSuccess, exitFailure, )-import qualified System.IO as IO--import Control.Monad (when, )--import qualified NumericPrelude.Numeric as NP-import Prelude hiding (Real, )---data T =- Cons {- device :: Play.Device,- clientName :: ClientName,- channel, extraChannel :: ChannelMsg.Channel,- sampleDirectory :: FilePath,- sampleRateInt :: SampleRate Integer,- chunkSize :: SVL.ChunkSize,- lazySize :: SigG.LazySize,- periodTime :: Double,- latency :: Int- }- deriving (Show)---deflt :: T-deflt =- Cons {- device = Play.defaultDevice,- clientName = defaultClientName,- channel = defaultChannel,- extraChannel = ChannelMsg.toChannel 1,- sampleDirectory = "speech",- sampleRateInt = SampleRate defaultSampleRate,- chunkSize = Play.defaultChunkSize,- lazySize = error "Option.lazySize must be initialized after option parsing",- periodTime = error "Option.periodTime must be initialized after option parsing",- latency = defaultLatency- }--defaultClientName :: ClientName-defaultClientName =- ClientName "Haskell-LLVM-Synthesizer"--defaultChannel :: ChannelMsg.Channel-defaultChannel = ChannelMsg.toChannel 0--defaultSampleRate :: Num a => a--- defaultSampleRate = 24000--- defaultSampleRate = 48000-defaultSampleRate = 44100--defaultLatency :: Int-defaultLatency =- -- 0- -- 256- 1024---newtype SampleRate a = SampleRate a- deriving (Show)--instance Functor SampleRate where- fmap f (SampleRate sr) = SampleRate (f sr)---sampleRate :: Num a => T -> SampleRate a-sampleRate = fmap fromInteger . sampleRateInt---exitFailureMsg :: String -> IO a-exitFailureMsg msg =- IO.hPutStrLn IO.stderr msg >> exitFailure--parseChannel :: String -> IO ChannelMsg.Channel-parseChannel str =- case reads str of- [(chan, "")] ->- if 0<=chan && chan<16- then return $ ChannelMsg.toChannel chan- else exitFailureMsg "MIDI channel must a number from 0..15"- _ ->- exitFailureMsg $ "channel must be a number, but is '" ++ str ++ "'"--parseNumber ::- (Read a) =>- String -> (a -> Bool) -> String -> String -> IO a-parseNumber name constraint constraintName str =- case reads str of- [(n, "")] ->- if constraint n- then return n- else exitFailureMsg $ name ++ " must be a " ++ constraintName ++ " number"- _ ->- exitFailureMsg $ name ++ " must be a number, but is '" ++ str ++ "'"--maxInt :: Integer-maxInt =- fromIntegral (maxBound :: Int)---{--Guide for common Linux/Unix command-line options:- http://www.faqs.org/docs/artu/ch10s05.html--}-description :: [OptDescr (T -> IO T)]-description =- Option ['h'] ["help"]- (NoArg $ \ _flags -> do- programName <- getProgName- putStrLn- (usageInfo ("Usage: " ++ programName ++ " [OPTIONS]") description)- exitSuccess)- "show options" :- Option ['d'] ["device"]- (flip ReqArg "NAME" $ \str flags ->- return $ flags{device = str})- "select ALSA output device" :- Option [] ["clientname"]- (flip ReqArg "NAME" $ \str flags ->- return $ flags{clientName = ClientName str})- "name of the ALSA client" :- Option ['r'] ["samplerate"]- (flip ReqArg "RATE" $ \str flags ->- fmap (\rate -> flags{sampleRateInt = SampleRate rate}) $- parseNumber "sample-rate" (\n -> 0<n && n<=maxInt) "positive" str)- "sample-rate in samples per second" :- Option ['b'] ["blocksize"]- (flip ReqArg "SIZE" $ \str flags ->- fmap (\size -> flags{chunkSize = SVL.ChunkSize $ fromInteger size}) $- parseNumber "blocksize" (\n -> 0<n && n<=maxInt) "positive" str)- "block size as number of sample-frames" :- Option [] ["latency"]- (flip ReqArg "SIZE" $ \str flags ->- fmap (\size -> flags{latency = fromInteger size}) $- parseNumber "latency" (\n -> 0<=n && n<=maxInt) "non-negative" str)- "latency as number of sample-frames" :- Option ['c'] ["channel"]- (flip ReqArg "CHANNEL" $ \str flags ->- fmap (\chan -> flags{channel = chan}) $- parseChannel str)- "select MIDI input channel (0-based)" :- Option [] ["extra-channel"]- (flip ReqArg "CHANNEL" $ \str flags ->- fmap (\chan -> flags{extraChannel = chan}) $- parseChannel str)- "select MIDI channel with effects" :- Option ['I'] ["sample-directory"]- (flip ReqArg "DIR" $ \str flags ->- return $ flags{sampleDirectory = str})- "directory for sound samples" :- []---get :: IO T-get = do- argv <- getArgs- let (opts, files, errors) = getOpt RequireOrder description argv- when (not $ null errors) $- exitFailureMsg (init (concat errors))- when (not $ null files) $- exitFailureMsg $- "Do not know what to do with arguments " ++ show files- fmap- (\actual ->- case chunkSize actual of- SVL.ChunkSize size ->- actual {- lazySize = SigG.LazySize size,- periodTime =- NP.fromIntegral size NP./- case sampleRate actual of SampleRate sr -> sr- }) $- foldl (>>=)- (return deflt)- opts
src/Synthesizer/LLVM/Server/Packed/Instrument.hs view
@@ -23,6 +23,12 @@ where d is the tone period and f is non-linear, maybe chaotic function. In order to limit the appearance of chaotic waveforms, we could combine this with a lowpass filter.+ let attack and release depend on On and Off velocity+ tineStereoFM:+ continuous control of the modulation index+ by linear interpolation of waves between modulations with integral indices.+ E.g. modulation index 2.3 means+ 0.7*modulation with index 2 and 0.3*modulation with index 3. effects: reverb and controllable delay@@ -67,45 +73,42 @@ {-# LANGUAGE Rank2Types #-} module Synthesizer.LLVM.Server.Packed.Instrument where +import Synthesizer.LLVM.Server.CommonPacked import Synthesizer.LLVM.Server.Common -import qualified Synthesizer.LLVM.ALSA.BendModulation as BM-import qualified Synthesizer.PiecewiseConstant.ALSA.MIDI as PC-import qualified Synthesizer.EventList.ALSA.MIDI as Ev+import qualified Synthesizer.LLVM.Server.SampledSound as Sample+import qualified Synthesizer.LLVM.MIDI.BendModulation as BM+import qualified Synthesizer.MIDI.PiecewiseConstant as PC+import qualified Synthesizer.MIDI.EventList as Ev -import qualified Sound.Sox.Read as SoxRead-import qualified Sound.Sox.Option.Format as SoxOption import System.FilePath ((</>), )-import Control.Exception (bracket, ) -import Synthesizer.Storable.ALSA.MIDI (chunkSizesFromLazyTime, )+import Synthesizer.MIDI.Storable (chunkSizesFromLazyTime, ) import qualified Synthesizer.LLVM.Frame.Stereo as Stereo import qualified Synthesizer.LLVM.Filter.Universal as UniFilterL import qualified Synthesizer.LLVM.Filter.Allpass as Allpass import qualified Synthesizer.LLVM.Filter.Moog as MoogL-import qualified Synthesizer.LLVM.ALSA.MIDI as MIDIL+import qualified Synthesizer.LLVM.MIDI as MIDIL import qualified Synthesizer.LLVM.CausalParameterized.ControlledPacked as CtrlPS import qualified Synthesizer.LLVM.CausalParameterized.ProcessPacked as CausalPS import qualified Synthesizer.LLVM.CausalParameterized.Process as CausalP+import qualified Synthesizer.LLVM.CausalParameterized.Functional as F import qualified Synthesizer.LLVM.Parameterized.SignalPacked as SigPS import qualified Synthesizer.LLVM.Parameterized.Signal as SigP import qualified Synthesizer.LLVM.Parameter as Param import qualified Synthesizer.LLVM.Storable.Signal as SigStL import qualified Synthesizer.LLVM.Frame as Frame-import qualified Synthesizer.LLVM.SerialVector as Serial+import qualified Synthesizer.LLVM.Frame.SerialVector as Serial import qualified Synthesizer.LLVM.Wave as WaveL import Synthesizer.LLVM.CausalParameterized.Process (($<), ($>), ($*), )+import Synthesizer.LLVM.CausalParameterized.Functional (($&), (&|&), ) import Synthesizer.LLVM.Parameterized.Signal (($#), ) -import qualified LLVM.Extra.ScalarOrVector as SoV import qualified LLVM.Extra.Monad as LM import qualified LLVM.Extra.Arithmetic as A import qualified LLVM.Core as LLVM-import qualified Data.TypeLevel.Num as TypeNum--import Control.Arrow.Monad ((=<<<), listen, )-import qualified Data.HList as HL+import qualified Types.Data.Num as TypeNum import qualified Synthesizer.Generic.Cut as CutG import qualified Synthesizer.Storable.Signal as SigSt@@ -118,11 +121,9 @@ import Control.Category (id, ) import Control.Applicative (liftA2, liftA3, ) import Data.Traversable (traverse, )--import qualified Data.List.Match as Match-import Data.Tuple.HT (mapPair, fst3, snd3, thd3, )+import qualified Data.Traversable as Trav -import Data.Int (Int32, )+import Data.Tuple.HT (fst3, snd3, thd3, ) {- import qualified Numeric.NonNegative.Class as NonNeg@@ -137,43 +138,6 @@ -sumNested :: (Additive.C a) => [a] -> a-sumNested [] = Additive.zero-sumNested xs@(_:rs) =- let ys = xs ++ Match.take rs (sum2 ys)- in last ys--sum2 :: (Additive.C a) => [a] -> [a]-sum2 (x:y:rest) = (x+y) : sum2 rest-sum2 xs = xs---type Param p = Param.T (SampleRate Real, p)-type SigP p = SigP.T (SampleRate Real, p)-type CausalP p = CausalP.T (SampleRate Real, p)---type Vector = LLVM.Vector VectorSize Real-type VectorSize = TypeNum.D4---vectorSize :: Int-vectorSize = TypeNum.toInt (undefined :: VectorSize)--vectorRate :: Fractional a => SampleRate a -> a-vectorRate (SampleRate sampleRate) =- sampleRate / fromIntegral vectorSize---vectorTime :: (p -> Real) -> Param p Real-vectorTime param =- arr (\(SampleRate sampleRate, p) ->- param p * sampleRate / fromIntegral vectorSize)--noiseReference :: Real -> Param p Real-noiseReference freq =- arr (\(SampleRate sampleRate, _p) -> sampleRate/freq)- frequencyControl :: (p -> PC.T Real) -> Param p (PC.T Real) frequencyControl param = arr (\(SampleRate sampleRate, p) -> fmap (/sampleRate) $ param p)@@ -196,11 +160,11 @@ frequencyFromBendModulation :: {- (Storable a,- Class.MakeValueTuple a (Value a)) =>+ Class.MakeValueTuple a, ValueTuple a ~ (Value a)) => -} Param p Real -> Param p (PC.T (BM.T Real)) ->- SigP p (LLVM.Value Vector)+ SigP p VectorValue frequencyFromBendModulation speed fmFreq = MIDIL.frequencyFromBendModulationPacked speed $* piecewiseConstant fmFreq@@ -208,7 +172,7 @@ stereoFrequenciesFromDetuneBendModulation :: Param p Real -> Param p (PC.T Real, PC.T (BM.T Real)) ->- SigP p (Stereo.T (LLVM.Value Vector))+ SigP p (Stereo.T VectorValue) stereoFrequenciesFromDetuneBendModulation speed detFmFreq = (CausalP.envelopeStereo $< frequencyFromBendModulation speed@@ -219,13 +183,13 @@ (fmap (\(det,_fm) -> det) detFmFreq) piecewiseConstantVector ::- Param.T p (PC.T Real) -> SigP.T p (LLVM.Value Vector)+ Param.T p (PC.T Real) -> SigP.T p VectorValue {- (Storable a,- Class.MakeValueTuple a al,+ Class.MakeValueTuple a, Class.ValueTuple a ~ al, Memory.C al am, LLVM.IsSized am as) =>- Param.T p (PC.T a) -> SigP.T p (LLVM.Vector n al)+ Param.T p (PC.T a) -> SigP.T p (Serial.Value n al) -} piecewiseConstantVector = piecewiseConstant . fmap (fmap (Serial.replicate))@@ -294,10 +258,10 @@ (sr, ((phase, phaseDecay), shape, (detune,fm,freq))) (env dec rel vcsize sr vel dur)) (CausalP.runStorableChunky- (let phase = number (fst.fst3)- decay = time (snd.fst3)- shape = control snd3- fm = detuneModulation thd3+ (let phase = number (fst.fst3) :: Param ((Real,a), b, c) Real+ decay = time (snd.fst3) :: Param ((a,Real), b, c) Real+ shape = control snd3 :: Param (a, PC.T Real, c) (PC.T Real)+ fm = detuneModulation thd3 :: Param (a, b, (PC.T Real, PC.T (BM.T Real), Real)) (PC.T Real, PC.T (BM.T Real)) in CausalP.envelopeStereo $> ((CausalP.stereoFromMonoControlled (CausalPS.shapeModOsci WaveL.rationalApproxSine1)@@ -330,6 +294,10 @@ (let phs = control (fst.fst) shp = control (snd.fst) fm = detuneModulation snd+ chanOsci ::+ CausalP p+ ((VectorValue, VectorValue), VectorValue)+ VectorValue chanOsci = ((CausalPS.shapeModOsci WaveL.rationalApproxSine1 <<<@@ -346,6 +314,9 @@ $* stereoFrequenciesFromDetuneBendModulation (frequencyConst 10) fm))) pingReleaseEnvelope ++type Triple a = (a, a, a)+ bellStereoFM :: IO (Real -> Real -> PC.T Real ->@@ -364,6 +335,13 @@ vel = number snd3 env4 = signal (fst.thd3) env7 = signal (snd.thd3)+ osci ::+ (Triple VectorValue -> VectorValue) ->+ Param.T p Real ->+ Param.T p Real ->+ CausalP.T p+ (Triple VectorValue, Stereo.T VectorValue)+ (Stereo.T VectorValue) osci sel v d = CausalP.envelopeStereo <<<@@ -414,6 +392,14 @@ vel = number (fst3.thd3) env4 = signal (snd3.thd3) env7 = signal (thd3.thd3)++ osci ::+ (Triple VectorValue -> VectorValue) ->+ Param.T p Real ->+ Param.T p Real ->+ CausalP.T p+ (Triple VectorValue, VectorValue)+ VectorValue osci sel v d = CausalP.envelope <<<@@ -423,6 +409,13 @@ (CausalPS.osciSimple WaveL.approxSine4 $< zero) <<< CausalPS.amplify d))++ noise ::+ (Triple VectorValue -> VectorValue) ->+ Param (a, (PC.T Real, PC.T Real), c) Real ->+ CausalP (a, (PC.T Real, PC.T Real), c)+ (Triple VectorValue, VectorValue)+ VectorValue noise sel d = (CausalP.envelope $< piecewiseConstantVector noiseAmp)@@ -446,7 +439,7 @@ <<< CausalP.feedFst (piecewiseConstant noiseReson) <<<- CausalP.mapSimple Frame.subsampleVector+ CausalP.mapSimple Serial.subsample <<< CausalPS.amplify d)) in liftA2 Stereo.cons@@ -570,7 +563,7 @@ (let fm = modulation id osci :: Param.T fm Real ->- CausalP.T fm (LLVM.Value Vector) (LLVM.Value Vector)+ CausalP.T fm VectorValue VectorValue osci d = (CausalPS.osciSimple WaveL.saw $< zero) <<< CausalPS.amplify d@@ -616,8 +609,8 @@ Param p (PC.T Real) -> Param p Real -> CausalP p- (Stereo.T (LLVM.Value Vector))- (Stereo.T (LLVM.Value Vector))+ (Stereo.T VectorValue)+ (Stereo.T VectorValue) tineControlledProc index depth vel = CausalP.stereoFromMono (CausalPS.osciSimple WaveL.approxSine2)@@ -637,12 +630,11 @@ &&& id tineControlledFnProc index depth vel =- ((\freq ->- CausalP.stereoFromMono- (CausalPS.osciSimple WaveL.approxSine2)- <<<- Stereo.interleave- ^<<+ F.withArgs $ \freq ->+ CausalP.stereoFromMono+ (CausalPS.osciSimple WaveL.approxSine2)+ $&+ liftA2 (liftA2 (,)) ((CausalP.envelopeStereo $< SigP.envelope (piecewiseConstantVector depth)@@ -653,13 +645,9 @@ <<< (CausalP.envelopeStereo $< piecewiseConstantVector index)- <<<- listen freq)- &&&- listen freq)--- =<<< listen HL.hNil- =<<< arr HL.hHead)- <<< arr (\freq -> HL.hCons freq HL.hNil)+ $&+ freq)+ freq tineControlledFM :: IO (Real -> Real ->@@ -691,13 +679,18 @@ Param p (PC.T Real) -> Param p Real -> CausalP p- (Stereo.T (LLVM.Value Vector))- (Stereo.T (LLVM.Value Vector))+ (Stereo.T VectorValue)+ (Stereo.T VectorValue) fenderProc fade index depth vel =- ((\stereoFreq ->- let channel_n_1 freq =+ F.withArgs $ \stereoFreq ->+ let {-+ channel_n_1 ::+ FuncP p VectorValue VectorValue ->+ FuncP p VectorValue VectorValue+ -}+ channel_n_1 freq = CausalPS.osciSimple WaveL.approxSine2- <<<+ $& ((CausalP.envelope $< SigP.envelope (piecewiseConstantVector depth)@@ -707,32 +700,35 @@ <<< (CausalP.envelope $< piecewiseConstantVector index)- <<<+ $& freq)- &&&+ &|& freq+ {-+ channel_1_2 ::+ FuncP p VectorValue VectorValue ->+ FuncP p VectorValue VectorValue+ -} channel_1_2 freq = CausalPS.osciSimple WaveL.approxSine2- <<<+ $& ((CausalP.envelope $< SigP.envelope (piecewiseConstantVector depth) (SigPS.exponential2 (timeConst 1) (vel+1))) <<< (CausalPS.osciSimple WaveL.approxSine2 $< zero)- <<<+ $& freq)- &&&- (CausalPS.amplify 2 <<< freq)+ &|&+ (CausalPS.amplify 2 $& freq) in (CausalP.stereoFromMonoControlled (fadeProcess- (channel_n_1 id)- (channel_1_2 id))+ (F.compile $ channel_n_1 $ F.lift id)+ (F.compile $ channel_1_2 $ F.lift id)) $< piecewiseConstantVector fade)- <<<- listen stereoFreq)- =<<< arr HL.hHead)- <<< arr (\freq -> HL.hCons freq HL.hNil)+ $&+ stereoFreq fenderFM :: IO (Real -> Real ->@@ -764,8 +760,8 @@ Param p Real -> Param p (PC.T Real) -> CausalP p- (Stereo.T (LLVM.Value Vector))- (Stereo.T (LLVM.Value Vector))+ (Stereo.T VectorValue)+ (Stereo.T VectorValue) fmModulator vel n depth = (CausalP.envelopeStereo $< SigP.envelope@@ -849,11 +845,11 @@ vel = number (fst.thd3) fm = detuneModulation (snd.thd3) partial ::- LLVM.Value Vector -> Int32 -> LLVM.Value Vector ->- LLVM.CodeGenFunction r (LLVM.Value Vector)+ VectorValue -> Int -> VectorValue ->+ LLVM.CodeGenFunction r VectorValue partial amp n t = A.mul amp =<<- WaveL.partial WaveL.approxSine2 (LLVM.valueOf n) t+ WaveL.partial WaveL.approxSine2 n t in CausalP.envelopeStereo $> (CausalP.stereoFromMono (CausalPS.shapeModOsci@@ -893,13 +889,14 @@ Param p (PC.T Real) -> Param p Real -> CausalP p- (Stereo.T (LLVM.Value Vector))- (Stereo.T (LLVM.Value Vector))+ (Stereo.T VectorValue)+ (Stereo.T VectorValue) resonantFMSynthProc reson index depth vel =- ((\stereoFreq ->- let chan freq =+ F.withArgs $ \stereoFreq ->+ let -- chan :: FuncP p inp VectorValue -> FuncP p inp VectorValue+ chan freq = CausalPS.osciSimple WaveL.approxSine2- <<<+ $& ((CausalP.envelope $< SigP.envelope (piecewiseConstantVector depth)@@ -908,27 +905,24 @@ UniFilter.lowpass ^<< CtrlPS.process- <<<+ $& (CausalP.zipWithSimple UniFilterL.parameter <<< CausalP.feedFst (piecewiseConstant reson) <<< (CausalP.envelope $< piecewiseConstant index) <<<- CausalP.mapSimple Frame.subsampleVector- <<<+ CausalP.mapSimple Serial.subsample+ $& freq)- &&&+ &|& ((CausalPS.osciSimple WaveL.saw $< zero)- <<<+ $& freq))- &&&+ &|& freq- in CausalP.stereoFromMono (chan id)- <<<- listen stereoFreq)- =<<< arr HL.hHead)- <<< arr (\freq -> HL.hCons freq HL.hNil)+ in Trav.traverse chan $+ Stereo.sequence stereoFreq resonantFMSynth :: IO (Real -> Real ->@@ -956,8 +950,8 @@ phaserOsci ::- (Param.T p Real -> CausalP.T p a (LLVM.Value Vector)) ->- CausalP.T p a (Stereo.T (LLVM.Value Vector))+ (Param.T p Real -> CausalP.T p a VectorValue) ->+ CausalP.T p a (Stereo.T VectorValue) phaserOsci osci = CausalPS.amplifyStereo 0.25 <<<@@ -980,8 +974,8 @@ osci :: Param.T (det,fm) Real -> CausalP.T (det,fm)- (LLVM.Value Vector, LLVM.Value Vector)- (LLVM.Value Vector)+ (VectorValue, VectorValue)+ VectorValue osci d = (CausalPS.osciSimple WaveL.saw $< zero) <<<@@ -1021,8 +1015,8 @@ arcStringStereoFM :: (forall r.- LLVM.Value Vector ->- LLVM.CodeGenFunction r (LLVM.Value Vector)) ->+ VectorValue ->+ LLVM.CodeGenFunction r VectorValue) -> IO (Real -> PC.T Real -> PC.T Real ->@@ -1037,9 +1031,9 @@ softStringShapeCore :: (forall r.- LLVM.Value Vector ->- LLVM.Value Vector ->- LLVM.CodeGenFunction r (LLVM.Value Vector)) ->+ VectorValue ->+ VectorValue ->+ LLVM.CodeGenFunction r VectorValue) -> IO (Real -> PC.T Real -> PC.T Real ->@@ -1055,11 +1049,11 @@ osci :: Param.T (mod,fm) Real -> CausalP.T (mod,fm)- (LLVM.Value Vector,+ (VectorValue, {- wave shape parameter -}- (LLVM.Value Vector, LLVM.Value Vector)+ (VectorValue, VectorValue) {- detune, frequency modulation -})- (LLVM.Value Vector)+ VectorValue osci d = CausalPS.shapeModOsci wave <<<@@ -1095,11 +1089,11 @@ osci :: Param.T (mod,fm) Real -> CausalP.T (mod,fm)- ((LLVM.Value Vector, LLVM.Value Vector)+ ((VectorValue, VectorValue) {- phase modulation depth, modulator distortion -},- (LLVM.Value Vector, LLVM.Value Vector)+ (VectorValue, VectorValue) {- detune, frequency modulation -})- (LLVM.Value Vector)+ VectorValue osci d = CausalPS.osciSimple WaveL.approxSine2 <<<@@ -1132,7 +1126,7 @@ softStringReleaseEnvelope -stereoNoise :: SigP p (Stereo.T (LLVM.Value Vector))+stereoNoise :: SigP p (Stereo.T VectorValue) stereoNoise = traverse (\uid -> SigPS.noise uid (noiseReference 20000))@@ -1141,13 +1135,13 @@ windCore :: Param p (PC.T Real) -> Param p (PC.T (BM.T Real)) ->- SigP p (Stereo.T (LLVM.Value Vector))+ SigP p (Stereo.T VectorValue) windCore reson fm = CausalP.stereoFromMonoControlled CtrlPS.process $< SigP.zipWithSimple (MoogL.parameter TypeNum.d8) (piecewiseConstant reson)- (SigP.mapSimple Frame.subsampleVector+ (SigP.mapSimple Serial.subsample (frequencyFromBendModulation (frequencyConst 0.2) fm)) $* stereoNoise @@ -1199,7 +1193,7 @@ ((CausalP.stereoFromMonoControlled (fadeProcess (arr snd) CtrlPS.process <<<- first (CausalP.mapSimple SoV.replicate)+ first (CausalP.mapSimple Serial.upsample) <<^ (\((k,p),x) -> (k,(p,x)))) $< SigP.zip@@ -1337,11 +1331,11 @@ osci :: Param.T p Real -> CausalP.T p- (LLVM.Value Vector,+ (VectorValue, {- wave shrink/replication factor -}- (LLVM.Value Vector, LLVM.Value Vector)+ (VectorValue, VectorValue) {- detune, frequency modulation -})- (LLVM.Value Vector)+ VectorValue osci d = CausalPS.shapeModOsci WaveL.rationalApproxSine1 <<<@@ -1365,22 +1359,8 @@ adsr -data SamplePositions =- SamplePositions {- sampleStart, sampleLength,- sampleLoopStart, sampleLoopLength :: Int- }--data SampledSound =- SampledSound {- sampleData :: SigSt.T Real,- samplePositions :: SamplePositions,- samplePeriod :: Real- }-- sampledSound ::- IO (SampledSound ->+ IO (Sample.T -> PC.T (BM.T Real) -> Instrument Real (Stereo.T Vector)) sampledSound =@@ -1395,24 +1375,15 @@ let fmSig = freqMod (chunkSizesFromLazyTime (PC.duration fm))- (sr, (fm, freq*samplePeriod smp)) :: SigSt.T Vector- pos = samplePositions smp+ (sr, (fm, freq * Sample.period smp)) :: SigSt.T Vector+ pos = Sample.positions smp amp = 2 * amplitudeFromVelocity vel- (attack,sustain) =- mapPair- (SigSt.drop (sampleStart pos),- SigSt.take (sampleLoopLength pos)) $- SigSt.splitAt (sampleLoopStart pos) $- sampleData smp- release =- SigSt.drop (sampleLoopStart pos + sampleLoopLength pos) $- SigSt.take (sampleStart pos + sampleLength pos) $- sampleData smp+ (attack, sustain, release) = Sample.parts smp in (\cont -> osc cont (sr, (amp, attack `SigSt.append`- SVL.cycle (SigSt.take (sampleLoopLength pos) sustain),+ SVL.cycle (SigSt.take (Sample.loopLength pos) sustain), chunkSizesFromLazyTime dur)) fmSig) (osc (const SigSt.empty)@@ -1440,7 +1411,7 @@ sampledSoundLeaky ::- IO (SampledSound ->+ IO (Sample.T -> PC.T (BM.T Real) -> Instrument Real (Stereo.T Vector)) sampledSoundLeaky =@@ -1456,24 +1427,15 @@ SVP.splitAt (chunkSizesFromLazyTime dur) $ (freqMod (chunkSizesFromLazyTime (PC.duration fm))- (sr, (fm, freq*samplePeriod smp)) :: SigSt.T Vector)- pos = samplePositions smp+ (sr, (fm, freq * Sample.period smp)) :: SigSt.T Vector)+ pos = Sample.positions smp amp = 2 * amplitudeFromVelocity vel- (attack,sustain) =- mapPair- (SigSt.drop (sampleStart pos),- SigSt.take (sampleLoopLength pos)) $- SigSt.splitAt (sampleLoopStart pos) $- sampleData smp- release =- SigSt.drop (sampleLoopStart pos + sampleLoopLength pos) $- SigSt.take (sampleStart pos + sampleLength pos) $- sampleData smp+ (attack, sustain, release) = Sample.parts smp in osc (sr, (amp, attack `SigSt.append`- SVL.cycle (SigSt.take (sampleLoopLength pos) sustain)))+ SVL.cycle (SigSt.take (Sample.loopLength pos) sustain))) sustainFM `SigSt.append` osc (sr, (amp,release)) releaseFM)@@ -1494,19 +1456,10 @@ (frequencyFromBendModulation (frequencyConst 3) (modulation id))) -loadSound :: FilePath -> IO (SVL.Vector Real)-loadSound path =- bracket (SoxRead.open SoxOption.none path) SoxRead.close $- SoxRead.withHandle1 (SVL.hGetContentsSync SVL.defaultChunkSize)---type SampleInfo = (FilePath, [SamplePositions], Real)-- -- ToDo: flag failure if files cannot be found, or just remain silent makeSampledSounds :: FilePath ->- SampleInfo ->+ Sample.Info -> IO [-- PC.T Real -> PC.T (BM.T Real) -> Instrument Real (Stereo.T Vector)]@@ -1519,50 +1472,7 @@ -} liftA2 (\makeSmp smp ->- map (\pos -> makeSmp (SampledSound smp pos period))+ map (\pos -> makeSmp (Sample.Cons smp pos period)) positions) sampledSound- (loadSound (dir </> file))---tomatensalatPositions :: [SamplePositions]-tomatensalatPositions =- SamplePositions 0 29499 12501 15073 :- SamplePositions 29499 31672 38163 17312 :- SamplePositions 67379 28610 81811 10667 :- SamplePositions 95989 31253 106058 16111 :- SamplePositions 127242 38596 136689 11514 :- []--tomatensalat :: SampleInfo-tomatensalat =- ("tomatensalat2.wav", tomatensalatPositions, 324.5)---halPositions :: [SamplePositions]-halPositions =--- SamplePositions 2371 25957 7362 6321 :- SamplePositions 2371 25957 (2371+25957) 1 :- SamplePositions 40546 34460 63540 9546 :- SamplePositions 79128 32348 94367 14016 :- SamplePositions 112027 21227 125880 5500 :- SamplePositions 146057 23235 168941 352 :- []--hal :: SampleInfo-hal =- ("haskell-in-leipzig2.wav", halPositions, 316)---graphentheoriePositions :: [SamplePositions]-graphentheoriePositions =- SamplePositions 0 29524 13267 14768 :- SamplePositions 29524 35333 47624 9968 :- SamplePositions 64857 31189 73818 16408 :- SamplePositions 96046 31312 106206 18504 :- SamplePositions 127358 32127 132469 16530 :- []--graphentheorie :: SampleInfo-graphentheorie =- ("graphentheorie0.wav", graphentheoriePositions, 301.15)+ (Sample.load (dir </> file))
− src/Synthesizer/LLVM/Server/Packed/Run.hs
@@ -1,504 +0,0 @@-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))
− src/Synthesizer/LLVM/Server/Packed/Test.hs
@@ -1,727 +0,0 @@-module Synthesizer.LLVM.Server.Packed.Test 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,- sampleStart, sampleLength,- sampleLoopStart, sampleLoopLength,- samplePositions, sampleData, samplePeriod, )-import Synthesizer.LLVM.Server.Common hiding- (Instrument, )--import qualified Sound.ALSA.Sequencer.Event as Event-import qualified Synthesizer.PiecewiseConstant.ALSA.MIDI as PC-import qualified Synthesizer.Generic.ALSA.MIDI as Gen--import qualified Synthesizer.LLVM.Frame.Stereo as Stereo--import qualified Synthesizer.Storable.ALSA.Play as Play-import Synthesizer.Storable.ALSA.MIDI (Instrument, chunkSizesFromLazyTime, )--import qualified Synthesizer.LLVM.ALSA.BendModulation as BM-import qualified Synthesizer.LLVM.CausalParameterized.ProcessPacked as CausalPS-import qualified Synthesizer.LLVM.Parameterized.SignalPacked as SigPS-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 Synthesizer.LLVM.CausalParameterized.Process (($*), )--import qualified LLVM.Core as LLVM--import qualified Synthesizer.Storable.Cut as CutSt-import qualified Synthesizer.Storable.Signal as SigSt-import qualified Data.StorableVector.Lazy.Pattern as SVP-import qualified Data.StorableVector.Lazy as SVL--- import qualified Data.StorableVector as SV--import qualified Data.EventList.Relative.TimeBody as EventList-import qualified Data.EventList.Relative.BodyTime as EventListBT--import Control.Arrow ((<<<), arr, )-import Control.Applicative (pure, liftA, liftA2, )-import Control.Monad.Trans.State (evalState, )--import Data.Tuple.HT (mapPair, )--{--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 qualified Algebra.RealRing as RealRing-import qualified Algebra.Additive as Additive--}---- import NumericPrelude.Numeric (zero, round, (^?), )-import Prelude hiding (Real, round, break, )---vectorChunkSize :: SVL.ChunkSize-vectorChunkSize =- case Play.defaultChunkSize of- SVL.ChunkSize size ->- SVL.ChunkSize (divUp size vectorSize)--sampleRatePlain :: Num a => a-sampleRatePlain = Option.defaultSampleRate--sampleRate :: Option.SampleRate Real-sampleRate = Option.SampleRate Option.defaultSampleRate--{- |-try to reproduce a space leak--}-sequencePlain :: IO ()-sequencePlain =- SVL.writeFile "test.f32" $--- print $ last $ SVL.chunks $- CutSt.arrange Option.defaultChunkSize $- evalState (Gen.sequence Option.defaultChannel (error "no sound" :: Instrument Real Real)) $- let evs = EventList.cons 10 [] evs- in evs--sequenceLLVM :: IO ()-sequenceLLVM = do- arrange <- SigStL.makeArranger- SVL.writeFile "test.f32" $--- print $ last $ SVL.chunks $- arrange vectorChunkSize $- evalState (Gen.sequence Option.defaultChannel (error "no sound" :: Instrument Real Vector)) $- let evs = EventList.cons 10 [] evs- in evs--sequencePitchBendCycle :: IO ()-sequencePitchBendCycle = do- arrange <- SigStL.makeArranger- SVL.writeFile "test.f32" $- arrange vectorChunkSize $- evalState- (let -- fm = error "undefined pitch bend"- fm = EventListBT.cons 1 10 fm- in Gen.sequenceModulated fm Option.defaultChannel- (error "no sound" ::- PC.T Real -> Instrument Real Vector)) $- let evs = EventList.cons 10 [] evs- in evs--sequencePitchBendSimple :: IO ()-sequencePitchBendSimple = do- arrange <- SigStL.makeArranger- SVL.writeFile "test.f32" $- arrange vectorChunkSize $- evalState- (let fm y = EventListBT.cons y 10 (fm (2-y))- in Gen.sequenceModulated (fm 1) Option.defaultChannel- (error "no sound" ::- PC.T Real -> Instrument Real Vector)) $- let evs = EventList.cons 10 [] evs- in evs--sequencePitchBend :: IO ()-sequencePitchBend = do- arrange <- SigStL.makeArranger- SVL.writeFile "test.f32" $- arrange vectorChunkSize $- evalState- (do fm <- PC.pitchBend Option.defaultChannel 2 0.01- Gen.sequenceModulated fm Option.defaultChannel- (error "no sound" ::- PC.T Real -> Instrument Real Vector)) $- let evs = EventList.cons 10 [] evs- in evs--sequenceModulated :: IO ()-sequenceModulated = do- arrange <- SigStL.makeArranger- SVL.writeFile "test.f32" $- arrange vectorChunkSize $- evalState- (do fm <- PC.bendWheelPressure Option.defaultChannel 2 0.04 0.03- Gen.sequenceModulated fm Option.defaultChannel- (error "no sound" ::- PC.T (BM.T Real) ->- Instrument Real Vector)) $- let evs = EventList.cons 10 [] evs- in evs--sequenceModulatedLong :: IO ()-sequenceModulatedLong = do- arrange <- SigStL.makeArranger--- sound <- Instr.softStringReleaseEnvelope $/ sampleRate- sound <- Instr.softString $/ sampleRate -- space leak--- sound <- Instr.pingReleaseEnvelope $/ 1 $/ sampleRate -- no space leak--- sound <- Instr.pingRelease $/ 1 $/ 1 $/ sampleRate -- no space leak- SVL.writeFile "test.f32" $- arrange vectorChunkSize $- evalState (Gen.sequence Option.defaultChannel sound) $- let evs t = EventList.cons t [] (evs (20-t))- in EventList.cons 10 [makeNote Event.NoteOn 60] $- EventList.cons 10 [makeNote Event.NoteOn 64] $- evs 10--sequenceModulatedLongFM :: IO ()-sequenceModulatedLongFM = do- arrange <- SigStL.makeArranger- sound <- Instr.softStringFM- SVL.writeFile "test.f32" $- arrange vectorChunkSize $- evalState- (do fm <- PC.bendWheelPressure Option.defaultChannel 2 0.04 0.03- Gen.sequenceModulated fm Option.defaultChannel- (\fmlocal -> sound fmlocal $ sampleRate)) $- let evs t = EventList.cons t [] (evs (20-t))- in EventList.cons 10 [makeNote Event.NoteOn 60] $- EventList.cons 10 [makeNote Event.NoteOn 64] $- evs 10--sequenceModulatedRepeat :: IO ()-sequenceModulatedRepeat = do- arrange <- SigStL.makeArranger- sound <- Instr.softStringFM- SVL.writeFile "test.f32" $- arrange vectorChunkSize $- evalState- (do fm <- PC.bendWheelPressure Option.defaultChannel 2 0.04 0.03- Gen.sequenceModulated fm Option.defaultChannel- (\fmlocal -> sound fmlocal $ sampleRate)) $- let evs t =- EventList.cons t [makeNote Event.NoteOn 60] $- EventList.cons t [makeNote Event.NoteOff 60] $- evs (20-t)- in evs 10--sequencePress :: IO ()-sequencePress = do- arrange <- SigStL.makeArranger--- sound <- Instr.softString $/ sampleRate--- sound <- Instr.softStringReleaseEnvelope $/ sampleRate- sound <- Instr.pingReleaseEnvelope $/ 1 $/ 1 $/ vectorChunkSize $/ sampleRate- SVL.writeFile "test.f32" $- arrange vectorChunkSize $- evalState- (Gen.sequence Option.defaultChannel (\ _freq -> sound)) $- let evs t =- EventList.cons t [makeNote Event.NoteOn 60] $- EventList.cons t [makeNote Event.NoteOff 60] $- evs (20-t)- in evs 10---sampledSoundTest0 ::- IO (Instr.SampledSound ->- PC.T (BM.T Real) ->- Instrument Real (Stereo.T Vector))-sampledSoundTest0 =- liftA- (\osc smp _fm _vel _freq _dur ->- osc Option.defaultChunkSize (sampleData smp))- (SigP.runChunky- (let smp = arr id- in fmap (\x -> Stereo.cons x x) $- SigPS.pack $- SigP.fromStorableVectorLazy smp))--sampledSoundTest1 ::- IO (Instr.SampledSound ->- PC.T (BM.T Real) ->- Instrument Real (Stereo.T Vector))-sampledSoundTest1 =- liftA- (\osc smp _fm _vel _freq _dur ->- osc Option.defaultChunkSize (sampleData smp))- (SigP.runChunky- (let smp = arr id- in CausalP.stereoFromMono- (CausalPS.pack- (CausalP.frequencyModulationLinear- (SigP.fromStorableVectorLazy smp)))- $* liftA2 Stereo.cons- (SigPS.constant 0.999)- (SigPS.constant 1.001)))--- $* (SigPS.constant $# Stereo.cons 0.999 1.001)))--sampledSoundTest2 ::- IO (Instr.SampledSound ->- PC.T (BM.T Real) ->- Instrument Real (Stereo.T Vector))-sampledSoundTest2 =- liftA- (\osc smp fm _vel freq dur ->- let pos = samplePositions smp- body =- SigSt.take (sampleLength pos) $- SigSt.drop (sampleStart pos) $- sampleData smp- in SVP.take (chunkSizesFromLazyTime dur) $- osc Option.defaultChunkSize- (sampleRate, (body, (fm, freq * samplePeriod smp))))- (SigP.runChunky- (let smp = signal fst- fm = Instr.modulation snd- in (CausalP.stereoFromMono- (CausalPS.pack- (CausalP.frequencyModulationLinear- (SigP.fromStorableVectorLazy smp)))- <<<- liftA2 Stereo.cons- (CausalPS.amplify 0.999)- (CausalPS.amplify 1.001))- $* Instr.frequencyFromBendModulation (frequencyConst 3) fm))--sampledSoundTest3SpaceLeak ::- IO (Instr.SampledSound ->- PC.T (BM.T Real) ->- Instrument Real (Stereo.T Vector))-sampledSoundTest3SpaceLeak =- liftA- (\osc smp _fm vel freq dur ->- {-- We split the frequency modulation signal- in order to get a smooth frequency modulation curve.- Without (periodic) frequency modulation- we could just split the piecewise constant control curve @fm@.- -}- let (sustainFM, releaseFM) =- SVP.splitAt (chunkSizesFromLazyTime dur) $- (SigSt.repeat Option.defaultChunkSize- (LLVM.vector [freq*samplePeriod smp/sampleRatePlain])- :: SigSt.T Vector)- pos = samplePositions smp- amp = 2 * amplitudeFromVelocity vel- (attack,sustain) =- mapPair- (SigSt.drop (sampleStart pos),- SigSt.take (sampleLoopLength pos)) $- SigSt.splitAt (sampleLoopStart pos) $- sampleData smp- release =- SigSt.drop (sampleLoopStart pos + sampleLoopLength pos) $- SigSt.take (sampleStart pos + sampleLength pos) $- sampleData smp- in osc- (amp,- attack `SigSt.append`- SVL.cycle (SigSt.take (sampleLoopLength pos) sustain))- sustainFM- `SigSt.append`- osc (amp,release) releaseFM)- (CausalP.runStorableChunky- (let smp = arr snd- amp = arr fst- in CausalPS.amplifyStereo amp- <<<- CausalP.stereoFromMono- (CausalPS.pack- (CausalP.frequencyModulationLinear- (SigP.fromStorableVectorLazy smp)))- <<<- liftA2 Stereo.cons- (CausalPS.amplify 0.999)- (CausalPS.amplify 1.001)))--sampledSoundTest4NoSpaceLeak ::- IO (Instr.SampledSound ->- PC.T (BM.T Real) ->- Instrument Real (Stereo.T Vector))-sampledSoundTest4NoSpaceLeak =- liftA- (\freqMod smp fm _vel freq dur ->- {-- We split the frequency modulation signal- in order to get a smooth frequency modulation curve.- Without (periodic) frequency modulation- we could just split the piecewise constant control curve @fm@.- -}- let (sustainFM, releaseFM) =- SVP.splitAt (chunkSizesFromLazyTime dur) $- (freqMod- (chunkSizesFromLazyTime (PC.duration fm))- (sampleRate, (fm, freq*samplePeriod smp)) :: SigSt.T Vector)- in SigSt.map- (\x -> Stereo.cons x x)- (sustainFM `SigSt.append` releaseFM))- (SigP.runChunkyPattern- (Instr.frequencyFromBendModulation- (frequencyConst 3) (Instr.modulation id)))--sampledSoundTest5LargeSpaceLeak ::- IO (Instr.SampledSound ->- PC.T (BM.T Real) ->- Instrument Real (Stereo.T Vector))-sampledSoundTest5LargeSpaceLeak =- liftA2- (\osc freqMod smp fm vel freq dur ->- {-- We split the frequency modulation signal- in order to get a smooth frequency modulation curve.- Without (periodic) frequency modulation- we could just split the piecewise constant control curve @fm@.- -}- let (sustainFM, releaseFM) =- SVP.splitAt (chunkSizesFromLazyTime dur) $- (freqMod- (chunkSizesFromLazyTime (PC.duration fm))- (sampleRate, (fm, freq*samplePeriod smp)) :: SigSt.T Vector)- pos = samplePositions smp- amp = 2 * amplitudeFromVelocity vel- (attack,sustain) =- mapPair- (SigSt.drop (sampleStart pos),- SigSt.take (sampleLoopLength pos)) $- SigSt.splitAt (sampleLoopStart pos) $- sampleData smp- release =- SigSt.drop (sampleLoopStart pos + sampleLoopLength pos) $- SigSt.take (sampleStart pos + sampleLength pos) $- sampleData smp- in osc- (amp,- attack `SigSt.append`- SVL.cycle (SigSt.take (sampleLoopLength pos) sustain))- sustainFM- `SigSt.append`- osc (amp,release) releaseFM)- (CausalP.runStorableChunky- (arr (\x -> Stereo.cons x x)))- (SigP.runChunkyPattern- (Instr.frequencyFromBendModulation- (frequencyConst 3) (Instr.modulation id)))---sampledSoundSmallSpaceLeak4 ::- IO (Instr.SampledSound ->- PC.T (BM.T Real) ->- Instrument Real (Stereo.T Vector))-sampledSoundSmallSpaceLeak4 =- liftA- (\osc smp _fm _vel freq dur ->- let (sustainFM, releaseFM) =- SVP.splitAt (chunkSizesFromLazyTime dur) $- (SigSt.repeat Option.defaultChunkSize- (LLVM.vector [freq*samplePeriod smp/sampleRatePlain])- :: SigSt.T Vector)- in osc () sustainFM- `SigSt.append`- SigSt.map (\x -> Stereo.cons x x) releaseFM)- (CausalP.runStorableChunky- (arr (\x -> Stereo.cons x x)))--sampledSoundSmallSpaceLeak4a ::- IO (Instr.SampledSound ->- PC.T (BM.T Real) ->- Instrument Real (Stereo.T Vector))-sampledSoundSmallSpaceLeak4a =- liftA- (\osc smp _fm _vel freq dur ->- case SVP.splitAt (chunkSizesFromLazyTime dur) $- (SigSt.repeat Option.defaultChunkSize- (LLVM.vector [freq*samplePeriod smp/sampleRatePlain])- :: SigSt.T Vector) of- (sustainFM, releaseFM) ->- osc () sustainFM- `SigSt.append`- SigSt.map (\x -> Stereo.cons x x) releaseFM)- (CausalP.runStorableChunky- (arr (\x -> Stereo.cons x x)))--sampledSoundNoSmallSpaceLeak3 ::- IO (Instr.SampledSound ->- PC.T (BM.T Real) ->- Instrument Real (Stereo.T Vector))-sampledSoundNoSmallSpaceLeak3 =- pure- (\smp _fm _vel freq dur ->- let (sustainFM, releaseFM) =- SVP.splitAt (chunkSizesFromLazyTime dur) $- (SigSt.repeat Option.defaultChunkSize- (LLVM.vector [freq*samplePeriod smp/sampleRatePlain])- :: SigSt.T Vector)- in SigSt.map (\x -> Stereo.cons x x) sustainFM- `SigSt.append`- SigSt.map (\x -> Stereo.cons x x) releaseFM)--{-# NOINLINE amplifySVL #-}-amplifySVL :: SVL.Vector Vector -> SVL.Vector Vector-amplifySVL = SigSt.map (2*)--sampledSoundNoSmallSpaceLeak2 ::- IO (Instr.SampledSound ->- PC.T (BM.T Real) ->- Instrument Real (Stereo.T Vector))-sampledSoundNoSmallSpaceLeak2 =- liftA- (\osc smp _fm _vel freq dur ->- let (sustainFM, releaseFM) =- SVP.splitAt (chunkSizesFromLazyTime dur) $- (SigSt.repeat Option.defaultChunkSize- (LLVM.vector [freq*samplePeriod smp/sampleRatePlain])- :: SigSt.T Vector)- in osc ()- (amplifySVL sustainFM- `SigSt.append`- amplifySVL releaseFM))- (CausalP.runStorableChunky- (arr (\x -> Stereo.cons x x)))--sampledSoundSmallSpaceLeak1 ::- IO (Instr.SampledSound ->- PC.T (BM.T Real) ->- Instrument Real (Stereo.T Vector))-sampledSoundSmallSpaceLeak1 =- liftA- (\osc smp _fm _vel freq dur ->- let (sustainFM, releaseFM) =- SVP.splitAt (chunkSizesFromLazyTime dur) $- (SigSt.repeat Option.defaultChunkSize- (LLVM.vector [freq*samplePeriod smp/sampleRatePlain])- :: SigSt.T Vector)- in osc () sustainFM- `SigSt.append`- osc () releaseFM)- (CausalP.runStorableChunky- (arr (\x -> Stereo.cons x x)))--sampledSoundSmallSpaceLeak0 ::- IO (Instr.SampledSound ->- PC.T (BM.T Real) ->- Instrument Real (Stereo.T Vector))-sampledSoundSmallSpaceLeak0 =- liftA- (\osc smp _fm vel freq dur ->- {-- We split the frequency modulation signal- in order to get a smooth frequency modulation curve.- Without (periodic) frequency modulation- we could just split the piecewise constant control curve @fm@.- -}- let (sustainFM, releaseFM) =- SVP.splitAt (chunkSizesFromLazyTime dur) $- (SigSt.repeat Option.defaultChunkSize- (LLVM.vector [freq*samplePeriod smp/sampleRatePlain])- :: SigSt.T Vector)- pos = samplePositions smp- amp = 2 * amplitudeFromVelocity vel- (attack,sustain) =- mapPair- (SigSt.drop (sampleStart pos),- SigSt.take (sampleLoopLength pos)) $- SigSt.splitAt (sampleLoopStart pos) $- sampleData smp- release =- SigSt.drop (sampleLoopStart pos + sampleLoopLength pos) $- SigSt.take (sampleStart pos + sampleLength pos) $- sampleData smp- in osc- (amp,- attack `SigSt.append`- SVL.cycle (SigSt.take (sampleLoopLength pos) sustain))- sustainFM- `SigSt.append`- osc (amp,release) releaseFM)- (CausalP.runStorableChunky- (arr (\x -> Stereo.cons x x)))----sequenceSample :: IO ()-sequenceSample = do- arrange <- SigStL.makeArranger- sampler <- sampledSoundTest2- let sound =- sampler (Instr.SampledSound (SigSt.replicate Option.defaultChunkSize 100000 0)- (Instr.SamplePositions 0 100000 50000 50000)- 100)- SVL.writeFile "test.f32" $- arrange vectorChunkSize $- evalState- (do fm <- PC.bendWheelPressure Option.defaultChannel 2 0.04 0.03- Gen.sequenceModulated fm Option.defaultChannel sound) $- let evs t = EventList.cons t [] (evs (20-t))- in EventList.cons 10 [makeNote Event.NoteOn 60] $- evs 10--{--sequenceSample1 :: IO ()-sequenceSample1 = do- sampler <- Instr.sampledSound- let sound =- sampler (SampledSound (SigSt.replicate Option.defaultChunkSize 100000 0)- (SamplePositions 0 100000 50000 50000)- 100)- SVL.writeFile "test.f32" $- sound-{-- (let evs f =- EventListBT.cons (BM.Cons 0.001 f) 10 (evs (0.02-f))- in evs 0.01)--}- (let evs t =- EventListBT.cons (BM.Cons 0.01 0.001) t (evs (20-t))- in evs 10)-{-- (PCS.Cons- (Map.singleton- (PC.Controller VoiceMsg.modulation) 1)- (let evs t = EventList.cons t [] (evs (20-t))- in EventListMT.consTime 10 $ evs 10))--}- 0.01 1--- (NonNegChunky.fromChunks $ repeat $ NonNegW.fromNumber 10)- (NonNegChunky.fromChunks $ map NonNegW.fromNumber $ iterate (20-) 10)--}--sequenceSample1 :: IO ()-sequenceSample1 = do- sampler <- sampledSoundSmallSpaceLeak4a- let sound =- sampler (Instr.SampledSound (SigSt.replicate Option.defaultChunkSize 100000 0)- (Instr.SamplePositions 0 100000 50000 50000)- 100)- SVL.writeFile "test.f32" $- sound- (let evs = EventListBT.cons (BM.Cons 0.01 0.001) 1 evs- in evs)- 0.01 1- (NonNegChunky.fromChunks $ repeat $ NonNegW.fromNumber 10)--{--sequenceSample1a :: IO ()-sequenceSample1a = do-{-- makeStereoLLVM <-- CausalP.runStorableChunky2 -- NoSpaceLeak- (arr (\x -> Stereo.cons x x))- let stereoLLVM = makeStereoLLVM ()--}- stereoLLVM <- CausalP.runStorableChunky3- let stereoPlain = SigSt.map (\x -> Stereo.cons x x)- SVL.writeFile "test.f32" $- let dur = NonNegChunky.fromChunks $ repeat $ SVL.chunkSize 10- !(sustainFM, releaseFM) =- SVP.splitAt dur $- (SigSt.repeat Option.defaultChunkSize (LLVM.vector [1])- :: SigSt.T Vector)- in case 3::Int of- -- no leak- 0 -> stereoLLVM $ sustainFM `SigSt.append` releaseFM- -- no leak- 1 -> stereoPlain $ sustainFM `SigSt.append` releaseFM- -- no leak- 2 -> stereoPlain sustainFM `SigSt.append` stereoPlain releaseFM- -- leak- 3 -> stereoLLVM sustainFM `SigSt.append` stereoPlain releaseFM- -- no leak- 4 -> stereoPlain sustainFM `SigSt.append` stereoLLVM releaseFM- -- leak- 5 -> stereoLLVM sustainFM `SigSt.append` stereoLLVM releaseFM--}--sequenceSample2 :: IO ()-sequenceSample2 = do- arrange <- SigStL.makeArranger- sampler <- sampledSoundTest2- let sound =- sampler (Instr.SampledSound (SigSt.replicate Option.defaultChunkSize 100000 0)- (Instr.SamplePositions 0 100000 50000 50000)- 100)- SVL.writeFile "test.f32" $- arrange vectorChunkSize $- evalState- (do bend <- PC.pitchBend Option.defaultChannel 2 0.01- let fm = fmap (\t -> BM.Cons t t) bend- Gen.sequenceModulated fm Option.defaultChannel sound) $- let evs t = EventList.cons t [] (evs (20-t))- in EventList.cons 10 [makeNote Event.NoteOn 60] $- evs 10--{--Interestingly, when the program aborts because of heap exhaustion,-then the generated file has size 137MB independent of the heap size-(I tried sizes from 1MB to 64MB).--}-sequenceSample3 :: IO ()-sequenceSample3 = do- arrange <- SigStL.makeArranger- sampler <- sampledSoundTest2- let sound =- sampler (Instr.SampledSound (SigSt.replicate Option.defaultChunkSize 100000 0)- (Instr.SamplePositions 0 100000 50000 50000)- 100)- SVL.writeFile "test.f32" $- arrange vectorChunkSize $- evalState- (let evs =- EventListBT.cons (BM.Cons 0.01 0.001) 10 evs- in Gen.sequence Option.defaultChannel (sound evs)) $- let evs = EventList.cons 10 [] evs- in EventList.cons 10 [makeNote Event.NoteOn 60] evs--sequenceSample4 :: IO ()-sequenceSample4 = do- arrange <- SigStL.makeArranger- sampler <- Instr.sampledSound--- sampler <- sampledSoundTest2- let sound =- sampler (Instr.SampledSound (SigSt.replicate Option.defaultChunkSize 100000 0)- (Instr.SamplePositions 0 100000 50000 50000)- 100)- SVL.writeFile "test.f32" $- arrange vectorChunkSize $- evalState- (let evs =- EventListBT.cons (BM.Cons 0.01 0.001) 10 evs- in Gen.sequenceCore- Option.defaultChannel Gen.errorNoProgram- (Gen.Modulator () return- (return . Gen.renderInstrumentIgnoreProgram (sound evs sampleRate)))) $- let evs = EventList.cons 10 [] evs- in EventList.cons 10 [makeNote Event.NoteOn 60] evs--sequenceFM1 :: IO ()-sequenceFM1 = do- arrange <- SigStL.makeArranger- sound <- Instr.softStringFM $/- let evs =- EventListBT.cons (BM.Cons 0.01 0.001) 10 evs- in evs--- sound <- Instr.softStringReleaseEnvelope- SVL.writeFile "test.f32" $- arrange vectorChunkSize $- evalState- (Gen.sequenceCore- Option.defaultChannel Gen.errorNoProgram- (Gen.Modulator () return- (return . Gen.renderInstrumentIgnoreProgram (sound sampleRate)))) $- let evs = EventList.cons 10 [] evs- in EventList.cons 10 [makeNote Event.NoteOn 60] evs-{-- sound- 0.01 1- (NonNegChunky.fromChunks $ map NonNegW.fromNumber $ iterate (20-) 10)--}---adsr :: IO ()-adsr = do- env <- Instr.adsr- SVL.writeFile "adsr.f32" $- env 0.2 2 0.15 0.3 0.5 vectorChunkSize sampleRate (-0.5) 88200---constCtrl :: a -> PC.T a-constCtrl x =- let xs = EventListBT.cons x 10000 xs- in xs--bellNoiseStereoTest :: IO ()-bellNoiseStereoTest = do- str <- Instr.bellNoiseStereoFM- SVL.writeFile "bellnoise.f32" $- str 0.3 0.1 (constCtrl 0.3) (constCtrl 100)- vectorChunkSize- (constCtrl (BM.Cons 1 0.01)) sampleRate 0 440- 100000
+ src/Synthesizer/LLVM/Server/SampledSound.hs view
@@ -0,0 +1,100 @@+module Synthesizer.LLVM.Server.SampledSound where++import Synthesizer.LLVM.Server.Common (Real, )++import qualified Sound.Sox.Read as SoxRead+import qualified Sound.Sox.Option.Format as SoxOption+import Control.Exception (bracket, )++import qualified Synthesizer.Storable.Signal as SigSt+import qualified Data.StorableVector.Lazy as SVL++import Data.Tuple.HT (mapPair, )++import Prelude hiding (Real, length, )++++data T =+ Cons {+ body :: SigSt.T Real,+ positions :: Positions,+ period :: Real+ }++data Positions =+ Positions {+ start, length,+ loopStart, loopLength :: Int+ }+++load :: FilePath -> IO (SVL.Vector Real)+load path =+ bracket (SoxRead.open SoxOption.none path) SoxRead.close $+ SoxRead.withHandle1 (SVL.hGetContentsSync SVL.defaultChunkSize)+++type Info = (FilePath, [Positions], Real)+++parts :: T -> (SigSt.T Real, SigSt.T Real, SigSt.T Real)+parts smp =+ let pos = positions smp+ (attack,sustain) =+ mapPair+ (SigSt.drop (start pos),+ SigSt.take (loopLength pos)) $+ SigSt.splitAt (loopStart pos) $+ body smp+ release =+ SigSt.drop (loopStart pos + loopLength pos) $+ SigSt.take (start pos + length pos) $+ body smp+ in (attack, sustain, release)++++-- * examples++tomatensalatPositions :: [Positions]+tomatensalatPositions =+ Positions 0 29499 12501 15073 :+ Positions 29499 31672 38163 17312 :+ Positions 67379 28610 81811 10667 :+ Positions 95989 31253 106058 16111 :+ Positions 127242 38596 136689 11514 :+ []++tomatensalat :: Info+tomatensalat =+ ("tomatensalat2.wav", tomatensalatPositions, 324.5)+++halPositions :: [Positions]+halPositions =+-- Positions 2371 25957 7362 6321 :+ Positions 2371 25957 (2371+25957) 1 :+ Positions 40546 34460 63540 9546 :+ Positions 79128 32348 94367 14016 :+ Positions 112027 21227 125880 5500 :+ Positions 146057 23235 168941 352 :+ []++hal :: Info+hal =+ ("haskell-in-leipzig2.wav", halPositions, 316)+++graphentheoriePositions :: [Positions]+graphentheoriePositions =+ Positions 0 29524 13267 14768 :+ Positions 29524 35333 47624 9968 :+ Positions 64857 31189 73818 16408 :+ Positions 96046 31312 106206 18504 :+ Positions 127358 32127 132469 16530 :+ []++graphentheorie :: Info+graphentheorie =+ ("graphentheorie0.wav", graphentheoriePositions, 301.15)
src/Synthesizer/LLVM/Server/Scalar/Instrument.hs view
@@ -10,8 +10,8 @@ import qualified LLVM.Core as LLVM -import qualified Synthesizer.EventList.ALSA.MIDI as Ev-import Synthesizer.Storable.ALSA.MIDI (chunkSizesFromLazyTime, )+import qualified Synthesizer.MIDI.EventList as Ev+import Synthesizer.MIDI.Storable (chunkSizesFromLazyTime, ) import qualified Synthesizer.Storable.Signal as SigSt import qualified Data.StorableVector.Lazy.Pattern as SigStV@@ -160,7 +160,8 @@ (attack, sustain) = SigSt.splitAt attackTimeInt $ env (chunkSizesFromLazyTime dur)- (attackTimeInt, amplitudeFromVelocity vel)+ (fromIntegral attackTimeInt :: Real,+ amplitudeFromVelocity vel) release = SigSt.reverse attack in attack `SigSt.append` sustain `SigSt.append` release) (let amp = arr snd@@ -168,7 +169,7 @@ in SigP.runChunkyPattern $ flip SigP.append (SigP.constant amp) $ SigP.amplify amp $- (SigP.parabolaFadeIn (fmap fromIntegral attackTime)))+ (SigP.parabolaFadeIn attackTime)) softString :: IO (Instrument Real (Stereo.T Real)) softString =
− src/Synthesizer/LLVM/Server/Scalar/Run.hs
@@ -1,147 +0,0 @@-module Synthesizer.LLVM.Server.Scalar.Run where--import qualified Synthesizer.LLVM.Server.Scalar.Instrument as Instr-import qualified Synthesizer.LLVM.Server.Option as Option-import Synthesizer.LLVM.Server.Common--import qualified Sound.ALSA.Sequencer.Event as Event-import qualified Data.EventList.Relative.TimeBody as EventList--import qualified Synthesizer.EventList.ALSA.MIDI as Ev-import qualified Synthesizer.PiecewiseConstant.ALSA.MIDI as PC-import qualified Synthesizer.Generic.ALSA.MIDI as Gen--import qualified Synthesizer.LLVM.Frame.Stereo as Stereo--import qualified Synthesizer.LLVM.ALSA.MIDI as MIDIL-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 Synthesizer.Storable.Signal as SigSt--import qualified Sound.MIDI.Message.Channel.Voice as VoiceMsg--import Control.Arrow ((<<<), arr, )-import Control.Monad.Trans.State (evalState, )--import NumericPrelude.Numeric (zero, (*>), )-import Prelude hiding (Real, break, )---sampleRate :: Num a => Option.T -> a-sampleRate opt =- case Option.sampleRate opt of- SampleRate sr -> sr--{-# INLINE withMIDIEvents #-}-withMIDIEvents ::- Option.T ->- (Option.T -> Double -> a -> IO b) ->- (EventList.T Ev.StrictTime [Event.T] -> a) -> IO b-withMIDIEvents opt action proc =- let rate = sampleRate opt- in do- putStrLn startMessage- Ev.withMIDIEvents- (Option.clientName opt) (Option.periodTime opt) rate $- action opt rate . proc----pitchBend :: IO ()-pitchBend = do- opt <- Option.get- osc <-- SigP.runChunky- ((CausalP.osciSimple WaveL.triangle $<# (zero::Real))- $* piecewiseConstant (arr id))- withMIDIEvents opt play $- (id :: SigSt.T Real -> SigSt.T Real) .- osc (Option.chunkSize opt) .- evalState (PC.pitchBend (Option.channel opt) 2 (880/sampleRate opt::Real))---frequencyModulation :: IO ()-frequencyModulation = do- opt <- Option.get- osc <-- SigP.runChunky- (((CausalP.osciSimple WaveL.triangle $<# (zero::Real))- <<< (MIDIL.frequencyFromBendModulation $# (10/sampleRate opt::Real)))- $* piecewiseConstant (arr (transposeModulation (Option.sampleRate opt) 880)))- withMIDIEvents opt play $- (id :: SigSt.T Real -> SigSt.T Real) .- osc (Option.chunkSize opt) .- evalState (PC.bendWheelPressure (Option.channel opt) 2 0.04 (0.03::Real))----keyboard :: IO ()-keyboard = do- opt <- Option.get--- sound <- Instr.pingDur-{-- sound <-- fmap (\s vel _freq dur -> s vel dur) $- (Instr.pingReleaseEnvelope $/ 0.4 $/ 0.1)--}- sound <- Instr.pingRelease $/ 0.4 $/ 0.1- amp <- CausalP.runStorableChunky (CausalP.amplify $# 0.2)- arrange <- SigStL.makeArranger- withMIDIEvents opt play $- (amp () :: SigSt.T Real -> SigSt.T Real) .- arrange (Option.chunkSize opt) .- evalState- (Gen.sequence- (Option.channel opt)- (sound (Option.chunkSize opt) (Option.sampleRate opt)))--keyboardStereo :: IO ()-keyboardStereo = do- opt <- Option.get- sound <- Instr.pingStereoRelease $/ 0.4 $/ 0.1- amp <- CausalP.runStorableChunky (CausalP.amplifyStereo $# 0.2)- arrange <- SigStL.makeArranger- withMIDIEvents opt play $- (amp () :: SigSt.T (Stereo.T Real) -> SigSt.T (Stereo.T Real)) .- arrange (Option.chunkSize opt) .- evalState- (Gen.sequence- (Option.channel opt)- (sound (Option.chunkSize opt) (Option.sampleRate opt)))--keyboardMulti :: IO ()-keyboardMulti = do- opt <- Option.get- png <- Instr.pingDur- pngRel <- Instr.pingRelease $/ 0.4 $/ 0.1 $/ Option.chunkSize opt- tin <- Instr.tine $/ 0.4 $/ 0.1 $/ Option.chunkSize opt- arrange <- SigStL.makeArranger- withMIDIEvents opt play $--- playALSA (Bld.put :: Int16 -> Bld.Builder Int16) (sampleRate opt::Real) .- SigSt.map (0.2*) .- arrange (Option.chunkSize opt) .- evalState (Gen.sequenceMultiProgram (Option.channel opt)- (VoiceMsg.toProgram 2)- (map (\sound -> sound $ Option.sampleRate opt) $- [png, pngRel, tin]))--keyboardStereoMulti :: IO ()-keyboardStereoMulti = do- opt <- Option.get- png <- Instr.pingStereoRelease $/ 0.4 $/ 0.1 $/ Option.chunkSize opt- tin <- Instr.tineStereo $/ 0.4 $/ 0.1 $/ Option.chunkSize opt- str <- Instr.softString- arrange <- SigStL.makeArranger- withMIDIEvents opt play $--- playALSA (Bld.put :: Int16 -> Bld.Builder Int16) (sampleRate opt::Real) .- SigSt.map ((0.2::Real)*>) .- arrange (Option.chunkSize opt) .- evalState (Gen.sequenceMultiProgram (Option.channel opt)- (VoiceMsg.toProgram 1)- (map (\sound -> sound $ Option.sampleRate opt) $- [png, tin, str]))
− src/Synthesizer/LLVM/Server/Scalar/Test.hs
@@ -1,85 +0,0 @@-module Synthesizer.LLVM.Server.Scalar.Test where--import qualified Synthesizer.LLVM.Server.Scalar.Instrument as Instr-import qualified Synthesizer.LLVM.Server.Option as Option-import Synthesizer.LLVM.Server.Scalar.Run (withMIDIEvents, )-import Synthesizer.LLVM.Server.Common--import qualified Sound.ALSA.Sequencer.Event as Event-import qualified Synthesizer.PiecewiseConstant.ALSA.MIDI as PC-import qualified Synthesizer.Generic.ALSA.MIDI as Gen--import qualified Synthesizer.LLVM.CausalParameterized.Process as CausalP-import qualified Synthesizer.LLVM.Parameterized.Signal as SigP-import qualified Synthesizer.LLVM.Wave as WaveL-import Synthesizer.LLVM.CausalParameterized.Process (($<#), ($*), )--import qualified Synthesizer.Storable.Cut as CutSt-import qualified Synthesizer.Storable.Signal as SigSt-import qualified Data.StorableVector.Lazy as SVL--import qualified Data.EventList.Relative.TimeBody as EventList--import Control.Arrow (arr, )-import Control.Monad.Trans.State (evalState, )--import NumericPrelude.Numeric (zero, )-import Prelude hiding (Real, )---sampleRate :: Real-sampleRate =- Option.defaultSampleRate---pitchBend0 :: IO ()-pitchBend0 = do- osc <-- SigP.runChunky- ((CausalP.osciSimple WaveL.triangle $<# (zero::Real))- $* piecewiseConstant (arr id))- SVL.writeFile "test.f32" $- (id :: SigSt.T Real -> SigSt.T Real) .- osc Option.defaultChunkSize .- evalState (PC.pitchBend Option.defaultChannel 2 (880/sampleRate)) $- let evs = EventList.cons 100 [] evs- in EventList.cons 0 [] evs--pitchBend1 :: IO ()-pitchBend1 = do- opt <- Option.get- osc <-- SigP.runChunky- ((CausalP.osciSimple WaveL.triangle $<# (zero::Real))- $* piecewiseConstant (arr id))- withMIDIEvents opt (\ _opt _rate -> SVL.writeFile "test.f32") $- (id :: SigSt.T Real -> SigSt.T Real) .- osc Option.defaultChunkSize .- evalState (PC.pitchBend Option.defaultChannel 2 (880/sampleRate))--pitchBend2 :: IO ()-pitchBend2 = do- opt <- Option.get- withMIDIEvents opt (\ _opt _rate -> print) id----sequencePress :: IO ()-sequencePress = do--- arrange <- SigStL.makeArranger--- sound <- Instr.softString--- sound <- Instr.softStringReleaseEnvelope--- sound <- Instr.pingReleaseEnvelope $/ 1 $/ Option.defaultChunkSize--- sound <- Instr.pingDur--- sound <- Instr.pingDurTake- let sound = Instr.dummy Option.defaultChunkSize (SampleRate sampleRate)- SVL.writeFile "test.f32" $- CutSt.arrange Option.defaultChunkSize $- evalState- (do Gen.sequence Option.defaultChannel sound) $- let evs t =- EventList.cons t [makeNote Event.NoteOn 60] $- EventList.cons t [makeNote Event.NoteOff 60] $- evs (20-t)- in evs 10-
src/Synthesizer/LLVM/Simple/Signal.hs view
@@ -1,4 +1,5 @@ {-# LANGUAGE NoImplicitPrelude #-}+{-# LANGUAGE TypeFamilies #-} {-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE ExistentialQuantification #-} {-# LANGUAGE Rank2Types #-}@@ -23,7 +24,7 @@ import qualified LLVM.Extra.Arithmetic as A import LLVM.Extra.Arithmetic (advanceArrayElementPtr, ) import LLVM.Extra.Control (whileLoop, ifThen, )-import LLVM.Extra.Class (MakeValueTuple, Undefined, undefTuple, )+import LLVM.Extra.Class (MakeValueTuple, ValueTuple, Undefined, undefTuple, ) import LLVM.Core as LLVM import LLVM.Util.Loop (Phi, )@@ -42,16 +43,17 @@ import Foreign.Storable (Storable, ) import Foreign.Marshal.Array (advancePtr, ) import qualified Synthesizer.LLVM.Alloc as Alloc-import Foreign.ForeignPtr- (unsafeForeignPtrToPtr, touchForeignPtr, withForeignPtr, )+import Foreign.ForeignPtr (touchForeignPtr, withForeignPtr, ) import Foreign.Ptr (FunPtr, nullPtr, ) import Control.Exception (bracket, )-import System.IO.Unsafe (unsafePerformIO, unsafeInterleaveIO, )+import qualified System.Unsafe as Unsafe import NumericPrelude.Numeric import NumericPrelude.Base hiding (and, iterate, map, zip, zipWith, ) +import qualified Prelude as P + {- We need the forall quantification for 'CodeGenFunction's @r@ parameter. This type parameter will be unified with the result type of the final function.@@ -63,8 +65,8 @@ > newtype T a = Cons (Causal.T () a) -} data T a =- forall state packed size ioContext.- (Memory.C state packed, IsSized packed size) =>+ forall state ioContext.+ (Memory.C state) => Cons (forall r c. (Phi c) => ioContext ->@@ -76,14 +78,14 @@ -- initial state (IO ioContext) {- initialization from IO monad- This will be run within unsafePerformIO,+ This will be run within Unsafe.performIO, so no observable In/Out actions please! -} (ioContext -> IO ())- -- finalization from IO monad, also run within unsafePerformIO+ -- finalization from IO monad, also run within Unsafe.performIO simple ::- (Memory.C state packed, IsSized packed size) =>+ (Memory.C state) => (forall r c. state -> Maybe.T r c (a, state)) -> (forall r. CodeGenFunction r state) ->@@ -108,7 +110,7 @@ createIOContext deleteIOContext mapAccum ::- (Memory.C s struct, IsSized struct sa) =>+ (Memory.C s) => (forall r. a -> s -> CodeGenFunction r (b,s)) -> (forall r. CodeGenFunction r s) -> T a -> T b@@ -177,14 +179,27 @@ (/) = zipWith A.fdiv +instance (A.PseudoRing a, A.Real a, A.IntegerConstant a) => P.Num (T a) where+ fromInteger n = pure (A.fromInteger' n)+ negate = map A.neg+ (+) = zipWith A.add+ (-) = zipWith A.sub+ (*) = zipWith A.mul+ abs = map A.abs+ signum = map A.signum++instance (A.Field a, A.Real a, A.RationalConstant a) => P.Fractional (T a) where+ fromRational x = pure (A.fromRational' x)+ (/) = zipWith A.fdiv+ {- | Stretch signal in time by a certain factor. -} interpolateConstant ::- (Memory.C a struct, IsSized struct size,- Memory.FirstClass b bm, IsSized b bsize, IsSized bm bmsize,+ (Memory.C a,+ Memory.FirstClass b, Memory.Stored b ~ bm, IsSized b, IsSized bm, Ring.C b,- IsFloating b, CmpRet b Bool, IsConst b) =>+ IsFloating b, LLVM.CmpRet b, LLVM.CmpResult b ~ Bool, IsConst b) => b -> T a -> T a interpolateConstant k (Cons next start createIOContext deleteIOContext) =@@ -244,7 +259,7 @@ iterate ::- (Memory.FirstClass a am, IsSized a asize, IsSized am amsize, IsConst a) =>+ (Memory.FirstClass a, Memory.Stored a ~ am, IsSized a, IsSized am, IsConst a) => (forall r. Value a -> CodeGenFunction r (Value a)) -> Value a -> T (Value a) iterate f initial =@@ -254,14 +269,14 @@ exponential2 :: (Trans.C a, IsArithmetic a,- Memory.FirstClass a am, IsSized a asize, IsSized am amsize, IsConst a) =>+ Memory.FirstClass a, Memory.Stored a ~ am, IsSized a, IsSized am, IsConst a) => a -> a -> T (Value a) exponential2 halfLife = iterate (\y -> A.mul y (valueOf (0.5 ** recip halfLife))) . valueOf osciPlain ::- (Memory.FirstClass t tm, IsSized t tsize, IsSized tm tmsize,+ (Memory.FirstClass t, Memory.Stored t ~ tm, IsSized t, IsSized tm, SoV.Fraction t, IsConst t) => (forall r. Value t -> CodeGenFunction r y) -> Value t -> Value t -> T y@@ -271,7 +286,7 @@ phase osci ::- (Memory.FirstClass t tm, IsSized t tsize, IsSized tm tmsize,+ (Memory.FirstClass t, Memory.Stored t ~ tm, IsSized t, IsSized tm, SoV.Fraction t, IsConst t) => (forall r. Value t -> CodeGenFunction r y) -> t -> t -> T y@@ -279,8 +294,8 @@ osciPlain wave (valueOf phase) (valueOf freq) osciSaw ::- (Ring.C a0, IsConst a0, SoV.Replicate a0 a,- Memory.FirstClass a am, IsSized a asize, IsSized am amsize,+ (SoV.IntegerConstant a,+ Memory.FirstClass a, Memory.Stored a ~ am, IsSized a, IsSized am, SoV.Fraction a, IsConst a) => a -> a -> T (Value a) osciSaw = osci Wave.saw@@ -288,7 +303,7 @@ fromStorableVector ::- (Storable a, MakeValueTuple a value, Memory.C value struct) =>+ (Storable a, MakeValueTuple a, ValueTuple a ~ value, Memory.C value) => SV.Vector a -> T value fromStorableVector xs =@@ -302,7 +317,7 @@ l1 <- A.dec l0 return (y1,(p1,l1))) (const $ return- (valueOf (Memory.castStorablePtr $ unsafeForeignPtrToPtr fp `advancePtr` s),+ (valueOf (Memory.castStorablePtr $ Unsafe.foreignPtrToPtr fp `advancePtr` s), valueOf (fromIntegral l :: Word32))) -- keep the foreign ptr alive (return fp)@@ -314,7 +329,7 @@ and advances to the next chunk in the sequence. -} fromStorableVectorLazy ::- (Storable a, MakeValueTuple a value, Memory.C value struct) =>+ (Storable a, MakeValueTuple a, ValueTuple a ~ value, Memory.C value) => SVL.Vector a -> T value fromStorableVectorLazy sig =@@ -342,7 +357,7 @@ {- compile ::- (Memory.C value struct) =>+ (Memory.C value) => T value -> CodeGenModule (Function (Word32 -> Ptr struct -> IO Word32)) -}@@ -355,10 +370,10 @@ or compile once. -} render ::- (Storable a, MakeValueTuple a value, Memory.C value struct) =>+ (Storable a, MakeValueTuple a, ValueTuple a ~ value, Memory.C value) => Int -> T value -> SV.Vector a render len (Cons next start createIOContext deleteIOContext) =- unsafePerformIO $+ Unsafe.performIO $ bracket createIOContext deleteIOContext $ \ ioContext -> SVB.createAndTrim len $ \ ptr -> do fill <-@@ -379,9 +394,8 @@ compileChunky ::- (Memory.C value struct,- Memory.C state stateStruct,- IsSized stateStruct stateSize) =>+ (Memory.C value, Memory.Struct value ~ struct,+ Memory.C state, Memory.Struct state ~ stateStruct) => (forall r. state -> Maybe.T r (Value Bool, state) (value, state)) -> (forall r.@@ -420,7 +434,7 @@ runChunky ::- (Storable a, MakeValueTuple a value, Memory.C value struct) =>+ (Storable a, MakeValueTuple a, ValueTuple a ~ value, Memory.C value) => SVL.ChunkSize -> T value -> IO (SVL.Vector a) runChunky (SVL.ChunkSize size) (Cons next start createIOContext deleteIOContext) = do@@ -433,7 +447,7 @@ ioContextPtr <- ForeignPtr.new (deleteIOContext ioContext) False let go =- unsafeInterleaveIO $ do+ Unsafe.interleaveIO $ do v <- withForeignPtr statePtr $ \sptr -> SVB.createAndTrim size $@@ -450,7 +464,7 @@ fmap SVL.fromChunks go renderChunky ::- (Storable a, MakeValueTuple a value, Memory.C value struct) =>+ (Storable a, MakeValueTuple a, ValueTuple a ~ value, Memory.C value) => SVL.ChunkSize -> T value -> SVL.Vector a renderChunky size sig =- unsafePerformIO (runChunky size sig)+ Unsafe.performIO (runChunky size sig)
src/Synthesizer/LLVM/Simple/Value.hs view
@@ -1,24 +1,25 @@ {-# LANGUAGE NoImplicitPrelude #-} {-# LANGUAGE Rank2Types #-} {-# LANGUAGE MultiParamTypeClasses #-}-{-# LANGUAGE FunctionalDependencies #-}-{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE TypeFamilies #-}+{-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE UndecidableInstances #-} module Synthesizer.LLVM.Simple.Value ( T, decons,- twoPi,+ twoPi, square, sqrt,+ max, min, limit, lift0, lift1, lift2,+ unlift0, unlift1, unlift2, constantValue, constant,- Flatten(flatten, unfold), flattenTraversable, unfoldFunctor,++ Flatten(flatten, unfold), Registers,+ flattenTraversable, unfoldFunctor,+ flattenFunction, ) where -import qualified LLVM.Extra.ScalarOrVector as SoV import qualified LLVM.Extra.Arithmetic as A -import LLVM.Core- (CodeGenFunction,- Value, valueOf, CmpRet,- IsArithmetic, IsConst, IsType, IsFloating, )+import LLVM.Core (CodeGenFunction, ) import qualified LLVM.Core as LLVM import qualified Synthesizer.Basic.Phase as Phase@@ -28,7 +29,6 @@ import qualified Control.Monad.Trans.State as MS import Control.Monad (liftM2, liftM3, ) -import qualified Synthesizer.LLVM.Frame as Frame import qualified Synthesizer.LLVM.Frame.Stereo as Stereo -- import qualified Algebra.NormedSpace.Maximum as NormedMax@@ -48,10 +48,11 @@ import qualified Data.Traversable as Trav -import System.IO.Unsafe (unsafePerformIO, )+import qualified System.Unsafe as Unsafe -import NumericPrelude.Numeric-import NumericPrelude.Base+import qualified Prelude as P+import NumericPrelude.Numeric hiding (pi, sqrt, )+import NumericPrelude.Base hiding (min, max, ) {-@@ -68,9 +69,9 @@ > t -> t -> T (Value y) -}-newtype T a = Cons {code :: forall r. Compute r (Value a)}+newtype T a = Cons {code :: forall r. Compute r a} -decons :: T a -> (forall r. LLVM.CodeGenFunction r (Value a))+decons :: T a -> (forall r. LLVM.CodeGenFunction r a) decons value = MS.evalStateT (code value) Vault.empty @@ -78,12 +79,12 @@ type Compute r a = MS.StateT Vault.Vault (LLVM.CodeGenFunction r) a -consUnique :: (forall r. Compute r (Value a)) -> T a+consUnique :: (forall r. Compute r a) -> T a consUnique code0 =- unsafePerformIO $+ Unsafe.performIO $ fmap (consKey code0) Vault.newKey -consKey :: (forall r. Compute r (Value a)) -> Vault.Key (Value a) -> T a+consKey :: (forall r. Compute r a) -> Vault.Key a -> T a consKey code0 key = Cons (do ma <- MS.gets (Vault.lookup key)@@ -98,13 +99,13 @@ We do not require a numeric prelude superclass, thus also LLVM only types like vectors are instances. -}-instance (IsArithmetic a, IsType a) => Additive.C (T a) where- zero = constantValue (LLVM.value LLVM.zero)+instance (A.Additive a) => Additive.C (T a) where+ zero = constantValue A.zero (+) = lift2 A.add (-) = lift2 A.sub negate = lift1 A.neg -instance (IsArithmetic a, SoV.IntegerConstant a) =>+instance (A.PseudoRing a, A.IntegerConstant a) => Ring.C (T a) where one = constantValue (A.fromInteger' 1) (*) = lift2 A.mul@@ -115,15 +116,15 @@ The difference to Module instances on Haskell tuples is, that LLVM vectors cannot be nested. -}-instance (SoV.PseudoModule a v, SoV.IntegerConstant a) =>+instance (A.PseudoModule a v, A.IntegerConstant a) => Module.C (T a) (T v) where- (*>) = lift2 SoV.scale+ (*>) = lift2 A.scale -instance (IsArithmetic a, SoV.IntegerConstant a) => Enum (T a) where- succ x = x + one- pred x = x - one+instance (A.Additive a, A.IntegerConstant a) => Enum (T a) where+ succ x = x + constantValue A.one+ pred x = x - constantValue A.one fromEnum _ = error "CodeGenFunction Value: fromEnum"- toEnum = fromIntegral+ toEnum = constantValue . A.fromInteger' . fromIntegral {- instance (IsArithmetic a, Cmp a b, Num a, IsConst a) => Real (T a) where@@ -136,7 +137,7 @@ toInteger _ = error "CodeGenFunction Value: toInteger" -} -instance (IsFloating a, SoV.RationalConstant a) => Field.C (T a) where+instance (A.Field a, A.RationalConstant a) => Field.C (T a) where (/) = lift2 A.fdiv fromRational' = constantValue . A.fromRational' . fromRational'@@ -146,13 +147,13 @@ properFraction _ = error "CodeGenFunction Value: properFraction" -} -instance (IsFloating a, SoV.RationalConstant a) => Algebraic.C (T a) where+instance (A.Transcendental a, A.RationalConstant a) => Algebraic.C (T a) where sqrt = lift1 A.sqrt root n x = lift2 A.pow x (1 / fromInteger n) x^/r = lift2 A.pow x (fromRational' r) -instance (IsFloating a, SoV.RationalConstant a, Trans.C a) => Trans.C (T a) where- pi = constant pi+instance (A.Transcendental a, A.RationalConstant a) => Trans.C (T a) where+ pi = lift0 A.pi sin = lift1 A.sin cos = lift1 A.cos (**) = lift2 A.pow@@ -163,71 +164,118 @@ acos _ = error "LLVM missing intrinsic: acos" atan _ = error "LLVM missing intrinsic: atan" -{-- sinh x = (exp x - exp (-x)) / 2- cosh x = (exp x + exp (-x)) / 2- asinh x = log (x + sqrt (x*x + 1))- acosh x = log (x + sqrt (x*x - 1))- atanh x = (log (1 + x) - log (1 - x)) / 2--} +instance+ (A.PseudoRing a, A.Real a, A.IntegerConstant a) =>+ P.Num (T a) where+ fromInteger = constantValue . A.fromInteger'+ (+) = lift2 A.add+ (-) = lift2 A.sub+ (*) = lift2 A.mul+ negate = lift1 A.neg+ abs = lift1 A.abs+ signum = lift1 A.signum +instance+ (A.Field a, A.Real a, A.RationalConstant a) =>+ P.Fractional (T a) where+ fromRational =+ constantValue . A.fromRational' . P.fromRational+ (/) = lift2 A.fdiv++instance+ (A.Transcendental a, A.Real a, A.RationalConstant a) =>+ P.Floating (T a) where+ pi = lift0 A.pi+ sin = lift1 A.sin+ cos = lift1 A.cos+ (**) = lift2 A.pow+ exp = lift1 A.exp+ log = lift1 A.log++ asin _ = error "LLVM missing intrinsic: asin"+ acos _ = error "LLVM missing intrinsic: acos"+ atan _ = error "LLVM missing intrinsic: atan"++ sinh x = (exp x - exp (-x)) / 2+ cosh x = (exp x + exp (-x)) / 2+ asinh x = log (x + sqrt (x*x + 1))+ acosh x = log (x + sqrt (x*x - 1))+ atanh x = (log (1 + x) - log (1 - x)) / 2++ twoPi ::- (IsFloating a, IsConst a, Trans.C a) =>+ (A.Transcendental a, A.RationalConstant a) => T a-twoPi = constant (2*pi)-{--twoPi ::- (Cmp a b, P.Floating a, IsConst a, IsFloating a) =>- Compute r a-twoPi = P.fromInteger 2 P.* P.pi+twoPi = 2 * Trans.pi++square ::+ (A.PseudoRing a) =>+ T a -> T a+square = lift1 A.square++{- |+The same as 'Algebraic.sqrt',+but needs only Algebraic constraint, not Transcendental. -}+sqrt ::+ (A.Algebraic a) =>+ T a -> T a+sqrt = lift1 A.sqrt -instance (SoV.Real a, SoV.IntegerConstant a, CmpRet a Bool) =>++min, max :: (A.Real a) => T a -> T a -> T a+min = lift2 A.min+max = lift2 A.max++limit :: (A.Real a) => (T a, T a) -> T a -> T a+limit (l,u) = max l . min u+++instance (A.Real a, A.PseudoRing a, A.IntegerConstant a) => Absolute.C (T a) where abs = lift1 A.abs- signum = lift1 Frame.signum+ signum = lift1 A.signum {- For useful instances with different scalar and vector type, we would need a more flexible superclass. -}-instance (SoV.Real a, SoV.IntegerConstant a, CmpRet a Bool,- SoV.PseudoModule a a) =>+instance (A.Real a, A.IntegerConstant a, A.PseudoModule a a) => NormedSum.C (T a) (T a) where norm = lift1 A.abs -instance (SoV.Real a, SoV.IntegerConstant a, CmpRet a Bool,- SoV.PseudoModule a a) =>+instance (A.Real a, A.IntegerConstant a, A.PseudoModule a a) => NormedEuc.Sqr (T a) (T a) where normSqr = lift1 A.square instance- (Algebraic.C a, NormedEuc.Sqr (T a) (T v), SoV.RationalConstant a, IsFloating a) =>+ (NormedEuc.Sqr (T a) (T v),+ A.RationalConstant a, A.Algebraic a) => NormedEuc.C (T a) (T v) where- norm = NormedEuc.defltNorm+ norm = lift1 A.sqrt . NormedEuc.normSqr {--instance (Ring.C a, IsArithmetic a, IsConst a, CmpRet a Bool) =>+instance (A.Real a, A.IntegerConstant a, A.PseudoModule a a) => NormedMax.C (T a) (T a) where norm = lift1 A.abs -} lift0 ::- (forall r. CodeGenFunction r (Value a)) ->+ (forall r. CodeGenFunction r a) -> T a lift0 f = consUnique $ MT.lift $ f lift1 ::- (forall r. Value a -> CodeGenFunction r (Value b)) ->+ (forall r. a -> CodeGenFunction r b) -> T a -> T b lift1 f x = consUnique $ MT.lift . f =<< code x lift2 ::- (forall r. Value a -> Value b -> CodeGenFunction r (Value c)) ->+ (forall r. a -> b -> CodeGenFunction r c) -> T a -> T b -> T c lift2 f x y = consUnique $ do@@ -236,61 +284,102 @@ MT.lift $ f xv yv -constantValue :: Value a -> T a+unlift0 ::+ T a ->+ (forall r. CodeGenFunction r a)+unlift0 = decons++unlift1 ::+ (T a -> T b) ->+ (forall r. a -> CodeGenFunction r b)+unlift1 f x =+ decons (f (constantValue x))++unlift2 ::+ (T a -> T b -> T c) ->+ (forall r. a -> b -> CodeGenFunction r c)+unlift2 f x y =+ decons (f (constantValue x) (constantValue y))+++constantValue :: a -> T a constantValue x = consUnique (return x) -constant :: (IsConst a) => a -> T a-constant = constantValue . valueOf+constant :: (LLVM.IsConst a) => a -> T (LLVM.Value a)+constant = constantValue . LLVM.valueOf -class Flatten value register | value -> register where- flatten :: value -> CodeGenFunction r register- unfold :: register -> value+class Flatten value where+ type Registers value :: *+ flatten :: value -> CodeGenFunction r (Registers value)+ unfold :: (Registers value) -> value flattenTraversable ::- (Flatten value register, Trav.Traversable f) =>- f value -> CodeGenFunction r (f register)+ (Flatten value, Trav.Traversable f) =>+ f value -> CodeGenFunction r (f (Registers value)) flattenTraversable = Trav.mapM flatten unfoldFunctor ::- (Flatten value register, Functor f) =>- f register -> f value+ (Flatten value, Functor f) =>+ f (Registers value) -> f value unfoldFunctor = fmap unfold -instance (Flatten ah al, Flatten bh bl) =>- Flatten (ah,bh) (al,bl) where+flattenFunction ::+ (Flatten a, Flatten b) =>+ (a -> b) -> (Registers a -> CodeGenFunction r (Registers b))+flattenFunction f =+ flatten . f . unfold++{-+This function is hardly useful,+since most functions are not of type+@(Registers a -> (forall r. CodeGenFunction r (Registers b)))@+but of type+@(forall r. Registers a -> CodeGenFunction r (Registers b))@.+We would also need a method unfoldF.+See ValueUnfoldF for some implementations.++unfoldFunction ::+ (Flatten a, Flatten b) =>+ (Registers a -> (forall r. CodeGenFunction r (Registers b))) -> (a -> b)+unfoldFunction f x =+ unfoldF (f =<< flatten x)+-}+++instance (Flatten a, Flatten b) => Flatten (a,b) where+ type Registers (a,b) = (Registers a, Registers b) flatten (a,b) = liftM2 (,) (flatten a) (flatten b) unfold (a,b) = (unfold a, unfold b) -instance (Flatten ah al, Flatten bh bl, Flatten ch cl) =>- Flatten (ah,bh,ch) (al,bl,cl) where+instance (Flatten a, Flatten b, Flatten c) => Flatten (a,b,c) where+ type Registers (a,b,c) = (Registers a, Registers b, Registers c) flatten (a,b,c) = liftM3 (,,) (flatten a) (flatten b) (flatten c) unfold (a,b,c) = (unfold a, unfold b, unfold c) -instance Flatten v r =>- Flatten (Stereo.T v) (Stereo.T r) where+instance Flatten a => Flatten (Stereo.T a) where+ type Registers (Stereo.T a) = Stereo.T (Registers a) flatten = flattenTraversable unfold = unfoldFunctor -instance Flatten v r =>- Flatten (Complex.T v) (Complex.T r) where+instance Flatten a => Flatten (Complex.T a) where+ type Registers (Complex.T a) = Complex.T (Registers a) flatten s = liftM2 (Complex.+:) (flatten $ Complex.real s) (flatten $ Complex.imag s) unfold = unfoldFunctor -instance- (RealRing.C v, Flatten v r) =>- Flatten (Phase.T v) r where+instance (RealRing.C a, Flatten a) => Flatten (Phase.T a) where+ type Registers (Phase.T a) = Registers a flatten s = flatten $ Phase.toRepresentative s unfold s =@@ -298,9 +387,12 @@ Phase.fromRepresentative $ unfold s -instance Flatten (T a) (Value a) where+instance Flatten (T a) where+ type Registers (T a) = a flatten = decons unfold = constantValue-instance Flatten () () where++instance Flatten () where+ type Registers () = () flatten = return unfold = id
src/Synthesizer/LLVM/Simple/Vanilla.hs view
@@ -1,11 +1,6 @@ {-# LANGUAGE NoImplicitPrelude #-}-{-# LANGUAGE MultiParamTypeClasses #-}-{-# LANGUAGE FunctionalDependencies #-}-{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE TypeFamilies #-} {-# LANGUAGE FlexibleContexts #-}-{-# LANGUAGE UndecidableInstances #-}-{-# LANGUAGE ExistentialQuantification #-}-{-# LANGUAGE Rank2Types #-} module Synthesizer.LLVM.Simple.Vanilla where import qualified Synthesizer.LLVM.Simple.Signal as Sig@@ -40,7 +35,7 @@ iterateVal ::- (Memory.FirstClass a am, IsSized a asize, IsSized am amsize) =>+ (Memory.C a) => (Value.T a -> Value.T a) -> Value.T a -> Sig.T (Value.T a) iterateVal f initial =@@ -52,7 +47,7 @@ (Value.decons initial) iterate ::- (Value.Flatten a reg, Memory.C reg packed, IsSized packed size) =>+ (Value.Flatten a, Value.Registers a ~ reg, Memory.C reg) => (a -> a) -> (a -> Sig.T a) iterate f initial =@@ -72,11 +67,11 @@ osciReg ::- (RealRing.C (Value.T t),- Memory.FirstClass t tm, IsSized t tsize, IsSized tm tmsize,+ (RealRing.C (Value.T (Value t)),+ Memory.FirstClass t, Memory.Stored t ~ tm, IsSized t, IsSized tm, SoV.Fraction t, IsConst t, IsFirstClass y) =>- Wave.T (Value.T t) (Value.T y) ->+ Wave.T (Value.T (Value t)) (Value.T (Value y)) -> Value t -> Value t -> Sig.T (Value y) osciReg wave phase freq = Sig.map@@ -85,24 +80,23 @@ Sig.iterate (SoV.incPhase freq) phase osciVal ::- (RealRing.C (Value.T t),- Memory.FirstClass t tm, IsSized t tsize, IsSized tm tmsize,+ (RealRing.C (Value.T (Value t)),+ Memory.FirstClass t, Memory.Stored t ~ tm, IsSized t, IsSized tm, SoV.Fraction t, IsConst t) =>- Wave.T (Value.T t) y ->- Value.T t -> Value.T t -> Sig.T y+ Wave.T (Value.T (Value t)) y ->+ Value.T (Value t) -> Value.T (Value t) -> Sig.T y osciVal wave phase freq = map (Wave.apply wave . Phase.fromRepresentative) $ iterateVal (incPhaseVal freq) phase incPhaseVal :: (SoV.Fraction a, IsArithmetic a) =>- Value.T a -> Value.T a -> Value.T a+ Value.T (Value a) -> Value.T (Value a) -> Value.T (Value a) incPhaseVal = Value.lift2 SoV.incPhase osci :: (RealRing.C t,- Value.Flatten t reg,- Memory.C reg struct, IsSized struct size,+ Value.Flatten t, Value.Registers t ~ reg, Memory.C reg, SoV.Fraction t, IsConst t) => Wave.T t y -> Phase.T t -> t -> Sig.T y
src/Synthesizer/LLVM/Storable/Process.hs view
@@ -1,6 +1,5 @@ {-# LANGUAGE NoImplicitPrelude #-}-{-# LANGUAGE MultiParamTypeClasses #-}-{-# LANGUAGE FunctionalDependencies #-}+{-# LANGUAGE TypeFamilies #-} {- | Functions on lazy storable vectors that are implemented using LLVM. -}@@ -9,6 +8,7 @@ continuePacked, ) where +import qualified Synthesizer.LLVM.Frame.SerialVector as Serial import qualified Synthesizer.LLVM.Storable.Signal as SigStL import qualified Synthesizer.CausalIO.Process as PIO @@ -26,15 +26,15 @@ import qualified LLVM.Extra.Arithmetic as A import qualified LLVM.Extra.Memory as Memory import qualified LLVM.Core as LLVM-import LLVM.Extra.Class (MakeValueTuple, )-import qualified Data.TypeLevel.Num as TypeNum+import LLVM.Extra.Class (MakeValueTuple, ValueTuple, )+import qualified Types.Data.Num as TypeNum import qualified Control.Arrow as Arr import qualified Data.Foldable as Fold import Foreign.Storable (Storable, ) import Foreign.Marshal.Array (advancePtr, ) -import System.IO.Unsafe (unsafePerformIO, )+import qualified System.Unsafe as Unsafe import NumericPrelude.Numeric import NumericPrelude.Base@@ -50,7 +50,7 @@ -} makeArranger :: (Storable a, A.Additive value,- MakeValueTuple a value, Memory.C value struct,+ MakeValueTuple a, ValueTuple a ~ value, Memory.C value, Arr.Arrow arrow) => IO (arrow (EventListTT.T NonNeg.Int (SV.Vector a))@@ -67,7 +67,7 @@ AbsEventList.mapTime NonNeg.toNumber $ EventList.toAbsoluteEventList 0 $ EventListTM.switchTimeR const now- in unsafePerformIO $+ in Unsafe.performIO $ SVB.createAndTrim sz $ \dstPtr -> do fill (fromIntegral sz) dstPtr Fold.forM_ xs $ \(i,s) ->@@ -81,10 +81,10 @@ continuePacked ::- (CutG.Transform a, Storable b, LLVM.IsPrimitive b, TypeNum.Pos n) =>- PIO.T a (SV.Vector (LLVM.Vector n b)) ->- (b -> PIO.T a (SV.Vector (LLVM.Vector n b))) ->- PIO.T a (SV.Vector (LLVM.Vector n b))+ (CutG.Transform a, Storable b, LLVM.IsPrimitive b, TypeNum.PositiveT n) =>+ PIO.T a (SV.Vector (Serial.Plain n b)) ->+ (b -> PIO.T a (SV.Vector (Serial.Plain n b))) ->+ PIO.T a (SV.Vector (Serial.Plain n b)) continuePacked proc0 proc1 = PIO.continueChunk proc0 (proc1 Arr.<<^ SV.last . SigStL.unpackStrict)
src/Synthesizer/LLVM/Storable/Signal.hs view
@@ -1,6 +1,6 @@ {-# LANGUAGE NoImplicitPrelude #-}-{-# LANGUAGE MultiParamTypeClasses #-}-{-# LANGUAGE FunctionalDependencies #-}+{-# LANGUAGE TypeFamilies #-}+{-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE ForeignFunctionInterface #-} {- | Functions on lazy storable vectors that are implemented using LLVM.@@ -21,10 +21,10 @@ import qualified Synthesizer.LLVM.Execution as Exec import qualified LLVM.Extra.Memory as Memory-import qualified LLVM.Extra.Vector as Vector import qualified LLVM.Extra.Arithmetic as A import LLVM.Extra.Control (arrayLoop, ) +import qualified Synthesizer.LLVM.Frame.SerialVector as Serial import qualified Synthesizer.LLVM.Frame.Stereo as Stereo import qualified Synthesizer.LLVM.Frame.StereoInterleaved as StereoVector @@ -39,12 +39,11 @@ import LLVM.Extra.Arithmetic (advanceArrayElementPtr, ) -import LLVM.Extra.Class (MakeValueTuple, )+import LLVM.Extra.Class (MakeValueTuple, ValueTuple, ) import LLVM.Core (Linkage(ExternalLinkage), createNamedFunction, ret,- IsSized, IsPrimitive, getElementPtr,- Vector, )-import qualified Data.TypeLevel.Num as TypeNum+ IsPrimitive, getElementPtr, )+import qualified Types.Data.Num as TypeNum import qualified Control.Category as Cat @@ -56,7 +55,7 @@ import Foreign.Storable (Storable, ) import Foreign.Marshal.Array (advancePtr, ) -import System.IO.Unsafe (unsafePerformIO, )+import qualified System.Unsafe as Unsafe import NumericPrelude.Numeric import NumericPrelude.Base@@ -71,34 +70,34 @@ It would also need copying since the source data may not be aligned properly. -} unpackStrict ::- (Storable a, IsPrimitive a, TypeNum.Pos n) =>- SV.Vector (Vector n a) -> SV.Vector a+ (Storable a, IsPrimitive a, TypeNum.PositiveT n) =>+ SV.Vector (Serial.Plain n a) -> SV.Vector a unpackStrict v =- let getDim :: (TypeNum.Pos n) => SV.Vector (Vector n a) -> n -> Int- getDim _ = TypeNum.toInt+ let getDim :: (TypeNum.PositiveT n) => SV.Vector (Serial.Plain n a) -> n -> Int+ getDim _ = TypeNum.fromIntegerT d = getDim v undefined (fptr,s,l) = SVB.toForeignPtr v in SVB.SV (castForeignPtr fptr) (s*d) (l*d) unpack ::- (Storable a, IsPrimitive a, TypeNum.Pos n) =>- SVL.Vector (Vector n a) -> SVL.Vector a+ (Storable a, IsPrimitive a, TypeNum.PositiveT n) =>+ SVL.Vector (Serial.Plain n a) -> SVL.Vector a unpack = SVL.fromChunks . map unpackStrict . SVL.chunks unpackStereoStrict ::- (Storable a, IsPrimitive a, TypeNum.Pos n) =>+ (Storable a, IsPrimitive a, TypeNum.PositiveT n) => SV.Vector (StereoVector.T n a) -> SV.Vector (Stereo.T a) unpackStereoStrict v =- let getDim :: (TypeNum.Pos n) => SV.Vector (StereoVector.T n a) -> n -> Int- getDim _ = TypeNum.toInt+ let getDim :: (TypeNum.PositiveT n) => SV.Vector (StereoVector.T n a) -> n -> Int+ getDim _ = TypeNum.fromIntegerT d = getDim v undefined (fptr,s,l) = SVB.toForeignPtr v in SVB.SV (castForeignPtr fptr) (s*d) (l*d) unpackStereo ::- (Storable a, IsPrimitive a, TypeNum.Pos n) =>+ (Storable a, IsPrimitive a, TypeNum.PositiveT n) => SVL.Vector (StereoVector.T n a) -> SVL.Vector (Stereo.T a) unpackStereo = SVL.fromChunks . map unpackStereoStrict . SVL.chunks@@ -108,26 +107,28 @@ This is for instance necessary for stereo signals where the data layout of packed and unpacked data is different, thus simple casting of the data is not possible.-However, for vectorized Stereo data the StereoInterleaved+However, for vectorized Stereo data the StereoInterleaved type still uses vector operations for interleaving and thus is more efficient. -} makeUnpackGenericStrict ::- (Vector.Access n va vv,- Storable a, MakeValueTuple a va, Memory.C va as, IsSized as asize,- Storable v, MakeValueTuple v vv, Memory.C vv vs, IsSized vs vsize) =>+ (Serial.C vv, n ~ Serial.Size vv, va ~ Serial.Element vv,+ Memory.C (Serial.ReadIt vv),+ Storable a, MakeValueTuple a, ValueTuple a ~ va, Memory.C va,+ Storable v, MakeValueTuple v, ValueTuple v ~ vv, Memory.C vv) => IO (SV.Vector v -> SV.Vector a) makeUnpackGenericStrict = let vectorSize ::- (Vector.Access n al vl, Storable v, MakeValueTuple v vl) =>+ (Serial.C vl, n ~ Serial.Size vl, al ~ Serial.Element vl, Storable v, MakeValueTuple v, ValueTuple v ~ vl) => SV.Vector v -> n vectorSize _ = undefined- in fmap (\f v -> f (TypeNum.toInt (vectorSize v) * SV.length v) v) $+ in fmap (\f v -> f (TypeNum.fromIntegerT (vectorSize v) * SV.length v) v) $ SigP.run (SigPS.unpack $ SigP.fromStorableVector Cat.id) makeUnpackGeneric ::- (Vector.Access n va vv,- Storable a, MakeValueTuple a va, Memory.C va as, IsSized as asize,- Storable v, MakeValueTuple v vv, Memory.C vv vs, IsSized vs vsize) =>+ (Serial.C vv, n ~ Serial.Size vv, va ~ Serial.Element vv,+ Memory.C (Serial.ReadIt vv),+ Storable a, MakeValueTuple a, ValueTuple a ~ va, Memory.C va,+ Storable v, MakeValueTuple v, ValueTuple v ~ vv, Memory.C vv) => IO (SVL.Vector v -> SVL.Vector a) makeUnpackGeneric = fmap (\f -> SVL.fromChunks . map f . SVL.chunks) $@@ -135,10 +136,10 @@ makeReverser ::- (Storable a, Vector.ShuffleMatch n value,- MakeValueTuple a value, Memory.C value struct) =>+ (Storable a, Serial.C value,+ MakeValueTuple a, ValueTuple a ~ value, Memory.C value) => value -> IO (Word32 -> Ptr a -> Ptr a -> IO ())--- (Memory.C a struct, Vector.ShuffleMatch n a) =>+-- (Memory.C a struct, Serial.C a) => -- IO (Word32 -> Ptr struct -> Ptr struct -> IO ()) makeReverser dummy = fmap (\f len srcPtr dstPtr ->@@ -150,27 +151,27 @@ _ <- arrayLoop size ptrB ptrAEnd $ \ ptrBi ptrAj0 -> do ptrAj1 <- getElementPtr ptrAj0 (-1 :: Int32, ()) flip Memory.store ptrBi- =<< Vector.reverse+ =<< Serial.reverse . flip asTypeOf dummy =<< Memory.load ptrAj1 return ptrAj1 ret () makeReversePackedStrict ::- (Storable v, Vector.Access n va vv,- MakeValueTuple v vv, Memory.C vv vs, IsSized vs vsize) =>+ (Storable v, Serial.C vv, n ~ Serial.Size vv, va ~ Serial.Element vv,+ MakeValueTuple v, ValueTuple v ~ vv, Memory.C vv) => IO (SV.Vector v -> SV.Vector v) makeReversePackedStrict = do rev <- makeReverser undefined return $ \v ->- unsafePerformIO $+ Unsafe.performIO $ SVB.withStartPtr v $ \ptrA len -> SVB.create len $ \ptrB -> rev (fromIntegral len) ptrA ptrB makeReversePacked ::- (Storable v, Vector.Access n va vv,- MakeValueTuple v vv, Memory.C vv vs, IsSized vs vsize) =>+ (Storable v, Serial.C vv, n ~ Serial.Size vv, va ~ Serial.Element vv,+ MakeValueTuple v, ValueTuple v ~ vv, Memory.C vv) => IO (SVL.Vector v -> SVL.Vector v) makeReversePacked = fmap (\f -> SVL.fromChunks . reverse . map f . SVL.chunks) $@@ -201,10 +202,10 @@ (\body l -> SVL.append body (y l)) x continuePacked ::- (TypeNum.Pos n, Storable a, IsPrimitive a) =>- SVL.Vector (Vector n a) ->- (a -> SVL.Vector (Vector n a)) ->- SVL.Vector (Vector n a)+ (TypeNum.PositiveT n, Storable a, IsPrimitive a) =>+ SVL.Vector (Serial.Plain n a) ->+ (a -> SVL.Vector (Serial.Plain n a)) ->+ SVL.Vector (Serial.Plain n a) continuePacked x y = SVL.fromChunks $ withLast SV.empty@@ -228,8 +229,8 @@ -} continuePackedGeneric :: {-- (Storable v, Vector.Access n a v,- MakeValueTuple v vv, Memory.C vv vs, IsSized vs vsize) =>+ (Storable v, Serial.C v, n ~ Serial.Size v, a ~ Serial.Element v,+ MakeValueTuple v, ValueTuple v ~ vv, Memory.C vv) => -} (Storable v, Storable a) => (SV.Vector v -> SV.Vector a) ->@@ -269,7 +270,7 @@ it also simplifies type inference. -} fillBuffer ::- (MakeValueTuple a value, Memory.C value struct) =>+ (MakeValueTuple a, ValueTuple a ~ value, Memory.C value) => value -> IO (Word32 -> Ptr a -> IO ()) fillBuffer x = fmap (\f len ptr -> f len (Memory.castStorablePtr ptr)) $@@ -287,7 +288,7 @@ makeMixer :: (Storable a, A.Additive value,- MakeValueTuple a value, Memory.C value struct) =>+ MakeValueTuple a, ValueTuple a ~ value, Memory.C value) => value -> IO (Word32 -> Ptr a -> Ptr a -> IO ()) makeMixer dummy = fmap (\f len srcPtr dstPtr ->@@ -321,7 +322,7 @@ -} makeArranger :: (Storable a, A.Additive value,- MakeValueTuple a value, Memory.C value struct) =>+ MakeValueTuple a, ValueTuple a ~ value, Memory.C value) => IO (SVL.ChunkSize -> EventList.T NonNeg.Int (SVL.Vector a) -> SVL.Vector a)@@ -337,7 +338,7 @@ EventList.toAbsoluteEventList 0 $ EventListTM.switchTimeR const now (chunk,newAcc) =- unsafePerformIO $+ Unsafe.performIO $ SVB.createAndTrim' sz $ \ptr -> do fill (fromIntegral sz) ptr newAcc0 <- flip mapM acc $ addToBuffer mixer sz ptr 0@@ -364,7 +365,7 @@ {-# DEPRECATED arrange "better use makeArranger" #-} arrange :: (Storable a, A.Additive value,- MakeValueTuple a value, Memory.C value struct) =>+ MakeValueTuple a, ValueTuple a ~ value, Memory.C value) => SVL.ChunkSize -> EventList.T NonNeg.Int (SVL.Vector a) {-^ A list of pairs: (relative start time, signal part),@@ -373,4 +374,4 @@ -> SVL.Vector a {-^ The mixed signal. -} arrange =- unsafePerformIO makeArranger+ Unsafe.performIO makeArranger
− src/Synthesizer/LLVM/Test.hs
@@ -1,1336 +0,0 @@-{-# LANGUAGE Rank2Types #-}-module Main where--import qualified Synthesizer.LLVM.Filter.ComplexFirstOrderPacked as BandPass-import qualified Synthesizer.LLVM.Filter.Allpass as Allpass-import qualified Synthesizer.LLVM.Filter.Butterworth as Butterworth-import qualified Synthesizer.LLVM.Filter.Chebyshev as Chebyshev-import qualified Synthesizer.LLVM.Filter.FirstOrder as Filt1-import qualified Synthesizer.LLVM.Filter.SecondOrder as Filt2-import qualified Synthesizer.LLVM.Filter.SecondOrderPacked as Filt2P-import qualified Synthesizer.LLVM.Filter.Moog as Moog-import qualified Synthesizer.LLVM.Filter.Universal as UniFilter-import qualified Synthesizer.LLVM.CausalParameterized.Controlled as CtrlP-import qualified Synthesizer.LLVM.CausalParameterized.ControlledPacked as CtrlPS-import qualified Synthesizer.LLVM.CausalParameterized.ProcessPacked as CausalPS-import qualified Synthesizer.LLVM.CausalParameterized.Process as CausalP-import qualified Synthesizer.LLVM.CausalParameterized.Functional as Func-import qualified Synthesizer.LLVM.Causal.Process as Causal-import qualified Synthesizer.LLVM.Simple.Signal as Sig-import qualified Synthesizer.LLVM.Storable.Signal as SigStL-import qualified Synthesizer.LLVM.Frame as Frame-import qualified Synthesizer.LLVM.Wave as Wave-import qualified Synthesizer.LLVM.Parameter as Param--import qualified LLVM.Extra.ScalarOrVector as SoV-import qualified LLVM.Extra.Memory as Memory-import qualified LLVM.Extra.Arithmetic as A-import LLVM.Core (Value, value, valueOf, Vector, constVector, constOf, )-import LLVM.Util.Arithmetic () -- Floating instance for TValue-import qualified LLVM.Core as LLVM-import Data.TypeLevel.Num (D4, D8, D16, )-import qualified Data.TypeLevel.Num as TypeNum--import qualified Synthesizer.LLVM.Parameterized.SignalPacked as SigPS-import qualified Synthesizer.LLVM.Parameterized.Signal as SigP-import Synthesizer.LLVM.CausalParameterized.Process (($<), ($*), ($*#), )-import Synthesizer.LLVM.Parameterized.Signal (($#), )--import qualified Synthesizer.Plain.Filter.Recursive as FiltR-import qualified Synthesizer.Plain.Filter.Recursive.FirstOrder as Filt1Core-import qualified Synthesizer.Plain.Filter.Recursive.SecondOrder as Filt2Core--import Control.Arrow (Arrow, arr, (&&&), (^<<), (***), )-import Control.Category ((<<<), (.), id, )-import Control.Applicative (pure, liftA2, )--import qualified Data.StorableVector.Lazy as SVL-import qualified Data.StorableVector as SV--import qualified Data.EventList.Relative.TimeBody as EventList-import qualified Data.EventList.Relative.BodyTime as EventListBT-import qualified Data.EventList.Relative.MixedTime as EventListMT-import qualified Data.EventList.Relative.TimeMixed as EventListTM-import qualified Numeric.NonNegative.Wrapper as NonNeg--import qualified Sound.Sox.Option.Format as SoxOption-import qualified Sound.Sox.Play as SoxPlay--- import qualified Synthesizer.Storable.ALSA.Play as Play--import qualified Synthesizer.LLVM.Frame.Stereo as Stereo--import Data.Word (Word32, )--- import qualified Data.Function.HT as F-import Data.List (genericLength, )-import System.Random (randomRs, mkStdGen, )--import qualified System.IO as IO--- import System.Exit (ExitCode, )--import Prelude hiding (fst, snd, id, (.), )-import qualified Prelude as P---asMono :: vector Float -> vector Float-asMono = id--asStereo :: vector (Stereo.T Float) -> vector (Stereo.T Float)-asStereo = id--asMonoPacked :: vector (LLVM.Vector D4 Float) -> vector (LLVM.Vector D4 Float)-asMonoPacked = id--asMonoPacked16 :: vector (LLVM.Vector D16 Float) -> vector (LLVM.Vector D16 Float)-asMonoPacked16 = id--asWord32 :: vector Word32 -> vector Word32-asWord32 = id--asWord32Packed :: vector (LLVM.Vector D4 Word32) -> vector (LLVM.Vector D4 Word32)-asWord32Packed = id---{- |-> playStereo (Sig.amplifyStereo 0.3 $ stereoOsciSaw 0.01)--Unfortunately: If you call :reload,-then the next attempt to play something will be answered by:--ghci: JITEmitter.cpp:110: <unnamed>::JITResolver::JITResolver(llvm::JIT&): Assertion `TheJITResolver == 0 && "Multiple JIT resolvers?"' failed.--}-playStereo :: Sig.T (Stereo.T (Value Float)) -> IO ()-playStereo =- playStereoVector .- Sig.renderChunky (SVL.chunkSize 100000)--playStereoVector :: SVL.Vector (Stereo.T Float) -> IO ()-playStereoVector =- fmap (const ()) .- SoxPlay.simple SVL.hPut SoxOption.none 44100--playMono :: Sig.T (Value Float) -> IO ()-playMono =- playMonoVector .- Sig.renderChunky (SVL.chunkSize 100000)--playMonoVector :: SVL.Vector Float -> IO ()-playMonoVector =- fmap (const ()) .- SoxPlay.simple SVL.hPut SoxOption.none 44100---playFileMono :: FilePath -> IO ()-playFileMono fileName = do- IO.withFile fileName IO.ReadMode $ \h ->- playStereo .- Sig.fromStorableVectorLazy .- asStereo . snd- =<< SVL.hGetContentsAsync (SVL.chunkSize 4321) h- return ()---saw :: IO ()-saw =- SV.writeFile "speedtest.f32" $- asMono $- Sig.render 10000000 $- Sig.osciSaw 0 0.01--exponential :: IO ()-exponential =- SV.writeFile "speedtest.f32" $- asMono $- Sig.render 10000000 $- Sig.exponential2 50000 1--triangle :: IO ()-triangle =- SV.writeFile "speedtest.f32" $- asMono $- Sig.render 10000000 $- Sig.osci Wave.triangle 0.25 0.01--trianglePack :: IO ()-trianglePack =- SV.writeFile "speedtest.f32" $- asMonoPacked $- (\xs -> SigP.render xs (div 10000000 4) ()) $- SigP.mapSimple Wave.triangle $- SigPS.packSmall $- (SigP.osciCore $# (0.25::Float)) 4.015803e-4--trianglePacked :: IO ()-trianglePacked =- SV.writeFile "speedtest.f32" $- asMonoPacked $- (\xs -> SigP.render xs (div 10000000 4) ()) $- (CausalPS.osciSimple Wave.triangle- $< SigPS.constant 0.25- $* SigPS.constant 0.01)--triangleReplicate :: IO ()-triangleReplicate =- SV.writeFile "speedtest.f32" $- asMonoPacked $- (\xs -> SigP.render xs (div 10000000 4) ()) $- (CausalPS.shapeModOsci- (\k p -> do- x <- Wave.triangle =<< Wave.replicate k p- y <- Wave.approxSine4 =<< Wave.halfEnvelope p- A.mul x y)- $< SigPS.rampInf 1000000- $< SigPS.constant 0- $* SigPS.constant 0.01)--rationalSine :: IO ()-rationalSine =- SV.writeFile "speedtest.f32" $- asMonoPacked $- (\xs -> SigP.render xs (div 10000000 4) ()) $- (CausalPS.shapeModOsci Wave.rationalApproxSine1- $< SigP.mapSimple (A.add (valueOf 0.001)) (SigPS.rampInf 10000000)- $< SigPS.constant 0- $* SigPS.constant 0.01)---pingSig :: Float -> Sig.T (Value Float)-pingSig freq =- Sig.envelope- (Sig.exponential2 50000 1)- (Sig.osciSaw 0.5 freq)--pingSigP :: SigP.T Float (Value Float)-pingSigP =- let freq = id- in SigP.envelope- (SigP.exponential2 50000 1)- (SigP.osciSaw 0.5 freq)--ping :: IO ()-ping =- SV.writeFile "speedtest.f32" $- asMono $- Sig.render 10000000 $- pingSig 0.01--pingSigPacked :: SigP.T Float (Value (Vector D4 Float))-pingSigPacked =- let freq = id- in SigP.envelope- (SigPS.exponential2 50000 1)- (SigPS.osciSimple Wave.saw 0 freq)--pingPacked :: IO ()-pingPacked =- SV.writeFile "speedtest.f32" $- asMonoPacked $- (\xs -> SigP.render xs (div 10000000 4) 0.01) $- pingSigPacked--pingUnpack :: IO ()-pingUnpack =- SV.writeFile "speedtest.f32" $- asMono $- (\xs -> SigP.render xs 10000000 0.01) $- SigPS.unpack $- pingSigPacked--pingSmooth :: IO ()-pingSmooth =- SV.writeFile "speedtest-scalar.f32" $- asMono $- (\xs -> SigP.render xs 10000000 ()) $- (Filt1.lowpassCausalP- $< (fmap Filt1Core.Parameter $- SigP.mapSimple (A.sub (valueOf 1))- (SigP.exponential2 50000 $# (1::Float)))- $* SigP.osciSimple Wave.triangle 0 0.01)--pingSmoothPacked :: IO ()-pingSmoothPacked =- SV.writeFile "speedtest-vector.f32" $- asMonoPacked $- (\xs -> SigP.render xs (div 10000000 4) ()) $- (Filt1.lowpassCausalPackedP- $< (fmap Filt1Core.Parameter $- SigP.mapSimple (A.sub (valueOf 1))- (SigP.exponential2 (50000/4) $# (1::Float)))- $* SigPS.osciSimple Wave.triangle 0 0.01)--stereoOsciSaw :: Float -> Sig.T (Stereo.T (Value Float))-stereoOsciSaw freq =- liftA2 Stereo.cons- (Sig.osciSaw 0.0 (freq*1.001) `Sig.mix`- Sig.osciSaw 0.2 (freq*1.003) `Sig.mix`- Sig.osciSaw 0.1 (freq*0.995))- (Sig.osciSaw 0.1 (freq*1.005) `Sig.mix`- Sig.osciSaw 0.7 (freq*0.997) `Sig.mix`- Sig.osciSaw 0.5 (freq*0.999))--stereoOsciSawPacked :: Float -> Sig.T (Stereo.T (Value Float))-stereoOsciSawPacked freq =- let mix4 =- Frame.mixVector .- flip asTypeOf (undefined :: Value (Vector D4 Float))- in liftA2 Stereo.cons- (Sig.map mix4 $- Sig.osciPlain Wave.saw- (value $ constVector $ map constOf [0.0, 0.2, 0.1, 0.4])- (value $ constVector $- map (constOf . (freq*)) [1.001, 1.003, 0.995, 0.996]))- (Sig.map mix4 $- Sig.osciPlain Wave.saw- (value $ constVector $ map constOf [0.1, 0.7, 0.5, 0.7])- (value $ constVector $- map (constOf . (freq*)) [1.005, 0.997, 0.999, 1.001]))--stereoOsciSawPacked2 :: Float -> Sig.T (Stereo.T (Value Float))-stereoOsciSawPacked2 freq =- Sig.map (Frame.mixVectorToStereo .- flip asTypeOf (undefined :: Value (Vector D8 Float))) $- Sig.osciPlain (Wave.trapezoidSkew (SoV.replicateOf 0.2))- (valueOf $- LLVM.toVector (0.0, 0.2, 0.1, 0.4, 0.1, 0.7, 0.5, 0.7))- (value $ constVector $- map (constOf . (freq*)) $- [1.001, 1.003, 0.995, 0.996, 1.005, 0.997, 0.999, 1.001])--stereo :: IO ()-stereo =- SV.writeFile "speedtest.f32" $- asStereo $- Sig.render 10000000 $- Sig.amplifyStereo 0.25 $- stereoOsciSawPacked2 0.01--lazy :: IO ()-lazy =- SVL.writeFile "speedtest.f32" $- SVL.take 10000000 $- asMono $- Sig.renderChunky (SVL.chunkSize 100000)- {- SVL.defaultChunkSize - too slow -} $- Sig.envelope- (Sig.exponential2 50000 1)- (Sig.osci Wave.sine 0.5 0.01 :: Sig.T (Value Float))--lazyStereo :: IO ()-lazyStereo =- SVL.writeFile "speedtest.f32" $- SVL.take 10000000 $- asStereo $- Sig.renderChunky (SVL.chunkSize 100000) $- Sig.amplifyStereo 0.25 $- stereoOsciSawPacked 0.01--packTake :: IO ()-packTake =- SVL.writeFile "speedtest.f32" $- asMonoPacked $- flip (SigP.renderChunky (SVL.chunkSize 1000)) () $- SigPS.packRotate $- (CausalP.take 5 $*- SigP.osciSimple Wave.saw 0 0.01)--chord :: Float -> Sig.T (Stereo.T (Value Float))-chord base =- {-- This exceeds available vector registers- and thus needs more stack accesses.- Thus it needs twice as much time as the simple mixing.- However doing all 32 oscillators in parallel- and mix them in one go might be still faster.-- foldl1 (Sig.zipWith Frame.mixStereoV) $- -}- foldl1 Sig.mix $- map (\f -> stereoOsciSawPacked2 (base*f)) $- 0.25 : 1.00 : 1.25 : 1.50 : []--lazyChord :: IO ()-lazyChord =- SVL.writeFile "speedtest.f32" $- SVL.take 10000000 $- asStereo $- Sig.renderChunky (SVL.chunkSize 100000) $- Sig.amplifyStereo 0.1 $- chord 0.005--filterSweepComplex :: IO ()-filterSweepComplex =- SVL.writeFile "speedtest.f32" $- SVL.take 10000000 $- asStereo $- Sig.renderChunky (SVL.chunkSize 100000) $- Sig.amplifyStereo 0.3 $- Causal.apply BandPass.causal $- Sig.zip- (Sig.map (BandPass.parameter (valueOf 100)) $- Sig.map (\x -> 0.01 * exp (2 * return x)) $- Sig.osci Wave.sine 0 (0.1/44100)) $- chord 0.005--lfoSine ::- (Memory.C a ap, LLVM.IsSized ap asize) =>- (forall r. Value Float -> LLVM.CodeGenFunction r a) ->- Param.T p Float ->- SigP.T p a-lfoSine f reduct =- SigP.mapSimple f $- SigP.mapSimple (\x -> 0.01 * exp (2 * return x)) $- SigP.osciSimple Wave.sine 0 (reduct * 0.1/44100)--filterSweep :: IO ()-filterSweep =- SVL.writeFile "speedtest.f32" $- SVL.take 10000000 $- asMono $- flip (SigP.renderChunky (SVL.chunkSize 10000)) () $- (CausalP.amplify 0.2 .- CtrlP.processCtrlRate 128- (lfoSine (Filt2.bandpassParameter (valueOf 100)))- $* SigP.osciSimple Wave.saw 0 0.01)--filterSweepPacked :: IO ()-filterSweepPacked =- SVL.writeFile "speedtest.f32" $- SVL.take (div 10000000 4) $- asMonoPacked $- flip (SigP.renderChunky (SVL.chunkSize 10000)) () $- (CausalP.amplify 0.2 .- CtrlPS.processCtrlRate 128- (lfoSine (Filt2.bandpassParameter (valueOf 100)))- $* SigPS.osciSimple Wave.saw 0 0.01)--exponentialFilter2Packed :: IO ()-exponentialFilter2Packed =- SVL.writeFile "speedtest.f32" $- SVL.take (div 10000000 16) $- asMonoPacked16 $- flip (SigP.renderChunky (SVL.chunkSize 10000)) () $- (Filt2.causalPackedP- $< (SigP.constant $#- Filt2Core.Parameter (1::Float) 0 0 0 0.99)- $* (--- (CausalP.delay1 $# LLVM.vector [0.1,0.01,0.001,0.0001::Float])--- (CausalP.delay1 $# LLVM.vector [1::Float])- (CausalP.delay1 $# LLVM.vector ((1::Float):repeat 0))- $* (SigP.constant $# LLVM.vector [0::Float])))--filterSweepPacked2 :: IO ()-filterSweepPacked2 =- SVL.writeFile "speedtest.f32" $- SVL.take 10000000 $- asMono $- flip (SigP.renderChunky (SVL.chunkSize 10000)) () $- (CausalP.amplify 0.2 .- CtrlP.processCtrlRate 128- (lfoSine (Filt2P.bandpassParameter (valueOf 100)))- $* SigP.osciSimple Wave.saw 0 0.01)--butterworthNoisePacked :: IO ()-butterworthNoisePacked =- SVL.writeFile "speedtest.f32" $- SVL.take (div 10000000 4) $- asMonoPacked $- flip (SigP.renderChunky (SVL.chunkSize 10000)) () $- (CausalPS.amplify 0.2 .- CtrlPS.processCtrlRate 128- (lfoSine (Butterworth.parameter TypeNum.d3 FiltR.Lowpass (valueOf 0.5)))- $* SigPS.noise 0 0.3)--chebyshevNoisePacked :: IO ()-chebyshevNoisePacked =- SVL.writeFile "speedtest.f32" $- SVL.take (div 10000000 4) $- asMonoPacked $- flip (SigP.renderChunky (SVL.chunkSize 10000)) () $- (CausalPS.amplify 0.2 .- CtrlPS.processCtrlRate 128- (lfoSine (Chebyshev.parameterA TypeNum.d5 FiltR.Lowpass (valueOf 0.5)))- $* SigPS.noise 0 0.3)--{--Provoke non-aligned vector accesses by calling alloca for a record of 5 floats-in LLVM-2.6.-However, the vector accesses are those of noise.-Using scalar Noise there is no problem.--}-noiseAllocaBug :: IO ()-noiseAllocaBug =- SVL.writeFile "speedtest.f32" $- SVL.take (div 10000000 4) $- asMonoPacked $- flip (SigP.renderChunky (SVL.chunkSize 10000)) () $- (CausalPS.amplify 0.2 . Filt2.causalPackedP- $< (SigP.mapSimple (const $ Memory.load =<< LLVM.alloca) $- (SigP.constant $# (0::Float)))- $* SigPS.noise 0 0.3)--noiseAllocaScalar :: IO ()-noiseAllocaScalar =- SVL.writeFile "speedtest.f32" $- SVL.take 10000000 $- asMono $- flip (SigP.renderChunky (SVL.chunkSize 10000)) () $- (CausalP.amplify 0.2 . Filt2.causalP- $< (SigP.mapSimple (const $- (Memory.load =<< LLVM.alloca ::- LLVM.CodeGenFunction r (Filt2.Parameter (Value Float)))) $- (SigP.constant $# (0::Float)))- $* SigP.noise 0 0.3)---upsample :: IO ()-upsample =- SVL.writeFile "speedtest.f32" $- SVL.take 10000000 $- asMono $- Sig.renderChunky (SVL.chunkSize 100000) $- (let reduct = 128 :: Float- in Sig.interpolateConstant reduct $- Sig.osci Wave.sine 0 (reduct*0.1/44100))---filterSweepControlRateCausal ::- Causal.T- (Stereo.T (Value Float))- (Stereo.T (Value Float))-filterSweepControlRateCausal =- Causal.amplifyStereo 0.3 <<<- BandPass.causal <<<- Causal.feedFst- (let reduct = 128- in Sig.interpolateConstant reduct $- Sig.map (BandPass.parameter (valueOf 100)) $- Sig.map (\x -> 0.01 * exp (2 * return x)) $- Sig.osci Wave.sine 0 (reduct*0.1/44100))--filterSweepControlRateProc ::- Sig.T (Stereo.T (Value Float)) ->- Sig.T (Stereo.T (Value Float))-filterSweepControlRateProc =- Causal.apply filterSweepControlRateCausal--{- |-Trigonometric functions are very slow in LLVM-because they are translated to calls to C's math library.-Thus it is advantageous to compute filter parameters-at a lower rate and interpolate constantly.--}-filterSweepControlRate :: IO ()-filterSweepControlRate =- SVL.writeFile "speedtest.f32" $- asStereo $- SVL.take 10000000 $- Sig.renderChunky (SVL.chunkSize 100000) $- filterSweepControlRateProc $- chord 0.005---filterSweepMusic :: IO ()-filterSweepMusic =- do music <- SV.readFile "lichter.f32"- SVL.writeFile "speedtest.f32" $- asStereo $- Sig.renderChunky (SVL.chunkSize 100000) $- Sig.amplifyStereo 20 $- filterSweepControlRateProc $- Sig.fromStorableVector $- (music :: SV.Vector (Stereo.T Float))---playFilterSweepMusicLazy :: IO ()-playFilterSweepMusicLazy = do- IO.withFile "lichter.f32" IO.ReadMode $ \h ->- playStereo .--- Sig.amplifyStereo 1.125 .- Sig.amplifyStereo 20 .- filterSweepControlRateProc .- Sig.fromStorableVectorLazy .- asStereo . snd- =<< SVL.hGetContentsAsync (SVL.chunkSize 4321) h- return ()--playFilterSweepMusicCausal :: IO ()-playFilterSweepMusicCausal = do- do music <- SV.readFile "lichter.f32"- _ <- SoxPlay.simple SV.hPut SoxOption.none 44100 $- asStereo $- Causal.applyStorable- (Causal.amplifyStereo 20 <<< filterSweepControlRateCausal) $- (music :: SV.Vector (Stereo.T Float))- return ()--playFilterSweepMusicCausalLazy :: IO ()-playFilterSweepMusicCausalLazy = do- IO.withFile "lichter.f32" IO.ReadMode $ \h ->- playStereoVector .- Causal.applyStorableChunky- (Causal.amplifyStereo 20 <<< filterSweepControlRateCausal) .- asStereo . snd- =<< SVL.hGetContentsAsync (SVL.chunkSize 43210) h- return ()--arrangeLazy :: IO ()-arrangeLazy = do- IO.hSetBuffering IO.stdout IO.NoBuffering- print $- SigStL.arrange (SVL.chunkSize 2) $- EventList.fromPairList $- (0, SVL.pack (SVL.chunkSize 2) [1,2::Double]) :- (0, SVL.pack (SVL.chunkSize 2) [3,4,5,6]) :- (2, SVL.pack (SVL.chunkSize 2) [7,8,9,10]) :- -- repeat (2, SVL.empty)--- (2, SVL.empty) :--- (2, SVL.empty) :--- (2::NonNeg.Int, error "undefined sound") :- error "end of list"- -- []---{- |-This is inefficient because pingSig is compiled by LLVM-for every occurence of the sound!--randomTones :: IO ()-randomTones = do- playMonoVector $- SigStL.arrange (SVL.chunkSize 12345) $- EventList.fromPairList $ zip- (cycle $ map (flip div 16 . (44100*)) [1,2,3])- (cycle $ map (SVL.take 44100 . Sig.renderChunky (SVL.chunkSize 54321) .- pingSig . (0.01*))- [1,1.25,1.5,2])- return ()--}--{- |-So far we have not managed to compile signals-that depend on parameters.-Thus in order to avoid much recompilation,-we compile and render a few sounds in advance.--}-pingTones :: [SVL.Vector Float]-pingTones =- map (SVL.take 44100 . Sig.renderChunky (SVL.chunkSize 4321) .- pingSig . (0.01*))- [1,1.25,1.5,2]--pingTonesIO :: IO [SVL.Vector Float]-pingTonesIO =- fmap- (\pingVec ->- map- (SVL.take 44100 .- pingVec (SVL.chunkSize 4321) .- (0.01*))- [1,1.25,1.5,2])- (SigP.runChunky pingSigP)--{--Arrange itself does not seem to have a space leak with temporary data.-However it may leak sound data.-This is not very likely because this would result in a large memory leak.--Generate random tones in order to see whether generated sounds leak.-How does 'arrange' compare with 'concat'?--}--cycleTones :: IO ()-cycleTones = do--- playMono $- pings <- pingTonesIO- SVL.writeFile "test.f32" $--- Play.auto (0.01::Double) 44100 $- asMono $-{--after 13min runtime memory consumption increased from 2.5 to 3.9-and we get lot of buffer underruns with this implementation of amplification-(renderChunky . amplify . fromStorableVector)--}- Sig.renderChunky (SVL.chunkSize 432109) $- Sig.amplify 0.1 $- Sig.fromStorableVectorLazy $-{--after 20min memory consumption increased from 2.5 to 3.4-and we get lot of buffer underruns with applyStorableChunky--}-{--applyStorableChunky applied to concatenated zero vectors-starts with memory consumption 1.0 and after an hour, it's still 1.1-without buffer underruns.--}-{-- CausalP.applyStorableChunky (CausalP.amplify $# (0.1::Float)) () $- asMono $--}-{--with chunksize 12345678-after 50min runtime the memory consumption increased from 12.0 to 26.2--with chunksize 123-after 25min runtime the memory consumption is constant 7.4-however at start time there 5 buffer underruns, but no more-probably due to initial LLVM compilation--with chunksize 1234567 and SVL.replicate instead of pingTones-we get memory consumption from 1.3 to 3.2 in 15min,-while producing lots of buffer underruns.-After 45min in total, it is still 3.2 of memory consumption.-Is this a memory leak, or isn't it?--with chunksize 12345678 and SVL.replicate-we get from 5.6 to 10.2 in 3min-to 14.9 after total 13min.--}-{-- SigStL.arrange (SVL.chunkSize 12345678) $- EventList.fromPairList $ zip- (repeat (div 44100 8))--- (cycle $ map (flip div 4 . (44100*)) [1,2,3])--}-{--With plain concatenation of those zero vectors-we stay constantly at 0.4 memory consumption and no buffer underruns over 30min.--}- SVL.concat- (cycle pings)--- (repeat $ SVL.replicate (SVL.chunkSize 44100) 44100 0)- return ()---tonesChunkSize :: SVL.ChunkSize-numTones :: Int--{--For one-time-compiled fill functions,-larger chunks have no relevant effect on the processing speed.--}-(tonesChunkSize, numTones) =- (SVL.chunkSize 441, 200)--- (SVL.chunkSize 44100, 200)--fst :: Arrow arrow => arrow (a,b) a-fst = arr P.fst--snd :: Arrow arrow => arrow (a,b) b-snd = arr P.snd---{-# NOINLINE makePing #-}-makePing :: IO ((Float,Float) -> SVL.Vector Float)-makePing =- let freq = snd- halfLife = fst- in fmap ($tonesChunkSize) $- SigP.runChunky- (SigP.envelope- (SigP.exponential2 halfLife 1)- (SigP.osciSaw 0.5 freq))--tonesDown :: IO ()-tonesDown = do- let dist = div 44100 10- pingp <- makePing- playMonoVector $- CausalP.applyStorableChunky (CausalP.amplify id) 0.03 $- SigStL.arrange tonesChunkSize $- EventList.fromPairList $ zip- (repeat (NonNeg.fromNumber dist))- (map (SVL.take (numTones * dist) . curry pingp 50000) $- iterate (0.999*) 0.01)- return ()---vibes :: SigP.T (Float,Float) (Value Float)-vibes =- let freq = snd- modDepth = fst- halfLife = 5000- -- sine = Wave.sine- sine = Wave.approxSine4- in CausalP.envelope- $< SigP.exponential2 halfLife 1- $* (((CausalP.osciSimple sine- $< (CausalP.envelope- $< SigP.exponential2 halfLife modDepth- $* (CausalP.osciSimple sine- $* SigP.constant (return (0::Float) &&& (2*freq)))))- <<<- CausalP.mapLinear (0.01*freq) freq- <<<- CausalP.osciSimple sine)- $* SigP.constant (return (0::Float, 0.0001::Float)))--makeVibes :: IO ((Float,Float) -> SVL.Vector Float)-makeVibes =- fmap ($tonesChunkSize) $- SigP.runChunky vibes--vibesCycleVector :: ((Float,Float) -> SVL.Vector Float) -> SVL.Vector Float-vibesCycleVector pingp =- SigStL.arrange tonesChunkSize $- EventList.fromPairList $ zip- (repeat 5000)- (map (SVL.take 50000 . pingp) $- zip- (map (\k -> 0.5 * (1 - cos k)) $ iterate (0.05+) 0)- (cycle $ map (0.01*) [1, 1.25, 1.5, 2]))--vibesCycle :: IO ()-vibesCycle = do- pingp <- makeVibes- playMonoVector $- CausalP.applyStorableChunky (CausalP.amplify id) 0.2 $- vibesCycleVector pingp- return ()--vibesEcho :: IO ()-vibesEcho = do- pingp <- makeVibes- playMonoVector $- CausalP.applyStorableChunky- (CausalP.amplify id <<<- CausalP.comb 0.5 7000)- 0.2 $- vibesCycleVector pingp- return ()--vibesReverb :: IO ()-vibesReverb = do- pingp <- makeVibes- playMonoVector $- CausalP.applyStorableChunky- (CausalP.amplify id <<<- CausalP.reverb (mkStdGen 142) 16 (0.9,0.97) (400,1000))- 0.3 $- vibesCycleVector pingp- return ()--vibesReverbStereo :: IO ()-vibesReverbStereo = do- pingp <- makeVibes- playStereoVector $- CausalP.applyStorableChunky- (CausalP.amplifyStereo id <<<- CausalP.stereoFromChannels- (CausalP.reverb (mkStdGen 142) 16 (0.9,0.97) (400,1000))- (CausalP.reverb (mkStdGen 857) 16 (0.9,0.97) (400,1000)) <<<- CausalP.mapSimple Frame.stereoFromMono)- 0.3 $- vibesCycleVector pingp- return ()----stair :: IO ()-stair =- SVL.writeFile "speedtest.f32" $- SVL.take 10000000 $- asMono $- flip (SigP.renderChunky tonesChunkSize) () $- SigP.piecewiseConstant $- return $- EventListBT.fromPairList $- zip- (iterate (/2) (1::Float))- (iterate (2*) (1::NonNeg.Int))---filterBass :: IO ()-filterBass = do- playStereoVector $- asStereo $- flip (SigP.renderChunky tonesChunkSize) () $- CausalP.apply- (BandPass.causalP- <<<- CausalP.feedSnd- (liftA2 Stereo.cons- (SigP.osciSimple Wave.saw 0 0.001499)- (SigP.osciSimple Wave.saw 0 0.001501))- <<<- CausalP.mapSimple (BandPass.parameter (valueOf (100::Float)))) $- SigP.piecewiseConstant $- return $ EventListBT.fromPairList $- zip- (map (((0.03::Float)*) . (2**) . (/12) . fromInteger) $- randomRs (0,12) (mkStdGen 998))- (repeat (10000::NonNeg.Int))-- return ()---{- |-This function is not very efficient,-since it compiles an LLVM mixing routine-for every pair of mixer inputs.--}-mixVectorRecompile ::- SVL.Vector Float -> SVL.Vector Float -> SVL.Vector Float-mixVectorRecompile xs ys =- Sig.renderChunky tonesChunkSize $- Sig.mix- (Sig.fromStorableVectorLazy xs)- (Sig.fromStorableVectorLazy ys)--mixVectorParamIO ::- IO (SVL.Vector Float -> SVL.Vector Float -> SVL.Vector Float)-mixVectorParamIO =- fmap curry $- fmap ($tonesChunkSize) $- SigP.runChunky- (SigP.mix- (SigP.fromStorableVectorLazy fst)- (SigP.fromStorableVectorLazy snd))--mixVectorCausalIO ::- IO (SVL.Vector Float -> SVL.Vector Float -> SVL.Vector Float)-mixVectorCausalIO =- CausalP.runStorableChunky- (CausalP.mix $<- SigP.fromStorableVectorLazy id)--mixVectorCausal ::- SVL.Vector Float -> SVL.Vector Float -> SVL.Vector Float-mixVectorCausal =- CausalP.applyStorableChunky- (CausalP.mix $<- SigP.fromStorableVectorLazy id)--mixVectorStereo ::- SVL.Vector (Stereo.T Float) ->- SVL.Vector (Stereo.T Float) ->- SVL.Vector (Stereo.T Float)-mixVectorStereo =- CausalP.applyStorableChunky- (CausalP.mix $<- SigP.fromStorableVectorLazy id)--mixVectorStereoIO ::- IO (SVL.Vector (Stereo.T Float) ->- SVL.Vector (Stereo.T Float) ->- SVL.Vector (Stereo.T Float))-mixVectorStereoIO =- CausalP.runStorableChunky- (CausalP.mix $<- SigP.fromStorableVectorLazy id)--{--slightly slower than mixVectorParam--}-mixVectorHaskell ::- SVL.Vector Float -> SVL.Vector Float -> SVL.Vector Float-mixVectorHaskell = SVL.zipWith (+)--toneMix :: IO ()-toneMix = do- pingp <- makePing- mix <- mixVectorCausalIO- playMonoVector $- Causal.applyStorableChunky (Causal.amplify 0.1) $- foldl1 mix $- map (curry pingp 1000000) $- take numTones $- iterate (*(2/3)) 0.01- return ()--fadeEnvelope :: SigP.T (Int, Int) (Value Float)-fadeEnvelope =- SigP.parabolaFadeIn (fmap fromIntegral fst)- `SigP.append`- (CausalP.take snd $* (SigP.constant $# (1::Float)))- `SigP.append`- SigP.parabolaFadeOut (fmap fromIntegral fst)--fadeEnvelopeWrite :: IO ()-fadeEnvelopeWrite =- SVL.writeFile "speedtest.f32" $- asMono $- SigP.renderChunky (SVL.chunkSize 1234)- fadeEnvelope (100000, 200000)----- | normalize a list of numbers, such that they have a specific average--- Cf. haskore-supercollider/src/Haskore/Interface/SuperCollider/Example.hs-normalizeLevel :: Fractional a => a -> [a] -> [a]-normalizeLevel newAvrg xs =- let avrg = sum xs / genericLength xs- in map ((newAvrg-avrg)+) xs--stereoOsciSawP :: SigP.T Float (Stereo.T (Value Float))-stereoOsciSawP =- let freq = id- n = 5- volume = pure $ recip $ sqrt $ fromIntegral n :: Param.T p Float- detunes =- normalizeLevel 1 $ take (2*n) $- randomRs (0,0.03) $ mkStdGen 912- phases =- randomRs (0,1) $ mkStdGen 54- tones =- zipWith- (\phase detune ->- (SigP.osciSaw $# phase) (fmap (detune*) freq))- phases detunes- (tonesLeft,tonesRight) = splitAt n tones- in SigP.amplifyStereo volume $- liftA2 Stereo.cons- (foldl1 SigP.mix tonesLeft)- (foldl1 SigP.mix tonesRight)--stereoOsciSawVector :: Float -> SVL.Vector (Stereo.T Float)-stereoOsciSawVector =- SigP.renderChunky tonesChunkSize stereoOsciSawP--stereoOsciSawChord :: [Float] -> SVL.Vector (Stereo.T Float)-stereoOsciSawChord =- foldl1 mixVectorStereo . map stereoOsciSawVector--stereoOsciSawPad :: Int -> [Float] -> SVL.Vector (Stereo.T Float)-stereoOsciSawPad dur pitches =- let attack = 20000- in CausalP.applyStorableChunky- (CausalP.envelopeStereo $< fadeEnvelope)- (attack, dur-attack)- (stereoOsciSawChord pitches)--a0, as0, b0, c1, cs1, d1, ds1, e1, f1, fs1, g1, gs1,- a1, as1, b1, c2, cs2, d2, ds2, e2, f2, fs2, g2, gs2,- a2, as2, b2, c3, cs3, d3, ds3, e3, f3, fs3, g3, gs3,- a3, as3, b3, c4, cs4, d4, ds4, e4, f4, fs4, g4, gs4 :: Float-a0 : as0 : b0 : c1 : cs1 : d1 : ds1 : e1 : f1 : fs1 : g1 : gs1 :- a1 : as1 : b1 : c2 : cs2 : d2 : ds2 : e2 : f2 : fs2 : g2 : gs2 :- a2 : as2 : b2 : c3 : cs3 : d3 : ds3 : e3 : f3 : fs3 : g3 : gs3 :- a3 : as3 : b3 : c4 : cs4 : d4 : ds4 : e4 : f4 : fs4 : g4 : gs4 : _ =- iterate ((2 ** recip 12) *) (55/44100)---chordSequence :: [(Int, [Float])]-chordSequence =- (2, [f1, f2, a2, c3]) :- (1, [g1, g2, b2, d3]) :- (2, [c2, g2, c3, e3]) :- (1, [f1, a2, c3, f3]) :- (2, [g1, g2, b2, d3]) :- (1, [gs1, gs2, b2, e3]) :- (2, [a1, e2, a2, c3]) :- (1, [g1, g2, b2, d3]) :- (3, [c2, g2, c3, e3]) :-- (2, [f1, f2, a2, c3]) :- (1, [g1, g2, b2, d3]) :- (2, [c2, g2, c3, e3]) :- (1, [f1, a2, c3, f3]) :- (2, [g1, g2, b2, d3]) :- (1, [gs1, gs2, b2, e3]) :- (2, [a1, e2, a2, c3]) :- (1, [g1, g2, b2, e3]) :- (3, [c2, e2, g2, c3]) :- []---withDur :: (Int -> a -> v) -> Int -> a -> (v, NonNeg.Int)-withDur f d ps =- let dur = d*30000- in (f dur ps, NonNeg.fromNumber dur)---padMusic :: IO ()-padMusic = do- playStereoVector $- CausalP.applyStorableChunky (CausalP.amplifyStereo id) 0.1 $- SigStL.arrange tonesChunkSize $- EventListTM.switchTimeR const $- EventListMT.consTime 0 $- EventListBT.fromPairList $- map (\(d,ps) -> withDur stereoOsciSawPad d ps)- chordSequence- return ()---lowpassSweepControlRateCausal ::- CausalP.T p- (Stereo.T (Value Float))- (Stereo.T (Value Float))-lowpassSweepControlRateCausal =--- CausalP.stereoFromVector $- CausalP.stereoFromMono $- UniFilter.lowpass ^<<- CtrlP.processCtrlRate 128- (lfoSine (UniFilter.parameter (valueOf (10::Float))))---moogSweepControlRateCausal ::- CausalP.T p- (Stereo.T (Value Float))- (Stereo.T (Value Float))-moogSweepControlRateCausal =--- CausalP.stereoFromVector $- CausalP.stereoFromMono $- CtrlP.processCtrlRate 128- (lfoSine (Moog.parameter TypeNum.d8 (valueOf (10::Float))))---filterMusic :: IO ()-filterMusic = do- playStereoVector $- CausalP.applyStorableChunky- (CausalP.amplifyStereo id <<<- moogSweepControlRateCausal) 0.05 $- SigStL.arrange tonesChunkSize $- EventListTM.switchTimeR const $- EventListMT.consTime 0 $- EventListBT.fromPairList $- map (\(d,ps) -> withDur stereoOsciSawPad d ps)- chordSequence- return ()----stereoOsciSawVectorIO :: IO (Float -> SVL.Vector (Stereo.T Float))-stereoOsciSawVectorIO =- fmap ($tonesChunkSize) $- SigP.runChunky $- stereoOsciSawP--applyFadeEnvelopeIO ::- IO (Int -> SVL.Vector (Stereo.T Float) -> SVL.Vector (Stereo.T Float))-applyFadeEnvelopeIO =- fmap- (\envelope dur sig ->- let attack = 20000- in envelope (attack, dur-attack) sig)- (CausalP.runStorableChunky- (CausalP.envelopeStereo $< fadeEnvelope))--stereoOsciSawChordIO :: IO ([Float] -> SVL.Vector (Stereo.T Float))-stereoOsciSawChordIO = do- sawv <- stereoOsciSawVectorIO- mix <- mixVectorStereoIO- return (foldl1 mix . map sawv)--stereoOsciSawPadIO :: IO (Int -> [Float] -> SVL.Vector (Stereo.T Float))-stereoOsciSawPadIO = do- chrd <- stereoOsciSawChordIO- envelope <- applyFadeEnvelopeIO- return $- \ dur pitches -> envelope dur (chrd pitches)--padMusicIO :: IO ()-padMusicIO = do- pad <- stereoOsciSawPadIO- playStereoVector $- CausalP.applyStorableChunky (CausalP.amplifyStereo id) 0.08 $- SigStL.arrange tonesChunkSize $- EventListTM.switchTimeR const $- EventListMT.consTime 0 $- EventListBT.fromPairList $- map (uncurry (withDur pad)) $- chordSequence- return ()--{--Apply the envelope separately to each tone of the chord-and mix all tones by 'arrange'.--}-padMusicSeparate :: IO ()-padMusicSeparate = do- osci <- stereoOsciSawVectorIO- env <- applyFadeEnvelopeIO- playStereoVector $- CausalP.applyStorableChunky (CausalP.amplifyStereo id) 0.08 $- SigStL.arrange tonesChunkSize $- EventList.flatten $- EventListTM.switchTimeR const $- EventListMT.consTime 0 $- EventListBT.fromPairList $- map (uncurry (withDur (\d ps -> map (\p -> env d (osci p)) ps))) $- chordSequence- return ()---delay :: IO ()-delay =- SVL.writeFile "speedtest.f32" $- asMono $- flip (SigP.renderChunky tonesChunkSize) (0, 10000) $- CausalP.apply- ((CausalP.delay $# (0::Float)) fst- <<< CausalP.take snd) $- SigP.osciSaw 0 0.01--delayStereo :: IO ()-delayStereo =- SVL.writeFile "speedtest.f32" $- asStereo $- flip (SigP.renderChunky tonesChunkSize) (7, 10000) $- CausalP.apply- (CausalP.take snd- <<<- liftA2 Stereo.cons- id ((CausalP.delay $# (0::Float)) fst)) $- SigP.osciSaw 0 0.01----allpassControl ::- (TypeNum.Nat n) =>- n ->- SigP.T Float (Allpass.CascadeParameter n (Value Float))-allpassControl order =- let reduct = id- in SigP.interpolateConstant reduct $- lfoSine (Allpass.flangerParameter order) reduct--allpassPhaserCausal, allpassPhaserPipeline ::- SigP.T Float (Value Float) ->- SigP.T Float (Value Float)-allpassPhaserCausal =- let order = TypeNum.d16- in CausalP.apply $- CausalP.amplify 0.5 <<<- Allpass.phaserP <<<- CausalP.feedFst (allpassControl order)--allpassPhaserPipeline =- let order = TypeNum.d16- in -- (F.nest (TypeNum.toInt order) SigP.tail .) $- (SigP.drop (return $ TypeNum.toInt order) .) $- CausalP.apply $- CausalP.amplify 0.5 <<<- Allpass.phaserPipelineP <<<- CausalP.feedFst (allpassControl order)--allpassPhaser :: IO ()-allpassPhaser =- SVL.writeFile "speedtest.f32" $- asMono $- SVL.take 10000000 $- flip (SigP.renderChunky (SVL.chunkSize 100000)) 128 $- allpassPhaserPipeline $- (SigP.osciSaw 0 0.01)--noise :: IO ()-noise =- SVL.writeFile "speedtest.f32" $- asMono $- SVL.take 10000000 $- flip (SigP.renderChunky (SVL.chunkSize 100000)) () $- (SigP.noise 0 0.3)--noisePacked :: IO ()-noisePacked =- SVL.writeFile "speedtest.f32" $- asMonoPacked $- SVL.take (div 10000000 4) $- flip (SigP.renderChunky (SVL.chunkSize 100000)) () $- (SigPS.noise 0 0.3)--- (SigPS.pack (SigP.noise 0 0.3))--- (SigPS.packSmall (SigP.noise 0 0.3))--frequencyModulationStorable :: IO ()-frequencyModulationStorable = do- smp <- SigP.runChunky (SigP.osciSaw 0 0.01)- SVL.writeFile "speedtest.f32" $- asMono $- flip (SigP.renderChunky (SVL.chunkSize 100000)) () $- (CausalP.frequencyModulationLinear- (SigP.fromStorableVectorLazy $#- (SVL.take 1000000 $ asMono $- smp (SVL.chunkSize 1000) ()))- $*# (0.3::Float))--frequencyModulation :: IO ()-frequencyModulation =- SVL.writeFile "speedtest.f32" $- asMono $- SVL.take 10000000 $- flip (SigP.renderChunky (SVL.chunkSize 100000)) () $- (CausalP.frequencyModulationLinear- (SigP.osciSaw 0 0.01)- $* SigP.exponential2 500000 1)--frequencyModulationStereo :: IO ()-frequencyModulationStereo = do- smp <- SigP.runChunky (SigP.osciSaw 0 0.01)- SVL.writeFile "speedtest.f32" $- asStereo $- flip (SigP.renderChunky (SVL.chunkSize 100000)) () $- (CausalP.stereoFromMono- (CausalP.frequencyModulationLinear- (SigP.fromStorableVectorLazy $#- (SVL.take 1000000 $ asMono $- smp (SVL.chunkSize 1000) ())))- $*# Stereo.cons (0.2999::Float) 0.3001)---quantize :: IO ()-quantize =-{-- SV.writeFile "speedtest.f32" $- asMono $- (\xs -> SigP.render xs 10000000 ()) $--}- SVL.writeFile "speedtest.f32" $- asMono $- SVL.take 10000000 $- flip (SigP.renderChunky (SVL.chunkSize 100000)) () $- ((CausalP.quantizeLift $# (5.5::Float)) id $*- SigP.osciSaw 0 0.01)--quantizedFilterControl :: IO ()-quantizedFilterControl =- SVL.writeFile "speedtest.f32" $- asMono $- SVL.take 10000000 $- flip (SigP.renderChunky (SVL.chunkSize 100000)) () $- CausalP.apply (CausalP.amplify 0.3 <<< UniFilter.lowpass ^<< CtrlP.process) $- SigP.zip- ((CausalP.quantizeLift $# (128::Float))- (CausalP.mapSimple (UniFilter.parameter (valueOf 100)) <<<--- (CausalP.mapSimple (Moog.parameter TypeNum.d8 (valueOf 100)) <<<- CausalP.mapSimple (\x -> 0.01 * exp (2 * return x)))- $* (SigP.osciSimple Wave.approxSine2 $# (0::Float)) (0.1/44100)) $- (SigP.osciSaw $# (0::Float)) 0.01---arrowNonShared :: IO ()-arrowNonShared =- SVL.writeFile "speedtest.f32" $- asStereo $- SVL.take 10000000 $- flip (SigP.renderChunky (SVL.chunkSize 100000)) () $- (let osci = CausalP.osciSimple Wave.approxSine2- in liftA2 Stereo.cons osci osci $*- SigP.constant (return (0::Float, 0.01::Float)))--arrowShared :: IO ()-arrowShared =- SVL.writeFile "speedtest.f32" $- asStereo $- SVL.take 10000000 $- flip (SigP.renderChunky (SVL.chunkSize 100000)) () $- (let osci = Func.lift (CausalP.osciSimple Wave.approxSine2)- in Func.compile (liftA2 Stereo.cons osci osci) $*- SigP.constant (return (0::Float, 0.01::Float)))--arrowIndependent :: IO ()-arrowIndependent =- SVL.writeFile "speedtest.f32" $- asStereo $- SVL.take 10000000 $- flip (SigP.renderChunky (SVL.chunkSize 100000)) () $- (let osci = CausalP.osciSimple Wave.approxSine2- in Func.compile- (fmap (uncurry Stereo.cons) $- osci *** osci Func.$&- Func.lift id) $*- SigP.constant (return ((0::Float, 0.01::Float), (0.25::Float, 0.01001::Float))))---main :: IO ()-main = do- LLVM.initializeNativeTarget- arrowIndependent
src/Synthesizer/LLVM/Wave.hs view
@@ -1,88 +1,78 @@ {-# LANGUAGE NoImplicitPrelude #-}+{-# LANGUAGE TypeFamilies #-} module Synthesizer.LLVM.Wave where import qualified Synthesizer.LLVM.Simple.Value as Value-import qualified LLVM.Extra.ScalarOrVector as SoV import qualified LLVM.Extra.Arithmetic as A import qualified LLVM.Extra.Monad as M -import qualified LLVM.Core as LLVM-import LLVM.Core- (Value, CodeGenFunction,- IsFloating, IsArithmetic, IsConst, )+import LLVM.Core (CodeGenFunction, ) import Control.Monad.HT ((<=<), ) -import qualified Algebra.Transcendental as Trans-import qualified Algebra.Field as Field-import qualified Algebra.Ring as Ring- import NumericPrelude.Numeric import NumericPrelude.Base hiding (replicate, ) saw ::- (Ring.C a, IsConst a, SoV.Replicate a v, IsArithmetic v) =>- Value v -> CodeGenFunction r (Value v)+ (A.PseudoRing a, A.IntegerConstant a) =>+ a -> CodeGenFunction r a saw =- A.sub (SoV.replicateOf 1) <=<- A.mul (SoV.replicateOf 2)+ A.sub (A.fromInteger' 1) <=<+ A.mul (A.fromInteger' 2) square ::- (Ring.C a, IsConst a,- SoV.Replicate a v, SoV.Fraction v, SoV.Real v) =>- Value v -> CodeGenFunction r (Value v)+ (A.PseudoRing a, A.IntegerConstant a, A.Fraction a) =>+ a -> CodeGenFunction r a square =- A.sub (SoV.replicateOf 1) <=<- A.mul (SoV.replicateOf 2) <=<- SoV.truncate <=<- A.mul (SoV.replicateOf 2)+ A.sub (A.fromInteger' 1) <=<+ A.mul (A.fromInteger' 2) <=<+ A.truncate <=<+ A.mul (A.fromInteger' 2) triangle ::- (Field.C a, IsConst a,- SoV.Replicate a v, SoV.Fraction v, SoV.Real v) =>- Value v -> CodeGenFunction r (Value v)+ (A.PseudoRing a, A.RationalConstant a, A.Fraction a) =>+ a -> CodeGenFunction r a triangle =- flip A.sub (SoV.replicateOf 1) <=<- SoV.abs <=<- flip A.sub (SoV.replicateOf 2) <=<- A.mul (SoV.replicateOf 4) <=<- SoV.incPhase (SoV.replicateOf 0.75)+ flip A.sub (A.fromInteger' 1) <=<+ A.abs <=<+ flip A.sub (A.fromInteger' 2) <=<+ A.mul (A.fromInteger' 4) <=<+ A.incPhase (A.fromRational' 0.75) approxSine2 ::- (Ring.C a, IsConst a, SoV.Replicate a v, SoV.Real v) =>- Value v -> CodeGenFunction r (Value v)+ (A.PseudoRing a, A.IntegerConstant a, A.Fraction a) =>+ a -> CodeGenFunction r a approxSine2 t = do x <- saw t- A.mul (SoV.replicateOf 4) =<<+ A.mul (A.fromInteger' 4) =<< A.mul x =<<- A.sub (SoV.replicateOf 1) =<<- SoV.abs x+ A.sub (A.fromInteger' 1) =<<+ A.abs x approxSine3 ::- (Field.C a, IsConst a,- SoV.Replicate a v, SoV.Fraction v, SoV.Real v) =>- Value v -> CodeGenFunction r (Value v)+ (A.PseudoRing a, A.RationalConstant a, A.Fraction a) =>+ a -> CodeGenFunction r a approxSine3 t = do x <- triangle t- A.mul (SoV.replicateOf 0.5) =<<+ A.mul (A.fromRational' 0.5) =<< A.mul x =<<- A.sub (SoV.replicateOf 3) =<<+ A.sub (A.fromInteger' 3) =<< A.mul x x approxSine4 ::- (Field.C a, IsConst a, SoV.Replicate a v, SoV.Real v) =>- Value v -> CodeGenFunction r (Value v)+ (A.PseudoRing a, A.RationalConstant a, A.Real a) =>+ a -> CodeGenFunction r a approxSine4 t = do x <- saw t- ax <- SoV.abs x- sax <- A.sub (SoV.replicateOf 1) ax- A.mul (SoV.replicateOf (16/5)) =<<+ ax <- A.abs x+ sax <- A.sub (A.fromInteger' 1) ax+ A.mul (A.fromRational' (16/5)) =<< A.mul x =<< A.mul sax =<<- A.add (SoV.replicateOf 1) =<<+ A.add (A.fromInteger' 1) =<< A.mul sax ax {- |@@ -91,18 +81,18 @@ We have chosen this scaling in order to stay with field operations. -} rationalApproxCosine1, rationalApproxSine1 ::- (Field.C a, IsConst a, SoV.Replicate a v, SoV.Real v, IsFloating v) =>- Value v -> Value v -> CodeGenFunction r (Value v)+ (A.Field a, A.RationalConstant a, A.Real a) =>+ a -> a -> CodeGenFunction r a rationalApproxCosine1 k t = do num2 <- A.square =<< A.mul k =<<- A.add (SoV.replicateOf (-1)) =<<- A.mul (SoV.replicateOf 2) t+ A.add (A.fromInteger' (-1)) =<<+ A.mul (A.fromInteger' 2) t den2 <- A.square =<< A.mul t =<<- A.sub (SoV.replicateOf 1) t+ A.sub (A.fromInteger' 1) t M.liftR2 A.fdiv (A.sub num2 den2) (A.add num2 den2)@@ -110,31 +100,29 @@ rationalApproxSine1 k t = do num <- A.mul k =<<- A.add (SoV.replicateOf (-1)) =<<- A.mul (SoV.replicateOf 2) t+ A.add (A.fromInteger' (-1)) =<<+ A.mul (A.fromInteger' 2) t den <- A.mul t =<<- A.sub (SoV.replicateOf 1) t+ A.sub (A.fromInteger' 1) t M.liftR2 A.fdiv- (A.mul (SoV.replicateOf (-2)) =<< A.mul num den)+ (A.mul (A.fromInteger' (-2)) =<< A.mul num den) (M.liftR2 A.add (A.square num) (A.square den)) trapezoidSkew ::- (Field.C a, IsConst a,- SoV.Replicate a v, SoV.Fraction v, SoV.Real v) =>- Value v -> Value v -> CodeGenFunction r (Value v)+ (A.Field a, A.RationalConstant a, A.Real a) =>+ a -> a -> CodeGenFunction r a trapezoidSkew p =- SoV.max (SoV.replicateOf (-1)) <=<- SoV.min (SoV.replicateOf 1) <=<+ A.max (A.fromInteger' (-1)) <=<+ A.min (A.fromInteger' 1) <=< flip A.fdiv p <=<- A.sub (SoV.replicateOf 1) <=<- A.mul (SoV.replicateOf 2)+ A.sub (A.fromInteger' 1) <=<+ A.mul (A.fromInteger' 2) sine ::- (Trans.C a, IsFloating a, IsConst a) =>--- Value a -> TValue r a- Value a -> CodeGenFunction r (Value a)+ (A.Transcendental a, A.RationalConstant a) =>+ a -> CodeGenFunction r a sine t = A.sin =<< A.mul t =<< Value.decons Value.twoPi @@ -150,14 +138,13 @@ shrinks a triangle wave such that 2.5 periods fit into one. -} replicate ::- (Field.C a, IsConst a,- SoV.Replicate a v, SoV.Fraction v, SoV.Real v) =>- Value v -> Value v -> CodeGenFunction r (Value v)+ (A.PseudoRing a, A.RationalConstant a, A.Fraction a) =>+ a -> a -> CodeGenFunction r a replicate k =- SoV.fraction <=<+ A.fraction <=< A.mul k <=<- flip A.sub (SoV.replicateOf 0.5) <=<- SoV.incPhase (SoV.replicateOf 0.5)+ flip A.sub (A.fromRational' 0.5) <=<+ A.incPhase (A.fromRational' 0.5) {- | Preprocess the phase such that the first half of a wave@@ -171,23 +158,18 @@ generated using 'replicate'. -} halfEnvelope ::- (Field.C a, IsConst a,- SoV.Replicate a v, SoV.Fraction v, SoV.Real v) =>- Value v -> CodeGenFunction r (Value v)+ (A.PseudoRing a, A.RationalConstant a, A.Fraction a) =>+ a -> CodeGenFunction r a halfEnvelope =- A.mul (SoV.replicateOf 0.5) <=<- SoV.incPhase (SoV.replicateOf 0.5)+ A.mul (A.fromRational' 0.5) <=<+ A.incPhase (A.fromRational' 0.5) partial ::- (LLVM.IsPrimitive i, LLVM.IsPrimitive a,- LLVM.IsInteger i, IsFloating a,- SoV.Replicate a v, SoV.Fraction v) =>- (Value v -> CodeGenFunction r (Value v)) ->- Value i ->- (Value v -> CodeGenFunction r (Value v))+ (A.Fraction v, A.PseudoRing v, A.IntegerConstant v) =>+ (v -> CodeGenFunction r v) ->+ Int ->+ (v -> CodeGenFunction r v) partial w n t = w =<<- SoV.signedFraction =<<- A.mul t =<<- SoV.replicate =<<- LLVM.inttofp n+ A.signedFraction =<<+ A.mul t (A.fromInteger' (fromIntegral n))
− src/Test/Main.hs
@@ -1,22 +0,0 @@-module Main where--import qualified Test.Synthesizer.LLVM.Filter as Filter-import qualified Test.Synthesizer.LLVM.Packed as Packed--import qualified LLVM.Core as LLVM--import Data.Tuple.HT (mapFst, )---prefix :: String -> [(String, IO ())] -> [(String, IO ())]-prefix msg =- map (mapFst (\str -> msg ++ "." ++ str))--main :: IO ()-main = do- LLVM.initializeNativeTarget- mapM_ (\(name,test) -> putStr (name ++ ": ") >> test) $- concat $- prefix "Filter" Filter.tests :- prefix "Packed" Packed.tests :- []
− src/Test/Synthesizer/LLVM/Filter.hs
@@ -1,500 +0,0 @@-{-# LANGUAGE NoImplicitPrelude #-}-{-# LANGUAGE Rank2Types #-}-module Test.Synthesizer.LLVM.Filter (tests) where--import qualified Synthesizer.LLVM.Filter.Allpass as Allpass-import qualified Synthesizer.LLVM.Filter.FirstOrder as FirstOrder-import qualified Synthesizer.LLVM.Filter.SecondOrder as SecondOrder-import qualified Synthesizer.LLVM.Filter.SecondOrderPacked as SecondOrderP-import qualified Synthesizer.LLVM.Filter.Universal as UniFilter-import qualified Synthesizer.LLVM.Filter.Moog as Moog-import qualified Synthesizer.LLVM.Filter.ComplexFirstOrder as ComplexFilter-import qualified Synthesizer.LLVM.Filter.ComplexFirstOrderPacked as ComplexFilterP--import qualified Synthesizer.Plain.Filter.Recursive.Allpass as AllpassCore-import qualified Synthesizer.Plain.Filter.Recursive.FirstOrder as FirstOrderCore-import qualified Synthesizer.Plain.Filter.Recursive.Universal as UniFilterCore-import qualified Synthesizer.Plain.Filter.Recursive.Moog as MoogCore-import qualified Synthesizer.Plain.Filter.Recursive.FirstOrderComplex as ComplexFilterCore--import qualified Synthesizer.LLVM.Parameter as Param-import qualified LLVM.Extra.Memory as Memory-import qualified Synthesizer.LLVM.Wave as Wave-import qualified Synthesizer.LLVM.CausalParameterized.Process as CausalP-import qualified Synthesizer.LLVM.Parameterized.SignalPacked as SigPS-import qualified Synthesizer.LLVM.Parameterized.Signal as SigP-import Synthesizer.LLVM.CausalParameterized.Process (($<), ($*), )-import Synthesizer.LLVM.Parameterized.Signal (($#), )--import Synthesizer.Plain.Filter.Recursive (Pole(Pole))--- import qualified Synthesizer.Storable.Signal as SigSt-import qualified Synthesizer.Interpolation.Module as Ip-import qualified Synthesizer.Causal.Interpolation as InterpC-import qualified Synthesizer.Causal.Filter.NonRecursive as FiltC-import qualified Synthesizer.Causal.Displacement as DispC-import qualified Synthesizer.Causal.Process as CausalS-import qualified Synthesizer.Basic.Wave as WaveCore-import qualified Synthesizer.State.Displacement as DispS-import qualified Synthesizer.State.Oscillator as OsciS-import qualified Synthesizer.State.Signal as SigS-import qualified Synthesizer.Basic.Phase as Phase--import qualified Data.StorableVector.Lazy as SVL-import Data.StorableVector.Lazy (ChunkSize, )--import Test.Synthesizer.LLVM.Utility- (checkSimilarity, checkSimilarityState, rangeFromInt, )--import qualified Control.Category as Cat-import Control.Category ((<<<), )-import Control.Arrow ((&&&), (^<<), (<<^), )--import LLVM.Core (Value, Vector, )-import qualified LLVM.Core as LLVM-import qualified Data.TypeLevel.Num as TypeNum-import Data.TypeLevel.Num (D4, )--import qualified Number.Complex as Complex-import qualified Synthesizer.LLVM.Frame.Stereo as Stereo--import Test.QuickCheck (quickCheck, )--import NumericPrelude.Numeric-import NumericPrelude.Base---signalLength :: Int-signalLength = 10000---limitFloat :: SVL.Vector Float -> SVL.Vector Float-limitFloat = SVL.take signalLength--{--limitStereoFloat :: SVL.Vector (Stereo.T Float) -> SVL.Vector (Stereo.T Float)-limitStereoFloat = SVL.take signalLength--}---lfoSine ::- (Memory.C a ap, LLVM.IsSized ap asize) =>- (forall r. Value Float -> LLVM.CodeGenFunction r a) ->- Param.T p Float ->- SigP.T p a-lfoSine f reduct =- SigP.interpolateConstant reduct $- SigP.mapSimple f $- CausalP.apply (CausalP.mapExponential 2 0.01) $- SigP.osciSimple Wave.sine 0 (fmap (* (0.1/44100)) reduct)--allpassControl ::- (TypeNum.Nat n) =>- n ->- Param.T p Float ->- SigP.T p (Allpass.CascadeParameter n (Value Float))-allpassControl order =- lfoSine (Allpass.flangerParameter order)--allpassPhaserCausal, allpassPhaserPipeline ::- Param.T p Float ->- SigP.T p (Value Float) ->- SigP.T p (Value Float)-allpassPhaserCausal reduct =- CausalP.apply- (Allpass.phaserP- $< allpassControl TypeNum.d16 reduct)--allpassPhaserPipeline reduct xs =- let order = TypeNum.d16- in (SigP.drop $# TypeNum.toInt order) $- (Allpass.phaserPipelineP- $< allpassControl order reduct- $* xs)--allpassPipeline :: IO (ChunkSize -> ((Int,Int), Int) -> Bool)-allpassPipeline =- let freq = rangeFromInt (0.001, 0.01) <<^ fst . fst- phase = rangeFromInt (0, 0.99) <<^ snd . fst- reduct = rangeFromInt (10, 100) <<^ snd- tone = SigP.osciSimple Wave.triangle phase freq- in checkSimilarity 1e-2 limitFloat- (allpassPhaserCausal reduct tone)- (allpassPhaserPipeline reduct tone)----{- |-Shrink control signal in time-since we can only handle one control parameter per vector chunk.--}-applyPacked ::- (Memory.C c cp, LLVM.IsSized cp cs) =>- CausalP.T p- (c, Value (Vector D4 Float))- (Value (Vector D4 Float)) ->- SigP.T p c ->- SigP.T p (Value (Vector D4 Float)) ->- SigP.T p (Value (Vector D4 Float))-applyPacked proc cs xs =- proc- $< ((SigP.interpolateConstant $#- (recip $ TypeNum.toNum TypeNum.d4 :: Float)) cs)- $* xs---allpassPhaserPacked ::- Param.T p Float ->- SigP.T p (Value (Vector D4 Float)) ->- SigP.T p (Value (Vector D4 Float))-allpassPhaserPacked reduct =- applyPacked Allpass.phaserPackedP- (allpassControl TypeNum.d16 reduct)--allpassPacked :: IO (ChunkSize -> ((Int,Int), Int) -> Bool)-allpassPacked =- let freq = rangeFromInt (0.001, 0.01) <<^ fst . fst- phase = rangeFromInt (0, 0.99) <<^ snd . fst- reduct = (4*) ^<< rangeFromInt (1, 25) <<^ snd- tone = SigP.osciSimple Wave.triangle phase freq- toneP = SigPS.osciSimple Wave.triangle phase freq- in checkSimilarity 1e-2 limitFloat- (allpassPhaserCausal reduct tone)- (SigPS.unpack $ allpassPhaserPacked reduct toneP)---interpolateConstant :: Float -> SigS.T a -> SigS.T a-interpolateConstant reduct xs =- CausalS.apply (InterpC.relative Ip.constant 0 xs) $- SigS.repeat $ recip reduct---{-# INLINE lfoSineCore #-}-lfoSineCore ::- (Float -> a) ->- Float ->- SigS.T a-lfoSineCore f reduct =- interpolateConstant reduct $- SigS.map f $- DispS.mapExponential 2 0.01 $- OsciS.static WaveCore.sine zero (reduct * 0.1/44100)--{-# INLINE allpassPhaserCore #-}-allpassPhaserCore ::- Float ->- SigS.T Float ->- SigS.T Float-allpassPhaserCore reduct =- let order = 16- in CausalS.apply $- FiltC.amplify 0.5 <<<- DispC.mix <<<- ((CausalS.applyFst (AllpassCore.cascadeCausal order) $- lfoSineCore (AllpassCore.flangerParameter order) reduct)- &&&- Cat.id)--allpassCore :: IO (ChunkSize -> ((Int,Int), Int) -> Bool)-allpassCore =- let freq = rangeFromInt (0.001, 0.01) <<^ fst . fst- phase = rangeFromInt (0, 0.99) <<^ snd . fst- reduct = rangeFromInt (10, 100) <<^ snd- tone = SigP.osciSimple Wave.triangle phase freq- toneS p =- OsciS.static WaveCore.triangle- (Phase.fromRepresentative (Param.get phase p)) (Param.get freq p)- in checkSimilarityState 1e-2 limitFloat- (allpassPhaserCausal reduct tone)- (\p -> allpassPhaserCore (Param.get reduct p) (toneS p))----diracImpulse :: SigP.T p (Value Float)-diracImpulse =- (CausalP.delay1 $# (one::Float)) $*- (SigP.constant $# (zero::Float))--firstOrderConstant ::- Param.T p Float ->- SigP.T p (Value Float) ->- SigP.T p (Value Float)-firstOrderConstant cutOff xs =- FirstOrder.lowpassCausalP- $< SigP.constant (FirstOrderCore.parameter ^<< cutOff)- $* xs--firstOrderExponential :: IO (ChunkSize -> (Int,Int) -> Bool)-firstOrderExponential =- let cutOff = rangeFromInt (0.001, 0.01) <<^ fst- gain = exp(-2*pi*cutOff)- in checkSimilarity 1e-2 limitFloat- (SigP.amplify (recip (1 - gain)) $- firstOrderConstant cutOff diracImpulse)- (SigP.exponentialCore gain $# (one :: Float))--firstOrderCausal ::- Param.T p Float ->- SigP.T p (Value Float) ->- SigP.T p (Value Float)-firstOrderCausal reduct xs =- FirstOrder.lowpassCausalP- $< lfoSine FirstOrder.parameter reduct- $* xs--{-# INLINE firstOrderCore #-}-firstOrderCore ::- Float ->- SigS.T Float ->- SigS.T Float-firstOrderCore reduct =- CausalS.apply $- CausalS.applyFst FirstOrderCore.lowpassCausal $- lfoSineCore FirstOrderCore.parameter reduct--firstOrder :: IO (ChunkSize -> ((Int,Int), Int) -> Bool)-firstOrder =- let freq = rangeFromInt (0.001, 0.01) <<^ fst . fst- phase = rangeFromInt (0, 0.99) <<^ snd . fst- reduct = rangeFromInt (10, 100) <<^ snd- tone = SigP.osciSimple Wave.triangle phase freq- toneS p =- OsciS.static WaveCore.triangle- (Phase.fromRepresentative (Param.get phase p)) (Param.get freq p)- in checkSimilarityState 1e-2 limitFloat- (firstOrderCausal reduct tone)- (\p -> firstOrderCore (Param.get reduct p) (toneS p))--firstOrderCausalPacked ::- Param.T p Float ->- SigP.T p (Value (Vector D4 Float)) ->- SigP.T p (Value (Vector D4 Float))-firstOrderCausalPacked reduct =- applyPacked- (FirstOrder.lowpassCausalPackedP)- (lfoSine FirstOrder.parameter reduct)--firstOrderPacked :: IO (ChunkSize -> ((Int,Int), Int) -> Bool)-firstOrderPacked =- let freq = rangeFromInt (0.001, 0.01) <<^ fst . fst- phase = rangeFromInt (0, 0.99) <<^ snd . fst- reduct = (4*) ^<< rangeFromInt (1, 25) <<^ snd- tone = SigP.osciSimple Wave.triangle phase freq- toneP = SigPS.osciSimple Wave.triangle phase freq- in checkSimilarity 1e-2 limitFloat- (firstOrderCausal reduct tone)- (SigPS.unpack $ firstOrderCausalPacked reduct toneP)---secondOrderCausal ::- Param.T p Float ->- SigP.T p (Value Float) ->- SigP.T p (Value Float)-secondOrderCausal reduct xs =- SecondOrder.causalP- $< lfoSine (SecondOrder.bandpassParameter (LLVM.valueOf (10::Float))) reduct- $* xs--secondOrderCausalPacked ::- Param.T p Float ->- SigP.T p (Value (Vector D4 Float)) ->- SigP.T p (Value (Vector D4 Float))-secondOrderCausalPacked reduct =- applyPacked SecondOrder.causalPackedP- (lfoSine (SecondOrder.bandpassParameter (LLVM.valueOf (10::Float))) reduct)--secondOrderPacked :: IO (ChunkSize -> ((Int,Int), Int) -> Bool)-secondOrderPacked =- let freq = rangeFromInt (0.001, 0.01) <<^ fst . fst- phase = rangeFromInt (0, 0.99) <<^ snd . fst- reduct = (4*) ^<< rangeFromInt (1, 25) <<^ snd- tone = SigP.osciSimple Wave.triangle phase freq- toneP = SigPS.osciSimple Wave.triangle phase freq- in checkSimilarity 1e-2 limitFloat- (secondOrderCausal reduct tone)- (SigPS.unpack $ secondOrderCausalPacked reduct toneP)--secondOrderCausalPacked2 ::- Param.T p Float ->- SigP.T p (Value Float) ->- SigP.T p (Value Float)-secondOrderCausalPacked2 reduct xs =- SecondOrderP.causalP- $< lfoSine (SecondOrderP.bandpassParameter (LLVM.valueOf (10::Float))) reduct- $* xs--secondOrderPacked2 :: IO (ChunkSize -> ((Int,Int), Int) -> Bool)-secondOrderPacked2 =- let freq = rangeFromInt (0.001, 0.01) <<^ fst . fst- phase = rangeFromInt (0, 0.99) <<^ snd . fst- reduct = rangeFromInt (10, 100) <<^ snd- tone = SigP.osciSimple Wave.triangle phase freq- in checkSimilarity 1e-2 limitFloat- (secondOrderCausal reduct tone)- (secondOrderCausalPacked2 reduct tone)---{--limitUniFilter ::- SVL.Vector (UniFilterCore.Result Float) ->- SVL.Vector (UniFilterCore.Result Float)-limitUniFilter = SVL.take signalLength--}--universalCausal ::- Param.T p Float ->- SigP.T p (Value Float) ->- SigP.T p (UniFilter.Result (Value Float))-universalCausal reduct xs =- UniFilter.causalP- $< lfoSine (UniFilter.parameter (LLVM.valueOf (10::Float))) reduct- $* xs--{-# INLINE universalCore #-}-universalCore ::- Float ->- SigS.T Float ->- SigS.T (UniFilterCore.Result Float)-universalCore reduct =- CausalS.apply $- CausalS.applyFst UniFilterCore.causal $- lfoSineCore (UniFilterCore.parameter . Pole 10) reduct--universal :: IO (ChunkSize -> ((Int,Int), Int) -> Bool)-universal =- let freq = rangeFromInt (0.001, 0.01) <<^ fst . fst- phase = rangeFromInt (0, 0.99) <<^ snd . fst- reduct = rangeFromInt (10, 100) <<^ snd- tone = SigP.osciSimple Wave.triangle phase freq- toneS p =- OsciS.static WaveCore.triangle- (Phase.fromRepresentative (Param.get phase p)) (Param.get freq p)- in checkSimilarityState 1e-2 limitFloat- (fmap UniFilter.lowpass $- universalCausal reduct tone)- (\p ->- SigS.map UniFilterCore.lowpass $- universalCore (Param.get reduct p) (toneS p))-{-- checkSimilarityState 1e-2 limitUniFilter- (universalCausal reduct tone)- (\p -> universalCore (Param.get reduct p) (toneS p))--}---moogCausal ::- (TypeNum.Nat n) =>- n ->- Param.T p Float ->- SigP.T p (Value Float) ->- SigP.T p (Value Float)-moogCausal order reduct xs =- Moog.causalP- $< lfoSine (Moog.parameter order (LLVM.valueOf (10::Float))) reduct- $* xs--{-# INLINE moogCore #-}-moogCore ::- Int ->- Float ->- SigS.T Float ->- SigS.T Float-moogCore order reduct =- CausalS.apply $- CausalS.applyFst (MoogCore.lowpassCausal order) $- lfoSineCore (MoogCore.parameter order . Pole 10) reduct--moog :: IO (ChunkSize -> ((Int,Int), Int) -> Bool)-moog =- let freq = rangeFromInt (0.001, 0.01) <<^ fst . fst- phase = rangeFromInt (0, 0.99) <<^ snd . fst- reduct = rangeFromInt (10, 100) <<^ snd- order = TypeNum.d6- tone = SigP.osciSimple Wave.triangle phase freq- toneS p =- OsciS.static WaveCore.triangle- (Phase.fromRepresentative (Param.get phase p)) (Param.get freq p)- in checkSimilarityState 1e-2 limitFloat- (moogCausal order reduct tone)- (\p -> moogCore (TypeNum.toInt order) (Param.get reduct p) (toneS p))---complexCausal ::- Param.T p Float ->- SigP.T p (Value Float) ->- SigP.T p (Stereo.T (Value Float))-complexCausal reduct =- CausalP.apply $- (ComplexFilter.causalP- $< lfoSine (ComplexFilter.parameter (LLVM.valueOf (10::Float))) reduct)- <<^ (\x -> Stereo.cons x (LLVM.value LLVM.zero))--complexCausalPacked ::- Param.T p Float ->- SigP.T p (Value Float) ->- SigP.T p (Stereo.T (Value Float))-complexCausalPacked reduct =- CausalP.apply $- (ComplexFilterP.causalP- $< lfoSine (ComplexFilterP.parameter (LLVM.valueOf (10::Float))) reduct)- <<^ (\x -> Stereo.cons x (LLVM.value LLVM.zero))--complexPacked :: IO (ChunkSize -> ((Int,Int), Int) -> Bool)-complexPacked =- let freq = rangeFromInt (0.001, 0.01) <<^ fst . fst- phase = rangeFromInt (0, 0.99) <<^ snd . fst- reduct = rangeFromInt (10, 100) <<^ snd- tone = SigP.osciSimple Wave.triangle phase freq- in checkSimilarity 1e-2 limitFloat- (fmap Stereo.left $- complexCausal reduct tone)- (fmap Stereo.left $- complexCausalPacked reduct tone)--{-# INLINE complexCore #-}-complexCore ::- Float ->- SigS.T Float ->- SigS.T (Stereo.T Float)-complexCore reduct =- CausalS.apply $- (\x -> Stereo.cons (Complex.real x) (Complex.imag x)) ^<<- CausalS.applyFst ComplexFilterCore.causal- (lfoSineCore (ComplexFilterCore.parameter . Pole 10) reduct)--complex :: IO (ChunkSize -> ((Int,Int), Int) -> Bool)-complex =- let freq = rangeFromInt (0.001, 0.01) <<^ fst . fst- phase = rangeFromInt (0, 0.99) <<^ snd . fst- reduct = rangeFromInt (10, 100) <<^ snd- tone = SigP.osciSimple Wave.triangle phase freq- toneS p =- OsciS.static WaveCore.triangle- (Phase.fromRepresentative (Param.get phase p)) (Param.get freq p)- in checkSimilarityState 1e-2 limitFloat- (fmap Stereo.left $- complexCausal reduct tone)- (\p ->- SigS.map ((0.1*) . Stereo.left) $- complexCore (Param.get reduct p) (toneS p))-{-- in checkSimilarityState 1e-2 limitStereoFloat- (complexCausal reduct tone)- (\p -> complexCore (Param.get reduct p) (toneS p))--}---tests :: [(String, IO ())]-tests =- ("secondOrderPacked", quickCheck =<< secondOrderPacked) :- ("secondOrderPacked2", quickCheck =<< secondOrderPacked2) :- ("firstOrderExponential", quickCheck =<< firstOrderExponential) :- ("firstOrder", quickCheck =<< firstOrder) :- ("firstOrderPacked", quickCheck =<< firstOrderPacked) :- ("universal", quickCheck =<< universal) :- ("allpassPacked", quickCheck =<< allpassPacked) :- ("allpassPipeline", quickCheck =<< allpassPipeline) :- ("allpassCore", quickCheck =<< allpassCore) :- ("moog", quickCheck =<< moog) :- ("complexPacked", quickCheck =<< complexPacked) :- ("complex", quickCheck =<< complex) :- []
− src/Test/Synthesizer/LLVM/Packed.hs
@@ -1,200 +0,0 @@-{-# LANGUAGE NoImplicitPrelude #-}-module Test.Synthesizer.LLVM.Packed (tests) where--import Test.Synthesizer.LLVM.Utility- (checkSimilarity, checkEquality, rangeFromInt, )--import qualified Synthesizer.LLVM.Wave as Wave-import qualified Synthesizer.LLVM.Parameter as Param--import LLVM.Core (Value, Vector, )-import Data.TypeLevel.Num (D4, )-import qualified Data.TypeLevel.Num as TypeNum--import qualified Synthesizer.LLVM.Generator.Exponential2 as Exp-import qualified Synthesizer.LLVM.Parameterized.SignalPacked as SigPS-import qualified Synthesizer.LLVM.Parameterized.Signal as SigP-import qualified Synthesizer.LLVM.CausalParameterized.Process as CausalP-import Synthesizer.LLVM.Parameterized.Signal (($#), )-import Synthesizer.LLVM.CausalParameterized.Process (($*), )--import qualified Synthesizer.LLVM.Storable.Signal as SigStL-import qualified Data.StorableVector.Lazy as SVL-import Data.StorableVector.Lazy (ChunkSize, )--import Control.Arrow ((^<<), (<<^), (<<<), )--import Data.Word (Word32, )--import Test.QuickCheck (quickCheck, )--import NumericPrelude.Numeric-import NumericPrelude.Base---signalLength :: Int-signalLength = 10000---limitFloat :: SVL.Vector Float -> SVL.Vector Float-limitFloat = SVL.take signalLength--{--limitPackedFloat ::- SVL.Vector (Vector D4 Float) -> SVL.Vector (Vector D4 Float)-limitPackedFloat = SVL.take (div signalLength 4)--}--constant :: IO (ChunkSize -> Int -> Bool)-constant =- let y = rangeFromInt (-1, 1)- in checkSimilarity 1e-3 limitFloat- (SigP.constant y)- (SigPS.unpack (SigPS.constant y ::- SigP.T Int (Value (Vector D4 Float))))--ramp :: IO (ChunkSize -> Int -> Bool)-ramp =- let dur = fromIntegral ^<< rangeFromInt (signalLength,2*signalLength)- in checkSimilarity 1e-3 limitFloat- (SigP.rampInf dur)- (SigPS.unpack (SigPS.rampInf dur ::- SigP.T Int (Value (Vector D4 Float))))--parabolaFadeIn :: IO (ChunkSize -> Int -> Bool)-parabolaFadeIn =- let dur = fromIntegral ^<< rangeFromInt (signalLength,2*signalLength)- in checkSimilarity 1e-3 limitFloat- (SigP.parabolaFadeInInf dur)- (SigPS.unpack (SigPS.parabolaFadeInInf dur ::- SigP.T Int (Value (Vector D4 Float))))--parabolaFadeOut :: IO (ChunkSize -> Int -> Bool)-parabolaFadeOut =- let dur = fromIntegral ^<< rangeFromInt (signalLength,2*signalLength)- in checkSimilarity 1e-3 limitFloat- (SigP.parabolaFadeOutInf dur)- (SigPS.unpack (SigPS.parabolaFadeOutInf dur ::- SigP.T Int (Value (Vector D4 Float))))--parabolaFadeInMap :: IO (ChunkSize -> Int -> Bool)-parabolaFadeInMap =- let dur = fromIntegral ^<< rangeFromInt (signalLength,2*signalLength)- in checkSimilarity 1e-3 limitFloat- (SigP.parabolaFadeIn dur)- (SigP.parabolaFadeInMap dur)--parabolaFadeOutMap :: IO (ChunkSize -> Int -> Bool)-parabolaFadeOutMap =- let dur = fromIntegral ^<< rangeFromInt (signalLength,2*signalLength)- in checkSimilarity 1e-3 limitFloat- (SigP.parabolaFadeOut dur)- (SigP.parabolaFadeOutMap dur)--exponential2 :: IO (ChunkSize -> (Int,Int) -> Bool)-exponential2 =- let halfLife = rangeFromInt (1000,10000) <<^ fst- start = rangeFromInt ( -1, 1) <<^ snd- in checkSimilarity 1e-3 limitFloat- (SigP.exponential2 halfLife start)- (SigPS.unpack (SigPS.exponential2 halfLife start ::- SigP.T (Int,Int) (Value (Vector D4 Float))))--exponential2Static :: IO (ChunkSize -> (Int,Int) -> Bool)-exponential2Static =- let halfLife = rangeFromInt (1000,10000) <<^ fst- start = rangeFromInt ( -1, 1) <<^ snd- in checkSimilarity 1e-3 limitFloat- (SigP.exponential2 halfLife start)- (Exp.causalP start <<<- CausalP.mapSimple Exp.parameter $*- SigP.constant halfLife)--exponential2PackedStatic :: IO (ChunkSize -> (Int,Int) -> Bool)-exponential2PackedStatic =- let halfLife = rangeFromInt (1000,10000) <<^ fst- start = rangeFromInt ( -1, 1) <<^ snd- in checkSimilarity 1e-3 (limitFloat . SigStL.unpack)- (SigPS.exponential2 halfLife start ::- SigP.T (Int,Int) (Value (Vector D4 Float)))- (Exp.causalPackedP start <<<- CausalP.mapSimple Exp.parameterPacked $*- SigP.constant halfLife)--exponential2Controlled :: IO (ChunkSize -> ((Int,Int), (Int,Int)) -> Bool)-exponential2Controlled =- let halfLife = rangeFromInt (1000,10000) <<^ (fst.fst)- start = rangeFromInt ( -1, 1) <<^ (snd.fst)- -- this is the LFO frequency measured at vector-rate- freq = rangeFromInt (0.0001, 0.001) <<^ (fst.snd)- phase = rangeFromInt (0, 0.99) <<^ (snd.snd)- lfo =- CausalP.mapExponential 2 halfLife $*- SigP.osciSimple Wave.approxSine2 phase freq- in checkSimilarity 1e-3 limitFloat- (Exp.causalP start <<<- CausalP.mapSimple Exp.parameter $*- SigP.interpolateConstant- (fromIntegral (TypeNum.toInt TypeNum.d4) :: Param.T p Float)- lfo)- (SigPS.unpack- (Exp.causalPackedP start <<<- CausalP.mapSimple Exp.parameterPacked $*- lfo ::- SigP.T ((Int,Int),(Int,Int)) (Value (Vector D4 Float))))--osci :: IO (ChunkSize -> (Int,Int) -> Bool)-osci =- let freq = rangeFromInt (0.001, 0.01) <<^ fst- phase = rangeFromInt (0, 0.99) <<^ snd- in checkSimilarity 1e-2 limitFloat- (SigP.osciSimple Wave.approxSine2 phase freq)- (SigPS.unpack (SigPS.osciSimple Wave.approxSine2 phase freq ::- SigP.T (Int,Int) (Value (Vector D4 Float))))----limitWord32 :: SVL.Vector Word32 -> SVL.Vector Word32-limitWord32 = SVL.take signalLength--limitPackedWord32 ::- SVL.Vector (Vector D4 Word32) -> SVL.Vector (Vector D4 Word32)-limitPackedWord32 = SVL.take (div signalLength 4)---noise :: IO (ChunkSize -> () -> Bool)-noise =- checkEquality limitWord32- (SigP.noiseCore $# 0)- (SigP.noiseCoreAlt $# 0)--noiseVector :: IO (ChunkSize -> () -> Bool)-noiseVector =- checkEquality limitPackedWord32- (SigPS.noiseCore $# 0)- (SigPS.noiseCoreAlt $# 0)--noiseScalarVector :: IO (ChunkSize -> () -> Bool)-noiseScalarVector =- checkEquality limitPackedWord32- (SigPS.noiseCore $# 0)- (SigPS.packSmall (SigP.noiseCore $# 0))---tests :: [(String, IO ())]-tests =- ("constant", quickCheck =<< constant) :- ("ramp", quickCheck =<< ramp) :- ("parabolaFadeIn", quickCheck =<< parabolaFadeIn) :- ("parabolaFadeOut", quickCheck =<< parabolaFadeOut) :- ("parabolaFadeInMap", quickCheck =<< parabolaFadeInMap) :- ("parabolaFadeOutMap", quickCheck =<< parabolaFadeOutMap) :- ("exponential2", quickCheck =<< exponential2) :- ("exponential2Static", quickCheck =<< exponential2Static) :- ("exponential2PackedStatic", quickCheck =<< exponential2PackedStatic) :- ("exponential2Controlled", quickCheck =<< exponential2Controlled) :- ("osci", quickCheck =<< osci) :- ("noise", quickCheck =<< noise) :- ("noiseVector", quickCheck =<< noiseVector) :- ("noiseScalarVector", quickCheck =<< noiseScalarVector) :- []
− src/Test/Synthesizer/LLVM/Utility.hs
@@ -1,101 +0,0 @@-{-# LANGUAGE NoImplicitPrelude #-}-module Test.Synthesizer.LLVM.Utility where--import qualified Synthesizer.LLVM.Parameter as Param-import qualified LLVM.Extra.Memory as Memory-import qualified LLVM.Extra.Class as Class--import qualified Synthesizer.LLVM.Parameterized.Signal as SigP--import qualified Synthesizer.State.Signal as SigS--import Control.Arrow (arr, )-import Control.Monad (liftM, liftM2, )--import qualified Data.StorableVector.Lazy as SVL-import Data.StorableVector.Lazy (ChunkSize, )-import Foreign.Storable (Storable, )--import qualified Algebra.RealRing as RealRing--import System.Random (Random, randomR, mkStdGen, )--import NumericPrelude.Numeric-import NumericPrelude.Base---rangeFromInt :: Random a => (a,a) -> Param.T Int a-rangeFromInt rng =- arr $ fst . randomR rng . mkStdGen---{-# INLINE checkSimilarityState #-}-checkSimilarityState ::- (RealRing.C a, Storable a,- Class.MakeValueTuple a av,- Memory.C av ap) =>- a ->- (SVL.Vector a -> SVL.Vector a) ->- SigP.T p av ->- (p -> SigS.T a) ->- IO (ChunkSize -> p -> Bool)-checkSimilarityState tol limit gen0 sig1 =- let render sig =- fmap- (\func chunkSize ->- limit . func chunkSize) $- SigP.runChunky sig- in liftM- (\sig0 chunkSize p ->- SigS.foldR (&&) True $- -- dangerous, since shortened signals would be tolerated- SigS.zipWith (\x y -> abs(x-y) < tol)- (SigS.fromStorableSignal (sig0 chunkSize p))- (sig1 p))- (render gen0)---{-# INLINE checkSimilarity #-}-checkSimilarity ::- (RealRing.C b, Storable b,- Storable a,- Class.MakeValueTuple a av, Memory.C av ap) =>- b ->- (SVL.Vector a -> SVL.Vector b) ->- SigP.T p av -> SigP.T p av ->- IO (ChunkSize -> p -> Bool)-checkSimilarity tol limit gen0 gen1 =- let render sig =- fmap- (\func chunkSize ->- limit . func chunkSize) $- SigP.runChunky sig- in liftM2- (\sig0 sig1 chunkSize p ->- SigS.foldR (&&) True $- -- dangerous, since shortened signals would be tolerated- SigS.zipWith (\x y -> abs(x-y) < tol)- (SigS.fromStorableSignal (sig0 chunkSize p))- (SigS.fromStorableSignal (sig1 chunkSize p)))- (render gen0)- (render gen1)---checkEquality ::- (Eq a, Storable a,- Class.MakeValueTuple a av,- Memory.C av ap) =>- (SVL.Vector a -> SVL.Vector a) ->- SigP.T p av -> SigP.T p av ->- IO (ChunkSize -> p -> Bool)-checkEquality limit gen0 gen1 =- let render sig =- fmap- (\func chunkSize ->- limit . func chunkSize) $- SigP.runChunky sig- in liftM2- (\sig0 sig1 chunkSize p ->- sig0 chunkSize p == sig1 chunkSize p)- (render gen0)- (render gen1)
synthesizer-llvm.cabal view
@@ -1,5 +1,5 @@ Name: synthesizer-llvm-Version: 0.3+Version: 0.5 License: GPL License-File: LICENSE Author: Henning Thielemann <haskell@henning-thielemann.de>@@ -12,14 +12,33 @@ Efficient signal processing using runtime compilation and vector instructions. It uses LLVM library, thus it is not bound to a specific CPU.- If you compile with Cabal flag @buildExamples@- you get the executable @synthi-llvm-server@,- that is a realtime software synthesizer- that receives MIDI events via ALSA- and in response plays some tones via ALSA.+ There are some example executables that you can build+ with Cabal flag @buildExamples@:+ .+ * @synthi-llvm-render@:+ Render a MIDI file into an audio file+ using some arbitrary instruments.+ .+ * @synthi-llvm-alsa@:+ A realtime software synthesizer+ that receives MIDI events via ALSA+ and in response plays tones via ALSA.+ If you have no ALSA (or Linux at all),+ then you can disable this example with @-f-alsa@.+ .+ * @synthi-llvm-jack@:+ The same realtime software synthesizer using JACK.+ If you have no JACK,+ then you can disable this example with @-f-jack@.+ .+ * @synthi-llvm-example@:+ Not very useful as an executable.+ You should better load the according module into GHCi+ and play around with it. Stability: Experimental-Tested-With: GHC==6.10.4, GHC==6.12.3, GHC==7.0.4, GHC==7.2.1-Cabal-Version: >=1.6+Tested-With: GHC==6.10.4, GHC==6.12.3+Tested-With: GHC==7.0.4, GHC==7.2.1, GHC==7.4.1, GHC==7.6.3+Cabal-Version: >=1.14 Build-Type: Simple Flag buildExamples@@ -30,8 +49,16 @@ description: Build test suite default: False +Flag alsa+ description: Build ALSA synthesizer if examples are built+ default: True++Flag jack+ description: Build JACK synthesizer if examples are built+ default: True+ Source-Repository this- Tag: 0.3+ Tag: 0.5 Type: darcs Location: code.haskell.org:/srv/code/synthesizer/llvm/ @@ -42,46 +69,41 @@ Library Build-Depends:- llvm-extra >= 0.3 && <0.4,+ llvm-extra >=0.4.1 && <0.5, -- llvm must be imported with restrictive version bounds, -- because we import implicitly and unqualified- llvm >=0.10 && <0.10.1,- type-level >=0.2.3 && <0.3,- functional-arrow >=0.0 && <0.1,- vault >=0.1 && <0.2,- HList >=0.2 && <0.3,- synthesizer-core >=0.5 && <0.6,- -- for ALSA.BendModulation- synthesizer-alsa >=0.4 && <0.5,- alsa-seq >=0.5 && <0.6,- alsa-pcm >=0.5 && <0.6,- midi-alsa >= 0.1.2 && <0.2,- midi >= 0.1.6 && <0.2,+ llvm-tf >=3.0 && <3.0.1,+ tfp >=0.7 && <0.8,+ vault >=0.1 && <0.3,+ synthesizer-core >=0.6 && <0.7,+ synthesizer-midi >=0.6 && <0.7,+ midi >=0.2.1 && <0.3, storable-record >=0.0.2 && <0.1, storable-tuple >=0.0.2 && <0.1, sox >=0.2 && <0.3, sample-frame-np >=0.0.1 && <0.1, sample-frame >=0.0.1 && <0.1, storablevector >=0.2.6 && <0.3,- numeric-prelude >=0.3 && <0.4,+ unsafe >=0.0 && <0.1,+ numeric-prelude >=0.3 && <0.5, non-negative >=0.1 && <0.2, event-list >=0.1 && <0.2,- -- data-accessor >=0.1 && <0.2,- filepath >=1.1 && <1.3,- random >= 1.0 && < 1.1,- containers >=0.1 && <0.5,- transformers >=0.2 && <0.3,- utility-ht >=0.0.1 && <0.1+ filepath >=1.1 && <1.4,+ random >=1.0 && <1.1,+ containers >=0.1 && <0.6,+ transformers >=0.2 && <0.4,+ utility-ht >=0.0.8 && <0.1 Build-Depends: -- base-4 needed for Control.Category- base >= 4 && <5+ base >=4 && <5 + Default-Language: Haskell98 GHC-Options: -Wall If impl(ghc>=7.0) GHC-Options: -fwarn-unused-do-bind -fcontext-stack=1000 CPP-Options: -DNoImplicitPrelude=RebindableSyntax- Extensions: CPP+ Default-Extensions: CPP Hs-source-dirs: src Exposed-Modules:@@ -96,10 +118,12 @@ Synthesizer.LLVM.Storable.Process Synthesizer.LLVM.Causal.Process Synthesizer.LLVM.CausalParameterized.Process+ Synthesizer.LLVM.CausalParameterized.ProcessValue Synthesizer.LLVM.CausalParameterized.ProcessPacked Synthesizer.LLVM.CausalParameterized.Controlled Synthesizer.LLVM.CausalParameterized.ControlledPacked Synthesizer.LLVM.CausalParameterized.Functional+ Synthesizer.LLVM.CausalParameterized.FunctionalPlug Synthesizer.LLVM.Plug.Input Synthesizer.LLVM.Plug.Output Synthesizer.LLVM.Filter.Allpass@@ -116,24 +140,23 @@ Synthesizer.LLVM.Generator.Exponential2 Synthesizer.LLVM.RingBuffer Synthesizer.LLVM.ConstantPiece- Synthesizer.LLVM.SerialVector+ Synthesizer.LLVM.Frame.SerialVector Synthesizer.LLVM.Frame Synthesizer.LLVM.Frame.Stereo Synthesizer.LLVM.Frame.StereoInterleaved Synthesizer.LLVM.Complex Synthesizer.LLVM.Wave- Synthesizer.LLVM.Server.Common- Synthesizer.LLVM.Server.Packed.Test- Synthesizer.LLVM.Server.Packed.Run+ Synthesizer.LLVM.MIDI+ Synthesizer.LLVM.MIDI.BendModulation Synthesizer.LLVM.Server.Packed.Instrument- Synthesizer.LLVM.Server.Scalar.Test- Synthesizer.LLVM.Server.Scalar.Run Synthesizer.LLVM.Server.Scalar.Instrument Synthesizer.LLVM.Server.CausalPacked.Instrument- Synthesizer.LLVM.Server.CausalPacked.Run- Synthesizer.LLVM.Server.CausalPacked.Test- Synthesizer.LLVM.ALSA.MIDI- Synthesizer.LLVM.ALSA.BendModulation+ Synthesizer.LLVM.Server.CausalPacked.InstrumentPlug+ Synthesizer.LLVM.Server.CausalPacked.Speech+ Synthesizer.LLVM.Server.CausalPacked.Arrange+ Synthesizer.LLVM.Server.SampledSound+ Synthesizer.LLVM.Server.Common+ Synthesizer.LLVM.Server.CommonPacked Other-Modules: Synthesizer.LLVM.Random@@ -145,28 +168,86 @@ Synthesizer.LLVM.Debug.Counter Synthesizer.LLVM.Debug.StablePtr Synthesizer.LLVM.Debug.Storable- Synthesizer.LLVM.Server.Option -- may be moved to llvm-extra Synthesizer.LLVM.Execution -- shall be removed when Foreign.Marshal.Alloc is fixed Synthesizer.LLVM.Alloc- Synthesizer.LLVM.LAC2011- Synthesizer.LLVM.LNdW2011 Executable synthi-llvm-example- If !flag(buildExamples)+ If flag(buildExamples) && flag(alsa)+ Build-Depends:+ synthesizer-llvm,++ llvm-extra >=0.4.1 && <0.5,+ llvm-tf,+ tfp >=0.7 && <0.8,+ synthesizer-core >=0.6 && <0.7,+ synthesizer-midi >=0.6 && <0.7,+ midi >=0.2.1 && <0.3,+ storable-record >=0.0.2 && <0.1,+ storable-tuple >=0.0.2 && <0.1,+ sox >=0.2 && <0.3,+ sample-frame-np >=0.0.1 && <0.1,+ sample-frame >=0.0.1 && <0.1,+ storablevector >=0.2.6 && <0.3,+ numeric-prelude >=0.3 && <0.5,+ non-negative >=0.1 && <0.2,+ event-list >=0.1 && <0.2,+ random >=1.0 && <1.1,+ containers >=0.1 && <0.6,+ transformers >=0.2 && <0.4,+ utility-ht >=0.0.8 && <0.1,++ synthesizer-alsa >=0.5 && <0.6,+ alsa-pcm >=0.6 && <0.7,+ base >=4 && <5+ Else Buildable: False- GHC-Options: -Wall+ Default-Language: Haskell98+ GHC-Options: -Wall+ GHC-Prof-Options: -auto-all If impl(ghc>=7.0) GHC-Options: -fwarn-unused-do-bind -fcontext-stack=1000 CPP-Options: -DNoImplicitPrelude=RebindableSyntax- Extensions: CPP- Hs-Source-Dirs: src+ Default-Extensions: CPP+ Hs-Source-Dirs: example Main-Is: Synthesizer/LLVM/Test.hs+ Other-Modules:+ Synthesizer.LLVM.LAC2011+ Synthesizer.LLVM.LNdW2011 -Executable synthi-llvm-server- If !flag(buildExamples)+Executable synthi-llvm-alsa+ If flag(buildExamples) && flag(alsa)+ Build-Depends:+ synthesizer-llvm,++ llvm-extra >=0.4.1 && <0.5,+ llvm-tf,+ tfp >=0.7 && <0.8,+ synthesizer-core >=0.6 && <0.7,+ synthesizer-midi >=0.6 && <0.7,+ midi >=0.2.1 && <0.3,+ storable-record >=0.0.2 && <0.1,+ storable-tuple >=0.0.2 && <0.1,+ sample-frame-np >=0.0.1 && <0.1,+ sample-frame >=0.0.1 && <0.1,+ storablevector >=0.2.6 && <0.3,+ numeric-prelude >=0.3 && <0.5,+ non-negative >=0.1 && <0.2,+ event-list >=0.1 && <0.2,+ filepath >=1.1 && <1.4,+ containers >=0.1 && <0.6,+ transformers >=0.2 && <0.4,+ utility-ht >=0.0.8 && <0.1,++ synthesizer-alsa >=0.5 && <0.6,+ midi-alsa >=0.2.1 && <0.3,+ alsa-seq >=0.6 && <0.7,+ alsa-pcm >=0.6 && <0.7,+ base >=4 && <5+ Else Buildable: False+ Default-Language: Haskell98 -- -threaded -debug GHC-Options: -Wall GHC-Options: -rtsopts@@ -174,29 +255,129 @@ If impl(ghc>=7.0) GHC-Options: -fwarn-unused-do-bind -fcontext-stack=1000 CPP-Options: -DNoImplicitPrelude=RebindableSyntax- Extensions: CPP- Hs-Source-Dirs: src+ Default-Extensions: CPP+ Hs-Source-Dirs: alsa Main-Is: Synthesizer/LLVM/Server.hs Other-Modules:- Synthesizer.LLVM.Server.Packed.Instrument Synthesizer.LLVM.Server.Packed.Test Synthesizer.LLVM.Server.Packed.Run- Synthesizer.LLVM.Server.Scalar.Instrument Synthesizer.LLVM.Server.Scalar.Test Synthesizer.LLVM.Server.Scalar.Run- Synthesizer.LLVM.Server.Common+ Synthesizer.LLVM.Server.CausalPacked.Run+ Synthesizer.LLVM.Server.CausalPacked.Test+ Synthesizer.LLVM.Server.ALSA+ Synthesizer.LLVM.Server.Option +Executable synthi-llvm-jack+ If flag(buildExamples) && flag(jack)+ Build-Depends:+ synthesizer-llvm,++ jack >=0.7 && <0.8,++ llvm-extra >=0.4.1 && <0.5,+ llvm-tf,+ tfp >=0.7 && <0.8,+ synthesizer-core >=0.6 && <0.7,+ synthesizer-midi >=0.6 && <0.7,+ midi >=0.2.1 && <0.3,+ storable-record >=0.0.2 && <0.1,+ storable-tuple >=0.0.2 && <0.1,+ sample-frame-np >=0.0.1 && <0.1,+ sample-frame >=0.0.1 && <0.1,+ storablevector >=0.2.6 && <0.3,+ numeric-prelude >=0.3 && <0.5,+ non-negative >=0.1 && <0.2,+ explicit-exception >=0.1.7 && <0.2,+ event-list >=0.1 && <0.2,+ filepath >=1.1 && <1.4,+ containers >=0.1 && <0.6,+ transformers >=0.2 && <0.4,+ utility-ht >=0.0.8 && <0.1,++ base >=4 && <5++ Else+ Buildable: False+ Default-Language: Haskell98+ -- -threaded -debug+ GHC-Options: -Wall+ GHC-Options: -rtsopts+ GHC-Prof-Options: -auto-all+ If impl(ghc>=7.0)+ GHC-Options: -fwarn-unused-do-bind+ CPP-Options: -DNoImplicitPrelude=RebindableSyntax+ Default-Extensions: CPP+ Hs-Source-Dirs: jack+ Main-Is: Synthesizer/LLVM/Server/JACK.hs++Executable synthi-llvm-render+ If flag(buildExamples)+ Build-Depends:+ synthesizer-llvm,++ llvm-extra >=0.4.1 && <0.5,+ llvm-tf,+ tfp >=0.7 && <0.8,+ sox >=0.2.1 && <0.3,+ synthesizer-core >=0.6 && <0.7,+ synthesizer-midi >=0.6 && <0.7,+ midi >=0.2.1 && <0.3,+ storable-record >=0.0.2 && <0.1,+ storable-tuple >=0.0.2 && <0.1,+ sample-frame-np >=0.0.1 && <0.1,+ sample-frame >=0.0.1 && <0.1,+ storablevector >=0.2.6 && <0.3,+ numeric-prelude >=0.3 && <0.5,+ non-negative >=0.1 && <0.2,+ explicit-exception >=0.1.7 && <0.2,+ event-list >=0.1 && <0.2,+ filepath >=1.1 && <1.4,+ containers >=0.1 && <0.6,+ transformers >=0.2 && <0.4,+ utility-ht >=0.0.8 && <0.1,++ base >=4 && <5++ Else+ Buildable: False+ Default-Language: Haskell98+ -- -threaded -debug+ GHC-Options: -Wall+ GHC-Options: -rtsopts+ GHC-Prof-Options: -auto-all+ If impl(ghc>=7.0)+ GHC-Options: -fwarn-unused-do-bind+ CPP-Options: -DNoImplicitPrelude=RebindableSyntax+ Default-Extensions: CPP+ Hs-Source-Dirs: render+ Main-Is: Synthesizer/LLVM/Server/Render.hs+ Executable synthi-llvm-test If flag(buildTests)- Build-Depends: QuickCheck >= 1 && <3+ Build-Depends:+ synthesizer-llvm,++ llvm-extra >=0.4.1 && <0.5,+ llvm-tf,+ tfp >=0.7 && <0.8,+ synthesizer-core >=0.6 && <0.7,+ storablevector >=0.2.6 && <0.3,+ numeric-prelude >=0.3 && <0.5,+ random >=1.0 && <1.1,+ utility-ht >=0.0.8 && <0.1,++ QuickCheck >=1 && <3,+ base >=4 && <5 Else Buildable: False+ Default-Language: Haskell98 GHC-Options: -Wall If impl(ghc>=7.0) GHC-Options: -fwarn-unused-do-bind -fcontext-stack=1000 CPP-Options: -DNoImplicitPrelude=RebindableSyntax- Extensions: CPP- Hs-Source-Dirs: src+ Default-Extensions: CPP+ Hs-Source-Dirs: testsuite Main-Is: Test/Main.hs Other-Modules: Test.Synthesizer.LLVM.Filter
+ testsuite/Test/Main.hs view
@@ -0,0 +1,22 @@+module Main where++import qualified Test.Synthesizer.LLVM.Filter as Filter+import qualified Test.Synthesizer.LLVM.Packed as Packed++import qualified LLVM.Core as LLVM++import Data.Tuple.HT (mapFst, )+++prefix :: String -> [(String, IO ())] -> [(String, IO ())]+prefix msg =+ map (mapFst (\str -> msg ++ "." ++ str))++main :: IO ()+main = do+ LLVM.initializeNativeTarget+ mapM_ (\(name,test) -> putStr (name ++ ": ") >> test) $+ concat $+ prefix "Filter" Filter.tests :+ prefix "Packed" Packed.tests :+ []
+ testsuite/Test/Synthesizer/LLVM/Filter.hs view
@@ -0,0 +1,505 @@+{-# LANGUAGE NoImplicitPrelude #-}+{-# LANGUAGE Rank2Types #-}+module Test.Synthesizer.LLVM.Filter (tests) where++import qualified Synthesizer.LLVM.Filter.Allpass as Allpass+import qualified Synthesizer.LLVM.Filter.FirstOrder as FirstOrder+import qualified Synthesizer.LLVM.Filter.SecondOrder as SecondOrder+import qualified Synthesizer.LLVM.Filter.SecondOrderPacked as SecondOrderP+import qualified Synthesizer.LLVM.Filter.Universal as UniFilter+import qualified Synthesizer.LLVM.Filter.Moog as Moog+import qualified Synthesizer.LLVM.Filter.ComplexFirstOrder as ComplexFilter+import qualified Synthesizer.LLVM.Filter.ComplexFirstOrderPacked as ComplexFilterP++import qualified Synthesizer.Plain.Filter.Recursive.Allpass as AllpassCore+import qualified Synthesizer.Plain.Filter.Recursive.FirstOrder as FirstOrderCore+import qualified Synthesizer.Plain.Filter.Recursive.Universal as UniFilterCore+import qualified Synthesizer.Plain.Filter.Recursive.Moog as MoogCore+import qualified Synthesizer.Plain.Filter.Recursive.FirstOrderComplex as ComplexFilterCore++import qualified Synthesizer.LLVM.Frame.SerialVector as Serial+import qualified Synthesizer.LLVM.Parameter as Param+import qualified Synthesizer.LLVM.Wave as Wave+import qualified Synthesizer.LLVM.CausalParameterized.Process as CausalP+import qualified Synthesizer.LLVM.Parameterized.SignalPacked as SigPS+import qualified Synthesizer.LLVM.Parameterized.Signal as SigP+import Synthesizer.LLVM.CausalParameterized.Process (($<), ($*), )+import Synthesizer.LLVM.Parameterized.Signal (($#), )++import Synthesizer.Plain.Filter.Recursive (Pole(Pole))+-- import qualified Synthesizer.Storable.Signal as SigSt+import qualified Synthesizer.Interpolation.Module as Ip+import qualified Synthesizer.Causal.Interpolation as InterpC+import qualified Synthesizer.Causal.Filter.NonRecursive as FiltC+import qualified Synthesizer.Causal.Displacement as DispC+import qualified Synthesizer.Causal.Process as CausalS+import qualified Synthesizer.Basic.Wave as WaveCore+import qualified Synthesizer.State.Displacement as DispS+import qualified Synthesizer.State.Oscillator as OsciS+import qualified Synthesizer.State.Signal as SigS+import qualified Synthesizer.Basic.Phase as Phase++import qualified Data.StorableVector.Lazy as SVL+import Data.StorableVector.Lazy (ChunkSize, )++import Test.Synthesizer.LLVM.Utility+ (checkSimilarity, checkSimilarityState, rangeFromInt,+ CheckSimilarity, CheckSimilarityState, )++import qualified Control.Category as Cat+import Control.Category ((<<<), )+import Control.Arrow ((&&&), (^<<), (<<^), )++import qualified LLVM.Extra.Memory as Memory++import LLVM.Core (Value, )+import qualified LLVM.Core as LLVM+import qualified Types.Data.Num as TypeNum+import Types.Data.Num (D4, )++import qualified Number.Complex as Complex+import qualified Synthesizer.LLVM.Frame.Stereo as Stereo++import Test.QuickCheck (quickCheck, )++import NumericPrelude.Numeric+import NumericPrelude.Base+++type SimFloat = CheckSimilarity Float+type SimStateFloat = CheckSimilarityState Float+type VectorValue = Serial.Value D4 Float++signalLength :: Int+signalLength = 10000+++limitFloat :: SVL.Vector Float -> SVL.Vector Float+limitFloat = SVL.take signalLength++{-+limitStereoFloat :: SVL.Vector (Stereo.T Float) -> SVL.Vector (Stereo.T Float)+limitStereoFloat = SVL.take signalLength+-}+++lfoSine ::+ (Memory.C a) =>+ (forall r. Value Float -> LLVM.CodeGenFunction r a) ->+ Param.T p Float ->+ SigP.T p a+lfoSine f reduct =+ SigP.interpolateConstant reduct $+ SigP.mapSimple f $+ CausalP.apply (CausalP.mapExponential 2 0.01) $+ SigP.osciSimple Wave.sine 0 (fmap (* (0.1/44100)) reduct)++allpassControl ::+ (TypeNum.NaturalT n) =>+ n ->+ Param.T p Float ->+ SigP.T p (Allpass.CascadeParameter n (Value Float))+allpassControl order =+ lfoSine (Allpass.flangerParameter order)++allpassPhaserCausal, allpassPhaserPipeline ::+ Param.T p Float ->+ SigP.T p (Value Float) ->+ SigP.T p (Value Float)+allpassPhaserCausal reduct =+ CausalP.apply+ (Allpass.phaserP+ $< allpassControl TypeNum.d16 reduct)++allpassPhaserPipeline reduct xs =+ let order = TypeNum.d16+ in (SigP.drop $# TypeNum.fromIntegerT order) $+ (Allpass.phaserPipelineP+ $< allpassControl order reduct+ $* xs)++allpassPipeline :: IO (ChunkSize -> ((Int,Int), Int) -> SimFloat)+allpassPipeline =+ let freq = rangeFromInt (0.001, 0.01) <<^ fst . fst+ phase = rangeFromInt (0, 0.99 :: Float) <<^ snd . fst+ reduct = rangeFromInt (10, 100) <<^ snd+ tone = SigP.osciSimple Wave.triangle phase freq+ in checkSimilarity 1e-2 limitFloat+ (allpassPhaserCausal reduct tone)+ (allpassPhaserPipeline reduct tone)++++{- |+Shrink control signal in time+since we can only handle one control parameter per vector chunk.+-}+applyPacked ::+ (Memory.C c) =>+ CausalP.T p (c, VectorValue) VectorValue ->+ SigP.T p c ->+ SigP.T p VectorValue ->+ SigP.T p VectorValue+applyPacked proc cs xs =+ proc+ $< ((SigP.interpolateConstant $#+ (recip $ TypeNum.fromIntegerT TypeNum.d4 :: Float)) cs)+ $* xs+++allpassPhaserPacked ::+ Param.T p Float ->+ SigP.T p VectorValue ->+ SigP.T p VectorValue+allpassPhaserPacked reduct =+ applyPacked Allpass.phaserPackedP+ (allpassControl TypeNum.d16 reduct)++allpassPacked :: IO (ChunkSize -> ((Int,Int), Int) -> SimFloat)+allpassPacked =+ let freq = rangeFromInt (0.001, 0.01) <<^ fst . fst+ phase = rangeFromInt (0, 0.99) <<^ snd . fst+ reduct = (4*) ^<< rangeFromInt (1, 25) <<^ snd+ tone = SigP.osciSimple Wave.triangle phase freq+ toneP = SigPS.osciSimple Wave.triangle phase freq+ in checkSimilarity 1e-2 limitFloat+ (allpassPhaserCausal reduct tone)+ (SigPS.unpack $ allpassPhaserPacked reduct toneP)+++interpolateConstant :: Float -> SigS.T a -> SigS.T a+interpolateConstant reduct xs =+ CausalS.apply (InterpC.relative Ip.constant 0 xs) $+ SigS.repeat $ recip reduct+++{-# INLINE lfoSineCore #-}+lfoSineCore ::+ (Float -> a) ->+ Float ->+ SigS.T a+lfoSineCore f reduct =+ interpolateConstant reduct $+ SigS.map f $+ DispS.mapExponential 2 0.01 $+ OsciS.static WaveCore.sine zero (reduct * 0.1/44100)++{-# INLINE allpassPhaserCore #-}+allpassPhaserCore ::+ Float ->+ SigS.T Float ->+ SigS.T Float+allpassPhaserCore reduct =+ let order = 16+ in CausalS.apply $+ FiltC.amplify 0.5 <<<+ DispC.mix <<<+ ((CausalS.applyFst (AllpassCore.cascadeCausal order) $+ lfoSineCore (AllpassCore.flangerParameter order) reduct)+ &&&+ Cat.id)++allpassCore :: IO (ChunkSize -> ((Int,Int), Int) -> SimStateFloat)+allpassCore =+ let freq = rangeFromInt (0.001, 0.01) <<^ fst . fst+ phase = rangeFromInt (0, 0.99) <<^ snd . fst+ reduct = rangeFromInt (10, 100) <<^ snd+ tone = SigP.osciSimple Wave.triangle phase freq+ toneS p =+ OsciS.static WaveCore.triangle+ (Phase.fromRepresentative (Param.get phase p)) (Param.get freq p)+ in checkSimilarityState 1e-2 limitFloat+ (allpassPhaserCausal reduct tone)+ (\p -> allpassPhaserCore (Param.get reduct p) (toneS p))++++diracImpulse :: SigP.T p (Value Float)+diracImpulse =+ (CausalP.delay1 $# (one::Float)) $*+ (SigP.constant $# (zero::Float))++firstOrderConstant ::+ Param.T p Float ->+ SigP.T p (Value Float) ->+ SigP.T p (Value Float)+firstOrderConstant cutOff xs =+ FirstOrder.lowpassCausalP+ $< SigP.constant (FirstOrderCore.parameter ^<< cutOff)+ $* xs++firstOrderExponential :: IO (ChunkSize -> (Int,Int) -> SimFloat)+firstOrderExponential =+ let cutOff = rangeFromInt (0.001, 0.01) <<^ fst+ gain = exp(-2*pi*cutOff)+ in checkSimilarity 1e-2 limitFloat+ (SigP.amplify (recip (1 - gain)) $+ firstOrderConstant cutOff diracImpulse)+ (SigP.exponentialCore gain $# (one :: Float))++firstOrderCausal ::+ Param.T p Float ->+ SigP.T p (Value Float) ->+ SigP.T p (Value Float)+firstOrderCausal reduct xs =+ FirstOrder.lowpassCausalP+ $< lfoSine FirstOrder.parameter reduct+ $* xs++{-# INLINE firstOrderCore #-}+firstOrderCore ::+ Float ->+ SigS.T Float ->+ SigS.T Float+firstOrderCore reduct =+ CausalS.apply $+ CausalS.applyFst FirstOrderCore.lowpassCausal $+ lfoSineCore FirstOrderCore.parameter reduct++firstOrder :: IO (ChunkSize -> ((Int,Int), Int) -> SimStateFloat)+firstOrder =+ let freq = rangeFromInt (0.001, 0.01) <<^ fst . fst+ phase = rangeFromInt (0, 0.99) <<^ snd . fst+ reduct = rangeFromInt (10, 100) <<^ snd+ tone = SigP.osciSimple Wave.triangle phase freq+ toneS p =+ OsciS.static WaveCore.triangle+ (Phase.fromRepresentative (Param.get phase p)) (Param.get freq p)+ in checkSimilarityState 1e-2 limitFloat+ (firstOrderCausal reduct tone)+ (\p -> firstOrderCore (Param.get reduct p) (toneS p))++firstOrderCausalPacked ::+ Param.T p Float ->+ SigP.T p VectorValue ->+ SigP.T p VectorValue+firstOrderCausalPacked reduct =+ applyPacked+ (FirstOrder.lowpassCausalPackedP)+ (lfoSine FirstOrder.parameter reduct)++firstOrderPacked :: IO (ChunkSize -> ((Int,Int), Int) -> SimFloat)+firstOrderPacked =+ let freq = rangeFromInt (0.001, 0.01) <<^ fst . fst+ phase = rangeFromInt (0, 0.99) <<^ snd . fst+ reduct = (4*) ^<< rangeFromInt (1, 25) <<^ snd+ tone = SigP.osciSimple Wave.triangle phase freq+ toneP = SigPS.osciSimple Wave.triangle phase freq+ in checkSimilarity 1e-2 limitFloat+ (firstOrderCausal reduct tone)+ (SigPS.unpack $ firstOrderCausalPacked reduct toneP)+++secondOrderCausal ::+ Param.T p Float ->+ SigP.T p (Value Float) ->+ SigP.T p (Value Float)+secondOrderCausal reduct xs =+ SecondOrder.causalP+ $< lfoSine (SecondOrder.bandpassParameter (LLVM.valueOf (10::Float))) reduct+ $* xs++secondOrderCausalPacked ::+ Param.T p Float ->+ SigP.T p VectorValue ->+ SigP.T p VectorValue+secondOrderCausalPacked reduct =+ applyPacked SecondOrder.causalPackedP+ (lfoSine (SecondOrder.bandpassParameter (LLVM.valueOf (10::Float))) reduct)++secondOrderPacked :: IO (ChunkSize -> ((Int,Int), Int) -> SimFloat)+secondOrderPacked =+ let freq = rangeFromInt (0.001, 0.01) <<^ fst . fst+ phase = rangeFromInt (0, 0.99) <<^ snd . fst+ reduct = (4*) ^<< rangeFromInt (1, 25) <<^ snd+ tone = SigP.osciSimple Wave.triangle phase freq+ toneP = SigPS.osciSimple Wave.triangle phase freq+ in checkSimilarity 1e-2 limitFloat+ (secondOrderCausal reduct tone)+ (SigPS.unpack $ secondOrderCausalPacked reduct toneP)++secondOrderCausalPacked2 ::+ Param.T p Float ->+ SigP.T p (Value Float) ->+ SigP.T p (Value Float)+secondOrderCausalPacked2 reduct xs =+ SecondOrderP.causalP+ $< lfoSine (SecondOrderP.bandpassParameter (LLVM.valueOf (10::Float))) reduct+ $* xs++secondOrderPacked2 :: IO (ChunkSize -> ((Int,Int), Int) -> SimFloat)+secondOrderPacked2 =+ let freq = rangeFromInt (0.001, 0.01) <<^ fst . fst+ phase = rangeFromInt (0, 0.99 :: Float) <<^ snd . fst+ reduct = rangeFromInt (10, 100) <<^ snd+ tone = SigP.osciSimple Wave.triangle phase freq+ in checkSimilarity 1e-2 limitFloat+ (secondOrderCausal reduct tone)+ (secondOrderCausalPacked2 reduct tone)+++{-+limitUniFilter ::+ SVL.Vector (UniFilterCore.Result Float) ->+ SVL.Vector (UniFilterCore.Result Float)+limitUniFilter = SVL.take signalLength+-}++universalCausal ::+ Param.T p Float ->+ SigP.T p (Value Float) ->+ SigP.T p (UniFilter.Result (Value Float))+universalCausal reduct xs =+ UniFilter.causalP+ $< lfoSine (UniFilter.parameter (LLVM.valueOf (10::Float))) reduct+ $* xs++{-# INLINE universalCore #-}+universalCore ::+ Float ->+ SigS.T Float ->+ SigS.T (UniFilterCore.Result Float)+universalCore reduct =+ CausalS.apply $+ CausalS.applyFst UniFilterCore.causal $+ lfoSineCore (UniFilterCore.parameter . Pole 10) reduct++universal :: IO (ChunkSize -> ((Int,Int), Int) -> SimStateFloat)+universal =+ let freq = rangeFromInt (0.001, 0.01) <<^ fst . fst+ phase = rangeFromInt (0, 0.99) <<^ snd . fst+ reduct = rangeFromInt (10, 100) <<^ snd+ tone = SigP.osciSimple Wave.triangle phase freq+ toneS p =+ OsciS.static WaveCore.triangle+ (Phase.fromRepresentative (Param.get phase p)) (Param.get freq p)+ in checkSimilarityState 1e-2 limitFloat+ (fmap UniFilter.lowpass $+ universalCausal reduct tone)+ (\p ->+ SigS.map UniFilterCore.lowpass $+ universalCore (Param.get reduct p) (toneS p))+{-+ checkSimilarityState 1e-2 limitUniFilter+ (universalCausal reduct tone)+ (\p -> universalCore (Param.get reduct p) (toneS p))+-}+++moogCausal ::+ (TypeNum.NaturalT n) =>+ n ->+ Param.T p Float ->+ SigP.T p (Value Float) ->+ SigP.T p (Value Float)+moogCausal order reduct xs =+ Moog.causalP+ $< lfoSine (Moog.parameter order (LLVM.valueOf (10::Float))) reduct+ $* xs++{-# INLINE moogCore #-}+moogCore ::+ Int ->+ Float ->+ SigS.T Float ->+ SigS.T Float+moogCore order reduct =+ CausalS.apply $+ CausalS.applyFst (MoogCore.lowpassCausal order) $+ lfoSineCore (MoogCore.parameter order . Pole 10) reduct++moog :: IO (ChunkSize -> ((Int,Int), Int) -> SimStateFloat)+moog =+ let freq = rangeFromInt (0.001, 0.01) <<^ fst . fst+ phase = rangeFromInt (0, 0.99) <<^ snd . fst+ reduct = rangeFromInt (10, 100) <<^ snd+ order = TypeNum.d6+ tone = SigP.osciSimple Wave.triangle phase freq+ toneS p =+ OsciS.static WaveCore.triangle+ (Phase.fromRepresentative (Param.get phase p)) (Param.get freq p)+ in checkSimilarityState 1e-2 limitFloat+ (moogCausal order reduct tone)+ (\p -> moogCore (TypeNum.fromIntegerT order) (Param.get reduct p) (toneS p))+++complexCausal ::+ Param.T p Float ->+ SigP.T p (Value Float) ->+ SigP.T p (Stereo.T (Value Float))+complexCausal reduct =+ CausalP.apply $+ (ComplexFilter.causalP+ $< lfoSine (ComplexFilter.parameter (LLVM.valueOf (10::Float))) reduct)+ <<^ (\x -> Stereo.cons x (LLVM.value LLVM.zero))++complexCausalPacked ::+ Param.T p Float ->+ SigP.T p (Value Float) ->+ SigP.T p (Stereo.T (Value Float))+complexCausalPacked reduct =+ CausalP.apply $+ (ComplexFilterP.causalP+ $< lfoSine (ComplexFilterP.parameter (LLVM.valueOf (10::Float))) reduct)+ <<^ (\x -> Stereo.cons x (LLVM.value LLVM.zero))++complexPacked :: IO (ChunkSize -> ((Int,Int), Int) -> SimFloat)+complexPacked =+ let freq = rangeFromInt (0.001, 0.01) <<^ fst . fst+ phase = rangeFromInt (0, 0.99 :: Float) <<^ snd . fst+ reduct = rangeFromInt (10, 100) <<^ snd+ tone = SigP.osciSimple Wave.triangle phase freq+ in checkSimilarity 1e-2 limitFloat+ (fmap Stereo.left $+ complexCausal reduct tone)+ (fmap Stereo.left $+ complexCausalPacked reduct tone)++{-# INLINE complexCore #-}+complexCore ::+ Float ->+ SigS.T Float ->+ SigS.T (Stereo.T Float)+complexCore reduct =+ CausalS.apply $+ (\x -> Stereo.cons (Complex.real x) (Complex.imag x)) ^<<+ CausalS.applyFst ComplexFilterCore.causal+ (lfoSineCore (ComplexFilterCore.parameter . Pole 10) reduct)++complex :: IO (ChunkSize -> ((Int,Int), Int) -> SimStateFloat)+complex =+ let freq = rangeFromInt (0.001, 0.01) <<^ fst . fst+ phase = rangeFromInt (0, 0.99) <<^ snd . fst+ reduct = rangeFromInt (10, 100) <<^ snd+ tone = SigP.osciSimple Wave.triangle phase freq+ toneS p =+ OsciS.static WaveCore.triangle+ (Phase.fromRepresentative (Param.get phase p)) (Param.get freq p)+ in checkSimilarityState 1e-2 limitFloat+ (fmap Stereo.left $+ complexCausal reduct tone)+ (\p ->+ SigS.map ((0.1*) . Stereo.left) $+ complexCore (Param.get reduct p) (toneS p))+{-+ in checkSimilarityState 1e-2 limitStereoFloat+ (complexCausal reduct tone)+ (\p -> complexCore (Param.get reduct p) (toneS p))+-}+++tests :: [(String, IO ())]+tests =+ ("secondOrderPacked", quickCheck =<< secondOrderPacked) :+ ("secondOrderPacked2", quickCheck =<< secondOrderPacked2) :+ ("firstOrderExponential", quickCheck =<< firstOrderExponential) :+ ("firstOrder", quickCheck =<< firstOrder) :+ ("firstOrderPacked", quickCheck =<< firstOrderPacked) :+ ("universal", quickCheck =<< universal) :+ ("allpassPacked", quickCheck =<< allpassPacked) :+ ("allpassPipeline", quickCheck =<< allpassPipeline) :+ ("allpassCore", quickCheck =<< allpassCore) :+ ("moog", quickCheck =<< moog) :+ ("complexPacked", quickCheck =<< complexPacked) :+ ("complex", quickCheck =<< complex) :+ []
+ testsuite/Test/Synthesizer/LLVM/Packed.hs view
@@ -0,0 +1,206 @@+{-# LANGUAGE NoImplicitPrelude #-}+module Test.Synthesizer.LLVM.Packed (tests) where++import Test.Synthesizer.LLVM.Utility+ (checkSimilarity, checkEquality, rangeFromInt,+ CheckSimilarity, CheckEquality, )++import qualified Synthesizer.LLVM.Wave as Wave+import qualified Synthesizer.LLVM.Parameter as Param++import Types.Data.Num (D4, )+import qualified Types.Data.Num as TypeNum++import qualified Synthesizer.LLVM.Frame.SerialVector as Serial+import qualified Synthesizer.LLVM.Generator.Exponential2 as Exp+import qualified Synthesizer.LLVM.Parameterized.SignalPacked as SigPS+import qualified Synthesizer.LLVM.Parameterized.Signal as SigP+import qualified Synthesizer.LLVM.CausalParameterized.Process as CausalP+import Synthesizer.LLVM.Parameterized.Signal (($#), )+import Synthesizer.LLVM.CausalParameterized.Process (($*), )++import qualified Synthesizer.LLVM.Storable.Signal as SigStL+import qualified Data.StorableVector.Lazy as SVL+import Data.StorableVector.Lazy (ChunkSize, )++import Control.Arrow ((^<<), (<<^), (<<<), )++import Data.Word (Word32, )++import Test.QuickCheck (quickCheck, )++import NumericPrelude.Numeric+import NumericPrelude.Base+++type SimFloat = CheckSimilarity Float+type VectorValue = Serial.Value D4 Float++signalLength :: Int+signalLength = 10000+++limitFloat :: SVL.Vector Float -> SVL.Vector Float+limitFloat = SVL.take signalLength+++durFromInt :: Param.T Int Float+durFromInt =+ fromIntegral ^<< rangeFromInt (signalLength,2*signalLength)++{-+limitPackedFloat ::+ SVL.Vector (Serial.Plain D4 Float) -> SVL.Vector (Serial.Plain D4 Float)+limitPackedFloat = SVL.take (div signalLength 4)+-}++constant :: IO (ChunkSize -> Int -> SimFloat)+constant =+ let y = rangeFromInt (-1, 1)+ in checkSimilarity 1e-3 limitFloat+ (SigP.constant y)+ (SigPS.unpack (SigPS.constant y :: SigP.T Int VectorValue))++ramp :: IO (ChunkSize -> Int -> SimFloat)+ramp =+ let dur = durFromInt+ in checkSimilarity 1e-3 limitFloat+ (SigP.rampInf dur)+ (SigPS.unpack (SigPS.rampInf dur :: SigP.T Int VectorValue))++parabolaFadeIn :: IO (ChunkSize -> Int -> SimFloat)+parabolaFadeIn =+ let dur = durFromInt+ in checkSimilarity 1e-3 limitFloat+ (SigP.parabolaFadeInInf dur)+ (SigPS.unpack (SigPS.parabolaFadeInInf dur ::+ SigP.T Int VectorValue))++parabolaFadeOut :: IO (ChunkSize -> Int -> SimFloat)+parabolaFadeOut =+ let dur = durFromInt+ in checkSimilarity 1e-3 limitFloat+ (SigP.parabolaFadeOutInf dur)+ (SigPS.unpack (SigPS.parabolaFadeOutInf dur ::+ SigP.T Int VectorValue))++parabolaFadeInMap :: IO (ChunkSize -> Int -> SimFloat)+parabolaFadeInMap =+ let dur = durFromInt+ in checkSimilarity 1e-3 limitFloat+ (SigP.parabolaFadeIn dur)+ (SigP.parabolaFadeInMap dur)++parabolaFadeOutMap :: IO (ChunkSize -> Int -> SimFloat)+parabolaFadeOutMap =+ let dur = durFromInt+ in checkSimilarity 1e-3 limitFloat+ (SigP.parabolaFadeOut dur)+ (SigP.parabolaFadeOutMap dur)++exponential2 :: IO (ChunkSize -> (Int,Int) -> SimFloat)+exponential2 =+ let halfLife = rangeFromInt (1000,10000) <<^ fst+ start = rangeFromInt ( -1, 1) <<^ snd+ in checkSimilarity 1e-3 limitFloat+ (SigP.exponential2 halfLife start)+ (SigPS.unpack (SigPS.exponential2 halfLife start ::+ SigP.T (Int,Int) VectorValue))++exponential2Static :: IO (ChunkSize -> (Int,Int) -> SimFloat)+exponential2Static =+ let halfLife = rangeFromInt (1000,10000) <<^ fst+ start = rangeFromInt ( -1, 1) <<^ snd+ in checkSimilarity 1e-3 limitFloat+ (SigP.exponential2 halfLife start)+ (Exp.causalP start <<<+ CausalP.mapSimple Exp.parameter $*+ SigP.constant halfLife)++exponential2PackedStatic :: IO (ChunkSize -> (Int,Int) -> SimFloat)+exponential2PackedStatic =+ let halfLife = rangeFromInt (1000,10000) <<^ fst+ start = rangeFromInt ( -1, 1) <<^ snd+ in checkSimilarity 1e-3 (limitFloat . SigStL.unpack)+ (SigPS.exponential2 halfLife start ::+ SigP.T (Int,Int) VectorValue)+ (Exp.causalPackedP start <<<+ CausalP.mapSimple Exp.parameterPacked $*+ SigP.constant halfLife)++exponential2Controlled :: IO (ChunkSize -> ((Int,Int), (Int,Int)) -> SimFloat)+exponential2Controlled =+ let halfLife = rangeFromInt (1000,10000) <<^ (fst.fst)+ start = rangeFromInt ( -1, 1) <<^ (snd.fst)+ -- this is the LFO frequency measured at vector-rate+ freq = rangeFromInt (0.0001, 0.001) <<^ (fst.snd)+ phase = rangeFromInt (0, 0.99 :: Float) <<^ (snd.snd)+ lfo =+ CausalP.mapExponential 2 halfLife $*+ SigP.osciSimple Wave.approxSine2 phase freq+ in checkSimilarity 1e-3 limitFloat+ (Exp.causalP start <<<+ CausalP.mapSimple Exp.parameter $*+ SigP.interpolateConstant+ (TypeNum.fromIntegerT TypeNum.d4 :: Param.T p Float)+ lfo)+ (SigPS.unpack+ (Exp.causalPackedP start <<<+ CausalP.mapSimple Exp.parameterPacked $*+ lfo :: SigP.T ((Int,Int),(Int,Int)) VectorValue))++osci :: IO (ChunkSize -> (Int,Int) -> SimFloat)+osci =+ let freq = rangeFromInt (0.001, 0.01) <<^ fst+ phase = rangeFromInt (0, 0.99) <<^ snd+ in checkSimilarity 1e-2 limitFloat+ (SigP.osciSimple Wave.approxSine2 phase freq)+ (SigPS.unpack (SigPS.osciSimple Wave.approxSine2 phase freq ::+ SigP.T (Int,Int) VectorValue))++++limitWord32 :: SVL.Vector Word32 -> SVL.Vector Word32+limitWord32 = SVL.take signalLength++limitPackedWord32 ::+ SVL.Vector (Serial.Plain D4 Word32) -> SVL.Vector (Serial.Plain D4 Word32)+limitPackedWord32 = SVL.take (div signalLength 4)+++noise :: IO (ChunkSize -> () -> CheckEquality Word32)+noise =+ checkEquality limitWord32+ (SigP.noiseCore $# 0)+ (SigP.noiseCoreAlt $# 0)++noiseVector :: IO (ChunkSize -> () -> CheckEquality (Serial.Plain D4 Word32))+noiseVector =+ checkEquality limitPackedWord32+ (SigPS.noiseCore $# 0)+ (SigPS.noiseCoreAlt $# 0)++noiseScalarVector :: IO (ChunkSize -> () -> CheckEquality (Serial.Plain D4 Word32))+noiseScalarVector =+ checkEquality limitPackedWord32+ (SigPS.noiseCore $# 0)+ (SigPS.packSmall (SigP.noiseCore $# 0))+++tests :: [(String, IO ())]+tests =+ ("constant", quickCheck =<< constant) :+ ("ramp", quickCheck =<< ramp) :+ ("parabolaFadeIn", quickCheck =<< parabolaFadeIn) :+ ("parabolaFadeOut", quickCheck =<< parabolaFadeOut) :+ ("parabolaFadeInMap", quickCheck =<< parabolaFadeInMap) :+ ("parabolaFadeOutMap", quickCheck =<< parabolaFadeOutMap) :+ ("exponential2", quickCheck =<< exponential2) :+ ("exponential2Static", quickCheck =<< exponential2Static) :+ ("exponential2PackedStatic", quickCheck =<< exponential2PackedStatic) :+ ("exponential2Controlled", quickCheck =<< exponential2Controlled) :+ ("osci", quickCheck =<< osci) :+ ("noise", quickCheck =<< noise) :+ ("noiseVector", quickCheck =<< noiseVector) :+ ("noiseScalarVector", quickCheck =<< noiseScalarVector) :+ []
+ testsuite/Test/Synthesizer/LLVM/Utility.hs view
@@ -0,0 +1,128 @@+{-# LANGUAGE NoImplicitPrelude #-}+{-# LANGUAGE TypeFamilies #-}+module Test.Synthesizer.LLVM.Utility where++import qualified Synthesizer.LLVM.Parameterized.Signal as SigP+import qualified Synthesizer.LLVM.Parameter as Param++import qualified Synthesizer.State.Signal as SigS++import Control.Arrow (arr, )+import Control.Monad (liftM, liftM2, )++import qualified Data.StorableVector.Lazy as SVL+import Data.StorableVector.Lazy (ChunkSize, )+import Foreign.Storable (Storable, )++import qualified LLVM.Extra.Memory as Memory+import qualified LLVM.Extra.Class as Class++import System.Random (Random, randomR, mkStdGen, )++import qualified Test.QuickCheck as QC++import qualified Algebra.RealRing as RealRing+import qualified Algebra.Absolute as Absolute++import NumericPrelude.Numeric+import NumericPrelude.Base+++rangeFromInt :: Random a => (a,a) -> Param.T Int a+rangeFromInt rng =+ arr $ fst . randomR rng . mkStdGen+++render ::+ (Storable a, Class.MakeValueTuple a, Class.ValueTuple a ~ al, Memory.C al) =>+ (SVL.Vector a -> sig) ->+ SigP.T p (Class.ValueTuple a) -> IO (ChunkSize -> p -> sig)+render limit sig =+ fmap+ (\func chunkSize ->+ limit . func chunkSize) $+ SigP.runChunky sig+++data CheckSimilarityState a =+ CheckSimilarityState a (SVL.Vector a) (SigS.T a)++instance (Storable a, Ord a, Absolute.C a) =>+ QC.Testable (CheckSimilarityState a) where+ property (CheckSimilarityState tol xs ys) =+ QC.property $+ SigS.foldR (&&) True $+ -- dangerous, since shortened signals would be tolerated+ SigS.zipWith (\x y -> abs(x-y) < tol)+ (SigS.fromStorableSignal xs) ys++{-# INLINE checkSimilarityState #-}+checkSimilarityState ::+ (RealRing.C a, Storable a,+ Class.MakeValueTuple a, Class.ValueTuple a ~ av,+ Memory.C av) =>+ a ->+ (SVL.Vector a -> SVL.Vector a) ->+ SigP.T p av ->+ (p -> SigS.T a) ->+ IO (ChunkSize -> p -> CheckSimilarityState a)+checkSimilarityState tol limit gen0 sig1 =+ liftM+ (\sig0 chunkSize p ->+ CheckSimilarityState tol (sig0 chunkSize p) (sig1 p))+ (render limit gen0)+++data CheckSimilarity a =+ CheckSimilarity a (SVL.Vector a) (SVL.Vector a)++instance (Storable a, Ord a, Absolute.C a) => QC.Testable (CheckSimilarity a) where+ property (CheckSimilarity tol xs ys) =+ QC.property $+ SigS.foldR (&&) True $+ -- dangerous, since shortened signals would be tolerated+ SigS.zipWith (\x y -> abs(x-y) < tol)+ (SigS.fromStorableSignal xs)+ (SigS.fromStorableSignal ys)++{-# INLINE checkSimilarity #-}+checkSimilarity ::+ (RealRing.C b, Storable b,+ Storable a,+ Class.MakeValueTuple a, Class.ValueTuple a ~ av, Memory.C av) =>+ b ->+ (SVL.Vector a -> SVL.Vector b) ->+ SigP.T p av -> SigP.T p av ->+ IO (ChunkSize -> p -> CheckSimilarity b)+checkSimilarity tol limit gen0 gen1 =+ liftM2+ (\sig0 sig1 chunkSize p ->+ CheckSimilarity tol (sig0 chunkSize p) (sig1 chunkSize p))+ (render limit gen0)+ (render limit gen1)+++{- |+Instead of testing on equality immediately+we use this interim data type.+This allows us to inspect the signals that are compared.+-}+data CheckEquality a =+ CheckEquality (SVL.Vector a) (SVL.Vector a)++instance (Storable a, Eq a) => QC.Testable (CheckEquality a) where+ property (CheckEquality x y) = QC.property (x==y)++checkEquality ::+ (Eq a, Storable a,+ Class.MakeValueTuple a, Class.ValueTuple a ~ av,+ Memory.C av) =>+ (SVL.Vector a -> SVL.Vector a) ->+ SigP.T p av -> SigP.T p av ->+ IO (ChunkSize -> p -> CheckEquality a)+checkEquality limit gen0 gen1 =+ liftM2+ (\sig0 sig1 chunkSize p ->+ CheckEquality (sig0 chunkSize p) (sig1 chunkSize p))+ (render limit gen0)+ (render limit gen1)