audiojs/audio

View on GitHub
src/metrics.js

Summary

Maintainability
A
2 hrs
Test Coverage
/**
 * Extend audio with playback functionality
 *
 * @module  audio/src/metrics
 */

'use strict'


const ft = require('fourier-transform')

//TODO: make external package
const loudness = {
    rms: require('compute-qmean')
}

let {parseArgs} = require('./util')
let Audio = require('../')

//get amplitudes range for the interval
Audio.prototype.limits = function (time, duration, options) {
    options = parseArgs(this, time, duration, options)

    if (this.stats) {
        //TODO: implement fast bounds search, extremum-based
    }

    let max = -1, min = 1

    //search across channels
    this.buffer.map((buf, idx, offset) => {
        for (let c = 0, l = buf.length; c < options.channels.length; c++) {
            let channel = options.channels[c]
            let data = buf.getChannelData(channel)

            for (let i = 0; i < l; i++) {
                if (data[i] > max) max = data[i]
                if (data[i] < min) min = data[i]
            }
        }
    }, options.start, options.end)

    return [min, max]
}

Audio.prototype.spectrum = function (start, options) {
    if (typeof start !== 'number') {
        options = start
    }
    options = options || {}
    start = start || 0

    if (!options.size) options.size = 1024;

    if (!bit.isPow2(options.size)) throw Error('Size must be a power of 2')

    if (options.channel == null) options.channel = 0;

    let buf = this.readRaw(start * this.buffer.sampleRate, options.size);
    let waveform = buf.getChannelData(options.channel);
    let magnitudes = ft(waveform);

    if (options.db) {
        magnitudes = magnitudes.map(value => db.fromGain(value))
    }

    return magnitudes;
}

Audio.prototype.cepstrum = function () {

}

Audio.prototype.stats = function () {

}

//calculate loudness by provided method/interval
Audio.prototype.loudness = function (time, duration, options) {
    if (typeof options === 'string') options = {method: options}

    options = parseArgs(this, time, duration, options)

    if (options.type) options.method = options.type

    let calc = loudness[options.method] || loudness.rms

    let result = []

    let mean2 = []
    if (this.stats) {
        for (let c = 0; c < options.channels.length; c++) {
            let channel = options.channels[c]
            mean2.push(this.stats.mean2[channel])
        }
    }
    else {
        //TODO: compute-qmean has faster rms calculation, utilize it's method
        for (let c = 0; c < options.channels.length; c++) {
            let channel = options.channels[c]
            let data = this.getChannelData(channel, options.from, options.duration)
            let sum2 = 0
            for (let i = 0, l = data.length; i < l; i++) {
                // sum2 +=
            }

            // result.push(val)
        }
    }


    return options.channels.length === 1 ? result[0] : result
}


Audio.prototype.size = function size () {

    return this;
}