Skip to content

Commit

Permalink
Merge branch 'chord-finder'
Browse files Browse the repository at this point in the history
  • Loading branch information
threedalpeng committed Feb 26, 2024
2 parents 6a4fc3a + 7a00973 commit ceff21c
Show file tree
Hide file tree
Showing 12 changed files with 1,209 additions and 55 deletions.
32 changes: 27 additions & 5 deletions src/lib/notation/ChordNotation.svelte
Original file line number Diff line number Diff line change
@@ -1,12 +1,34 @@
<script lang="ts">
import { getChordNotations, type ChordName, type ChordRoot } from '$/utils/music/chords';
import {
type ChordBass,
type ChordExtension,
type ChordQuality,
type ChordRoot
} from '$/utils/music/chords';
import { stringifyFinaleJazzChordSigns } from '$/utils/music/font';
import ChordExtentionNotation from './chord/ChordExtensionNotation.svelte';
import ChordQualityNotation from './chord/ChordQualityNotation.svelte';
import ChordRootNotation from './chord/ChordRootNotation.svelte';
import ChordTensionNotation from './chord/ChordTensionNotation .svelte';
export let root: ChordRoot;
export let name: ChordName;
export let quality: ChordQuality | undefined = undefined;
export let extension: ChordExtension | undefined | null = undefined;
export let tensions: number[] = [];
export let bass: ChordBass | undefined = undefined;
$: chordNotations = getChordNotations(root, name);
$: needsToSwitch =
(quality === 'sus2' || quality === 'sus4') && extension !== 'b6' && extension !== 'maj7';
</script>

<span class="font-chord">
{chordNotations.default.short}
<span class="font-chord"
><ChordRootNotation {root} />{#if !needsToSwitch}<ChordQualityNotation
{quality}
/>{/if}<ChordExtentionNotation {extension} />{#if needsToSwitch}<ChordQualityNotation
{quality}
/>{/if}<ChordTensionNotation
{tensions}
/>{#if bass !== undefined && bass !== root}{stringifyFinaleJazzChordSigns([
'/'
])}<ChordRootNotation root={bass} />{/if}
</span>
9 changes: 5 additions & 4 deletions src/lib/notation/PitchNotation.svelte
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
<script lang="ts">
import { getChordNotations, type ChordRoot } from '$/utils/music/chords';
import { type ChordRoot } from '$/utils/music/chords';
import { stringifyFinaleJazzChordSigns } from '$/utils/music/font';
import { chordRootToFinaleJazzChordSignMap } from './chord/chord-map';
export let note: ChordRoot;
export let octave: number;
$: chordNotations = getChordNotations(note, 'none');
$: chordNotation = stringifyFinaleJazzChordSigns(chordRootToFinaleJazzChordSignMap[note]);
</script>

<span class="font-chord">{chordNotations.default.short}</span><span class="font-jazz">{octave}</span
>
<span class="font-chord">{chordNotation}</span><span class="font-jazz">{octave}</span>
17 changes: 17 additions & 0 deletions src/lib/notation/chord/ChordExtensionNotation.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
<script lang="ts">
import { type ChordExtension } from '$/utils/music/chords';
import { stringifyFinaleJazzChordSigns } from '$/utils/music/font';
import { chordExtensionToFinaleJazzChordSignMap } from './chord-map';
export let extension: ChordExtension | undefined | null = undefined;
</script>

{#if extension !== undefined && extension !== null}{#if extension === '7, maj7'}{stringifyFinaleJazzChordSigns(
['7']
)}<span class="font-jazz align-super">,</span>{stringifyFinaleJazzChordSigns([
'Major',
'7'
])}{:else if extension === 'b6'}<span class="align-super ml-1"
>{stringifyFinaleJazzChordSigns(['Flat'])}</span
>{stringifyFinaleJazzChordSigns(['6'])}{:else}{stringifyFinaleJazzChordSigns(
chordExtensionToFinaleJazzChordSignMap[extension]
)}{/if}{/if}
11 changes: 11 additions & 0 deletions src/lib/notation/chord/ChordQualityNotation.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<script lang="ts">
import { type ChordQuality } from '$/utils/music/chords';
import { stringifyFinaleJazzChordSigns } from '$/utils/music/font';
import { chordQualityToFinaleJazzChordSignMap } from './chord-map';
export let quality: ChordQuality | undefined = undefined;
</script>

{#if quality !== undefined && quality !== 'major'}{stringifyFinaleJazzChordSigns([
chordQualityToFinaleJazzChordSignMap[quality]
])}{/if}
9 changes: 9 additions & 0 deletions src/lib/notation/chord/ChordRootNotation.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<script lang="ts">
import { type ChordRoot } from '$/utils/music/chords';
import { stringifyFinaleJazzChordSigns } from '$/utils/music/font';
import { chordRootToFinaleJazzChordSignMap } from './chord-map';
export let root: ChordRoot;
</script>

{stringifyFinaleJazzChordSigns(chordRootToFinaleJazzChordSignMap[root])}
19 changes: 19 additions & 0 deletions src/lib/notation/chord/ChordTensionNotation .svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
<script lang="ts">
import { stringifyFinaleJazzChordSigns } from '$/utils/music/font';
import { chordTensionToFinaleJazzChordSignMap } from './chord-map';
export let tensions: number[] = [];
</script>

{#if tensions.length > 0}{#if tensions.length === 1}<span class="align-[0.20em]">add</span
>{:else}<span class="mr-4 align-super">{stringifyFinaleJazzChordSigns(['('])}</span
>{/if}{#each tensions as tension, idx}{#if idx !== 0}<span class="mr-1 align-[0.20em] font-jazz"
>{','}</span
>{/if}{@const flat = tension === 13 || tension === 20}{@const sharp =
tension === 15 || tension === 18}{#if flat}<span class="align-super"
>{stringifyFinaleJazzChordSigns(['Flat'])}</span
>{/if}{#if sharp}<span class="align-super">{stringifyFinaleJazzChordSigns(['Sharp'])}</span
>{/if}{stringifyFinaleJazzChordSigns(
chordTensionToFinaleJazzChordSignMap[tension]
)}{/each}{#if tensions.length > 1}<span class="ml-2 align-super"
>{stringifyFinaleJazzChordSigns([')'])}</span
>{/if}{/if}
65 changes: 65 additions & 0 deletions src/lib/notation/chord/chord-map.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
import type { ChordRoot, ChordExtension, ChordQuality } from '$/utils/music/chords';
import type { finaleJazzChordCharacterMap } from '$/utils/music/font';

export const chordRootToFinaleJazzChordSignMap: Record<
ChordRoot,
(keyof typeof finaleJazzChordCharacterMap)[]
> = {
C: ['C'],
'C#': ['C', 'Sharp'],
Db: ['D', 'Flat'],
D: ['D'],
'D#': ['D', 'Sharp'],
Eb: ['E', 'Flat'],
E: ['E'],
F: ['F'],
'F#': ['F', 'Sharp'],
Gb: ['G', 'Flat'],
G: ['G'],
'G#': ['G', 'Sharp'],
Ab: ['A', 'Flat'],
A: ['A'],
'A#': ['A', 'Sharp'],
Bb: ['B', 'Flat'],
B: ['B']
};

export const chordExtensionToFinaleJazzChordSignMap: Record<
ChordExtension,
(keyof typeof finaleJazzChordCharacterMap)[]
> = {
'5': ['5'],
'6': ['6'],
'6/9': ['6/9'],
dim7: ['7'],
maj7: ['Major', '7'],
'7, maj7': ['7', 'Major', '7'],
'7': ['7'],
b6: ['Flat', '6']
};

export const chordQualityToFinaleJazzChordSignMap: Record<
ChordQuality,
keyof typeof finaleJazzChordCharacterMap
> = {
major: 'Major',
minor: 'Minor',
aug: 'Augmented',
dim: 'Diminished',
'half-dim': 'HalfDiminished',
sus2: 'SuspendedSecond',
sus4: 'SuspendedFourth'
};

export const chordTensionToFinaleJazzChordSignMap: Record<
number,
(keyof typeof finaleJazzChordCharacterMap)[]
> = {
13: ['9'],
14: ['9'],
15: ['9'],
17: ['11'],
18: ['11'],
20: ['13'],
21: ['13']
};
26 changes: 26 additions & 0 deletions src/routes/tools/chord-finder/+page.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
<script lang="ts">
import type { FingerInfo, FingerPosition } from '$/lib/guitar/finger-board/FingerBoard.svelte';
import Board from './Board.svelte';
let fingers: Record<number, FingerInfo> = {};
function updateFingerPosition(position: FingerPosition) {
if (fingers[position.line]?.position.fret === position.fret) {
delete fingers[position.line];
} else {
fingers[position.line] = { position };
}
fingers = fingers;
}
</script>

<div class="h-full w-screen">
<div class="relative flex h-full flex-col items-center">
<Board
fingers={Object.values(fingers)}
on:click={({ detail: { fret, line } }) => {
updateFingerPosition({ fret, line });
}}
></Board>
</div>
<!-- <MetronomeProvider><RandomBox {components} /></MetronomeProvider> -->
</div>
69 changes: 69 additions & 0 deletions src/routes/tools/chord-finder/Board.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
<script lang="ts">
import FingerBoard, { type FingerInfo } from '$/lib/guitar/finger-board/FingerBoard.svelte';
import { identifyChordsFromPitches } from '$/utils/music/chords';
import {
getPitchFromNumber,
getPitchesFromFingerPositions,
sortPitches
} from '$/utils/music/pitch';
import ChordNotation from '$lib/notation/ChordNotation.svelte';
export let fingers: FingerInfo[] = [];
$: pitches = sortPitches(getPitchesFromFingerPositions(fingers.map((finger) => finger.position)));
$: chords = identifyChordsFromPitches(pitches);
</script>

<div class="relative flex h-full flex-col items-center justify-center">
{#if chords != undefined}
{@const primaryChord = chords.chords.at(0)}
<div class="flex flex-col items-center gap-8 lg:flex-row lg:gap-28">
{#if primaryChord}
<div class="inline-block h-fit select-none text-center text-[80px] leading-[1.2em]">
<ChordNotation
root={getPitchFromNumber(primaryChord.symbols.root).note}
quality={primaryChord.symbols.quality}
extension={primaryChord.symbols.extension}
tensions={primaryChord.tones.tensions}
bass={getPitchFromNumber(chords.bass).note}
/>
</div>
{/if}
<div class="flex flex-col">
{#each chords.chords.slice(1) as chord, idx}
{#if idx === 0}
<div class="inline-block h-fit select-none text-center text-[60px] leading-[1.2em]">
<ChordNotation
root={getPitchFromNumber(chord.symbols.root).note}
quality={chord.symbols.quality}
extension={chord.symbols.extension}
tensions={chord.tones.tensions}
bass={getPitchFromNumber(chords.bass).note}
/>
</div>
{:else}
<div class="block h-fit select-none text-center text-[40px] leading-[1.2em]">
<ChordNotation
root={getPitchFromNumber(chord.symbols.root).note}
quality={chord.symbols.quality}
extension={chord.symbols.extension}
tensions={chord.tones.tensions}
bass={getPitchFromNumber(chords.bass).note}
/>
</div>
{/if}
{/each}
</div>
</div>
{/if}
</div>
<!-- <p>
{#each pitches as pitch}
<PitchNotation note={pitch.note} octave={pitch.octave}></PitchNotation>
{/each}
</p> -->
<FingerBoard
class="mb-28 w-screen lg:w-[calc(100vw-14rem)]"
{fingers}
fretRange={{ start: 0, end: 12, visibility: 'all' }}
on:click
/>
Loading

0 comments on commit ceff21c

Please sign in to comment.