UNPKG

dilla

Version:

Schedule looped playback of Web Audio notes at 96 ticks per beat

451 lines (431 loc) 14.9 kB
var chai = require('chai'); var expect = chai.expect; var Dilla = require('../index'); var MockAudioContext = require('./mocks/AudioContext'); var audioContext = new MockAudioContext(); var dilla; beforeEach(function () { dilla = new Dilla(audioContext); }); describe('Dilla (audioContext, options)', function () { describe('when audioContext is not an object', function () { it('should throw an error', function () { expect(function () { new Dilla(); }).to.throw(/invalid argument/i); }); }); describe('when called without "new"', function () { it('should still return a new instance', function () { dilla = Dilla(audioContext); expect(dilla).to.be.instanceOf(Dilla); }); }); describe('when options are defined', function () { it('should set the tempo', function () { dilla = new Dilla(audioContext, { 'tempo': 122 }); expect(dilla.tempo()).to.equal(122); }); it('should set the beatsPerBar', function () { dilla = new Dilla(audioContext, { 'beatsPerBar': 7 }); expect(dilla.beatsPerBar()).to.equal(7); }); it('should set the loopLength', function () { dilla = new Dilla(audioContext, { 'loopLength': 3 }); expect(dilla.loopLength()).to.equal(3); }); }); }); describe('dilla.getDurationFromTicks (ticks)', function () { describe('when "ticks" is not a number', function () { it('should throw an error', function () { expect(function () { dilla.getDurationFromTicks(); }).to.throw(/invalid argument/i); expect(function () { dilla.getDurationFromTicks('foo'); }).to.throw(/invalid argument/i); expect(function () { dilla.getDurationFromTicks({}); }).to.throw(/invalid argument/i); expect(function () { dilla.getDurationFromTicks(true); }).to.throw(/invalid argument/i); expect(function () { dilla.getDurationFromTicks(parseInt('foo', 10)); }).to.throw(/invalid argument/i); }); }); describe('when "ticks" is a negative number', function () { it('should throw an error', function () { expect(function () { dilla.getDurationFromTicks(-10); }).to.throw(/invalid argument/i); }); }); describe('when "ticks" is a positive number', function () { it('should return clock duration for ticks', function () { expect(dilla.getDurationFromTicks(48)).to.equal(0.5); expect(dilla.getDurationFromTicks(96)).to.equal(1); }); }); }); describe('dilla.setLoopLength (bars)', function () { describe('when "bars" is not a number', function () { it('should throw an error', function () { expect(function () { dilla.setLoopLength(); }).to.throw(/invalid argument/i); expect(function () { dilla.setLoopLength('foo'); }).to.throw(/invalid argument/i); expect(function () { dilla.setLoopLength({}); }).to.throw(/invalid argument/i); expect(function () { dilla.setLoopLength(true); }).to.throw(/invalid argument/i); expect(function () { dilla.setLoopLength(parseInt('foo', 10)); }).to.throw(/invalid argument/i); }); }); describe('when "bars" is a negative number', function () { it('should throw an error', function () { expect(function () { dilla.setLoopLength(-10); }).to.throw(/invalid argument/i); }); }); describe('when "bars" is a positive number', function () { it('should set the loop length', function () { dilla.setLoopLength(5); expect(dilla.loopLength()).to.equal(5); }); }); }); describe('dilla.setBeatsPerBar (beats)', function () { describe('when "beats" is not a number', function () { it('should throw an error', function () { expect(function () { dilla.setBeatsPerBar(); }).to.throw(/invalid argument/i); expect(function () { dilla.setBeatsPerBar('foo'); }).to.throw(/invalid argument/i); expect(function () { dilla.setBeatsPerBar({}); }).to.throw(/invalid argument/i); expect(function () { dilla.setBeatsPerBar(true); }).to.throw(/invalid argument/i); expect(function () { dilla.setBeatsPerBar(parseInt('foo', 10)); }).to.throw(/invalid argument/i); }); }); describe('when "beats" is a negative number', function () { it('should throw an error', function () { expect(function () { dilla.setBeatsPerBar(-10); }).to.throw(/invalid argument/i); }); }); describe('when "beats" is a positive number', function () { it('should set the loop length', function () { dilla.setBeatsPerBar(3); expect(dilla.beatsPerBar()).to.equal(3); }); }); }); describe('dilla.tempo ()', function () { it('should return the current tempo', function () { expect(dilla.tempo()).to.equal(120); }); }); describe('dilla.setTempo (bpm)', function () { describe('when "bpm" is not a number', function () { it('should throw an error', function () { expect(function () { dilla.setTempo(); }).to.throw(/invalid argument/i); expect(function () { dilla.setTempo('foo'); }).to.throw(/invalid argument/i); expect(function () { dilla.setTempo({}); }).to.throw(/invalid argument/i); expect(function () { dilla.setTempo(true); }).to.throw(/invalid argument/i); expect(function () { dilla.setTempo(parseInt('foo', 10)); }).to.throw(/invalid argument/i); }); }); describe('when "bpm" is a negative number', function () { it('should throw an error', function () { expect(function () { dilla.setTempo(-10); }).to.throw(/invalid argument/i); }); }); describe('when "bpm" is a positive number', function () { it('should set the loop length', function () { dilla.setTempo(92); expect(dilla.tempo()).to.equal(92); }); }); }); describe('dilla.setPosition (position)', function () { describe('when an invalid position is passed', function () { it('should throw an error', function () { expect(function () { dilla.setPosition(); }).to.throw(/invalid argument/i); expect(function () { dilla.setPosition(10); }).to.throw(/invalid argument/i); expect(function () { dilla.setPosition(true); }).to.throw(/invalid argument/i); }); }); describe('when the position is out of bounds', function () { it('should throw an error', function () { expect(function () { dilla.setPosition('1.1.97'); }).to.throw(/invalid argument/i); expect(function () { dilla.setPosition('1.8.01'); }).to.throw(/invalid argument/i); expect(function () { dilla.setPosition('4.1.01'); }).to.throw(/invalid argument/i); }); }); describe('when a valid position is passed', function () { it('should set the clock position', function () { dilla.setPosition('1.3.45'); expect(dilla.position()).to.equal('1.3.45'); }); }); }); describe('dilla.getPositionFromClockPosition (clockPosition)', function () { describe('when clockPosition is not a valid number', function () { it('should throw an error', function () { expect(function () { dilla.getPositionFromClockPosition(); }).to.throw(/invalid argument/i); expect(function () { dilla.getPositionFromClockPosition('foo'); }).to.throw(/invalid argument/i); expect(function () { dilla.getPositionFromClockPosition(parseInt('foo', 10)); }).to.throw(/invalid argument/i); expect(function () { dilla.getPositionFromClockPosition(true); }).to.throw(/invalid argument/i); }); }); describe('when clockPosition is negative', function () { it('should return 0.0.00', function () { expect(dilla.getPositionFromClockPosition(-0.1)).to.equal('0.0.00'); }); }); describe('when clockPosition is positive', function () { it('should return the correct position', function () { expect(dilla.getPositionFromClockPosition(0)).to.equal('1.1.01'); expect(dilla.getPositionFromClockPosition(1)).to.equal('1.2.01'); expect(dilla.getPositionFromClockPosition(0.5)).to.equal('1.1.49'); expect(dilla.getPositionFromClockPosition(3.75)).to.equal('1.4.73'); }); }); }); describe('dilla.getClockPositionFromPosition', function () { it('should return the correct clock position', () => { expect(dilla.getClockPositionFromPosition('1.1.01', 4)).to.equal(0) expect(dilla.getClockPositionFromPosition('1.3.01', 4)).to.equal(2) expect(dilla.getClockPositionFromPosition('3.1.01', 4)).to.equal(8) expect(dilla.getClockPositionFromPosition('3.2.49', 4)).to.equal(9.5) }) describe('when beatsPerBar changes from the last call', () => { it('should return the correct clock position', () => { expect(dilla.getClockPositionFromPosition('3.1.01', 4)).to.equal(8) expect(dilla.getClockPositionFromPosition('3.1.01', 3)).to.equal(6) }) }) }); describe('dilla.getPositionWithOffset (position, offset)', function () { describe('when position is not a valid position string', function () { it('should throw an error', function () { expect(function () { dilla.getPositionWithOffset('1.1.a', 96); }).to.throw(/invalid argument/i); }); }); describe('when offset is not a valid number', function () { it('should throw an error', function () { expect(function () { dilla.getPositionWithOffset('1.1.01', '96'); }).to.throw(/invalid argument/i); expect(function () { dilla.getPositionWithOffset('1.1.01', true); }).to.throw(/invalid argument/i); }); }); describe('when offset is a float', function () { it('should throw an error', function () { expect(function () { dilla.getPositionWithOffset('1.1.01', 1.1); }).to.throw(/invalid argument/i); }); }); describe('when valid arguments are passed', function () { it('it should return a position string with the correct offset', function () { expect(dilla.getPositionWithOffset('1.1.01', 0)).to.equal('1.1.01'); expect(dilla.getPositionWithOffset('1.1.01', 96)).to.equal('1.2.01'); expect(dilla.getPositionWithOffset('1.3.73', 72)).to.equal('1.4.49'); }); }); }); describe('dilla.set (id, notes)', function () { describe('when id is not a valid id string', function () { it('should throw an error', function () { expect(function () { dilla.set(null, []); }).to.throw(/invalid argument/i); expect(function () { dilla.set(1, []); }).to.throw(/invalid argument/i); expect(function () { dilla.set({}, []); }).to.throw(/invalid argument/i); }); }); describe('when notes is not an array', function () { it('should throw an error', function () { expect(function () { dilla.set('foo', {}); }).to.throw(/invalid argument/i); expect(function () { dilla.set('foo', null); }).to.throw(/invalid argument/i); expect(function () { dilla.set('foo', true); }).to.throw(/invalid argument/i); expect(function () { dilla.set('foo', 123); }).to.throw(/invalid argument/i); expect(function () { dilla.set('foo', '1.1.01'); }).to.throw(/invalid argument/i); }); }); describe('when notes are out of bounds', function () { it('should filter out these notes', function () { dilla.set('foo', [ ['1.1.01', { 'foo': 'bar' }], ['5.1.01'] ]); var notes = dilla.get('foo'); expect(notes.length).to.equal(1); expect(notes[0].position).to.equal('1.1.01'); expect(notes[0].foo).to.equal('bar'); }); }); describe('when re-using a channel id', function () { it('should overwrite previously registered notes', function () { dilla.set('foo', [ ['1.1.01', { 'foo': 'bar' }] ]); dilla.set('foo', [ ['1.2.01', { 'foo': 'bar' }] ]); var notes = dilla.get('foo'); expect(notes.length).to.equal(1); expect(notes[0].position).to.equal('1.2.01'); expect(notes[0].foo).to.equal('bar'); }); }); }); describe('dilla.get (id)', function () { describe('when id is not a valid id string', function () { it('should throw an error', function () { expect(function () { dilla.get(); }).to.throw(/invalid argument/i); expect(function () { dilla.get(3); }).to.throw(/invalid argument/i); expect(function () { dilla.get(true); }).to.throw(/invalid argument/i); }); }); describe('when no channel with id exists', function () { it('should return an empty array', function () { var returned = dilla.get('foobar'); expect(returned).to.be.a('array'); expect(returned.length).to.equal(0); }); }); describe('when a channel with registered note exists', function () { it('should return an array of note objects', function () { dilla.set('foozle', [ ['1.1.01'], { 'position': '1.2.02' } ]); var returned = dilla.get('foozle'); expect(returned).to.be.a('array'); expect(returned.length).to.equal(2); expect(returned[0].position).to.equal('1.1.01'); expect(returned[1].position).to.equal('1.2.02'); }); }); }); describe('dilla.clear (id)', function () { describe('when id is not a valid id string', function () { it('should throw an error', function () { expect(function () { dilla.clear(3); }).to.throw(/invalid argument/i); expect(function () { dilla.clear(true); }).to.throw(/invalid argument/i); }); }); describe('when no channel with id exists', function () { it('should do nothing', function () { expect(function () { dilla.clear('foo'); }).not.to.throw(Error); }); }); describe('when a channel with registered note exists', function () { it('should unregister all notes on that channel', function () { dilla.set('foo', [['1.1.01'], ['1.1.02']]); var returned = dilla.clear('foo'); var notes = dilla.get('foo'); expect(notes).to.be.a('array'); expect(notes.length).to.equal(0); }); }); }); describe('dilla.clear ()', function () { describe('when a channel with registered note exists', function () { it('should unregister all notes on all channels', function () { dilla.set('foo', [['1.1.01'], ['1.1.02']]); dilla.set('boo', [['2.1.01'], ['2.1.02']]); dilla.clear(); expect(dilla.get('foo').length).to.equal(0); expect(dilla.get('boo').length).to.equal(0); }); }); });