[Haskell-cafe] Precise timing
Heinrich Apfelmus
apfelmus at quantentunnel.de
Sun Oct 19 07:40:26 UTC 2014
Jeffrey Brown wrote:
> An earlier version of this question is cross-posted at StackOverflow
> <http://stackoverflow.com/questions/26437770/timing-inaccuracy-in-haskell-threaddelay>
> ..
>
> What should I use for precise (and eventually, concurrency-compatible)
> timing in Haskell? I want to make rhythms. I tried the following to produce
> a repeating rhythm in which one note is twice as long as the other two.
> (That rhythm is encoded by the list [1,1,2].)
>
> import Control.Concurrent
> import Text.Printf
> import Control.Monad
>
> main = mapM_ note (cycle [1,1,2])
>
> beat = round (10^6 / 4) -- measured in microseconds
>
> note :: Int -> IO ()
> note n = do
> threadDelay $ beat * n
> printf "\BEL\n"
>
> When I run it the long note is three times as long as the others, not
> twice. If I speed it up, by changing the number 4 to a 10, the rhythm is
> destroyed completely: the notes all have the same length.
>
> threadDelay is guaranteed
> <http://hackage.haskell.org/package/base-4.7.0.1/docs/Control-Concurrent.html#v:threadDelay>
> to
> wait at least as long, but potentially longer than, what the caller
> specifies. Another potential problem could be buffering in printf.
> (Eventually I intend to replace the printf statement with OSC output to a
> sound generator.)
>
> Thanks,
> Jeff
I found that that compiling a program with the -threaded option greatly
improves the precision of threadDelay for the purpose of making rhythms.
Your program is simple enough that this shouldn't make a difference,
though. Note that there may also be issues with stdout buffering. Try
System.IO.hSetBuffering stdout NoBuffering
before the main loop.
Best regards,
Heinrich Apfelmus
--
http://apfelmus.nfshost.com
More information about the Haskell-Cafe
mailing list