Saturday, March 8, 2014

Audio and Ruby

I'm working on a gem which will make songs for me.  This may be a pie-in-the-sky dream, but I'm still working on it.  One thing I need is to be able to play arbitrary digital signals to a sound device.  A cursory google search will show that there is a gem to do just this!

gem install win32-audio

And then all you have to do is load up the gem, and make a native system call to make a beep.

require 'win32/sound'
include Win32
Sound.beep(440, 500)

This code will play a 440Hz tone for 500 millisecond.  But there's a problem.  It's synchronous. I need to be able to play multiple tones at once, or even be able to mix some signals and stream the result to a sound device.

The win32-audio uses the ffi gem to do its dirty work, so I've decided to jump in and do the same.

My plan is to code up a gem (or an extension to win32-audio) which makes native calls to the waveOut multimedia library in windows.  Hopefully then I'll be able to shove in arbitrary PCM signal to a sound device of my choosing, and even with as many channels as I'd like!

It's basically this:

1. waveOutOpen to open up a device for streaming
2. waveOutPrepareHeader to prepare a block of audio for playback
3. waveOutWrite to submit the prepared audio to the device for playing
4. waveOutClose to close up the stream when I'm done

As much as I wish it was simple to just define these four functions in ffi, it gets a little more hairy.  Of course, I have to go in and define and set up memory management for the underlying code which relies on various structs like WAVEFORMATEX and WAVEHDR.

Wish me luck!

No comments:

Post a Comment