haskore-supercollider-0.0.2: src/Haskore/Interface/SuperCollider/Render.hs
module Haskore.Interface.SuperCollider.Render (
fileFromMelody, fileFromMelodyMonad,
byteStringFromSchedule, runSCSynth,
HeaderFormat(..), SampleFormat(..),
) where
import qualified Haskore.Interface.SuperCollider.Schedule as Schedule
import qualified Haskore.Interface.SuperCollider.Play as Play
import Haskore.Interface.SuperCollider.SoundMap (Instrument)
import qualified Sound.SC3.Server.NRT as SCNRT
import qualified Sound.SC3.Server.PlayEasy as SCPlay
-- import Sound.OpenSoundControl.Transport (Transport)
-- import qualified Sound.OpenSoundControl.Transport.Monad as Trans
import qualified Data.ByteString.Lazy as B
import qualified Haskore.Melody as Melody
import qualified Haskore.RealTime.Timer.Immediate as TimerImmediate
import System.Cmd (rawSystem)
import System.Exit (ExitCode)
import Data.Array(Array, Ix, (!), listArray)
{- * Generate audio files for various representations of music. -}
fileFromMelody :: FilePath -> Instrument -> Melody.T () -> IO ()
fileFromMelody fileName sound =
B.writeFile fileName .
byteStringFromSchedule .
Schedule.fromMelody sound
fileFromMelodyMonad :: FilePath -> Instrument -> Melody.T () -> IO ()
fileFromMelodyMonad fileName sound =
SCPlay.withSC3File fileName .
Play.scheduleWithPlayer
(Play.messagesGrouped TimerImmediate.timer 0) .
Schedule.fromMelody sound
{- * invocation of SuperCollider program -}
data HeaderFormat = AIFF | Wave | NeXT
deriving (Read, Show, Eq, Ord, Ix, Bounded)
headerExtension :: Array HeaderFormat String
headerExtension =
listArray (minBound,maxBound) ["aiff", "wav", "au"]
headerName :: Array HeaderFormat String
headerName =
listArray (minBound,maxBound) ["AIFF", "WAVE", "NeXT"]
data SampleFormat = Int16 | Int24 | Int32 | Float | Double
deriving (Read, Show, Eq, Ord, Ix, Bounded)
sampleName :: Array SampleFormat String
sampleName =
listArray (minBound,maxBound)
["int16", "int24", "int32", "float", "double"]
{-
because there are so much parameters,
an option list would be the better choice
-}
runSCSynth ::
[String] ->
Int {- ^ number of (stereo) channels -} ->
HeaderFormat ->
SampleFormat ->
Int {- ^ sample rate -} ->
FilePath ->
IO ExitCode
runSCSynth
options numChannels headerFormat sampleFormat sampleRate fileName =
rawSystem "scsynth"
(options ++
["-D", "0", "-o", show numChannels, "-N",
fileName++".osc", "_", fileName ++ '.' : headerExtension ! headerFormat,
show sampleRate, headerName ! headerFormat, sampleName ! sampleFormat])
{- * helper functions -}
byteStringFromSchedule :: Schedule.T -> B.ByteString
byteStringFromSchedule =
SCNRT.encodeNRT .
Schedule.toStream