
I think it would be much easier to take a different approach. For example one of these: * Use an audio library * Write your own audio synthesis John Lato already said something about the usual approach to audio software. I will just sketch out how to write very simple audio synthesis: * You need a sample rate! * Think in terms of a modular audio synthesizer * Write your own oscillator. * Write an "amplifier", which scales the oscilators amplitude up and down. Whenever you want the oscilator to not make sound you have to mute the amplifier. * Write an envelop generator, which generates an envelop for your amplifier. * Write a sequencer, which controlls the envelop generator. The sequencer should take your prefered encoding (like 'cycle [1,1,2]') * Write the output of the amplifier straight into the audio-out buffer of your OS. I don't know how you do that exactly. You have to find out. But I do know that on Linux you could also just write the output of your program to standard-out and pipe it into ALSA on the command line with the padsp command. Advantages of this approach: * IO-Monad is used only on the highest level of abstraction. * If you write straight into the audio-out buffer of your OS, the OS will suspend and schedule your process as needed. Whenever the audio-out buffer is full, your process will be blocked by the OS on the write system call. You don't have to think much about scheduling. * it's easy. Most of the components could be a single and simple function. Just my 2 cents, Alexander On 10/22/2014 05:14 AM, Jeffrey Brown wrote:
On a separate thread http://haskell.1045720.n5.nabble.com/How-to-send-a-string-somewhere-via-UDP-..., Rohan Drape showed me how to send OSC. The following test, which simplifies the old one and replaces printf with OSC, demonstrates timing as perfect as my ears are able to distinguish.
import Control.Concurrent import Control.Monad import System.IO import Sound.OSC main = do hSetBuffering stdout NoBuffering mapM_ note (cycle [1,1,2]) withMax = withTransport (openUDP "127.0.0.1" 9000) beat = 60000 -- 60 ms, measured in µs note :: Int -> IO () note n = do withMax (sendMessage (Message "sin0 frq 100" [])) -- set sine wave 0 to frequency 100 withMax (sendMessage (Message "sin0 amp 1" [])) -- set sine wave 0 to amplitude 1 threadDelay $ beat * n withMax (sendMessage (Message "sin0 amp 0" [])) -- set sine wave 0 to amplitude 0 threadDelay $ beat * n
This means I can use Haskell instead of Python or SuperCollider. I am beside myself with excitement.
Thanks again, everyone!
On Tue, Oct 21, 2014 at 2:24 AM, Brandon Allbery
mailto:allbery.b@gmail.com> wrote: On Tue, Oct 21, 2014 at 4:05 AM, Heinrich Apfelmus
mailto:apfelmus@quantentunnel.de> wrote: I would be hesitant to attribute your problem to the scheduler. An alternative explanation could be the following: The sound file played by the terminal when it encounters the \BEL character is longer than 100ms. A new sound will be played only when the previous sound has finished playing,
On most systems I've used, this isn't true; they're either suppressed or they overlap, depending on system. (I've had to work around this.)
-- brandon s allbery kf8nh sine nomine associates allbery.b@gmail.com mailto:allbery.b@gmail.com ballbery@sinenomine.net mailto:ballbery@sinenomine.net unix, openafs, kerberos, infrastructure, xmonad http://sinenomine.net
_______________________________________________ Haskell-Cafe mailing list Haskell-Cafe@haskell.org mailto:Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
_______________________________________________ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe