From eba83f262d225358fc1192a93be39be6e7c61a2f Mon Sep 17 00:00:00 2001 From: AdamSEY Date: Tue, 4 Jul 2023 03:54:34 +0200 Subject: [PATCH 1/5] Remove duplicate chords based on this issue: https://github.com/CoderLine/alphaTab/issues/1209 --- src/rendering/layout/ScoreLayout.ts | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/src/rendering/layout/ScoreLayout.ts b/src/rendering/layout/ScoreLayout.ts index dade26e6a..7f944f18b 100644 --- a/src/rendering/layout/ScoreLayout.ts +++ b/src/rendering/layout/ScoreLayout.ts @@ -1,7 +1,6 @@ import { StaveProfile } from '@src/StaveProfile'; import { Environment } from '@src/Environment'; import { Bar } from '@src/model/Bar'; -import { Chord } from '@src/model/Chord'; import { Font, FontStyle, FontWeight } from '@src/model/Font'; import { Score } from '@src/model/Score'; import { Staff } from '@src/model/Staff'; @@ -209,23 +208,24 @@ export abstract class ScoreLayout { if (notation.isNotationElementVisible(NotationElement.ChordDiagrams)) { this.chordDiagrams = new ChordDiagramContainerGlyph(0, 0); this.chordDiagrams.renderer = fakeBarRenderer; - let chords: Map = new Map(); + let chordNames: Set = new Set(); + for (let track of this.renderer.tracks!) { - for (let staff of track.staves) { - const sc = staff.chords; - if (sc) { - for (const [chordId, chord] of sc) { - if (!chords.has(chordId)) { - if (chord.showDiagram) { - chords.set(chordId, chord); - this.chordDiagrams!.addChord(chord); - } - } - } + for (let staff of track.staves) { + const sc = staff.chords; + if (sc) { + for (const [, chord] of sc) { + if (!chordNames.has(chord.name)) { + if (chord.showDiagram) { + chordNames.add(chord.name); + this.chordDiagrams!.addChord(chord); + } } + } } + } } - } + } } public get scale(): number { From 08e11ede91028af96d1ed5fc0ace66ff4fd4fc4b Mon Sep 17 00:00:00 2001 From: Adam <28712999+AdamSEY@users.noreply.github.com> Date: Wed, 5 Jul 2023 16:41:53 +0200 Subject: [PATCH 2/5] Update ScoreLayout.ts We're creating chord uniqueId based on the chord props. --- src/rendering/layout/ScoreLayout.ts | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/src/rendering/layout/ScoreLayout.ts b/src/rendering/layout/ScoreLayout.ts index 7f944f18b..3f35a1534 100644 --- a/src/rendering/layout/ScoreLayout.ts +++ b/src/rendering/layout/ScoreLayout.ts @@ -208,24 +208,24 @@ export abstract class ScoreLayout { if (notation.isNotationElementVisible(NotationElement.ChordDiagrams)) { this.chordDiagrams = new ChordDiagramContainerGlyph(0, 0); this.chordDiagrams.renderer = fakeBarRenderer; - let chordNames: Set = new Set(); + let chordIds: Set = new Set(); for (let track of this.renderer.tracks!) { - for (let staff of track.staves) { - const sc = staff.chords; - if (sc) { - for (const [, chord] of sc) { - if (!chordNames.has(chord.name)) { - if (chord.showDiagram) { - chordNames.add(chord.name); - this.chordDiagrams!.addChord(chord); - } + for (let staff of track.staves) { + const sc = staff.chords; + if (sc) { + for (const [, chord] of sc) { + if (!chordIds.has(chord.uniqueId)) { + if (chord.showDiagram) { + chordIds.add(chord.uniqueId); + this.chordDiagrams!.addChord(chord); + } + } + } } - } } - } } - } + } } public get scale(): number { From f9e1da332a21d3b280e86ddda3bd1befadc02f7e Mon Sep 17 00:00:00 2001 From: Adam <28712999+AdamSEY@users.noreply.github.com> Date: Wed, 5 Jul 2023 16:43:28 +0200 Subject: [PATCH 3/5] Update Chord.ts Generating chord uniqueId based on chord props. --- src/model/Chord.ts | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/src/model/Chord.ts b/src/model/Chord.ts index bb64efca6..7fe46fe3c 100644 --- a/src/model/Chord.ts +++ b/src/model/Chord.ts @@ -1,7 +1,7 @@ import { Staff } from '@src/model/Staff'; -// TODO: rework model to specify for each finger -// on which frets they are placed. +// TODO: rework model to specify for each finger +// on which frets they are placed. /** * A chord definition. @@ -51,4 +51,16 @@ export class Chord { * Gets or sets whether the fingering is shown below the chord diagram. */ public showFingering: boolean = true; + /** + * Gets a unique id for this chord based on its properties. + */ + public get uniqueId(): string { + const properties = [ + this.name, + this.firstFret, + JSON.stringify(this.strings), + JSON.stringify(this.barreFrets) + ]; + return properties.join('|'); + } } From 48b97d4ef3375d1b856e2201f9430c9596ed81c6 Mon Sep 17 00:00:00 2001 From: Adam <28712999+AdamSEY@users.noreply.github.com> Date: Fri, 7 Jul 2023 04:39:58 +0200 Subject: [PATCH 4/5] Update Chord.ts Fixing issue with building on Kotlin --- src/model/Chord.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/model/Chord.ts b/src/model/Chord.ts index 7fe46fe3c..42716187d 100644 --- a/src/model/Chord.ts +++ b/src/model/Chord.ts @@ -58,8 +58,8 @@ export class Chord { const properties = [ this.name, this.firstFret, - JSON.stringify(this.strings), - JSON.stringify(this.barreFrets) + this.strings.join(','), + this.barreFrets.join(',') ]; return properties.join('|'); } From e20ddbaaed4f93131f021cb5b6e97d694ddffd8b Mon Sep 17 00:00:00 2001 From: Danielku15 Date: Sun, 6 Aug 2023 00:49:44 +0200 Subject: [PATCH 5/5] Fix build, update uniqueid properties and added test --- src.csharp/AlphaTab/Core/TypeHelper.cs | 6 ++++++ src/model/Chord.ts | 7 +++++-- .../chords-duplicates.gp | Bin 0 -> 12311 bytes .../chords-duplicates.png | Bin 0 -> 28505 bytes .../features/EffectsAndAnnotations.test.ts | 5 +++++ 5 files changed, 16 insertions(+), 2 deletions(-) create mode 100644 test-data/visual-tests/effects-and-annotations/chords-duplicates.gp create mode 100644 test-data/visual-tests/effects-and-annotations/chords-duplicates.png diff --git a/src.csharp/AlphaTab/Core/TypeHelper.cs b/src.csharp/AlphaTab/Core/TypeHelper.cs index 161fd4814..b0894622d 100644 --- a/src.csharp/AlphaTab/Core/TypeHelper.cs +++ b/src.csharp/AlphaTab/Core/TypeHelper.cs @@ -376,6 +376,12 @@ public static string SubstringIndex(this string s, double startIndex, double end return s.Substring((int) startIndex, (int) (endIndex - startIndex)); } + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static string Join(this IList s, string separator) + { + return string.Join(separator, s); + } + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static string ReplaceAll(this string s, string before, string after) { diff --git a/src/model/Chord.ts b/src/model/Chord.ts index 42716187d..914588276 100644 --- a/src/model/Chord.ts +++ b/src/model/Chord.ts @@ -57,9 +57,12 @@ export class Chord { public get uniqueId(): string { const properties = [ this.name, - this.firstFret, + this.firstFret.toString(), this.strings.join(','), - this.barreFrets.join(',') + this.barreFrets.join(','), + this.showDiagram.toString(), + this.showFingering.toString(), + this.showName.toString() ]; return properties.join('|'); } diff --git a/test-data/visual-tests/effects-and-annotations/chords-duplicates.gp b/test-data/visual-tests/effects-and-annotations/chords-duplicates.gp new file mode 100644 index 0000000000000000000000000000000000000000..f22e341f4eefd9fdde43f4ef99a71ebb3465d106 GIT binary patch literal 12311 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
>?jojXXWm>oey`eGJ$?@hlDr^ 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

0Utc(HbF~O!&e*CvEL={z~ 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 N^rH3!)OqVW{|~bORyzOy literal 0 HcmV?d00001 diff --git a/test/visualTests/features/EffectsAndAnnotations.test.ts b/test/visualTests/features/EffectsAndAnnotations.test.ts index 59032338f..6b25d18fa 100644 --- a/test/visualTests/features/EffectsAndAnnotations.test.ts +++ b/test/visualTests/features/EffectsAndAnnotations.test.ts @@ -20,6 +20,11 @@ describe('EffectsAndAnnotationsTests', () => { await VisualTestHelper.runVisualTest('effects-and-annotations/chords.gp'); }); + it('chords-duplicates', async () => { + // This file was manually modified to contain 2 separate chords with the same details. + await VisualTestHelper.runVisualTest('effects-and-annotations/chords-duplicates.gp'); + }); + it('vibrato', async () => { await VisualTestHelper.runVisualTest('effects-and-annotations/vibrato.gp'); });