From 8e4ddd19dad6b6dd19335dad3cab27008768ec87 Mon Sep 17 00:00:00 2001 From: TheoryOfNekomata Date: Sun, 2 Apr 2023 22:17:21 +0800 Subject: [PATCH] Fix half-diminished analysis Use lowered fifth notation for half-diminished analysis. --- package.json | 17 ++ src/analyze.ts | 56 ++++-- src/index.ts | 526 ++++++++++++++++++++++++------------------------- 3 files changed, 322 insertions(+), 277 deletions(-) diff --git a/package.json b/package.json index 3af2e21..4700310 100644 --- a/package.json +++ b/package.json @@ -45,5 +45,22 @@ "author": "TheoryOfNekomata ", "publishConfig": { "access": "public" + }, + "types": "./dist/types/index.d.ts", + "main": "./dist/cjs/production/index.js", + "module": "./dist/esm/production/index.js", + "exports": { + ".": { + "development": { + "require": "./dist/cjs/development/index.js", + "import": "./dist/esm/development/index.js" + }, + "require": "./dist/cjs/production/index.js", + "import": "./dist/esm/production/index.js", + "types": "./dist/types/index.d.ts" + } + }, + "typesVersions": { + "*": {} } } diff --git a/src/analyze.ts b/src/analyze.ts index b2c70a1..254ad82 100644 --- a/src/analyze.ts +++ b/src/analyze.ts @@ -125,12 +125,13 @@ const getChordSeventh = ( normalizedIntervals: Interval[], priorAnalysis: ChordAnalysis, ) => { - const { extensions: priorExtensions = [] } = priorAnalysis; + const { extensions: priorExtensions = [], base: oldBase, modifications = [] } = priorAnalysis; const { + [CHORD_COMPONENT_ORDERS.indexOf(ChordComponent.THIRD)]: third, [CHORD_COMPONENT_ORDERS.indexOf(ChordComponent.SIXTH)]: sixth, [CHORD_COMPONENT_ORDERS.indexOf(ChordComponent.SEVENTH)]: seventh, } = normalizedIntervals; - if (priorAnalysis.base === ChordBase.DIMINISHED && sixth === Interval.DIMINISHED_SEVENTH) { + if (oldBase === ChordBase.DIMINISHED && sixth === Interval.DIMINISHED_SEVENTH) { return { ...priorAnalysis, extensions: [...priorExtensions, { @@ -140,25 +141,52 @@ const getChordSeventh = ( }; } - switch (seventh) { - case Interval.MAJOR_SEVENTH: - return { - ...priorAnalysis, - extensions: [...priorExtensions, { - type: ChordExtensionType.MAJOR, - component: ChordComponent.SEVENTH, - }], - }; - case Interval.MINOR_SEVENTH: + if (seventh === Interval.MINOR_SEVENTH) { + let newBase: ChordBase | undefined; + if (third === Interval.MINOR_THIRD) { + newBase = ChordBase.MINOR; + } else if (third === Interval.MAJOR_THIRD) { + newBase = ChordBase.MAJOR; + } else { + newBase = oldBase; + } + + if (oldBase === ChordBase.DIMINISHED) { return { ...priorAnalysis, + base: newBase, extensions: [...priorExtensions, { type: ChordExtensionType.DOMINANT, component: ChordComponent.SEVENTH, }], + modifications: [ + ...modifications, + { + type: ChordModificationType.LOWERED, + component: ChordComponent.FIFTH, + }, + ], }; - default: - break; + } + + return { + ...priorAnalysis, + base: newBase, + extensions: [...priorExtensions, { + type: ChordExtensionType.DOMINANT, + component: ChordComponent.SEVENTH, + }], + }; + } + + if (seventh === Interval.MAJOR_SEVENTH) { + return { + ...priorAnalysis, + extensions: [...priorExtensions, { + type: ChordExtensionType.MAJOR, + component: ChordComponent.SEVENTH, + }], + }; } return priorAnalysis; diff --git a/src/index.ts b/src/index.ts index bdc54b0..7d602f2 100644 --- a/src/index.ts +++ b/src/index.ts @@ -9,266 +9,266 @@ export * from './analyze'; export * from './common'; export * from './utils'; - -const CHORD_DICTIONARY = [ - { - name: 'Augmented', - symbol: 'aug', - id: 'aug', - notes: [0, 4, 8], - }, - { - name: 'Augmented eleventh', - symbol: '(♯11)', - id: '(#11)', - notes: [0, 4, 7, 10, 14, 18], - }, - { - name: 'Augmented major seventh', - symbol: 'augmaj7', - id: 'augmaj7', - notes: [0, 4, 8, 11], - }, - { - name: 'Augmented seventh', - symbol: 'aug7', - id: 'aug7', - notes: [0, 4, 8, 10], - }, - { - name: 'Diminished', - symbol: 'dim', - id: 'dim', - notes: [0, 3, 6], - }, - { - name: 'Diminished major seventh', - symbol: 'dimmaj7', - id: 'dimmaj7', - notes: [0, 3, 6, 11], - }, - { - name: 'Diminished seventh', - symbol: 'dim7', - id: 'dim7', - notes: [0, 3, 6, 9], - }, - { - name: 'Dominant eleventh', - symbol: '11', - id: '11', - notes: [0, 4, 7, 10, 14, 17], - }, - { - name: 'Dominant minor ninth', - symbol: '7♭9', - notes: [0, 4, 7, 10, 13], - }, - { - name: 'Dominant ninth', - symbol: '9', - notes: [0, 4, 7, 10, 14], - }, - { - name: 'Dominant seventh', - symbol: '7', - notes: [0, 4, 7, 10], - }, - { - name: 'Dominant seventh flat five', - symbol: '7♭5', - notes: [0, 4, 6, 10], - }, - { - name: 'Dominant seventh sharp nine', - symbol: '(♯9)', - notes: [0, 4, 7, 10, 15], - }, - { name: 'Dominant thirteenth', symbol: '13', notes: [0, 4, 7, 10, 14, 17, 21] }, - { name: 'Half-diminished seventh', symbol: 'm7(♭5)', notes: [0, 3, 6, 10] }, - { - name: 'Major', - symbol: '', - id: '', - notes: [0, 4, 7], - }, - { name: 'Major eleventh', symbol: 'maj11', notes: [0, 4, 7, 11, 14, 17] }, - { - name: 'Major seventh', - symbol: 'maj7', - notes: [0, 4, 7, 11], - }, - { name: 'Major seventh sharp eleventh', symbol: 'maj7♯11', notes: [0, 4, 8, 11, 18] }, - { - name: 'Major sixth', - symbol: '6', - notes: [0, 4, 7, 9], - }, - { - name: 'Major sixth ninth', - symbol: '6(9)', - notes: [0, 4, 7, 9, 14], - }, - { name: 'Major ninth', symbol: 'maj9', notes: [0, 4, 7, 11, 14] }, - { - name: 'Major thirteenth', - symbol: 'maj13', - notes: [0, 4, 7, 11, 14, 18, 21], - }, - { - name: 'Minor', - symbol: 'm', - notes: [0, 3, 7], - }, - { name: 'Minor eleventh', symbol: 'm11', notes: [0, 3, 7, 10, 14, 17] }, - { - name: 'Minor major seventh', - symbol: 'mmaj7', - notes: [0, 3, 7, 11], - }, - { name: 'Minor ninth', symbol: 'm9', notes: [0, 3, 7, 10, 14] }, - { - name: 'Minor seventh', - symbol: 'm7', - notes: [0, 3, 7, 10], - }, - { name: 'Minor sixth', symbol: 'm6', notes: [0, 3, 7, 9] }, - { - name: 'Minor sixth ninth (6/9)', - symbol: 'm6(9)', - notes: [0, 3, 7, 9, 14], - }, - { name: 'Minor thirteenth', symbol: 'm13', notes: [0, 3, 7, 10, 14, 17, 21] }, - { - name: 'Ninth augmented fifth', - symbol: '9♯5', - notes: [0, 4, 8, 10, 14], - }, - { name: 'Ninth flat fifth', notes: [0, 4, 6, 10, 14], symbol: '9♭5' }, - { - name: 'Seven six', - symbol: '7(6)', - notes: [0, 4, 7, 9, 10], - }, - { name: 'Seventh suspension four', symbol: '7sus4', notes: [0, 5, 7, 10] }, - { - name: 'Suspended fourth', - symbol: 'sus4', - notes: [0, 5, 7], - }, - { - name: 'Suspended second', - symbol: 'sus2', - notes: [0, 2, 7], - }, - { - name: 'Thirteenth flat ninth', - symbol: '13♭9', - notes: [0, 4, 7, 10, 13, 21], - }, - { - name: 'Thirteenth flat ninth flat fifth', - symbol: '13♭9(♭5)', - notes: [0, 4, 6, 10, 13, 21], - }, -]; - -export enum ConstructChordFormat { - PITCH_ARRAY, - NOTATION, - SOUND, -} - -enum NotationType { - STANDARD, - TABLATURE, -} - -interface ConstructChordOptions { - format?: ConstructChordFormat; -} - -enum ConstructChordStyle { - CHORD = 'CHORD', - ARPEGGIO = 'ARPEGGIO', - ARPEGGIO_THEN_CHORD = 'ARPEGGIO_THEN_CHORD', - CHORD_THEN_ARPEGGIO = 'CHORD_THEN_ARPEGGIO', -} - -interface ConstructChordSoundOptions extends ConstructChordOptions { - format?: ConstructChordFormat.SOUND; - midiInstrument?: number; - style?: ConstructChordStyle; - mimeType?: string; -} - -interface ConstructChordNotationOptions extends ConstructChordOptions { - format?: ConstructChordFormat.NOTATION; - notationType?: NotationType; - mimeType?: string; -} - -export enum PitchClass { - C, - B_SHARP = C, - C_SHARP, - D_FLAT = C_SHARP, - D, - D_SHARP, - E_FLAT = D_SHARP, - E, - F_FLAT = E, - F, - E_SHARP = F, - F_SHARP, - G_FLAT = F_SHARP, - G, - G_SHARP, - A_FLAT = G_SHARP, - A, - A_SHARP, - B_FLAT = A_SHARP, - B, - C_FLAT = B, -} - -interface ChordParams { - pitchClass: PitchClass; - chord?: string; - inversion?: number; -} - -const constructChordPitchArray = (params: ChordParams) => { - const { pitchClass, chord = '', inversion = 0 } = params; - const chordDefinition = CHORD_DICTIONARY.find((c) => c.id === chord); - if (!chordDefinition) { - throw new Error(`Chord ${chord} not found`); - } - const { notes } = chordDefinition; - const pitchArray = notes.map((note) => note + pitchClass); - return pitchArray; -}; - -const constructChordNotation = (params: ChordParams, options: ConstructChordNotationOptions) => { - return constructChordPitchArray(params); -}; - -const constructChordSound = (params: ChordParams, options: ConstructChordSoundOptions) => { - return constructChordPitchArray(params); -}; - -export const constructChord = (params: ChordParams, options = {} as ConstructChordOptions) => { - const { format = ConstructChordFormat.PITCH_ARRAY } = options; - switch (format) { - case ConstructChordFormat.PITCH_ARRAY: - return constructChordPitchArray(params); - case ConstructChordFormat.NOTATION: - return constructChordNotation(params, options as ConstructChordNotationOptions); - case ConstructChordFormat.SOUND: - return constructChordSound(params, options as ConstructChordSoundOptions); - default: - break; - } - - throw new TypeError(`Unknown format ${format as string}`); -}; +// +// const CHORD_DICTIONARY = [ +// { +// name: 'Augmented', +// symbol: 'aug', +// id: 'aug', +// notes: [0, 4, 8], +// }, +// { +// name: 'Augmented eleventh', +// symbol: '(♯11)', +// id: '(#11)', +// notes: [0, 4, 7, 10, 14, 18], +// }, +// { +// name: 'Augmented major seventh', +// symbol: 'augmaj7', +// id: 'augmaj7', +// notes: [0, 4, 8, 11], +// }, +// { +// name: 'Augmented seventh', +// symbol: 'aug7', +// id: 'aug7', +// notes: [0, 4, 8, 10], +// }, +// { +// name: 'Diminished', +// symbol: 'dim', +// id: 'dim', +// notes: [0, 3, 6], +// }, +// { +// name: 'Diminished major seventh', +// symbol: 'dimmaj7', +// id: 'dimmaj7', +// notes: [0, 3, 6, 11], +// }, +// { +// name: 'Diminished seventh', +// symbol: 'dim7', +// id: 'dim7', +// notes: [0, 3, 6, 9], +// }, +// { +// name: 'Dominant eleventh', +// symbol: '11', +// id: '11', +// notes: [0, 4, 7, 10, 14, 17], +// }, +// { +// name: 'Dominant minor ninth', +// symbol: '7♭9', +// notes: [0, 4, 7, 10, 13], +// }, +// { +// name: 'Dominant ninth', +// symbol: '9', +// notes: [0, 4, 7, 10, 14], +// }, +// { +// name: 'Dominant seventh', +// symbol: '7', +// notes: [0, 4, 7, 10], +// }, +// { +// name: 'Dominant seventh flat five', +// symbol: '7♭5', +// notes: [0, 4, 6, 10], +// }, +// { +// name: 'Dominant seventh sharp nine', +// symbol: '(♯9)', +// notes: [0, 4, 7, 10, 15], +// }, +// { name: 'Dominant thirteenth', symbol: '13', notes: [0, 4, 7, 10, 14, 17, 21] }, +// { name: 'Half-diminished seventh', symbol: 'm7(♭5)', notes: [0, 3, 6, 10] }, +// { +// name: 'Major', +// symbol: '', +// id: '', +// notes: [0, 4, 7], +// }, +// { name: 'Major eleventh', symbol: 'maj11', notes: [0, 4, 7, 11, 14, 17] }, +// { +// name: 'Major seventh', +// symbol: 'maj7', +// notes: [0, 4, 7, 11], +// }, +// { name: 'Major seventh sharp eleventh', symbol: 'maj7♯11', notes: [0, 4, 8, 11, 18] }, +// { +// name: 'Major sixth', +// symbol: '6', +// notes: [0, 4, 7, 9], +// }, +// { +// name: 'Major sixth ninth', +// symbol: '6(9)', +// notes: [0, 4, 7, 9, 14], +// }, +// { name: 'Major ninth', symbol: 'maj9', notes: [0, 4, 7, 11, 14] }, +// { +// name: 'Major thirteenth', +// symbol: 'maj13', +// notes: [0, 4, 7, 11, 14, 18, 21], +// }, +// { +// name: 'Minor', +// symbol: 'm', +// notes: [0, 3, 7], +// }, +// { name: 'Minor eleventh', symbol: 'm11', notes: [0, 3, 7, 10, 14, 17] }, +// { +// name: 'Minor major seventh', +// symbol: 'mmaj7', +// notes: [0, 3, 7, 11], +// }, +// { name: 'Minor ninth', symbol: 'm9', notes: [0, 3, 7, 10, 14] }, +// { +// name: 'Minor seventh', +// symbol: 'm7', +// notes: [0, 3, 7, 10], +// }, +// { name: 'Minor sixth', symbol: 'm6', notes: [0, 3, 7, 9] }, +// { +// name: 'Minor sixth ninth (6/9)', +// symbol: 'm6(9)', +// notes: [0, 3, 7, 9, 14], +// }, +// { name: 'Minor thirteenth', symbol: 'm13', notes: [0, 3, 7, 10, 14, 17, 21] }, +// { +// name: 'Ninth augmented fifth', +// symbol: '9♯5', +// notes: [0, 4, 8, 10, 14], +// }, +// { name: 'Ninth flat fifth', notes: [0, 4, 6, 10, 14], symbol: '9♭5' }, +// { +// name: 'Seven six', +// symbol: '7(6)', +// notes: [0, 4, 7, 9, 10], +// }, +// { name: 'Seventh suspension four', symbol: '7sus4', notes: [0, 5, 7, 10] }, +// { +// name: 'Suspended fourth', +// symbol: 'sus4', +// notes: [0, 5, 7], +// }, +// { +// name: 'Suspended second', +// symbol: 'sus2', +// notes: [0, 2, 7], +// }, +// { +// name: 'Thirteenth flat ninth', +// symbol: '13♭9', +// notes: [0, 4, 7, 10, 13, 21], +// }, +// { +// name: 'Thirteenth flat ninth flat fifth', +// symbol: '13♭9(♭5)', +// notes: [0, 4, 6, 10, 13, 21], +// }, +// ]; +// +// export enum ConstructChordFormat { +// PITCH_ARRAY, +// NOTATION, +// SOUND, +// } +// +// enum NotationType { +// STANDARD, +// TABLATURE, +// } +// +// interface ConstructChordOptions { +// format?: ConstructChordFormat; +// } +// +// enum ConstructChordStyle { +// CHORD = 'CHORD', +// ARPEGGIO = 'ARPEGGIO', +// ARPEGGIO_THEN_CHORD = 'ARPEGGIO_THEN_CHORD', +// CHORD_THEN_ARPEGGIO = 'CHORD_THEN_ARPEGGIO', +// } +// +// interface ConstructChordSoundOptions extends ConstructChordOptions { +// format?: ConstructChordFormat.SOUND; +// midiInstrument?: number; +// style?: ConstructChordStyle; +// mimeType?: string; +// } +// +// interface ConstructChordNotationOptions extends ConstructChordOptions { +// format?: ConstructChordFormat.NOTATION; +// notationType?: NotationType; +// mimeType?: string; +// } +// +// export enum PitchClass { +// C, +// B_SHARP = C, +// C_SHARP, +// D_FLAT = C_SHARP, +// D, +// D_SHARP, +// E_FLAT = D_SHARP, +// E, +// F_FLAT = E, +// F, +// E_SHARP = F, +// F_SHARP, +// G_FLAT = F_SHARP, +// G, +// G_SHARP, +// A_FLAT = G_SHARP, +// A, +// A_SHARP, +// B_FLAT = A_SHARP, +// B, +// C_FLAT = B, +// } +// +// interface ChordParams { +// pitchClass: PitchClass; +// chord?: string; +// inversion?: number; +// } +// +// const constructChordPitchArray = (params: ChordParams) => { +// const { pitchClass, chord = '', inversion = 0 } = params; +// const chordDefinition = CHORD_DICTIONARY.find((c) => c.id === chord); +// if (!chordDefinition) { +// throw new Error(`Chord ${chord} not found`); +// } +// const { notes } = chordDefinition; +// const pitchArray = notes.map((note) => note + pitchClass); +// return pitchArray; +// }; +// +// const constructChordNotation = (params: ChordParams, options: ConstructChordNotationOptions) => { +// return constructChordPitchArray(params); +// }; +// +// const constructChordSound = (params: ChordParams, options: ConstructChordSoundOptions) => { +// return constructChordPitchArray(params); +// }; +// +// export const constructChord = (params: ChordParams, options = {} as ConstructChordOptions) => { +// const { format = ConstructChordFormat.PITCH_ARRAY } = options; +// switch (format) { +// case ConstructChordFormat.PITCH_ARRAY: +// return constructChordPitchArray(params); +// case ConstructChordFormat.NOTATION: +// return constructChordNotation(params, options as ConstructChordNotationOptions); +// case ConstructChordFormat.SOUND: +// return constructChordSound(params, options as ConstructChordSoundOptions); +// default: +// break; +// } +// +// throw new TypeError(`Unknown format ${format as string}`); +// };