Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Add tempo label and adjust tempo marker rendering #1906

Merged
merged 2 commits into from
Feb 19, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions src/importer/AlphaTexImporter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3060,6 +3060,7 @@ export class AlphaTexImporter extends ScoreImporter {
tempoAutomation.isLinear = false;
tempoAutomation.type = AutomationType.Tempo;
tempoAutomation.value = this._score.tempo;
tempoAutomation.text = this._score.tempoLabel;
master.tempoAutomations.push(tempoAutomation);
}
return anyMeta;
Expand Down
20 changes: 16 additions & 4 deletions src/rendering/BarRendererBase.ts
Original file line number Diff line number Diff line change
Expand Up @@ -249,12 +249,15 @@ export class BarRendererBase {
this._postBeatGlyphs.width = this.layoutingInfo.postBeatSize;
this.width = Math.ceil(this._postBeatGlyphs.x + this._postBeatGlyphs.width);
this.computedWidth = this.width;

// For cases like in the horizontal layout we need to set the fixed width early
// to have correct partials splitting. the proper alignment to this scale will happen
// later in the workflow.
const fixedBarWidth = this.barDisplayWidth;
if (fixedBarWidth > 0 && this.scoreRenderer.layout!.systemsLayoutMode == InternalSystemsLayoutMode.FromModelWithWidths) {
if (
fixedBarWidth > 0 &&
this.scoreRenderer.layout!.systemsLayoutMode == InternalSystemsLayoutMode.FromModelWithWidths
) {
this.width = fixedBarWidth;
this.computedWidth = fixedBarWidth;
}
Expand Down Expand Up @@ -452,7 +455,7 @@ export class BarRendererBase {
}

protected createBeatGlyphs(): void {
for(const voice of this.bar.voices) {
for (const voice of this.bar.voices) {
if (this.hasVoiceContainer(voice)) {
this.createVoiceGlyphs(voice);
}
Expand Down Expand Up @@ -499,6 +502,15 @@ export class BarRendererBase {
return 0;
}

public getRatioPositionX(ticks: number): number {
const firstOnNoteX = this.bar.isEmpty
? this.beatGlyphsStart
: this.getBeatX(this.bar.voices[0].beats[0], BeatXPosition.OnNotes);
const x = firstOnNoteX;
const w = this.postBeatGlyphsStart - firstOnNoteX;
return x + w * ticks;
}

public getNoteX(note: Note, requestedPosition: NoteXPosition): number {
let container = this.getBeatContainer(note.beat);
if (container) {
Expand Down Expand Up @@ -529,7 +541,7 @@ export class BarRendererBase {
this.updateSizes();
this.registerLayoutingInfo();
}

protected recreatePreBeatGlyphs() {
this._preBeatGlyphs = new LeftToRightLayoutingGlyphGroup();
this._preBeatGlyphs.renderer = this;
Expand Down
23 changes: 13 additions & 10 deletions src/rendering/glyphs/BarTempoGlyph.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import { ICanvas, TextBaseline } from '@src/platform';
import { EffectGlyph } from './EffectGlyph';
import { Automation, MusicFontSymbol } from '@src/model';
import { NoteHeadGlyph } from './NoteHeadGlyph';

/**
* This glyph renders tempo annotations for tempo automations
Expand All @@ -21,26 +20,30 @@ export class BarTempoGlyph extends EffectGlyph {
}

public override paint(cx: number, cy: number, canvas: ICanvas): void {
const startX = cx + this.x;
const endX = cx + this.renderer.postBeatGlyphsStart;
for (const automation of this.tempoAutomations) {
let x = cx + this.renderer.getRatioPositionX(automation.ratioPosition);

for(const automation of this.tempoAutomations) {
const x = cx + this.x + (endX - startX) * automation.ratioPosition;
const res = this.renderer.resources;
canvas.font = res.markerFont;

canvas.textBaseline = TextBaseline.Top;
if (automation.text) {
const size = canvas.measureText(automation.text);
canvas.fillText(automation.text, x, cy + this.y + canvas.font.size / 2);
x += size.width + canvas.font.size * 0.7;
}
canvas.fillMusicFontSymbol(
x,
cy + this.y + this.height * 0.8,
NoteHeadGlyph.GraceScale,
0.5,
MusicFontSymbol.NoteQuarterUp,
false
true
);
canvas.textBaseline = TextBaseline.Top;
canvas.fillText(
'= ' + automation.value.toString(),
x + this.height / 2,
x + 8,
cy + this.y + canvas.font.size / 2
);
}
}
}
}
21 changes: 6 additions & 15 deletions src/rendering/glyphs/SustainPedalGlyph.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ import { ICanvas } from '@src/platform';
import { EffectGlyph } from './EffectGlyph';
import { SustainPedalMarker, SustainPedalMarkerType } from '@src/model/Bar';
import { MusicFontSymbol } from '@src/model';
import { BeatXPosition } from '../BeatXPosition';

export class SustainPedalGlyph extends EffectGlyph {
private static readonly TextHeight = 19;
Expand All @@ -24,13 +23,7 @@ export class SustainPedalGlyph extends EffectGlyph {
public override paint(cx: number, cy: number, canvas: ICanvas): void {
const renderer = this.renderer;

const firstOnNoteX = renderer.bar.isEmpty
? renderer.beatGlyphsStart
: renderer.getBeatX(renderer.bar.voices[0].beats[0], BeatXPosition.OnNotes);

const x = cx + this.x + firstOnNoteX;
const y = cy + this.y;
const w = renderer.postBeatGlyphsStart - firstOnNoteX;
const h = this.height;

let markers = renderer.bar.sustainPedals;
Expand All @@ -39,34 +32,32 @@ export class SustainPedalGlyph extends EffectGlyph {
while (markerIndex < markers.length) {
let marker: SustainPedalMarker | null = markers[markerIndex];
while (marker != null) {
const markerX = x + w * marker.ratioPosition;
const markerX = cx + this.renderer.getRatioPositionX(marker.ratioPosition);

// real own marker
let linePadding = 0;
if (marker.pedalType === SustainPedalMarkerType.Down) {
canvas.fillMusicFontSymbol(markerX, y + h, 1, MusicFontSymbol.KeyboardPedalPed, true);
linePadding =
(SustainPedalGlyph.TextWidth / 2) + SustainPedalGlyph.TextLinePadding;
linePadding = SustainPedalGlyph.TextWidth / 2 + SustainPedalGlyph.TextLinePadding;
} else if (marker.pedalType === SustainPedalMarkerType.Up) {
canvas.fillMusicFontSymbol(markerX, y + h, 1, MusicFontSymbol.KeyboardPedalUp, true);
linePadding =
(SustainPedalGlyph.StarSize / 2) + SustainPedalGlyph.StarLinePadding;
linePadding = SustainPedalGlyph.StarSize / 2 + SustainPedalGlyph.StarLinePadding;
}

// line to next marker or end-of-bar
if (marker.nextPedalMarker) {
if (marker.nextPedalMarker.bar === marker.bar) {
let nextX = x + w * marker.nextPedalMarker.ratioPosition;
let nextX = cx + this.renderer.getRatioPositionX(marker.nextPedalMarker.ratioPosition);

switch (marker.nextPedalMarker.pedalType) {
case SustainPedalMarkerType.Down:
nextX -= (SustainPedalGlyph.TextWidth / 2);
nextX -= SustainPedalGlyph.TextWidth / 2;
break;
case SustainPedalMarkerType.Hold:
// no offset on hold
break;
case SustainPedalMarkerType.Up:
nextX -= (SustainPedalGlyph.StarSize / 2);
nextX -= SustainPedalGlyph.StarSize / 2;
break;
}

Expand Down
2 changes: 1 addition & 1 deletion src/synth/IAlphaSynth.ts
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,7 @@ export interface IAlphaSynth {
applyTranspositionPitches(transpositionPitches: Map<number, number>): void;

/**
* Sets the transposition pitch a channel. This pitch is additionally applied beside the
* Sets the transposition pitch of a given channel. This pitch is additionally applied beside the
* ones applied already via {@link applyTranspositionPitches}.
* @param channel The channel number
* @param semitones The number of semitones to apply as pitch offset.
Expand Down
Binary file modified test-data/visual-tests/effects-and-annotations/accentuations.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified test-data/visual-tests/effects-and-annotations/brush.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified test-data/visual-tests/effects-and-annotations/dynamics.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified test-data/visual-tests/effects-and-annotations/fade-in.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified test-data/visual-tests/effects-and-annotations/fade.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified test-data/visual-tests/effects-and-annotations/fingering-new.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified test-data/visual-tests/effects-and-annotations/let-ring.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified test-data/visual-tests/effects-and-annotations/markers.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified test-data/visual-tests/effects-and-annotations/ornaments.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified test-data/visual-tests/effects-and-annotations/palm-mute.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified test-data/visual-tests/effects-and-annotations/pick-stroke.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified test-data/visual-tests/effects-and-annotations/slides.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified test-data/visual-tests/effects-and-annotations/string-numbers.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified test-data/visual-tests/effects-and-annotations/tap.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified test-data/visual-tests/effects-and-annotations/tempo.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified test-data/visual-tests/effects-and-annotations/text.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified test-data/visual-tests/effects-and-annotations/tremolo-picking.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified test-data/visual-tests/effects-and-annotations/trill.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified test-data/visual-tests/effects-and-annotations/vibrato.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified test-data/visual-tests/general/alternate-endings.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified test-data/visual-tests/general/repeats.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified test-data/visual-tests/general/song-details.png
Binary file modified test-data/visual-tests/general/tuning.png
Binary file modified test-data/visual-tests/music-notation/clefs.png
Binary file modified test-data/visual-tests/music-notation/time-signatures.png
Binary file modified test-data/visual-tests/notation-elements/chord-diagrams-off.png
Binary file modified test-data/visual-tests/notation-elements/chord-diagrams-on.png
Binary file modified test-data/visual-tests/notation-elements/effects-on.png
Binary file modified test-data/visual-tests/notation-elements/guitar-tuning-off.png
Binary file modified test-data/visual-tests/notation-elements/guitar-tuning-on.png
Binary file modified test-data/visual-tests/notation-elements/score-info-album.png
Binary file modified test-data/visual-tests/notation-elements/score-info-all.png
Binary file modified test-data/visual-tests/notation-elements/score-info-artist.png
Binary file modified test-data/visual-tests/notation-elements/score-info-music.png
Binary file modified test-data/visual-tests/notation-elements/score-info-subtitle.png
Binary file modified test-data/visual-tests/notation-elements/score-info-title.png
Binary file modified test-data/visual-tests/notation-elements/score-info-words.png
Binary file modified test-data/visual-tests/notation-elements/track-names-off.png
Binary file modified test-data/visual-tests/notation-elements/track-names-on.png
Binary file modified test-data/visual-tests/special-notes/dead-notes.png
Binary file modified test-data/visual-tests/special-notes/ghost-notes.png
Binary file modified test-data/visual-tests/special-notes/grace-notes.png
Binary file modified test-data/visual-tests/special-notes/tied-notes.png
Binary file modified test-data/visual-tests/special-tracks/percussion.png
19 changes: 17 additions & 2 deletions test/visualTests/features/EffectsAndAnnotations.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,17 @@ describe('EffectsAndAnnotationsTests', () => {
await VisualTestHelper.runVisualTest('effects-and-annotations/tempo.gp');
});

it('tempo-text', async () => {
await VisualTestHelper.runVisualTestTex(
`
\\tempo 90 "First"
.
:4 3.3*4 | 3.3 3.3 {v f tempo 120 "Other" } 3.3 6.3
`,
`effects-and-annotations/tempo-text.png`
);
});

it('beat-tempo-change', async () => {
await VisualTestHelper.runVisualTest('effects-and-annotations/beat-tempo-change.gp');
});
Expand Down Expand Up @@ -245,15 +256,19 @@ describe('EffectsAndAnnotationsTests', () => {
});

it('bend-vibrato-default', async () => {
const inputFileData = await TestPlatform.loadFile(`test-data/visual-tests/effects-and-annotations/bend-vibrato.gp`);
const inputFileData = await TestPlatform.loadFile(
`test-data/visual-tests/effects-and-annotations/bend-vibrato.gp`
);
const referenceFileName = 'effects-and-annotations/bend-vibrato-default.png';
const settings = new Settings();
const score = ScoreLoader.loadScoreFromBytes(inputFileData, settings);
await VisualTestHelper.runVisualTestScore(score, referenceFileName, settings);
});

it('bend-vibrato-songbook', async () => {
const inputFileData = await TestPlatform.loadFile(`test-data/visual-tests/effects-and-annotations/bend-vibrato.gp`);
const inputFileData = await TestPlatform.loadFile(
`test-data/visual-tests/effects-and-annotations/bend-vibrato.gp`
);
const referenceFileName = 'effects-and-annotations/bend-vibrato-songbook.png';
const settings = new Settings();
settings.setSongBookModeSettings();
Expand Down