UNPKG

audio-2.0.0

Version:

Class for high-level audio manipulations

159 lines (136 loc) 4.18 kB
/** * lil helpers */ 'use strict' const callsites = require('callsites') const extend = require('extend') const nidx = require('negative-index') const isBrowser = require('is-browser') const isRelative = require('is-relative') const isURL = require('is-url') const path = require('path') const pick = require('pick-by-alias') module.exports = { isMultisource, parseArgs, resolvePath } // if source is multisource function isMultisource(arg) { return Array.isArray(arg) && !(typeof arg[0] === 'number' && (arg.length === 1 || typeof arg[1] === 'number')) && !(arg.length < 32 && arg.every(ch => Array.isArray(ch) || ArrayBuffer.isView(ch))) } // calc start, end, length and channels params from options function parseArgs (audio, time, duration, options) { // no args at all if (time == null && duration == null && options == null) { options = {} time = 0 duration = audio.duration } // single arg else if (time != null && duration == null && options == null) { // {} if (typeof time !== 'number') { options = time time = 0 duration = audio.duration } // number else { options = {} duration = audio.duration } } // two args else if (time != null && duration != null && options == null) { // 1, 1 if (typeof duration === 'number') { options = {} } // 1, {} else if (typeof duration != 'number') { options = duration duration = audio.duration } } if (typeof time !== 'number') throw Error('Bad argument `time`') if (time == null) time = 0 if (duration == null) duration = audio.duration if (!time && duration < 0) time = -0; options = pick(options, { channel: 'channel ch numberOfChannel', channels: 'channels channelMap', destination: 'destination dest dst target out output container', start: 'start startTime fromTime', end: 'end endTime toTime', from: 'from offset fromOffset startOffset', to: 'to toOffset endOffset', duration: 'duration time', length: 'length number', format: 'format dtype dataFormat dataType type', keep: 'keep cut keepFragment return', copy: 'copy cpy cp clone', left: 'left beginning begin head', right: 'right ending end tail', threshold: 'threshold level lvl tol db', value: 'value val', rotate: 'rotate circular' }) // ensure channels if (options.channel != null) { options.channels = options.channel } if (typeof options.channels === 'number') { options.channels = [options.channels] } if (options.channels == null) { let channels = options.channels || audio.channels options.channels = [] for (let i = 0; i < channels; i++) { options.channels.push(i) } } if (!Array.isArray(options.channels)) { throw Error('Bad `channels` argument') } // take over from/to params // FIXME: reconsider these params if (options.from != null) time = options.from if (options.to != null) duration = options.to - time if (options.length != null) duration = options.length * audio.sampleRate if (options.duration != null) duration = options.duration // detect raw interval if (options.start == null) { let startOffset = Math.floor(time * audio.sampleRate) startOffset = nidx(startOffset, audio.buffer.length) options.start = startOffset } if (options.end == null) { let len = Math.ceil(duration * audio.sampleRate) let endOffset; if (len < 0) { endOffset = nidx(options.start + len, audio.buffer.length) } else { endOffset = Math.min(options.start + len, audio.buffer.length) } options.end = endOffset } // provide full options if (options.length == null) options.length = options.end - options.start if (options.from == null) options.from = options.start / audio.sampleRate if (options.to == null) options.to = options.end / audio.sampleRate if (options.duration == null) options.duration = options.length / audio.sampleRate return options } // path resolver taking in account file structure function resolvePath (fileName, depth=2) { if (!isBrowser && isRelative(fileName) && !isURL(fileName)) { var callerPath = callsites()[depth].getFileName() fileName = path.dirname(callerPath) + path.sep + fileName fileName = path.normalize(fileName) } return fileName }