hunterHearsPy 1.0.3__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- hunterHearsPy/__init__.py +36 -0
- hunterHearsPy/amplitude.py +170 -0
- hunterHearsPy/autoRevert.py +75 -0
- hunterHearsPy/clippingArrays.py +143 -0
- hunterHearsPy/ioAudio.py +663 -0
- hunterHearsPy/py.typed +0 -0
- hunterHearsPy/theTypes.py +118 -0
- hunterHearsPy/windowingFunctions.py +211 -0
- hunterHearsPy/windowingFunctionsTensor.py +168 -0
- hunterhearspy-1.0.3.dist-info/METADATA +115 -0
- hunterhearspy-1.0.3.dist-info/RECORD +13 -0
- hunterhearspy-1.0.3.dist-info/WHEEL +4 -0
- hunterhearspy-1.0.3.dist-info/licenses/LICENSE +407 -0
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
# ruff: noqa: D104
|
|
2
|
+
from __future__ import annotations
|
|
3
|
+
|
|
4
|
+
from hunterHearsPy.theTypes import (
|
|
5
|
+
ArraySpectrograms as ArraySpectrograms, ArrayType as ArrayType, ArrayWaveforms as ArrayWaveforms,
|
|
6
|
+
callableReturnsNDArray as callableReturnsNDArray, NormalizationReverter as NormalizationReverter,
|
|
7
|
+
ParametersShortTimeFFT as ParametersShortTimeFFT, ParametersSTFT as ParametersSTFT, ParametersUniversal as ParametersUniversal,
|
|
8
|
+
Spectrogram as Spectrogram, SpectrogramDtype as SpectrogramDtype, Waveform as Waveform, WaveformDtype as WaveformDtype,
|
|
9
|
+
WaveformMetadata as WaveformMetadata, WindowingFunction as WindowingFunction, WindowingFunctionDtype as WindowingFunctionDtype)
|
|
10
|
+
|
|
11
|
+
# isort: split
|
|
12
|
+
from hunterHearsPy.amplitude import normalizeArrayWaveforms as normalizeArrayWaveforms, normalizeWaveform as normalizeWaveform
|
|
13
|
+
from hunterHearsPy.clippingArrays import applyHardLimit as applyHardLimit, applyHardLimitComplexValued as applyHardLimitComplexValued
|
|
14
|
+
from hunterHearsPy.windowingFunctions import cosineWings as cosineWings, equalPower as equalPower, halfsine as halfsine, tukey as tukey
|
|
15
|
+
|
|
16
|
+
# isort: split
|
|
17
|
+
from hunterHearsPy.autoRevert import moveToAxisOfOperation as moveToAxisOfOperation
|
|
18
|
+
|
|
19
|
+
# isort: split
|
|
20
|
+
from hunterHearsPy.ioAudio import (
|
|
21
|
+
getWaveformMetadata as getWaveformMetadata, lengthWindowingFunctionDEFAULT as lengthWindowingFunctionDEFAULT,
|
|
22
|
+
loadSpectrograms as loadSpectrograms, loadWaveforms as loadWaveforms, parametersDEFAULT as parametersDEFAULT,
|
|
23
|
+
parametersShortTimeFFTUniversal as parametersShortTimeFFTUniversal, parametersSTFTUniversal as parametersSTFTUniversal,
|
|
24
|
+
readAudioFile as readAudioFile, resampleWaveform as resampleWaveform, setParametersUniversal as setParametersUniversal,
|
|
25
|
+
spectrogramToWAV as spectrogramToWAV, stft as stft, universalDtypeSpectrogram as universalDtypeSpectrogram,
|
|
26
|
+
universalDtypeWaveform as universalDtypeWaveform, waveformSpectrogramWaveform as waveformSpectrogramWaveform,
|
|
27
|
+
windowingFunctionCallableDEFAULT as windowingFunctionCallableDEFAULT,
|
|
28
|
+
windowingFunctionCallableUniversal as windowingFunctionCallableUniversal, writeWAV as writeWAV)
|
|
29
|
+
|
|
30
|
+
# isort: split
|
|
31
|
+
from contextlib import suppress
|
|
32
|
+
|
|
33
|
+
with suppress(ModuleNotFoundError): # noqa: RUF067
|
|
34
|
+
from hunterHearsPy.windowingFunctionsTensor import (
|
|
35
|
+
cosineWingsTensor as cosineWingsTensor, equalPowerTensor as equalPowerTensor, halfsineTensor as halfsineTensor,
|
|
36
|
+
tukeyTensor as tukeyTensor)
|
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
"""Normalize audio waveform amplitudes.
|
|
2
|
+
|
|
3
|
+
(AI generated docstring)
|
|
4
|
+
|
|
5
|
+
You can use this module to scale audio waveforms to a target peak amplitude. Each normalization
|
|
6
|
+
function returns both the scaled waveform and a reversion callable that restores the original
|
|
7
|
+
amplitude scale when applied to any waveform derived from the normalized result.
|
|
8
|
+
|
|
9
|
+
Contents
|
|
10
|
+
--------
|
|
11
|
+
Functions
|
|
12
|
+
normalizeArrayWaveforms
|
|
13
|
+
Normalize multiple waveforms in an array to a specified peak amplitude.
|
|
14
|
+
normalizeWaveform
|
|
15
|
+
Normalize a waveform to a specified peak amplitude.
|
|
16
|
+
|
|
17
|
+
"""
|
|
18
|
+
from __future__ import annotations
|
|
19
|
+
|
|
20
|
+
from numpy import divide, finfo as numpy_finfo, max as numpy_max, multiply
|
|
21
|
+
from typing import cast, overload, TYPE_CHECKING
|
|
22
|
+
|
|
23
|
+
if TYPE_CHECKING:
|
|
24
|
+
from hunterHearsPy import ArrayWaveforms, NormalizationReverter, Waveform
|
|
25
|
+
|
|
26
|
+
def normalizeWaveform(waveform: Waveform, amplitudeNorm: float = 1.0) -> tuple[Waveform, NormalizationReverter]:
|
|
27
|
+
"""Normalize a waveform to a specified peak amplitude.
|
|
28
|
+
|
|
29
|
+
(AI generated docstring)
|
|
30
|
+
|
|
31
|
+
You can use this function to scale a `Waveform` [1] so that its absolute peak value equals
|
|
32
|
+
`amplitudeNorm`. This function also returns `revertNormalization`, a `NormalizationReverter` [2]
|
|
33
|
+
callable that reverses the scaling when applied to any waveform derived from `waveformNormalized`.
|
|
34
|
+
|
|
35
|
+
Parameters
|
|
36
|
+
----------
|
|
37
|
+
waveform : Waveform
|
|
38
|
+
The input audio waveform to normalize.
|
|
39
|
+
amplitudeNorm : float = 1.0
|
|
40
|
+
Target peak amplitude. The absolute maximum value of `waveformNormalized` equals `amplitudeNorm`.
|
|
41
|
+
|
|
42
|
+
Returns
|
|
43
|
+
-------
|
|
44
|
+
waveformNormalized : Waveform
|
|
45
|
+
The scaled waveform with absolute peak value equal to `amplitudeNorm`.
|
|
46
|
+
revertNormalization : NormalizationReverter
|
|
47
|
+
A callable that reverses the normalization scaling. Apply `revertNormalization` to any
|
|
48
|
+
waveform derived from `waveformNormalized` to restore the original amplitude scale.
|
|
49
|
+
|
|
50
|
+
Warns
|
|
51
|
+
-----
|
|
52
|
+
UserWarning
|
|
53
|
+
If `amplitudeNorm` is 0, `normalizeWaveform` replaces it with the smallest positive finite
|
|
54
|
+
value representable in the dtype of `waveform` using `numpy.finfo` [3] and continues.
|
|
55
|
+
UserWarning
|
|
56
|
+
If `waveform` contains only zeros, `waveformNormalized` will also be all zeros.
|
|
57
|
+
`revertNormalization` will divide by `amplitudeNorm` rather than by the waveform peak.
|
|
58
|
+
|
|
59
|
+
See Also
|
|
60
|
+
--------
|
|
61
|
+
`normalizeArrayWaveforms`
|
|
62
|
+
Normalize multiple waveforms in an array to a specified peak amplitude.
|
|
63
|
+
|
|
64
|
+
Amplitude Scaling
|
|
65
|
+
-----------------
|
|
66
|
+
`normalizeWaveform` computes the absolute peak of `waveform` as the maximum of `waveform.max()`
|
|
67
|
+
and `-waveform.min()`, then multiplies every sample by `amplitudeNorm / peakAbsolute`.
|
|
68
|
+
`revertNormalization` reverses this by dividing every sample by the same factor.
|
|
69
|
+
|
|
70
|
+
Examples
|
|
71
|
+
--------
|
|
72
|
+
Normalize a waveform and revert the normalization:
|
|
73
|
+
|
|
74
|
+
```python
|
|
75
|
+
from hunterHearsPy import normalizeWaveform
|
|
76
|
+
|
|
77
|
+
waveformNormalized, revertNormalization = normalizeWaveform(waveform.copy())
|
|
78
|
+
waveformReverted = revertNormalization(waveformNormalized)
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
References
|
|
82
|
+
----------
|
|
83
|
+
[1] `hunterHearsPy.theTypes.Waveform`
|
|
84
|
+
|
|
85
|
+
[2] `hunterHearsPy.theTypes.NormalizationReverter`
|
|
86
|
+
|
|
87
|
+
[3] numpy.finfo - NumPy reference
|
|
88
|
+
https://numpy.org/doc/stable/reference/generated/numpy.finfo.html
|
|
89
|
+
|
|
90
|
+
"""
|
|
91
|
+
amplitudeNorm = amplitudeNorm or float(numpy_finfo(waveform.dtype).tiny.astype(waveform.dtype))
|
|
92
|
+
|
|
93
|
+
peakAbsolute: float = abs(float(numpy_max([waveform.max(), -waveform.min()]))) or 1.0
|
|
94
|
+
amplitudeAdjustment: float = amplitudeNorm / peakAbsolute
|
|
95
|
+
|
|
96
|
+
multiply(waveform, amplitudeAdjustment, out=waveform)
|
|
97
|
+
|
|
98
|
+
@overload
|
|
99
|
+
def revertNormalization(waveformDescendant: Waveform) -> Waveform: ...
|
|
100
|
+
@overload
|
|
101
|
+
def revertNormalization(waveformDescendant: ArrayWaveforms) -> ArrayWaveforms: ...
|
|
102
|
+
def revertNormalization(waveformDescendant: ArrayWaveforms | Waveform) -> ArrayWaveforms | Waveform:
|
|
103
|
+
return divide(waveformDescendant, amplitudeAdjustment, out=waveformDescendant)
|
|
104
|
+
return waveform, revertNormalization
|
|
105
|
+
|
|
106
|
+
def normalizeArrayWaveforms(arrayWaveforms: ArrayWaveforms, amplitudeNorm: float = 1.0) -> tuple[ArrayWaveforms, list[NormalizationReverter]]:
|
|
107
|
+
"""Normalize multiple waveforms in an array to a specified peak amplitude.
|
|
108
|
+
|
|
109
|
+
(AI generated docstring)
|
|
110
|
+
|
|
111
|
+
You can use this function to scale each `Waveform` [1] in an `ArrayWaveforms` [2] so that
|
|
112
|
+
each waveform's absolute peak value equals `amplitudeNorm`. This function also returns
|
|
113
|
+
`listRevertNormalization`, a list of `NormalizationReverter` [3] callables, one per waveform,
|
|
114
|
+
that each reverse the scaling for the corresponding waveform at the matching last-axis index.
|
|
115
|
+
|
|
116
|
+
`normalizeArrayWaveforms` delegates each individual waveform normalization to
|
|
117
|
+
`normalizeWaveform` [4] and modifies `arrayWaveforms` in place before returning it.
|
|
118
|
+
|
|
119
|
+
Parameters
|
|
120
|
+
----------
|
|
121
|
+
arrayWaveforms : ArrayWaveforms
|
|
122
|
+
Array containing multiple waveforms indexed on the last axis. Shape is
|
|
123
|
+
(channels, samples, waveforms).
|
|
124
|
+
amplitudeNorm : float = 1.0
|
|
125
|
+
Target peak amplitude. The absolute maximum value of each normalized waveform equals
|
|
126
|
+
`amplitudeNorm`.
|
|
127
|
+
|
|
128
|
+
Returns
|
|
129
|
+
-------
|
|
130
|
+
arrayWaveformsNormalized : ArrayWaveforms
|
|
131
|
+
The array of normalized waveforms, identical to `arrayWaveforms` modified in place.
|
|
132
|
+
Each waveform is scaled to peak amplitude `amplitudeNorm`.
|
|
133
|
+
listRevertNormalization : list[NormalizationReverter]
|
|
134
|
+
A list of callables indexed in the same order as the last axis of `arrayWaveforms`.
|
|
135
|
+
Each callable reverses the normalization scaling for the corresponding waveform.
|
|
136
|
+
|
|
137
|
+
See Also
|
|
138
|
+
--------
|
|
139
|
+
`normalizeWaveform`
|
|
140
|
+
Normalize a single waveform to a specified peak amplitude.
|
|
141
|
+
|
|
142
|
+
Examples
|
|
143
|
+
--------
|
|
144
|
+
Normalize all waveforms in an array and revert each one:
|
|
145
|
+
|
|
146
|
+
```python
|
|
147
|
+
from hunterHearsPy import normalizeArrayWaveforms
|
|
148
|
+
|
|
149
|
+
arrayNormalized, listRevertNormalization = normalizeArrayWaveforms(arrayWaveforms.copy())
|
|
150
|
+
for indexWaveform in range(arrayNormalized.shape[-1]):
|
|
151
|
+
arrayReverted[..., indexWaveform] = listRevertNormalization[indexWaveform](
|
|
152
|
+
arrayReverted[..., indexWaveform]
|
|
153
|
+
)
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
References
|
|
157
|
+
----------
|
|
158
|
+
[1] `hunterHearsPy.theTypes.Waveform`
|
|
159
|
+
|
|
160
|
+
[2] `hunterHearsPy.theTypes.ArrayWaveforms`
|
|
161
|
+
|
|
162
|
+
[3] `hunterHearsPy.theTypes.NormalizationReverter`
|
|
163
|
+
|
|
164
|
+
[4] `normalizeWaveform`
|
|
165
|
+
|
|
166
|
+
"""
|
|
167
|
+
listRevertNormalization: list[NormalizationReverter] = [lambda makeTypeCheckerHappy: makeTypeCheckerHappy] * arrayWaveforms.shape[-1]
|
|
168
|
+
for index in range(arrayWaveforms.shape[-1]):
|
|
169
|
+
arrayWaveforms[..., index], listRevertNormalization[index] = normalizeWaveform(cast("Waveform", arrayWaveforms[..., index]), amplitudeNorm)
|
|
170
|
+
return arrayWaveforms, listRevertNormalization
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
"""Temporarily reposition array axes and restore the original axis order on context exit.
|
|
2
|
+
|
|
3
|
+
Contents
|
|
4
|
+
--------
|
|
5
|
+
Functions
|
|
6
|
+
moveToAxisOfOperation
|
|
7
|
+
Move an array axis to an operation position, then automatically restore the original axis order on exit.
|
|
8
|
+
|
|
9
|
+
"""
|
|
10
|
+
from __future__ import annotations
|
|
11
|
+
|
|
12
|
+
from contextlib import contextmanager
|
|
13
|
+
from hunterHearsPy import normalizeWaveform
|
|
14
|
+
from numpy import moveaxis
|
|
15
|
+
from typing import TYPE_CHECKING
|
|
16
|
+
|
|
17
|
+
if TYPE_CHECKING:
|
|
18
|
+
from collections.abc import Generator
|
|
19
|
+
from hunterHearsPy import ArrayType, Waveform
|
|
20
|
+
|
|
21
|
+
@contextmanager
|
|
22
|
+
def moveToAxisOfOperation(arrayTarget: ArrayType, axisSource: int, axisOfOperation: int = -1) -> Generator[ArrayType]:
|
|
23
|
+
"""Move an array axis to an operation position, then automatically restore the original axis order on exit.
|
|
24
|
+
|
|
25
|
+
You can use `moveToAxisOfOperation` as a context manager to temporarily rearrange the axes of
|
|
26
|
+
`arrayTarget`. The context yields `arrayStandardized`, a `numpy.moveaxis` [1] view of `arrayTarget`
|
|
27
|
+
with `axisSource` moved to `axisOfOperation`. Because `arrayStandardized` shares memory with
|
|
28
|
+
`arrayTarget`, modifications to `arrayStandardized` inside the context are reflected in `arrayTarget`.
|
|
29
|
+
When the context exits, `arrayTarget` retains its original axis order.
|
|
30
|
+
|
|
31
|
+
Parameters
|
|
32
|
+
----------
|
|
33
|
+
arrayTarget : ArrayType
|
|
34
|
+
The array whose axis to move.
|
|
35
|
+
axisSource : int
|
|
36
|
+
The source axis position to move. Negative values count from the last axis.
|
|
37
|
+
axisOfOperation : int = -1
|
|
38
|
+
The destination axis position for `axisSource`. Negative values count from the last axis.
|
|
39
|
+
|
|
40
|
+
Yields
|
|
41
|
+
------
|
|
42
|
+
arrayStandardized : ArrayType
|
|
43
|
+
A view of `arrayTarget` with `axisSource` at position `axisOfOperation`.
|
|
44
|
+
|
|
45
|
+
Examples
|
|
46
|
+
--------
|
|
47
|
+
Move axis 0 to the last position and modify values inside the context:
|
|
48
|
+
|
|
49
|
+
```python
|
|
50
|
+
import numpy
|
|
51
|
+
from hunterHearsPy import moveToAxisOfOperation
|
|
52
|
+
|
|
53
|
+
arrayAxisOperation = numpy.arange(24).reshape(2, 3, 4)
|
|
54
|
+
with moveToAxisOfOperation(arrayAxisOperation, axisSource=0, axisOfOperation=-1) as arrayStandardized:
|
|
55
|
+
arrayStandardized += 10
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
References
|
|
59
|
+
----------
|
|
60
|
+
[1] numpy.moveaxis
|
|
61
|
+
https://numpy.org/doc/stable/reference/generated/numpy.moveaxis.html
|
|
62
|
+
|
|
63
|
+
"""
|
|
64
|
+
arrayStandardized: ArrayType = moveaxis(arrayTarget, axisSource, axisOfOperation)
|
|
65
|
+
try:
|
|
66
|
+
yield arrayStandardized
|
|
67
|
+
finally:
|
|
68
|
+
moveaxis(arrayStandardized, axisOfOperation, axisSource)
|
|
69
|
+
|
|
70
|
+
"""
|
|
71
|
+
@contextmanager
|
|
72
|
+
def normalizeUnnormalize(waveform: Waveform, amplitudeNorm: float = 1.0):
|
|
73
|
+
pass
|
|
74
|
+
"""
|
|
75
|
+
# C:\apps\loudnessWeightedSpectrogram\loudnessWeightedSpectrogram\spectrogram.py
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
"""Clip and limit array values using magnitude-based hard limits.
|
|
2
|
+
|
|
3
|
+
(AI generated docstring)
|
|
4
|
+
|
|
5
|
+
You can use this module to apply hard clipping [1] to NumPy [2] arrays, constraining element
|
|
6
|
+
magnitudes within bounds defined by a comparand array. The module is not yet fully implemented
|
|
7
|
+
and may not correctly handle all cases.
|
|
8
|
+
|
|
9
|
+
Contents
|
|
10
|
+
--------
|
|
11
|
+
Functions
|
|
12
|
+
applyHardLimit
|
|
13
|
+
Clip the elements of a real-valued array to stay within the magnitude of a comparand.
|
|
14
|
+
applyHardLimitComplexValued
|
|
15
|
+
Clip the elements of a complex-valued array using magnitude-based scaling.
|
|
16
|
+
|
|
17
|
+
References
|
|
18
|
+
----------
|
|
19
|
+
[1] Clipping (signal processing) - Wikipedia
|
|
20
|
+
https://en.wikipedia.org/wiki/Clipping_(signal_processing)
|
|
21
|
+
|
|
22
|
+
[2] NumPy
|
|
23
|
+
https://numpy.org/doc/stable/
|
|
24
|
+
"""
|
|
25
|
+
from __future__ import annotations
|
|
26
|
+
|
|
27
|
+
from numpy import absolute, complexfloating, float64, floating, multiply, ones_like
|
|
28
|
+
from typing import Any, TYPE_CHECKING
|
|
29
|
+
|
|
30
|
+
if TYPE_CHECKING:
|
|
31
|
+
from hunterHearsPy import ArrayType
|
|
32
|
+
from numpy.typing import ArrayLike, NDArray
|
|
33
|
+
|
|
34
|
+
def applyHardLimit(arrayTarget: ArrayType, comparand: ArrayLike = 1.0) -> ArrayType:
|
|
35
|
+
"""Clip the elements of `arrayTarget` to the magnitude bounds defined by `comparand`.
|
|
36
|
+
|
|
37
|
+
This function applies a hard amplitude limit element-wise to `arrayTarget`. Elements whose
|
|
38
|
+
magnitude exceeds the corresponding magnitude of `comparand` are reduced toward zero until
|
|
39
|
+
the element magnitude equals the comparand magnitude. The operation modifies `arrayTarget`
|
|
40
|
+
in place and returns a reference to it.
|
|
41
|
+
|
|
42
|
+
Parameters
|
|
43
|
+
----------
|
|
44
|
+
arrayTarget : ArrayType
|
|
45
|
+
The array to clip. Modified in place.
|
|
46
|
+
comparand : ArrayLike = 1.0
|
|
47
|
+
The magnitude threshold. Elements of `arrayTarget` whose magnitude strictly exceeds the
|
|
48
|
+
corresponding magnitude in `comparand` are clipped to that comparand magnitude.
|
|
49
|
+
|
|
50
|
+
Returns
|
|
51
|
+
-------
|
|
52
|
+
arrayClipped : ArrayType
|
|
53
|
+
A reference to the modified `arrayTarget`.
|
|
54
|
+
|
|
55
|
+
See Also
|
|
56
|
+
--------
|
|
57
|
+
`applyHardLimitComplexValued`
|
|
58
|
+
Clip complex-valued array elements using magnitude-based scaling.
|
|
59
|
+
|
|
60
|
+
References
|
|
61
|
+
----------
|
|
62
|
+
[1] Clipping (signal processing) - Wikipedia
|
|
63
|
+
https://en.wikipedia.org/wiki/Clipping_(signal_processing)
|
|
64
|
+
|
|
65
|
+
[2] numpy.typing.NDArray
|
|
66
|
+
https://numpy.org/doc/stable/reference/typing.html#numpy.typing.NDArray
|
|
67
|
+
|
|
68
|
+
[3] numpy.typing.ArrayLike
|
|
69
|
+
https://numpy.org/doc/stable/reference/typing.html#numpy.typing.ArrayLike
|
|
70
|
+
|
|
71
|
+
"""
|
|
72
|
+
maskTrueAboveThreshold = absolute(comparand) - absolute(arrayTarget) < 0.0
|
|
73
|
+
reduction = arrayTarget - (absolute(arrayTarget) - absolute(comparand))
|
|
74
|
+
arrayTarget[maskTrueAboveThreshold] = reduction[maskTrueAboveThreshold]
|
|
75
|
+
return arrayTarget
|
|
76
|
+
|
|
77
|
+
def applyHardLimitComplexValued(
|
|
78
|
+
arrayTarget: ArrayType,
|
|
79
|
+
comparand: NDArray[floating[Any] | complexfloating[Any, Any]],
|
|
80
|
+
penalty: float = 1.0
|
|
81
|
+
) -> ArrayType:
|
|
82
|
+
"""Clip the elements of complex-valued `arrayTarget` by scaling magnitudes to stay within `comparand`.
|
|
83
|
+
|
|
84
|
+
This function applies a magnitude-based hard limit to each element of `arrayTarget`. When the
|
|
85
|
+
magnitude of an element strictly exceeds the corresponding value in `comparand`, the element is
|
|
86
|
+
scaled down by a power of the ratio of comparand magnitude to target magnitude. Elements whose
|
|
87
|
+
magnitudes are within the limit are left unchanged. This function returns a new array and does
|
|
88
|
+
not modify `arrayTarget` in place.
|
|
89
|
+
|
|
90
|
+
Parameters
|
|
91
|
+
----------
|
|
92
|
+
arrayTarget : NDArray[complexfloating[Any, Any]]
|
|
93
|
+
The complex-valued array to clip.
|
|
94
|
+
comparand : NDArray[floating[Any] | complexfloating[Any, Any]]
|
|
95
|
+
The magnitude threshold array. Only the magnitudes of `comparand` values are used.
|
|
96
|
+
penalty : float = 1.0
|
|
97
|
+
Exponent applied to the scaling factor when limiting is needed. Values greater than 1.0
|
|
98
|
+
produce more aggressive clipping; values between 0.0 and 1.0 produce less aggressive clipping.
|
|
99
|
+
|
|
100
|
+
Returns
|
|
101
|
+
-------
|
|
102
|
+
arrayResult : NDArray[complexfloating[Any, Any]]
|
|
103
|
+
A new array with the same shape and dtype as `arrayTarget`, with element magnitudes
|
|
104
|
+
clipped according to `comparand`.
|
|
105
|
+
|
|
106
|
+
See Also
|
|
107
|
+
--------
|
|
108
|
+
`applyHardLimit`
|
|
109
|
+
Clip real-valued array elements to stay within the magnitude of a comparand.
|
|
110
|
+
|
|
111
|
+
Mathematics
|
|
112
|
+
-----------
|
|
113
|
+
magnitude scaling : equation
|
|
114
|
+
```
|
|
115
|
+
Let a ≜ `arrayTarget`, c ≜ `comparand`, p ≜ `penalty`,
|
|
116
|
+
s ≜ (|cᵢ| / |aᵢ|)
|
|
117
|
+
|
|
118
|
+
For each element i where |aᵢ| > |cᵢ|:
|
|
119
|
+
resultᵢ = aᵢ × sᵖ
|
|
120
|
+
|
|
121
|
+
For each element i where |aᵢ| ≤ |cᵢ|:
|
|
122
|
+
resultᵢ = aᵢ
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
References
|
|
126
|
+
----------
|
|
127
|
+
[1] Clipping (signal processing) - Wikipedia
|
|
128
|
+
https://en.wikipedia.org/wiki/Clipping_(signal_processing)
|
|
129
|
+
|
|
130
|
+
[2] numpy.typing.NDArray
|
|
131
|
+
https://numpy.org/doc/stable/reference/typing.html#numpy.typing.NDArray
|
|
132
|
+
|
|
133
|
+
"""
|
|
134
|
+
magnitudeArrayTarget: NDArray[float64] = absolute(arrayTarget, dtype=float64)
|
|
135
|
+
magnitudeComparand: NDArray[float64] = absolute(comparand, dtype=float64)
|
|
136
|
+
|
|
137
|
+
maskTrueAboveThreshold = magnitudeComparand - magnitudeArrayTarget < 0.0
|
|
138
|
+
|
|
139
|
+
arrayCoefficients_Float64: NDArray[float64] = magnitudeComparand[maskTrueAboveThreshold] / magnitudeArrayTarget[maskTrueAboveThreshold]
|
|
140
|
+
arrayCoefficients_ComplexValued: ArrayType = ones_like(arrayTarget, dtype=arrayTarget.dtype)
|
|
141
|
+
arrayCoefficients_ComplexValued[maskTrueAboveThreshold] = arrayCoefficients_Float64**penalty
|
|
142
|
+
|
|
143
|
+
return multiply(arrayTarget, arrayCoefficients_ComplexValued)
|