mirror of
https://github.com/gyurix1968/guacamole-client.git
synced 2025-09-06 13:17:41 +00:00
GUACAMOLE-25: Migrate to Lanczos interpolation (a = 3).
This commit is contained in:
@@ -126,6 +126,17 @@ Guacamole.RawAudioRecorder = function RawAudioRecorder(stream, mimetype) {
|
|||||||
*/
|
*/
|
||||||
var BUFFER_SIZE = 512;
|
var BUFFER_SIZE = 512;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The window size to use when applying Lanczos interpolation, commonly
|
||||||
|
* denoted by the variable "a".
|
||||||
|
* See: https://en.wikipedia.org/wiki/Lanczos_resampling
|
||||||
|
*
|
||||||
|
* @private
|
||||||
|
* @contant
|
||||||
|
* @type Number
|
||||||
|
*/
|
||||||
|
var LANCZOS_WINDOW_SIZE = 3;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The format of audio this recorder will encode.
|
* The format of audio this recorder will encode.
|
||||||
*
|
*
|
||||||
@@ -218,12 +229,65 @@ Guacamole.RawAudioRecorder = function RawAudioRecorder(stream, mimetype) {
|
|||||||
*/
|
*/
|
||||||
var processor = null;
|
var processor = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The normalized sinc function. The normalized sinc function is defined as
|
||||||
|
* 1 for x=0 and sin(PI * x) / (PI * x) for all other values of x.
|
||||||
|
*
|
||||||
|
* See: https://en.wikipedia.org/wiki/Sinc_function
|
||||||
|
*
|
||||||
|
* @private
|
||||||
|
* @param {Number} x
|
||||||
|
* The point at which the normalized sinc function should be computed.
|
||||||
|
*
|
||||||
|
* @returns {Number}
|
||||||
|
* The value of the normalized sinc function at x.
|
||||||
|
*/
|
||||||
|
var sinc = function sinc(x) {
|
||||||
|
|
||||||
|
// The value of sinc(0) is defined as 1
|
||||||
|
if (x === 0)
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
// Otherwise, normlized sinc(x) is sin(PI * x) / (PI * x)
|
||||||
|
var piX = Math.PI * x;
|
||||||
|
return Math.sin(piX) / piX;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Calculates the value of the Lanczos kernal at point x for a given window
|
||||||
|
* size. See: https://en.wikipedia.org/wiki/Lanczos_resampling
|
||||||
|
*
|
||||||
|
* @private
|
||||||
|
* @param {Number} x
|
||||||
|
* The point at which the value of the Lanczos kernel should be
|
||||||
|
* computed.
|
||||||
|
*
|
||||||
|
* @param {Number} a
|
||||||
|
* The window size to use for the Lanczos kernel.
|
||||||
|
*
|
||||||
|
* @returns {Number}
|
||||||
|
* The value of the Lanczos kernel at the given point for the given
|
||||||
|
* window size.
|
||||||
|
*/
|
||||||
|
var lanczos = function lanczos(x, a) {
|
||||||
|
|
||||||
|
// Lanczos is sinc(x) * sinc(x / a) for -a < x < a ...
|
||||||
|
if (-a < x && x < a)
|
||||||
|
return sinc(x) * sinc(x / a);
|
||||||
|
|
||||||
|
// ... and 0 otherwise
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Determines the value of the waveform represented by the audio data at
|
* Determines the value of the waveform represented by the audio data at
|
||||||
* the given location. If the value cannot be determined exactly as it does
|
* the given location. If the value cannot be determined exactly as it does
|
||||||
* not correspond to an exact sample within the audio data, the value will
|
* not correspond to an exact sample within the audio data, the value will
|
||||||
* be derived through interpolating nearby samples.
|
* be derived through interpolating nearby samples.
|
||||||
*
|
*
|
||||||
|
* @private
|
||||||
* @param {Float32Array} audioData
|
* @param {Float32Array} audioData
|
||||||
* An array of audio data, as returned by AudioBuffer.getChannelData().
|
* An array of audio data, as returned by AudioBuffer.getChannelData().
|
||||||
*
|
*
|
||||||
@@ -241,17 +305,19 @@ Guacamole.RawAudioRecorder = function RawAudioRecorder(stream, mimetype) {
|
|||||||
// Convert [0, 1] range to [0, audioData.length - 1]
|
// Convert [0, 1] range to [0, audioData.length - 1]
|
||||||
var index = (audioData.length - 1) * t;
|
var index = (audioData.length - 1) * t;
|
||||||
|
|
||||||
// Get the closest whole integer samples indices
|
// Determine the start and end points for the summation used by the
|
||||||
var left = Math.floor(index);
|
// Lanczos interpolation algorithm (see: https://en.wikipedia.org/wiki/Lanczos_resampling)
|
||||||
var right = Math.ceil(index);
|
var start = Math.floor(index) - LANCZOS_WINDOW_SIZE + 1;
|
||||||
|
var end = Math.floor(index) + LANCZOS_WINDOW_SIZE;
|
||||||
|
|
||||||
// Pull the values of the closest samples
|
// Calculate the value of the Lanczos interpolation function for the
|
||||||
var leftValue = audioData[left];
|
// required range
|
||||||
var rightValue = audioData[right];
|
var sum = 0;
|
||||||
|
for (var i = start; i <= end; i++) {
|
||||||
|
sum += (audioData[i] || 0) * lanczos(index - i, LANCZOS_WINDOW_SIZE);
|
||||||
|
}
|
||||||
|
|
||||||
// Determine the value of the sample at the given non-integer location
|
return sum;
|
||||||
// through linear interpolation of the nearest samples
|
|
||||||
return leftValue + (rightValue - leftValue) / (right - left) * (index - left);
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user