hommage-ds-0.0.5: Sound/Hommage/DSPlayer/UnsafeSimpleControl.hs
-- |
-- example: (you need a Wavfile (44100Hz, 16Bit, mono or stereo) named \"bassdrum.wav\")
--
-- @ ghci @
--
-- @ :m Sound.Hommage Sound.Hommage.DSPlayer.UnsafeSimpleControl @ -- load the modules
--
-- @ startAudio 4 @ -- start direct sound with a buffersize of 4*512
--
-- @ let s1 p = L $ Mono $ zipWith (*) (playADSR FitADR Linear (1,1,0.3,3) 20000) $ sinus $ repeat $ noteToFrequency 12 p @ -- define a simple synthesizer
--
-- @ next $ (\\x -> [x]:replicate 11 []) =<< [s1 12, s1 24, s1 16, s1 19, s1 24, s1 12, s1 16, s1 19]) @ -- run a simple bassline (1 bar = 96 ticks)
--
-- @ importSample \"bassdrum.wav\" @ -- load the bassdrum sample
--
-- @ let b1 = concat $ replicate 4 ([S 0 (1,0)] : replicate 23 []) @ -- define a beat
--
-- @ fnext $ zipWith (++) b1 @ -- add the beat to the current playing bassline
--
-- @ fnext $ map $ filter $ \\e -> case e of { S 0 _ -> False; _ -> True } @ -- remove the bassdrum sample events from the current playing loop
--
-- @ next [] @ -- silence
--
-- @ :q @
--
module Sound.Hommage.DSPlayer.UnsafeSimpleControl
( startAudio
, stopAudio
, importSample
, killAllVoices
, ev
, next
, after
, once
, fnext
, fafter
, current
, setBPM
, module Sound.Hommage.DSPlayer.SimpleControl
, module Sound.Hommage.DSPlayer.SimplePlayer
)
where
import Sound.Hommage.DSPlayer.SimpleControl
import Sound.Hommage.DSPlayer.SimplePlayer
import Sound.Hommage.DSPlayer.AudioSample
import Control.Concurrent
import Data.IORef
import System.IO.Unsafe
------------------------------------------------------------------------------
{-# NOINLINE ref_simplecontrol #-}
ref_simplecontrol :: IORef SimpleControl
ref_simplecontrol = unsafePerformIO $ newIORef undefined
------------------------------------------------------------------------------
-- | Start DirectSound and the sequencer loop
startAudio :: Int -> IO ()
startAudio latency = forkIO (startSimpleControl latency >>= writeIORef ref_simplecontrol) >> return ()
-- | Don't use this - quit ghci instead...
stopAudio :: IO ()
stopAudio = readIORef ref_simplecontrol >>= \c -> stopSC c
-- | Load an audiosample into RAM. The number\/ID of the sample is shown.
--
-- example: @ loadSample \"bassdrum.wav\" @ (shows for example \"Loading Sample Nr. 5\")
importSample :: FilePath -> IO ()
importSample fp = do
sc <- readIORef ref_simplecontrol
nr <- loadAudioSample (poolSC sc) fp
putStrLn ("Loading Sample Nr. " ++ show nr)
-- | Kill all current playing voices (lists and samples)
killAllVoices :: IO ()
killAllVoices = readIORef ref_simplecontrol >>= \sc -> killSP (playerSC sc)
-- | Set Beats-Per-Minute, (based on a 4-4-beat - so its equal to loops-per-4-minutes)
--
-- example: @ setBPM 133.33 @
setBPM :: Double -> IO ()
setBPM x = readIORef ref_simplecontrol >>= \sc -> fptSP (playerSC sc) (round(44100/((max 1 x)*24/60)))
-- | run an event
ev :: Event -> IO ()
ev e = readIORef ref_simplecontrol >>= \sc -> runEvent sc e
-- | set next loop (starting at next bar)
next :: [[Event]] -> IO ()
next es = readIORef ref_simplecontrol >>= \sc -> setOnZeroLS (sequencerSC sc) True es
-- | set next loop (starting at first bar after current events are played)
after :: [[Event]] -> IO ()
after es = readIORef ref_simplecontrol >>= \sc -> setOnZeroLS (sequencerSC sc) False es
-- | add some events to be played only once
once :: [[Event]] -> IO ()
once es = readIORef ref_simplecontrol >>= \sc -> setOnceLS (sequencerSC sc) es
-- | update next loop
fnext :: ([[Event]]->[[Event]]) -> IO ()
fnext f = readIORef ref_simplecontrol >>= \sc -> updOnZeroLS (sequencerSC sc) True f
-- | update next loop
fafter :: ([[Event]]->[[Event]]) -> IO ()
fafter f = readIORef ref_simplecontrol >>= \sc -> updOnZeroLS (sequencerSC sc) False f
-- | get next loop
current :: IO [[Event]]
current = readIORef ref_simplecontrol >>= \sc -> getOnZeroLS (sequencerSC sc)