|
| 1 | +import { ScoreLoader } from '@coderline/alphatab/importer/ScoreLoader'; |
| 2 | +import { IOHelper } from '@coderline/alphatab/io/IOHelper'; |
| 3 | +import { Clef } from '@coderline/alphatab/model/Clef'; |
| 4 | +import { Duration } from '@coderline/alphatab/model/Duration'; |
| 5 | +import type { Score } from '@coderline/alphatab/model/Score'; |
| 6 | +import type { Staff } from '@coderline/alphatab/model/Staff'; |
| 7 | +import { Settings } from '@coderline/alphatab/Settings'; |
| 8 | +import { TestPlatform } from 'test/TestPlatform'; |
| 9 | +import { describe, expect, it } from 'vitest'; |
| 10 | + |
| 11 | +describe('CapellaImporterTests', () => { |
| 12 | + function pitches(staff: Staff): number[][] { |
| 13 | + return staff.bars.map(b => b.voices[0].beats.map(beat => (beat.isRest ? -1 : beat.notes[0].realValue))); |
| 14 | + } |
| 15 | + |
| 16 | + function capXml(noteObjects: string): Score { |
| 17 | + const xml = `<?xml version="1.0" encoding="UTF-8"?> |
| 18 | +<score xmlns="http://www.capella.de/CapXML/3.0"> |
| 19 | + <info/> |
| 20 | + <layout> |
| 21 | + <staves> |
| 22 | + <staffLayout description="Voice"><notation defaultClef="treble"/><sound instr="0" volume="100"/></staffLayout> |
| 23 | + </staves> |
| 24 | + </layout> |
| 25 | + <systems> |
| 26 | + <system> |
| 27 | + <staves> |
| 28 | + <staff layout="Voice" defaultTime="4/4"> |
| 29 | + <voices><voice><noteObjects>${noteObjects}</noteObjects></voice></voices> |
| 30 | + </staff> |
| 31 | + </staves> |
| 32 | + </system> |
| 33 | + </systems> |
| 34 | +</score>`; |
| 35 | + return ScoreLoader.loadScoreFromBytes(IOHelper.stringToBytes(xml), new Settings()); |
| 36 | + } |
| 37 | + |
| 38 | + it('grand-staff', async () => { |
| 39 | + const data = await TestPlatform.loadFile('test-data/capella/twinkle-mozart.capx'); |
| 40 | + const score = ScoreLoader.loadScoreFromBytes(data, new Settings()); |
| 41 | + |
| 42 | + expect(score.title).toBe('Twinkle, Twinkle Little Star'); |
| 43 | + expect(score.artist).toBe('W.A. Mozart (1756-1791)'); |
| 44 | + expect(score.tracks[0].name).toBe('Piano'); |
| 45 | + expect(score.masterBars.length).toBe(4); |
| 46 | + expect(score.tempo).toBe(100); |
| 47 | + expect(score.tracks.length).toBe(1); |
| 48 | + |
| 49 | + expect(score.tracks[0].staves.length).toBe(2); |
| 50 | + const rightHand = score.tracks[0].staves[0]; |
| 51 | + const leftHand = score.tracks[0].staves[1]; |
| 52 | + expect(rightHand.bars[0].clef).toBe(Clef.G2); |
| 53 | + expect(leftHand.bars[0].clef).toBe(Clef.F4); |
| 54 | + expect(pitches(rightHand)).toEqual([ |
| 55 | + [60, 60, 67, 67], |
| 56 | + [69, 69, 67], |
| 57 | + [65, 65, 64, 64], |
| 58 | + [62, 62, 60] |
| 59 | + ]); |
| 60 | + expect(pitches(leftHand)).toEqual([ |
| 61 | + [48, 52, 55, 52], |
| 62 | + [53, 57, 55, 52], |
| 63 | + [50, 53, 48, 52], |
| 64 | + [43, 47, 48] |
| 65 | + ]); |
| 66 | + expect(rightHand.bars[1].voices[0].beats[2].duration).toBe(Duration.Half); |
| 67 | + expect(rightHand.bars[0].voices[0].beats.map(b => b.lyrics![0])).toEqual(['Twin-', 'kle,', 'twin-', 'kle,']); |
| 68 | + }); |
| 69 | + |
| 70 | + it('whole-notes-and-rests', () => { |
| 71 | + const score = capXml(` |
| 72 | + <chord><duration base="1/1"/><heads><head pitch="C5"/></heads></chord> |
| 73 | + <barline type="single"/> |
| 74 | + <rest><duration base="1/1"/></rest> |
| 75 | + <barline type="single"/> |
| 76 | + <rest><duration base="1"/></rest> |
| 77 | + <barline type="single"/> |
| 78 | + <chord><duration base="1/2"/><heads><head pitch="E5"/></heads></chord> |
| 79 | + <rest><duration base="1/2"/></rest> |
| 80 | + <barline type="end"/>`); |
| 81 | + |
| 82 | + const staff = score.tracks[0].staves[0]; |
| 83 | + expect(score.masterBars.length).toBe(4); |
| 84 | + expect(pitches(staff)).toEqual([[60], [-1], [-1], [64, -1]]); |
| 85 | + expect(staff.bars[1].voices[0].beats[0].isFullBarRest).toBe(true); |
| 86 | + expect(staff.bars[2].voices[0].beats[0].isFullBarRest).toBe(true); |
| 87 | + expect(staff.bars[0].voices[0].beats[0].isFullBarRest).toBe(false); |
| 88 | + expect(score.masterBars.map(m => m.isAnacrusis)).toEqual([false, false, false, false]); |
| 89 | + }); |
| 90 | +}); |
0 commit comments