tuneflow
Version:
Programmable, extensible music composition & arrangement
805 lines (719 loc) • 26.7 kB
text/typescript
import { Song, TuneflowPlugin } from '../src';
import { StructureType } from '../src/models/marker';
describe('Song-related Tests', () => {
class TestUtilsPlugin extends TuneflowPlugin {}
const testUtilsPlugin = new TestUtilsPlugin();
let song = new Song();
beforeEach(() => {
song = new Song();
// @ts-ignore
song.setPluginContextInternal(testUtilsPlugin);
song.setResolution(480);
song.createTempoChange({
ticks: 0,
bpm: 120,
});
song.createTempoChange({
ticks: 1440,
bpm: 60,
});
song.createTimeSignature({ ticks: 0, numerator: 4, denominator: 4 });
song.createTimeSignature({ ticks: 2880, numerator: 7, denominator: 8 });
});
describe('Creates song correctly', () => {
const newSong = Song.create();
expect(newSong.getResolution()).toBe(480);
expect(newSong.getTempoChanges().length).toBe(1);
expect(newSong.getTempoChanges()[0].getBpm()).toBe(120);
expect(newSong.getTempoChanges()[0].getTicks()).toBe(0);
expect(newSong.getTimeSignatures().length).toBe(1);
expect(newSong.getTimeSignatures()[0].getNumerator()).toBe(4);
expect(newSong.getTimeSignatures()[0].getDenominator()).toBe(4);
expect(newSong.getTimeSignatures()[0].getTicks()).toBe(0);
});
describe('Works with tempos correctly', () => {
it('Gets tempo at tick correctly', async () => {
expect(song.getTempoAtTick(-10).getTicks()).toBe(0);
expect(song.getTempoAtTick(-10).getBpm()).toBe(120);
expect(song.getTempoAtTick(0).getTicks()).toBe(0);
expect(song.getTempoAtTick(0).getBpm()).toBe(120);
expect(song.getTempoAtTick(10).getTicks()).toBe(0);
expect(song.getTempoAtTick(10).getBpm()).toBe(120);
expect(song.getTempoAtTick(1439).getTicks()).toBe(0);
expect(song.getTempoAtTick(1439).getBpm()).toBe(120);
expect(song.getTempoAtTick(1440).getTicks()).toBe(1440);
expect(song.getTempoAtTick(1440).getBpm()).toBe(60);
expect(song.getTempoAtTick(1441).getTicks()).toBe(1440);
expect(song.getTempoAtTick(1441).getBpm()).toBe(60);
expect(song.getTempoAtTick(9999).getTicks()).toBe(1440);
expect(song.getTempoAtTick(9999).getBpm()).toBe(60);
});
it('Move tempo non-overlapping correctly', async () => {
song.createTempoChange({
ticks: 2880,
bpm: 240,
});
expect(song.getTempoChanges().length).toBe(3);
expect(() => song.moveTempo(1, 0)).toThrowError();
song.moveTempo(1, 480);
expect(song.getTempoChanges().length).toBe(3);
expect(song.getTempoChanges()[0].getBpm()).toBe(120);
expect(song.getTempoChanges()[0].getTime()).toBe(0);
expect(song.getTempoChanges()[1].getBpm()).toBe(60);
expect(song.getTempoChanges()[1].getTime()).toBeCloseTo(0.5);
expect(song.getTempoChanges()[2].getBpm()).toBe(240);
expect(song.getTempoChanges()[2].getTime()).toBeCloseTo(5.5);
});
it('Move tempo past another correctly', async () => {
song.createTempoChange({
ticks: 2880,
bpm: 240,
});
expect(song.getTempoChanges().length).toBe(3);
song.moveTempo(1, 3360);
expect(song.getTempoChanges().length).toBe(3);
expect(song.getTempoChanges()[0].getBpm()).toBe(120);
expect(song.getTempoChanges()[0].getTime()).toBe(0);
expect(song.getTempoChanges()[1].getBpm()).toBe(240);
expect(song.getTempoChanges()[1].getTime()).toBeCloseTo(3);
expect(song.getTempoChanges()[2].getBpm()).toBe(60);
expect(song.getTempoChanges()[2].getTime()).toBeCloseTo(3.25);
});
it('Move tempo overwrite correctly', async () => {
song.createTempoChange({
ticks: 2880,
bpm: 240,
});
expect(song.getTempoChanges().length).toBe(3);
expect(() => song.moveTempo(1, 0)).toThrowError();
song.moveTempo(2, 1440);
expect(song.getTempoChanges().length).toBe(2);
expect(song.getTempoChanges()[0].getBpm()).toBe(120);
expect(song.getTempoChanges()[1].getBpm()).toBe(240);
});
it('Remove tempo correctly', async () => {
expect(() => song.removeTempoChange(0)).toThrowError();
song.removeTempoChange(1);
expect(song.getTempoChanges().length).toBe(1);
expect(song.getTempoChanges()[0].getBpm()).toBe(120);
expect(() => song.removeTempoChange(0)).toThrowError();
});
});
describe('Works with time signatures correctly', () => {
it('Move time signature non-overlapping correctly', async () => {
expect(song.getTimeSignatures().length).toBe(2);
expect(() => song.moveTimeSignature(1, 0)).toThrowError();
song.moveTimeSignature(1, 480);
expect(song.getTimeSignatures().length).toBe(2);
expect(song.getTimeSignatures()[0].getNumerator()).toBe(4);
expect(song.getTimeSignatures()[0].getDenominator()).toBe(4);
expect(song.getTimeSignatures()[1].getNumerator()).toBe(7);
expect(song.getTimeSignatures()[1].getDenominator()).toBe(8);
});
it('Move time signature past another correctly', async () => {
song.createTimeSignature({
ticks: 480,
numerator: 3,
denominator: 4,
});
expect(song.getTimeSignatures().length).toBe(3);
expect(song.getTimeSignatures()[0].getNumerator()).toBe(4);
expect(song.getTimeSignatures()[0].getDenominator()).toBe(4);
expect(song.getTimeSignatures()[1].getNumerator()).toBe(3);
expect(song.getTimeSignatures()[1].getDenominator()).toBe(4);
expect(song.getTimeSignatures()[2].getNumerator()).toBe(7);
expect(song.getTimeSignatures()[2].getDenominator()).toBe(8);
song.moveTimeSignature(1, 3360);
expect(song.getTimeSignatures().length).toBe(3);
expect(song.getTimeSignatures()[0].getNumerator()).toBe(4);
expect(song.getTimeSignatures()[0].getDenominator()).toBe(4);
expect(song.getTimeSignatures()[1].getNumerator()).toBe(7);
expect(song.getTimeSignatures()[1].getDenominator()).toBe(8);
expect(song.getTimeSignatures()[2].getNumerator()).toBe(3);
expect(song.getTimeSignatures()[2].getDenominator()).toBe(4);
});
it('Move time signature overwrite correctly', async () => {
song.createTimeSignature({
ticks: 480,
numerator: 3,
denominator: 4,
});
expect(song.getTimeSignatures().length).toBe(3);
expect(song.getTimeSignatures()[0].getNumerator()).toBe(4);
expect(song.getTimeSignatures()[0].getDenominator()).toBe(4);
expect(song.getTimeSignatures()[1].getNumerator()).toBe(3);
expect(song.getTimeSignatures()[1].getDenominator()).toBe(4);
expect(song.getTimeSignatures()[2].getNumerator()).toBe(7);
expect(song.getTimeSignatures()[2].getDenominator()).toBe(8);
song.moveTimeSignature(2, 480);
expect(song.getTimeSignatures().length).toBe(2);
expect(song.getTimeSignatures()[0].getNumerator()).toBe(4);
expect(song.getTimeSignatures()[0].getDenominator()).toBe(4);
expect(song.getTimeSignatures()[1].getNumerator()).toBe(7);
expect(song.getTimeSignatures()[1].getDenominator()).toBe(8);
});
it('Remove time signature correctly', async () => {
expect(song.getTimeSignatures().length).toBe(2);
expect(() => song.removeTimeSignature(0)).toThrowError();
song.removeTimeSignature(1);
expect(song.getTimeSignatures().length).toBe(1);
expect(song.getTimeSignatures()[0].getNumerator()).toBe(4);
expect(song.getTimeSignatures()[0].getDenominator()).toBe(4);
expect(() => song.removeTimeSignature(0)).toThrowError();
});
it('Gets time signature at tick correctly', async () => {
expect(song.getTimeSignatureAtTick(-10).getTicks()).toBe(0);
expect(song.getTimeSignatureAtTick(-10).getNumerator()).toBe(4);
expect(song.getTimeSignatureAtTick(-10).getDenominator()).toBe(4);
expect(song.getTimeSignatureAtTick(0).getTicks()).toBe(0);
expect(song.getTimeSignatureAtTick(0).getNumerator()).toBe(4);
expect(song.getTimeSignatureAtTick(0).getDenominator()).toBe(4);
expect(song.getTimeSignatureAtTick(10).getTicks()).toBe(0);
expect(song.getTimeSignatureAtTick(10).getNumerator()).toBe(4);
expect(song.getTimeSignatureAtTick(10).getDenominator()).toBe(4);
expect(song.getTimeSignatureAtTick(1440).getTicks()).toBe(0);
expect(song.getTimeSignatureAtTick(1440).getNumerator()).toBe(4);
expect(song.getTimeSignatureAtTick(1440).getDenominator()).toBe(4);
expect(song.getTimeSignatureAtTick(2880).getTicks()).toBe(2880);
expect(song.getTimeSignatureAtTick(2880).getNumerator()).toBe(7);
expect(song.getTimeSignatureAtTick(2880).getDenominator()).toBe(8);
expect(song.getTimeSignatureAtTick(2881).getTicks()).toBe(2880);
expect(song.getTimeSignatureAtTick(2881).getNumerator()).toBe(7);
expect(song.getTimeSignatureAtTick(2881).getDenominator()).toBe(8);
expect(song.getTimeSignatureAtTick(9999).getTicks()).toBe(2880);
expect(song.getTimeSignatureAtTick(9999).getNumerator()).toBe(7);
expect(song.getTimeSignatureAtTick(9999).getDenominator()).toBe(8);
});
});
describe('Works with structures correctly', () => {
it('Gets structure at index correctly', async () => {
expect(song.getStructureAtIndex(0)).toBeUndefined();
song.createStructure({
tick: 0,
type: StructureType.INTRO,
});
song.createStructure({
tick: 480,
type: StructureType.VERSE,
});
song.createStructure({
tick: 960,
type: StructureType.CUSTOM,
customName: 'myStructure',
});
expect(song.getStructureAtIndex(0).getTick()).toBe(0);
expect(song.getStructureAtIndex(0).getType()).toBe(StructureType.INTRO);
expect(song.getStructureAtIndex(1).getTick()).toBe(480);
expect(song.getStructureAtIndex(1).getType()).toBe(StructureType.VERSE);
expect(song.getStructureAtIndex(2).getTick()).toBe(960);
expect(song.getStructureAtIndex(2).getType()).toBe(StructureType.CUSTOM);
expect(song.getStructureAtIndex(2).getCustomName()).toBe('myStructure');
});
it('updates structure correctly', async () => {
expect(song.getStructureAtIndex(0)).toBeUndefined();
song.createStructure({
tick: 0,
type: StructureType.INTRO,
});
expect(song.getStructureAtIndex(0).getTick()).toBe(0);
expect(song.getStructureAtIndex(0).getType()).toBe(StructureType.INTRO);
expect(song.getStructureAtIndex(0).getCustomName()).toBeUndefined();
song.getStructureAtIndex(0).setType(StructureType.CUSTOM);
song.getStructureAtIndex(0).setCustomName('myStructure');
expect(song.getStructureAtIndex(0).getType()).toBe(StructureType.CUSTOM);
expect(song.getStructureAtIndex(0).getCustomName()).toBe('myStructure');
});
it('Gets structure at tick correctly', async () => {
expect(song.getStructureAtTick(0)).toBeUndefined();
expect(song.getStructureAtTick(-1)).toBeUndefined();
song.createStructure({
tick: 0,
type: StructureType.INTRO,
});
song.createStructure({
tick: 480,
type: StructureType.VERSE,
});
expect(song.getStructureAtTick(-1).getTick()).toBe(0);
expect(song.getStructureAtTick(-1).getType()).toBe(StructureType.INTRO);
expect(song.getStructureAtTick(0).getTick()).toBe(0);
expect(song.getStructureAtTick(0).getType()).toBe(StructureType.INTRO);
expect(song.getStructureAtTick(240).getTick()).toBe(0);
expect(song.getStructureAtTick(240).getType()).toBe(StructureType.INTRO);
expect(song.getStructureAtTick(480).getTick()).toBe(480);
expect(song.getStructureAtTick(480).getType()).toBe(StructureType.VERSE);
expect(song.getStructureAtTick(960).getTick()).toBe(480);
expect(song.getStructureAtTick(960).getType()).toBe(StructureType.VERSE);
});
it('Create first structure from non-0 tick', async () => {
song.createStructure({
tick: 480,
type: StructureType.INTRO,
});
expect(song.getStructureAtIndex(0).getTick()).toBe(0);
expect(song.getStructureAtIndex(0).getType()).toBe(StructureType.INTRO);
});
it('Sort created structures correctly', async () => {
song.createStructure({
tick: 480,
type: StructureType.INTRO,
});
song.createStructure({
tick: 960,
type: StructureType.VERSE,
});
song.createStructure({
tick: 480,
type: StructureType.OUTRO,
});
expect(song.getStructureAtIndex(0).getTick()).toBe(0);
expect(song.getStructureAtIndex(0).getType()).toBe(StructureType.INTRO);
expect(song.getStructureAtIndex(1).getTick()).toBe(480);
expect(song.getStructureAtIndex(1).getType()).toBe(StructureType.OUTRO);
expect(song.getStructureAtIndex(2).getTick()).toBe(960);
expect(song.getStructureAtIndex(2).getType()).toBe(StructureType.VERSE);
});
it('Move structure non-overlapping correctly', async () => {
song.createStructure({
tick: 0,
type: StructureType.INTRO,
});
song.createStructure({
tick: 480,
type: StructureType.VERSE,
});
song.createStructure({
tick: 960,
type: StructureType.CHORUS,
});
expect(song.getStructures().length).toBe(3);
song.moveStructure(1, 240);
expect(song.getStructures().length).toBe(3);
expect(song.getStructures()[0].getType()).toBe(StructureType.INTRO);
expect(song.getStructures()[0].getTick()).toBe(0);
expect(song.getStructures()[1].getType()).toBe(StructureType.VERSE);
expect(song.getStructures()[1].getTick()).toBe(240);
expect(song.getStructures()[2].getType()).toBe(StructureType.CHORUS);
expect(song.getStructures()[2].getTick()).toBe(960);
});
it('Move structure past another correctly', async () => {
song.createStructure({
tick: 0,
type: StructureType.INTRO,
});
song.createStructure({
tick: 480,
type: StructureType.VERSE,
});
song.createStructure({
tick: 960,
type: StructureType.CHORUS,
});
expect(song.getStructures().length).toBe(3);
song.moveStructure(1, 1920);
expect(song.getStructures().length).toBe(3);
expect(song.getStructures()[0].getType()).toBe(StructureType.INTRO);
expect(song.getStructures()[0].getTick()).toBe(0);
expect(song.getStructures()[1].getType()).toBe(StructureType.CHORUS);
expect(song.getStructures()[1].getTick()).toBe(960);
expect(song.getStructures()[2].getType()).toBe(StructureType.VERSE);
expect(song.getStructures()[2].getTick()).toBe(1920);
});
it('Move structure overwrite correctly', async () => {
song.createStructure({
tick: 0,
type: StructureType.INTRO,
});
song.createStructure({
tick: 480,
type: StructureType.VERSE,
});
song.createStructure({
tick: 960,
type: StructureType.CHORUS,
});
expect(song.getStructures().length).toBe(3);
song.moveStructure(1, 960);
expect(song.getStructures().length).toBe(2);
expect(song.getStructures()[0].getType()).toBe(StructureType.INTRO);
expect(song.getStructures()[0].getTick()).toBe(0);
expect(song.getStructures()[1].getType()).toBe(StructureType.VERSE);
expect(song.getStructures()[1].getTick()).toBe(960);
});
it('Move structure overwrite first correctly', async () => {
song.createStructure({
tick: 0,
type: StructureType.INTRO,
});
song.createStructure({
tick: 480,
type: StructureType.VERSE,
});
song.createStructure({
tick: 960,
type: StructureType.CHORUS,
});
expect(song.getStructures().length).toBe(3);
song.moveStructure(1, 0);
expect(song.getStructures().length).toBe(2);
expect(song.getStructures()[0].getType()).toBe(StructureType.VERSE);
expect(song.getStructures()[0].getTick()).toBe(0);
expect(song.getStructures()[1].getType()).toBe(StructureType.CHORUS);
expect(song.getStructures()[1].getTick()).toBe(960);
});
it('Remove structure correctly', async () => {
song.createStructure({
tick: 0,
type: StructureType.INTRO,
});
song.createStructure({
tick: 480,
type: StructureType.VERSE,
});
song.createStructure({
tick: 960,
type: StructureType.CHORUS,
});
expect(song.getStructures().length).toBe(3);
song.removeStructure(1);
expect(song.getTempoChanges().length).toBe(2);
expect(song.getStructures()[0].getType()).toBe(StructureType.INTRO);
expect(song.getStructures()[0].getTick()).toBe(0);
expect(song.getStructures()[1].getType()).toBe(StructureType.CHORUS);
expect(song.getStructures()[1].getTick()).toBe(960);
song.removeStructure(3);
song.removeStructure(-1);
expect(song.getTempoChanges().length).toBe(2);
});
});
describe('Gets bar beats correctly', () => {
it('Gets bar beat when there are multiple time signatures correctly', () => {
expect(song.getBarBeats(4570)).toEqual([
{ bar: 1, beat: 1, tick: 0, ticksPerBeat: 480, numerator: 4, denominator: 4 },
{ bar: 1, beat: 2, tick: 480 },
{ bar: 1, beat: 3, tick: 960 },
{ bar: 1, beat: 4, tick: 1440 },
{ bar: 2, beat: 1, tick: 1920, ticksPerBeat: 480, numerator: 4, denominator: 4 },
{ bar: 2, beat: 2, tick: 2400 },
{ bar: 3, beat: 1, tick: 2880, ticksPerBeat: 240, numerator: 7, denominator: 8 },
{ bar: 3, beat: 2, tick: 3120 },
{ bar: 3, beat: 3, tick: 3360 },
{ bar: 3, beat: 4, tick: 3600 },
{ bar: 3, beat: 5, tick: 3840 },
{ bar: 3, beat: 6, tick: 4080 },
{ bar: 3, beat: 7, tick: 4320 },
{ bar: 4, beat: 1, tick: 4560, ticksPerBeat: 240, numerator: 7, denominator: 8 },
]);
});
it('Gets bar beat when there are duplicate time signatures correctly', () => {
song.createTimeSignature({ ticks: 480, numerator: 4, denominator: 4 });
expect(song.getBarBeats(4570)).toEqual([
{ bar: 1, beat: 1, tick: 0, ticksPerBeat: 480, numerator: 4, denominator: 4 },
{ bar: 1, beat: 2, tick: 480 },
{ bar: 1, beat: 3, tick: 960 },
{ bar: 1, beat: 4, tick: 1440 },
{ bar: 2, beat: 1, tick: 1920, ticksPerBeat: 480, numerator: 4, denominator: 4 },
{ bar: 2, beat: 2, tick: 2400 },
{ bar: 3, beat: 1, tick: 2880, ticksPerBeat: 240, numerator: 7, denominator: 8 },
{ bar: 3, beat: 2, tick: 3120 },
{ bar: 3, beat: 3, tick: 3360 },
{ bar: 3, beat: 4, tick: 3600 },
{ bar: 3, beat: 5, tick: 3840 },
{ bar: 3, beat: 6, tick: 4080 },
{ bar: 3, beat: 7, tick: 4320 },
{ bar: 4, beat: 1, tick: 4560, ticksPerBeat: 240, numerator: 7, denominator: 8 },
]);
});
});
describe('Gets closest/leading/trailing beats/bars correctly', () => {
it('Gets closest beats correctly', () => {
const barBeats = song.getBarBeats(5000);
expect(Song.getClosestBeat(0, barBeats)).toEqual({
bar: 1,
beat: 1,
tick: 0,
ticksPerBeat: 480,
numerator: 4,
denominator: 4,
});
expect(Song.getClosestBeat(240, barBeats)).toEqual({
bar: 1,
beat: 1,
tick: 0,
ticksPerBeat: 480,
numerator: 4,
denominator: 4,
});
expect(Song.getClosestBeat(241, barBeats)).toEqual({
bar: 1,
beat: 2,
tick: 480,
});
expect(Song.getClosestBeat(1660, barBeats)).toEqual({
bar: 1,
beat: 4,
tick: 1440,
});
expect(Song.getClosestBeat(2640, barBeats)).toEqual({
bar: 2,
beat: 2,
tick: 2400,
});
expect(Song.getClosestBeat(2641, barBeats)).toEqual({
bar: 3,
beat: 1,
tick: 2880,
ticksPerBeat: 240,
numerator: 7,
denominator: 8,
});
});
it('Gets leading beats correctly', () => {
const barBeats = song.getBarBeats(5000);
expect(Song.getLeadingBeat(0, barBeats)).toEqual({
bar: 1,
beat: 1,
tick: 0,
ticksPerBeat: 480,
numerator: 4,
denominator: 4,
});
expect(Song.getLeadingBeat(480, barBeats)).toEqual({
bar: 1,
beat: 2,
tick: 480,
});
expect(Song.getLeadingBeat(490, barBeats)).toEqual({
bar: 1,
beat: 2,
tick: 480,
});
expect(Song.getLeadingBeat(1920, barBeats)).toEqual({
bar: 2,
beat: 1,
tick: 1920,
ticksPerBeat: 480,
numerator: 4,
denominator: 4,
});
expect(Song.getLeadingBeat(2779, barBeats)).toEqual({
bar: 2,
beat: 2,
tick: 2400,
});
expect(Song.getLeadingBeat(2880, barBeats)).toEqual({
bar: 3,
beat: 1,
tick: 2880,
ticksPerBeat: 240,
numerator: 7,
denominator: 8,
});
expect(Song.getLeadingBeat(3119, barBeats)).toEqual({
bar: 3,
beat: 1,
tick: 2880,
ticksPerBeat: 240,
numerator: 7,
denominator: 8,
});
expect(Song.getLeadingBeat(3120, barBeats)).toEqual({
bar: 3,
beat: 2,
tick: 3120,
});
expect(Song.getLeadingBeat(4559, barBeats)).toEqual({
bar: 3,
beat: 7,
tick: 4320,
});
expect(Song.getLeadingBeat(4560, barBeats)).toEqual({
bar: 4,
beat: 1,
tick: 4560,
ticksPerBeat: 240,
numerator: 7,
denominator: 8,
});
});
it('Gets trailing beats correctly', () => {
const barBeats = song.getBarBeats(5000);
expect(Song.getTrailingBeat(0, barBeats)).toEqual({
bar: 1,
beat: 1,
tick: 0,
ticksPerBeat: 480,
numerator: 4,
denominator: 4,
});
expect(Song.getTrailingBeat(480, barBeats)).toEqual({
bar: 1,
beat: 2,
tick: 480,
});
expect(Song.getTrailingBeat(490, barBeats)).toEqual({
bar: 1,
beat: 3,
tick: 960,
});
expect(Song.getTrailingBeat(1920, barBeats)).toEqual({
bar: 2,
beat: 1,
tick: 1920,
ticksPerBeat: 480,
numerator: 4,
denominator: 4,
});
expect(Song.getTrailingBeat(2779, barBeats)).toEqual({
bar: 3,
beat: 1,
tick: 2880,
ticksPerBeat: 240,
numerator: 7,
denominator: 8,
});
expect(Song.getTrailingBeat(2880, barBeats)).toEqual({
bar: 3,
beat: 1,
tick: 2880,
ticksPerBeat: 240,
numerator: 7,
denominator: 8,
});
expect(Song.getTrailingBeat(3119, barBeats)).toEqual({
bar: 3,
beat: 2,
tick: 3120,
});
expect(Song.getTrailingBeat(3120, barBeats)).toEqual({
bar: 3,
beat: 2,
tick: 3120,
});
expect(Song.getTrailingBeat(4319, barBeats)).toEqual({
bar: 3,
beat: 7,
tick: 4320,
});
expect(Song.getTrailingBeat(4559, barBeats)).toEqual({
bar: 4,
beat: 1,
tick: 4560,
ticksPerBeat: 240,
numerator: 7,
denominator: 8,
});
expect(Song.getTrailingBeat(4560, barBeats)).toEqual({
bar: 4,
beat: 1,
tick: 4560,
ticksPerBeat: 240,
numerator: 7,
denominator: 8,
});
});
it('Gets leading bars correctly', () => {
const barBeats = song.getBarBeats(5000);
expect(Song.getLeadingBar(-10, barBeats)).toEqual({
bar: 1,
beat: 1,
tick: 0,
ticksPerBeat: 480,
numerator: 4,
denominator: 4,
});
expect(Song.getLeadingBar(0, barBeats)).toEqual({
bar: 1,
beat: 1,
tick: 0,
ticksPerBeat: 480,
numerator: 4,
denominator: 4,
});
expect(Song.getLeadingBar(480, barBeats)).toEqual({
bar: 1,
beat: 1,
tick: 0,
ticksPerBeat: 480,
numerator: 4,
denominator: 4,
});
expect(Song.getLeadingBar(1920, barBeats)).toEqual({
bar: 2,
beat: 1,
tick: 1920,
ticksPerBeat: 480,
numerator: 4,
denominator: 4,
});
expect(Song.getLeadingBar(2779, barBeats)).toEqual({
bar: 2,
beat: 1,
tick: 1920,
ticksPerBeat: 480,
numerator: 4,
denominator: 4,
});
expect(Song.getLeadingBar(2880, barBeats)).toEqual({
bar: 3,
beat: 1,
tick: 2880,
ticksPerBeat: 240,
numerator: 7,
denominator: 8,
});
expect(Song.getLeadingBar(3119, barBeats)).toEqual({
bar: 3,
beat: 1,
tick: 2880,
ticksPerBeat: 240,
numerator: 7,
denominator: 8,
});
expect(Song.getLeadingBar(3120, barBeats)).toEqual({
bar: 3,
beat: 1,
tick: 2880,
ticksPerBeat: 240,
numerator: 7,
denominator: 8,
});
expect(Song.getLeadingBar(4559, barBeats)).toEqual({
bar: 3,
beat: 1,
tick: 2880,
ticksPerBeat: 240,
numerator: 7,
denominator: 8,
});
expect(Song.getLeadingBar(4560, barBeats)).toEqual({
bar: 4,
beat: 1,
tick: 4560,
ticksPerBeat: 240,
numerator: 7,
denominator: 8,
});
expect(Song.getLeadingBar(9999, barBeats)).toEqual({
bar: 4,
beat: 1,
tick: 4560,
ticksPerBeat: 240,
numerator: 7,
denominator: 8,
});
});
});
describe('Gets/Sets buses correctly', () => {
it('Gets/Sets buses correctly', async () => {
expect(song.getBusByRank(1)).toBeUndefined();
song.setBus(/* rank= */ 1, 'Reverb');
expect(song.getBusByRank(1).getRank()).toBe(1);
expect(song.getBusByRank(1).getName()).toBe('Reverb');
song.setBus(32, 'Compress');
expect(song.getBusByRank(32).getRank()).toBe(32);
expect(song.getBusByRank(32).getName()).toBe('Compress');
expect(() => song.setBus(33, 'test bus')).toThrow();
});
});
});