From 14ae8dee203d1e554f4813cadbf05f642104e7c3 Mon Sep 17 00:00:00 2001 From: stephband Date: Mon, 22 Oct 2018 03:34:33 +0200 Subject: [PATCH] Envelope test --- index.html | 13 ++-- modules/audio-objects/output.js | 59 ----------------- modules/nodes/envelope.js | 3 +- .../nodes/envelope.test.js | 64 +++++++++---------- modules/nodes/output.js | 51 +++++++++++++++ modules/nodes/tick.js | 14 ++-- modules/soundstage.js | 20 +----- 7 files changed, 98 insertions(+), 126 deletions(-) delete mode 100644 modules/audio-objects/output.js rename test/node-envelope.test.js => modules/nodes/envelope.test.js (54%) create mode 100644 modules/nodes/output.js diff --git a/index.html b/index.html index c025b27..f361f10 100644 --- a/index.html +++ b/index.html @@ -76,9 +76,6 @@

- - - diff --git a/modules/audio-objects/output.js b/modules/audio-objects/output.js deleted file mode 100644 index 7d18e8c..0000000 --- a/modules/audio-objects/output.js +++ /dev/null @@ -1,59 +0,0 @@ - -import AudioObject from '../../../audio-object/modules/audio-object.js'; - -var Soundstage = window.Soundstage; -var assign = Object.assign; -var defaults = { channels: [0, 1] }; - -var rautoname = /Out\s\d+\/\d+/; - -function increment(n) { return n + 1; } - -export default function Output(audio, settings, output) { - var options = assign({}, defaults, settings); - var channels = []; - var object = this; - var input = new ChannelSplitterNode(audio, { - numberOfOutputs: 2 - }); - - AudioObject.call(this, audio, input); - - Object.defineProperties(this, { - channels: { - get: function() { return channels; }, - set: function(array) { - // Where there is no change do nothing - if (array + '' === channels + '') { return; } - - //input.disconnect(output); - var count = array.length > output.numberOfInputs ? - output.numberOfInputs : - array.length ; - - while (count--) { - // output.channelCount may not be as high as the index - // of channel in array. Ignore routings to channels the - // output does not have. - if (array[count] > output.channelCount) { continue; } - input.connect(output, count, array[count]); - channels[count] = array[count]; - } - - if (!object.name || rautoname.test(object.name)) { - object.name = 'Out ' + channels.map(increment).join('-'); - } - }, - enumerable: true, - configurable: true - } - }); - - this.channels = options.channels; - - this.destroy = function destroy() { - input.disconnect(output); - }; -} - -Output.prototype = AudioObject.prototype; diff --git a/modules/nodes/envelope.js b/modules/nodes/envelope.js index 34ac807..2b02629 100644 --- a/modules/nodes/envelope.js +++ b/modules/nodes/envelope.js @@ -22,7 +22,8 @@ function cueAutomation(param, events, time, gain, rate) { param.cancelAndHoldAtTime(time); for (let event of events) { - automate(param, time + event[0] / rate, event[1], event[2] * gain, event[3], arguments[5]); + // param, time, curve, value, decay + automate(param, time + event[0] / rate, event[1], event[2] * gain, event[3]); } } diff --git a/test/node-envelope.test.js b/modules/nodes/envelope.test.js similarity index 54% rename from test/node-envelope.test.js rename to modules/nodes/envelope.test.js index b1273a3..1f537f3 100644 --- a/test/node-envelope.test.js +++ b/modules/nodes/envelope.test.js @@ -1,11 +1,11 @@ -import { test } from '../../fn/fn.js'; -import { create, append, find } from '../../dom/dom.js'; -import { getValueAtTime, getAutomationEvents, requestAutomationData } from '../modules/audio-param.js'; -import EnvelopeNode from '../modules/nodes/envelope.js'; -import { drawYAxisAmplitude, drawCurve, drawPoint } from '../modules/canvas.js'; -import audio from '../modules/audio-context.js'; +import { test } from '../../../fn/fn.js'; +import { create, append, find } from '../../../dom/dom.js'; +import { getValueAtTime, getAutomationEvents, requestAutomationData } from '../audio-param.js'; +import Envelope from './envelope.js'; +import { drawYAxisAmplitude, drawCurve, drawPoint } from '../canvas.js'; +import audio from '../audio-context.js'; -test('EnvelopeNode', function(run, print, fixture) { +test('Envelope', function(run, print, fixture) { const canvas = find('canvas', fixture); const ctx = canvas.getContext('2d'); const box = [2, 2, 636, 355]; @@ -14,23 +14,22 @@ test('EnvelopeNode', function(run, print, fixture) { run('getValueAtTime(param, time)', function(equals, done) { const offline = new OfflineAudioContext(1, 22050, 22050); - const envelope = new EnvelopeNode(offline, { - sequences: { - attack: [ - [0, 0, 'step'], - [0.05, 1, 'linear'], - [0.05, 0.8, 'target', 0.1] - ], + const envelope = new Envelope(offline, { + attack: [ + [0, 'step', 0], + [0.05, 'linear', 1], + [0.05, 'target', 0.8, 0.1] + ], - release: [ - [0, 0, 'target', 0.1] - ] - } + release: [ + [0, 'target', 0, 0.1] + ] }); envelope.connect(offline.destination); - envelope.start(0.1); - envelope.stop(0.2); + envelope.start(0.1, 'attack'); + envelope.start(0.2, 'release'); + envelope.stop(1); offline.startRendering().then(function(buffer) { console.log(buffer); @@ -43,23 +42,22 @@ test('EnvelopeNode', function(run, print, fixture) { run('getValueAtTime(param, time)', function(equals, done) { const offline = new OfflineAudioContext(1, 22050, 22050); - const envelope = new EnvelopeNode(offline, { - sequences: { - attack: [ - [0, 0, 'step'], - [0.4, 1, 'linear'], - [0.4, 0.8, 'target', 0.1] - ], + const envelope = new Envelope(offline, { + attack: [ + [0, 'step', 0], + [0.4, 'linear', 1], + [0.4, 'target', 0.8, 0.1] + ], - release: [ - [0, 0, 'target', 0.1] - ] - } + release: [ + [0, 'target', 0, 0.1] + ] }); envelope.connect(offline.destination); - envelope.start(0.1); - envelope.stop(0.2); + envelope.start(0.1, 'attack'); + envelope.start(0.2, 'release'); + envelope.stop(1); offline.startRendering().then(function(buffer) { console.log(buffer); diff --git a/modules/nodes/output.js b/modules/nodes/output.js new file mode 100644 index 0000000..ecfe965 --- /dev/null +++ b/modules/nodes/output.js @@ -0,0 +1,51 @@ + +const assign = Object.assign; +const define = Object.defineProperties; +const rautoname = /Out\s\d+\/\d+/; +const defaults = { + channels: [0, 1] +}; + +function increment(n) { return n + 1; } + +export default class Output extends ChannelSplitterNode { + constructor(context, settings, output) { + var options = assign({}, defaults, settings); + options.numberOfOutputs = options.channels.length || 2; + super(context, options); + + var channels = []; + + define(this, { + channels: { + get: function() { return channels; }, + set: function(array) { + // Where there is no change do nothing + if (array + '' === channels + '') { return; } + + //this.disconnect(output); + var count = array.length > output.numberOfInputs ? + output.numberOfInputs : + array.length ; + + while (count--) { + // output.channelCount may not be as high as the index + // of channel in array. Ignore routings to channels the + // output does not have. + if (array[count] > output.channelCount) { continue; } + this.connect(output, count, array[count]); + channels[count] = array[count]; + } + + if (!this.name || rautoname.test(this.name)) { + this.name = 'Out ' + channels.map(increment).join('-'); + } + }, + enumerable: true, + configurable: true + } + }); + + this.channels = options.channels; + } +} diff --git a/modules/nodes/tick.js b/modules/nodes/tick.js index 544b953..eada238 100644 --- a/modules/nodes/tick.js +++ b/modules/nodes/tick.js @@ -113,13 +113,13 @@ export default function Tick(audio, options) { return this; }; - this.stop = function(time) { - // Don't. It's causing problems. I think we'll simply live with the - // fact that the metronome doesn't stop immediately when you stop - // the sequencer. - //unschedule(time, this.decay); - return this; - }; + //this.stop = function(time) { + // // Don't. It's causing problems. I think we'll simply live with the + // // fact that the metronome doesn't stop immediately when you stop + // // the sequencer. + // //unschedule(time, this.decay); + // return this; + //}; this.stop = function(time) { stop(time || audio.currentTime, this.decay); diff --git a/modules/soundstage.js b/modules/soundstage.js index 8c591c4..714e4c9 100644 --- a/modules/soundstage.js +++ b/modules/soundstage.js @@ -7,7 +7,7 @@ import { print } from './print.js'; import { distributeEvent } from './distribute.js'; import audio from './audio-context.js'; import Input from './audio-objects/input.js'; -import Output from './audio-objects/output.js'; +import Output from './nodes/output.js'; import Graph from './graph.js'; import requestPlugin from './request-plugin.js'; import Controls from './controls.js'; @@ -79,11 +79,6 @@ export default function Soundstage(data, settings) { // // audio: audio context -/* -.context() -The audio context. -*/ - const context = settings.context || audio; const destination = settings.output || context.destination; const output = createOutputMerger(context, destination); @@ -91,6 +86,7 @@ The audio context. AudioObject.call(this, context, undefined, output); Soundstage.inspector && Soundstage.inspector.drawAudioFromNode(output); + // Initialise soundstage as a plugin graph. Assigns: // // plugins: array @@ -129,12 +125,6 @@ The audio context. // // controls: array-like -/* -.controls() - -An array-like list of controls. -*/ - this.ready(function graphReady(stage) { define(stage, { controls: { @@ -160,12 +150,6 @@ An array-like list of controls. // // regions: array -/* -.regions() - -An array of audio regions. -*/ - const regions = this.regions = (settings.regions || []).map(function(data) {