{- |
This is a variant of the "Haskore.Interface.SuperCollider.Play.Install" module.
It assigns output channels to instruments
such that instrument specific global effects can be applied to them.
-}moduleHaskore.Interface.SuperCollider.Play.Channel{-# DEPRECATED "use Haskore.Interface.SuperCollider.Schedule.Channel instead" #-}whereimportqualifiedSound.SC3.UGen.UGenasSCUGenimportqualifiedSound.SC3.UGen.OscillatorasSCOsciimportqualifiedSound.SC3.UGen.FilterasSCFiltimportSound.SC3.UGen.Rate(Rate(KR))importqualifiedSound.SC3.Server.PlayEasyasSCPlayimportqualifiedSound.SC3.Server.CommandasSCCmdimportSound.SC3.UGen.UGen(UGen)importSound.OpenSoundControl.Transport(Transport)importSound.OpenSoundControl.Transport.UDP(UDP)importSound.OpenSoundControl.Transport.File(File)importqualifiedSound.OpenSoundControl.Transport.MonadasTransimportqualifiedHaskore.Interface.SuperCollider.Channel.StateasChannelStateimportqualifiedHaskore.Interface.SuperCollider.ChannelasChannelimportHaskore.Interface.SuperCollider.Channel(Channel,NumberChannels)importqualifiedHaskore.Interface.SuperCollider.ExampleasExampleimportqualifiedHaskore.Interface.SuperCollider.PlayasPlayimportqualifiedHaskore.Interface.SuperCollider.ScheduleasScheduleimportqualifiedHaskore.Interface.SuperCollider.PerformanceasSCPfimportqualifiedHaskore.Interface.SuperCollider.SoundMapasSoundMapimportHaskore.Interface.SuperCollider.Schedule.Channel(Sound(..),SoundAttributes(..),ugenFromSound,DrumAttributes,InstrumentAttributes,{- rhythmicMusicFromDynamicMelody, -}rhythmicMusicFromMelody,{- rhythmicMusicFromRhythm, rhythmicMusicFromDrum, -})importHaskore.Interface.SuperCollider.SoundMap(AttributeList)importqualifiedHaskore.MusicasMusicimportqualifiedHaskore.Music.RhythmicasRhyMusicimportHaskore.Music.Rhythmic(qn)importHaskore.MelodyasMelodyimportqualifiedHaskore.RealTime.Timer.ThreadasTimerThread-- import qualified Haskore.RealTime.Timer.Immediate as TimerImmediateimportqualifiedHaskore.General.IdGeneratorasIdGenimportqualifiedControl.Monad.StateasStateimportControl.Monad.State(StateT,evalStateT,lift,liftM2)importControl.Monad.Reader(ReaderT){- * Install instruments -}{-
The @[OSC]@ state is used for messages for installing the instruments.
We cannot use a Writer monad for this purpose
because we have to read the generated messages for 'playMusic'.
-}typeEnvironmentta=StateTChannel(ReaderTtIO)a-- type Environment t a = StateT Channel (Trans.IO t) ainstallUGen::Transportt=>String->UGen->Environmentt(Channel,NumberChannels)installUGennamesound=doletnumChan=SCPlay.mceDegreesoundchan<-Channel.nextChannelState.managernumChanlift$SCPlay.simpleSync$Schedule.installUGenMsgnamechansoundreturn(chan,numChan)installSound::(Transportt,SoundMap.SoundParametersparams)=>(parameterTuple->AttributeList,graph->SoundMap.Soundparams)->String->graph->Environmentt(SoundparamsparameterTuple)installSound(makeAttributeList,makeSoundUGen)nameinstr=dochanChunk<-installUGenname$SoundMap.ugenFromSound$makeSoundUGeninstrreturn(SoundnamechanChunkmakeAttributeList){- * Play music -}reset::Transportt=>Environmentt()reset=doChannel.resetChannelState.managerliftSCPlay.resetplayMusic::Transportt=>UGen->RhyMusic.TDrumAttributesInstrumentAttributes->Environmentt()playMusiceffectsong=let(sid,pf)=SCPf.fixNodeIds$liftM2(,)IdGen.alloc(SCPf.fromRhythmicMusicWithAttributes(\(SoundAttributesattrsname)->(attrs,name))(\(SoundAttributesattrsname)->(attrs,name))song)effectsName="global effects"inlift${- 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.messagesGroupedTimerThread.timerPlay.defaultLatency)(Schedule.fromPerformance[Schedule.installUGenMsgeffectsNameSchedule.defaultChanneleffect][SCCmd.s_neweffectsNamesidSCCmd.AddToTailSCPlay.homeId[]]pf)>>return()run::EnvironmentUDPa->IOarunact=SCPlay.withSC3(evalStateTactChannel.least)writeScript::FilePath->EnvironmentFilea->IOawriteScriptfnact=SCPlay.withSC3Filefn(evalStateTactChannel.least){- * Example music -}example::IO()example=run$dosawPerc<-installSoundSoundMap.with0Attributes"saw percussion"Example.sawPercdynPerc<-installSoundSoundMap.with1Attribute"detuned bass"Example.dynPercletlfoSine=exp(SCOsci.sinOscKR0.2(-pi/2)*0.5)*1000lfoSquare=exp(SCOsci.pulseKR5.10.5*1)*1000mix=SCFilt.rlpf(0.5*ugenFromSoundsawPerc)lfoSine0.1+SCFilt.rlpf(0.5*ugenFromSounddynPerc)lfoSquare0.1-- SCUGen.Constant 0letmel=rhythmicMusicFromMelodysawPerc$Music.transpose12$Music.line$cycle[c0qn(),b0qn(),c1qn()]bass=rhythmicMusicFromMelodydynPerc$Music.line$cycle[c0qn0.001,c0qn0.003,c0qn0.01]playMusicmix$-- (0.3 * SCOsci.sinOsc AR 880 0) $Music.changeTempo2$Music.chord[Music.changeTempo3mel,bass]