-- Hoogle documentation, generated by Haddock -- See Hoogle, http://www.haskell.org/hoogle/ -- | Routines for realtime playback of Haskore songs -- -- This package contains support for realtime playback of Haskore songs. -- However this does not work satisfyingly and it introduces dependencies -- like on unix package, that reduce portability. Thus we have -- removed this part from core Haskore. @package haskore-realtime @version 0.2 -- | replace functionality of shell-pipe package module Haskore.RealTime.ShellPipe launch :: FilePath -> [String] -> IO (Handle, Handle, Handle) -- | This module uses a pipe in order to play CSound music without a -- temporary score file. A temporary orchestra file is necessary, though. -- -- In my tests on a SuSE Linux only CSound5 (but not CSound4) could play -- via '-odac'. module Haskore.Interface.CSound.Play play :: Output out => T out -> T -> IO () scorePipe :: FilePath tmpWave :: FilePath playV4 :: Output out => FilePath -> (Name, T out, T) -> IO () playV5 :: Output out => FilePath -> (Name, T out, T) -> IO () playNamedPipe :: Output out => (String, String) -> FilePath -> Name -> T out -> T -> IO () playV5NamedPipe :: Output out => FilePath -> (Name, T, T out) -> IO () playV4NamedPipe :: Output out => FilePath -> (Name, T, T out) -> IO () playV4AnonymousPipe :: Output out => FilePath -> (Name, T, T out) -> IO () -- | This module used shell-haskell and a pipe in order to play MIDI music -- without temporary files. Today it uses runInteractiveProcess. -- -- I got this running only with GHC and Linux so far. Though it is not -- satisfying. It seems that timidity forks itself away so that -- it doesn't block the prompt of Haskell. I assume that because -- sometimes ghci tries to write to the pipe before timidity can -- read it. Interestingly if I start timidity with an input pipe -- from the console it stays synchronously. -- -- Some music seems to be to large, maybe larger than a pipe buffer, then -- the buffer runs over and the replay fails. E.g. ChildSong6 is short -- enough, Kantate147 is too long. -- -- Using a pipe is the only way to play infinite streams of music using -- an external program. It is no problem to control a MIDI device over an -- unlimited time, but unfortunately the MIDI file format uses absolute -- time points and a file length value. Thus it is not possible to play -- infinite MIDI streams via the MIDI file format! For better realtime -- support on Linux look at the alsa-midi package. module Haskore.Interface.MIDI.Play play :: (Ord instr, Ord drum, C time, RealFrac time, Fractional time, RealFrac dyn) => (ChannelProgramPitchTable drum, ChannelProgramTable instr, T time dyn (Note drum instr), T drum instr) -> IO () playSimple :: T -> IO () module Haskore.RealTime.Timer data T m Cons :: m ClockTime -> (Int -> m ()) -> Integer -> T m getClockTime :: T m -> m ClockTime waitInt :: T m -> Int -> m () resolution :: T m -> Integer lift :: (MonadTrans t, Monad m) => T m -> T (t m) liftIO :: MonadIO io => T IO -> T io getTime :: Monad m => T m -> m Integer clockTimeToWaitTime :: Integer -> ClockTime -> Integer getTimeSeconds :: (Fractional time, Monad m) => T m -> m time clockTimeToSeconds :: Fractional time => ClockTime -> time wait :: Monad m => T m -> Integer -> m () waitUntil :: Monad m => T m -> Integer -> m () waitUntilSeconds :: (RealFrac time, Monad m) => T m -> time -> m () -- | This timer doesn't wait but returns immediately. This is useful for -- turning real-time processing to non-real-time processing. module Haskore.RealTime.Timer.Immediate timer :: Monad m => T m module Haskore.RealTime.Timer.Thread timer :: T IO module Haskore.RealTime.Timer.Posix timer :: T IO -- | Apply actions to event lists (starting with time, ending with body) at -- given times. module Haskore.RealTime.EventList.TimeBody data T time body :: * -> * -> * mapBodyM :: Monad m => (body0 -> m body1) -> T time body0 -> m (T time body1) mapM :: Monad m => (time0 -> m time1) -> (body0 -> m body1) -> T time0 body0 -> m (T time1 body1) mapM_ :: Monad m => (time -> m ()) -> (body -> m ()) -> T time body -> m () getBodies :: T time body -> [body] mapBody :: (body0 -> body1) -> T time body0 -> T time body1 mapTime :: (time0 -> time1) -> T time0 body -> T time1 body mapTimeTail :: (T time body0 -> T time body1) -> T time body0 -> T time body1 empty :: T time body singleton :: time -> body -> T time body null :: T time body -> Bool viewL :: T time body -> Maybe ((time, body), T time body) viewTimeL :: T time body -> Maybe (time, T time body) viewBodyL :: T time body -> (body, T time body) cons :: time -> body -> T time body -> T time body snoc :: T time body -> time -> body -> T time body consBody :: body -> T time body -> T time body consTime :: time -> T time body -> T time body append :: T time body -> T time body -> T time body concat :: [T time body] -> T time body cycle :: T time body -> T time body -- | insert inserts an event into an event list at the given time. insert :: (C time, Ord body) => time -> body -> T time body -> T time body decreaseStart :: C time => time -> T time body -> T time body delay :: C time => time -> T time body -> T time body partition :: C time => (body -> Bool) -> T time body -> (T time body, T time body) foldr :: (time -> a -> b) -> (body -> b -> a) -> b -> T time body -> b -- | Using a classification function we splice the event list into lists, -- each containing the same class. Absolute time stamps are preserved. slice :: (Eq a, C time) => (body -> a) -> T time body -> [(a, T time body)] -- | sort sorts a list of coinciding events, that is all events but -- the first one have time difference 0. normalize sorts all -- coinciding events in a list thus yielding a canonical representation -- of a time ordered list. normalize :: (C time, Ord body) => T time body -> T time body -- | Group events that have equal start times (that is zero time -- differences). collectCoincident :: C time => T time body -> T time [body] -- | Reverse to collectCoincident: Turn each body into a separate -- event. -- --
--   xs  ==  flatten (collectCoincident xs)
--   
flatten :: C time => T time [body] -> T time body -- | Apply a function to the lists of coincident events. mapCoincident :: C time => ([a] -> [b]) -> T time a -> T time b resample :: (C time, RealFrac time, C i, Integral i) => time -> T time body -> T i body -- | We tried hard to compute everything with respect to relative times. -- However sometimes we need absolute time values. toAbsoluteEventList :: Num time => time -> T time body -> T time body -- | The next set of routines is more precise. It computes a time table -- starting with current system time and tries to stick to it. -- -- So far, I worked hard to use time differences instead of absolute -- times in order to avoid increasing memory consumption of time numbers -- (which however slows down as time evolves) but the time related -- functions of the system are absolute, so have to make our ones -- absolute as well. run :: (RealFrac time, Monad m) => T m -> (body -> m a) -> T time body -> m [a] -- | The wait calls are necessarily quantized, but the time passed to the -- action is not quantized. runTimeStamp :: (RealFrac time, Monad m) => T m -> (time -> body -> m a) -> T time body -> m [a] -- | This routine is only necessary, because differences might be too small -- to be noticed in the absolute time values. That is, collectCoincident -- will split events which actually belong together. runTimeStampGrouped :: (RealFrac time, Monad m) => T m -> (time -> [body] -> m a) -> T time body -> m [a] runCore :: (Fractional time0, RealFrac time1, Monad m) => (T time0 body0 -> T time1 body1) -> T m -> (time1 -> body1 -> m a) -> T time0 body0 -> m [a] -- | The first function assumes, that the action does not consume time and -- that the wait command is precise. It is not very useful in practice, -- but very simple. runRelative :: (C time, RealFrac time, Monad m) => T m -> (body -> m a) -> T time body -> m [a] runRelativeCore :: Monad m => T m -> (body -> m a) -> T Integer body -> m [a] -- | We export this function only for use in -- Haskore.RealTime.EventList.TimeTime. attachTime :: T time body -> T time (time, body) -- | Apply actions to event lists (starting with time, ending with time) at -- given times. module Haskore.RealTime.EventList.TimeTime data T time body :: * -> * -> * mapBody :: (body0 -> body1) -> T time body0 -> T time body1 mapTime :: (time0 -> time1) -> T time0 body -> T time1 body mapM :: Monad m => (time0 -> m time1) -> (body0 -> m body1) -> T time0 body0 -> m (T time1 body1) mapM_ :: Monad m => (time -> m ()) -> (body -> m ()) -> T time body -> m () empty :: T time body pause :: time -> T time body -- | The first important function is merge which merges the events -- of two lists into a new time order list. merge :: (C time, Ord body) => T time body -> T time body -> T time body -- | Note that merge compares entire events rather than just start -- times. This is to ensure that it is commutative, a desirable condition -- for some of the proofs used in Haskore/section equivalence. It is also -- necessary to assert a unique representation of the event list -- independent of the structure of the event type. The same function for -- inserting into a time ordered list with a trailing pause. insert :: (C time, Ord body) => time -> body -> T time body -> T time body decreaseStart :: C time => time -> T time body -> T time body delay :: C time => time -> T time body -> T time body -- | Analogously to the concat / concatNaive pair we have to -- versions of filter, where the clever implementation sums up -- pauses from the beginning to the end. filter :: C time => (body -> Bool) -> T time body -> T time body foldr :: (time -> a -> b) -> (body -> b -> a) -> a -> T time body -> b viewTimeL :: T time body -> (time, T time body) viewBodyL :: T time body -> Maybe (body, T time body) viewTimeR :: T time body -> (T time body, time) viewBodyR :: T time body -> Maybe (T time body, body) cons :: time -> body -> T time body -> T time body consBody :: body -> T time body -> T time body consTime :: time -> T time body -> T time body snoc :: T time body -> body -> time -> T time body snocBody :: T time body -> body -> T time body snocTime :: T time body -> time -> T time body mapTimeL :: (time -> time, T time body0 -> T time body1) -> T time body0 -> T time body1 mapTimeHead :: (time -> time) -> T time body -> T time body mapTimeTail :: (T time body0 -> T time body1) -> T time body0 -> T time body1 mapBodyL :: (body -> body, T time0 body -> T time1 body) -> T time0 body -> T time1 body mapBodyHead :: (body -> body) -> T time body -> T time body mapBodyTail :: (T time0 body -> T time1 body) -> T time0 body -> T time1 body mapTimeR :: (T time body0 -> T time body1, time -> time) -> T time body0 -> T time body1 mapTimeLast :: (time -> time) -> T time body -> T time body mapTimeInit :: (T time body0 -> T time body1) -> T time body0 -> T time body1 mapBodyR :: (T time0 body -> T time1 body, body -> body) -> T time0 body -> T time1 body mapBodyLast :: (body -> body) -> T time body -> T time body mapBodyInit :: (T time0 body -> T time1 body) -> T time0 body -> T time1 body -- | Adds times in a left-associative fashion. Use this if the time is a -- strict data type. catMaybes :: C time => T time (Maybe body) -> T time body append :: C time => T time body -> T time body -> T time body concat :: C time => [T time body] -> T time body -- | concat and concatNaive are essentially the same. -- concat must use foldr in order to work on infinite -- lists, however if there are many empty lists, summing of their -- durations will be done from right to left, which is inefficient. Thus -- we detect subsequent empty lists and merge them from left to right. concatNaive :: C time => [T time body] -> T time body resample :: (C time, RealFrac time, C i, Integral i) => time -> T time body -> T i body toAbsoluteEventList :: Num time => time -> T time body -> T time body run :: (RealFrac time, Monad m) => T m -> (body -> m a) -> T time body -> m [a] runTimeStamp :: (RealFrac time, Monad m) => T m -> (time -> body -> m a) -> T time body -> m [a] runTimeStampGrouped :: (RealFrac time, Monad m) => T m -> (time -> [body] -> m a) -> T time body -> m [a] runRelative :: (C time, RealFrac time, Monad m) => T m -> (body -> m a) -> T time body -> m [a] collectCoincident :: C time => T time body -> T time [body] flatten :: C time => T time [body] -> T time body mapCoincident :: C time => ([a] -> [b]) -> T time a -> T time b