Skip to content

Commit

Permalink
Merge pull request #14 from kilmc/rework-system
Browse files Browse the repository at this point in the history
[Improvement] Rework system
  • Loading branch information
kilmc authored Sep 21, 2023
2 parents fabf4ee + 4b8e1ee commit d50cc6b
Show file tree
Hide file tree
Showing 53 changed files with 2,324 additions and 717 deletions.
5 changes: 5 additions & 0 deletions .changeset/silly-tips-shop.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@kilmc/music-fns": minor
---

Improve system to improve accuracy
18 changes: 18 additions & 0 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,24 @@ jobs:
pnpm install
- name: Run Tests
run: pnpm run test
build:
name: Build
runs-on: ubuntu-latest
steps:
- name: Checkout Code
uses: actions/checkout@v3

- name: Use Node.js
uses: actions/setup-node@v3
with:
node-version: '18.x'

- name: Install Dependencies
run: |
npm install -g pnpm
pnpm install
- name: Run Tests
run: pnpm run build
release:
needs: test
name: Release
Expand Down
100 changes: 54 additions & 46 deletions src/chords/determineChordInfo.ts
Original file line number Diff line number Diff line change
@@ -1,68 +1,76 @@
import { numberTypeChordMap } from '../consts';
import type { IChordInfo, TChordQuality, TChordType, TSusType } from '../types';
import { chordRegexp, isAddType } from './helpers';
import { numberTypeChordMap } from '../consts.js';
import { determineNoteType } from '../notes/determineNoteType.js';
import type {
ChordInfo,
AddType,
ChordQuality,
ChordType,
SusType,
} from '../types.js';
import { chordRegexp, isAddType } from './helpers.js';

const determineAlteredNotes = (alteredNotes?: string) => {
return alteredNotes === undefined
? undefined
: (alteredNotes.match(/(#|b)(?:5|7|9|11|13)/g) as string[]);
return alteredNotes === undefined
? undefined
: (alteredNotes.match(/(#|b)(?:5|7|9|11|13)/g) as string[]);
};

const determineChordQuality = (quality?: string): TChordQuality => {
if (quality === undefined || ['Δ', 'M', 'maj'].includes(quality)) {
return 'major';
}
const determineChordQuality = (quality?: string): ChordQuality => {
if (quality === undefined || ['Δ', 'M', 'maj'].includes(quality)) {
return 'major';
}

if (quality === 'm') {
return 'minor';
}
if (quality === 'm') {
return 'minor';
}

if (['dim', 'o'].includes(quality)) {
return 'diminished';
}
if (['dim', 'o'].includes(quality)) {
return 'diminished';
}

if (['ø'].includes(quality)) {
return 'half-diminished';
}
if (['ø'].includes(quality)) {
return 'half-diminished';
}

if (['aug', '+'].includes(quality)) {
return 'augmented';
}
if (['aug', '+'].includes(quality)) {
return 'augmented';
}

return 'major';
return 'major';
};

const determindChordType = (type?: string): TChordType => {
return type === undefined ? 'triad' : numberTypeChordMap[type];
const determindChordType = (type?: string): ChordType => {
return type === undefined ? 'triad' : numberTypeChordMap[type];
};

const determineAdd = (add?: string) => {
return add && isAddType(add) ? add : undefined;
const determineAdd = (add?: string): AddType | undefined => {
return add && isAddType(add) ? add : undefined;
};

const determineSus = (sus?: string): TSusType | undefined => {
if (sus === undefined) return undefined;
if (['sus', 'sus4', 'sus9'].includes(sus)) return 'sus4';
if (sus === 'sus2') return 'sus2';
return undefined;
const determineSus = (sus?: string): SusType | undefined => {
if (sus === undefined) return undefined;
if (['sus', 'sus4', 'sus9'].includes(sus)) return 'sus4';
if (sus === 'sus2') return 'sus2';
return undefined;
};

const determineSlashChord = (slashNote?: string) => {
return slashNote?.replace('/', '');
return slashNote?.replace('/', '');
};

export const determineChord = (name: string): IChordInfo => {
const [note, quality, type, altered, add, sus, slashNote] =
name.match(chordRegexp)?.slice(1) || [];
export const determineChord = (name: string): ChordInfo => {
const [note, quality, type, altered, add, sus, slashNote] =
name.match(chordRegexp)?.slice(1) || [];

return {
name,
note,
quality: determineChordQuality(quality),
type: determindChordType(type),
alteredNotes: determineAlteredNotes(altered),
addType: determineAdd(add),
susType: determineSus(sus),
slashNote: determineSlashChord(slashNote)
};
return {
name,
note,
quality: determineChordQuality(quality),
type: determindChordType(type),
alteredNotes: determineAlteredNotes(altered),
addType: determineAdd(add),
susType: determineSus(sus),
slashNote: determineSlashChord(slashNote),
pitchClassType: determineNoteType(name),
};
};
125 changes: 64 additions & 61 deletions src/chords/getChord.test.ts
Original file line number Diff line number Diff line change
@@ -1,72 +1,75 @@
import { describe, expect, it } from 'vitest';
import { getChord } from './getChord';
import { getChord } from './getChord.js';

describe('getChord', () => {
it('supports major chords', () => {
expect(getChord('C').notes).toEqual(['C', 'E', 'G']);
expect(getChord('Eb').notes).toEqual(['Eb', 'G', 'Bb']);
});
it('supports major chords', () => {
expect(getChord('C').notes).toEqual(['C', 'E', 'G']);
expect(getChord('Eb').notes).toEqual(['Eb', 'G', 'Bb']);
});

it('supports minor chords', () => {
expect(getChord('Am').notes).toEqual(['A', 'C', 'E']);
expect(getChord('D#m').notes).toEqual(['D#', 'F#', 'A#']);
});
it('supports minor chords', () => {
expect(getChord('Am').notes).toEqual(['A', 'C', 'E']);
expect(getChord('D#m').notes).toEqual(['D#', 'F#', 'A#']);
});

it('supports augmented chords', () => {
expect(getChord('Caug').notes).toEqual(['C', 'E', 'G#']);
expect(getChord('C#aug').notes).toEqual(['C#', 'F', 'A']);
expect(getChord('Bbaug').notes).toEqual(['Bb', 'D', 'F#']);
expect(getChord('Aaug7').notes).toEqual(['A', 'Db', 'F', 'G']);
});
it('supports augmented chords', () => {
expect(getChord('Caug').notes).toEqual(['C', 'E', 'G#']);
expect(getChord('C#aug').notes).toEqual(['C#', 'F', 'A']);
expect(getChord('Bbaug').notes).toEqual(['Bb', 'D', 'F#']);
expect(getChord('Aaug7').notes).toEqual(['A', 'Db', 'F', 'G']);
});

it('supports diminished chords', () => {
expect(getChord('Cdim').notes).toEqual(['C', 'Eb', 'Gb']);
expect(getChord('C#dim').notes).toEqual(['C#', 'E', 'G']);
expect(getChord('Dbdim').notes).toEqual(['Db', 'E', 'G']);
expect(getChord('Ddim').notes).toEqual(['D', 'F', 'Ab']);
expect(getChord('D#dim').notes).toEqual(['D#', 'F#', 'A']);
expect(getChord('Ebdim').notes).toEqual(['Eb', 'Gb', 'A']);
expect(getChord('Edim').notes).toEqual(['E', 'G', 'Bb']);
expect(getChord('Fdim').notes).toEqual(['F', 'Ab', 'B']);
expect(getChord('F#dim').notes).toEqual(['F#', 'A', 'C']);
expect(getChord('Gbdim').notes).toEqual(['Gb', 'A', 'C']);
expect(getChord('Gdim').notes).toEqual(['G', 'Bb', 'Db']);
expect(getChord('G#dim').notes).toEqual(['G#', 'B', 'D']);
expect(getChord('Abdim').notes).toEqual(['Ab', 'B', 'D']);
expect(getChord('Adim').notes).toEqual(['A', 'C', 'Eb']);
expect(getChord('A#dim').notes).toEqual(['A#', 'C#', 'E']);
expect(getChord('Bbdim').notes).toEqual(['Bb', 'Db', 'E']);
expect(getChord('Bdim').notes).toEqual(['B', 'D', 'F']);
});
it('supports diminished chords', () => {
expect(getChord('Cdim').notes).toEqual(['C', 'Eb', 'Gb']);
expect(getChord('C#dim').notes).toEqual(['C#', 'E', 'G']);
expect(getChord('Dbdim').notes).toEqual(['Db', 'E', 'G']);
expect(getChord('Ddim').notes).toEqual(['D', 'F', 'Ab']);
expect(getChord('D#dim').notes).toEqual(['D#', 'F#', 'A']);
expect(getChord('Ebdim').notes).toEqual(['Eb', 'Gb', 'A']);
expect(getChord('Edim').notes).toEqual(['E', 'G', 'Bb']);
expect(getChord('Fdim').notes).toEqual(['F', 'Ab', 'B']);
expect(getChord('F#dim').notes).toEqual(['F#', 'A', 'C']);
expect(getChord('Gbdim').notes).toEqual(['Gb', 'A', 'C']);
expect(getChord('Gdim').notes).toEqual(['G', 'Bb', 'Db']);
expect(getChord('G#dim').notes).toEqual(['G#', 'B', 'D']);
expect(getChord('Abdim').notes).toEqual(['Ab', 'B', 'D']);
expect(getChord('Adim').notes).toEqual(['A', 'C', 'Eb']);
expect(getChord('A#dim').notes).toEqual(['A#', 'C#', 'E']);
expect(getChord('Bbdim').notes).toEqual(['Bb', 'Db', 'E']);
expect(getChord('Bdim').notes).toEqual(['B', 'D', 'F']);
});

it('supports modified notes', () => {
expect(getChord('C7b5').notes).toEqual(['C', 'E', 'Gb', 'Bb']);
expect(getChord('C7#5').notes).toEqual(['C', 'E', 'G#', 'Bb']);
expect(getChord('Cm7#5').notes).toEqual(['C', 'Eb', 'G#', 'Bb']);
expect(getChord('C7b9').notes).toEqual(['C', 'E', 'G', 'Bb', 'Db']);
expect(getChord('C7#9').notes).toEqual(['C', 'E', 'G', 'Bb', 'D#']);
expect(getChord('C7b5b9').notes).toEqual(['C', 'E', 'Gb', 'Bb', 'Db']);
expect(getChord('C7#5#9').notes).toEqual(['C', 'E', 'G#', 'Bb', 'D#']);
expect(getChord('C7b5#9').notes).toEqual(['C', 'E', 'Gb', 'Bb', 'D#']);
expect(getChord('C7#5b9').notes).toEqual(['C', 'E', 'G#', 'Bb', 'Db']);
});
it('supports modified notes', () => {
expect(getChord('C7b5').notes).toEqual(['C', 'E', 'Gb', 'Bb']);
expect(getChord('C7#5').notes).toEqual(['C', 'E', 'G#', 'Bb']);
expect(getChord('Cm7#5').notes).toEqual(['C', 'Eb', 'G#', 'Bb']);
expect(getChord('C7b9').notes).toEqual(['C', 'E', 'G', 'Bb', 'Db']);
expect(getChord('C7#9').notes).toEqual(['C', 'E', 'G', 'Bb', 'D#']);
expect(getChord('C7b5b9').notes).toEqual(['C', 'E', 'Gb', 'Bb', 'Db']);
expect(getChord('C7#5#9').notes).toEqual(['C', 'E', 'G#', 'Bb', 'D#']);
expect(getChord('C7b5#9').notes).toEqual(['C', 'E', 'Gb', 'Bb', 'D#']);
expect(getChord('C7#5b9').notes).toEqual(['C', 'E', 'G#', 'Bb', 'Db']);
});

it('supports add chords', () => {
expect(getChord('Cadd2').notes).toEqual(['C', 'D', 'E', 'G']);
expect(getChord('Cadd4').notes).toEqual(['C', 'E', 'F', 'G']);
expect(getChord('Cadd9').notes).toEqual(['C', 'E', 'G', 'D']);
expect(getChord('Cadd11').notes).toEqual(['C', 'E', 'G', 'F']);
expect(getChord('Cadd13').notes).toEqual(['C', 'E', 'G', 'A']);
});
it('supports add chords', () => {
expect(getChord('Cadd2').notes).toEqual(['C', 'D', 'E', 'G']);
expect(getChord('Cadd4').notes).toEqual(['C', 'E', 'F', 'G']);
expect(getChord('Cadd9').notes).toEqual(['C', 'E', 'G', 'D']);
expect(getChord('Cadd11').notes).toEqual(['C', 'E', 'G', 'F']);
expect(getChord('Cadd13').notes).toEqual(['C', 'E', 'G', 'A']);
});

it('supports slash chords (chord inversions)', () => {
expect(getChord('C/E').notes).toEqual(['E', 'G', 'C']);
expect(getChord('C/G').notes).toEqual(['G', 'C', 'E']);
expect(getChord('Eb/G').notes).toEqual(['G', 'Bb', 'Eb']);
expect(getChord('Eb/Bb').notes).toEqual(['Bb', 'Eb', 'G']);
});
it('supports slash chords (chord inversions)', () => {
expect(getChord('C/E').notes).toEqual(['E', 'G', 'C']);
expect(getChord('C/G').notes).toEqual(['G', 'C', 'E']);
expect(getChord('Eb/G').notes).toEqual(['G', 'Bb', 'Eb']);
expect(getChord('Eb/Bb').notes).toEqual(['Bb', 'Eb', 'G']);
});

// it('supports weird chords', () => {
// expect(getChord('Cø7').notes).toEqual(['C', 'Eb', 'Gb', 'Bb']);
// });
// it('supports weird chords', () => {
// expect(getChord('Cø7').notes).toEqual(['C', 'Eb', 'Gb', 'Bb']);
// });
// it('supports constraining to the notes in a scale', () => {

// })
});
Loading

0 comments on commit d50cc6b

Please sign in to comment.