Some refactoring

This commit is contained in:
2023-02-20 18:22:33 +02:00
parent 65257217c5
commit a9e2936a29
3 changed files with 47 additions and 32 deletions

View File

@ -213,6 +213,7 @@ class Chord(Event):
pitch_classes: list[Pitch] = field(default=None) pitch_classes: list[Pitch] = field(default=None)
notes: list[int] = field(default=None) notes: list[int] = field(default=None)
freqs: list[float] = field(default=None, init=False)
def set_notes(self, notes: list[int]): def set_notes(self, notes: list[int]):
"""Set notes to the class""" """Set notes to the class"""
@ -221,11 +222,16 @@ class Chord(Event):
def update_notes(self, options): def update_notes(self, options):
"""Update notes""" """Update notes"""
notes = [] notes = []
freqs = []
for pitch in self.pitch_classes: for pitch in self.pitch_classes:
pitch.update_options(options) pitch.update_options(options)
pitch.update_note() pitch.update_note()
notes.append(pitch.note) notes.append(pitch.note)
freqs.append(pitch.freq)
self.notes = notes self.notes = notes
self.freqs = freqs
@dataclass(kw_only=True) @dataclass(kw_only=True)
@ -481,6 +487,7 @@ class Ziffers(Sequence):
"""Main class for holding options and the current state""" """Main class for holding options and the current state"""
options: dict = field(default_factory=DEFAULT_OPTIONS) options: dict = field(default_factory=DEFAULT_OPTIONS)
start_options: dict = None
loop_i: int = 0 loop_i: int = 0
iterator = None iterator = None
current: Item = field(default=None) current: Item = field(default=None)
@ -505,12 +512,13 @@ class Ziffers(Sequence):
else: else:
self.options = DEFAULT_OPTIONS self.options = DEFAULT_OPTIONS
self.start_options = self.options.copy()
self.evaluated_values = list(self.evaluate_tree(self.options)) self.evaluated_values = list(self.evaluate_tree(self.options))
self.iterator = iter(self.evaluated_values) self.iterator = iter(self.evaluated_values)
def re_eval(self, options=None): def re_eval(self, options=None):
"""Re-evaluate the iterator""" """Re-evaluate the iterator"""
self.options.update(DEFAULT_OPTIONS) self.options = self.start_options.copy()
if options: if options:
self.options.update(options) self.options.update(options)
self.evaluated_values = list(self.evaluate_tree(self.options)) self.evaluated_values = list(self.evaluate_tree(self.options))
@ -628,11 +636,13 @@ class Subdivision(Sequence):
has_children: bool = field(default=False, init=False) has_children: bool = field(default=False, init=False)
def evaluate(self, options): def evaluate(self, options):
"""Evaluate tree and then calculate lengths using subdivision"""
self.evaluated_values = list(self.evaluate_tree(options.copy())) self.evaluated_values = list(self.evaluate_tree(options.copy()))
self.evaluated_values = list(self.evaluate_subdivisions(options)) self.evaluated_values = list(self.evaluate_subdivisions(options))
return self return self
def evaluate_subdivisions(self, options): def evaluate_subdivisions(self, options):
"""Calculate new durations by dividing with the number of items in the sequence"""
self.subdiv_length = len(self.evaluated_values) self.subdiv_length = len(self.evaluated_values)
self.local_options = options.copy() self.local_options = options.copy()
self.local_options["duration"] = options["duration"] / self.subdiv_length self.local_options["duration"] = options["duration"] / self.subdiv_length
@ -785,6 +795,7 @@ class Euclid(Item):
evaluated_values: list = field(default=None) evaluated_values: list = field(default=None)
def evaluate(self, options): def evaluate(self, options):
"""Evaluate values using euclidean spread"""
onset_values = [ onset_values = [
val for val in self.onset.values if not isinstance(val, Whitespace) val for val in self.onset.values if not isinstance(val, Whitespace)
] ]

View File

@ -58,13 +58,13 @@ def string_rewrite(axiom: str, rules: dict):
def euclidian_rhythm(pulses: int, length: int, rotate: int = 0): def euclidian_rhythm(pulses: int, length: int, rotate: int = 0):
"""Calculate Euclidean rhythms. Original algorithm by Thomas Morrill.""" """Calculate Euclidean rhythms. Original algorithm by Thomas Morrill."""
def _starts_descent(list, index): def _starts_descent(arr, index):
length = len(list) length = len(arr)
next_index = (index + 1) % length next_index = (index + 1) % length
return list[index] > list[next_index] return arr[index] > arr[next_index]
def rotation(l, n): def rotation(arr, idx):
return l[-n:] + l[:-n] return arr[-idx:] + arr[:-idx]
if pulses >= length: if pulses >= length:
return [True] return [True]

View File

@ -1,40 +1,44 @@
"""Collection of converters""" """Collection of converters"""
from music21 import converter, note, stream, meter, chord from music21 import converter, note, stream, meter, chord, environment
from ziffers import zparse, Ziffers, Pitch, Rest, Chord from ziffers import zparse, Ziffers, Pitch, Rest, Chord
def to_music21(strData: str|Ziffers, **options):
def to_music21(expression: str | Ziffers, **options):
"""Helper for passing options to the parser""" """Helper for passing options to the parser"""
converter.registerSubconverter(ZiffersMusic21) converter.registerSubconverter(ZiffersMusic21)
if isinstance(strData,Ziffers): if isinstance(expression, Ziffers):
if options: if options:
options["preparsed"] = strData options["preparsed"] = expression
else: else:
options = {"preparsed": strData} options = {"preparsed": expression}
options = {"ziffers": options} options = {"ziffers": options}
return converter.parse("PREPARSED", format="ziffers", keywords=options) return converter.parse("PREPARSED", format="ziffers", keywords=options)
if options: if options:
options = {"ziffers": options} options = {"ziffers": options}
return converter.parse(strData, format="ziffers", keywords=options) return converter.parse(expression, format="ziffers", keywords=options)
else:
test = converter.parse(strData, format="ziffers") test = converter.parse(expression, format="ziffers")
return test return test
def set_musescore_path(path: str): def set_musescore_path(path: str):
"""Helper for setting the Musescore path""" """Helper for setting the Musescore path"""
us = environment.UserSettings() settings = environment.UserSettings()
# Default windows path: # Default windows path:
# 'C:\\Program Files\\MuseScore 3\\bin\\MuseScore3.exe' # 'C:\\Program Files\\MuseScore 3\\bin\\MuseScore3.exe'
us['musicxmlPath'] = path settings["musicxmlPath"] = path
us['musescoreDirectPNGPath'] = path settings["musescoreDirectPNGPath"] = path
class ZiffersMusic21(converter.subConverters.SubConverter): class ZiffersMusic21(converter.subConverters.SubConverter):
"""Ziffers converter to Music21""" """Ziffers converter to Music21"""
registerFormats = ("ziffers",) registerFormats = ("ziffers",)
registerInputExtensions = ("zf",) registerInputExtensions = ("zf",)
def parseData(self, strData, number=None): def parseData(self, dataString, number=None):
"""Parses Ziffers string to Music21 object""" """Parses Ziffers string to Music21 object"""
# Look for options in keywords object # Look for options in keywords object
keywords = self.keywords["keywords"] keywords = self.keywords["keywords"]
@ -43,25 +47,25 @@ class ZiffersMusic21(converter.subConverters.SubConverter):
if "preparsed" in options: if "preparsed" in options:
parsed = options["preparsed"] parsed = options["preparsed"]
else: else:
parsed = zparse(strData, **options) parsed = zparse(dataString, **options)
else: else:
parsed = zparse(strData) parsed = zparse(dataString)
s = stream.Part() note_stream = stream.Part()
if "time" in options: if "time" in options:
m = meter.TimeSignature(options["time"]) # Common time m_item = meter.TimeSignature(options["time"]) # Common time
else: else:
m = meter.TimeSignature("c") # Common time m_item = meter.TimeSignature("c") # Common time
s.insert(0, m) note_stream.insert(0, m_item)
for item in parsed: for item in parsed:
if isinstance(item,Pitch): if isinstance(item, Pitch):
m_item = note.Note(item.note) m_item = note.Note(item.note)
m_item.duration.quarterLength = item.duration * 4 m_item.duration.quarterLength = item.duration * 4
elif isinstance(item,Rest): elif isinstance(item, Rest):
m_item = note.Rest(item.duration * 4) m_item = note.Rest(item.duration * 4)
elif isinstance(item,Chord): elif isinstance(item, Chord):
m_item = chord.Chord(item.notes) m_item = chord.Chord(item.notes)
m_item.duration.quarterLength = item.duration * 4 m_item.duration.quarterLength = item.duration * 4
s.append(m_item) note_stream.append(m_item)
self.stream = s.makeMeasures() self.stream = note_stream.makeMeasures()