Skip to content

Commit

Permalink
Merge pull request #139 from rserota/feature/poly-panning
Browse files Browse the repository at this point in the history
panning for polywads
  • Loading branch information
rserota committed Oct 16, 2021
2 parents e558aec + e341e04 commit 5117e6a
Show file tree
Hide file tree
Showing 11 changed files with 76 additions and 62 deletions.
10 changes: 9 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -740,13 +740,21 @@ This method sets the default pitch for each wad inside this polywad.
| -------- | ------ | ------- | ---------------------------------------- |
| volume | number | none | The new volume setting for this polywad. |

### Wad.Poly.prototype.setPanning(panning, timeConstant)

| Property | Type | Default | Description |
| ------------ | --------------- | -------------- | ----------- |
| panning | object or array | none (required) | New detune setting. |
| timeConstant | string | none | Time in seconds for 63% of the transition to complete. |

Change the panning of this polywad at any time, even during playback.

### Wad.Poly.prototype.updatePitch()

This method is used for pitch detection. After calling it, the polywad will calculate the frequency of its output, and write that information to `this.pitch` and `this.noteName`.


### Wad.Poly.prototype.updatePitch()
### Wad.Poly.prototype.stopUpdatingPitch()

This method stops the polywad from continuing to detect the pitch in real time.

Expand Down
21 changes: 7 additions & 14 deletions build/wad.js
Original file line number Diff line number Diff line change
Expand Up @@ -21123,6 +21123,10 @@ Polywad.prototype.setPitch = function(pitch){
});
};

Polywad.prototype.setPanning = function(panning, timeConstant){
Wad.prototype.setPanning.call(this, panning, timeConstant);
};

Polywad.prototype.play = function(arg){
if ( this.isSetUp ) {
if ( this.playable < 1 ) {
Expand Down Expand Up @@ -21489,19 +21493,16 @@ let Wad = function(arg){
this.duration = (this.env.attack + this.env.decay + this.env.hold + this.env.release) * (1/(this.rate)) * 1000;
this.constructExternalFx(arg, _common__WEBPACK_IMPORTED_MODULE_2__["context"]);


/** If the Wad's source is noise, set the Wad's buffer to the noise buffer we created earlier. **/
if ( this.source === 'noise' ) {
this.decodedBuffer = _common__WEBPACK_IMPORTED_MODULE_2__["noiseBuffer"];
}


/** If the Wad's source is the microphone, the rest of the setup happens here. **/
else if ( this.source === 'mic' ) {
Object(_common__WEBPACK_IMPORTED_MODULE_2__["getConsent"])(this, arg);
}


/** If the source is not a pre-defined value, assume it is a URL for an audio file, and grab it now. **/
else if ( !( this.source in { 'sine' : 0, 'sawtooth' : 0, 'square' : 0, 'triangle' : 0 } ) ) {
Object(_common__WEBPACK_IMPORTED_MODULE_2__["requestAudioFile"])(this, arg.callback);
Expand All @@ -21524,6 +21525,7 @@ let Wad = function(arg){
}
}
else { arg.callback && arg.callback(this); }

Wad.allWads.push(this);
};

Expand Down Expand Up @@ -21590,11 +21592,9 @@ Wad.prototype.play = function(arg){
else { this.volume = this.defaultVolume; }
arg.offset = arg.offset || this.offset || 0;


if ( this.source in { 'sine' : 0, 'sawtooth' : 0, 'square' : 0, 'triangle' : 0 } ) {
Object(_common__WEBPACK_IMPORTED_MODULE_2__["setUpOscillator"])(this, arg);
}

else {
this.soundSource = _common__WEBPACK_IMPORTED_MODULE_2__["context"].createBufferSource();
this.soundSource.buffer = this.decodedBuffer;
Expand All @@ -21604,26 +21604,24 @@ Wad.prototype.play = function(arg){

}


if ( this.soundSource.detune ) {
this.soundSource.detune.value = arg.detune || this.detune;
}

if ( arg.wait === undefined ) {
arg.wait = 0;
}

if (arg.exactTime === undefined) {
arg.exactTime = _common__WEBPACK_IMPORTED_MODULE_2__["context"].currentTime + arg.wait;
}
this.lastPlayedTime = arg.exactTime - arg.offset;

this.nodes.push(this.soundSource);


/** sets the volume envelope based on the play() arguments if present,
or defaults to the constructor arguments if the volume envelope is not set on play() **/
Object(_common__WEBPACK_IMPORTED_MODULE_2__["setUpEnvOnPlay"])(this, arg);
////////////////////////////////////////////////////////////////////////////////////////

if ( this.soundSource.playbackRate ) {
this.soundSource.playbackRate.value = arg.rate || this.rate;
Expand All @@ -21633,12 +21631,10 @@ or defaults to the constructor arguments if the volume envelope is not set on pl
/** sets up the filter and filter envelope based on the play() argument if present,
or defaults to the constructor argument if the filter and filter envelope are not set on play() **/
Object(_common__WEBPACK_IMPORTED_MODULE_2__["setUpFilterOnPlay"])(this, arg);
///////////////////////////////////////////////////////////////////////////////////////////////////
Object(_common__WEBPACK_IMPORTED_MODULE_2__["setUpTunaOnPlay"])(this, arg);

this.setUpExternalFxOnPlay(arg, _common__WEBPACK_IMPORTED_MODULE_2__["context"]);


this.gain.unshift(_common__WEBPACK_IMPORTED_MODULE_2__["context"].createGain()); // sets up the gain node
this.gain[0].label = arg.label;
this.gain[0].soundSource = this.soundSource;
Expand All @@ -21648,13 +21644,10 @@ or defaults to the constructor argument if the filter and filter envelope are no
this.gain.length = 15;
}

// sets up reverb
if ( this.reverb ) { Object(_common__WEBPACK_IMPORTED_MODULE_2__["setUpReverbOnPlay"])(this, arg); }

/** sets panning based on the play() argument if present, or defaults to the constructor argument if panning is not set on play **/
Object(_common__WEBPACK_IMPORTED_MODULE_2__["setUpPanningOnPlay"])(this, arg);
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////


Object(_common__WEBPACK_IMPORTED_MODULE_2__["setUpDelayOnPlay"])(this, arg);

Expand Down Expand Up @@ -21791,7 +21784,7 @@ Wad.prototype.setDetune = function(detune, timeConstant, label){
};

/** Change the panning of a Wad at any time, including during playback **/
Wad.prototype.setPanning = function(panning, timeConstant, label){
Wad.prototype.setPanning = function(panning, timeConstant){
timeConstant = timeConstant || .01;
if ( typeof panning === 'number' && !_common__WEBPACK_IMPORTED_MODULE_2__["context"].createStereoPanner ) {
panning = [panning, 0, 0];
Expand Down
2 changes: 1 addition & 1 deletion build/wad.js.map

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions build/wad.min.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "web-audio-daw",
"version": "4.11.1",
"version": "4.12.0",
"description": "Web Audio DAW. It's like jQuery for your ears.",
"main": "build/wad.js",
"scripts": {
Expand Down
4 changes: 4 additions & 0 deletions src/polywad.js
Original file line number Diff line number Diff line change
Expand Up @@ -283,6 +283,10 @@ Polywad.prototype.setPitch = function(pitch){
});
};

Polywad.prototype.setPanning = function(panning, timeConstant){
Wad.prototype.setPanning.call(this, panning, timeConstant);
};

Polywad.prototype.play = function(arg){
if ( this.isSetUp ) {
if ( this.playable < 1 ) {
Expand Down
2 changes: 1 addition & 1 deletion src/wad.js
Original file line number Diff line number Diff line change
Expand Up @@ -349,7 +349,7 @@ Wad.prototype.setDetune = function(detune, timeConstant, label){
};

/** Change the panning of a Wad at any time, including during playback **/
Wad.prototype.setPanning = function(panning, timeConstant, label){
Wad.prototype.setPanning = function(panning, timeConstant){
timeConstant = timeConstant || .01;
if ( typeof panning === 'number' && !context.createStereoPanner ) {
panning = [panning, 0, 0];
Expand Down
50 changes: 25 additions & 25 deletions test/gui/build/test.js
Original file line number Diff line number Diff line change
Expand Up @@ -21213,6 +21213,10 @@ Polywad.prototype.setPitch = function(pitch){
});
};

Polywad.prototype.setPanning = function(panning, timeConstant){
Wad.prototype.setPanning.call(this, panning, timeConstant);
};

Polywad.prototype.play = function(arg){
if ( this.isSetUp ) {
if ( this.playable < 1 ) {
Expand Down Expand Up @@ -21579,19 +21583,16 @@ let Wad = function(arg){
this.duration = (this.env.attack + this.env.decay + this.env.hold + this.env.release) * (1/(this.rate)) * 1000;
this.constructExternalFx(arg, _common__WEBPACK_IMPORTED_MODULE_2__["context"]);


/** If the Wad's source is noise, set the Wad's buffer to the noise buffer we created earlier. **/
if ( this.source === 'noise' ) {
this.decodedBuffer = _common__WEBPACK_IMPORTED_MODULE_2__["noiseBuffer"];
}


/** If the Wad's source is the microphone, the rest of the setup happens here. **/
else if ( this.source === 'mic' ) {
Object(_common__WEBPACK_IMPORTED_MODULE_2__["getConsent"])(this, arg);
}


/** If the source is not a pre-defined value, assume it is a URL for an audio file, and grab it now. **/
else if ( !( this.source in { 'sine' : 0, 'sawtooth' : 0, 'square' : 0, 'triangle' : 0 } ) ) {
Object(_common__WEBPACK_IMPORTED_MODULE_2__["requestAudioFile"])(this, arg.callback);
Expand All @@ -21614,6 +21615,7 @@ let Wad = function(arg){
}
}
else { arg.callback && arg.callback(this); }

Wad.allWads.push(this);
};

Expand Down Expand Up @@ -21680,11 +21682,9 @@ Wad.prototype.play = function(arg){
else { this.volume = this.defaultVolume; }
arg.offset = arg.offset || this.offset || 0;


if ( this.source in { 'sine' : 0, 'sawtooth' : 0, 'square' : 0, 'triangle' : 0 } ) {
Object(_common__WEBPACK_IMPORTED_MODULE_2__["setUpOscillator"])(this, arg);
}

else {
this.soundSource = _common__WEBPACK_IMPORTED_MODULE_2__["context"].createBufferSource();
this.soundSource.buffer = this.decodedBuffer;
Expand All @@ -21694,26 +21694,24 @@ Wad.prototype.play = function(arg){

}


if ( this.soundSource.detune ) {
this.soundSource.detune.value = arg.detune || this.detune;
}

if ( arg.wait === undefined ) {
arg.wait = 0;
}

if (arg.exactTime === undefined) {
arg.exactTime = _common__WEBPACK_IMPORTED_MODULE_2__["context"].currentTime + arg.wait;
}
this.lastPlayedTime = arg.exactTime - arg.offset;

this.nodes.push(this.soundSource);


/** sets the volume envelope based on the play() arguments if present,
or defaults to the constructor arguments if the volume envelope is not set on play() **/
Object(_common__WEBPACK_IMPORTED_MODULE_2__["setUpEnvOnPlay"])(this, arg);
////////////////////////////////////////////////////////////////////////////////////////

if ( this.soundSource.playbackRate ) {
this.soundSource.playbackRate.value = arg.rate || this.rate;
Expand All @@ -21723,12 +21721,10 @@ or defaults to the constructor arguments if the volume envelope is not set on pl
/** sets up the filter and filter envelope based on the play() argument if present,
or defaults to the constructor argument if the filter and filter envelope are not set on play() **/
Object(_common__WEBPACK_IMPORTED_MODULE_2__["setUpFilterOnPlay"])(this, arg);
///////////////////////////////////////////////////////////////////////////////////////////////////
Object(_common__WEBPACK_IMPORTED_MODULE_2__["setUpTunaOnPlay"])(this, arg);

this.setUpExternalFxOnPlay(arg, _common__WEBPACK_IMPORTED_MODULE_2__["context"]);


this.gain.unshift(_common__WEBPACK_IMPORTED_MODULE_2__["context"].createGain()); // sets up the gain node
this.gain[0].label = arg.label;
this.gain[0].soundSource = this.soundSource;
Expand All @@ -21738,13 +21734,10 @@ or defaults to the constructor argument if the filter and filter envelope are no
this.gain.length = 15;
}

// sets up reverb
if ( this.reverb ) { Object(_common__WEBPACK_IMPORTED_MODULE_2__["setUpReverbOnPlay"])(this, arg); }

/** sets panning based on the play() argument if present, or defaults to the constructor argument if panning is not set on play **/
Object(_common__WEBPACK_IMPORTED_MODULE_2__["setUpPanningOnPlay"])(this, arg);
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////


Object(_common__WEBPACK_IMPORTED_MODULE_2__["setUpDelayOnPlay"])(this, arg);

Expand Down Expand Up @@ -21881,7 +21874,7 @@ Wad.prototype.setDetune = function(detune, timeConstant, label){
};

/** Change the panning of a Wad at any time, including during playback **/
Wad.prototype.setPanning = function(panning, timeConstant, label){
Wad.prototype.setPanning = function(panning, timeConstant){
timeConstant = timeConstant || .01;
if ( typeof panning === 'number' && !_common__WEBPACK_IMPORTED_MODULE_2__["context"].createStereoPanner ) {
panning = [panning, 0, 0];
Expand Down Expand Up @@ -22092,7 +22085,7 @@ __webpack_require__.r(__webpack_exports__);
window.Wad = _build_wad_js__WEBPACK_IMPORTED_MODULE_0___default.a;

_build_wad_js__WEBPACK_IMPORTED_MODULE_0___default.a.logs.verbosity = 1;
var ignition = new _build_wad_js__WEBPACK_IMPORTED_MODULE_0___default.a({source:'./ignition.mp3'});
let ignition = new _build_wad_js__WEBPACK_IMPORTED_MODULE_0___default.a({source:'./ignition.mp3'});
document.getElementById('ignition').addEventListener('click', async function(){
// await ignition.play()
await ignition.play();
Expand Down Expand Up @@ -22121,7 +22114,7 @@ document.getElementById('ignition-slower').addEventListener('click', async funct
});
console.log('slow ignition');
});
var helloMan = new _build_wad_js__WEBPACK_IMPORTED_MODULE_0___default.a({
let helloMan = new _build_wad_js__WEBPACK_IMPORTED_MODULE_0___default.a({
source: './hello-man.wav',
sprite: {
hello: [0, .4],
Expand All @@ -22141,7 +22134,7 @@ document.getElementById('sprite-ab').addEventListener('click', async function(){
await helloMan.play({env:{attack: .1, release:.02}});
});

var longClip = new _build_wad_js__WEBPACK_IMPORTED_MODULE_0___default.a({source:'./do-re-mi.wav'});
let longClip = new _build_wad_js__WEBPACK_IMPORTED_MODULE_0___default.a({source:'./do-re-mi.wav'});
document.getElementById('full-song').addEventListener('click', function(){
longClip.play().then(function(thatWad){
console.log('Clip finished.');
Expand All @@ -22160,7 +22153,7 @@ document.getElementById('reverse-full-song').addEventListener('click', function(
longClip.reverse();
});

var sine = new _build_wad_js__WEBPACK_IMPORTED_MODULE_0___default.a({source:'sine', env: {attack: .07, hold: 1.5, release: .6}});
let sine = new _build_wad_js__WEBPACK_IMPORTED_MODULE_0___default.a({source:'sine', env: {attack: .07, hold: 1.5, release: .6}});

document.getElementById('sine').addEventListener('click', async function(){
await sine.play();
Expand Down Expand Up @@ -22207,24 +22200,25 @@ document.getElementById('stop').addEventListener('click', function(){
});


var sawtooth = new _build_wad_js__WEBPACK_IMPORTED_MODULE_0___default.a({source:'sawtooth', env:{hold:1, release:.2}});
var triangle = new _build_wad_js__WEBPACK_IMPORTED_MODULE_0___default.a({source:'triangle', env:{hold:1, release:.2}});
let sawtooth = new _build_wad_js__WEBPACK_IMPORTED_MODULE_0___default.a({source:'sawtooth', env:{hold:1, release:.2}});
let triangle = new _build_wad_js__WEBPACK_IMPORTED_MODULE_0___default.a({source:'triangle', env:{hold:1, release:.2}});

var volumeDisplay = document.getElementById('polywad-volume');
var clippingDisplay = document.getElementById('polywad-clipping');
let volumeDisplay = document.getElementById('polywad-volume');
let clippingDisplay = document.getElementById('polywad-clipping');
let displayAudioMeter = function(thatWad){
thatWad.add(sawtooth).add(triangle);
setInterval(function(){
volumeDisplay.innerText = Math.round(thatWad.audioMeter.volume * 1000);
clippingDisplay.innerText = thatWad.audioMeter.checkClipping();
}, 50);
};
window.polywad = new _build_wad_js__WEBPACK_IMPORTED_MODULE_0___default.a.Poly({
let polywad = window.polywad = new _build_wad_js__WEBPACK_IMPORTED_MODULE_0___default.a.Poly({
volume: .5,
reverb : {
wet : 1,
impulse : 'widehall.wav'
},
panning: [0,0,0],
recorder: true,
audioMeter: {
clipLevel: .98,
Expand All @@ -22241,6 +22235,12 @@ document.getElementById('polywad').addEventListener('click', function(){
document.getElementById('polywad-set-pitch').addEventListener('click', function(){
polywad.setPitch('B3');
});
document.getElementById('polywad-pan-left').addEventListener('click', function(){
polywad.setPanning([-1,0,0]);
});
document.getElementById('polywad-pan-right').addEventListener('click', function(){
polywad.setPanning([1,0,0]);
});

document.getElementById('stop').addEventListener('click', function(){
sine.stop();
Expand All @@ -22249,8 +22249,8 @@ document.getElementById('polywad-stop').addEventListener('click', function(){
polywad.stop();
});

var rafId;
var logPitch = function(){
let rafId, tuner, voice;
let logPitch = function(){
console.log(tuner.pitch, tuner.noteName);
rafId = requestAnimationFrame(logPitch);
};
Expand Down
2 changes: 1 addition & 1 deletion test/gui/build/test.js.map

Large diffs are not rendered by default.

12 changes: 7 additions & 5 deletions test/gui/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -35,11 +35,13 @@

<hr>

<button id="polywad">PLAY POLYWAD</button>
<button id="polywad-set-pitch">SET POLYWAD PITCH</button>
<button id="polywad-stop">STOP POLYWAD</button>
<span id="polywad-volume">VOLUME</span>
<span id="polywad-clipping">CLIPPING?</span>
<button id="polywad">Play PolyWad</button>
<button id="polywad-set-pitch">Set PolyWad pitch</button>
<button id="polywad-stop">Stop PolyWad</button>
<button id="polywad-pan-left">Pan PolyWad left</button>
<button id="polywad-pan-right">Pan PolyWad right</button>
<span id="polywad-volume">Volume</span>
<span id="polywad-clipping">Clipping?</span>

<hr>

Expand Down
Loading

0 comments on commit 5117e6a

Please sign in to comment.