- From: Chris Rogers <crogers@google.com>
- Date: Tue, 13 Jul 2010 12:25:40 -0700
- To: Corban Brook <corbanbrook@gmail.com>
- Cc: Ricard Marxer Piñón <ricardmp@gmail.com>, public-xg-audio@w3.org
- Message-ID: <AANLkTikjkvR442wLNnuIXMQXfbEBLS6yGqGv8iaKFK2V@mail.gmail.com>
Hi Corban,
In the provisional specification I've been working on with Apple, an audio
element has an "audioSource" attribute. But an audio element is not also
considered to be a destination. The only destination is the AudioContext's
destination. Consider if you have multiple sources (multiple audio elements
perhaps) but you want to create a mixer and apply an effect like reverb on
all three sources. Then each source can share the reverb effect and route
the rendered audio to a single destination.
Here's your example with a few changes:
var context = new AudioContext();
var lowpass = context.createLowPass2Filter();
var audio = document.getElementById('audioElement');
function setupAudioFilter() {
var source = audio.audioSource; // notice the audio element has this new
attribute
source.connect(lowpass);
lowpass.connect(context.destination);
}
As soon as you start playing the audio element, it will be heard through the
lowpass filter.
But this isn't what you want for JavaScript processing, because this code
will setup a routing graph which will do native processing (for example, the
filter is run using native code).
I think what you guys are interested in right now is how to do the actual
DSP in JavaScript. So here's what I would suggest for that. I just made up
the API for this with the idea that there would be a JavaScriptProcessorNode
which invokes a callback function (called process() in this example). I'm
pretty sure this will work and can be a good starting point for the API, but
we'll need to refine and perfect it.
var context;
var jsProcessor;
function init() {
context = new AudioContext();
}
function setupJavascriptProcessing() {
jsProcessor = context.createJavaScriptProcessor();
jsProcessor.onprocess = process;
var audio = document.getElementById('audioElement');
audio.audioSource.connect(jsProcessor);
jsProcessor.connect(context.destination);
}
// This function gets called periodically to process a single buffer's worth
of audio
function process(event) {
// For this example, let's assume inputSamples and outputSamples are
stereo interleaved, although I'd like
// to move to an API where these are non-interleaved. This is a detail
we can discuss later.
var inputSamples = event.inputSamples; // a Float32Array
var outputSamples = event.outputSamples; // a Float32Array
var n = event.numberOfSampleFrames; // number of sample-frames (for
example 4096 left and right samples)
// DSP magic here where you would process n sample-frames from
inputSamples -> outputSamples...
// We might need to have a commit() method (or something) here at the
end - hopefully not though...
event.commit();
}
Let me know if this makes sense.
Cheers,
Chris
On Tue, Jul 13, 2010 at 9:38 AM, Corban Brook <corbanbrook@gmail.com> wrote:
> Hello Chris,
>
> Had another chance to go over your api today. I am going to be making a
> javascript layer implementation of your spec which will work on top of the
> mozilla audio data api.
> This should allow us to review and quickly prototype new features or
> changes on our working firefox implementation.
>
> One question Richard brought up on IRC which I could not find an answer for
> in your API is how do we add existing DOM audio elements to the graph? An
> audio element is in essence a Source and Destination node, How would I
> inject a lowpass filter into the pipeline? In the mozilla API we do this by
> muting the audio element and then reading out frames, filtering and then
> piping to a second non-DOM Audio element (Hacky, I know).
>
> Here is a rough setup of how this might work, could you fill in the gaps
> for me?
>
> var context = new AudioContext();
>
> var lowpass = context.createLowPass2Filter();
>
> var audio = document.getElementById('audioEle');
>
>
> function filterSound() {
>
> var source = context.createAudioBuffer(audio); // perhaps passing in the audio element here generates 1 frame worth of buffer as it plays ?
>
> source.connect(lowpass);
>
> lowpass.connect(context.destination);
>
> }
>
> Re,
> Corban
>
Received on Tuesday, 13 July 2010 19:26:10 UTC