src/utilities/ScientificFunctions.ts
import { Note, PitchClass, RawFlatPitchClass } from 'types';
import { FLAT_CLASS_NOTES, NUMBER_OF_PITCH_CLASSES, PITCH_STANDARD, SEMITONE } from '../Constants.js';
import { getPitchClassIndex, noteToObject } from './PureMusicUtils.js';
/**
* Calculate the frequency of a note by its octave and index out of all notes(c, c#, etc...).
* @param {String} note
* @returns {Number}
*/
export function freqFromPitch(note: Note): number {
const { pitchClass, octave } = noteToObject(note);
const oct = octave - PITCH_STANDARD.octave; // calculate octave difference
const pitchClassIndex = getPitchClassIndex(pitchClass as PitchClass);
return Math.pow(
SEMITONE,
pitchClassIndex - FLAT_CLASS_NOTES.indexOf(PITCH_STANDARD.pitchClass as RawFlatPitchClass) + oct * NUMBER_OF_PITCH_CLASSES,
) * PITCH_STANDARD.frequency;
}
export function freqToPitch(frequency: number): Note {
const midi = freqToMidi(frequency);
const pitchClass = midi % NUMBER_OF_PITCH_CLASSES;
const octave = Math.floor(midi / NUMBER_OF_PITCH_CLASSES) - 1;
const note = `${FLAT_CLASS_NOTES[pitchClass]}${octave}`;
return note as Note;
}
/**
* Turns a midi value to frequency.
* @param {Number} midi
* @returns {number}
*/
export function freqFromMidi(midi: number): number {
return PITCH_STANDARD.frequency * Math.pow(2, (midi - PITCH_STANDARD.midi) / NUMBER_OF_PITCH_CLASSES);
}
/**
* Turns a frequency value to midi note.
* @param frequency
* @returns {number}
*/
export function freqToFloatMidi(frequency: number): number {
return PITCH_STANDARD.midi + NUMBER_OF_PITCH_CLASSES * Math.log2(frequency / PITCH_STANDARD.frequency);
}
/**
* Turns frequency value to a ABSOLUTE midi note.
* @param {Number} frequency
* @returns {number}
*/
export function freqToMidi(frequency: number): number {
return Math.round(freqToFloatMidi(frequency));
}
/**
* Returns how much cents off a frequency is from an absolute note.
* @param {Number} frequency
* @param {Number} midi
* @returns {number}
*/
export function centsOffFromFreq(frequency: number, midi: number): number {
return Math.floor(1200 * Math.log(frequency / freqFromMidi(midi)) / Math.log(2));
}
/**
* Generate frequency from real number.
* @param realNumber
* @returns {Number}
*/
export function midiToFreq(realNumber: number): number {
return PITCH_STANDARD.frequency * (Math.pow(2, (realNumber - PITCH_STANDARD.midi) / NUMBER_OF_PITCH_CLASSES));
}
/**
* Convert MIDI value to pitch.
* @param {Number} midi
* @returns {Note}
*/
export function midiToPitch(midi: number): Note {
const freq = freqFromMidi(midi);
return freqToPitch(freq);
}
/**
* Convert pitch to MIDI value.
* @param {Note} pitch
* @returns {number}
*/
export function pitchToMidi(note: Note): number {
const freq = freqFromPitch(note);
return freqToMidi(freq);
}