#WEBWONDERS : The world of web audio

TMS Software Delphi  Components

A new year and yet another new theme for blog articles. After #GRIDGOODIES and #FREEBIEFRIDAY, this is a new theme we introduce with #WEBWONDERS. In these blogs, we explore the wonderful world of the browser operating system and uncover hidden or not so hidden treasures, tips and tricks.

So, let’s kick of this new series with exploring the world of web audio. Modern browsers make the web audio API available. The goals of the web audio API are mixing sound, generating sound and applying effects to sound from web applications. 
TMS WEB Core includes the Pascal import unit for using the web audio API from our beloved language. This unit is in the RTL subfolder that contains all units for several different browser APIs.

So, in this blog, we let you explore the web audio API with a small code snippet that shows how you can create your own audio wave and have it played through the speakers of the device. The most straightforward is to create a sound through a sine wave with variable frequency. While technically, the web audio API comes with oscillator objects that could generate this, in this sample, we will use Pascal code for creating the buffer that will hold the sine wave. It is this buffer of floats (TJSFloat32Array) that will be played. The only part of the code where we need to use JavaScript is for the creation of the audio context. This is because there is a subtle difference between the creation on Chromium based browsers and webkit based browsers. So, basically the JavaScript code tries the webkit based creation if the Chromium based creation failed.

So, the Pascal function to do this is:

procedure playfreq(freq, volume: double);
var
  ctx: TJSAudioContext;
  buf: TJSAudioBuffer;
  wave: TJSFloat32Array;
  i,len: integer;
  src: TJSAudioBufferSourceNode;
  sampleFreq: double;

begin
  // connect to the browser window Audio Context. 
  asm
    ctx = new (window.AudioContext || window.webkitAudioContext)();
  end;

  // get the sample frequency the audio context can use 
  len := round(ctx.sampleRate);

  // create a new buffer of floating point values
  wave := TJSFloat32Array.new(len);

  // determine the sine wave frequency in relation to the audio context sample frequency
  sampleFreq := ctx.sampleRate / freq;

  // create a buffer on the audio context
  buf := ctx.createBuffer(1, len, ctx.sampleRate);
  wave := buf.getChannelData(0);

  // fill the float array with the sine wave data taking frequency & volume in account
  for i := 0 to len - 1 do
    wave[i] := (volume /100) * sin(i/(samplefreq/(2*PI)));

  // create a buffer source object for the audio contect
  src := ctx.createBufferSource();

  // assign the buffer holding the wave to the audio buffer source object
  src.buffer := buf;

  // connect the audio buffer source object to the audio context output
  src.connect(ctx.destination);

  // play the sample from position 0
  src.start(0.0);
end;

With this Pascal routine, it becomes simple to put two TWebTrackBar components on the form that allow to select the frequency and the volume and add a button to play the sound. With a frequency selectable between 20Hz en 20000Hz and volume between 0% and 100%, you have a little web application to test your ears frequency range or speaker frequency range, whatever fails first.

TMS Software Delphi  Components
You can experiment with the web application here

Curious about web technology? Or you have interesting challenges to accomplish in a web application, let us hear what you want to see covered in a next #WEBWONDERS blog!