import warnings
import reapy
from reapy import reascript_api as RPR
from reapy.core import ReapyObject
[docs]class Envelope(ReapyObject):
def __init__(self, parent, id):
self.id = id
self._parent = parent
@property
def _args(self):
return (self.parent, self.id)
[docs] def add_item(self, position=0., length=1., pool=0):
"""
Add automation item to envelope.
Parameters
----------
position : float, optional
New item position in seconds (default=0).
length : float
New item length in seconds (default=0).
pool : int
New item pool index. If >= 0 the automation item will be a
new instance of that pool (which will be created as an
empty instance if it does not exist).
Returns
-------
item : reapy.AutomationItem
New automation item.
"""
item_index = RPR.InsertAutomationItem(self.id, pool, position, length)
item = reapy.AutomationItem(envelope=self, index=item_index)
return item
[docs] def delete_points_in_range(self, start, end):
"""
Delete envelope points between `start` and `end`.
Parameters
----------
start : float
Range start in seconds.
end : float
Range end in seconds.
"""
RPR.DeleteEnvelopePointRange(self.id, start, end)
[docs] @reapy.inside_reaper()
def get_derivatives(self, time, raw=False):
"""
Return envelope derivatives of order 1, 2, 3 at a given time.
Parameters
----------
time : float
Time in seconds.
raw : bool, optional
Whether to return raw values or the human-readable version
which is printed in REAPER GUI (default=False).
Returns
-------
d, d2, d3 : float
First, second and third order derivatives.
Examples
--------
>>> envelope = track.envelopes["Pan"]
>>> envelope.get_derivatives(10, raw=True)
(0.10635556358181712, 0.2127113398749741, 0.21271155258652666)
>>> envelope.get_value(10) # human-readable
('10%L', '21%L', '21%L')
"""
d, d2, d3 = RPR.Envelope_Evaluate(self.id, time, 1, 1, 0, 0, 0, 0)[6:]
if not raw:
d = RPR.Envelope_FormatValue(self.id, d, "", 2048)[2]
d2 = RPR.Envelope_FormatValue(self.id, d2, "", 2048)[2]
d3 = RPR.Envelope_FormatValue(self.id, d3, "", 2048)[2]
return d, d2, d3
[docs] @reapy.inside_reaper()
def get_value(self, time, raw=False):
"""
Return envelope value at a given time.
Parameters
----------
time : float
Time in seconds.
raw : bool, optional
Whether to return raw value or its human-readable version,
which is the one that is printed in REAPER GUI
(default=False).
Returns
-------
value : float or str
Envelope value.
Examples
--------
>>> envelope = track.envelopes["Pan"]
>>> envelope.get_value(10, raw=True)
-0.5145481809245827
>>> envelope.get_value(10) # human-readable
'51%R'
"""
value = RPR.Envelope_Evaluate(self.id, time, 0, 0, 0, 0, 0, 0)[5]
if not raw:
value = RPR.Envelope_FormatValue(self.id, value, "", 2048)[2]
return value
@reapy.inside_reaper()
@property
def has_valid_id(self):
"""
Whether ReaScript ID is still valid.
For instance, if envelope has been deleted, ID will not be valid
anymore.
:type: bool
"""
try:
project_id = self.parent.project.id
except (OSError, AttributeError):
return False
pointer, name = self._get_pointer_and_name()
return bool(RPR.ValidatePtr2(project_id, pointer, name))
@property
def items(self):
"""
List of automation items in envelope.
:type: list of reapy.AutomationItem
"""
items = [reapy.AutomationItem(self, i) for i in range(self.n_items)]
return items
@property
def n_items(self):
"""
Number of automation items in envelope.
:type: int
"""
n_items = RPR.CountAutomationItems(self.id)
return n_items
@property
def n_points(self):
"""
Number of points in envelope.
:type: int
"""
n_points = RPR.CountEnvelopePoints(self.id)
return n_points
@property
def name(self):
"""
Envelope name.
:type: str
"""
name = RPR.GetEnvelopeName(self.id, "", 2048)[2]
return name
@property
def parent(self):
"""
Envelope parent.
:type: Take or Track
"""
return self._parent
[docs]class EnvelopeList(ReapyObject):
"""
Container class for the list of envelopes on a Take or Track.
Envelopes can be accessed from the EnvelopeList either by index,
name or chunk_name (e.g. "<VOLENV").
Examples
--------
>>> len(track.envelopes)
2
>>> envelope = track.envelopes[0]
>>> envelope.name
'Volume'
>>> envelope == track.envelopes["Volume"]
True
>>> envelope == track.envelopes["<VOLENV"]
True
>>> [e.name for e in track.envelopes]
['Volume', 'Pan']
"""
def __init__(self, parent):
self.parent = parent
@property
def _args(self):
return (self.parent,)
def __getitem__(self, key):
parent_type = self.parent.__class__._reapy_parent.__name__
attr = "Get{}Envelope".format(parent_type)
if isinstance(key, str):
if key.startswith("<") and parent_type == 'Track':
attr += "ByChunkName"
else:
attr += "ByName"
callback = getattr(RPR, attr)
envelope = Envelope(self.parent, callback(self.parent.id, key))
if not envelope._is_defined:
raise KeyError("No envelope for key {}".format(repr(key)))
return envelope
def __len__(self):
return self.parent.n_envelopes