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 cython
flake8 flake8
docs = docs =
mkdocs sphinx
mkdocs-macros-plugin sphinx-rtd-theme
mkdocs-material
mkdocstrings
pymdown-extensions
[build_ext] [build_ext]
inplace=1 inplace=1

View file

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

View file

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

View file

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

View file

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

View file

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