haskore-supercollider 0.1 → 0.1.1
raw patch · 7 files changed
+370/−355 lines, 7 filesdep ~arraydep ~containersdep ~random
Dependency ranges changed: array, containers, random
Files
- haskore-supercollider.cabal +37/−31
- src/Haskore/Interface/SuperCollider/Example.hs +2/−2
- src/Haskore/Interface/SuperCollider/Performance.hs +1/−1
- src/Haskore/Interface/SuperCollider/Play.hs +2/−2
- src/Haskore/Interface/SuperCollider/Play/Life.hs +4/−318
- src/Haskore/Interface/SuperCollider/Play/Live.hs +323/−0
- src/Haskore/Interface/SuperCollider/Schedule.hs +1/−1
haskore-supercollider.cabal view
@@ -1,5 +1,5 @@ Name: haskore-supercollider-Version: 0.1+Version: 0.1.1 License: GPL License-File: LICENSE Author: Henning Thielemann <haskell@henning-thielemann.de>@@ -26,7 +26,7 @@ Source-Repository this type: darcs location: http://darcs.haskell.org/haskore-supercollider/- tag: 0.1+ tag: 0.1.1 Flag splitBase description: Choose the new smaller, split-up base package.@@ -40,8 +40,10 @@ haskore-realtime >= 0.1 && < 0.2, haskore >=0.1 && <0.2, -- for SuperCollider support- hosc >=0.6 && <0.7, hsc3 >=0.6 && <0.7,- opensoundcontrol-ht >=0.1 && <0.2, supercollider-ht >=0.1 && <0.2,+ hosc >=0.6 && <0.7,+ hsc3 >=0.6 && <0.7,+ opensoundcontrol-ht >=0.1 && <0.2,+ supercollider-ht >=0.1 && <0.2, bytestring >=0.9 && <1.0, -- dependency on non-negative for Haddock non-negative >=0.0.1 && <0.1,@@ -54,9 +56,9 @@ If flag(splitBase) Build-Depends: base >= 3,- array >= 0.1 && <1.0,- containers >=0.1 && <1.0,- random >= 1.0 && <2.0,+ array >= 0.1 && <0.3,+ containers >=0.1 && <0.3,+ random >= 1.0 && <1.1, process >= 1.0 && <1.1 Else Build-Depends:@@ -65,31 +67,33 @@ GHC-Options: -Wall Hs-source-dirs: src Exposed-modules:- Haskore.Interface.SuperCollider.Channel,- Haskore.Interface.SuperCollider.Channel.State,- Haskore.Interface.SuperCollider.Channel.File,+ Haskore.Interface.SuperCollider.Channel+ Haskore.Interface.SuperCollider.Channel.State+ Haskore.Interface.SuperCollider.Channel.File -- needs 'unix' package- Haskore.Interface.SuperCollider.Channel.Env,- Haskore.Interface.SuperCollider.Example,- Haskore.Interface.SuperCollider.SoundMap,+ Haskore.Interface.SuperCollider.Channel.Env+ Haskore.Interface.SuperCollider.Example+ Haskore.Interface.SuperCollider.SoundMap -- needs Haskore.Interface.SuperCollider.Channel.Env and thus 'unix' package- Haskore.Interface.SuperCollider.Note,- Haskore.Interface.SuperCollider.Performance,- Haskore.Interface.SuperCollider.Play,- Haskore.Interface.SuperCollider.Play.Install,- Haskore.Interface.SuperCollider.Play.Channel,- Haskore.Interface.SuperCollider.Play.Life,- Haskore.Interface.SuperCollider.Render,- Haskore.Interface.SuperCollider.Schedule,- Haskore.Interface.SuperCollider.Schedule.Install,+ Haskore.Interface.SuperCollider.Note+ Haskore.Interface.SuperCollider.Performance+ Haskore.Interface.SuperCollider.Play+ Haskore.Interface.SuperCollider.Play.Install+ Haskore.Interface.SuperCollider.Play.Channel+ Haskore.Interface.SuperCollider.Play.Live+ Haskore.Interface.SuperCollider.Render+ Haskore.Interface.SuperCollider.Schedule+ Haskore.Interface.SuperCollider.Schedule.Install Haskore.Interface.SuperCollider.Schedule.Channel+ -- deprecated+ Haskore.Interface.SuperCollider.Play.Life Other-modules:- Haskore.Interface.SuperCollider.Timer,- Haskore.General.IdGenerator,- Haskore.General.IdGenerator.Modulo,- Haskore.General.IdGenerator.Set,- Haskore.General.IdGenerator.Simple,- Haskore.Interface.SuperCollider.Example.Air,+ Haskore.Interface.SuperCollider.Timer+ Haskore.General.IdGenerator+ Haskore.General.IdGenerator.Modulo+ Haskore.General.IdGenerator.Set+ Haskore.General.IdGenerator.Simple+ Haskore.Interface.SuperCollider.Example.Air Haskore.Interface.SuperCollider.Example.Morph Executable song-air@@ -98,12 +102,14 @@ Main-Is: Haskore/Interface/SuperCollider/Example/AirMain.hs Executable test- If !flag(buildTests)+ If flag(buildTests)+ Build-Depends:+ QuickCheck >=1 && <2, HUnit >=1.2 && <1.3+ Else Buildable: False - Build-Depends:- QuickCheck >=1 && <2, HUnit >=1.2 && <1.3 Hs-source-dirs: src GHC-Options: -Wall Main-Is: Test/Main.hs+ -- tests could not properly be extracted from main Haskore package Buildable: False
src/Haskore/Interface/SuperCollider/Example.hs view
@@ -146,7 +146,7 @@ sawPerc :: SoundMap.Instrument sawPerc = SoundMap.instrumentFromUGen sawPercUGen --- for demonstration in Play.Life+-- for demonstration in Play.Live sawPercUGen :: UGen -> UGen -> UGen sawPercUGen vel freq = let -- env = SCEnv.envGen SCRate.KR 1 2 0 1 PauseSynth SCEnv.envperc'@@ -159,7 +159,7 @@ dynPerc :: UGen -> SoundMap.Instrument dynPerc detune = SoundMap.instrumentFromUGen (dynPercUGen detune) --- for demonstration in Play.Life+-- for demonstration in Play.Live dynPercUGen :: UGen -> UGen -> UGen -> UGen dynPercUGen detune vel freq = let env = SCEnv.xLine SCRate.KR 1.5 0.1 1 DoNothing
src/Haskore/Interface/SuperCollider/Performance.hs view
@@ -164,7 +164,7 @@ PfBE.fromPaddedPerformance makeNote . FancyPf.paddedFromMusic -{- needed for Play.Install, Play.Channel, Life -}+{- needed for Play.Install, Play.Channel, Live -} {- fromRhythmicMusic :: (Show drum, Show instr, Ord drum, Ord instr,
src/Haskore/Interface/SuperCollider/Play.hs view
@@ -3,7 +3,7 @@ schedule, scheduleWithPlayer, shutUp, defaultLatency, timeStamp, - -- for Life module+ -- for Live module installSound, playAtom, performanceTrans, messagesGrouped, @@ -122,7 +122,7 @@ {- * Initialization of replay -} {- |-Default value for latency used in "Haskore.Interface.SuperCollider.Play.Life"+Default value for latency used in "Haskore.Interface.SuperCollider.Play.Live" and connected modules. -} defaultLatency :: Time
src/Haskore/Interface/SuperCollider/Play/Life.hs view
@@ -1,319 +1,5 @@-{- |-This is a module specialised to life performances.--You can create and install instruments in SuperCollider,-obtain a handle and use that in your song.--The alternative way would be to upload an instrument-whenever one tone shall be played.-This is less efficient but simpler and certainly more flexbile.--}-module Haskore.Interface.SuperCollider.Play.Life where--import qualified Sound.SC3 as SC-import qualified Sound.SC3.UGen.IO as SCIO-import qualified Sound.SC3.UGen.UGen as SCUGen-import qualified Sound.SC3.UGen.Oscillator as SCOsci-import qualified Sound.SC3.UGen.Filter as SCFilt-import qualified Sound.SC3.UGen.Envelope as SCUGEnv-import qualified Sound.SC3.UGen.Noise.Base as SCNoise-import qualified Sound.SC3.UGen.UId as SCUId--import Sound.SC3.UGen.Enum (DoneAction(DoNothing, PauseSynth))-import Sound.SC3.UGen.Rate (Rate(AR,KR))--import qualified Sound.SC3.Server.PlayEasy as SCPlay-import qualified Sound.SC3.Server.Command as SCCmd--import Sound.SC3.UGen.UGen (UGen)--import Sound.OpenSoundControl.Transport (Transport)-import qualified Sound.OpenSoundControl.Transport.Monad as Trans--import qualified Haskore.Interface.SuperCollider.Example as Example-import qualified Haskore.Interface.SuperCollider.Play.Install as IPlay-import qualified Haskore.Interface.SuperCollider.Play as Play-import qualified Haskore.Interface.SuperCollider.Schedule as Schedule-import qualified Haskore.Interface.SuperCollider.Schedule.Channel as CSched-import qualified Haskore.Interface.SuperCollider.Schedule.Install as ISched-import qualified Haskore.Interface.SuperCollider.Performance as SCPf-import qualified Haskore.Interface.SuperCollider.SoundMap as SoundMap--import Haskore.Interface.SuperCollider.SoundMap- (InstrumentParameters, DrumParameters, AttributeList)--import qualified Haskore.Interface.SuperCollider.Channel.Env as ChannelEnv-import qualified Haskore.Interface.SuperCollider.Channel as Channel-import Haskore.Interface.SuperCollider.Channel (Channel, NumberChannels)--import Haskore.Interface.SuperCollider.Schedule.Channel- (Sound(..), ugenFromSound,- Instrument, -- InstrumentAttributes,- Drum, -- DrumAttributes,- rhythmicMusicFromDynamicMelody, rhythmicMusicFromMelody,- rhythmicMusicFromRhythm, rhythmicMusicFromDrum)-import Haskore.Interface.SuperCollider.Schedule.Install- (InstrumentAttributes(..), DrumAttributes(..))--import qualified Haskore.Basic.Pitch as Pitch-import qualified Haskore.Basic.Duration as Dur-import Haskore.Basic.Duration ((%+))--import qualified Haskore.Interface.SuperCollider.Timer as SCTimer--import qualified Haskore.General.IdGenerator as IdGen--import qualified Haskore.Composition.Drum as Drum-import Haskore.Composition.Chord as Chord--import Haskore.Melody as Melody-import qualified Haskore.Music as Music-import Haskore.Music (mapNote)-import qualified Haskore.Music.Rhythmic as RhyMusic-import Haskore.Music.Rhythmic (- (+:+), (=:=),- wn, hn, qn, en, sn, tn, sfn,- dwn, dhn, dqn, den, dsn, dtn,- wnr, hnr, qnr, enr, snr, tnr, sfnr,- dwnr, dhnr, dqnr, denr, dsnr, dtnr,)---- import System.Random (randomRs, mkStdGen)--import System.Posix.Process (forkProcess)--- import Control.Concurrent (forkIO)-import Control.Monad (liftM2)--import Data.List (elemIndex)----{- * Install instruments -}--type InstrumentUGen = UGen -> UGen -> UGen--installInstr ::- (parameterTuple -> AttributeList, graph -> InstrumentUGen) ->- String ->- graph ->- IO (ISched.Instrument parameterTuple)-installInstr (makeAttributeList, makeSoundUGen) name sound =- SCPlay.withSC3 $- IPlay.installSound- (makeAttributeList, SoundMap.instrumentFromUGen . makeSoundUGen) name sound---installInstr0 ::- String ->- InstrumentUGen ->- IO (ISched.Instrument ())-installInstr0 =- installInstr SoundMap.with0Attributes--installInstr1 ::- String ->- (UGen -> InstrumentUGen) ->- IO (ISched.Instrument Double)-installInstr1 =- installInstr SoundMap.with1Attribute--installInstr2 ::- String ->- (UGen -> UGen -> InstrumentUGen) ->- IO (ISched.Instrument (Double,Double))-installInstr2 =- installInstr SoundMap.with2Attributes---type DrumUGen = UGen -> UGen--installDrum ::- (parameterTuple -> AttributeList, graph -> DrumUGen) ->- String ->- graph ->- IO (ISched.Drum parameterTuple)-installDrum (makeAttributeList, makeSoundUGen) name sound =- SCPlay.withSC3 $- IPlay.installSound- (makeAttributeList, SoundMap.drumFromUGen . makeSoundUGen) name sound-----{- * Install instruments on specific channels -}---installSoundChan ::- SoundMap.SoundParameters params =>- String ->- SoundMap.Sound params ->- IO (Channel, NumberChannels)-installSoundChan name sound =- do let ugen = SoundMap.ugenFromSound sound- let numChan = SCPlay.mceDegree ugen- chan <- Channel.next ChannelEnv.manager numChan- SCPlay.withSC3 $- SCPlay.simpleSync $ SCPlay.d_recv_synthdef name $- SCIO.out (SCUGen.Constant (fromIntegral chan)) ugen- return (chan, numChan)---installInstrChan ::- (parameterTuple -> AttributeList, graph -> InstrumentUGen) ->- String ->- graph ->- IO (Instrument parameterTuple)-installInstrChan (makeAttributeList, makeInstrumentUGen) name sound =- do chanChunk <-- installSoundChan name $- SoundMap.instrumentFromUGen $- makeInstrumentUGen sound- return (Sound name chanChunk makeAttributeList)--installDrumChan ::- (parameterTuple -> AttributeList, graph -> DrumUGen) ->- String ->- graph ->- IO (Drum parameterTuple)-installDrumChan (makeAttributeList, makeDrumUGen) name sound =- do chanChunk <-- installSoundChan name $- SoundMap.drumFromUGen $- makeDrumUGen sound- return (Sound name chanChunk makeAttributeList)----{- |-This one is more portable but less elegant.--}---{- * Play music -}--reset :: IO ()-reset =- do Channel.reset ChannelEnv.manager- SCPlay.withSC3 $ SCPlay.reset--playSound :: UGen -> IO ()-playSound = fmap (const ()) . SCPlay.withSC3 . SCPlay.play--playMusic ::- RhyMusic.T DrumAttributes InstrumentAttributes -> IO ()-playMusic =- Play.performance Play.defaultLatency [] .- SCPf.fixNodeIds .- SCPf.fromRhythmicMusicWithAttributes- (\(ISched.SoundAttributes params name) -> (params,name))- (\(ISched.SoundAttributes params name) -> (params,name))--playMusicEffect ::- UGen ->- RhyMusic.T CSched.DrumAttributes CSched.InstrumentAttributes ->- IO ()-playMusicEffect effect song =- let (sid,pf) =- SCPf.fixNodeIds $- liftM2 (,)- IdGen.alloc- (SCPf.fromRhythmicMusicWithAttributes- (\(CSched.SoundAttributes params name) -> (params,name))- (\(CSched.SoundAttributes params name) -> (params,name))- song)- effectsName = "global effects"- in SCPlay.withSC3 $- {- We rely on the fact, that the performance player- always adds new nodes to the head.- This way, the effect is run after the instrument nodes. -}- Play.scheduleWithPlayer- (Play.messagesGrouped SCTimer.timer Play.defaultLatency)- (Schedule.fromPerformance- [Schedule.installUGenMsg effectsName- Schedule.defaultChannel effect]- [SCCmd.s_new effectsName sid SCCmd.AddToTail SCPlay.homeId []]- pf) >>- return ()---{- * Interactively play music on keyboard -}--germanLatin1Keyboard :: [Char]-germanLatin1Keyboard =- let oUmlaut = '\246'- uUmlaut = '\252'- szLig = '\223'- in "ysxdcvgbhnjm,l."++oUmlaut:"-q2w3e4rt6z7ui9o0p"++szLig:uUmlaut:"+"--playKey :: ISched.Instrument () -> Char -> IO ()-playKey (ISched.Sound name _) key =- maybe- (return ())- (\pitch ->- do SCPlay.withSC3 $- Play.playAtom SCPlay.noId name $- ("pitch", Pitch.intToFreq pitch) :- ("velocity", 1) : []- print (Pitch.fromInt pitch))- (elemIndex key germanLatin1Keyboard)--{- |-Interprets the keyboard as piano and play according tones,-when keys are hit.--Is it more convenient to have a UGen parameter and install the instrument automatically?--}-{--Try suppressing output on keys by-System.IO.hSetEcho System.IO.stdin False--}-playKeyboard :: ISched.Instrument () -> IO ()-playKeyboard instr =- let recourse =- do char <- getChar- if char == '\004'- then putStrLn ""- else do putChar '\008'- playKey instr char- recourse- in recourse----{- * Example music -}---example :: IO ()-example =- do reset- sawPerc <- installInstr0 "saw percussion" Example.sawPercUGen- dynPerc <- installInstr1 "detuned bass" Example.dynPercUGen- let mel = ISched.rhythmicMusicFromMelody sawPerc $ Music.transpose 12 $ Music.line- [c 0 qn (), e 0 qn (),- Music.chord [c 0 qn (), e 0 qn (), g 0 qn ()]]- bass = ISched.rhythmicMusicFromMelody dynPerc $ Music.line- [c 0 qn 0.001, c 0 qn 0.003, c 0 qn 0.01]- playMusic $- Music.changeTempo 2 $- Music.chord [mel,bass]---exampleEffect :: IO ()-exampleEffect =- do reset- sawPerc <- installInstrChan SoundMap.with0Attributes "saw percussion" Example.sawPercUGen- dynPerc <- installInstrChan SoundMap.with1Attribute "detuned bass" Example.dynPercUGen- let lfoSine = exp (SCOsci.sinOsc KR 0.2 (-pi/2) * 0.5) * 1000- lfoSquare = exp (SCOsci.pulse KR 5.1 0.5 * 1) * 1000- mix =- SCFilt.rlpf (0.5 * ugenFromSound sawPerc) lfoSine 0.1 +- SCFilt.rlpf (0.5 * ugenFromSound dynPerc) lfoSquare 0.1- -- SCUGen.Constant 0- let mel = CSched.rhythmicMusicFromMelody sawPerc $ Music.transpose 12 $ Music.line $- cycle [c 0 qn (), b 0 qn (), c 1 qn ()]- bass = CSched.rhythmicMusicFromMelody dynPerc $ Music.line $- cycle [c 0 qn 0.001, c 0 qn 0.003, c 0 qn 0.01]- playMusicEffect mix $- -- (0.3 * SCOsci.sinOsc AR 880 0) $- Music.changeTempo 2 $- Music.chord [Music.changeTempo 3 mel, bass]+module Haskore.Interface.SuperCollider.Play.Life+ {-# DEPRECATED "use Play.Live instead" #-}+ (module Haskore.Interface.SuperCollider.Play.Live) where +import Haskore.Interface.SuperCollider.Play.Live
+ src/Haskore/Interface/SuperCollider/Play/Live.hs view
@@ -0,0 +1,323 @@+{- |+This is a module specialised to life performances.++You can create and install instruments in SuperCollider,+obtain a handle and use that in your song.++The alternative way would be to upload an instrument+whenever one tone shall be played.+This is less efficient but simpler and certainly more flexible.++It is certainly not sensible to import that module.+Maybe I should provide it as Extra-Source-File or+as Main module of a dummy executable in order to ship it via Cabal.+-}+module Haskore.Interface.SuperCollider.Play.Live where++import qualified Sound.SC3 as SC+import qualified Sound.SC3.UGen.IO as SCIO+import qualified Sound.SC3.UGen.UGen as SCUGen+import qualified Sound.SC3.UGen.Oscillator as SCOsci+import qualified Sound.SC3.UGen.Filter as SCFilt+import qualified Sound.SC3.UGen.Envelope as SCUGEnv+import qualified Sound.SC3.UGen.Noise.Base as SCNoise+import qualified Sound.SC3.UGen.UId as SCUId++import Sound.SC3.UGen.Enum (DoneAction(DoNothing, PauseSynth))+import Sound.SC3.UGen.Rate (Rate(AR,KR))++import qualified Sound.SC3.Server.PlayEasy as SCPlay+import qualified Sound.SC3.Server.Command as SCCmd++import Sound.SC3.UGen.UGen (UGen)++import Sound.OpenSoundControl.Transport (Transport)+import qualified Sound.OpenSoundControl.Transport.Monad as Trans++import qualified Haskore.Interface.SuperCollider.Example as Example+import qualified Haskore.Interface.SuperCollider.Play.Install as IPlay+import qualified Haskore.Interface.SuperCollider.Play as Play+import qualified Haskore.Interface.SuperCollider.Schedule as Schedule+import qualified Haskore.Interface.SuperCollider.Schedule.Channel as CSched+import qualified Haskore.Interface.SuperCollider.Schedule.Install as ISched+import qualified Haskore.Interface.SuperCollider.Performance as SCPf+import qualified Haskore.Interface.SuperCollider.SoundMap as SoundMap++import Haskore.Interface.SuperCollider.SoundMap+ (InstrumentParameters, DrumParameters, AttributeList)++import qualified Haskore.Interface.SuperCollider.Channel.Env as ChannelEnv+import qualified Haskore.Interface.SuperCollider.Channel as Channel+import Haskore.Interface.SuperCollider.Channel (Channel, NumberChannels)++import Haskore.Interface.SuperCollider.Schedule.Channel+ (Sound(..), ugenFromSound,+ Instrument, -- InstrumentAttributes,+ Drum, -- DrumAttributes,+ rhythmicMusicFromDynamicMelody, rhythmicMusicFromMelody,+ rhythmicMusicFromRhythm, rhythmicMusicFromDrum)+import Haskore.Interface.SuperCollider.Schedule.Install+ (InstrumentAttributes(..), DrumAttributes(..))++import qualified Haskore.Basic.Pitch as Pitch+import qualified Haskore.Basic.Duration as Dur+import Haskore.Basic.Duration ((%+))++import qualified Haskore.Interface.SuperCollider.Timer as SCTimer++import qualified Haskore.General.IdGenerator as IdGen++import qualified Haskore.Composition.Drum as Drum+import Haskore.Composition.Chord as Chord++import Haskore.Melody as Melody+import qualified Haskore.Music as Music+import Haskore.Music (mapNote)+import qualified Haskore.Music.Rhythmic as RhyMusic+import Haskore.Music.Rhythmic (+ (+:+), (=:=),+ wn, hn, qn, en, sn, tn, sfn,+ dwn, dhn, dqn, den, dsn, dtn,+ wnr, hnr, qnr, enr, snr, tnr, sfnr,+ dwnr, dhnr, dqnr, denr, dsnr, dtnr,)++-- import System.Random (randomRs, mkStdGen)++import System.Posix.Process (forkProcess)+-- import Control.Concurrent (forkIO)+import Control.Monad (liftM2)++import Data.List (elemIndex)++++{- * Install instruments -}++type InstrumentUGen = UGen -> UGen -> UGen++installInstr ::+ (parameterTuple -> AttributeList, graph -> InstrumentUGen) ->+ String ->+ graph ->+ IO (ISched.Instrument parameterTuple)+installInstr (makeAttributeList, makeSoundUGen) name sound =+ SCPlay.withSC3 $+ IPlay.installSound+ (makeAttributeList, SoundMap.instrumentFromUGen . makeSoundUGen) name sound+++installInstr0 ::+ String ->+ InstrumentUGen ->+ IO (ISched.Instrument ())+installInstr0 =+ installInstr SoundMap.with0Attributes++installInstr1 ::+ String ->+ (UGen -> InstrumentUGen) ->+ IO (ISched.Instrument Double)+installInstr1 =+ installInstr SoundMap.with1Attribute++installInstr2 ::+ String ->+ (UGen -> UGen -> InstrumentUGen) ->+ IO (ISched.Instrument (Double,Double))+installInstr2 =+ installInstr SoundMap.with2Attributes+++type DrumUGen = UGen -> UGen++installDrum ::+ (parameterTuple -> AttributeList, graph -> DrumUGen) ->+ String ->+ graph ->+ IO (ISched.Drum parameterTuple)+installDrum (makeAttributeList, makeSoundUGen) name sound =+ SCPlay.withSC3 $+ IPlay.installSound+ (makeAttributeList, SoundMap.drumFromUGen . makeSoundUGen) name sound+++++{- * Install instruments on specific channels -}+++installSoundChan ::+ SoundMap.SoundParameters params =>+ String ->+ SoundMap.Sound params ->+ IO (Channel, NumberChannels)+installSoundChan name sound =+ do let ugen = SoundMap.ugenFromSound sound+ let numChan = SCPlay.mceDegree ugen+ chan <- Channel.next ChannelEnv.manager numChan+ SCPlay.withSC3 $+ SCPlay.simpleSync $ SCPlay.d_recv_synthdef name $+ SCIO.out (SCUGen.Constant (fromIntegral chan)) ugen+ return (chan, numChan)+++installInstrChan ::+ (parameterTuple -> AttributeList, graph -> InstrumentUGen) ->+ String ->+ graph ->+ IO (Instrument parameterTuple)+installInstrChan (makeAttributeList, makeInstrumentUGen) name sound =+ do chanChunk <-+ installSoundChan name $+ SoundMap.instrumentFromUGen $+ makeInstrumentUGen sound+ return (Sound name chanChunk makeAttributeList)++installDrumChan ::+ (parameterTuple -> AttributeList, graph -> DrumUGen) ->+ String ->+ graph ->+ IO (Drum parameterTuple)+installDrumChan (makeAttributeList, makeDrumUGen) name sound =+ do chanChunk <-+ installSoundChan name $+ SoundMap.drumFromUGen $+ makeDrumUGen sound+ return (Sound name chanChunk makeAttributeList)++++{- |+This one is more portable but less elegant.+-}+++{- * Play music -}++reset :: IO ()+reset =+ do Channel.reset ChannelEnv.manager+ SCPlay.withSC3 $ SCPlay.reset++playSound :: UGen -> IO ()+playSound = fmap (const ()) . SCPlay.withSC3 . SCPlay.play++playMusic ::+ RhyMusic.T DrumAttributes InstrumentAttributes -> IO ()+playMusic =+ Play.performance Play.defaultLatency [] .+ SCPf.fixNodeIds .+ SCPf.fromRhythmicMusicWithAttributes+ (\(ISched.SoundAttributes params name) -> (params,name))+ (\(ISched.SoundAttributes params name) -> (params,name))++playMusicEffect ::+ UGen ->+ RhyMusic.T CSched.DrumAttributes CSched.InstrumentAttributes ->+ IO ()+playMusicEffect effect song =+ let (sid,pf) =+ SCPf.fixNodeIds $+ liftM2 (,)+ IdGen.alloc+ (SCPf.fromRhythmicMusicWithAttributes+ (\(CSched.SoundAttributes params name) -> (params,name))+ (\(CSched.SoundAttributes params name) -> (params,name))+ song)+ effectsName = "global effects"+ in SCPlay.withSC3 $+ {- We rely on the fact, that the performance player+ always adds new nodes to the head.+ This way, the effect is run after the instrument nodes. -}+ Play.scheduleWithPlayer+ (Play.messagesGrouped SCTimer.timer Play.defaultLatency)+ (Schedule.fromPerformance+ [Schedule.installUGenMsg effectsName+ Schedule.defaultChannel effect]+ [SCCmd.s_new effectsName sid SCCmd.AddToTail SCPlay.homeId []]+ pf) >>+ return ()+++{- * Interactively play music on keyboard -}++germanLatin1Keyboard :: [Char]+germanLatin1Keyboard =+ let oUmlaut = '\246'+ uUmlaut = '\252'+ szLig = '\223'+ in "ysxdcvgbhnjm,l."++oUmlaut:"-q2w3e4rt6z7ui9o0p"++szLig:uUmlaut:"+"++playKey :: ISched.Instrument () -> Char -> IO ()+playKey (ISched.Sound name _) key =+ maybe+ (return ())+ (\pitch ->+ do SCPlay.withSC3 $+ Play.playAtom SCPlay.noId name $+ ("pitch", Pitch.intToFreq pitch) :+ ("velocity", 1) : []+ print (Pitch.fromInt pitch))+ (elemIndex key germanLatin1Keyboard)++{- |+Interprets the keyboard as piano and play according tones,+when keys are hit.++Is it more convenient to have a UGen parameter and install the instrument automatically?+-}+{-+Try suppressing output on keys by+System.IO.hSetEcho System.IO.stdin False+-}+playKeyboard :: ISched.Instrument () -> IO ()+playKeyboard instr =+ let recourse =+ do char <- getChar+ if char == '\004'+ then putStrLn ""+ else do putChar '\008'+ playKey instr char+ recourse+ in recourse++++{- * Example music -}+++example :: IO ()+example =+ do reset+ sawPerc <- installInstr0 "saw percussion" Example.sawPercUGen+ dynPerc <- installInstr1 "detuned bass" Example.dynPercUGen+ let mel = ISched.rhythmicMusicFromMelody sawPerc $ Music.transpose 12 $ Music.line+ [c 0 qn (), e 0 qn (),+ Music.chord [c 0 qn (), e 0 qn (), g 0 qn ()]]+ bass = ISched.rhythmicMusicFromMelody dynPerc $ Music.line+ [c 0 qn 0.001, c 0 qn 0.003, c 0 qn 0.01]+ playMusic $+ Music.changeTempo 2 $+ Music.chord [mel,bass]+++exampleEffect :: IO ()+exampleEffect =+ do reset+ sawPerc <- installInstrChan SoundMap.with0Attributes "saw percussion" Example.sawPercUGen+ dynPerc <- installInstrChan SoundMap.with1Attribute "detuned bass" Example.dynPercUGen+ let lfoSine = exp (SCOsci.sinOsc KR 0.2 (-pi/2) * 0.5) * 1000+ lfoSquare = exp (SCOsci.pulse KR 5.1 0.5 * 1) * 1000+ mix =+ SCFilt.rlpf (0.5 * ugenFromSound sawPerc) lfoSine 0.1 ++ SCFilt.rlpf (0.5 * ugenFromSound dynPerc) lfoSquare 0.1+ -- SCUGen.Constant 0+ let mel = CSched.rhythmicMusicFromMelody sawPerc $ Music.transpose 12 $ Music.line $+ cycle [c 0 qn (), b 0 qn (), c 1 qn ()]+ bass = CSched.rhythmicMusicFromMelody dynPerc $ Music.line $+ cycle [c 0 qn 0.001, c 0 qn 0.003, c 0 qn 0.01]+ playMusicEffect mix $+ -- (0.3 * SCOsci.sinOsc AR 880 0) $+ Music.changeTempo 2 $+ Music.chord [Music.changeTempo 3 mel, bass]+
src/Haskore/Interface/SuperCollider/Schedule.hs view
@@ -248,7 +248,7 @@ OSC atomPlayMsg sid name = SCCmd.s_new name sid SCCmd.AddToHead SCPlay.homeId- -- adding to head is necessary for allowing global effects like in the Life module+ -- adding to head is necessary for allowing global effects like in the Live module installUGenMsg ::