mirror of
https://github.com/overte-org/overte.git
synced 2025-08-04 04:03:35 +02:00
Merge pull request #3898 from DaveDubUK/walk-JS-1.12
Version 1.12 of the walk.js script
This commit is contained in:
commit
dbf64b2de7
4 changed files with 2072 additions and 5937 deletions
File diff suppressed because it is too large
Load diff
|
@ -1,225 +1,277 @@
|
||||||
//
|
//
|
||||||
// walkFilters.js
|
// walkFilters.js
|
||||||
//
|
//
|
||||||
// version 1.001
|
// version 1.002
|
||||||
//
|
//
|
||||||
// Created by David Wooldridge, Autumn 2014
|
// Created by David Wooldridge, Autumn 2014
|
||||||
//
|
//
|
||||||
// Provides a variety of filters for use by the walk.js script v1.1
|
// Provides a variety of filters for use by the walk.js script v1.12
|
||||||
//
|
//
|
||||||
// Distributed under the Apache License, Version 2.0.
|
// Distributed under the Apache License, Version 2.0.
|
||||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||||
//
|
//
|
||||||
|
|
||||||
AveragingFilter = function(length) {
|
AveragingFilter = function(length) {
|
||||||
|
|
||||||
//this.name = name;
|
//this.name = name;
|
||||||
this.pastValues = [];
|
this.pastValues = [];
|
||||||
|
|
||||||
for(var i = 0; i < length; i++) {
|
for(var i = 0; i < length; i++) {
|
||||||
this.pastValues.push(0);
|
this.pastValues.push(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
// single arg is the nextInputValue
|
// single arg is the nextInputValue
|
||||||
this.process = function() {
|
this.process = function() {
|
||||||
|
|
||||||
if (this.pastValues.length === 0 && arguments[0]) {
|
if (this.pastValues.length === 0 && arguments[0]) {
|
||||||
return arguments[0];
|
|
||||||
} else if (arguments[0]) {
|
return arguments[0];
|
||||||
// apply quick and simple LP filtering
|
|
||||||
this.pastValues.push(arguments[0]);
|
} else if (arguments[0] !== null) {
|
||||||
this.pastValues.shift();
|
|
||||||
var nextOutputValue = 0;
|
// apply quick and simple LP filtering
|
||||||
for (var ea in this.pastValues) nextOutputValue += this.pastValues[ea];
|
this.pastValues.push(arguments[0]);
|
||||||
return nextOutputValue / this.pastValues.length;
|
this.pastValues.shift();
|
||||||
} else {
|
var nextOutputValue = 0;
|
||||||
return 0;
|
for (var ea in this.pastValues) nextOutputValue += this.pastValues[ea];
|
||||||
}
|
return nextOutputValue / this.pastValues.length;
|
||||||
};
|
|
||||||
};
|
} else {
|
||||||
|
|
||||||
// 2nd order Butterworth LP filter - calculate coeffs here: http://www-users.cs.york.ac.uk/~fisher/mkfilter/trad.html
|
return 0;
|
||||||
// provides LP filtering with a more stable frequency / phase response
|
}
|
||||||
ButterworthFilter = function(cutOff) {
|
};
|
||||||
|
};
|
||||||
// cut off frequency = 5Hz
|
|
||||||
this.gain = 20.20612010;
|
|
||||||
this.coeffOne = -0.4775922501;
|
// 1st order Butterworth filter - calculate coeffs here: http://www-users.cs.york.ac.uk/~fisher/mkfilter/trad.html
|
||||||
this.coeffTwo = 1.2796324250;
|
// provides LP filtering with a more stable frequency / phase response (-3 dB @ 3 Hz)
|
||||||
|
ButterworthFilter1 = function() {
|
||||||
// initialise the arrays
|
|
||||||
this.xv = [];
|
this.gain = 7.313751515;
|
||||||
this.yv = [];
|
this.coeff = 0.7265425280;
|
||||||
for(var i = 0; i < 3; i++) {
|
|
||||||
this.xv.push(0);
|
// initialise the arrays
|
||||||
this.yv.push(0);
|
this.xv = [];
|
||||||
}
|
this.yv = [];
|
||||||
|
|
||||||
// process values
|
for(var i = 0; i < 2; i++) {
|
||||||
this.process = function(nextInputValue) {
|
|
||||||
|
this.xv.push(0);
|
||||||
this.xv[0] = this.xv[1];
|
this.yv.push(0);
|
||||||
this.xv[1] = this.xv[2];
|
}
|
||||||
this.xv[2] = nextInputValue / this.gain;
|
|
||||||
|
// process values
|
||||||
this.yv[0] = this.yv[1];
|
this.process = function(nextInputValue) {
|
||||||
this.yv[1] = this.yv[2];
|
|
||||||
this.yv[2] = (this.xv[0] + this.xv[2]) +
|
this.xv[0] = this.xv[1];
|
||||||
2 * this.xv[1] +
|
this.xv[1] = nextInputValue / this.gain;
|
||||||
(this.coeffOne * this.yv[0]) +
|
|
||||||
(this.coeffTwo * this.yv[1]);
|
this.yv[0] = this.yv[1];
|
||||||
|
this.yv[1] = this.xv[0] + this.xv[1] + this.coeff * this.yv[0];
|
||||||
return this.yv[2];
|
|
||||||
};
|
return this.yv[1];
|
||||||
}; // end Butterworth filter contructor
|
};
|
||||||
|
|
||||||
// Add harmonics to a given sine wave to form square, sawtooth or triangle waves
|
}; // end Butterworth filter constructor
|
||||||
// Geometric wave synthesis fundamentals taken from: http://hyperphysics.phy-astr.gsu.edu/hbase/audio/geowv.html
|
|
||||||
WaveSynth = function(waveShape, numHarmonics, smoothing) {
|
// 2nd order Butterworth LP filter - calculate coeffs here: http://www-users.cs.york.ac.uk/~fisher/mkfilter/trad.html
|
||||||
|
// provides LP filtering with a more stable frequency / phase response
|
||||||
this.numHarmonics = numHarmonics;
|
ButterworthFilter2 = function(cutOff) {
|
||||||
this.waveShape = waveShape;
|
|
||||||
this.averagingFilter = new AveragingFilter(smoothing);
|
switch(cutOff) {
|
||||||
|
|
||||||
// NB: frequency in radians
|
case 5:
|
||||||
this.shapeWave = function(frequency) {
|
default:
|
||||||
|
|
||||||
// make some shapes
|
this.gain = 20.20612010;
|
||||||
var harmonics = 0;
|
this.coeffOne = -0.4775922501;
|
||||||
var multiplier = 0;
|
this.coeffTwo = 1.2796324250;
|
||||||
var iterations = this.numHarmonics * 2 + 2;
|
break;
|
||||||
if (this.waveShape === TRIANGLE) {
|
}
|
||||||
iterations++;
|
|
||||||
}
|
// initialise the arrays
|
||||||
|
this.xv = [];
|
||||||
for(var n = 2; n < iterations; n++) {
|
this.yv = [];
|
||||||
|
for(var i = 0; i < 3; i++) {
|
||||||
switch(this.waveShape) {
|
|
||||||
|
this.xv.push(0);
|
||||||
case SAWTOOTH: {
|
this.yv.push(0);
|
||||||
|
}
|
||||||
multiplier = 1 / n;
|
|
||||||
harmonics += multiplier * Math.sin(n * frequency);
|
// process values
|
||||||
break;
|
this.process = function(nextInputValue) {
|
||||||
}
|
|
||||||
|
this.xv[0] = this.xv[1];
|
||||||
case TRIANGLE: {
|
this.xv[1] = this.xv[2];
|
||||||
|
this.xv[2] = nextInputValue / this.gain;
|
||||||
if (n % 2 === 1) {
|
|
||||||
var mulitplier = 1 / (n * n);
|
this.yv[0] = this.yv[1];
|
||||||
// multiply (4n-1)th harmonics by -1
|
this.yv[1] = this.yv[2];
|
||||||
if (n === 3 || n === 7 || n === 11 || n === 15) {
|
this.yv[2] = (this.xv[0] + this.xv[2]) +
|
||||||
mulitplier *= -1;
|
2 * this.xv[1] +
|
||||||
}
|
(this.coeffOne * this.yv[0]) +
|
||||||
harmonics += mulitplier * Math.sin(n * frequency);
|
(this.coeffTwo * this.yv[1]);
|
||||||
}
|
|
||||||
break;
|
return this.yv[2];
|
||||||
}
|
};
|
||||||
|
}; // end Butterworth filter constructor
|
||||||
case SQUARE: {
|
|
||||||
|
|
||||||
if (n % 2 === 1) {
|
// Add harmonics to a given sine wave to form square, sawtooth or triangle waves
|
||||||
multiplier = 1 / n;
|
// Geometric wave synthesis fundamentals taken from: http://hyperphysics.phy-astr.gsu.edu/hbase/audio/geowv.html
|
||||||
harmonics += multiplier * Math.sin(n * frequency);
|
WaveSynth = function(waveShape, numHarmonics, smoothing) {
|
||||||
}
|
|
||||||
break;
|
this.numHarmonics = numHarmonics;
|
||||||
}
|
this.waveShape = waveShape;
|
||||||
}
|
this.smoothingFilter = new AveragingFilter(smoothing);
|
||||||
}
|
|
||||||
|
// NB: frequency in radians
|
||||||
// smooth the result and return
|
this.calculate = function(frequency) {
|
||||||
return this.averagingFilter.process(harmonics);
|
|
||||||
};
|
// make some shapes
|
||||||
};
|
var harmonics = 0;
|
||||||
|
var multiplier = 0;
|
||||||
// Create a wave shape by summing pre-calcualted sinusoidal harmonics
|
var iterations = this.numHarmonics * 2 + 2;
|
||||||
HarmonicsFilter = function(magnitudes, phaseAngles) {
|
if (this.waveShape === TRIANGLE) {
|
||||||
|
iterations++;
|
||||||
this.magnitudes = magnitudes;
|
}
|
||||||
this.phaseAngles = phaseAngles;
|
|
||||||
|
for(var n = 1; n < iterations; n++) {
|
||||||
this.calculate = function(twoPiFT) {
|
|
||||||
|
switch(this.waveShape) {
|
||||||
var harmonics = 0;
|
|
||||||
var numHarmonics = magnitudes.length;
|
case SAWTOOTH: {
|
||||||
|
|
||||||
for(var n = 0; n < numHarmonics; n++) {
|
multiplier = 1 / n;
|
||||||
harmonics += this.magnitudes[n] * Math.cos(n * twoPiFT - this.phaseAngles[n]);
|
harmonics += multiplier * Math.sin(n * frequency);
|
||||||
}
|
break;
|
||||||
return harmonics;
|
}
|
||||||
};
|
|
||||||
};
|
case TRIANGLE: {
|
||||||
|
|
||||||
// the main filter object literal
|
if (n % 2 === 1) {
|
||||||
filter = (function() {
|
var mulitplier = 1 / (n * n);
|
||||||
|
// multiply (4n-1)th harmonics by -1
|
||||||
// Bezier private functions
|
if (n === 3 || n === 7 || n === 11 || n === 15) {
|
||||||
function _B1(t) { return t * t * t };
|
mulitplier *= -1;
|
||||||
function _B2(t) { return 3 * t * t * (1 - t) };
|
}
|
||||||
function _B3(t) { return 3 * t * (1 - t) * (1 - t) };
|
harmonics += mulitplier * Math.sin(n * frequency);
|
||||||
function _B4(t) { return (1 - t) * (1 - t) * (1 - t) };
|
}
|
||||||
|
break;
|
||||||
return {
|
}
|
||||||
|
|
||||||
// helper methods
|
case SQUARE: {
|
||||||
degToRad: function(degrees) {
|
|
||||||
|
if (n % 2 === 1) {
|
||||||
var convertedValue = degrees * Math.PI / 180;
|
multiplier = 1 / n;
|
||||||
return convertedValue;
|
harmonics += multiplier * Math.sin(n * frequency);
|
||||||
},
|
}
|
||||||
|
break;
|
||||||
radToDeg: function(radians) {
|
}
|
||||||
|
}
|
||||||
var convertedValue = radians * 180 / Math.PI;
|
}
|
||||||
return convertedValue;
|
|
||||||
},
|
// smooth the result and return
|
||||||
|
return this.smoothingFilter.process(harmonics);
|
||||||
// these filters need instantiating, as they hold arrays of previous values
|
};
|
||||||
createAveragingFilter: function(length) {
|
};
|
||||||
|
|
||||||
var newAveragingFilter = new AveragingFilter(length);
|
// Create a motion wave by summing pre-calcualted sinusoidal harmonics
|
||||||
return newAveragingFilter;
|
HarmonicsFilter = function(magnitudes, phaseAngles) {
|
||||||
},
|
|
||||||
|
this.magnitudes = magnitudes;
|
||||||
createButterworthFilter: function(cutoff) {
|
this.phaseAngles = phaseAngles;
|
||||||
|
|
||||||
var newButterworthFilter = new ButterworthFilter(cutoff);
|
this.calculate = function(twoPiFT) {
|
||||||
return newButterworthFilter;
|
|
||||||
},
|
var harmonics = 0;
|
||||||
|
var numHarmonics = magnitudes.length;
|
||||||
createWaveSynth: function(waveShape, numHarmonics, smoothing) {
|
|
||||||
|
for(var n = 0; n < numHarmonics; n++) {
|
||||||
var newWaveSynth = new WaveSynth(waveShape, numHarmonics, smoothing);
|
harmonics += this.magnitudes[n] * Math.cos(n * twoPiFT - this.phaseAngles[n]);
|
||||||
return newWaveSynth;
|
}
|
||||||
},
|
return harmonics;
|
||||||
|
};
|
||||||
createHarmonicsFilter: function(magnitudes, phaseAngles) {
|
};
|
||||||
|
|
||||||
var newHarmonicsFilter = new HarmonicsFilter(magnitudes, phaseAngles);
|
|
||||||
return newHarmonicsFilter;
|
// the main filter object
|
||||||
},
|
filter = (function() {
|
||||||
|
|
||||||
|
// Bezier private functions
|
||||||
// the following filters do not need separate instances, as they hold no previous values
|
function _B1(t) { return t * t * t };
|
||||||
bezier: function(percent, C1, C2, C3, C4) {
|
function _B2(t) { return 3 * t * t * (1 - t) };
|
||||||
|
function _B3(t) { return 3 * t * (1 - t) * (1 - t) };
|
||||||
// Bezier functions for more natural transitions
|
function _B4(t) { return (1 - t) * (1 - t) * (1 - t) };
|
||||||
// based on script by Dan Pupius (www.pupius.net) http://13thparallel.com/archive/bezier-curves/
|
|
||||||
var pos = {x: 0, y: 0};
|
return {
|
||||||
pos.x = C1.x * _B1(percent) + C2.x * _B2(percent) + C3.x * _B3(percent) + C4.x * _B4(percent);
|
|
||||||
pos.y = C1.y * _B1(percent) + C2.y * _B2(percent) + C3.y * _B3(percent) + C4.y * _B4(percent);
|
// helper methods
|
||||||
return pos;
|
degToRad: function(degrees) {
|
||||||
},
|
|
||||||
|
var convertedValue = degrees * Math.PI / 180;
|
||||||
// simple clipping filter (clips bottom of wave only, special case for hips y-axis skeleton offset)
|
return convertedValue;
|
||||||
clipTrough: function(inputValue, peak, strength) {
|
},
|
||||||
|
|
||||||
var outputValue = inputValue * strength;
|
radToDeg: function(radians) {
|
||||||
if (outputValue < -peak) {
|
|
||||||
outputValue = -peak;
|
var convertedValue = radians * 180 / Math.PI;
|
||||||
}
|
return convertedValue;
|
||||||
return outputValue;
|
},
|
||||||
}
|
|
||||||
}
|
// these filters need instantiating, as they hold arrays of previous values
|
||||||
|
createAveragingFilter: function(length) {
|
||||||
|
|
||||||
|
var newAveragingFilter = new AveragingFilter(length);
|
||||||
|
return newAveragingFilter;
|
||||||
|
},
|
||||||
|
|
||||||
|
createButterworthFilter1: function() {
|
||||||
|
|
||||||
|
var newButterworthFilter = new ButterworthFilter1();
|
||||||
|
return newButterworthFilter;
|
||||||
|
},
|
||||||
|
|
||||||
|
createButterworthFilter2: function(cutoff) {
|
||||||
|
|
||||||
|
var newButterworthFilter = new ButterworthFilter2(cutoff);
|
||||||
|
return newButterworthFilter;
|
||||||
|
},
|
||||||
|
|
||||||
|
createWaveSynth: function(waveShape, numHarmonics, smoothing) {
|
||||||
|
|
||||||
|
var newWaveSynth = new WaveSynth(waveShape, numHarmonics, smoothing);
|
||||||
|
return newWaveSynth;
|
||||||
|
},
|
||||||
|
|
||||||
|
createHarmonicsFilter: function(magnitudes, phaseAngles) {
|
||||||
|
|
||||||
|
var newHarmonicsFilter = new HarmonicsFilter(magnitudes, phaseAngles);
|
||||||
|
return newHarmonicsFilter;
|
||||||
|
},
|
||||||
|
|
||||||
|
|
||||||
|
// the following filters do not need separate instances, as they hold no previous values
|
||||||
|
bezier: function(percent, C1, C2, C3, C4) {
|
||||||
|
|
||||||
|
// Bezier functions for more natural transitions
|
||||||
|
// based on script by Dan Pupius (www.pupius.net) http://13thparallel.com/archive/bezier-curves/
|
||||||
|
var pos = {x: 0, y: 0};
|
||||||
|
pos.x = C1.x * _B1(percent) + C2.x * _B2(percent) + C3.x * _B3(percent) + C4.x * _B4(percent);
|
||||||
|
pos.y = C1.y * _B1(percent) + C2.y * _B2(percent) + C3.y * _B3(percent) + C4.y * _B4(percent);
|
||||||
|
return pos;
|
||||||
|
},
|
||||||
|
|
||||||
|
// simple clipping filter (clips bottom of wave only)
|
||||||
|
clipTrough: function(inputValue, peak, strength) {
|
||||||
|
|
||||||
|
var outputValue = inputValue * strength;
|
||||||
|
if (outputValue < -peak) {
|
||||||
|
outputValue = -peak;
|
||||||
|
}
|
||||||
|
return outputValue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
})();
|
})();
|
File diff suppressed because it is too large
Load diff
3465
examples/walk.js
3465
examples/walk.js
File diff suppressed because it is too large
Load diff
Loading…
Reference in a new issue