Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do i use AudioContext in WebAudio

I'm trying to create a way to generate sounds in sms. This gives me a "Cannot call method 'createScriptProcessor' of null" ?

Is the JAudioContext supposed to be created ?

...

AudioContext  : JAudioContext;
node          : JScriptProcessorNode;

...

procedure TForm1.W3Button1Click(Sender: TObject);
var bufferSize : integer;
    lastOut : float;
    input,output : JFloat32Array;
begin
  bufferSize := 4096;
  lastOut := 0;
  node := AudioContext.createScriptProcessor(bufferSize, 1, 1);
  node.onaudioprocess := procedure (e: JAudioProcessingEvent)
  var i : integer;
  begin
    input := e.inputBuffer.getChannelData(0);
    output := e.outputBuffer.getChannelData(0);
    for i := 0 to bufferSize-1 do
    begin
      output[i] := (input[i] + lastOut) / 2.0;
      lastOut := output[i];
    end;
  end;
end;
like image 424
Flemming Avatar asked Mar 31 '14 17:03

Flemming


1 Answers

At the moment you still need some JavaScript workaround to get the audio context created.

Something like

var AudioContext: JAudioContext;

procedure InitializeAudioContext;
begin 
  asm
    // Fix up for prefixing
    window.AudioContext = window.AudioContext||window.webkitAudioContext;

    if('webkitAudioContext' in window) {
      @AudioContext = new webkitAudioContext();
     }
  end;
end;

Note: The unit w3c.WebAudio is basically just a wrapper for the W3C API and does not contain code to get the audio context initialized. So far this has to be done (as shown above) in your code.

For the future we plan to have some higher level abstraction.

The upcoming version 2.1 will contain another featured example about the Web Audio API and an improved 'Sine Generator' example. It is planned to be released in April/May.

Update 1:

Alternatively you can instantiate your context using this code:

AudioContext := new JAudioContext;

However, it does not work for older webkit based browsers. These need an additional webkit prefix.

In this case something like:

type
       JWebkitAudioContext = class external 'webkitAudioContext' (JAudioContext);

AudioContext := new JWebkitAudioContext;

would work.

For compatibility reasons, you may need to check whether the prefix is necessary or not. Or just use the "asm" snippet posted above.

Update 2:

Eric just wrote me an email about how to do the check in Pascal code. While it is still a bit ugly, it avoids the asm section.

First declare the webkitAudioContext and then check if it's assigned:

var webkitAudioContext external 'webkitAudioContext' : JwebkitAudioContext;
var hasWebkitAudio := Boolean(Variant(webkitAudioContext));
like image 107
CWBudde Avatar answered Oct 19 '22 08:10

CWBudde