JS-Xtract

Using Procedural Calls

Procedural calls are a way of directly calling a function which is global in scope. This means it is not a member of any object and can be called by any other function that is within scope of it. In JS-Xtract, all the features are supplied as procedural calls. Each function accepts a data, usually as an array, and some extra arguments should they be required. The individual function pages will give an overview of each function

Example

In JavaScript we can calculate the mean of a signal

// Assume the wave is contained in wave
var wave = new Float64Array(1024);

var mean = xtract_mean(wave);
console.log(mean);
// Will display the mean in the browser console

Procedural calls enable the feature extraction library to be modified into many different formats without actually modifying the functions being operated upon. This way we can have Object-Oriented calls as well as callback functions all using procedural calling.

Chaining

Procedural calls enable complex features to be derived easily by stacking them into a chain. For instance we could calculate the loudness from a time domain source

var N = 1024;
var sampleRate = 44100.0;
var wave = new Float64Array(N);
// Assume the wave is contained in wave

// Calculate the spectrum with a sample rate of 44.1kHz
var spectrum = xtract_spectrum(wave,sampleRate,true,false);

// Define the boundaries for the bark bands
var barkBands = xtract_init_bark(N/2+1);

// Calculate the bark band coefficients
var barkCoeffs = xtract_bark_coefficients(spectrum,barkBands);

// Process the bark band coefficients to get the loudness
var loudness = xtract_loudness(barkCoeffs);

// Display the loudness in the console
console.log(loudness);

Chaining the feature extraction functions together like this has one key advantage over the C library style calls. Take the following function call xtract_variance(data, mean). The function call for the variance requires the data array and the mean of the data. We could process it like this:

var mean = xtract_mean(data);

var variance = xtract_variace(data, mean);

// Or in one line:

var variance = xtract_variance(data,xtract_mean(data));

The JavaScript langauge defines a special object called "undefined" which allows an argument to be ignored, or a variable to be created but not assigned anything. In traditional langauges, like C, if I write float mean;, then the value 'mean' will be created and will be populated with some giberish. If I then passed that in to a function, on execution the function will see a number and execute using that number giving undefined results! However there is no way to detect that. In javascript, if I write the equivalent var mean;, then the 'mean' is given the value of "undefined". Because of this state we can detect it. For the xtract_variance instance above, we can write the following:

var variance = xtract_variance(data);

On execution, the mean is still passed but is "undefined". Instead of throwing an error, the function simply calculates the mean in-place, uses it and discards it. This makes processing simpler especially for use once variables. However, do note that if you are using functions which are all using the same underlying feature, such as the mean, it may be more efficient to call xtract_mean and store the variable to pass through.

There is a key double-edged sword to this though. The kurtosis function is a key example of this. The function takes three arguments, the data, mean and spectral_deviation. If only the data argument is supplied, the mean and spectral deviation have to be calculated. The function header is as follows:

if (typeof mean != "number") {
    mean = xtract_mean(array);
}
if (typeof standard_deviation != "number") {
    standard_deviation = xtract_standard_deviation(array, xtract_variance(data, mean));
}

So firstly, it determines if the mean variable is a number, if not it calculates the mean. The same is done for the standard deviation, however the standard deviation takes the variance. Now the function detects it must have a valid mean in there (either passed in or just calculated) so it calls the xtract_variance straight away, saving on computing the mean again. This variance is fed straight into the stanrd_deviation function and is therefore discarded. The real danger here is, the variance may have actually been computed somewhere else, but we cannot pass in the variance directly. The other major danger is if we then call, for example, the skewness which takes the same arguments. All the data is computed internally again, although we have actually computed this already. Therefore it is impertitive in time sensitive operations to keep function calls and variables that may be re-used.

The information in the temporal feature list give the argument, the expected data type and if the argument is mandatory. If it is not mandatory, then the auto-compute function is shown. For the kurtosis feature, the standard_deviation function has the auto-complete variable of xtract_standard_deviation(array, xtract_variance(data, mean)); showing you the exact features that are called.