Skip to content

Commit 5ef8ea8

Browse files
authored
feat: detect bass cleff on Guitar Pro 3-5 files (#2483)
1 parent 962b45b commit 5ef8ea8

File tree

4 files changed

+59
-14
lines changed

4 files changed

+59
-14
lines changed

packages/alphatab/src/importer/Gp3To5Importer.ts

Lines changed: 18 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -37,17 +37,17 @@ import { TripletFeel } from '@coderline/alphatab/model/TripletFeel';
3737
import { VibratoType } from '@coderline/alphatab/model/VibratoType';
3838
import { Voice } from '@coderline/alphatab/model/Voice';
3939

40-
import { Logger } from '@coderline/alphatab/Logger';
41-
import { ModelUtils } from '@coderline/alphatab/model/ModelUtils';
4240
import type { IWriteable } from '@coderline/alphatab/io/IWriteable';
43-
import { FadeType } from '@coderline/alphatab/model/FadeType';
44-
import { Rasgueado } from '@coderline/alphatab/model/Rasgueado';
41+
import { Logger } from '@coderline/alphatab/Logger';
42+
import { AccidentalType } from '@coderline/alphatab/model/AccidentalType';
4543
import { Direction } from '@coderline/alphatab/model/Direction';
46-
import { BeamDirection } from '@coderline/alphatab/rendering/utils/BeamDirection';
44+
import { FadeType } from '@coderline/alphatab/model/FadeType';
45+
import { ModelUtils } from '@coderline/alphatab/model/ModelUtils';
4746
import { Ottavia } from '@coderline/alphatab/model/Ottavia';
48-
import { WahPedal } from '@coderline/alphatab/model/WahPedal';
49-
import { AccidentalType } from '@coderline/alphatab/model/AccidentalType';
47+
import { Rasgueado } from '@coderline/alphatab/model/Rasgueado';
5048
import { TremoloPickingEffect } from '@coderline/alphatab/model/TremoloPickingEffect';
49+
import { WahPedal } from '@coderline/alphatab/model/WahPedal';
50+
import { BeamDirection } from '@coderline/alphatab/rendering/utils/BeamDirection';
5151

5252
/**
5353
* @internal
@@ -434,6 +434,11 @@ export class Gp3To5Importer extends ScoreImporter {
434434
}
435435
}
436436

437+
/**
438+
* Guitar Pro 3-6 changes to a bass clef if any string tuning is below B2;
439+
*/
440+
private static readonly _bassClefTuningThreshold = ModelUtils.parseTuning('B2')!.realValue;
441+
437442
public readTrack(): void {
438443
const newTrack: Track = new Track();
439444
newTrack.ensureStaveCount(1);
@@ -527,10 +532,10 @@ export class Gp3To5Importer extends ScoreImporter {
527532

528533
// `12` for all tunings which have bass clefs
529534
const clefMode = IOHelper.readInt32LE(this.data);
530-
if (clefMode === 12) {
531-
this._clefsPerTrack.set(index, Clef.F4);
535+
if (clefMode === 12 || tuning[tuning.length - 1] < Gp3To5Importer._bassClefTuningThreshold) {
536+
this._clefsPerTrack.set(newTrack.index, Clef.F4);
532537
} else {
533-
this._clefsPerTrack.set(index, Clef.G2);
538+
this._clefsPerTrack.set(newTrack.index, Clef.G2);
534539
}
535540

536541
// Unknown, no UI setting seem to affect this
@@ -570,10 +575,10 @@ export class Gp3To5Importer extends ScoreImporter {
570575
GpBinaryHelpers.gpReadStringIntByte(this.data, this.settings.importer.encoding);
571576
}
572577
} else {
573-
if (GeneralMidi.isBass(newTrack.playbackInfo.program)) {
574-
this._clefsPerTrack.set(index, Clef.F4);
578+
if (tuning[tuning.length - 1] < Gp3To5Importer._bassClefTuningThreshold) {
579+
this._clefsPerTrack.set(newTrack.index, Clef.F4);
575580
} else {
576-
this._clefsPerTrack.set(index, Clef.G2);
581+
this._clefsPerTrack.set(newTrack.index, Clef.G2);
577582
}
578583
}
579584
}
2 KB
Binary file not shown.

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

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import { TextAlign } from '@coderline/alphatab/platform/ICanvas';
88
import { BeamDirection } from '@coderline/alphatab/rendering/utils/BeamDirection';
99
import { GpImporterTestHelper } from 'test/importer/GpImporterTestHelper';
1010
import { expect } from 'chai';
11+
import { Clef } from '@coderline/alphatab/model/Clef';
1112

1213
describe('Gp5ImporterTest', () => {
1314
it('score-info', async () => {
@@ -544,4 +545,12 @@ describe('Gp5ImporterTest', () => {
544545
expect(score.tracks[1].playbackInfo.program).to.equal(25);
545546
expect(score.tracks[1].playbackInfo.bank).to.equal(77);
546547
});
548+
549+
it('tuning-bass-clef', async () => {
550+
const score = (await GpImporterTestHelper.prepareImporterWithFile('guitarpro5/bass-tuning.gp5')).readScore();
551+
expect(score.tracks[0].staves[0].bars[0].clef).to.equal(Clef.F4);
552+
expect(score.tracks[1].staves[0].bars[0].clef).to.equal(Clef.F4);
553+
expect(score.tracks[2].staves[0].bars[0].clef).to.equal(Clef.F4);
554+
expect(score.tracks[3].staves[0].bars[0].clef).to.equal(Clef.F4);
555+
});
547556
});

packages/transpiler/src/AstPrinterBase.ts

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -152,10 +152,41 @@ export default abstract class AstPrinterBase {
152152
d.isStatic &&
153153
!d.setAccessor &&
154154
cs.isPrimitiveTypeNode(d.type) &&
155-
!!d.initializer &&
155+
this._isConstantExpression(d.initializer) &&
156156
(!d.getAccessor || !d.getAccessor.body)
157157
);
158158
}
159+
private _isConstantExpression(expression: cs.Expression | undefined): boolean {
160+
if (expression === undefined) {
161+
return false;
162+
}
163+
164+
switch (expression.nodeType) {
165+
case cs.SyntaxKind.PrefixUnaryExpression:
166+
return this._isConstantExpression((expression as cs.PrefixUnaryExpression).operand);
167+
case cs.SyntaxKind.PostfixUnaryExpression:
168+
return this._isConstantExpression((expression as cs.PostfixUnaryExpression).operand);
169+
case cs.SyntaxKind.NullLiteral:
170+
case cs.SyntaxKind.TrueLiteral:
171+
case cs.SyntaxKind.FalseLiteral:
172+
case cs.SyntaxKind.StringLiteral:
173+
case cs.SyntaxKind.NumericLiteral:
174+
case cs.SyntaxKind.DefaultExpression:
175+
return true;
176+
case cs.SyntaxKind.BinaryExpression:
177+
return (
178+
this._isConstantExpression((expression as cs.BinaryExpression).left) &&
179+
this._isConstantExpression((expression as cs.BinaryExpression).right)
180+
);
181+
case cs.SyntaxKind.ParenthesizedExpression:
182+
return this._isConstantExpression((expression as cs.ParenthesizedExpression).expression);
183+
// case cs.SyntaxKind.MemberAccessExpression:
184+
// case cs.SyntaxKind.Identifier:
185+
// maybe detect enums and other constant declarations?
186+
}
187+
188+
return false;
189+
}
159190

160191
protected writePropertyAsField(d: cs.PropertyDeclaration) {
161192
if (

0 commit comments

Comments
 (0)