From cca4963dd3940666079693dd813aaa10ec776fee Mon Sep 17 00:00:00 2001 From: Josh Washburne Date: Tue, 23 Mar 2021 09:15:26 -0400 Subject: [PATCH] Code cleanup and switched back to Sphinx. --- setup.cfg | 7 +- src/pyebur128/pyebur128.pyx | 559 +++++++++++++++++-------------- tests/test_loudness_global.py | 12 +- tests/test_loudness_momentary.py | 12 +- tests/test_loudness_range.py | 12 +- tests/test_loudness_shortterm.py | 12 +- tests/test_max_true_peak.py | 12 +- 7 files changed, 343 insertions(+), 283 deletions(-) diff --git a/setup.cfg b/setup.cfg index 695d1f2..969c49b 100644 --- a/setup.cfg +++ b/setup.cfg @@ -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 diff --git a/src/pyebur128/pyebur128.pyx b/src/pyebur128/pyebur128.pyx index 7e50f62..4edf34d 100644 --- a/src/pyebur128/pyebur128.pyx +++ b/src/pyebur128/pyebur128.pyx @@ -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 = 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] = (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))) diff --git a/tests/test_loudness_global.py b/tests/test_loudness_global.py index 101fa50..6f889e0 100644 --- a/tests/test_loudness_global.py +++ b/tests/test_loudness_global.py @@ -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) diff --git a/tests/test_loudness_momentary.py b/tests/test_loudness_momentary.py index f45dbc6..2c84c26 100644 --- a/tests/test_loudness_momentary.py +++ b/tests/test_loudness_momentary.py @@ -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. diff --git a/tests/test_loudness_range.py b/tests/test_loudness_range.py index bf0eab6..cf88c4c 100644 --- a/tests/test_loudness_range.py +++ b/tests/test_loudness_range.py @@ -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) diff --git a/tests/test_loudness_shortterm.py b/tests/test_loudness_shortterm.py index 356fea4..7a23479 100644 --- a/tests/test_loudness_shortterm.py +++ b/tests/test_loudness_shortterm.py @@ -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') diff --git a/tests/test_max_true_peak.py b/tests/test_max_true_peak.py index 871f4b1..5cae0ca 100644 --- a/tests/test_max_true_peak.py +++ b/tests/test_max_true_peak.py @@ -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)