Skip to content

Commit

Permalink
added AudioContextMonkeyPatch to the build fixes #56
Browse files Browse the repository at this point in the history
  • Loading branch information
sebpiq committed May 4, 2015
1 parent 66fcca2 commit fe3bb46
Show file tree
Hide file tree
Showing 8 changed files with 425 additions and 39 deletions.
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
*~
node_modules
coverage
waatest
waatest
build
7 changes: 1 addition & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@ For security reasons, browsers control access to your file system from web pages
Python comes bundled with such a web server. Open a terminal, navigate to the folder containing the web page you want to open, then run `python -m SimpleHTTPServer` if you are using **Python 2** or `python -m http.server` if you are using **Python 3**. Then open your web browser to [http://localhost:8000](http://localhost:8000) and things should start working.


### A patch that used to work fine with WebPd has stopped working after I modified it
### Other patches have worked before but this one doesn't

WebPd has a few [limitations](#list-of-implemented-objects-and-other-limitations). For example, some of the Pd objects are not available. Open your browser's developer console (`ctrl+shift+i` on firefox and chrome for linux or windows), and you should get a clear error message telling you what is wrong. If the error is unclear, or if there is no error, it might be a bug with WebPd. In that case, it would be great if you could [submit a bug report](#submitting-a-bug-report).

Expand All @@ -128,11 +128,6 @@ WebPd uses Web Audio API, and as it happens, running Web Audio API on mobile is
On iPhone and iPad, things are even trickier. For security reasons, audio is blocked by iOS, unless you start it in direct answer to a user action (click, touch, ...). So to get sound with WebPd, you will need to do exactly that and for example call `Pd.start` in a button's `onclick` handler : `onclick="Pd.start()"`.


### My patch doesn't work on some browser which should support Web Audio API

Web Audio API is a work in progress, so there is discrepencies between different browser implementations. WebPd builds on the latest version of Web Audio API. To make sure that your web page also works with browsers implementing older versions of Web Audio API, include [that javascript](https://github.com/cwilso/AudioContext-MonkeyPatch) in your web page, before you include WebPd.


List of implemented objects and other limitations
---------------------------------------------------

Expand Down
182 changes: 182 additions & 0 deletions deps/AudioContextMonkeyPatch.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,182 @@
/* Copyright 2013 Chris Wilson
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

/*
This monkeypatch library is intended to be included in projects that are
written to the proper AudioContext spec (instead of webkitAudioContext),
and that use the new naming and proper bits of the Web Audio API (e.g.
using BufferSourceNode.start() instead of BufferSourceNode.noteOn()), but may
have to run on systems that only support the deprecated bits.
This library should be harmless to include if the browser supports
unprefixed "AudioContext", and/or if it supports the new names.
The patches this library handles:
if window.AudioContext is unsupported, it will be aliased to webkitAudioContext().
if AudioBufferSourceNode.start() is unimplemented, it will be routed to noteOn() or
noteGrainOn(), depending on parameters.
The following aliases only take effect if the new names are not already in place:
AudioBufferSourceNode.stop() is aliased to noteOff()
AudioContext.createGain() is aliased to createGainNode()
AudioContext.createDelay() is aliased to createDelayNode()
AudioContext.createScriptProcessor() is aliased to createJavaScriptNode()
AudioContext.createPeriodicWave() is aliased to createWaveTable()
OscillatorNode.start() is aliased to noteOn()
OscillatorNode.stop() is aliased to noteOff()
OscillatorNode.setPeriodicWave() is aliased to setWaveTable()
AudioParam.setTargetAtTime() is aliased to setTargetValueAtTime()
This library does NOT patch the enumerated type changes, as it is
recommended in the specification that implementations support both integer
and string types for AudioPannerNode.panningModel, AudioPannerNode.distanceModel
BiquadFilterNode.type and OscillatorNode.type.
*/
(function (global, exports, perf) {
'use strict';

function fixSetTarget(param) {
if (!param) // if NYI, just return
return;
if (!param.setTargetAtTime)
param.setTargetAtTime = param.setTargetValueAtTime;
}

if (window.hasOwnProperty('webkitAudioContext') &&
!window.hasOwnProperty('AudioContext')) {
window.AudioContext = webkitAudioContext;

if (!AudioContext.prototype.hasOwnProperty('createGain'))
AudioContext.prototype.createGain = AudioContext.prototype.createGainNode;
if (!AudioContext.prototype.hasOwnProperty('createDelay'))
AudioContext.prototype.createDelay = AudioContext.prototype.createDelayNode;
if (!AudioContext.prototype.hasOwnProperty('createScriptProcessor'))
AudioContext.prototype.createScriptProcessor = AudioContext.prototype.createJavaScriptNode;
if (!AudioContext.prototype.hasOwnProperty('createPeriodicWave'))
AudioContext.prototype.createPeriodicWave = AudioContext.prototype.createWaveTable;


AudioContext.prototype.internal_createGain = AudioContext.prototype.createGain;
AudioContext.prototype.createGain = function() {
var node = this.internal_createGain();
fixSetTarget(node.gain);
return node;
};

AudioContext.prototype.internal_createDelay = AudioContext.prototype.createDelay;
AudioContext.prototype.createDelay = function(maxDelayTime) {
var node = maxDelayTime ? this.internal_createDelay(maxDelayTime) : this.internal_createDelay();
fixSetTarget(node.delayTime);
return node;
};

AudioContext.prototype.internal_createBufferSource = AudioContext.prototype.createBufferSource;
AudioContext.prototype.createBufferSource = function() {
var node = this.internal_createBufferSource();
if (!node.start) {
node.start = function ( when, offset, duration ) {
if ( offset || duration )
this.noteGrainOn( when || 0, offset, duration );
else
this.noteOn( when || 0 );
};
} else {
node.internal_start = node.start;
node.start = function( when, offset, duration ) {
if( typeof duration !== 'undefined' )
node.internal_start( when || 0, offset, duration );
else
node.internal_start( when || 0, offset );
};
}
if (!node.stop) {
node.stop = function ( when ) {
this.noteOff( when || 0 );
};
} else {
node.internal_stop = node.stop;
node.stop = function( when ) {
node.internal_stop( when || 0 );
};
}
fixSetTarget(node.playbackRate);
return node;
};

AudioContext.prototype.internal_createDynamicsCompressor = AudioContext.prototype.createDynamicsCompressor;
AudioContext.prototype.createDynamicsCompressor = function() {
var node = this.internal_createDynamicsCompressor();
fixSetTarget(node.threshold);
fixSetTarget(node.knee);
fixSetTarget(node.ratio);
fixSetTarget(node.reduction);
fixSetTarget(node.attack);
fixSetTarget(node.release);
return node;
};

AudioContext.prototype.internal_createBiquadFilter = AudioContext.prototype.createBiquadFilter;
AudioContext.prototype.createBiquadFilter = function() {
var node = this.internal_createBiquadFilter();
fixSetTarget(node.frequency);
fixSetTarget(node.detune);
fixSetTarget(node.Q);
fixSetTarget(node.gain);
return node;
};

if (AudioContext.prototype.hasOwnProperty( 'createOscillator' )) {
AudioContext.prototype.internal_createOscillator = AudioContext.prototype.createOscillator;
AudioContext.prototype.createOscillator = function() {
var node = this.internal_createOscillator();
if (!node.start) {
node.start = function ( when ) {
this.noteOn( when || 0 );
};
} else {
node.internal_start = node.start;
node.start = function ( when ) {
node.internal_start( when || 0);
};
}
if (!node.stop) {
node.stop = function ( when ) {
this.noteOff( when || 0 );
};
} else {
node.internal_stop = node.stop;
node.stop = function( when ) {
node.internal_stop( when || 0 );
};
}
if (!node.setPeriodicWave)
node.setPeriodicWave = node.setWaveTable;
fixSetTarget(node.frequency);
fixSetTarget(node.detune);
return node;
};
}
}

if (window.hasOwnProperty('webkitOfflineAudioContext') &&
!window.hasOwnProperty('OfflineAudioContext')) {
window.OfflineAudioContext = webkitOfflineAudioContext;
}

}(window));

Loading

0 comments on commit fe3bb46

Please sign in to comment.