Skip to content

Commit

Permalink
Respect correct duration of tick lookup result for caching (CoderLine…
Browse files Browse the repository at this point in the history
  • Loading branch information
Danielku15 authored and ChiHoc committed Nov 7, 2022
1 parent a5b7e3c commit a739edd
Show file tree
Hide file tree
Showing 3 changed files with 62 additions and 4 deletions.
14 changes: 10 additions & 4 deletions src/midi/MidiTickLookup.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,12 @@ export class MidiTickLookupFindBeatResult {
*/
public duration: number = 0;

/**
* Gets or sets the duration in midi ticks for how long this tick lookup is valid
* starting at the `currentBeatLookup.start`
*/
public tickDuration: number = 0;

/**
* Gets or sets the beats ot highlight along the current beat.
*/
Expand Down Expand Up @@ -134,7 +140,8 @@ export class MidiTickLookup {
currentBeatHint: MidiTickLookupFindBeatResult,
tick: number
): MidiTickLookupFindBeatResult | null {
if (tick >= currentBeatHint.currentBeatLookup.start && tick < currentBeatHint.currentBeatLookup.end) {
const end = currentBeatHint.currentBeatLookup.start + currentBeatHint.tickDuration;
if (tick >= currentBeatHint.currentBeatLookup.start && tick < end) {
// still same beat?
return currentBeatHint;
} else if (
Expand Down Expand Up @@ -190,9 +197,8 @@ export class MidiTickLookup {
const result = new MidiTickLookupFindBeatResult();
result.currentBeatLookup = beat;
result.nextBeatLookup = nextBeat;
result.duration = !nextBeat
? MidiUtils.ticksToMillis(beat.end - beat.start, beat.masterBar.tempo)
: MidiUtils.ticksToMillis(nextBeat.start - beat.start, beat.masterBar.tempo);
result.tickDuration = !nextBeat ? beat.end - beat.start : nextBeat.start - beat.start;
result.duration = MidiUtils.ticksToMillis(result.tickDuration, beat.masterBar.tempo)
result.beatsToHighlight = beat.beatsToHighlight;
return result;
}
Expand Down
Binary file added test-data/audio/cursor-snapping.gp
Binary file not shown.
52 changes: 52 additions & 0 deletions test/audio/MidiTickLookup.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
import { ScoreLoader } from '@src/importer';
import { AlphaSynthMidiFileHandler, MidiFile, MidiFileGenerator, MidiTickLookup } from '@src/midi';
import { Duration, Score } from '@src/model';
import { Settings } from '@src/Settings';
import { TestPlatform } from '@test/TestPlatform';

describe('MidiTickLookupTest', () => {
async function buildLookup(score:Score, settings:Settings): Promise<MidiTickLookup> {
const midiFile = new MidiFile();
const handler = new AlphaSynthMidiFileHandler(midiFile);
const midiFileGenerator = new MidiFileGenerator(score, settings, handler);
midiFileGenerator.generate();
return midiFileGenerator.tickLookup;
}

it('cursor-snapping', async () => {
const buffer = await TestPlatform.loadFile('test-data/audio/cursor-snapping.gp');
const settings = new Settings();
const score = ScoreLoader.loadScoreFromBytes(buffer, settings);
const lookup = await buildLookup(score, settings);

// initial lookup should detect correctly first rest on first voice
// with the quarter rest on the second voice as next beat
const firstBeat = lookup.findBeat([score.tracks[0]], 0, null);
expect(firstBeat!.currentBeat.id).toEqual(score.tracks[0].staves[0].bars[0].voices[0].beats[0].id);
expect(firstBeat!.nextBeat!.id).toEqual(score.tracks[0].staves[0].bars[0].voices[1].beats[1].id);
expect(firstBeat!.currentBeat.duration).toEqual(Duration.Whole);
expect(firstBeat!.nextBeat!.duration).toEqual(Duration.Quarter);

// Duration must only go to the next rest on the second voice despite the whole note
expect(firstBeat!.duration).toEqual(750);
expect(firstBeat!.tickDuration).toEqual(960);

// Still playing first beat
const stillFirst = lookup.findBeat([score.tracks[0]], 400, firstBeat);
expect(stillFirst!.currentBeat.id).toEqual(score.tracks[0].staves[0].bars[0].voices[0].beats[0].id);
expect(stillFirst!.nextBeat!.id).toEqual(score.tracks[0].staves[0].bars[0].voices[1].beats[1].id);
expect(stillFirst!.currentBeat.duration).toEqual(Duration.Whole);
expect(stillFirst!.nextBeat!.duration).toEqual(Duration.Quarter);
expect(stillFirst!.duration).toEqual(750);
expect(stillFirst!.tickDuration).toEqual(960);

// Now we're past the second rest heading to the third
const secondBeat = lookup.findBeat([score.tracks[0]], 970 /* after first quarter */, stillFirst);
expect(secondBeat!.currentBeat.id).toEqual(score.tracks[0].staves[0].bars[0].voices[1].beats[1].id);
expect(secondBeat!.nextBeat!.id).toEqual(score.tracks[0].staves[0].bars[0].voices[1].beats[2].id);
expect(secondBeat!.currentBeat.duration).toEqual(Duration.Quarter);
expect(secondBeat!.nextBeat!.duration).toEqual(Duration.Quarter);
expect(secondBeat!.duration).toEqual(750);
expect(secondBeat!.tickDuration).toEqual(960);
});
});

0 comments on commit a739edd

Please sign in to comment.