Saturday, April 26, 2008

Fun with Real-time Audio

Over the past week, I've had fun with real-time audio. I'd worked a bit with sound in the past, but in Python, where synthesizing audio is noticeably slow. This time, I coded in C#, which is a lot faster and has access to DirectX. I use DirectSound to put raw bytes of data right into a buffer, enabling seamless audio.

After experimentation, I came up with a program that plays a continous tone. While it is playing, you can change the pulse-width and "smoothness", creating interesting sounds. Quickly changing pulse-width creates the illusion of motion. The "smoothness" parameter goes from sine wave-like to a square wave (approximated by quadratics). As another experiment, I added a joystick interface - if you plug in a game controller and open the program, you can use the joystick to control these parameters. I encourage the reader to think of more audio effects and interfaces.

I wrote a custom control plotting the waveform, which was useful. The program also contains my implementations of waves such as square, triangle, sawtooth, white noise, red noise.

As an aside, delegates in C# are very convenient, allowing you to easily store and pass refrences to methods. What is great is that there is so little code involved. Here's an example from my sound class:

// Takes integer index, returns double between -1 and 1
delegate double SoundDelegate(int i);
double timeScale = frequency * 2 * Math.PI / (double) 44100;
SoundDelegate fn = delegate(int i)
    return Math.Sin(i * timeScale);
return create16bit_sound(fn);
Notice how the anonymous function can even keep references to variables. It's better than a Python lambda.

Here is a sample. The real thing sounds even better, the rate of updating was limited in the process of recording this sample.

I found that smooth pitch-changing for real-time audio could be complicated. If you just change pitch, you hear a lot of "clicks" - the period doesn't line up with the size of the buffer, causing a click every refresh. I sidestepped this problem by only playing frequencies that fit into the buffer, but that's not a very good solution. If I took the previous phase into account, I could fix this.

Download (Windows, .NET 2.0, DirectX9) Joystick is optional
Source GPLv3

If you want to write DirectC audio in C#,the following may help: To get the Managed DirectX dlls, I downloaded the "DirectX 9.0c Redistributable for Software Developers", ran it, and opened the resulting file. Also, using these in Visual Studio 2005, I would get an exception upon starting the program. One can disable this false excption in Debug->Exceptions->Managed Debugging Assistants, uncheck LoaderLock.


Dumuro said...

See Please Here

jowdjbrown said...

While it appears to be fairly free flowing, there is structure and form in the presentation that builds upon previous sections.projector installation toronto