mirror of
https://github.com/9x/sheetmusictrainer.git
synced 2026-11-03 22:03:54 +01:00
antigravity one shot
This commit is contained in:
51
src/music/NoteUtils.ts
Normal file
51
src/music/NoteUtils.ts
Normal file
@@ -0,0 +1,51 @@
|
||||
|
||||
export const NOTE_NAMES = ["C", "C#", "D", "D#", "E", "F", "F#", "G", "G#", "A", "A#", "B"];
|
||||
export const A4 = 440;
|
||||
|
||||
export interface NoteDetail {
|
||||
midi: number;
|
||||
name: string;
|
||||
octave: number;
|
||||
scientific: string; // e.g., "C4"
|
||||
frequency: number;
|
||||
}
|
||||
|
||||
export function frequencyToMidi(frequency: number): number {
|
||||
if (frequency <= 0) return 0;
|
||||
return Math.round(69 + 12 * Math.log2(frequency / A4));
|
||||
}
|
||||
|
||||
export function midiToFrequency(midi: number): number {
|
||||
return A4 * Math.pow(2, (midi - 69) / 12);
|
||||
}
|
||||
|
||||
export function getNoteDetails(midi: number): NoteDetail {
|
||||
const semitone = midi % 12;
|
||||
const name = NOTE_NAMES[semitone];
|
||||
const octave = Math.floor(midi / 12) - 1; // MIDI 60 is C4
|
||||
return {
|
||||
midi,
|
||||
name,
|
||||
octave,
|
||||
scientific: `${name}${octave}`,
|
||||
frequency: midiToFrequency(midi)
|
||||
};
|
||||
}
|
||||
|
||||
export function getCentDifference(frequency: number, targetMidi: number): number {
|
||||
const targetFreq = midiToFrequency(targetMidi);
|
||||
if (frequency <= 0 || targetFreq <= 0) return 0;
|
||||
return 1200 * Math.log2(frequency / targetFreq);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a random MIDI note between min and max (inclusive)
|
||||
*/
|
||||
export function getRandomNote(min: number, max: number, validNotes?: number[]): number {
|
||||
if (validNotes && validNotes.length > 0) {
|
||||
const filtered = validNotes.filter(n => n >= min && n <= max);
|
||||
if (filtered.length === 0) return min; // Fallback
|
||||
return filtered[Math.floor(Math.random() * filtered.length)];
|
||||
}
|
||||
return Math.floor(Math.random() * (max - min + 1)) + min;
|
||||
}
|
||||
64
src/music/Tunings.ts
Normal file
64
src/music/Tunings.ts
Normal file
@@ -0,0 +1,64 @@
|
||||
|
||||
|
||||
export interface Tuning {
|
||||
name: string;
|
||||
strings: number[]; // MIDI numbers for strings, usually low to high (6th to 1st)
|
||||
}
|
||||
|
||||
// Low E2 (40), A2 (45), D3 (50), G3 (55), B3 (59), E4 (64)
|
||||
export const STANDARD_TUNING: Tuning = {
|
||||
name: "Standard",
|
||||
strings: [40, 45, 50, 55, 59, 64]
|
||||
};
|
||||
|
||||
// Low D2 (38), A2 (45), D3 (50), G3 (55), B3 (59), E4 (64)
|
||||
export const DROP_D_TUNING: Tuning = {
|
||||
name: "Drop D",
|
||||
strings: [38, 45, 50, 55, 59, 64]
|
||||
};
|
||||
|
||||
export const TUNINGS: Record<string, Tuning> = {
|
||||
"standard": STANDARD_TUNING,
|
||||
"drop_d": DROP_D_TUNING,
|
||||
};
|
||||
|
||||
export interface FretPosition {
|
||||
stringIndex: number; // 0-based index of the string in the strings array (0 = lowest string)
|
||||
fret: number;
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds all places on the fretboard where a specific note can be played.
|
||||
* Assumes 20 frets by default.
|
||||
*/
|
||||
export function getFretboardPositions(midiNote: number, tuning: Tuning = STANDARD_TUNING, maxFrets: number = 20): FretPosition[] {
|
||||
const positions: FretPosition[] = [];
|
||||
|
||||
tuning.strings.forEach((openNote, stringIndex) => {
|
||||
const fret = midiNote - openNote;
|
||||
if (fret >= 0 && fret <= maxFrets) {
|
||||
positions.push({ stringIndex, fret });
|
||||
}
|
||||
});
|
||||
|
||||
return positions;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Helpers to get useful ranges for beginners
|
||||
*/
|
||||
export function getOpenStringNotes(tuning: Tuning = STANDARD_TUNING): number[] {
|
||||
return tuning.strings;
|
||||
}
|
||||
|
||||
export function getFirstPositionNotes(tuning: Tuning = STANDARD_TUNING): number[] {
|
||||
const notes = new Set<number>();
|
||||
tuning.strings.forEach(openNote => {
|
||||
// First position usually means frets 0-4
|
||||
for (let i = 0; i <= 4; i++) {
|
||||
notes.add(openNote + i);
|
||||
}
|
||||
});
|
||||
return Array.from(notes).sort((a, b) => a - b);
|
||||
}
|
||||
Reference in New Issue
Block a user