[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