Map
The classes in this section allow arbitrary or matrices to be multiplied by vectors.
MapVec
Section titled “MapVec”The MapVec provides a generic vector type that 2-dimensional mapping operations can return, and provides methods to be converted into a Pitch or Interval vector as required.
MapVec follows the shape of Pitch and Interval, exposing two fields:
x: floaty: floatClass Constructor
Section titled “Class Constructor”MapVec(x: float, y: float)Simply pass in coordinates to instantiate a vector:
v = MapVec(12, 5)to_pitch
Section titled “to_pitch”MapVec.to_pitch() -> PitchConverts a MapVec into a Pitch vector.
v = MapVec(25, 10)p = v.to_pitch()
p.w # 25p.h # 10to_interval
Section titled “to_interval”MapVec.to_interval() -> IntervalConverts a MapVec into an Interval vector.
v = MapVec(5, 2)m = v.to_interval()
m.w # 5m.h # 2A Map1D is a matrix, used to map a 2-dimensional vector to a 1-dimensional number. Conceptually, many of Meantonal’s Pitch and Interval queries utilise this principle under the hood (see the Learn page for a detailed explanation).
Class Constructor
Section titled “Class Constructor”Map1D(m0: float, m1: float)Creates a matrix :
A = Map1D(5, 3)Map1D.map(v: MapVec | Pitch | Interval) -> floatCarries out the mapping operation on the passed in vector. Result will be a number.
A = Map1D(5, 3) # 31EDO mapping matrixp = SPN.to_pitch("G4")
A.map(p) # 173, an ordered MIDI-style numbering for 31EDOcompose
Section titled “compose”Map1D.compose(map: Map2D) -> Map1DComposes the Map1D instance with a passed in Map2D; essentially carries out matrix multiplication:
Returns a new Map1D. Creating new maps from the composition of existing maps can save on unnecessary computation.
A Map2D is a matrix, used to map a 2-dimensional vector to another 2-dimensional vector. Essentially effects a change of coordinate system (see the Learn page for a detailed explanation).
Class Constructor
Section titled “Class Constructor”Map2D(m00: float, m01: float, m10: float, m11: float)Creates a matrix:
A = Map2D(1, 2, 3, 4)Map2D.map(v: MapVec | Pitch | Interval) -> MapVecCarries out the mapping operation on the passed in vector. Result will be a generic MapVec.
A = Map2D(2, -5, -1, 3) # basis change: (w, h) => (P5, P8)p = SPN.to_pitch("E5")
A.map(p) # MapVec(x=4, y=4): E5 is 4 fifths and 4 octaves above C-1compose
Section titled “compose”Map2D.compose(map: Map2D) -> Map2DComposes the Map2D instance with a passed in Map2D; essentially carries out matrix multiplication:
Returns a new Map2D. Creating new maps from the composition of existing maps can save on unnecessary computation.
TuningMap
Section titled “TuningMap”A TuningMap represents a map onto a given tuning system, and is used to produce frequency values for Pitch vectors in that tuning. It is specified in terms of:
- The width of its fifth in cents.
- The name of a reference pitch in Scientific Pitch Notation.
- The frequency of that reference pitch in Hz.
If no reference pitch is given, the default is C4 = 261.6255653Hz. This is equivalent to A4 = 440Hz in 12TET, but is centered about C4.
Class Constructor
Section titled “Class Constructor”TuningMap(fifth: float, reference_pitch: str = "C4", reference_freq: float = 261.6255653)Creates a TuningMap instance manually.
Raises a ValueError if the fifth implied by fifth (in cents) falls outside ~685.7¢ to 720¢ ( to ), which cannot produce a well-defined diatonic scale.
T = TuningMap(700) # a fifth of exactly 700 cents (12TET)
TuningMap(600) # ValueError: TuningMap requires a fifth between ~685.7¢ and 720¢ to produce a well-defined diatonic.from_edo
Section titled “from_edo”TuningMap.from_edo(edo: int, reference_pitch: str = "C4", reference_freq: float = 261.6255653) -> TuningMapIf you’re working with an EDO tuning system, it can be more convenient to initialise a TuningMap by specifying the number of parts the octave is divided into rather than the specific width of a perfect fifth in cents within that system. This class method allows just that.
As with the class constructor, if the reference Pitch and its frequency are not specified, defaults to C4 = 261.6255653Hz.
Raises a ValueError if the fifth implied by edo falls outside ~685.7¢ to 720¢, which cannot produce a well-defined diatonic scale.
T = TuningMap.from_edo(31)
p = SPN.to_pitch("C4")T.to_hz(p) # ~261.63Hz
m = Interval.from_name("M3")T.to_cents(m) # ~387.10 cents
TuningMap.from_edo(2) # ValueError: 2-EDO does not support a diatonic scale.TuningMap.to_hz(p: Pitch) -> floatReturns the frequency of the passed-in Pitch in Hertz.
T = TuningMap.from_edo(12, "A4", 440)
p = SPN.to_pitch("A4")T.to_hz(p) # 440.0
p = SPN.to_pitch("A5")T.to_hz(p) # 880.0to_cents
Section titled “to_cents”TuningMap.to_cents(m: Interval) -> floatReturns the width of the passed in Interval in cents.
T = TuningMap.from_edo(12)
m = Interval.from_name("M3")T.to_cents(m) # 400.0to_ratio
Section titled “to_ratio”TuningMap.to_ratio(m: Interval) -> floatReturns the ratio of the passed Interval as a decimal number.
T = TuningMap.from_edo(31)
m = Interval.from_name("A6")T.to_ratio(m) # 1.7489046221194973EDOMap
Section titled “EDOMap”This handy class creates a map 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.
Class Constructor
Section titled “Class Constructor”EDOMap(edo: int)Create an EDOMap instance by simply specifying the number of parts the octave will be divided into.
Raises a ValueError if the fifth implied by edo falls outside ~685.7¢ to 720¢, which cannot produce a well-defined diatonic scale.
T = EDOMap(31)
EDOMap(2) # ValueError: 2-EDO does not support a diatonic scale.to_number
Section titled “to_number”EDOMap.to_number(p: Pitch) -> intReturns an ordered pitch numbering for the passed Pitch as an integer. For 12TET, this will be the ordinary MIDI value for a given Pitch, but for other EDO tunings it provides an ordered MIDI-equivalent mapping.
T1 = EDOMap(12)T2 = EDOMap(31)
p = SPN.to_pitch("C4")
T1.to_number(p) # 60T2.to_number(p) # 155compare
Section titled “compare”EDOMap.compare(p: Pitch, q: Pitch) -> intIn the specified EDO:
- Returns a positive number if p is above q.
- Returns a negative value if p is below q.
- Returns 0 if p and q are enharmonic.
p = SPN.to_pitch("C#4")q = SPN.to_pitch("Db4")
T = EDOMap(53)T.compare(p, q) # 1
T = EDOMap(31)T.compare(p, q) # -1
T = EDOMap(12)T.compare(p, q) # 0