selcal/src/midi.h

27 lines
920 B
C++

#pragma once
#include <cmath>
#include <algorithm>
// Applicable for standard (even temperament) MIDI tuning only.
// The formula connecting the MIDI note number and the base frequency assume equal tuning based
// on A4 = 440 Hz.
constexpr int NUM_MIDI_KEYS = 128; // Also inclusive of 0 & 128, apparently.
constexpr double A4_FREQUENCY = 440.0; // Hz
constexpr int A4_MIDI_KEY = 69; // Hehe
constexpr int KEYS_PER_OCTAVE = 12;
// Template parameter allows for (non-standard) fractional keys.
template <typename T>
constexpr double MidiKeyToFrequency(T key) {
return A4_FREQUENCY * std::pow(2, (key - A4_MIDI_KEY) / KEYS_PER_OCTAVE);
}
constexpr double frequencyToMidiKey(double f) {
return ((KEYS_PER_OCTAVE * std::log2(f / A4_FREQUENCY)) + A4_MIDI_KEY);
}
constexpr int frequencyToNearestMidiKey(double f) {
return std::clamp(static_cast<int>(std::round(frequencyToMidiKey(f))), 0, NUM_MIDI_KEYS);
}