module Haskore.Interface.SuperCollider.Play (
music, melody, performance,
schedule, scheduleWithPlayer, shutUp,
defaultLatency, timeStamp,
installSound, playAtom,
performanceTrans, messagesGrouped,
messagesGroupedManual, messagesSingly, messagesSimple,
) where
import qualified Haskore.Interface.SuperCollider.Schedule as Schedule
import Haskore.Interface.SuperCollider.Schedule (Time)
import qualified Haskore.Interface.SuperCollider.Performance as SCPf
import qualified Haskore.Interface.SuperCollider.SoundMap as SoundMap
import Haskore.Interface.SuperCollider.SoundMap (Instrument, Sound)
import qualified Sound.SC3.Server.PlayEasy as SCPlay
import Sound.OSC.Transport.Monad (Transport, waitReply, )
import qualified Sound.OSC.Type as OSC
import qualified Sound.OSC.Time as OSCTime
import qualified Haskore.Melody as Melody
import qualified Haskore.Music as Music
import qualified Haskore.Interface.SuperCollider.Timer as SCTimer
import qualified Haskore.RealTime.Timer as Timer
import qualified Haskore.RealTime.EventList.TimeBody as TimeList
import qualified Numeric.NonNegative.Wrapper as NonNeg
import Control.Monad.IO.Class (MonadIO, )
import Control.Monad (liftM, )
music :: Ord note =>
Time ->
Schedule.SoundHandler note ->
Music.T note ->
IO ()
music latency soundHandler =
schedule latency .
Schedule.fromMusic soundHandler
melody :: Time -> Instrument -> Melody.T () -> IO ()
melody latency sound =
schedule latency .
Schedule.fromMelody sound
performanceTrans :: (Transport m, MonadIO m) =>
Time ->
[OSC.Message] ->
SCPf.T Time ->
m ()
performanceTrans latency installMsgs =
scheduleWithPlayer
(messagesGrouped SCTimer.timer latency) .
Schedule.fromPerformance installMsgs []
performance ::
Time ->
[OSC.Message] ->
SCPf.T Time ->
IO ()
performance latency installMsgs =
schedule latency .
Schedule.fromPerformance installMsgs []
schedule ::
Time ->
Schedule.T ->
IO ()
schedule latency =
SCPlay.withSC3 .
scheduleWithPlayer
(messagesGrouped SCTimer.timer latency)
shutUp :: IO ()
shutUp =
do SCPlay.withSC3 SCPlay.stop
return ()
defaultLatency :: Time
defaultLatency = 0.1
timeStamp :: Time -> Time -> [OSC.Message] -> OSC.Bundle
timeStamp start t msgs = OSC.Bundle (OSCTime.ut_to_ntpr $ NonNeg.toNumber (start+t)) msgs
installSound ::
(Transport m, SoundMap.SoundParameters params) =>
String ->
Sound params ->
m ()
installSound name instr =
SCPlay.simpleSync $ Schedule.installSoundMsg name Schedule.defaultChannel instr
playAtom :: Transport m =>
SCPlay.NodeId
-> String
-> [(String,Double)]
-> m ()
playAtom sid name params =
SCPlay.send (Schedule.atomPlayMsg sid name params)
scheduleWithPlayer :: Transport m =>
(TimeList.T Time OSC.Message -> m ()) ->
Schedule.T ->
m ()
scheduleWithPlayer player sc =
do
let isc = Schedule.initial sc
mapM_ SCPlay.send isc
mapM_ (const (waitReply "/done" >> return ())) isc
player (Schedule.body sc)
return ()
messagesGrouped :: (Transport m) =>
Timer.T m ->
Time ->
TimeList.T Time OSC.Message -> m ()
messagesGrouped timer latency =
liftM (const ()) .
TimeList.runTimeStampGrouped timer
(\time -> SCPlay.send . timeStamp latency time)
messagesGroupedManual :: (Transport m) =>
Timer.T m ->
Time ->
TimeList.T Time OSC.Message -> m ()
messagesGroupedManual timer latency =
liftM (const ()) .
TimeList.runTimeStamp timer
(\time ->
(SCPlay.send . timeStamp latency time))
. TimeList.collectCoincident
messagesSingly :: (Transport m) =>
Timer.T m ->
Time ->
TimeList.T Time OSC.Message -> m ()
messagesSingly timer latency =
liftM (const ()) .
TimeList.runTimeStamp timer
(\time ->
(SCPlay.send . timeStamp latency time . (:[])))
messagesSimple :: (Transport m) =>
Timer.T m ->
TimeList.T Time OSC.Message ->
m ()
messagesSimple timer =
liftM (const ()) .
TimeList.run timer SCPlay.send