MCC
Loading...
Searching...
No Matches
EqualTemperament.h
1#ifndef MCC_TUNING_EQUAL_TEMPERAMENT_H
2#define MCC_TUNING_EQUAL_TEMPERAMENT_H
3
4#include <MCC_BuildSettings.h>
5
6#include <float.h>
7#include <stdint.h>
8
9#include <Foundation/Math/Arithmetic.h>
10
11#include <MCC/Pitch/PitchClass.h>
12#include <MCC/Pitch/Pitch.h>
13#include <MCC/Tuning/Tuning.h>
14
15namespace MCC {
16
29 MCC::Tuning _tuning;
30
31public:
33 constexpr EqualTemperament() noexcept : _tuning() {}
34
36 constexpr explicit EqualTemperament(MCC::Tuning tuning) noexcept
37 : _tuning(tuning) {}
38
40 static constexpr EqualTemperament Standard() noexcept {
42 }
43
45 constexpr bool IsValid() const noexcept { return _tuning.IsValid(); }
46
48 constexpr MCC::Tuning Tuning() const noexcept { return _tuning; }
49
58 MCC_CONSTEXPR14 float Frequency(MCC::Pitch pitch) const noexcept {
59 if (!IsValid() || !pitch.IsValid()) {
60 return 0.0f;
61 }
62
63 // 2^(k / 12) for k = 0..11.
64 constexpr float ratios[MCC::PitchClass::Count] = {
65 1.0f,
66 1.0594630943592953f,
67 1.1224620483093730f,
68 1.1892071150027210f,
69 1.2599210498948732f,
70 1.3348398541700344f,
71 1.4142135623730951f,
72 1.4983070768766815f,
73 1.5874010519681994f,
74 1.6817928305074290f,
75 1.7817974362806785f,
76 1.8877486253633870f};
77
78 const int32_t distance =
79 static_cast<int32_t>(pitch.ChromaticIndex().Value()) -
80 _tuning.Reference().ChromaticIndex().Value();
81 int32_t octaves = Foundation::Math::FloorDiv(
82 distance, MCC::PitchClass::Count);
83 const int32_t semitones = Foundation::Math::FloorMod(
84 distance, MCC::PitchClass::Count);
85
86 float frequency = _tuning.ReferenceFrequency() * ratios[semitones];
87 for (; octaves > 0; --octaves) {
88 if (frequency > FLT_MAX / 2.0f) {
89 return 0.0f;
90 }
91 frequency *= 2.0f;
92 }
93 for (; octaves < 0; ++octaves) {
94 frequency *= 0.5f;
95 }
96 return frequency;
97 }
98
100 friend constexpr bool operator==(EqualTemperament a, EqualTemperament b) noexcept {
101 return a._tuning == b._tuning;
102 }
103
104 friend constexpr bool operator!=(EqualTemperament a, EqualTemperament b) noexcept {
105 return !(a == b);
106 }
107};
108
109} // namespace MCC
110
111#endif // MCC_TUNING_EQUAL_TEMPERAMENT_H
Twelve-tone equal temperament relative to a Tuning.
Definition EqualTemperament.h:28
constexpr bool IsValid() const noexcept
Returns true when the tuning is valid.
Definition EqualTemperament.h:45
constexpr EqualTemperament(MCC::Tuning tuning) noexcept
Creates the temperament for tuning.
Definition EqualTemperament.h:36
static constexpr EqualTemperament Standard() noexcept
Returns equal temperament with A4 = 440 Hz (SPEC-OCT-2).
Definition EqualTemperament.h:40
constexpr EqualTemperament() noexcept
Creates the invalid temperament (SPEC-ERR-2).
Definition EqualTemperament.h:33
MCC_CONSTEXPR14 float Frequency(MCC::Pitch pitch) const noexcept
Returns the frequency of pitch in hertz.
Definition EqualTemperament.h:58
friend constexpr bool operator==(EqualTemperament a, EqualTemperament b) noexcept
Equality of tunings.
Definition EqualTemperament.h:100
constexpr MCC::Tuning Tuning() const noexcept
Returns the tuning reference.
Definition EqualTemperament.h:48
static constexpr uint8_t Count
Number of pitch classes in an octave.
Definition PitchClass.h:24
Written absolute pitch: a note name plus an octave.
Definition Pitch.h:35
Tuning reference: a written pitch and its frequency in hertz.
Definition Tuning.h:18
static constexpr Tuning Standard() noexcept
Returns the standard tuning, A4 = 440 Hz (SPEC-OCT-2).
Definition Tuning.h:38
Music Composition Core public namespace.
Definition Version.h:4