module Haskore.Interface.SuperCollider.Schedule.Install where
import Sound.SC3.UGen.UGen (UGen)
import Sound.OpenSoundControl.OSC (OSC)
import qualified Haskore.Interface.SuperCollider.Example as Example
import qualified Haskore.Interface.SuperCollider.Play as Play
import qualified Haskore.Interface.SuperCollider.Schedule as Schedule
import qualified Haskore.Interface.SuperCollider.Note as Note
import qualified Haskore.Interface.SuperCollider.SoundMap as SoundMap
import Haskore.Interface.SuperCollider.SoundMap
(DrumParameters, InstrumentParameters, AttributeList)
import qualified Haskore.Composition.Drum as Drum
import qualified Haskore.Composition.Rhythm as Rhythm
import qualified Haskore.Music.Rhythmic as RhyMusic
import Haskore.Music.Rhythmic (qn)
import qualified Haskore.Music as Music
import Haskore.Melody as Melody
import Control.Monad.Trans.Writer (Writer, tell, runWriter)
newtype Environment a =
Environment {unwrapEnvironment :: Writer [OSC] a}
instance Monad Environment where
x >>= y = Environment $ unwrapEnvironment . y =<< unwrapEnvironment x
return = Environment . return
writeOSC :: [OSC] -> Environment ()
writeOSC = Environment . tell
data Sound params attr =
Sound
{nameFromSound :: String,
flattenAttrFromSound :: (attr -> AttributeList)}
type Instrument attr = Sound InstrumentParameters attr
type Drum attr = Sound DrumParameters attr
installSound ::
SoundMap.SoundParameters params =>
(parameterTuple -> AttributeList, graph -> SoundMap.Sound params) ->
String ->
graph ->
Environment (Sound params parameterTuple)
installSound (makeAttributeList, makeSoundUGen) name instr =
writeOSC [Schedule.installSoundMsg name
Schedule.defaultChannel (makeSoundUGen instr)] >>
return (Sound name makeAttributeList)
installSound0 ::
SoundMap.SoundParameters params =>
String ->
SoundMap.Sound params ->
Environment (Sound params ())
installSound0 =
installSound SoundMap.with0Attributes
installSound1 ::
SoundMap.SoundParameters params =>
String ->
(UGen -> SoundMap.Sound params) ->
Environment (Sound params Double)
installSound1 =
installSound SoundMap.with1Attribute
installSound2 ::
SoundMap.SoundParameters params =>
String ->
(UGen -> UGen -> SoundMap.Sound params) ->
Environment (Sound params (Double,Double))
installSound2 =
installSound SoundMap.with2Attributes
data SoundAttributes params = SoundAttributes AttributeList String
deriving (Eq, Ord)
type DrumAttributes = SoundAttributes DrumParameters
type InstrumentAttributes = SoundAttributes InstrumentParameters
rhythmicMusicFromDynamicMelody ::
Instrument attr ->
Melody.T (Rational, attr) ->
RhyMusic.T DrumAttributes InstrumentAttributes
rhythmicMusicFromDynamicMelody (Sound name flattenAttr) =
RhyMusic.fromMelody
(\(vel,attr) -> (vel, SoundAttributes (flattenAttr attr) name))
rhythmicMusicFromMelody ::
Instrument attr ->
Melody.T attr ->
RhyMusic.T DrumAttributes InstrumentAttributes
rhythmicMusicFromMelody instr =
rhythmicMusicFromDynamicMelody instr .
Music.mapNote (\(Melody.Note attr p) -> Melody.Note (1,attr) p)
rhythmicMusicFromRhythm ::
Drum () ->
Music.Dur ->
String ->
RhyMusic.T DrumAttributes InstrumentAttributes
rhythmicMusicFromRhythm sound dur =
Rhythm.toMusicWithDrumUnit dur (SoundAttributes [] (nameFromSound sound)) .
Rhythm.fromString
rhythmicMusicFromDrum ::
Drum () ->
Music.Dur ->
RhyMusic.T DrumAttributes InstrumentAttributes
rhythmicMusicFromDrum sound dur =
Drum.toMusicDefaultAttr (SoundAttributes [] (nameFromSound sound)) dur
fromRhythmicMusic ::
Environment (RhyMusic.T DrumAttributes InstrumentAttributes) ->
Schedule.T
fromRhythmicMusic genMusic =
let (music, installInstruments) = runWriter $ unwrapEnvironment genMusic
in Schedule.fromMusicMsgs
(Note.fromRhythmicNoteWithAttributes
(\(SoundAttributes params name) -> (params,name))
(\(SoundAttributes params name) -> (params,name)),
installInstruments) $
music
example :: IO ()
example =
Play.schedule Play.defaultLatency $ fromRhythmicMusic $
do sawPerc <- installSound0 "saw percussion" Example.sawPerc
dynPerc <- installSound1 "detuned bass" Example.dynPerc
let mel = 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 = rhythmicMusicFromMelody dynPerc $ Music.line
[c 0 qn 0.001, c 0 qn 0.003, c 0 qn 0.01]
return $
Music.changeTempo 2 $
Music.chord [mel,bass]