INTRODUCTION:
The audible range for humans is 20Hz to 20KHz. We can easily generate these frequencies using Javascript and then play them and see which one of those can we hear. This blog will show a very sample way of tone generation. Just make sure when testing, the volume is at a reasonable level. The signal will become audible abruptly so be prepared and don’t get a shock!
Signal Processing
Let's talk about some signal processing first. Since the maximum frequency of interest is 20KHz it becomes the Nyquist Frequency. The data thus needs to be generated at least at twice the Nyquist Rate which is 2*20KHz = 40KHz. Assuming this to be our sampling rate denoted by Fs, the duration between each sample of data is 1/Fs seconds. If we want the duration of generated frequency to be 2 seconds, we need 2/(1/Fs) = 2Fs number of data samples. If the desired frequency to be generated is f, then the nth sample value is found using the equation:
X[n]=sin(2*pi*f*1/Fs*n)
Web Audio API
Javascript has a Web Audio API library that has “AudioContext” interface that provides a route to a device. That device then produces the signal to the user. So first we need to create a variable of “AudioContext” type
var audioContext = new AudioContext();
AudioContext has a read-only attribute of sampling rate which is based on the device. Generally, this value is 44.1KHz. We will use this as sampling rate for generation of our signal. AudioContext also provides a read only destination attribute that represents the actual audio hardware. To play the audio via this destination, a source node needs to be connected to it. The source node should contain the buffer with the desired data. The following function achieves these.
function playFrequency(frequency) { // create 2 second worth of audio buffer, with single channels and sampling rate of your device. var sampleRate = audioContext.sampleRate; var duration = 2*sampleRate; var numChannels = 1; var buffer = audioContext.createBuffer(numChannels, duration, sampleRate); // fill the channel with the desired frequency's data var channelData = buffer.getChannelData(0); for (var i = 0; i < sampleRate; i++) { channelData[i]=Math.sin(2*Math.PI*frequency*i/(sampleRate)); } // create audio source node. var source = audioContext.createBufferSource(); source.buffer = buffer; source.connect(audioContext.destination); // finally start to play source.start(0); }
Test
In order, to test it we can quickly create a simple html page with a text box to read the desired frequency and a “Play” button to play the tone.
<html> <head> <title>Tone Generator</title> <link rel='stylesheet' href='/stylesheets/style.css' /> <script type="text/javascript" src="/javascripts/library/jquery-2.1.4.min.js"></script> <script type="text/javascript" src="/javascripts/library/jquery.backTop.min.js"></script> </head> <script src="/javascripts/index1.js" type="text/javascript"></script> <body> Frequency to play(Hz): <input type="text" name="frequency" id="frequency" value="1000"/><br> <button class=button id="start-button" title="Play">Play</button> </body> </html>
We can have the following code to call our “playFrequency” function when the “Play” button is clicked.
$(document).ready(function () { $(document).on("click", "#start-button", function(e) { playFrequency(document.getElementById("frequency").value); }) });
There is a lot more that one can do with Web Audio API. There are built-in oscillators that can be used to generate signals. The signal can be ramped up or down in a smoother fashion. In this blog I have just shown a vary simple of generating a tone. Enjoy playing around with it.
To learn about how Agile Trailblazers can deliver working software, check out our Agile Software Delivery page.