36 lines
1.1 KiB
TypeScript
36 lines
1.1 KiB
TypeScript
import type { VibePreset } from '../vibes';
|
|
import type { GardenAudioChord, GardenAudioVibeProfile } from './garden-audio-config';
|
|
|
|
export const PITCH_SEMITONES_PER_OCTAVE = 12;
|
|
|
|
const chordVoicings = {
|
|
majorOpen: [0, 7, 12, 16],
|
|
minorOpen: [0, 7, 12, 15],
|
|
majorClosed: [0, 4, 7, 12, 16],
|
|
minorClosed: [0, 3, 7, 12, 15],
|
|
};
|
|
|
|
export const getVibeProfile = (vibe: VibePreset): GardenAudioVibeProfile => vibe.audio;
|
|
|
|
export const getChordIntervals = (
|
|
chord: GardenAudioChord,
|
|
openVoicing: boolean
|
|
): Array<number> => {
|
|
if (openVoicing) {
|
|
return chord.quality === 'major' ? chordVoicings.majorOpen : chordVoicings.minorOpen;
|
|
}
|
|
|
|
return chord.quality === 'major'
|
|
? chordVoicings.majorClosed
|
|
: chordVoicings.minorClosed;
|
|
};
|
|
|
|
export const degreeToSemitone = (
|
|
profile: GardenAudioVibeProfile,
|
|
degree: number
|
|
): number => {
|
|
const scaleIndex =
|
|
((degree % profile.scale.length) + profile.scale.length) % profile.scale.length;
|
|
const octave = Math.floor(degree / profile.scale.length);
|
|
return profile.scale[scaleIndex] + octave * PITCH_SEMITONES_PER_OCTAVE;
|
|
};
|