Skip to content

Commit 6cb767f

Browse files
committed
fix: handle GP5 percussion instruments which were removed in later GP versions (#2537)
(cherry picked from commit 7e9e08c)
1 parent c6e059c commit 6cb767f

5 files changed

Lines changed: 45 additions & 2 deletions

File tree

packages/alphatab/src/importer/Gp3To5Importer.ts

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,26 @@ import { BeamDirection } from '@coderline/alphatab/rendering/utils/BeamDirection
5454
*/
5555
export class Gp3To5Importer extends ScoreImporter {
5656
private static readonly _versionString: string = 'FICHIER GUITAR PRO ';
57+
58+
// NOTE: General Midi only defines percussion instruments from 35-81
59+
// Guitar Pro 5 allowed GS extensions (27-34 and 82-87)
60+
// GP7-8 do not have all these definitions anymore, this lookup ensures some fallback
61+
// (even if they are not correct)
62+
// we can support this properly in future when we allow custom alphaTex articulation definitions
63+
// then we don't need to rely on GP specifics anymore but handle things on export/import
64+
private static readonly _gp5PercussionInstrumentMap = new Map<number, number>([
65+
// High Q -> GS "High Q / Filter Snap"
66+
[27, 42],
67+
// Slap
68+
[28, 60],
69+
// Scratch Push
70+
[29, 29],
71+
// Scratch Pull
72+
[30, 30],
73+
// Square Click
74+
[32, 31]
75+
]);
76+
5777
private _versionNumber: number = 0;
5878
private _score!: Score;
5979
private _globalTripletFeel: TripletFeel = TripletFeel.NoTripletFeel;
@@ -1225,7 +1245,9 @@ export class Gp3To5Importer extends ScoreImporter {
12251245
}
12261246

12271247
if (bar.staff.isPercussion) {
1228-
newNote.percussionArticulation = newNote.fret;
1248+
newNote.percussionArticulation = Gp3To5Importer._gp5PercussionInstrumentMap.has(newNote.fret)
1249+
? Gp3To5Importer._gp5PercussionInstrumentMap.get(newNote.fret)!
1250+
: newNote.fret;
12291251
newNote.string = -1;
12301252
newNote.fret = -1;
12311253
}

packages/alphatab/src/model/PercussionMapper.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1068,7 +1068,8 @@ export class PercussionMapper {
10681068
}
10691069
}
10701070

1071-
return 'unknown';
1071+
// unknown combination, should not happen, fallback to some default value (Snare hit)
1072+
return 'Snare (hit)';
10721073
}
10731074

10741075
public static getArticulation(n: Note): InstrumentArticulation | null {
2.23 KB
Binary file not shown.

packages/alphatab/test/exporter/AlphaTexExporter.test.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -168,6 +168,10 @@ describe('AlphaTexExporterTest', () => {
168168
await testRoundTripEqual(`conversion/full-song.gp5`);
169169
});
170170

171+
it('gp5-articulation', async () => {
172+
await testRoundTripEqual(`guitarpro5/percussion-all.gp5`);
173+
});
174+
171175
it('gp6-to-alphaTex', async () => {
172176
await testRoundTripEqual(`conversion/full-song.gpx`);
173177
});

packages/alphatab/test/importer/Gp5Importer.test.ts

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import { BeamDirection } from '@coderline/alphatab/rendering/utils/BeamDirection
99
import { GpImporterTestHelper } from 'test/importer/GpImporterTestHelper';
1010
import { expect } from 'chai';
1111
import { Clef } from '@coderline/alphatab/model/Clef';
12+
import { PercussionMapper } from '@coderline/alphatab/model/PercussionMapper';
1213

1314
describe('Gp5ImporterTest', () => {
1415
it('score-info', async () => {
@@ -553,4 +554,19 @@ describe('Gp5ImporterTest', () => {
553554
expect(score.tracks[2].staves[0].bars[0].clef).to.equal(Clef.F4);
554555
expect(score.tracks[3].staves[0].bars[0].clef).to.equal(Clef.F4);
555556
});
557+
558+
it('percusson', async () => {
559+
const score = (await GpImporterTestHelper.prepareImporterWithFile('guitarpro5/percussion-all.gp5')).readScore();
560+
561+
let beat: Beat | null = score.tracks[0].staves[0].bars[0].voices[0].beats[0];
562+
563+
while (beat) {
564+
if (beat.notes.length === 1) {
565+
const articulationName = PercussionMapper.getArticulationName(beat.notes[0]);
566+
const hasArticulation = PercussionMapper.instrumentArticulationNames.has(articulationName);
567+
expect(hasArticulation).to.be.true;
568+
beat = beat.nextBeat;
569+
}
570+
}
571+
});
556572
});

0 commit comments

Comments
 (0)