[Haskell-cafe] Precise timing

Jeffrey Brown jeffbrown.the at gmail.com
Sun Oct 19 18:50:32 UTC 2014


Thanks, everybody! Those were incredibly informative answers. This list is
amazing.

Heinrich's suggestion of compiling with "-threaded" was by itself
sufficient to get the first rhythm to sound right.

The second rhythm, however, still blurs into a string of beeps of the same
duration even after I throw all of Heinrich's and Carter's suggestions at
it by doing this:

ghc --make fast -threaded -fno-omit-yields -with-rtsopts -C0

(although I should admit to not really knowing what I'm doing when I run
that) where fast.hs is this:

import Control.Concurrent
import Text.Printf
import Control.Monad
import System.IO
 main = do
hSetBuffering stdout NoBuffering
mapM_ note (cycle [1,1,2])
 beat = round (10^6 / 10) -- measured in microseconds
 note :: Int -> IO ()
note n = do
threadDelay $ beat * n
printf "\BEL\n"

I therefore suspect I have to teach myself, as Brandon suggested, a
realtime scheduler. This seems like a general, powerful thing:
http://hackage.haskell.org/package/atom
Hayoo also returns a lot of domain-specific results, e.g. from the Sound
and Data.Reactive libraries:
http://hackage.haskell.org/package/alsa-0.4/docs/Sound-Alsa-Sequencer.html
http://hackage.haskell.org/package/midi-0.2.1.3/docs/Sound-MIDI-Message-System-RealTime.html#
http://hackage.haskell.org/package/definitive-reactive-1.0/docs/Data-Reactive.html
but I suspect a general tool like Atom would be more useful so I'll start
there.

Thanks again,
Jeff


On Sun, Oct 19, 2014 at 12:40 AM, Heinrich Apfelmus <
apfelmus at quantentunnel.de> wrote:

> 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
>
>
> _______________________________________________
> Haskell-Cafe mailing list
> Haskell-Cafe at haskell.org
> http://www.haskell.org/mailman/listinfo/haskell-cafe
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://www.haskell.org/pipermail/haskell-cafe/attachments/20141019/6d9631a5/attachment.html>


More information about the Haskell-Cafe mailing list