diff --git a/src/midi/MidiFileGenerator.ts b/src/midi/MidiFileGenerator.ts index 1390f680f..fbbb7ad1e 100644 --- a/src/midi/MidiFileGenerator.ts +++ b/src/midi/MidiFileGenerator.ts @@ -441,7 +441,7 @@ export class MidiFileGenerator { } if (initialBend >= 0) { - this._handler.addBend(track.index, noteStart, channel, initialBend); + this._handler.addNoteBend(track.index, noteStart, channel, noteKey, initialBend); } // @@ -832,7 +832,7 @@ export class MidiFileGenerator { duration = noteDuration.noteOnly; } // ensure prebends are slightly before the actual note. - if (bendPoints[0].value > 0 && !note.isContinuedBend) { + if (bendPoints[0].value > 0 && !note.isContinuedBend && noteStart > 0) { noteStart--; } const bendDuration: number = Math.min( @@ -922,7 +922,7 @@ export class MidiFileGenerator { break; case BendStyle.Fast: const preBendValue: number = MidiFileGenerator.getPitchWheel(note.bendPoints[0].value); - this._handler.addBend(track.index, noteStart, channel, preBendValue | 0); + addBend(noteStart, preBendValue | 0); if (!finalBendValue || finalBendValue < note.bendPoints[1].value) { finalBendValue = note.bendPoints[1].value; } @@ -948,7 +948,7 @@ export class MidiFileGenerator { break; case BendStyle.Fast: const preBendValue: number = MidiFileGenerator.getPitchWheel(note.bendPoints[0].value); - this._handler.addBend(track.index, noteStart, channel, preBendValue | 0); + addBend(noteStart, preBendValue | 0); this.generateSongBookWhammyOrBend( noteStart, duration, diff --git a/test/audio/MidiFileGenerator.test.ts b/test/audio/MidiFileGenerator.test.ts index e4180a6b3..cbe7794ca 100644 --- a/test/audio/MidiFileGenerator.test.ts +++ b/test/audio/MidiFileGenerator.test.ts @@ -16,7 +16,6 @@ import { Score } from '@src/model/Score'; import { Settings } from '@src/Settings'; import { Logger } from '@src/Logger'; import { - BendEvent, NoteBendEvent, ControlChangeEvent, FlatMidiEventGenerator, @@ -30,7 +29,7 @@ import { import { TestPlatform } from '@test/TestPlatform'; describe('MidiFileGeneratorTest', () => { - const parseTex: (tex:string) => Score = (tex: string): Score => { + const parseTex: (tex: string) => Score = (tex: string): Score => { let importer: AlphaTexImporter = new AlphaTexImporter(); importer.init(TestPlatform.createStringReader(tex), new Settings()); return importer.readScore(); @@ -97,7 +96,7 @@ describe('MidiFileGeneratorTest', () => { new TempoEvent(0, 120), // bend effect - new BendEvent(0, 0, info.secondaryChannel, 8192), // no bend + new NoteBendEvent(0, 0, info.secondaryChannel, note.realValue, 8192), // no bend new NoteBendEvent(0, 0, info.secondaryChannel, note.realValue, 8192), new NoteBendEvent(1 * 80, 0, info.secondaryChannel, note.realValue, 8277), new NoteBendEvent(2 * 80, 0, info.secondaryChannel, note.realValue, 8363), @@ -122,7 +121,7 @@ describe('MidiFileGeneratorTest', () => { ), // reset bend - new BendEvent(960, 0, info.primaryChannel, 8192), + new NoteBendEvent(960, 0, info.primaryChannel, note.realValue, 8192), new NoteEvent( 960, 0, @@ -139,10 +138,10 @@ describe('MidiFileGeneratorTest', () => { Logger.info('Test', `i[${i}] ${handler.midiEvents[i]}`); if (i < expectedEvents.length) { expect(expectedEvents[i].equals(handler.midiEvents[i])) - .withContext(`i[${i}] expected[${expectedEvents[i]}] !== actual[${handler.midiEvents[i]}]`) - .toEqual( - true, - ); + .withContext(`i[${i}] expected[${expectedEvents[i]}] !== actual[${handler.midiEvents[i]}]`) + .toEqual( + true, + ); } } expect(handler.midiEvents.length).toEqual(expectedEvents.length); @@ -220,27 +219,27 @@ describe('MidiFileGeneratorTest', () => { new TempoEvent(0, 120), // on beat - new BendEvent(ticks[0], 0, info.primaryChannel, 8192), + new NoteBendEvent(ticks[0], 0, info.primaryChannel, 67, 8192), new NoteEvent(ticks[0], 0, info.primaryChannel, 3840, 67, DynamicValue.MF), - new BendEvent(ticks[1], 0, info.primaryChannel, 8192), + new NoteBendEvent(ticks[1], 0, info.primaryChannel, 67, 8192), new NoteEvent(ticks[1], 0, info.primaryChannel, 120, 67, DynamicValue.MF), - new BendEvent(ticks[2], 0, info.primaryChannel, 8192), + new NoteBendEvent(ticks[2], 0, info.primaryChannel, 67, 8192), new NoteEvent(ticks[2], 0, info.primaryChannel, 3720, 67, DynamicValue.MF), // before beat - new BendEvent(ticks[3], 0, info.primaryChannel, 8192), + new NoteBendEvent(ticks[3], 0, info.primaryChannel, 67, 8192), new NoteEvent(ticks[3], 0, info.primaryChannel, 3720, 67, DynamicValue.MF), - new BendEvent(ticks[4], 0, info.primaryChannel, 8192), + new NoteBendEvent(ticks[4], 0, info.primaryChannel, 67, 8192), new NoteEvent(ticks[4], 0, info.primaryChannel, 120, 67, DynamicValue.MF), - new BendEvent(ticks[5], 0, info.primaryChannel, 8192), + new NoteBendEvent(ticks[5], 0, info.primaryChannel, 67, 8192), new NoteEvent(ticks[5], 0, info.primaryChannel, 3840, 67, DynamicValue.MF), // bend beat - new BendEvent(ticks[6], 0, info.secondaryChannel, 8192), + new NoteBendEvent(ticks[6], 0, info.secondaryChannel, 67, 8192), new NoteBendEvent(ticks[6] + 12 * 0, 0, info.secondaryChannel, 67, 8192), new NoteBendEvent(ticks[6] + 12 * 1, 0, info.secondaryChannel, 67, 8277), new NoteBendEvent(ticks[6] + 12 * 2, 0, info.secondaryChannel, 67, 8363), @@ -263,8 +262,8 @@ describe('MidiFileGeneratorTest', () => { Logger.info('Test', `i[${i}] ${handler.midiEvents[i]}`); if (i < expectedEvents.length) { expect(handler.midiEvents[i].equals(expectedEvents[i])) - .withContext(`i[${i}] expected[${expectedEvents[i]}] !== actual[${handler.midiEvents[i]}]`) - .toEqual(true); + .withContext(`i[${i}] expected[${expectedEvents[i]}] !== actual[${handler.midiEvents[i]}]`) + .toEqual(true); } } expect(handler.midiEvents.length).toEqual(expectedEvents.length); @@ -272,7 +271,7 @@ describe('MidiFileGeneratorTest', () => { it('bend-multi-point', () => { let tex: string = ':4 15.6{b(0 4 0)} 15.6'; - let score: Score = parseTex(tex); + let score: Score = parseTex(tex); expect(score.tracks.length).toEqual(1); expect(score.tracks[0].staves[0].bars.length).toEqual(1); expect(score.tracks[0].staves[0].bars[0].voices.length).toEqual(1); @@ -308,7 +307,7 @@ describe('MidiFileGeneratorTest', () => { new TempoEvent(0, 120), // bend effect - new BendEvent(0, 0, info.secondaryChannel, 8192), + new NoteBendEvent(0, 0, info.secondaryChannel, note.realValue, 8192), new NoteBendEvent(0 * 40, 0, info.secondaryChannel, note.realValue, 8192), // no bend new NoteBendEvent(1 * 40, 0, info.secondaryChannel, note.realValue, 8277), new NoteBendEvent(2 * 40, 0, info.secondaryChannel, note.realValue, 8363), @@ -319,21 +318,21 @@ describe('MidiFileGeneratorTest', () => { new NoteBendEvent(7 * 40, 0, info.secondaryChannel, note.realValue, 8789), new NoteBendEvent(8 * 40, 0, info.secondaryChannel, note.realValue, 8875), new NoteBendEvent(9 * 40, 0, info.secondaryChannel, note.realValue, 8960), - new NoteBendEvent(10 * 40, 0, info.secondaryChannel,note.realValue, 9045), - new NoteBendEvent(11 * 40, 0, info.secondaryChannel,note.realValue, 9131), - new NoteBendEvent(12 * 40, 0, info.secondaryChannel,note.realValue, 9216), // full bend - new NoteBendEvent(13 * 40, 0, info.secondaryChannel,note.realValue, 9131), - new NoteBendEvent(14 * 40, 0, info.secondaryChannel,note.realValue, 9045), - new NoteBendEvent(15 * 40, 0, info.secondaryChannel,note.realValue, 8960), - new NoteBendEvent(16 * 40, 0, info.secondaryChannel,note.realValue, 8875), - new NoteBendEvent(17 * 40, 0, info.secondaryChannel,note.realValue, 8789), - new NoteBendEvent(18 * 40, 0, info.secondaryChannel,note.realValue, 8704), - new NoteBendEvent(19 * 40, 0, info.secondaryChannel,note.realValue, 8619), - new NoteBendEvent(20 * 40, 0, info.secondaryChannel,note.realValue, 8533), - new NoteBendEvent(21 * 40, 0, info.secondaryChannel,note.realValue, 8448), - new NoteBendEvent(22 * 40, 0, info.secondaryChannel,note.realValue, 8363), - new NoteBendEvent(23 * 40, 0, info.secondaryChannel,note.realValue, 8277), - new NoteBendEvent(24 * 40, 0, info.secondaryChannel,note.realValue, 8192), // no bend + new NoteBendEvent(10 * 40, 0, info.secondaryChannel, note.realValue, 9045), + new NoteBendEvent(11 * 40, 0, info.secondaryChannel, note.realValue, 9131), + new NoteBendEvent(12 * 40, 0, info.secondaryChannel, note.realValue, 9216), // full bend + new NoteBendEvent(13 * 40, 0, info.secondaryChannel, note.realValue, 9131), + new NoteBendEvent(14 * 40, 0, info.secondaryChannel, note.realValue, 9045), + new NoteBendEvent(15 * 40, 0, info.secondaryChannel, note.realValue, 8960), + new NoteBendEvent(16 * 40, 0, info.secondaryChannel, note.realValue, 8875), + new NoteBendEvent(17 * 40, 0, info.secondaryChannel, note.realValue, 8789), + new NoteBendEvent(18 * 40, 0, info.secondaryChannel, note.realValue, 8704), + new NoteBendEvent(19 * 40, 0, info.secondaryChannel, note.realValue, 8619), + new NoteBendEvent(20 * 40, 0, info.secondaryChannel, note.realValue, 8533), + new NoteBendEvent(21 * 40, 0, info.secondaryChannel, note.realValue, 8448), + new NoteBendEvent(22 * 40, 0, info.secondaryChannel, note.realValue, 8363), + new NoteBendEvent(23 * 40, 0, info.secondaryChannel, note.realValue, 8277), + new NoteBendEvent(24 * 40, 0, info.secondaryChannel, note.realValue, 8192), // no bend // note itself new NoteEvent( @@ -346,7 +345,7 @@ describe('MidiFileGeneratorTest', () => { ), // reset bend - new BendEvent(960, 0, info.primaryChannel, 8192), // finish + new NoteBendEvent(960, 0, info.primaryChannel, note.realValue, 8192), // finish new NoteEvent( 960, 0, @@ -361,10 +360,246 @@ describe('MidiFileGeneratorTest', () => { Logger.info('Test', `i[${i}] ${handler.midiEvents[i]}`); if (i < expectedEvents.length) { expect(expectedEvents[i].equals(handler.midiEvents[i])) - .withContext(`i[${i}] expected[${expectedEvents[i]}] !== actual[${handler.midiEvents[i]}]`) - .toEqual( - true - ); + .withContext(`i[${i}] expected[${expectedEvents[i]}] !== actual[${handler.midiEvents[i]}]`) + .toEqual( + true + ); + } + } + expect(handler.midiEvents.length).toEqual(expectedEvents.length); + }); + + it('bend-continued', () => { + let tex: string = '7.3{b (0 4)} -.3{b (4 0)}'; + let score: Score = parseTex(tex); + + let handler: FlatMidiEventGenerator = new FlatMidiEventGenerator(); + let generator: MidiFileGenerator = new MidiFileGenerator(score, null, handler); + generator.generate(); + let info: PlaybackInformation = score.tracks[0].playbackInfo; + let note: Note = score.tracks[0].staves[0].bars[0].voices[0].beats[0].notes[0]; + let expectedEvents: FlatMidiEvent[] = [ + // channel init + new ControlChangeEvent(0, 0, info.primaryChannel, ControllerType.VolumeCoarse, 120), + new ControlChangeEvent(0, 0, info.primaryChannel, ControllerType.PanCoarse, 64), + new ControlChangeEvent(0, 0, info.primaryChannel, ControllerType.ExpressionControllerCoarse, 127), + new ControlChangeEvent(0, 0, info.primaryChannel, ControllerType.RegisteredParameterFine, 0), + new ControlChangeEvent(0, 0, info.primaryChannel, ControllerType.RegisteredParameterCourse, 0), + new ControlChangeEvent(0, 0, info.primaryChannel, ControllerType.DataEntryFine, 0), + new ControlChangeEvent(0, 0, info.primaryChannel, ControllerType.DataEntryCoarse, 16), + new ProgramChangeEvent(0, 0, info.primaryChannel, info.program), + + new ControlChangeEvent(0, 0, info.secondaryChannel, ControllerType.VolumeCoarse, 120), + new ControlChangeEvent(0, 0, info.secondaryChannel, ControllerType.PanCoarse, 64), + new ControlChangeEvent(0, 0, info.secondaryChannel, ControllerType.ExpressionControllerCoarse, 127), + new ControlChangeEvent(0, 0, info.secondaryChannel, ControllerType.RegisteredParameterFine, 0), + new ControlChangeEvent(0, 0, info.secondaryChannel, ControllerType.RegisteredParameterCourse, 0), + new ControlChangeEvent(0, 0, info.secondaryChannel, ControllerType.DataEntryFine, 0), + new ControlChangeEvent(0, 0, info.secondaryChannel, ControllerType.DataEntryCoarse, 16), + new ProgramChangeEvent(0, 0, info.secondaryChannel, info.program), + + new TimeSignatureEvent(0, 4, 4), + new TempoEvent(0, 120), + + // bend up + new NoteBendEvent(0, 0, info.secondaryChannel, 62, 8192), + new NoteBendEvent(0 * 80, 0, info.secondaryChannel, 62, 8192), // no bend + new NoteBendEvent(1 * 80, 0, info.secondaryChannel, 62, 8277), + new NoteBendEvent(2 * 80, 0, info.secondaryChannel, 62, 8363), + new NoteBendEvent(3 * 80, 0, info.secondaryChannel, 62, 8448), + new NoteBendEvent(4 * 80, 0, info.secondaryChannel, 62, 8533), + new NoteBendEvent(5 * 80, 0, info.secondaryChannel, 62, 8619), + new NoteBendEvent(6 * 80, 0, info.secondaryChannel, 62, 8704), + new NoteBendEvent(7 * 80, 0, info.secondaryChannel, 62, 8789), + new NoteBendEvent(8 * 80, 0, info.secondaryChannel, 62, 8875), + new NoteBendEvent(9 * 80, 0, info.secondaryChannel, 62, 8960), + new NoteBendEvent(10 * 80, 0, info.secondaryChannel, 62, 9045), + new NoteBendEvent(11 * 80, 0, info.secondaryChannel, 62, 9131), + + // note itself + new NoteEvent( + 0, + 0, + info.secondaryChannel, + MidiUtils.toTicks(note.beat.duration) * 2, + note.realValue, + note.dynamics + ), + + // release on tied note + new NoteBendEvent(12 * 80, 0, info.secondaryChannel, 62, 9216), // reset bend for tied note + new NoteBendEvent(12 * 80, 0, info.secondaryChannel, 62, 9216), // full bend + new NoteBendEvent(13 * 80, 0, info.secondaryChannel, 62, 9131), + new NoteBendEvent(14 * 80, 0, info.secondaryChannel, 62, 9045), + new NoteBendEvent(15 * 80, 0, info.secondaryChannel, 62, 8960), + new NoteBendEvent(16 * 80, 0, info.secondaryChannel, 62, 8875), + new NoteBendEvent(17 * 80, 0, info.secondaryChannel, 62, 8789), + new NoteBendEvent(18 * 80, 0, info.secondaryChannel, 62, 8704), + new NoteBendEvent(19 * 80, 0, info.secondaryChannel, 62, 8619), + new NoteBendEvent(20 * 80, 0, info.secondaryChannel, 62, 8533), + new NoteBendEvent(21 * 80, 0, info.secondaryChannel, 62, 8448), + new NoteBendEvent(22 * 80, 0, info.secondaryChannel, 62, 8363), + new NoteBendEvent(23 * 80, 0, info.secondaryChannel, 62, 8277), + new NoteBendEvent(24 * 80, 0, info.secondaryChannel, 62, 8192), // no bend + + new TrackEndEvent(3840, 0) // 3840 = end of bar + ]; + for (let i: number = 0; i < handler.midiEvents.length; i++) { + Logger.info('Test', `i[${i}] ${handler.midiEvents[i]}`); + if (i < expectedEvents.length) { + expect(expectedEvents[i].equals(handler.midiEvents[i])) + .withContext(`i[${i}] expected[${expectedEvents[i]}] !== actual[${handler.midiEvents[i]}]`) + .toEqual( + true + ); + } + } + expect(handler.midiEvents.length).toEqual(expectedEvents.length); + }); + + it('pre-bend-release-continued', () => { + let tex: string = '7.3{b (4 0)} -.3'; + let score: Score = parseTex(tex); + + let handler: FlatMidiEventGenerator = new FlatMidiEventGenerator(); + let generator: MidiFileGenerator = new MidiFileGenerator(score, null, handler); + generator.generate(); + let info: PlaybackInformation = score.tracks[0].playbackInfo; + let note: Note = score.tracks[0].staves[0].bars[0].voices[0].beats[0].notes[0]; + let expectedEvents: FlatMidiEvent[] = [ + // channel init + new ControlChangeEvent(0, 0, info.primaryChannel, ControllerType.VolumeCoarse, 120), + new ControlChangeEvent(0, 0, info.primaryChannel, ControllerType.PanCoarse, 64), + new ControlChangeEvent(0, 0, info.primaryChannel, ControllerType.ExpressionControllerCoarse, 127), + new ControlChangeEvent(0, 0, info.primaryChannel, ControllerType.RegisteredParameterFine, 0), + new ControlChangeEvent(0, 0, info.primaryChannel, ControllerType.RegisteredParameterCourse, 0), + new ControlChangeEvent(0, 0, info.primaryChannel, ControllerType.DataEntryFine, 0), + new ControlChangeEvent(0, 0, info.primaryChannel, ControllerType.DataEntryCoarse, 16), + new ProgramChangeEvent(0, 0, info.primaryChannel, info.program), + + new ControlChangeEvent(0, 0, info.secondaryChannel, ControllerType.VolumeCoarse, 120), + new ControlChangeEvent(0, 0, info.secondaryChannel, ControllerType.PanCoarse, 64), + new ControlChangeEvent(0, 0, info.secondaryChannel, ControllerType.ExpressionControllerCoarse, 127), + new ControlChangeEvent(0, 0, info.secondaryChannel, ControllerType.RegisteredParameterFine, 0), + new ControlChangeEvent(0, 0, info.secondaryChannel, ControllerType.RegisteredParameterCourse, 0), + new ControlChangeEvent(0, 0, info.secondaryChannel, ControllerType.DataEntryFine, 0), + new ControlChangeEvent(0, 0, info.secondaryChannel, ControllerType.DataEntryCoarse, 16), + new ProgramChangeEvent(0, 0, info.secondaryChannel, info.program), + + new TimeSignatureEvent(0, 4, 4), + new TempoEvent(0, 120), + + // bend up + new NoteBendEvent(0 * 80, 0, info.secondaryChannel, 62, 9216), // pre-bend + new NoteBendEvent(0 * 160, 0, info.secondaryChannel, 62, 9216), // bend start + new NoteBendEvent(1 * 160, 0, info.secondaryChannel, 62, 9131), + new NoteBendEvent(2 * 160, 0, info.secondaryChannel, 62, 9045), + new NoteBendEvent(3 * 160, 0, info.secondaryChannel, 62, 8960), + new NoteBendEvent(4 * 160, 0, info.secondaryChannel, 62, 8875), + new NoteBendEvent(5 * 160, 0, info.secondaryChannel, 62, 8789), + new NoteBendEvent(6 * 160, 0, info.secondaryChannel, 62, 8704), + new NoteBendEvent(7 * 160, 0, info.secondaryChannel, 62, 8619), + new NoteBendEvent(8 * 160, 0, info.secondaryChannel, 62, 8533), + new NoteBendEvent(9 * 160, 0, info.secondaryChannel, 62, 8448), + new NoteBendEvent(10 * 160, 0, info.secondaryChannel, 62, 8363), + new NoteBendEvent(11 * 160, 0, info.secondaryChannel, 62, 8277), + new NoteBendEvent(12 * 160, 0, info.secondaryChannel, 62, 8192), + + // note itself + new NoteEvent( + 0, + 0, + info.secondaryChannel, + MidiUtils.toTicks(note.beat.duration) * 2, + note.realValue, + note.dynamics + ), + + new TrackEndEvent(3840, 0) // 3840 = end of bar + ]; + for (let i: number = 0; i < handler.midiEvents.length; i++) { + Logger.info('Test', `i[${i}] ${handler.midiEvents[i]}`); + if (i < expectedEvents.length) { + expect(expectedEvents[i].equals(handler.midiEvents[i])) + .withContext(`i[${i}] expected[${expectedEvents[i]}] !== actual[${handler.midiEvents[i]}]`) + .toEqual( + true + ); + } + } + expect(handler.midiEvents.length).toEqual(expectedEvents.length); + }); + + it('pre-bend-release-continued-songbook', () => { + let tex: string = '7.3{b (4 0)} -.3'; + let score: Score = parseTex(tex); + + let handler: FlatMidiEventGenerator = new FlatMidiEventGenerator(); + let settings = new Settings(); + settings.setSongBookModeSettings(); + let generator: MidiFileGenerator = new MidiFileGenerator(score, settings, handler); + generator.generate(); + let info: PlaybackInformation = score.tracks[0].playbackInfo; + let note: Note = score.tracks[0].staves[0].bars[0].voices[0].beats[0].notes[0]; + let expectedEvents: FlatMidiEvent[] = [ + // channel init + new ControlChangeEvent(0, 0, info.primaryChannel, ControllerType.VolumeCoarse, 120), + new ControlChangeEvent(0, 0, info.primaryChannel, ControllerType.PanCoarse, 64), + new ControlChangeEvent(0, 0, info.primaryChannel, ControllerType.ExpressionControllerCoarse, 127), + new ControlChangeEvent(0, 0, info.primaryChannel, ControllerType.RegisteredParameterFine, 0), + new ControlChangeEvent(0, 0, info.primaryChannel, ControllerType.RegisteredParameterCourse, 0), + new ControlChangeEvent(0, 0, info.primaryChannel, ControllerType.DataEntryFine, 0), + new ControlChangeEvent(0, 0, info.primaryChannel, ControllerType.DataEntryCoarse, 16), + new ProgramChangeEvent(0, 0, info.primaryChannel, info.program), + + new ControlChangeEvent(0, 0, info.secondaryChannel, ControllerType.VolumeCoarse, 120), + new ControlChangeEvent(0, 0, info.secondaryChannel, ControllerType.PanCoarse, 64), + new ControlChangeEvent(0, 0, info.secondaryChannel, ControllerType.ExpressionControllerCoarse, 127), + new ControlChangeEvent(0, 0, info.secondaryChannel, ControllerType.RegisteredParameterFine, 0), + new ControlChangeEvent(0, 0, info.secondaryChannel, ControllerType.RegisteredParameterCourse, 0), + new ControlChangeEvent(0, 0, info.secondaryChannel, ControllerType.DataEntryFine, 0), + new ControlChangeEvent(0, 0, info.secondaryChannel, ControllerType.DataEntryCoarse, 16), + new ProgramChangeEvent(0, 0, info.secondaryChannel, info.program), + + new TimeSignatureEvent(0, 4, 4), + new TempoEvent(0, 120), + + // bend up + new NoteBendEvent(0 * 80, 0, info.secondaryChannel, 62, 9216), // pre-bend + new NoteBendEvent(0 * 80, 0, info.secondaryChannel, 62, 9216), // bend start + new NoteBendEvent(1 * 80, 0, info.secondaryChannel, 62, 9131), + new NoteBendEvent(2 * 80, 0, info.secondaryChannel, 62, 9045), + new NoteBendEvent(3 * 80, 0, info.secondaryChannel, 62, 8960), + new NoteBendEvent(4 * 80, 0, info.secondaryChannel, 62, 8875), + new NoteBendEvent(5 * 80, 0, info.secondaryChannel, 62, 8789), + new NoteBendEvent(6 * 80, 0, info.secondaryChannel, 62, 8704), + new NoteBendEvent(7 * 80, 0, info.secondaryChannel, 62, 8619), + new NoteBendEvent(8 * 80, 0, info.secondaryChannel, 62, 8533), + new NoteBendEvent(9 * 80, 0, info.secondaryChannel, 62, 8448), + new NoteBendEvent(10 * 80, 0, info.secondaryChannel, 62, 8363), + new NoteBendEvent(11 * 80, 0, info.secondaryChannel, 62, 8277), + new NoteBendEvent(12 * 80, 0, info.secondaryChannel, 62, 8192), + + // note itself + new NoteEvent( + 0, + 0, + info.secondaryChannel, + MidiUtils.toTicks(note.beat.duration) * 2, + note.realValue, + note.dynamics + ), + + new TrackEndEvent(3840, 0) // 3840 = end of bar + ]; + for (let i: number = 0; i < handler.midiEvents.length; i++) { + Logger.info('Test', `i[${i}] ${handler.midiEvents[i]}`); + if (i < expectedEvents.length) { + expect(expectedEvents[i].equals(handler.midiEvents[i])) + .withContext(`i[${i}] expected[${expectedEvents[i]}] !== actual[${handler.midiEvents[i]}]`) + .toEqual( + true + ); } } expect(handler.midiEvents.length).toEqual(expectedEvents.length); @@ -414,7 +649,7 @@ describe('MidiFileGeneratorTest', () => { // prettier-ignore let expectedMidiDurations: number[] = [ 640, 320, 640, 320, - 320, 160, 320, 160, 320, 160, 320 ,160, + 320, 160, 320, 160, 320, 160, 320, 160, 720, 240, 720, 240, 360, 120, 360, 120, 360, 120, 360, 120, 240, 720, 240, 720, @@ -475,7 +710,7 @@ describe('MidiFileGeneratorTest', () => { new TempoEvent(0, 120), // bend effect (note 1) - new BendEvent(0, 0, info.secondaryChannel, 8192), // no bend + new NoteBendEvent(0, 0, info.secondaryChannel, note1.realValue, 8192), // no bend new NoteBendEvent(0, 0, info.secondaryChannel, note1.realValue, 8192), new NoteBendEvent(1 * 80, 0, info.secondaryChannel, note1.realValue, 8277), new NoteBendEvent(2 * 80, 0, info.secondaryChannel, note1.realValue, 8363), @@ -500,7 +735,7 @@ describe('MidiFileGeneratorTest', () => { ), // bend effect (note 2) - new BendEvent(0, 0, info.secondaryChannel, 8192), // no bend + new NoteBendEvent(0, 0, info.secondaryChannel, note2.realValue, 8192), // no bend new NoteBendEvent(0, 0, info.secondaryChannel, note2.realValue, 8192), new NoteBendEvent(1 * 40, 0, info.secondaryChannel, note2.realValue, 8277), new NoteBendEvent(2 * 40, 0, info.secondaryChannel, note2.realValue, 8363), @@ -537,7 +772,7 @@ describe('MidiFileGeneratorTest', () => { ), // reset bend - new BendEvent(960, 0, info.primaryChannel, 8192), + new NoteBendEvent(960, 0, info.primaryChannel, note1.realValue, 8192), new NoteEvent( 960, 0, @@ -554,10 +789,10 @@ describe('MidiFileGeneratorTest', () => { Logger.info('Test', `i[${i}] ${handler.midiEvents[i]}`); if (i < expectedEvents.length) { expect(expectedEvents[i].equals(handler.midiEvents[i])) - .withContext(`i[${i}] expected[${expectedEvents[i]}] !== actual[${handler.midiEvents[i]}]`) - .toEqual( - true, - ); + .withContext(`i[${i}] expected[${expectedEvents[i]}] !== actual[${handler.midiEvents[i]}]`) + .toEqual( + true, + ); } } expect(handler.midiEvents.length).toEqual(expectedEvents.length);