This commit is contained in:
khodowany
2026-10-04 22:29:06 -05:00
parent 0e68f5364b
commit ef62af892b
40 changed files with 1754 additions and 789 deletions
+1 -30
View File
@@ -1,7 +1,7 @@
"""Complete generated rhythm groups, indexed once, independent of source rhythms."""
from fractions import Fraction as F
from generator import vocabulary
from generator.solo import groups, policy
from generator.solo import groups
class Rhythms:
def __init__(self, library, tempo):
@@ -31,32 +31,3 @@ class Rhythms:
representatives.setdefault(descriptor,(item.id,pattern,bar.length,('develop','answer')))
self.catalog[meter]=tuple(representatives.values())
self.cache={}
def realize(self,start,end,purpose,seed,meter):
key=(start,end,purpose,seed,meter)
if key in self.cache:return self.cache[key]
cursor=start;notes=[];sources=[];chosen=[];home=None;uses=0
while cursor<end:
available=[g for g in self.groups if purpose in g[3] and g[2]<=end-cursor]
# Catalog is a separate family, not thousands of duplicate votes.
if purpose in ('develop','answer'):
available += sorted((g for g in self.catalog.get(meter,()) if g[2]<=end-cursor),key=lambda g:policy.stable_rank(seed,('catalog',cursor,g[0])))[:1]
available=[g for g in available if ((end-cursor-g[2])*2).denominator==1]
if not available:return (),(),()
# Prefer complete multi-event groups; single values finish an exact remainder.
large=[g for g in available if g[2]>=1]
if home is not None and uses<2 and home in available:
selected=home
else:
# Establish one rhythmic idea before reshaping it. A complete phrase
# is not a fresh unrelated catalog draw at every short boundary.
selected=min(large or available,key=lambda g:policy.stable_rank(seed,('rhythm',len(chosen)//4,g[0])))
home=selected;uses=0
uses+=1
name,pattern,length,_=selected
events=tuple((cursor+a,cursor+b) for a,b in pattern)
notes.extend(events);sources.append(name)
chosen.extend(groups.describe(pattern,origin=cursor,source=name))
cursor+=length
result=(tuple(notes),tuple(chosen),tuple(sources));self.cache[key]=result
return result