[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