Skip to content

Commit

Permalink
parameters: Refactor *TempoPoint to *Tempo
Browse files Browse the repository at this point in the history
Perhaps the reason why it was called 'TempoPoint' instead of 'Tempo' was
that 'Tempo' is a part of a 'TempoEnvelope' and therefore only a point
in the wider tempo trajectory. On the other hand the same could be said
of a pitch: also pitches can be continuously changing ('glissando'), but
we don't call them 'PitchPoints'. The difference is perhaps that the
pitch attribute has an optionally activated '.envelope' attribute, while
'Tempo' hasn't. But we should rather fix this and make this uniform
instead of having a specific *Point parameter.
  • Loading branch information
levinericzimmermann committed Feb 26, 2024
1 parent d7b34c8 commit 5972c97
Show file tree
Hide file tree
Showing 10 changed files with 127 additions and 127 deletions.
34 changes: 17 additions & 17 deletions mutwo/core_converters/tempos.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# This file is part of mutwo, ecosystem for time-based arts.
#
# Copyright (C) 2020-2023
# Copyright (C) 2020-2024
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
Expand All @@ -15,7 +15,7 @@
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.

"""Apply tempo curve on any :class:`~mutwo.core_events.abc.Event` and convert :class:`~mutwo.core_parameters.abc.TempoPoint` to beat-length-in-seconds.
"""Apply tempo curve on any :class:`~mutwo.core_events.abc.Event` and convert :class:`~mutwo.core_parameters.abc.Tempo` to beat-length-in-seconds.
"""

Expand All @@ -28,40 +28,40 @@


__all__ = (
"TempoPointToBeatLengthInSeconds",
"TempoToBeatLengthInSeconds",
"TempoConverter",
"EventToMetrizedEvent",
)


class TempoPointToBeatLengthInSeconds(core_converters.abc.Converter):
"""Convert a :class:`~mutwo.core_parameters.abc.TempoPoint` to beat length in seconds.
class TempoToBeatLengthInSeconds(core_converters.abc.Converter):
"""Convert a :class:`~mutwo.core_parameters.abc.Tempo` to beat length in seconds.
**Example:**
>>> from mutwo import core_converters
>>> tempo_point_converter = core_converters.TempoPointToBeatLengthInSeconds()
>>> tempo_converter = core_converters.TempoToBeatLengthInSeconds()
"""

def convert(
self, tempo_point_to_convert: core_parameters.abc.TempoPoint.Type
self, tempo_to_convert: core_parameters.abc.Tempo.Type
) -> float:
"""Converts a :class:`TempoPoint` to beat-length-in-seconds.
"""Converts a :class:`Tempo` to beat-length-in-seconds.
:param tempo_point_to_convert: A tempo point defines the active tempo
:param tempo_to_convert: A tempo defines the active tempo
from which the beat-length-in-seconds shall be calculated.
:return: The duration of one beat in seconds within the passed tempo.
**Example:**
>>> from mutwo import core_converters
>>> converter = core_converters.TempoPointToBeatLengthInSeconds()
>>> converter = core_converters.TempoToBeatLengthInSeconds()
>>> converter.convert(60) # one beat in tempo 60 bpm takes 1 second
1.0
>>> converter.convert(120) # one beat in tempo 120 bpm takes 0.5 second
0.5
"""
t = core_parameters.abc.TempoPoint.from_any(tempo_point_to_convert)
t = core_parameters.abc.Tempo.from_any(tempo_to_convert)
return float(60 / t.bpm)


Expand All @@ -71,7 +71,7 @@ class TempoConverter(core_converters.abc.EventConverter):
:param tempo_envelope: The tempo curve that shall be applied on the
mutwo events. This is expected to be a :class:`core_events.TempoEnvelope`
which values are filled with numbers that will be interpreted as BPM
[beats per minute]) or with :class:`mutwo.core_parameters.abc.TempoPoint`
[beats per minute]) or with :class:`mutwo.core_parameters.abc.Tempo`
objects.
:param apply_converter_on_events_tempo_envelope: If set to `True` the
converter adjusts the :attr:`tempo_envelope` attribute of each
Expand All @@ -83,12 +83,12 @@ class TempoConverter(core_converters.abc.EventConverter):
>>> from mutwo import core_events
>>> from mutwo import core_parameters
>>> tempo_envelope = core_events.Envelope(
... [[0, core_parameters.DirectTempoPoint(60)], [3, 60], [3, 30], [5, 50]],
... [[0, core_parameters.DirectTempo(60)], [3, 60], [3, 30], [5, 50]],
... )
>>> c = core_converters.TempoConverter(tempo_envelope)
"""

_tempo_point_to_beat_length_in_seconds = TempoPointToBeatLengthInSeconds().convert
_tempo_to_beat_length_in_seconds = TempoToBeatLengthInSeconds().convert

# Define private tempo envelope class which catches its
# absolute times and durations. With this we can
Expand Down Expand Up @@ -133,11 +133,11 @@ def __init__(
def _tempo_envelope_to_beat_length_in_seconds_envelope(
tempo_envelope: core_events.Envelope,
) -> core_events.Envelope:
"""Convert bpm / TempoPoint based env to beat-length-in-seconds env."""
"""Convert bpm / Tempo based env to beat-length-in-seconds env."""
e = tempo_envelope
value_list: list[float] = []
for tp in e.parameter_tuple:
value_list.append(TempoConverter._tempo_point_to_beat_length_in_seconds(tp))
value_list.append(TempoConverter._tempo_to_beat_length_in_seconds(tp))

return TempoConverter._CatchedTempoEnvelope(
[
Expand Down Expand Up @@ -238,7 +238,7 @@ def convert(self, event_to_convert: core_events.abc.Event) -> core_events.abc.Ev
>>> from mutwo import core_events
>>> from mutwo import core_parameters
>>> tempo_envelope = core_events.Envelope(
... [[0, core_parameters.DirectTempoPoint(60)], [3, 60], [3, 30], [5, 50]],
... [[0, core_parameters.DirectTempo(60)], [3, 60], [3, 30], [5, 50]],
... )
>>> my_tempo_converter = core_converters.TempoConverter(tempo_envelope)
>>> my_events = core_events.Consecution([core_events.Chronon(d) for d in (3, 2, 5)])
Expand Down
42 changes: 21 additions & 21 deletions mutwo/core_events/envelopes.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# This file is part of mutwo, ecosystem for time-based arts.
#
# Copyright (C) 2020-2023
# Copyright (C) 2020-2024
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
Expand Down Expand Up @@ -805,16 +805,16 @@ class TempoEnvelope(Envelope):
"""Define dynamic or static tempo trajectories.
You can either define a new `TempoEnvelope` with instances
of classes which inherit from :class:`mutwo.core_parameters.abc.TempoPoint`
(for instance :class:`mutwo.core_parameters.DirectTempoPoint`) or with
of classes which inherit from :class:`mutwo.core_parameters.abc.Tempo`
(for instance :class:`mutwo.core_parameters.DirectTempo`) or with
`float` or `int` objects which represent beats per minute.
Please see the :class:`mutwo.core_events.Envelope` for full documentation
for initialization attributes.
The default parameters of the `TempoEnvelope` class expects
:class:`mutwo.core_events.Chronon` to which a tempo point
was assigned by the name "tempo_point".
:class:`mutwo.core_events.Chronon` to which a tempo
was assigned by the name "tempo".
**Example:**
Expand All @@ -826,12 +826,12 @@ class TempoEnvelope(Envelope):
>>> tempo_envelope_with_float = core_events.TempoEnvelope(
... [[0, 60], [1, 30], [2, 60]]
... )
>>> # (2) define with tempo points
>>> tempo_envelope_with_tempo_points = core_events.TempoEnvelope(
>>> # (2) define with tempos
>>> tempo_envelope_with_tempos = core_events.TempoEnvelope(
... [
... [0, core_parameters.DirectTempoPoint(60)],
... [1, core_parameters.DirectTempoPoint(30)],
... [2, core_parameters.WesternTempoPoint(30, reference=2)],
... [0, core_parameters.DirectTempo(60)],
... [1, core_parameters.DirectTempo(30)],
... [2, core_parameters.WesternTempo(30, reference=2)],
... ]
... )
"""
Expand All @@ -856,30 +856,30 @@ def __eq__(self, other: typing.Any):

def event_to_parameter(
self, event: core_events.abc.Event
) -> core_parameters.abc.TempoPoint:
return event.tempo_point
) -> core_parameters.abc.Tempo:
return event.tempo

def value_to_parameter(self, value: float) -> core_parameters.abc.TempoPoint:
return core_parameters.DirectTempoPoint(value)
def value_to_parameter(self, value: float) -> core_parameters.abc.Tempo:
return core_parameters.DirectTempo(value)

def parameter_to_value(
self, parameter: core_parameters.abc.TempoPoint.Type
self, parameter: core_parameters.abc.Tempo.Type
) -> float:
# Here we specify, that we allow either core_parameters.abc.TempoPoint
# Here we specify, that we allow either core_parameters.abc.Tempo
# or float/number objects.
# So in case we have a core_parameters.abc.TempoPoint 'getattr' is
# So in case we have a core_parameters.abc.Tempo 'getattr' is
# successful, if not it will return 'parameter', because it
# will assume that we have a number based tempo point.
# will assume that we have a number based tempo.
return float(
getattr(parameter, "bpm", parameter)
)

def apply_parameter_on_event(
self, event: core_events.abc.Event, parameter: core_parameters.abc.TempoPoint
self, event: core_events.abc.Event, parameter: core_parameters.abc.Tempo
):
event.tempo_point = parameter
event.tempo = parameter

def initialise_default_event_class(
self, duration: core_parameters.abc.Duration
) -> core_events.abc.Event:
return self.default_event_class(tempo_point=1, duration=duration)
return self.default_event_class(tempo=1, duration=duration)
16 changes: 8 additions & 8 deletions mutwo/core_events/tempos.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# This file is part of mutwo, ecosystem for time-based arts.
#
# Copyright (C) 2020-2023
# Copyright (C) 2020-2024
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
Expand Down Expand Up @@ -28,14 +28,14 @@
class TempoChronon(core_events.Chronon):
"""A :class:`TempoChronon` describes the tempo for a given time."""

def __init__(self, tempo_point, *args, **kwargs):
self.tempo_point = tempo_point
def __init__(self, tempo, *args, **kwargs):
self.tempo = tempo
super().__init__(*args, **kwargs)

@property
def tempo_point(self):
return self._tempo_point
def tempo(self):
return self._tempo

@tempo_point.setter
def tempo_point(self, tempo_point):
self._tempo_point = core_parameters.abc.TempoPoint.from_any(tempo_point)
@tempo.setter
def tempo(self, tempo):
self._tempo = core_parameters.abc.Tempo.from_any(tempo)
18 changes: 9 additions & 9 deletions mutwo/core_parameters/abc.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# This file is part of mutwo, ecosystem for time-based arts.
#
# Copyright (C) 2020-2023
# Copyright (C) 2020-2024
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
Expand Down Expand Up @@ -52,7 +52,7 @@
"SingleNumberParameter",
"ParameterWithEnvelope",
"Duration",
"TempoPoint",
"Tempo",
)

T = typing.TypeVar("T", bound="Parameter")
Expand Down Expand Up @@ -383,26 +383,26 @@ def from_any(cls: typing.Type[T], object: Duration.Type) -> T:
raise core_utilities.CannotParseError(object, cls)


class TempoPoint(SingleNumberParameter, value_name="bpm", value_return_type="float"):
class Tempo(SingleNumberParameter, value_name="bpm", value_return_type="float"):
"""Represent the active tempo at a specific moment in time.
If the user wants to define a `TempoPoint` class, the abstract
If the user wants to define a `Tempo` class, the abstract
property :attr:`bpm` needs to be overridden. ``BPM`` is an abbreviation
for 'beats per minute' and the unit of the parameter tempo, see more
information at this `wikipedia article <https://en.wikipedia.org/wiki/Tempo#Measurement>`_.
"""

Type: typing.TypeAlias = typing.Union["TempoPoint", core_constants.Real]
"""TempoPoint.Type hosts all types that are supported by the tempo point
parser :func:`TempoPoint.from_any`."""
Type: typing.TypeAlias = typing.Union["Tempo", core_constants.Real]
"""Tempo.Type hosts all types that are supported by the tempo
parser :func:`Tempo.from_any`."""

@classmethod
def from_any(cls: typing.Type[T], object: TempoPoint.Type) -> T:
def from_any(cls: typing.Type[T], object: Tempo.Type) -> T:
builtin_fraction = _fractions.Fraction if _fractions else fractions.Fraction
match object:
case Tempo():
return object
case float() | int() | fractions.Fraction() | builtin_fraction():
return core_parameters.DirectTempoPoint(object)
return core_parameters.DirectTempo(object)
case _:
raise core_utilities.CannotParseError(object, cls)
8 changes: 4 additions & 4 deletions mutwo/core_parameters/configurations.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# This file is part of mutwo, ecosystem for time-based arts.
#
# Copyright (C) 2020-2023
# Copyright (C) 2020-2024
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
Expand Down Expand Up @@ -37,10 +37,10 @@

DEFAULT_REFERENCE: fractions.Fraction = fractions.Fraction(1, 4)
"""The default value for the 'reference' parameter of
:class:`mutwo.core_parameters.WesternTempoPoint`. By default
:class:`mutwo.core_parameters.WesternTempo`. By default
it is set to 1/4 because it's most common to think that
the tempo in BPM refers to a 1/4 note (so that tempo = 60 BPM
means that a 1/4 beat takes one second). Therefore a tempo
of '60' in :class:`~mutwo.core_parameters.WesternTempoPoint` is
of '60' in :class:`~mutwo.core_parameters.WesternTempo` is
by default 4 times slower than a tempo of '60' in
:class:`~mutwo.core_parameters.DirectTempoPoint`."""
:class:`~mutwo.core_parameters.DirectTempo`."""
18 changes: 9 additions & 9 deletions mutwo/core_parameters/tempos.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# This file is part of mutwo, ecosystem for time-based arts.
#
# Copyright (C) 2020-2023
# Copyright (C) 2020-2024
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
Expand Down Expand Up @@ -30,11 +30,11 @@
from mutwo import core_constants
from mutwo import core_parameters

__all__ = ("DirectTempoPoint", "WesternTempoPoint")
__all__ = ("DirectTempo", "WesternTempo")


class DirectTempoPoint(core_parameters.abc.TempoPoint):
"""Simple `TempoPoint` that is directly initialised by its tempo.
class DirectTempo(core_parameters.abc.Tempo):
"""Simple `Tempo` that is directly initialised by its tempo.
:param tempo: Specify a tempo in `beats per minute <https://en.wikipedia.org/wiki/Tempo#Measurement>`_.
Expand All @@ -43,7 +43,7 @@ class DirectTempoPoint(core_parameters.abc.TempoPoint):
>>> from mutwo import core_events
>>> from mutwo import core_parameters
>>> tempo_envelope = core_events.TempoEnvelope([
... [0, core_parameters.DirectTempoPoint(60)]
... [0, core_parameters.DirectTempo(60)]
... ])
"""

Expand All @@ -59,14 +59,14 @@ def bpm(self, bpm: core_constants.Real | str):
self._bpm = float(bpm)


class WesternTempoPoint(core_parameters.abc.TempoPoint):
"""A tempo point useful for western notation.
class WesternTempo(core_parameters.abc.Tempo):
"""A tempo useful for western notation.
:param bpm_range: Specify a tempo range in
`beats per minute <https://en.wikipedia.org/wiki/Tempo#Measurement>`_.
In western notation tempo is often indicated as a range from the
minimal accepted tempo to the fastest accepted tempo. Therefore
a :class:`WesternTempoPoint` is initialized by a range. In internal
a :class:`WesternTempo` is initialized by a range. In internal
calculations the minimal (slowest) tempo is used. The tempo in
the tempo range is relative as the absolute tempo depends on
the ``reference``.
Expand All @@ -84,7 +84,7 @@ class WesternTempoPoint(core_parameters.abc.TempoPoint):
>>> from mutwo import core_events
>>> from mutwo import core_parameters
>>> tempo_envelope = core_events.TempoEnvelope([
... [0, core_parameters.WesternTempoPoint(60, reference=2)]
... [0, core_parameters.WesternTempo(60, reference=2)]
... ])
"""

Expand Down
Loading

0 comments on commit 5972c97

Please sign in to comment.