Map
This page details functions that apply linear maps to generic 2d vectors. Many of Meantonal’s built-in functions that operate on Pitch and Interval vectors are essentially performing these maps under the hood, but these generalised mapping operations are available in case something you need isn’t a built-in.
Generic Maps
Section titled “Generic Maps”map_to_1d
Section titled “map_to_1d”static inline double map_to_1d(MapVec v, Map1D T);This function allows an arbitrary Map1D matrix to multiply a MapVec, sending it to some integer. Allows things like:
(double)map_to_1d((MapVec){p.w, p.h}, ED31);This would send any Pitch to a 31-tone equal temperament equivalent of MIDI numbering, such that:
and so on…
map_compose_1d_2d
Section titled “map_compose_1d_2d”static inline Map1D map_compose_1d_2d(Map1D A, Map2D B);Composes a Map1D with a Map2D; essentially carries out matrix multiplication:
Returns a new Map1D. Creating new maps from the composition of existing maps can save on unnecessary computation. Just be aware that floating point arithmetic is cursed, and does not necessarily equal .
map_to_2d
Section titled “map_to_2d”static inline MapVec map_to_2d(MapVec v, Map2D T);This function allows an arbitrary Map2D matrix to multiply a MapVec. If it’s an invertible matrix, this essentially facilitates a change of basis. The returned vector is another MapVec.
This could be useful if working with generalised isomorphic keyboard layouts. For example, if reading numbers off a grid intended to represent a Wicki-Hayden layout, they could be parsed into Meantonal Pitch vectors simply:
typedef struct { int x, y;} WickiKey;
Pitch pitch_from_key(WickiKey k) { MapVec v = map_to_2d((MapVec) k, WICKI_FROM); return (Pitch){v.x, v.y};}map_compose_2d_2d
Section titled “map_compose_2d_2d”static inline Map2D map_compose_2d_2d(Map2D A, Map2D B);Composes a Map2D with another Map2D; essentially carries out matrix multiplication:
Returns a new Map2D. Creating new maps from the composition of existing maps can save on unnecessary computation. Just be aware that floating point arithmetic is cursed, and does not necessarily equal .
Tuning Maps
Section titled “Tuning Maps”tuning_map_from_fifth
Section titled “tuning_map_from_fifth”int tuning_map_from_fifth(double fifth, Pitch ref_pitch, double ref_freq, TuningMap *out);Construct a TuningMap from the width of the fifth in the target tuning system in cents, along with a reference Pitch and its frequency in the tuning in Hertz (e.g. A4 = 440Hz). The result is written to out.
Returns 1 if fifth falls outside ~685.7¢ to 720¢ ( to ), which cannot produce a well-defined diatonic scale — in this case *out is left untouched. Returns 0 otherwise.
TuningMap T;if (tuning_map_from_fifth(700.0, (Pitch){29, 11}, 440, &T)) { // handle invalid fifth}tuning_map_from_edo
Section titled “tuning_map_from_edo”int tuning_map_from_edo(int edo, Pitch ref_pitch, double ref_freq, TuningMap *out);Construct a TuningMap for an EDO tuning system from the number of parts the octave will be divided into, along with a reference Pitch and its frequency in the tuning in Hertz (e.g. A4 = 440Hz). The result is written to out.
Returns 1 if the fifth implied by edo falls outside ~685.7¢ to 720¢, which cannot produce a well-defined diatonic scale—in this case *out is left untouched. Returns 0 otherwise.
TuningMap T;if (tuning_map_from_edo(12, (Pitch){29, 11}, 440, &T)) { // handle EDO that can't support a diatonic scale}double to_hz(Pitch p, TuningMap T);Returns the frequency of a Pitch in a given tuning in Hertz.
Pitch p;pitch_from_spn("C4", &p);
TuningMap T;tuning_map_from_edo(12, p, CONCERT_C4, &T);
to_hz(p, T); // 261.6255653to_ratio
Section titled “to_ratio”double to_ratio(Interval m, TuningMap T);Returns a decimal approximation of the ratio of an Interval in a given tuning system.
Interval m;interval_from_name("A6", &m);
Pitch ref;pitch_from_spn("C4", &ref);TuningMap T;tuning_map_from_edo(31, ref, CONCERT_C4, &T);
to_ratio(m, T); // 1.7489046221194973 (very close to 7/4)to_cents
Section titled “to_cents”double to_cents(Interval m, TuningMap T);Returns the width of an Interval in a given tuning system in cents.
Interval m;interval_from_name("P5", &m);
Pitch ref;pitch_from_spn("C4", &ref);TuningMap T;tuning_map_from_edo(31, ref, CONCERT_C4, &T);
to_cents(m, T); // 696.7741935483871create_edo_map
Section titled “create_edo_map”int create_edo_map(int edo, EDOMap *out);Create an EDOMap that maps Pitch vectors to a well-ordered integer numbering for a given EDO tuning. For 12TET this is equivalent to standard MIDI, and for other EDO tunings a similar numbering is generated. The result is written to out.
Returns 1 if the fifth implied by edo falls outside ~685.7¢ to 720¢, which cannot produce a well-defined diatonic scale — in this case *out is left untouched. Returns 0 otherwise.
Used with pitch_to_number and pitches_compare.
EDOMap T;if (create_edo_map(31, &T)) { // handle EDO that can't support a diatonic scale}