Real-Time Audio Generation Using WASAPI on Windows 8.1


Most of my audio coding work these days is in Flash or iOS, but I always keep an eye on other possible platforms to develop audio apps for. One of the biggies is of course Windows 8, so I figured I should at least get familiar with the basics of doing interactive real-time audio generation in a Windows 8 app, using Microsoft audio APIs.

Much to my surprise I couldn’t find a good demo app (at least when I searched a few months ago). The nearest I could find was an MSDN WASAPI sample, which is fine, but doesn’t do real-time audio generation, i.e. it doesn’t generate audio that’s calculated continuously, on-the-fly, and sent to the audio output with relatively little latency.

So I created my own (full code here), using the MSDN WASAPI sample as a starting point, stripping it down to the bare essentials for interactive audio generation. It’s a simple continuous sine tone generator, with the sine frequency adjustable via a slider. It looks like this:

SinePlayer

My code sets up a real-time audio output that calls an audio generation callback function at regular intervals. The fiddly WASAPI stuff is encapsulated in C++ AudioOutput class with a very simple interface. Basically you create the AudioOutput, initialize it with a static callback function and an object pointer.

	// Create and initialize a WASAPI renderer
	m_audioOutput = Make<AudioOutput>();
	if (m_audioOutput)
		m_audioOutput->Init(AudioOutputCallback, this);

In that static callback function, you can use the object pointer to call a non-static method of an object. In my demo, the callback function is implemented in MainPage.xaml.cpp. MainPage.xaml has a slider that sets the instantaneous frequency of the sine tone. Here’s the static callback function and the redirection to MainPage’s class method:

void MainPage::AudioOutputCallback(
	float32 *output, 
	int n, 
	int numChannels,
	int sampleRate,
	Platform::Object^ user)
{
	MainPage^ mainPage = safe_cast<MainPage^>(user);
	assert(mainPage);
	mainPage->GenerateAudio(output, n, numChannels, sampleRate);
}

And here’s MainPage’s GenerateAudio function:

void MainPage::GenerateAudio(
	float32 *output, 
	int n, 
	int numChannels, 
	int sampleRate)
{
	// Compute the phase increment for the current frequency
	assert(m_frequency != 0);
	double phaseInc = 2*M_PI*m_frequency/sampleRate;

	// Generate the samples
	for (int i = 0; i < n; i++)
	{
		float32 x = float(0.1 * sin(m_phase));
		for (int ch = 0; ch < numChannels; ch++)
			*output++ = x;
		m_phase += phaseInc;
	}

	// Bring phase back into range [0, 2pi]
	m_phase = fmod(m_phase, 2*M_PI);
}

Again, you can download a zip with the full project source code. It builds fine in Microsoft Visual Studio Express 2013 for Windows, and runs fine on Windows 8.1 running under Bootcamp on my MacBook Pro. I make no claims that it will build or run on any other configuration! If you find this code useful and adapt the code for your own projects, no attribution is necessary… but of course it’s always welcome, as are thank you notes in comments. Enjoy!

Advertisements

About Gerry Beauregard

I'm a Singapore-based Canadian software engineer, inventor, musician, and occasional triathlete. My current work and projects mainly involve audio technology for the web and iOS. I'm the author of AudioStretch, an audio time-stretching/pitch-shifting app for musicians. Past jobs have included writing speech recognition software for Apple, creating automatic video editing software for muvee, and designing ASICs for Nortel. I hold a Bachelor of Applied Science (Electrical Engineering) from Queen's University and a Master of Arts in Electroacoustic Music from Dartmouth College.
This entry was posted in Uncategorized. Bookmark the permalink.

6 Responses to Real-Time Audio Generation Using WASAPI on Windows 8.1

  1. Viktor says:

    Thank you, this is exactly what I was looking for.

  2. Tim Miltz says:

    When I run this, Studio 2013 says can not open include file App.g.h No such file or directory.
    Also with MainPage.g.h

    Any thoughts if these headers were missing in the zip?

    Thanks

    Tim Miltz

    • It builds and runs fine for me using Visual Studio 2015 running in Windows 10 (in turn running in VMWare Fusion on my Mac). So not sure why it doesn’t work for you. You might want to choose Build / Clean Solution, then try building and running again. Files with a “.g” in the filename are supposed to be generated during the build process.

  3. Arunraj says:

    Hi Gerry,

    Is it possible to play AAC data supplying through GenerateAudio() method?

    Thanks
    Arunraj

    • Should be possible, though I don’t know offhand what the Microsoft APIs are for doing that. If you’re reading the AAC only sequentially and forward, you can probably do the decoding on-the-fly in the audio callback.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s