Added tests for scale
Added option to give intervals as scale name
This commit is contained in:
@ -43,4 +43,4 @@ def test_parsing_text(pattern: str):
|
|||||||
],
|
],
|
||||||
)
|
)
|
||||||
def test_pcs(pattern: str, expected: list):
|
def test_pcs(pattern: str, expected: list):
|
||||||
assert parse_expression(pattern).pcs == expected
|
assert parse_expression(pattern).pcs() == expected
|
||||||
24
tests/test_scale.py
Normal file
24
tests/test_scale.py
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
from ziffers import scale
|
||||||
|
import pytest
|
||||||
|
|
||||||
|
@pytest.mark.parametrize(
|
||||||
|
"name,expected",
|
||||||
|
[
|
||||||
|
("C4", 60),
|
||||||
|
("A1", 33),
|
||||||
|
("Bb3", 58),
|
||||||
|
("C#1", 25),
|
||||||
|
("foo", 60),
|
||||||
|
],
|
||||||
|
)
|
||||||
|
def test_notenames(name: str, expected: int):
|
||||||
|
assert scale.note_to_midi(name) == expected
|
||||||
|
|
||||||
|
@pytest.mark.parametrize(
|
||||||
|
"pcs,expected",
|
||||||
|
[
|
||||||
|
(list(range(-9,10)), [45, 47, 48, 50, 52, 53, 55, 57, 59, 60, 62, 64, 65, 67, 69, 71, 72, 74, 76]),
|
||||||
|
],
|
||||||
|
)
|
||||||
|
def test_note_to_midi(pcs: str, expected: int):
|
||||||
|
assert [scale.note_from_pc(root=60, pitch_class=val, intervals="Ionian") for val in pcs] == expected
|
||||||
@ -1515,14 +1515,13 @@ def note_to_midi(name: str) -> int:
|
|||||||
''' Parse note name to midi '''
|
''' Parse note name to midi '''
|
||||||
items = re.match(r"^([a-gA-G])([#bs])?([1-9])?$",name)
|
items = re.match(r"^([a-gA-G])([#bs])?([1-9])?$",name)
|
||||||
if items==None:
|
if items==None:
|
||||||
raise ValueError("Invalid note name: "+name)
|
return 60
|
||||||
values = items.groups()
|
values = items.groups()
|
||||||
octave = int(values[2]) if values[2] else 4
|
octave = int(values[2]) if values[2] else 4
|
||||||
modifier = modifiers[values[1]] if values[1] else 0
|
modifier = modifiers[values[1]] if values[1] else 0
|
||||||
interval = note_to_interval[values[0].capitalize()]
|
interval = note_to_interval[values[0].capitalize()]
|
||||||
return 12 + octave * 12 + interval + modifier
|
return 12 + octave * 12 + interval + modifier
|
||||||
|
|
||||||
|
|
||||||
def get_scale(name: str) -> list:
|
def get_scale(name: str) -> list:
|
||||||
"""Get a scale from the global scale list"""
|
"""Get a scale from the global scale list"""
|
||||||
scale = SCALES.get(
|
scale = SCALES.get(
|
||||||
@ -1534,19 +1533,21 @@ def get_scale(name: str) -> list:
|
|||||||
def note_from_pc(
|
def note_from_pc(
|
||||||
root: int|str,
|
root: int|str,
|
||||||
pitch_class: int,
|
pitch_class: int,
|
||||||
intervals: list[int|float],
|
intervals: str | list[int|float],
|
||||||
cents: bool = False,
|
cents: bool = False,
|
||||||
octave: int = 0,
|
octave: int = 0,
|
||||||
addition: int = 0
|
modifier: int = 0
|
||||||
) -> int:
|
) -> int:
|
||||||
"""Resolve a pitch class into a note from a scale"""
|
"""Resolve a pitch class into a note from a scale"""
|
||||||
if type(root)==str:
|
if type(root)==str:
|
||||||
root = note_to_midi(root)
|
root = note_to_midi(root)
|
||||||
if cents:
|
if cents:
|
||||||
intervals = list(map(lambda x: x / 100), intervals)
|
intervals = list(map(lambda x: x / 100), intervals)
|
||||||
|
if type(intervals) == str:
|
||||||
|
intervals = get_scale(intervals)
|
||||||
interval_sum = sum(intervals[0:pitch_class])
|
interval_sum = sum(intervals[0:pitch_class])
|
||||||
note = (root + interval_sum if pitch_class >= 0 else root - interval_sum)
|
note = (root + interval_sum if pitch_class >= 0 else root - interval_sum)
|
||||||
return note + octave*sum(intervals) + addition
|
return note + octave*sum(intervals) + modifier
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
|
|||||||
Reference in New Issue
Block a user