ciseaux
Version:
utility to chop an audio buffer
462 lines (367 loc) • 13.9 kB
JavaScript
"use strict";
var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })();
function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
/* eslint no-use-before-define: 0 */
var AudioData = require("audiodata");
var Track = require("./track");
var Fragment = require("./fragment");
var config = require("./config");
var renderer = require("./renderer");
var util = {};
var Tape = (function () {
_createClass(Tape, null, [{
key: "silence",
value: function silence(duration) {
return new Tape(1, config.sampleRate).silence(duration);
}
}, {
key: "concat",
value: function concat() {
var _ref;
return (_ref = new Tape(1, config.sampleRate)).concat.apply(_ref, arguments);
}
}, {
key: "mix",
value: function mix() {
var _ref2;
var newInstance = (_ref2 = new Tape(1, config.sampleRate)).mix.apply(_ref2, arguments);
if (1 < newInstance.tracks.length) {
newInstance.tracks.shift(); // remove first empty track
}
return newInstance;
}
}]);
function Tape(arg1, arg2) {
_classCallCheck(this, Tape);
if (AudioData.isAudioData(arg1)) {
return new TransferredTape(arg1);
}
this.tracks = [new Track()];
this._numberOfChannels = Math.max(1, arg1 | 0);
this._sampleRate = Math.max(0, arg2 | 0) || config.sampleRate;
}
_createClass(Tape, [{
key: "gain",
value: function gain() {
var _gain = arguments.length <= 0 || arguments[0] === undefined ? 1 : arguments[0];
_gain = util.toNumber(_gain);
var newInstance = new Tape(this.numberOfChannels, this.sampleRate);
newInstance.tracks = this.tracks.map(function (track) {
return track.gain(_gain);
});
return newInstance;
}
}, {
key: "pan",
value: function pan() {
var _pan = arguments.length <= 0 || arguments[0] === undefined ? 0 : arguments[0];
_pan = util.toNumber(_pan);
var newInstance = new Tape(this.numberOfChannels, this.sampleRate);
newInstance.tracks = this.tracks.map(function (track) {
return track.pan(_pan);
});
return newInstance;
}
}, {
key: "reverse",
value: function reverse() {
var newInstance = new Tape(this.numberOfChannels, this.sampleRate);
newInstance.tracks = this.tracks.map(function (track) {
return track.reverse();
});
return newInstance;
}
}, {
key: "pitch",
value: function pitch() {
var rate = arguments.length <= 0 || arguments[0] === undefined ? 1 : arguments[0];
rate = Math.max(0, util.toNumber(rate));
var newInstance = new Tape(this.numberOfChannels, this.sampleRate);
newInstance.tracks = this.tracks.map(function (track) {
return track.pitch(rate);
});
return newInstance;
}
}, {
key: "stretch",
value: function stretch() {
var rate = arguments.length <= 0 || arguments[0] === undefined ? 1 : arguments[0];
rate = Math.max(0, util.toNumber(rate));
var newInstance = new Tape(this.numberOfChannels, this.sampleRate);
newInstance.tracks = this.tracks.map(function (track) {
return track.stretch(rate);
});
return newInstance;
}
}, {
key: "clone",
value: function clone() {
var newInstance = new Tape(this.numberOfChannels, this.sampleRate);
newInstance.tracks = this.tracks.map(function (track) {
return track.clone();
});
return newInstance;
}
}, {
key: "silence",
value: function silence() {
var duration = arguments.length <= 0 || arguments[0] === undefined ? 0 : arguments[0];
duration = Math.max(0, util.toNumber(duration));
var newInstance = new Tape(this.numberOfChannels, this.sampleRate);
if (0 < duration) {
newInstance.tracks = this.tracks.map(function () {
return Track.silence(duration);
});
}
return newInstance;
}
}, {
key: "concat",
value: function concat() {
for (var _len = arguments.length, tapes = Array(_len), _key = 0; _key < _len; _key++) {
tapes[_key] = arguments[_key];
}
tapes = Array.prototype.concat.apply([], tapes);
var newInstance = new Tape(this.numberOfChannels, this.sampleRate);
newInstance.tracks = this.tracks.map(function (track) {
return track.clone();
});
tapes.forEach(function (tape) {
if (!(tape instanceof Tape && 0 < tape.duration)) {
return;
}
if (newInstance._numberOfChannels < tape._numberOfChannels) {
newInstance._numberOfChannels = tape._numberOfChannels;
}
if (newInstance.numberOfTracks < tape.numberOfTracks) {
newInstance = util.adjustNumberOfTracks(newInstance, tape.numberOfTracks);
}
if (tape.numberOfTracks < newInstance.numberOfTracks) {
tape = util.adjustNumberOfTracks(tape, newInstance.numberOfTracks);
}
tape.tracks.forEach(function (track, index) {
newInstance.tracks[index].append(track);
});
});
return newInstance;
}
}, {
key: "slice",
value: function slice() {
var beginTime = arguments.length <= 0 || arguments[0] === undefined ? 0 : arguments[0];
var duration = arguments.length <= 1 || arguments[1] === undefined ? Infinity : arguments[1];
beginTime = util.toNumber(beginTime);
duration = Math.max(0, util.toNumber(duration));
if (beginTime < 0) {
beginTime += this.duration;
}
beginTime = Math.max(0, beginTime);
var newInstance = new Tape(this.numberOfChannels, this.sampleRate);
newInstance.tracks = this.tracks.map(function (track) {
return track.slice(beginTime, duration);
});
return newInstance;
}
}, {
key: "loop",
value: function loop() {
var n = arguments.length <= 0 || arguments[0] === undefined ? 2 : arguments[0];
n = Math.max(0, n | 0);
var tapes = new Array(n);
for (var i = 0; i < tapes.length; i++) {
tapes[i] = this;
}
return new Tape(this.numberOfChannels, this.sampleRate).concat(tapes);
}
}, {
key: "fill",
value: function fill() {
var duration = arguments.length <= 0 || arguments[0] === undefined ? this.duration : arguments[0];
duration = Math.max(0, util.toNumber(duration));
var this$duration = this.duration;
if (this$duration === 0) {
return this.silence(duration);
}
var loopCount = Math.floor(duration / this$duration);
var remain = duration % this$duration;
return this.loop(loopCount).concat(this.slice(0, remain));
}
}, {
key: "replace",
value: function replace() {
var beginTime = arguments.length <= 0 || arguments[0] === undefined ? 0 : arguments[0];
var duration = arguments.length <= 1 || arguments[1] === undefined ? 0 : arguments[1];
var tape = arguments.length <= 2 || arguments[2] === undefined ? null : arguments[2];
beginTime = util.toNumber(beginTime);
duration = Math.max(0, util.toNumber(duration));
if (beginTime < 0) {
beginTime += this.duration;
}
beginTime = Math.max(0, beginTime);
if (typeof tape === "function") {
tape = tape(this.slice(beginTime, duration));
}
return this.slice(0, beginTime).concat(tape, this.slice(beginTime + duration));
}
}, {
key: "split",
value: function split() {
var n = arguments.length <= 0 || arguments[0] === undefined ? 2 : arguments[0];
n = Math.max(0, n | 0);
var tapes = new Array(n);
var duration = this.duration / n;
for (var i = 0; i < n; i++) {
tapes[i] = this.slice(duration * i, duration);
}
return tapes;
}
}, {
key: "mix",
value: function mix() {
for (var _len2 = arguments.length, tapes = Array(_len2), _key2 = 0; _key2 < _len2; _key2++) {
tapes[_key2] = arguments[_key2];
}
tapes = Array.prototype.concat.apply([], tapes);
var method = undefined;
if (typeof tapes[tapes.length - 1] === "string") {
method = tapes.pop();
}
var newInstance = new Tape(this.numberOfChannels, this.sampleRate);
newInstance.tracks = this.tracks.map(function (track) {
return track.clone();
});
tapes.forEach(function (tape) {
if (!(tape instanceof Tape && 0 < tape.duration)) {
return;
}
if (newInstance._numberOfChannels < tape._numberOfChannels) {
newInstance._numberOfChannels = tape._numberOfChannels;
}
if (newInstance.duration < tape.duration) {
newInstance = util.adjustDuration(newInstance, tape.duration, method);
}
if (tape.duration < newInstance.duration) {
tape = util.adjustDuration(tape, newInstance.duration, method);
}
newInstance.tracks = newInstance.tracks.concat(tape.tracks);
});
return newInstance;
}
}, {
key: "render",
value: function render() {
if (config.render) {
for (var _len3 = arguments.length, args = Array(_len3), _key3 = 0; _key3 < _len3; _key3++) {
args[_key3] = arguments[_key3];
}
return config.render.apply(config, [this.toJSON()].concat(args));
}
return new Promise(function (resolve, reject) {
reject(new Error("not implemented"));
});
}
}, {
key: "dispose",
value: function dispose() {
/* subclass responsibility */
}
}, {
key: "toJSON",
value: function toJSON() {
var tracks = this.tracks.map(function (track) {
return track.toJSON();
});
var duration = this.duration;
var sampleRate = this.sampleRate;
var numberOfChannels = this.numberOfChannels;
var usePan = tracks.some(function (fragments) {
return fragments.some(function (fragment) {
return fragment.pan !== 0;
});
});
if (usePan) {
numberOfChannels = Math.max(2, numberOfChannels);
}
return { tracks: tracks, duration: duration, sampleRate: sampleRate, numberOfChannels: numberOfChannels };
}
}, {
key: "sampleRate",
get: function get() {
return this._sampleRate || config.sampleRate;
}
}, {
key: "length",
get: function get() {
return Math.floor(this.duration * this.sampleRate);
}
}, {
key: "duration",
get: function get() {
return this.tracks[0].duration;
}
}, {
key: "numberOfChannels",
get: function get() {
return this._numberOfChannels;
}
}, {
key: "numberOfTracks",
get: function get() {
return this.tracks.length;
}
}]);
return Tape;
})();
var TransferredTape = (function (_Tape) {
_inherits(TransferredTape, _Tape);
function TransferredTape(audiodata) {
_classCallCheck(this, TransferredTape);
var _this = _possibleConstructorReturn(this, Object.getPrototypeOf(TransferredTape).call(this, AudioData.getNumberOfChannels(audiodata), audiodata.sampleRate));
var duration = AudioData.getDuration(audiodata);
_this._data = renderer.transfer(audiodata);
_this.tracks[0].addFragment(new Fragment(_this._data, 0, duration));
config.sampleRate = config.sampleRate || audiodata.sampleRate;
return _this;
}
_createClass(TransferredTape, [{
key: "dispose",
value: function dispose() {
renderer.dispose(this._data);
}
}]);
return TransferredTape;
})(Tape);
util.toNumber = function (num) {
return +num || 0;
};
util.adjustNumberOfTracks = function (tape, numberOfTracks) {
var newInstance = new Tape(tape.numberOfChannels, tape.sampleRate);
newInstance.tracks = tape.tracks.map(function (track) {
return track.clone();
});
var balance = numberOfTracks - newInstance.numberOfTracks;
var duration = newInstance.duration;
for (var i = 0; i < balance; i++) {
newInstance.tracks.push(Track.silence(duration));
}
return newInstance;
};
util.adjustDuration = function (tape, duration, method) {
if (tape.duration === 0) {
return tape.silence(duration);
}
switch (method) {
case "fill":
return tape.fill(duration);
case "pitch":
return tape.pitch(tape.duration / duration);
case "stretch":
return tape.stretch(tape.duration / duration);
default:
/* silence */
return tape.concat(tape.silence(duration - tape.duration));
}
};
module.exports = Tape;