Skip to content

Commit

Permalink
fix caching parameters
Browse files Browse the repository at this point in the history
  • Loading branch information
gesellkammer committed Nov 3, 2023
1 parent 6ad96a8 commit 4291993
Show file tree
Hide file tree
Showing 7 changed files with 58 additions and 47 deletions.
6 changes: 3 additions & 3 deletions csoundengine/baseevent.py
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ def set(self, param='', value: float = 0., delay=0., **kws) -> None:
self._setp(param=param, value=value, delay=delay)
else:
raise KeyError(f"Unknown parameter: '{param}'. "
f"Possible parameters for this event: {self.dynamicParams(aliased=True)}")
f"Possible parameters for this event: {self.dynamicParamNames(aliased=True)}")

def _automatePfield(self,
param: int | str,
Expand Down Expand Up @@ -197,9 +197,9 @@ def automate(self,
elif param.startswith('p') or ((pargs := self.pfieldNames(aliases=False)) and param in pargs):
return self._automatePfield(param=param, pairs=pairs, mode=mode, delay=delay, overtake=overtake)
else:
raise KeyError(f"Unknown parameter '{param}', supported parameters: {self.dynamicParams()}")
raise KeyError(f"Unknown parameter '{param}', supported parameters: {self.dynamicParamNames()}")

def dynamicParams(self, aliases=True, aliased=False) -> set[str]:
def dynamicParamNames(self, aliases=True, aliased=False) -> set[str]:
"""
The set of all dynamic parameters accepted by this event
Expand Down
20 changes: 20 additions & 0 deletions csoundengine/engine.py
Original file line number Diff line number Diff line change
Expand Up @@ -3936,6 +3936,26 @@ def assignBus(self, kind='', value: float = None, persist=False
self._perfThread.scoreEvent(0, "i", pfields)
return bustoken

def busSystemStatus(self) -> dict:
"""
Get debugging nformation about the status of the bus system
This is only provided for debugging
Returns:
a dict containing information about the status of the bus system
(used buses, free buses, etc)
"""
if not self.hasBusSupport():
raise RuntimeError("This Engine has no bus support")

audioBusesFree = self.evalCode('pool_size(gi__buspool)')
controlBusesFree = self.evalCode('pool_size(gi__buspoolk)')
return {'audioBusesFree': audioBusesFree,
'controlBusesFree': controlBusesFree,
'numAudioBuses': self.numAudioBuses,
'numControlBuses': self.numControlBuses}

def hasBusSupport(self) -> bool:
"""
Returns True if this Engine was started with bus support
Expand Down
16 changes: 8 additions & 8 deletions csoundengine/instr.py
Original file line number Diff line number Diff line change
Expand Up @@ -512,7 +512,7 @@ def dynamicParamNames(self, aliases=True, aliased=False
return frozenset(dynparams.keys())

@cache
def dynamicPfields(self, aliases=True, aliased=True) -> dict[str, float]:
def dynamicPfields(self, aliases=True, aliased=False) -> dict[str, float]:
"""
The dynamic pfields in this instr
Expand All @@ -526,19 +526,18 @@ def dynamicPfields(self, aliases=True, aliased=True) -> dict[str, float]:
Returns:
a dict mapping pfield name to default value.
"""
if not self.pfieldNameToIndex:
if not self.pfields:
return EMPTYDICT

pfields = {name: self.pfieldIndexToValue.get(idx, 0.)
for name, idx in self.pfieldNameToIndex.items()
pfields = {name: value for name, value in self.pfields.items()
if name.startswith('k')}

if aliases and self.aliases:
for alias, realname in self.aliases.items():
if realname in pfields:
pfields[alias] = pfields[realname]
if not aliased:
del pfields[realname]
pfields.pop(realname, None)

return pfields

Expand Down Expand Up @@ -592,11 +591,12 @@ def dynamicParams(self, aliases=True, aliased=False
if not self.pfields and not self.controls:
return EMPTYDICT

params = self.dynamicPfields()
params = self.dynamicPfields(aliases=False)
if self.controls:
params = params | self.controls

if aliases and self.aliases:
params = params.copy()
for alias, realname in self.aliases.items():
params[alias] = params[realname]
if not aliased:
Expand All @@ -611,7 +611,7 @@ def paramNames(self, aliases=True, aliased=False
pfields = self.pfieldNames(aliases=aliases, aliased=aliased)
return frozenset(pfields | self.controlNames()) if self.controls else pfields

@cache
# @cache
def pfieldNames(self, aliases=True, aliased=False
) -> frozenset[str]:
"""
Expand All @@ -629,7 +629,7 @@ def pfieldNames(self, aliases=True, aliased=False
pfields = set(self.pfieldNameToIndex.keys())
if aliases and self.aliases:
for alias, realname in self.aliases.items():
if alias in pfields:
if realname in pfields:
pfields.add(alias)
if not aliased:
pfields.remove(realname)
Expand Down
2 changes: 1 addition & 1 deletion csoundengine/interact.py
Original file line number Diff line number Diff line change
Expand Up @@ -182,7 +182,7 @@ def interactSynth(synth: _synth.AbstrSynth,
specs: a list of ParamSpec
"""
if not specs:
dynparams = synth.dynamicParams(aliases=False)
dynparams = synth.dynamicParamNames(aliases=False)
params = {param: synth.paramValue(param) for param in sorted(dynparams)}
specs = guessParamSpecs(params=params)

Expand Down
14 changes: 7 additions & 7 deletions csoundengine/offline.py
Original file line number Diff line number Diff line change
Expand Up @@ -242,7 +242,7 @@ def instr(self) -> Instr | None:
def paramNames(self, aliases=True, aliased=False) -> frozenset[str]:
return self.instr.paramNames(aliases=aliases, aliased=aliased)

def dynamicParams(self, aliases=True, aliased=False) -> frozenset[str]:
def dynamicParamNames(self, aliases=True, aliased=False) -> frozenset[str]:
instr = self.instr
return instr.dynamicParamNames(aliases=aliases, ) if instr else set()

Expand Down Expand Up @@ -301,7 +301,7 @@ def _setp(self, param: str, value: float, delay=0.) -> None:
ev._setp(delay=delay, param=param, value=value)
count += 1
if count == 0:
raise KeyError(f"Parameter '{param}' unknown. Possible paramters: {self.dynamicParams(aliased=True)}")
raise KeyError(f"Parameter '{param}' unknown. Possible paramters: {self.dynamicParamNames(aliased=True)}")

def _setTable(self, param: str, value: float, delay=0.) -> None:
count = 0
Expand All @@ -311,7 +311,7 @@ def _setTable(self, param: str, value: float, delay=0.) -> None:
count += 1
if count == 0:
raise KeyError(f"Parameter '{param}' unknown. "
f"Possible parameters: {self.dynamicParams(aliased=True)}")
f"Possible parameters: {self.dynamicParamNames(aliased=True)}")

@cache
def paramNames(self, aliases=True, aliased=False) -> frozenset[str]:
Expand All @@ -321,10 +321,10 @@ def paramNames(self, aliases=True, aliased=False) -> frozenset[str]:
return frozenset(allparams)

@cache
def dynamicParams(self, aliases=True, aliased=False) -> frozenset[str]:
def dynamicParamNames(self, aliases=True, aliased=False) -> frozenset[str]:
params = set()
for ev in self.events:
params.update(ev.dynamicParams(aliases=aliases, aliased=aliased))
params.update(ev.dynamicParamNames(aliases=aliases, aliased=aliased))
return frozenset(params)

def __hash__(self):
Expand All @@ -339,13 +339,13 @@ def automate(self,
) -> None:
count = 0
for ev in self.events:
if param in ev.dynamicParams(aliases=True, aliased=True):
if param in ev.dynamicParamNames(aliases=True, aliased=True):
count += 1
ev.automate(param=param, pairs=pairs, mode=mode,
delay=delay, overtake=overtake)
if count == 0:
raise KeyError(f"Param '{param}' not known by any events in this group. "
f"Possible parameters: {self.dynamicParams(aliased=True)}")
f"Possible parameters: {self.dynamicParamNames(aliased=True)}")


@dataclass
Expand Down
45 changes: 18 additions & 27 deletions csoundengine/synth.py
Original file line number Diff line number Diff line change
Expand Up @@ -138,7 +138,7 @@ def ui(self, **specs: tuple[float, float]) -> None:
"""
from . import interact
dynparams = self.dynamicParams(aliases=True, aliased=False)
dynparams = self.dynamicParamNames(aliases=True, aliased=False)
if not dynparams:
logger.error(f"No named parameters for {self}")
return
Expand Down Expand Up @@ -366,7 +366,7 @@ def playing(self) -> bool:
def finished(self) -> bool:
return self.playStatus() == 'stopped'

def dynamicParams(self, aliases=True, aliased=False) -> frozenset[str]:
def dynamicParamNames(self, aliases=True, aliased=False) -> frozenset[str]:
"""
The set of all dynamic parameters accepted by this Synth
Expand All @@ -382,7 +382,7 @@ def dynamicParams(self, aliases=True, aliased=False) -> frozenset[str]:
"""
return self.instr.dynamicParamNames(aliases=aliases, aliased=aliased)

def pfieldNames(self, aliases=True, aliased=False) -> set[str]:
def pfieldNames(self, aliases=True, aliased=False) -> frozenset[str]:
return self.instr.pfieldNames(aliases=aliases, aliased=aliased)

def _sliceStart(self) -> int:
Expand Down Expand Up @@ -432,7 +432,7 @@ def _setp(self, param: str, value: float, delay=0.) -> None:
idx = self.instr.pfieldIndex(param, default=0)
if idx == 0:
raise KeyError(f"Unknown parameter {param} for synth {self}. "
f"Possible parameters: {self.dynamicParams()}")
f"Possible parameters: {self.dynamicParamNames()}")
self.engine.setp(self.p1, idx, value, delay=delay)


Expand Down Expand Up @@ -571,7 +571,7 @@ def automate(self,
overtake=overtake)

param = self.unaliasParam(param, param)
params = self.dynamicParams(aliases=False)
params = self.instr.dynamicParams(aliases=False)
if param not in params:
raise KeyError(f"Unknown parameter '{param}' for {self}. Possible parameters: {params}")

Expand All @@ -580,7 +580,7 @@ def automate(self,
elif (pargs := self.pfieldNames(aliases=False)) and param in pargs:
return self._automatePfield(param=param, pairs=pairs, mode=mode, delay=delay, overtake=overtake)
else:
raise KeyError(f"Unknown parameter '{param}', supported parameters: {self.dynamicParams()}")
raise KeyError(f"Unknown parameter '{param}', supported parameters: {self.dynamicParamNames()}")

def _automatePfield(self, param: int | str, pairs: list[float] | np.ndarray,
mode="linear", delay=0., overtake=False) -> float:
Expand Down Expand Up @@ -728,26 +728,26 @@ def _automateTable(self, param: str, pairs, mode="linear", delay=0.,
count = 0
for synth in self.synths:
if isinstance(synth, Synth):
controls = synth.dynamicParams()
controls = synth.dynamicParamNames()
if controls and param in controls:
synth._automateTable(param, pairs, mode=mode, delay=delay,
overtake=overtake)
count += 1
elif isinstance(synth, SynthGroup):
controls = synth.dynamicParams()
controls = synth.dynamicParamNames()
if controls and param in controls:
synth._automateTable(param=param, pairs=pairs, mode=mode, delay=delay,
overtake=overtake)
count += 1
if count == 0:
raise KeyError(f"Parameter '{param}' not known. "
f"Possible parameters: {self.dynamicParams()}")
f"Possible parameters: {self.dynamicParamNames()}")

@cache
def dynamicParams(self, aliases=True, aliased=False) -> set[str]:
def dynamicParamNames(self, aliases=True, aliased=False) -> set[str]:
out: set[str] = set()
for synth in self.synths:
dynamicParams = synth.dynamicParams(aliases=aliases, aliased=aliased)
dynamicParams = synth.dynamicParamNames(aliases=aliases, aliased=aliased)
out.update(dynamicParams)
return out

Expand Down Expand Up @@ -797,8 +797,6 @@ def automate(self,
value of the given parameter is used. The same effect is achieved
if the first value is given as 'nan', in this case also the current
value of the synth is overtaken.
strict: if True, raise an Exception if the parameter does not match any
synth in this group
Returns:
a list of synthids. There will be one synthid per synth in this group.
Expand All @@ -808,22 +806,15 @@ def automate(self,
synth
"""
synthids = []
if strict:
allparams = self.dynamicParams()
if param not in allparams:
lines = [f"Parameter '{param}' unknown. Known parameters: {allparams}",
f"Synths in this group:"]
for synth in self.synths:
lines.append(" " + repr(synth))
logger.error("\n".join(lines))
raise KeyError(f"Parameter {param} not supported by any synth in this group. "
f"Possible parameters: {allparams}")
for synth in self.synths:
if param in synth.instr.dynamicParams():
synthid = synth.automate(param=param, pairs=pairs, mode=mode, delay=delay, overtake=overtake)
else:
synthid = 0
synthids.append(synthid)
if all(synthid == 0 for synthid in synthids):
raise KeyError(f"Parameter '{param}' not known. Possible parameters: "
f"{self.dynamicParamNames(aliases=True, aliased=True)}")
return synthids

def _automatePfield(self,
Expand All @@ -837,7 +828,7 @@ def _automatePfield(self,
if param in synth.instr.dynamicPfieldNames()]
if not eventids:
raise ValueError(f"Parameter '{param}' unknown for group, possible "
f"parameters: {self.dynamicParams()}")
f"parameters: {self.dynamicParamNames()}")
return eventids

def _htmlTable(self) -> str:
Expand Down Expand Up @@ -905,11 +896,11 @@ def __iter__(self):
def _setTable(self, param: str, value: float, delay=0) -> None:
count = 0
for synth in self.synths:
if param in synth.dynamicParams(aliases=True, aliased=True):
if param in synth.dynamicParamNames(aliases=True, aliased=True):
synth._setTable(param=param, value=value, delay=delay)
count += 1
if count == 0:
params = list(self.dynamicParams(aliases=False))
params = list(self.dynamicParamNames(aliases=False))
if aliases := self.aliases():
params.extend(f'{alias}>{orig}' for alias, orig in aliases.items())
raise KeyError(f"Parameter '{param}' unknown. "
Expand Down Expand Up @@ -939,7 +930,7 @@ def _setp(self, param: str, value: float, delay=0.) -> None:
count += 1
if count == 0:
raise KeyError(f"Parameter {param} unknown. "
f"Possible parameters: {self.dynamicParams()}")
f"Possible parameters: {self.dynamicParamNames()}")

def controlNames(self, aliases=True, aliased=False) -> set[str]:
"""
Expand Down
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
from setuptools import setup
import os

version = (2, 2, 1)
version = (2, 2, 2)

from os import path
this_directory = path.abspath(path.dirname(__file__))
Expand Down

0 comments on commit 4291993

Please sign in to comment.