Web Audio Sine Tone Generator


I’ve seen some very impressive examples of what can be done with the Web Audio API. Great for inspiration, but for learning a new API, personally I prefer examples that are stripped down to the bare essentials. With that in mind, I’ve created an ultra-simple sine tone generator, the full source code for which can be found below.

You can try it here.

Update 13 June 2012: Safari Version 6.0 (7536.16) supports the Web Audio API! For the sine tone example to work, however, NUM_INPUTS must be set to 1 or 2; if it’s 0, you’ll get a horrible, incredibly loud buzzing noise. Many thanks to my friend Kumar (Srikumar Karaikudi Subramanian) for the fix!



<!DOCTYPE HTML>
<html>
	<head>
		<title>WebAudioAPI Example</title>

			<script>
			
				// Ultra-simple example using the WebAudio API to generate a sine tone.
				//
				// It's a radical simplication of an example here:
				//	http://0xfe.blogspot.com/2011/08/generating-tones-with-web-audio-api.html
				// 
				// See also WebAudio API specification here:
				// https://dvcs.w3.org/hg/audio/raw-file/tip/webaudio/specification.html
				//
				// Gerry Beauregard, March 2012
			
				// Audio generation function			
				function generateAudio(e) 
				{
					// Get the left and right output buffers
					var left  = e.outputBuffer.getChannelData(0);
					var right = e.outputBuffer.getChannelData(1);
					
					// For each output sample
					var numSamples = right.length;
					for (var i = 0; i < numSamples; i++) 
					{
						// Get a sine wave value
						var val = 0.1 * Math.sin(currentPhase);
						
						// Put it in the left and right buffer
						left[i] = val;
						right[i] = val;
						
						// Increment the phase
						currentPhase += phaseIncrement;
					}
				}
				
				// ---------------------
				
				// Some constants...
				
				// Number of samples to generate on each call to generateAudio.
				// Legal values are 256, 512, 1024, 2048, 4096, 8192, 16384.				
				const BUFFER_SIZE = 1024; 					
				
				// Number of output channels. We want stereo, hence 2 (though 1 also works??).
				const NUM_OUTPUTS = 2;		

				// We only want to *generate* audio, so our node has no inputs.
				//const NUM_INPUTS = 0; Results in horrible noise in Safari 6
				const NUM_INPUTS = 1; // Works properly in Safari 6 
				
				// Frequency of the sine tone.			
				const SINE_FREQ = 440;
				
				// Create the audio context
				var context = new webkitAudioContext();
				
				// Create a source node
				var node = context.createJavaScriptNode(BUFFER_SIZE, NUM_INPUTS, NUM_OUTPUTS);
				
				// Specify the audio generation function
				node.onaudioprocess = generateAudio;
				
				// Set up the per-sample phase increment based on the desired 
				// sine tone frequency and the sample rate of the audio context.
				var currentPhase = 0.0;
				var phaseIncrement = 2 * Math.PI * SINE_FREQ / context.sampleRate;
				
				// Connect the node to a destination, i.e. the audio output.
				node.connect(context.destination);
				
			</script>
	</head>
	
	<body>
		<h1>WebAudioAPI Example</h1>
		<p>If this is working properly, you should hear a 440 Hz sine tone.<br>
		As of this writing (30 March 2012), this demo only<br>
		works in Google Chrome and nightly builds of Safari.</p>
	</body>
</html>

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 Audio, Programming and tagged . Bookmark the permalink.

9 Responses to Web Audio Sine Tone Generator

  1. Dmitr says:

    I tried on sfari 5.1 on macbook and Chrome and Firedox (latest auto update) on XP SP4
    It does not work! What version I need and where to download it?

    • Works for me with the latest build of Chrome (18.0.1025.168) running on my MacBook Pro with OS 10.7.3. I haven’t tested on any other platforms, but it should work with nightly builds of Safari/Webkit nightly builds (http://nightly.webkit.org/). If it doesn’t work, check for errors using the developer tools within the browser (e.g. in Chrome go to View/Developer/Javascript Console). It almost definitely will not work with Firefox, as it doesn’t implement the Web Audio API.

  2. When I play it, it sounds bubbly and distorted. Any thoughts on how to make it sound smoother? I am running it in Chromium on Ubuntu Precise Pangolin. …Nevermind I figured it out. Just had to up the BUFFER_SIZE. Thank you for the awesome post. You can check out my super sweet project on Cloud9 the online IDE http://c9.io/israfel/music 🙂

    ~Travel on my friend

  3. Would you also implement the audiostretch in javascript (using the webaudio api); so flash in no longer needed 🙂

    It’s certainly possible, but there’s not a lot of incentive to do it… -Gerry

  4. keghn says:

    hello.
    http://www.audiostretch.com/webaudiosine/ work fin. but in a terminal i use:

    mplayer http://www.audiostretch.com/webaudiosine/

    i get:

    Couldn’t resolve name for AF_INET6: http://www.audiostretch.com
    Resolving http://www.audiostretch.com for AF_INET…
    Connecting to server http://www.audiostretch.com[69.5.11.16]: 80…

    Cache size set to 320 KBytes
    Cache fill: 0.80% (2619 bytes)

    libavformat version 53.21.1 (external)
    Mismatching header version 53.19.0

    • Thanks for checking out the example. Can’t really help you with the errors you’re getting, as I’m not familiar with mplayer. In any case, the Web Audio API is really designed for use on web pages in web browsers, and my simple example does work in that context, at least with Safari and Chrome on MacOS. I make no promises for other platforms! 🙂

      • keghn says:

        O.k.
        I came across your web site when I was looking for web site that just stream pure
        tone sine wave for testing out software. If I use a music station and get wild distortion
        while trouble shooting a program it little help.

        Thanks for any help. Like your site.
        keghn

  5. Tyler says:

    I’m finding that performance with ScriptProcessorNodes is really lacking compared to Flash, especially on mobiles. I’ve only tested on Android, an NVidia Shield Tablet with the Tegra K1 (which is about the fastest Android device available), but the result isn’t promising. Where I could get dozens of simultaneous voices in Flash, I can’t get 3 in JS on mobile. I’m going to have to try to rewrite it to simply spawn a unique AudioBufferSourceNode for each note so that I can rely on less JS code execution. I’m afraid that applications which truly require script processing might just not be doable on the mobile web right now. If you’ve found any strategies to improve performance, I’d love to hear them.

    • I haven’t used WebAudio much at all recently, in part because it’s not supported by Internet Explorer, and also because the standards were still evolving. From what I’ve read/heard, there will be major improvements on both fronts in 2015. As for mobile, I stick to compiled C++ all the way, as Flash is very poorly supported.

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