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 new note effects (tuneto, string numbers) and rework fingering #1645

Merged
merged 10 commits into from
Aug 24, 2024
3 changes: 2 additions & 1 deletion src.compiler/csharp/CSharpAstPrinter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -156,7 +156,8 @@ export default class CSharpAstPrinter extends AstPrinterBase {
if (p.type) {
this.writeType(p.type, false, p.params);
}
this.write(` ${p.name}`);
this.write(' ');
this.writeIdentifier(p.name);

if (p.initializer) {
this.write(' = ');
Expand Down
7 changes: 6 additions & 1 deletion src/RenderingResources.ts
Original file line number Diff line number Diff line change
Expand Up @@ -81,10 +81,15 @@ export class RenderingResources {
public barNumberColor: Color = new Color(200, 0, 0, 0xff);

/**
* Gets or sets the font to use for displaying finger information in the music sheet.
* Gets or sets the font to use for displaying finger information above the music sheet.
*/
public fingeringFont: Font = new Font(RenderingResources.serifFont, 14, FontStyle.Plain);

/**
* Gets or sets the font to use for displaying finger information when inline into the music sheet.
*/
public inlineFingeringFont: Font = new Font(RenderingResources.serifFont, 12, FontStyle.Plain);

/**
* Gets or sets the font to use for section marker labels shown above the music sheet.
*/
Expand Down
6 changes: 6 additions & 0 deletions src/exporter/GpifWriter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -312,6 +312,9 @@ export class GpifWriter {
case AccentuationType.Heavy:
accentFlags |= 0x04;
break;
case AccentuationType.Tenuto:
accentFlags |= 0x10;
break;
}

if (accentFlags > 0) {
Expand Down Expand Up @@ -387,6 +390,9 @@ export class GpifWriter {
this.writeSimplePropertyNode(properties, 'String', 'String', (note.string - 1).toString());
this.writeSimplePropertyNode(properties, 'Fret', 'Fret', note.fret.toString());
this.writeSimplePropertyNode(properties, 'Midi', 'Number', note.realValue.toString());
if(note.showStringNumber) {
this.writeSimplePropertyNode(properties, 'ShowStringNumber', 'Enable', null);
}
}

if (note.isPiano) {
Expand Down
6 changes: 5 additions & 1 deletion src/generated/RenderingResourcesJson.ts
Original file line number Diff line number Diff line change
Expand Up @@ -69,9 +69,13 @@ export interface RenderingResourcesJson {
*/
barNumberColor?: ColorJson;
/**
* Gets or sets the font to use for displaying finger information in the music sheet.
* Gets or sets the font to use for displaying finger information above the music sheet.
*/
fingeringFont?: FontJson;
/**
* Gets or sets the font to use for displaying finger information when inline into the music sheet.
*/
inlineFingeringFont?: FontJson;
/**
* Gets or sets the font to use for section marker labels shown above the music sheet.
*/
Expand Down
4 changes: 4 additions & 0 deletions src/generated/RenderingResourcesSerializer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ export class RenderingResourcesSerializer {
o.set("barnumberfont", Font.toJson(obj.barNumberFont));
o.set("barnumbercolor", Color.toJson(obj.barNumberColor));
o.set("fingeringfont", Font.toJson(obj.fingeringFont));
o.set("inlinefingeringfont", Font.toJson(obj.inlineFingeringFont));
o.set("markerfont", Font.toJson(obj.markerFont));
o.set("mainglyphcolor", Color.toJson(obj.mainGlyphColor));
o.set("secondaryglyphcolor", Color.toJson(obj.secondaryGlyphColor));
Expand Down Expand Up @@ -87,6 +88,9 @@ export class RenderingResourcesSerializer {
case "fingeringfont":
obj.fingeringFont = Font.fromJson(v)!;
return true;
case "inlinefingeringfont":
obj.inlineFingeringFont = Font.fromJson(v)!;
return true;
case "markerfont":
obj.markerFont = Font.fromJson(v)!;
return true;
Expand Down
1 change: 1 addition & 0 deletions src/generated/model/NoteCloner.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ export class NoteCloner {
}
clone.fret = original.fret;
clone.string = original.string;
clone.showStringNumber = original.showStringNumber;
clone.octave = original.octave;
clone.tone = original.tone;
clone.percussionArticulation = original.percussionArticulation;
Expand Down
4 changes: 4 additions & 0 deletions src/generated/model/NoteSerializer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ export class NoteSerializer {
}
o.set("fret", obj.fret);
o.set("string", obj.string);
o.set("showstringnumber", obj.showStringNumber);
o.set("octave", obj.octave);
o.set("tone", obj.tone);
o.set("percussionarticulation", obj.percussionArticulation);
Expand Down Expand Up @@ -102,6 +103,9 @@ export class NoteSerializer {
case "string":
obj.string = v! as number;
return true;
case "showstringnumber":
obj.showStringNumber = v! as boolean;
return true;
case "octave":
obj.octave = v! as number;
return true;
Expand Down
3 changes: 3 additions & 0 deletions src/importer/AlphaTexImporter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1825,6 +1825,9 @@ export class AlphaTexImporter extends ScoreImporter {
} else if (syData === 'hac') {
this._sy = this.newSy();
note.accentuated = AccentuationType.Heavy;
} else if (syData === 'ten') {
this._sy = this.newSy();
note.accentuated = AccentuationType.Tenuto;
} else if (syData === 'pm') {
this._sy = this.newSy();
note.isPalmMute = true;
Expand Down
8 changes: 8 additions & 0 deletions src/importer/GpifParser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1819,6 +1819,9 @@ export class GpifParser {
if ((accentFlags & 0x08) !== 0) {
note.accentuated = AccentuationType.Normal;
}
if ((accentFlags & 0x10) !== 0) {
note.accentuated = AccentuationType.Tenuto;
}
break;
case 'Tie':
if (c.getAttribute('destination').toLowerCase() === 'true') {
Expand Down Expand Up @@ -1901,6 +1904,11 @@ export class GpifParser {
case 'Property':
let name: string = c.getAttribute('name');
switch (name) {
case 'ShowStringNumber':
if (c.findChildElement('Enable')) {
note.showStringNumber = true;
}
break;
case 'String':
note.string = parseInt(c.findChildElement('String')!.innerText) + 1;
break;
Expand Down
3 changes: 3 additions & 0 deletions src/importer/MusicXmlImporter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1149,6 +1149,9 @@ export class MusicXmlImporter extends ScoreImporter {
case 'detached-legato':
note.isStaccato = true;
break;
case 'tenuto':
note.accentuated = AccentuationType.Tenuto;
break;
}
}
}
Expand Down
6 changes: 5 additions & 1 deletion src/model/AccentuationType.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,5 +13,9 @@ export enum AccentuationType {
/**
* Heavy accentuation
*/
Heavy
Heavy,
/**
* Tenuto accentuation
*/
Tenuto
}
3 changes: 2 additions & 1 deletion src/model/ModelUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -83,10 +83,11 @@ export class ModelUtils {
if (leftHand) {
switch (finger) {
case Fingers.Unknown:
return null;
case Fingers.NoOrDead:
return '0';
case Fingers.Thumb:
return 'T';
return 't';
case Fingers.IndexFinger:
return '1';
case Fingers.MiddleFinger:
Expand Down
5 changes: 5 additions & 0 deletions src/model/MusicFontSymbol.ts
Original file line number Diff line number Diff line change
Expand Up @@ -82,8 +82,13 @@ export enum MusicFontSymbol {
AccidentalQuarterToneNaturalArrowUp = 0xe272,

ArticAccentAbove = 0xe4a0,
ArticAccentBelow = 0xe4a1,
ArticStaccatoAbove = 0xe4a2,
ArticStaccatoBelow = 0xe4a3,
ArticTenutoAbove = 0xe4a4,
ArticTenutoBelow = 0xe4a5,
ArticMarcatoAbove = 0xe4ac,
ArticMarcatoBelow = 0xe4aD,

FermataAbove = 0xe4c0,
FermataShortAbove = 0xe4c4,
Expand Down
5 changes: 5 additions & 0 deletions src/model/Note.ts
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,11 @@ export class Note {
*/
public string: number = -1;

/**
* Gets or sets whether the string number for this note should be shown.
*/
public showStringNumber: boolean = false;

public get isPiano(): boolean {
return !this.isStringed && this.octave >= 0 && this.tone >= 0;
}
Expand Down
51 changes: 2 additions & 49 deletions src/rendering/LineBarRenderer.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,13 @@
import { Bar, Beat, Duration, Fingers, GraceType, Note, TupletGroup } from '@src/model';
import { Bar, Beat, Duration, GraceType, TupletGroup } from '@src/model';
import { BarRendererBase } from './BarRendererBase';
import { ScoreRenderer } from './ScoreRenderer';
import { ICanvas, TextAlign, TextBaseline } from '@src/platform/ICanvas';
import { SpacingGlyph } from './glyphs/SpacingGlyph';
import { BeamingHelper } from './utils/BeamingHelper';
import { BeamDirection } from './utils/BeamDirection';
import { FingeringMode, NotationMode } from '@src/NotationSettings';
import { NotationMode } from '@src/NotationSettings';
import { FlagGlyph } from './glyphs/FlagGlyph';
import { NoteHeadGlyph } from './glyphs/NoteHeadGlyph';
import { Settings } from '@src/Settings';
import { ModelUtils } from '@src/model/ModelUtils';
import { RepeatOpenGlyph } from './glyphs/RepeatOpenGlyph';
import { BarSeperatorGlyph } from './glyphs/BarSeperatorGlyph';
Expand Down Expand Up @@ -415,18 +414,14 @@ export abstract class LineBarRenderer extends BarRendererBase {
let topY: number = this.getFlagTopY(beat);
let bottomY: number = this.getFlagBottomY(beat);
let beamY: number = 0;
let fingeringY: number = 0;
if (direction === BeamDirection.Down) {
bottomY += stemSize * scaleMod;
beamY = bottomY;
fingeringY = cy + this.y + bottomY;
} else {
topY -= stemSize * scaleMod;
beamY = topY;
fingeringY = cy + this.y + topY;
}

this.paintFingering(canvas, beat, cx + this.x + beatLineX, direction, fingeringY);
if (!h.hasLine(true, beat)) {
continue;
}
Expand Down Expand Up @@ -480,47 +475,6 @@ export abstract class LineBarRenderer extends BarRendererBase {
canvas: ICanvas
): void;

protected paintFingering(
canvas: ICanvas,
beat: Beat,
beatLineX: number,
direction: BeamDirection,
topY: number
): void {
let settings: Settings = this.settings;
if (
settings.notation.fingeringMode !== FingeringMode.ScoreDefault &&
settings.notation.fingeringMode !== FingeringMode.ScoreForcePiano
) {
return;
}
if (direction === BeamDirection.Up) {
beatLineX -= 10 * this.scale;
} else {
beatLineX += 3 * this.scale;
}
// sort notes ascending in their value to ensure
// we are drawing the numbers according to their order on the stave
let noteList: Note[] = beat.notes.slice(0);
noteList.sort((a, b) => {
return a.realValue - b.realValue;
});
for (let n: number = 0; n < noteList.length; n++) {
let note: Note = noteList[n];
let text: string | null = null;
if (note.leftHandFinger !== Fingers.Unknown) {
text = ModelUtils.fingerToString(settings, beat, note.leftHandFinger, true);
} else if (note.rightHandFinger !== Fingers.Unknown) {
text = ModelUtils.fingerToString(settings, beat, note.rightHandFinger, false);
}
if (!text) {
continue;
}
canvas.fillText(text, beatLineX, topY);
topY -= canvas.font.size | 0;
}
}

protected getFlagStemSize(duration: Duration): number {
let size: number = 0;
switch (duration) {
Expand Down Expand Up @@ -604,7 +558,6 @@ export abstract class LineBarRenderer extends BarRendererBase {
} else if (i !== 0) {
fingeringY -= canvas.font.size * 1.5;
}
this.paintFingering(canvas, beat, cx + this.x + beatLineX, direction, fingeringY);
let brokenBarOffset: number = 6 * this.scale * scaleMod;
let barSpacing: number =
(BarRendererBase.BeamSpacing + BarRendererBase.BeamThickness) * this.scale * scaleMod;
Expand Down
37 changes: 34 additions & 3 deletions src/rendering/ScoreBarRenderer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,9 @@ export class ScoreBarRenderer extends LineBarRenderer {

public simpleWhammyOverflow: number = 0;

public beatEffectsMinY: number | null = null;
public beatEffectsMaxY: number | null = null;

public accidentalHelper: AccidentalHelper;

public constructor(renderer: ScoreRenderer, bar: Bar) {
Expand All @@ -53,6 +56,18 @@ export class ScoreBarRenderer extends LineBarRenderer {
return this.bar.staff.standardNotationLineCount;
}

public registerBeatEffectOverflows(beatEffectsMinY: number, beatEffectsMaxY: number) {
const currentBeatEffectsMinY = this.beatEffectsMinY;
if (currentBeatEffectsMinY == null || beatEffectsMinY < currentBeatEffectsMinY) {
this.beatEffectsMinY = beatEffectsMinY;
}

const currentBeatEffectsMaxY = this.beatEffectsMaxY;
if (currentBeatEffectsMaxY == null || beatEffectsMaxY > currentBeatEffectsMaxY) {
this.beatEffectsMaxY = beatEffectsMaxY;
}
}

/**
* Gets the relative y position of the given steps relative to first line.
* @param steps the amount of steps while 2 steps are one line
Expand All @@ -78,12 +93,29 @@ export class ScoreBarRenderer extends LineBarRenderer {
let top: number = this.getScoreY(-2);
let bottom: number = this.getScoreY(10);
let whammyOffset: number = this.simpleWhammyOverflow;

const beatEffectsMinY = this.beatEffectsMinY;
if (beatEffectsMinY !== null) {
const beatEffectTopOverflow = top - beatEffectsMinY;
if (beatEffectTopOverflow > 0) {
this.registerOverflowTop(beatEffectTopOverflow);
}
}

const beatEffectsMaxY = this.beatEffectsMaxY;
if (beatEffectsMaxY !== null) {
const beatEffectBottomOverflow = beatEffectsMaxY - bottom;
if (beatEffectBottomOverflow > 0) {
this.registerOverflowBottom(beatEffectBottomOverflow);
}
}

this.registerOverflowTop(whammyOffset);

let maxNoteY: number = this.getScoreY(this.accidentalHelper.maxLine);
let maxNoteHelper: BeamingHelper = this.helpers.getBeamingHelperForBeat(this.accidentalHelper.maxLineBeat);
if (maxNoteHelper.direction === BeamDirection.Up) {
maxNoteY -= this.getStemSize(maxNoteHelper);
maxNoteY -= maxNoteHelper.fingeringCount * this.resources.graceFont.size;
if (maxNoteHelper.hasTuplet) {
maxNoteY -= this.tupletSize;
}
Expand All @@ -95,7 +127,6 @@ export class ScoreBarRenderer extends LineBarRenderer {
let minNoteHelper: BeamingHelper = this.helpers.getBeamingHelperForBeat(this.accidentalHelper.minLineBeat!);
if (minNoteHelper.direction === BeamDirection.Down) {
minNoteY += this.getStemSize(minNoteHelper);
minNoteY += minNoteHelper.fingeringCount * this.resources.graceFont.size;
if (minNoteHelper.hasTuplet) {
minNoteY += this.tupletSize;
}
Expand Down Expand Up @@ -475,7 +506,7 @@ export class ScoreBarRenderer extends LineBarRenderer {
this.bar.masterBar.timeSignatureNumerator,
this.bar.masterBar.timeSignatureDenominator,
this.bar.masterBar.timeSignatureCommon,
this.bar.masterBar.isFreeTime,
this.bar.masterBar.isFreeTime
)
);
}
Expand Down
Loading