Code cleanup and switched back to Sphinx.

This commit is contained in:
Josh W 2021-03-23 09:15:26 -04:00
parent 0340bd6427
commit cca4963dd3
7 changed files with 343 additions and 283 deletions

View file

@ -64,11 +64,8 @@ dev =
cython
flake8
docs =
mkdocs
mkdocs-macros-plugin
mkdocs-material
mkdocstrings
pymdown-extensions
sphinx
sphinx-rtd-theme
[build_ext]
inplace=1

View file

@ -7,74 +7,85 @@ from libc.stdlib cimport malloc, free
class ChannelType(enum.IntEnum):
'''Use these values when setting the channel map with
R128State.set_channel(). See definitions in ITU R-REC-BS 1770-4.
Note:
The ITU-R BS.1770-4 does not include the LFE channel in any of its
algorithms. For this channel, use the `UNUSED` attribute.
'''
Unused = 0 # unused channel (for example LFE channel)
Left = 1
Mplus030 = 1 # itu M+030
Right = 2
Mminus030 = 2 # itu M-030
Center = 3
Mplus000 = 3 # itu M+000
LeftSurround = 4
Mplus110 = 4 # itu M+110
RightSuround = 5
Mminus110 = 5 # itu M-110
DualMono = 6 # a channel that is counted twice
MplusSC = 7 # itu M+SC
MminusSC = 8 # itu M-SC
Mplus060 = 9 # itu M+060
Mminus060 = 10 # itu M-060
Mplus090 = 11 # itu M+090
Mminus090 = 12 # itu M-090
Mplus135 = 13 # itu M+135
Mminus135 = 14 # itu M-135
Mplus180 = 15 # itu M+180
Uplus000 = 16 # itu U+000
Uplus030 = 17 # itu U+030
Uminus030 = 18 # itu U-030
Uplus045 = 19 # itu U+045
Uminus045 = 20 # itu U-030
Uplus090 = 21 # itu U+090
Uminus090 = 22 # itu U-090
Uplus110 = 23 # itu U+110
Uminus110 = 24 # itu U-110
Uplus135 = 25 # itu U+135
Uminus135 = 26 # itu U-135
Uplus180 = 27 # itu U+180
Tplus000 = 28 # itu T+000
Bplus000 = 29 # itu B+000
Bplus045 = 30 # itu B+045
Bminus045 = 31 # itu B-045
UNUSED = 0
LEFT = 1
M_PLUS_030 = 1 # ITU M+030
RIGHT = 2
M_MINUS_030 = 2 # ITU M-030
CENTER = 3
M_PLUS_000 = 3 # ITU M+000
LEFT_SURROUND = 4
M_PLUS_110 = 4 # ITU M+110
RIGHT_SUROUND = 5
M_MINUS_110 = 5 # ITU M-110
DUAL_MONO = 6 # A channel that's counted twice
M_PLUS_SC = 7 # ITU M+SC
M_MINUS_SC = 8 # ITU M-SC
M_PLUS_060 = 9 # ITU M+060
M_MINUS_060 = 10 # ITU M-060
M_PLUS_090 = 11 # ITU M+090
M_MINUS_090 = 12 # ITU M-090
M_PLUS_135 = 13 # ITU M+135
M_MINUS_135 = 14 # ITU M+135
M_PLUS_180 = 15 # ITU M+180
U_PLUS_000 = 16 # ITU U+000
U_PLUS_030 = 17 # ITU U+030
U_MINUS_030 = 18 # ITU U-030
U_PLUS_045 = 19 # ITU U+045
U_MINUS_045 = 20 # ITU U-045
U_PLUS_090 = 21 # ITU U+090
U_MINUS_090 = 22 # ITU U-090
U_PLUS_110 = 23 # ITU U+110
U_MINUS_110 = 24 # ITU U-110
U_PLUS_135 = 25 # ITU U+135
U_MINUS_135 = 26 # ITU U-135
U_PLUS_180 = 27 # ITU U+180
T_PLUS_000 = 28 # ITU T+000
B_PLUS_000 = 29 # ITU B+000
B_PLUS_045 = 30 # ITU B+045
B_MINUS_045 = 31 # ITU B-045
class ErrorCode(enum.IntEnum):
'''Error codes returned by libebur128 functions.'''
Success = 0
OutOfMemory = 1
InvalidMode = 2
InvalidChannelIndex = 3
ValueDidNotChange = 4
'''Error codes returned by libebur128's functions.'''
SUCCESS = 0
OUT_OF_MEMORY = 1
INVALID_MODE = 2
INVALID_CHANNEL_INDEX = 3
VALUE_DID_NOT_CHANGE = 4
class MeasurementMode(enum.IntFlag):
'''Use these values bitwise OR'd when instancing an R128State class.
Try to use the lowest possible modes that suit your needs, as performance
will be better.
'''Various modes of measurement which can be used. These can be bitwise
OR'd together to allow a combination of modes.
'''
# can call get_loudness_momentary
ModeM = (1 << 0)
# can call get_loudness_shortterm
ModeS = (1 << 1) | ModeM
# can call get_loudness_global_* and get_relative_threshold
ModeI = (1 << 2) | ModeM
# can call get_loudness_range
ModeLRA = (1 << 3) | ModeS
# can call get_sample_peak
ModeSamplePeak = (1 << 4) | ModeM
# can call get_true_peak
ModeTruePeak = (1 << 5) | ModeM | ModeSamplePeak
# uses histogram algorithm to calculate loudness
ModeHistogram = (1 << 6)
# Can call get_loudness_momentary.
MODE_M = (1 << 0)
# Can call get_loudness_shortterm and get_loudness_momentary.
MODE_S = (1 << 1) | MODE_M
# Can call get_loudness_global, get_loudness_global_multiple,
# get_relative_threshold, and get_loudness_momentary.
MODE_I = (1 << 2) | MODE_M
# Can call get_loudness_range, get_loudness_shortterm, and
# get_loudness_momentary.
MODE_LRA = (1 << 3) | MODE_S
# Can call get_sample_peak and get_loudness_momentary.
MODE_SAMPLE_PEAK = (1 << 4) | MODE_M
# Can call get_true_peak, get_sample_peak, and get_loudness_momentary.
MODE_TRUE_PEAK = (1 << 5) | MODE_SAMPLE_PEAK | MODE_M
# Uses histogram algorithm to calculate loudness.
MODE_HISTOGRAM = (1 << 6)
ctypedef fused const_frames_array:
@ -85,16 +96,8 @@ ctypedef fused const_frames_array:
cdef class R128State:
'''This is a class representation of an EBU R128 Loudness Measurement State.
:param channels: The number of audio channels used in the measurement.
:type channels: int
:param samplerate: The samplerate in samples per second (or Hz).
:type samplerate: int
:param mode: A bitwise OR'd value from the :class:`Mode` enum. Try to use
the lowest possible modes that suit your needs, as performance will be
better.
:type mode: int
'''This is a class representation of an EBU R128 Loudness Measurement
State.
'''
# Contains information about the state of a loudness measurement.
@ -105,20 +108,36 @@ cdef class R128State:
unsigned int channels,
unsigned long samplerate,
int mode):
'''Initialize library state.
:raises MemoryError: If the underlying C-struct cannot be allocated in
memory.
'''
'''Constructor'''
self._state = ebur128_init(channels, samplerate, mode)
if self._state == NULL:
raise MemoryError('Out of memory.')
def __dealloc__(self):
'''Destroy library state.'''
'''Deconstructor'''
if self._state != NULL:
ebur128_destroy(&self._state)
# For autodoc purposes only.
def __init__(self,
unsigned int channels,
unsigned long samplerate,
int mode):
'''Initialize library state.
Args:
channels (int): The number of audio channels used in the
measurement.
samplerate (int): The samplerate in samples per second (or Hz).
mode (:class:`MeasurementMode` or int): A value from the
:class:`MeasurementMode` enum. Try to use the lowest possible
modes that suit your needs as performance will be better.
Raises:
MemoryError: If the underlying C-struct cannot be allocated in
memory.
'''
def __repr__(self):
'''A nicer way of explaining the object.'''
obj = '<{0}: channels={1}, samplerate={2}, mode={3} at 0x{4:0{5}X}>'
@ -152,9 +171,10 @@ cdef class R128State:
self.change_parameters(self._state.channels, s)
property mode:
''' A bitwise OR'd value from the :class:`Mode` enum. Try to use
the lowest possible modes that suit your needs, as performance will be
better.'''
''' A value from the :class:`MeasurementMode` enum. Try to use the
lowest possible modes that suit your needs, as performance will be
better.
'''
def __get__(self):
'''mode's getter'''
if self._state is not NULL:
@ -170,67 +190,71 @@ cdef class R128State:
'''Sets an audio channel to a specific channel type as defined in the
:class:`ChannelType` enum.
:param channel_number: The zero-based channel index.
:type channel_number: int
:param channel_type: The channel type from :class:`ChannelType`.
:type channel_type: int
Args:
channel_number (int): The zero-based channel index.
channel_type (:class:`ChannelType` or int): The channel type.
:raises IndexError: If specified channel index is out of bounds.
Raises:
IndexError: If specified channel index is out of bounds.
'''
cdef int result
result = ebur128_set_channel(self._state,
channel_number,
channel_type)
if result == ErrorCode.InvalidChannelIndex:
if result == ErrorCode.INVALID_CHANNEL_INDEX:
raise IndexError('Channel index is out of bounds.')
def change_parameters(self,
unsigned int channels,
unsigned long samplerate):
'''Changes number of audio channels and/or the samplerate of the
loudness measurement. Returns an integer error code.
'''Changes the number of audio channels and/or the samplerate of the
measurement state.
Note that the channel map will be reset when setting a different number
of channels. The current unfinished block will be lost.
Note:
The channel map will be reset when setting a different number of
channels. The current unfinished block will be lost.
:param channels: New number of audio channels.
:type channels: int
:param samplerate: The new samplerate in samples per second (or Hz).
:type samplerate: int
Args:
channels (int): New number of audio channels.
samplerate (int): The new samplerate in samples per second (or Hz).
:raises MemoryError: If not enough memory could be allocated for the
new values.
:raises ValueError: If both new values are the same as the currently
stored values.
Raises:
MemoryError: If not enough memory could be allocated for the new
values.
ValueError: If both new values are the same as the currently stored
values.
'''
cdef int result
result = ebur128_change_parameters(self._state,
channels,
samplerate)
if result == ErrorCode.OutOfMemory:
if result == ErrorCode.OUT_OF_MEMORY:
raise MemoryError('Out of memory.')
elif result == ErrorCode.ValueDidNotChange:
elif result == ErrorCode.VALUE_DID_NOT_CHANGE:
raise ValueError('Channel numbers & sample rate have not changed.')
def set_max_window(self, unsigned long window):
'''Set the maximum duration that will be used for
:func:`~pyebur128.get_loudness_window`.
:func:`get_loudness_window`.
Note that this destroys the current content of the audio buffer.
Note:
This will destroy the current content of the audio buffer in the
measurement state.
:param window: The duration of the window in milliseconds (ms).
:type window: int
Args:
window (int): The duration of the window in milliseconds (ms).
:raises MemoryError: If not enough memory could be allocated for the
new value.
:raises ValueError: If the new window value is the same as the
currently stored window value.
Raises:
MemoryError: If not enough memory could be allocated for the new
value.
ValueError: If the new window value is the same as the currently
stored window value.
'''
cdef int result
result = ebur128_set_max_window(self._state, window)
if result == ErrorCode.OutOfMemory:
if result == ErrorCode.OUT_OF_MEMORY:
raise MemoryError('Out of memory.')
elif result == ErrorCode.ValueDidNotChange:
elif result == ErrorCode.VALUE_DID_NOT_CHANGE:
raise ValueError('Maximum window duration has not changed.')
def set_max_history(self, unsigned long history):
@ -238,39 +262,47 @@ cdef class R128State:
More history provides more accurate results, but requires more
resources.
Applies to :func:`~pyebur128.get_loudness_range` and
:func:`~pyebur128.get_loudness_global` when ``ModeHistogram`` is
not set from :class:`pyebur128.MeasurementMode`.
Applies to :func:`get_loudness_range` and :func:`get_loudness_global`
when ``MODE_HISTOGRAM`` is not set from :class:`MeasurementMode`.
Default is ULONG_MAX (at least ~50 days).
Minimum is 3000ms for ``ModeLRA`` and 400ms for ``ModeM``.
Default is ULONG_MAX (approximately 50 days).
Minimum is 3000ms for ``MODE_LRA`` and 400ms for ``MODE_M``.
:param history: The duration of history in milliseconds (ms).
:type history: int
Args:
history (int): The duration of history in milliseconds (ms).
:raises MemoryError: If not enough memory could be allocated for the
new value.
:raises ValueError: If the new history value is the same as the
currently stored history value.
Raises:
MemoryError: If not enough memory could be allocated for the new
value.
ValueError: If the new history value is the same as the currently
stored history value.
'''
cdef int result
result = ebur128_set_max_history(self._state, history)
if result == ErrorCode.ValueDidNotChange:
if result == ErrorCode.VALUE_DID_NOT_CHANGE:
raise ValueError('Maximum history duration has not changed.')
@cython.boundscheck(False)
@cython.wraparound(False)
def add_frames(self, const_frames_array source, size_t frames):
'''Add frames to be processed.
'''Add audio frames to be processed.
:param source: An array of source frames. Channels must be interleaved.
:type source: New buffer protocol (PEP-3118) array of short, int, float,
or double.
:param frames: The number of frames. (Not the number of samples!)
:type frames: int
Note:
The ``source`` argument can be any one-dimensional array that is
compliant with Python's new buffer protocol (PEP-3118). It must
contain values of all `short`, `int`, `float`, or `double`.
:raises MemoryError: If not enough memory could be allocated for the
new frames.
Args:
source (see Note): An array of source frames. Channels must be
interleaved.
frames (int): The number of frames. (NOT the number of samples!)
Raises:
TypeError: If the source array: 1) is not one dimensional, 2) does
not use Python's new buffer protocol, or 3) does not contain
all short, int, float, or double values.
MemoryError: If not enough memory could be allocated for the new
frames.
'''
cdef int result
@ -290,8 +322,15 @@ cdef class R128State:
result = ebur128_add_frames_double(self._state,
&source[0],
frames)
else:
msg = (
'Source array must be one-dimensional, use the new buffer '
'protocol, and value type must be all short, int, float, or '
'double.'
)
raise TypeError(msg)
if result == ErrorCode.OutOfMemory:
if result == ErrorCode.OUT_OF_MEMORY:
raise MemoryError('Out of memory.')
@ -300,19 +339,22 @@ cdef class R128State:
cpdef double get_loudness_global(R128State state):
'''Get the global integrated loudness in LUFS.
:param state: An instance of the :class:`R128State` class.
:type state: R128State
Args:
state (:class:`R128State`): An instance of the :class:`R128State`
class.
:raises ValueError: If Mode ``ModeI`` has not been set.
Raises:
ValueError: If ``MODE_I`` has not been set from
:class:`MeasurementMode`.
:return: The integrated loudness in LUFS.
:rtype: float
Returns:
float: The integrated loudness in LUFS.
'''
cdef double lufs
cdef int result
result = ebur128_loudness_global(state._state, &lufs)
if result == ErrorCode.InvalidMode:
raise ValueError('Mode "ModeI" has not been set.')
if result == ErrorCode.INVALID_MODE:
raise ValueError('MODE_I has not been set.')
return lufs
@ -321,15 +363,18 @@ cpdef double get_loudness_global(R128State state):
cpdef double get_loudness_global_multiple(list states):
'''Get the global integrated loudness in LUFS across multiple instances.
:param state: A list of :class:`R128State` instances.
:type state: list of R128State
Args:
states (list of :class:`R128State`): A list of :class:`R128State`
instances.
:raises MemoryError: If not enough memory could be allocated for the
conversion of a Python list to a C array.
:raises ValueError: If Mode ``ModeI`` has not been set.
Raises:
MemoryError: If not enough memory could be allocated for the conversion
of a Python list to a C array.
ValueError: If ``MODE_I`` has not been set from
:class:`MeasurementMode`.
:return: The integrated loudness in LUFS.
:rtype: float
Returns:
float: The integrated loudness of all states in LUFS.
'''
cdef double lufs
cdef int result
@ -339,15 +384,15 @@ cpdef double get_loudness_global_multiple(list states):
num = len(states)
state_ptrs = <ebur128_state**>malloc(sizeof(ebur128_state*) * num)
if state_ptrs == NULL:
raise MemoryError('Unable to allocate array of R128 states.')
raise MemoryError('Unable to allocate array of states.')
for i in range(num):
state_ptrs[i] = (<R128State?>states[i])._state
result = ebur128_loudness_global_multiple(state_ptrs, num, &lufs)
free(state_ptrs)
if result == ErrorCode.InvalidMode:
raise ValueError('Mode "ModeI" has not been set.')
if result == ErrorCode.INVALID_MODE:
raise ValueError('MODE_I has not been set.')
return lufs
@ -356,11 +401,12 @@ cpdef double get_loudness_global_multiple(list states):
cpdef double get_loudness_momentary(R128State state):
'''Get the momentary loudness (last 400ms) in LUFS.
:param state: An instance of the :class:`R128State` class.
:type state: R128State
Args:
state (:class:`R128State`): An instance of the :class:`R128State`
class.
:return: The momentary loudness in LUFS.
:rtype: float
Returns:
float: The momentary loudness in LUFS.
'''
cdef double lufs
cdef int result
@ -373,44 +419,48 @@ cpdef double get_loudness_momentary(R128State state):
cpdef double get_loudness_shortterm(R128State state):
'''Get the short-term loudness (last 3s) in LUFS.
:param state: An instance of the :class:`R128State` class.
:type state: R128State
Args:
state (:class:`R128State`): An instance of the :class:`R128State`
class.
:raises ValueError: If Mode ``ModeS`` has not been set.
Raises:
ValueError: If ``MODE_S`` has not been set from
:class:`MeasurementMode`.
:return: The short-term loudness in LUFS.
:rtype: float
Returns:
float: The short-term loudness in LUFS.
'''
cdef double lufs
cdef int result
result = ebur128_loudness_shortterm(state._state, &lufs)
if result == ErrorCode.InvalidMode:
raise ValueError('Mode "ModeS" has not been set.')
if result == ErrorCode.INVALID_MODE:
raise ValueError('MODE_S has not been set.')
return lufs
@cython.boundscheck(False)
@cython.wraparound(False)
cpdef double get_loudness_window(R128State state, unsigned long window):
'''Get loudness of the specified window in LUFS.
'''Get the loudness of the specified window in LUFS.
:param state: An instance of the :class:`R128State` class.
:type state: R128State
:param window: The window size in milliseconds (ms) to calculate loudness.
:type window: int
Args:
state (:class:`R128State`): An instance of the :class:`R128State`
class.
window (int): The window size in milliseconds (ms).
:raises ValueError: If the new window size is larger than the current
window size stored in state.
Raises:
ValueError: If the new window size is larger than the current window
size stored in state.
:return: The loudness in LUFS.
:rtype: float
Returns:
float: The loudness in LUFS.
'''
cdef double lufs
cdef int result
result = ebur128_loudness_window(state._state, window, &lufs)
if result == ErrorCode.InvalidMode:
if result == ErrorCode.INVALID_MODE:
msg = (
'Requested window larger than the current '
'Requested window is larger than the current '
'window in the provided state.'
)
raise ValueError(msg)
@ -422,25 +472,27 @@ cpdef double get_loudness_window(R128State state, unsigned long window):
cpdef double get_loudness_range(R128State state):
'''Get loudness range (LRA) of audio in LU.
Calculates loudness range according to EBU 3342.
Calculates the loudness range according to EBU 3342.
:param state: An instance of the :class:`R128State` class.
:type state: R128State
Args:
state (:class:`R128State`): An instance of the :class:`R128State`
class.
:raises MemoryError: If not enough memory could be allocated for the
Raises:
MemoryError: If not enough memory could be allocated for the
measurement.
:raises ValueError: If Mode ``ModeLRA`` has not been set.
ValueError: If ``MODE_LRA`` has not been set.
:return: The loudness range (LRA) in LU.
:rtype: float
Returns:
float: The loudness range (LRA) in LU.
'''
cdef double lufs
cdef int result
result = ebur128_loudness_range(state._state, &lufs)
if result == ErrorCode.OutOfMemory:
if result == ErrorCode.OUT_OF_MEMORY:
raise MemoryError('Memory allocation error.')
elif result == ErrorCode.InvalidMode:
raise ValueError('Mode "ModeLRA" has not been set.')
elif result == ErrorCode.INVALID_MODE:
raise ValueError('MODE_LRA has not been set.')
return lufs
@ -451,16 +503,19 @@ cpdef double get_loudness_range_multiple(list states):
Calculates loudness range according to EBU 3342.
:param state: A list of :class:`R128State` instances.
:type state: list of R128State
Args:
states (list of :class:`R128State`): A list of :class:`R128State`
instances.
:raises MemoryError: If not enough memory could be allocated for the
Raises:
MemoryError: If not enough memory could be allocated for the
measurement or there was a problem with the Python list to C array
conversion.
:raises ValueError: If Mode ``ModeLRA`` has not been set.
ValueError: If ``MODE_LRA`` has not been set from
:class:`MeasurementMode`.
:return: The loudness range (LRA) in LU.
:rtype: float
Returns:
float: The loudness range (LRA) in LU.
'''
cdef double lufs
cdef int result
@ -477,10 +532,10 @@ cpdef double get_loudness_range_multiple(list states):
result = ebur128_loudness_range_multiple(state_ptrs, num, &lufs)
free(state_ptrs)
if result == ErrorCode.OutOfMemory:
if result == ErrorCode.OUT_OF_MEMORY:
raise MemoryError('Memory allocation error.')
elif result == ErrorCode.InvalidMode:
raise ValueError('Mode "ModeLRA" has not been set.')
elif result == ErrorCode.INVALID_MODE:
raise ValueError('MODE_LRA has not been set.')
return lufs
@ -491,23 +546,24 @@ cpdef double get_sample_peak(R128State state, unsigned int channel_number):
The equation to convert to dBFS is: 20 * log10(result).
:param state: An instance of the :class:`R128State` class.
:type state: R128State
:param channel_number: The index of the channel to analyze.
:type channel_number: int
Args:
state (:class:`R128State`): An instance of the :class:`R128State`
class.
channel_number (int): The index of the channel to analyze.
:raises ValueError: If Mode ``ModeSamplePeak`` has not been set or the
channel index is out of bounds.
Raise:
ValueError: If ``MODE_SAMPLE_PEAK`` has not been set or the channel
index is out of bounds.
:return: The maximum sample peak (1.0 is 0 dBFS).
:rtype: float
Returns:
float: The maximum sample peak (1.0 is 0 dBFS).
'''
cdef double max_peak
cdef int result
result = ebur128_sample_peak(state._state, channel_number, &max_peak)
if result == ErrorCode.InvalidMode:
raise ValueError('Mode "ModeSamplePeak" has not been set.')
elif result == ErrorCode.InvalidChannelIndex:
if result == ErrorCode.INVALID_MODE:
raise ValueError('MODE_SAMPLE_PEAK has not been set.')
elif result == ErrorCode.INVALID_CHANNEL_INDEX:
raise ValueError('Invalid channel index provided.')
return max_peak
@ -516,27 +572,29 @@ cpdef double get_sample_peak(R128State state, unsigned int channel_number):
@cython.wraparound(False)
cpdef double get_previous_sample_peak(R128State state,
unsigned int channel_number):
'''Get maximum sample peak from the last call to add_frames().
'''Get maximum sample peak from the last call to
:func:`R128State.add_frames`.
The equation to convert to dBFS is: 20 * log10(result).
:param state: An instance of the :class:`R128State` class.
:type state: R128State
:param channel_number: The index of the channel to analyze.
:type channel_number: int
Args:
state (:class:`R128State`): An instance of the :class:`R128State`
class.
channel_number (int): The index of the channel to analyze.
:raises ValueError: If Mode ``ModeSamplePeak`` has not been set or the
channel index is out of bounds.
Raise:
ValueError: If ``MODE_SAMPLE_PEAK`` has not been set or the channel
index is out of bounds.
:return: The maximum sample peak (1.0 is 0 dBFS).
:rtype: float
Returns:
float: The maximum sample peak (1.0 is 0 dBFS).
'''
cdef double max_peak
cdef int result
result = ebur128_prev_sample_peak(state._state, channel_number, &max_peak)
if result == ErrorCode.InvalidMode:
raise ValueError('Mode "ModeSamplePeak" has not been set.')
elif result == ErrorCode.InvalidChannelIndex:
if result == ErrorCode.INVALID_MODE:
raise ValueError('MODE_SAMPLE_PEAK has not been set.')
elif result == ErrorCode.INVALID_CHANNEL_INDEX:
raise ValueError('Invalid channel index provided.')
return max_peak
@ -556,23 +614,24 @@ cpdef double get_true_peak(R128State state, unsigned int channel_number):
The equation to convert to dBTP is: 20 * log10(out)
:param state: An instance of the :class:`R128State` class.
:type state: R128State
:param channel_number: The index of the channel to analyze.
:type channel_number: int
Args:
state (:class:`R128State`): An instance of the :class:`R128State`
class.
channel_number (int): The index of the channel to analyze.
:raises ValueError: If Mode ``ModeTruePeak`` has not been set or the
channel index is out of bounds.
Raise:
ValueError: If ``MODE_TRUE_PEAK`` has not been set or the channel index
is out of bounds.
:return: The maximum true peak (1.0 is 0 dBTP).
:rtype: float
Returns:
float: The maximum true peak (1.0 is 0 dBTP).
'''
cdef double max_peak
cdef int result
result = ebur128_true_peak(state._state, channel_number, &max_peak)
if result == ErrorCode.InvalidMode:
raise ValueError('Mode "ModeTruePeak" has not been set.')
elif result == ErrorCode.InvalidChannelIndex:
if result == ErrorCode.INVALID_MODE:
raise ValueError('MODE_TRUE_PEAK has not been set.')
elif result == ErrorCode.INVALID_CHANNEL_INDEX:
raise ValueError('Invalid channel index provided.')
return max_peak
@ -581,7 +640,8 @@ cpdef double get_true_peak(R128State state, unsigned int channel_number):
@cython.wraparound(False)
cpdef double get_previous_true_peak(R128State state,
unsigned int channel_number):
'''Get maximum true peak from the last call to add_frames().
'''Get maximum true peak from the last call to
:func:`R128State.add_frames`.
Uses an implementation defined algorithm to calculate the true peak. Do not
try to compare resulting values across different versions of the library,
@ -593,23 +653,24 @@ cpdef double get_previous_true_peak(R128State state,
The equation to convert to dBTP is: 20 * log10(out)
:param state: An instance of the :class:`R128State` class.
:type state: R128State
:param channel_number: The index of the channel to analyze.
:type channel_number: int
Args:
state (:class:`R128State`): An instance of the :class:`R128State`
class.
channel_number (int): The index of the channel to analyze.
:raises ValueError: If Mode ``ModeTruePeak`` has not been set or the
channel index is out of bounds.
Raise:
ValueError: If ``MODE_TRUE_PEAK`` has not been set or the channel index
is out of bounds.
:return: The maximum true peak (1.0 is 0 dBTP).
:rtype: float
Returns:
float: The maximum true peak (1.0 is 0 dBTP).
'''
cdef double max_peak
cdef int result
result = ebur128_prev_true_peak(state._state, channel_number, &max_peak)
if result == ErrorCode.InvalidMode:
raise ValueError('Mode "ModeTruePeak" has not been set.')
elif result == ErrorCode.InvalidChannelIndex:
if result == ErrorCode.INVALID_MODE:
raise ValueError('MODE_TRUE_PEAK has not been set.')
elif result == ErrorCode.INVALID_CHANNEL_INDEX:
raise ValueError('Invalid channel index provided.')
return max_peak
@ -619,29 +680,31 @@ cpdef double get_previous_true_peak(R128State state,
cpdef double get_relative_threshold(R128State state):
'''Get relative threshold in LUFS.
:param state: An instance of the :class:`R128State` class.
:type state: R128State
Args:
state (:class:`R128State`): An instance of the :class:`R128State`
class.
:raises ValueError: If Mode ``ModeI`` has not been set.
Raises:
ValueError: If ``MODE_I`` has not been set.
:return: The relative threshold in LUFS.
:rtype: float
Returns:
float: The relative threshold in LUFS.
'''
cdef double threshold
cdef int result
result = ebur128_relative_threshold(state._state, &threshold)
if result == ErrorCode.InvalidMode:
raise ValueError('Mode "ModeI" has not been set.')
if result == ErrorCode.INVALID_MODE:
raise ValueError('MODE_I has not been set.')
return threshold
cpdef get_libebur128_version():
'''Gets the version number of the compiled libebur128.
:return: The major, minor, and patch numbers of the implemented libebur128
Returns:
str: The major, minor, and patch numbers of the implemented libebur128
version.
:rtype: tuple of int
'''
cdef int major, minor, patch
ebur128_get_version(&major, &minor, &patch)
return major, minor, patch
return '.'.join(map(str, (major, minor, patch)))

View file

@ -10,14 +10,14 @@ import soundfile as sf
def get_single_loudness(filename):
'''Open the WAV file and get the global loudness.'''
with sf.SoundFile(filename) as wav:
state = R128State(wav.channels, wav.samplerate, MeasurementMode.ModeI)
state = R128State(wav.channels, wav.samplerate, MeasurementMode.MODE_I)
if wav.channels == 5:
state.set_channel(0, ChannelType.Left)
state.set_channel(1, ChannelType.Right)
state.set_channel(2, ChannelType.Center)
state.set_channel(3, ChannelType.LeftSurround)
state.set_channel(4, ChannelType.RightSuround)
state.set_channel(0, ChannelType.LEFT)
state.set_channel(1, ChannelType.RIGHT)
state.set_channel(2, ChannelType.CENTER)
state.set_channel(3, ChannelType.LEFT_SURROUND)
state.set_channel(4, ChannelType.RIGHT_SURROUND)
for sample in wav.read():
state.add_frames(sample, 1)

View file

@ -11,14 +11,14 @@ def get_max_loudness_momentary(filename):
with sf.SoundFile(filename) as wav:
state = R128State(wav.channels,
wav.samplerate,
MeasurementMode.ModeM)
MeasurementMode.MODE_M)
if wav.channels == 5:
state.set_channel(0, ChannelType.Left)
state.set_channel(1, ChannelType.Right)
state.set_channel(2, ChannelType.Center)
state.set_channel(3, ChannelType.LeftSurround)
state.set_channel(4, ChannelType.RightSuround)
state.set_channel(0, ChannelType.LEFT)
state.set_channel(1, ChannelType.RIGHT)
state.set_channel(2, ChannelType.CENTER)
state.set_channel(3, ChannelType.LEFT_SURROUND)
state.set_channel(4, ChannelType.RIGHT_SURROUND)
# 10 ms buffer / 100 Hz refresh rate as 10 Hz refresh rate fails on
# several tests.

View file

@ -11,14 +11,14 @@ def get_single_loudness_range(filename):
with sf.SoundFile(filename) as wav:
state = R128State(wav.channels,
wav.samplerate,
MeasurementMode.ModeLRA)
MeasurementMode.MODE_LRA)
if wav.channels == 5:
state.set_channel(0, ChannelType.Left)
state.set_channel(1, ChannelType.Right)
state.set_channel(2, ChannelType.Center)
state.set_channel(3, ChannelType.LeftSurround)
state.set_channel(4, ChannelType.RightSuround)
state.set_channel(0, ChannelType.LEFT)
state.set_channel(1, ChannelType.RIGHT)
state.set_channel(2, ChannelType.CENTER)
state.set_channel(3, ChannelType.LEFT_SURROUND)
state.set_channel(4, ChannelType.RIGHT_SURROUND)
for sample in wav.read():
state.add_frames(sample, 1)

View file

@ -11,14 +11,14 @@ def get_max_loudness_shortterm(filename):
with sf.SoundFile(filename) as wav:
state = R128State(wav.channels,
wav.samplerate,
MeasurementMode.ModeS)
MeasurementMode.MODE_S)
if wav.channels == 5:
state.set_channel(0, ChannelType.Left)
state.set_channel(1, ChannelType.Right)
state.set_channel(2, ChannelType.Center)
state.set_channel(3, ChannelType.LeftSurround)
state.set_channel(4, ChannelType.RightSuround)
state.set_channel(0, ChannelType.LEFT)
state.set_channel(1, ChannelType.RIGHT)
state.set_channel(2, ChannelType.CENTER)
state.set_channel(3, ChannelType.LEFT_SURROUND)
state.set_channel(4, ChannelType.RIGHT_SURROUND)
# 10 ms buffer / 10 Hz refresh rate.
max_shortterm = float('-inf')

View file

@ -13,14 +13,14 @@ def get_max_true_peak(filename):
with sf.SoundFile(filename) as wav:
state = R128State(wav.channels,
wav.samplerate,
MeasurementMode.ModeTruePeak)
MeasurementMode.MODE_TRUE_PEAK)
if wav.channels == 5:
state.set_channel(0, ChannelType.Left)
state.set_channel(1, ChannelType.Right)
state.set_channel(2, ChannelType.Center)
state.set_channel(3, ChannelType.LeftSurround)
state.set_channel(4, ChannelType.RightSuround)
state.set_channel(0, ChannelType.LEFT)
state.set_channel(1, ChannelType.RIGHT)
state.set_channel(2, ChannelType.CENTER)
state.set_channel(3, ChannelType.LEFT_SURROUND)
state.set_channel(4, ChannelType.RIGHT_SURROUND)
for sample in wav.read():
state.add_frames(sample, 1)