Code cleanup and switched back to Sphinx.
This commit is contained in:
parent
0340bd6427
commit
cca4963dd3
7 changed files with 343 additions and 283 deletions
|
@ -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
|
||||
|
|
|
@ -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
|
||||
measurement.
|
||||
:raises ValueError: If Mode ``ModeLRA`` has not been set.
|
||||
Raises:
|
||||
MemoryError: If not enough memory could be allocated for the
|
||||
measurement.
|
||||
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
|
||||
measurement or there was a problem with the Python list to C array
|
||||
conversion.
|
||||
:raises ValueError: If Mode ``ModeLRA`` has not been set.
|
||||
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.
|
||||
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
|
||||
version.
|
||||
:rtype: tuple of int
|
||||
Returns:
|
||||
str: The major, minor, and patch numbers of the implemented libebur128
|
||||
version.
|
||||
'''
|
||||
cdef int major, minor, patch
|
||||
ebur128_get_version(&major, &minor, &patch)
|
||||
return major, minor, patch
|
||||
return '.'.join(map(str, (major, minor, patch)))
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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')
|
||||
|
|
|
@ -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)
|
||||
|
|
Loading…
Add table
Reference in a new issue