hunterHearsPy 1.0.0__tar.gz → 1.0.3__tar.gz

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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: hunterHearsPy
3
- Version: 1.0.0
3
+ Version: 1.0.3
4
4
  Summary: Audio processing.
5
5
  Keywords:
6
6
  Author: Hunter Hogan
@@ -16,10 +16,11 @@ Classifier: Operating System :: OS Independent
16
16
  Classifier: Programming Language :: Python :: 3.10
17
17
  Classifier: Programming Language :: Python :: 3.14
18
18
  Classifier: Typing :: Typed
19
+ Requires-Dist: huntermakespy>=0.7.0
19
20
  Requires-Dist: numpy
20
21
  Requires-Dist: resampy
21
22
  Requires-Dist: scipy
22
- Requires-Dist: soundfile
23
+ Requires-Dist: soundfile>=0.14.0
23
24
  Requires-Dist: tqdm
24
25
  Requires-Dist: torch ; extra == 'torch'
25
26
  Maintainer: Hunter Hogan
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "hunterHearsPy"
3
- version = "1.0.0"
3
+ version = "1.0.3"
4
4
  description = "Audio processing."
5
5
  readme = "README.md"
6
6
  requires-python = ">=3.10"
@@ -20,7 +20,14 @@ classifiers = [
20
20
  "Programming Language :: Python :: 3.14",
21
21
  "Typing :: Typed",
22
22
  ]
23
- dependencies = ["numpy", "resampy", "scipy", "soundfile", "tqdm"]
23
+ dependencies = [
24
+ "hunterMakesPy>=0.7.0",
25
+ "numpy",
26
+ "resampy",
27
+ "scipy",
28
+ "soundfile>=0.14.0",
29
+ "tqdm",
30
+ ]
24
31
  optional-dependencies = { torch = ["torch"] }
25
32
 
26
33
  [project.urls]
@@ -3,17 +3,19 @@ from __future__ import annotations
3
3
 
4
4
  from hunterHearsPy.theTypes import (
5
5
  ArraySpectrograms as ArraySpectrograms, ArrayType as ArrayType, ArrayWaveforms as ArrayWaveforms,
6
- NormalizationReverter as NormalizationReverter, ParametersShortTimeFFT as ParametersShortTimeFFT, ParametersSTFT as ParametersSTFT,
7
- ParametersUniversal as ParametersUniversal, Spectrogram as Spectrogram, SpectrogramDtype as SpectrogramDtype, Waveform as Waveform,
8
- WaveformDtype as WaveformDtype, WaveformMetadata as WaveformMetadata, WindowingFunction as WindowingFunction,
9
- WindowingFunctionDtype as WindowingFunctionDtype, as )
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
10
 
11
11
  # isort: split
12
12
  from hunterHearsPy.amplitude import normalizeArrayWaveforms as normalizeArrayWaveforms, normalizeWaveform as normalizeWaveform
13
- from hunterHearsPy.autoRevert import moveToAxisOfOperation as moveToAxisOfOperation
14
13
  from hunterHearsPy.clippingArrays import applyHardLimit as applyHardLimit, applyHardLimitComplexValued as applyHardLimitComplexValued
15
14
  from hunterHearsPy.windowingFunctions import cosineWings as cosineWings, equalPower as equalPower, halfsine as halfsine, tukey as tukey
16
15
 
16
+ # isort: split
17
+ from hunterHearsPy.autoRevert import moveToAxisOfOperation as moveToAxisOfOperation
18
+
17
19
  # isort: split
18
20
  from hunterHearsPy.ioAudio import (
19
21
  getWaveformMetadata as getWaveformMetadata, lengthWindowingFunctionDEFAULT as lengthWindowingFunctionDEFAULT,
@@ -30,5 +32,5 @@ from contextlib import suppress
30
32
 
31
33
  with suppress(ModuleNotFoundError): # noqa: RUF067
32
34
  from hunterHearsPy.windowingFunctionsTensor import (
33
- callableReturnsNDArray as callableReturnsNDArray, cosineWingsTensor as cosineWingsTensor, equalPowerTensor as equalPowerTensor,
34
- halfsineTensor as halfsineTensor, tukeyTensor as tukeyTensor)
35
+ cosineWingsTensor as cosineWingsTensor, equalPowerTensor as equalPowerTensor, halfsineTensor as halfsineTensor,
36
+ tukeyTensor as tukeyTensor)
@@ -9,24 +9,24 @@ arrays shaped `(channels, samples)`. All spectrograms are complex 64-bit float
9
9
  Contents
10
10
  --------
11
11
  Functions
12
- getWaveformMetadata
13
- Retrieve metadata for a collection of audio waveform files.
14
- loadSpectrograms
15
- Load spectrograms from a list of audio files.
16
- loadWaveforms
17
- Load a list of audio files into a single stacked NumPy array.
18
- readAudioFile
19
- Read an audio file and return stereo waveform data as a NumPy array.
20
- resampleWaveform
21
- Resample a waveform array to a target sample rate.
22
- spectrogramToWAV
23
- Write a complex spectrogram to a WAV file.
24
- stft
25
- Perform Short-Time Fourier Transform or its inverse on waveform or spectrogram data.
26
- waveformSpectrogramWaveform
27
- Decorate a spectrogram-processing callable to accept and return waveforms.
28
- writeWAV
29
- Write a waveform array to a WAV file.
12
+ getWaveformMetadata
13
+ Retrieve metadata for a collection of audio waveform files.
14
+ loadSpectrograms
15
+ Load spectrograms from a list of audio files.
16
+ loadWaveforms
17
+ Load a list of audio files into a single stacked NumPy array.
18
+ readAudioFile
19
+ Read an audio file and return stereo waveform data as a NumPy array.
20
+ resampleWaveform
21
+ Resample a waveform array to a target sample rate.
22
+ spectrogramToWAV
23
+ Write a complex spectrogram to a WAV file.
24
+ stft
25
+ Perform Short-Time Fourier Transform or its inverse on waveform or spectrogram data.
26
+ waveformSpectrogramWaveform
27
+ Decorate a spectrogram-processing callable to accept and return waveforms.
28
+ writeWAV
29
+ Write a waveform array to a WAV file.
30
30
 
31
31
  """
32
32
  from __future__ import annotations
@@ -34,6 +34,7 @@ from __future__ import annotations
34
34
  from hunterHearsPy import (
35
35
  ArraySpectrograms, ArrayWaveforms, halfsine, ParametersShortTimeFFT, ParametersSTFT, ParametersUniversal, Spectrogram, Waveform,
36
36
  WaveformMetadata, WindowingFunction)
37
+ from hunterMakesPy.filesystemToolkit import makeDirectorySafely
37
38
  from math import ceil as ceiling, log2 as log_base2
38
39
  from multiprocessing import set_start_method as multiprocessing_set_start_method
39
40
  from numpy import complex64, dtype, float32, floating, ndarray
@@ -48,7 +49,6 @@ if TYPE_CHECKING:
48
49
  from collections.abc import Callable, Sequence
49
50
  from os import PathLike
50
51
 
51
- # When to use multiprocessing.set_start_method https://github.com/hunterhogan/mapFolding/issues/6
52
52
  if __name__ == '__main__':
53
53
  multiprocessing_set_start_method('spawn')
54
54
 
@@ -138,19 +138,18 @@ def getWaveformMetadata(listPathFilenames: Sequence[str | PathLike[str]], sample
138
138
  def readAudioFile(pathFilename: str | PathLike[Any] | BinaryIO, sampleRate: float | None = None) -> Waveform:
139
139
  """Read an audio file and return stereo waveform data as a NumPy array.
140
140
 
141
- You can use this function to load any audio file that `soundfile` [1] supports. The
142
- returned `Waveform` [2] is always shaped `(channels, samples)` where `channels` is `2`.
143
- When the source file is mono, `readAudioFile` duplicates the single channel to produce
144
- a stereo array. When `sampleRate` differs from the file's native sample rate,
145
- `readAudioFile` resamples using `resampleWaveform`.
141
+ You can use this function to load any audio file that `soundfile` [1] supports. The returned
142
+ `Waveform` [2] is always shaped `(channels, samples)` where `channels` is `2`. When the source
143
+ file is mono, `readAudioFile` duplicates the single channel to produce a stereo array. When
144
+ `sampleRate` differs from the file's native sample rate, `readAudioFile` resamples using
145
+ `resampleWaveform`.
146
146
 
147
147
  Parameters
148
148
  ----------
149
149
  pathFilename : str | PathLike[Any] | BinaryIO
150
150
  Path to the audio file or a binary stream compatible with `soundfile` [1].
151
- sampleRate : float | None = None
152
- Target sample rate of the returned `Waveform` [2] in Hz. Defaults to `44100`
153
- when `None`.
151
+ sampleRate : float | None = 44100
152
+ Target sample rate of the returned `Waveform` [2] in Hz. Defaults to `44100` when `None`.
154
153
 
155
154
  Returns
156
155
  -------
@@ -188,6 +187,7 @@ def readAudioFile(pathFilename: str | PathLike[Any] | BinaryIO, sampleRate: floa
188
187
  axisTime = 0
189
188
  axisChannels = 1
190
189
  waveform = cast('Waveform', resampleWaveform(waveform, sampleRateDesired=sampleRate, sampleRateSource=sampleRateSource, axisTime=axisTime))
190
+ # TODO In my audio ecosystem, must I force a minimum of 2 channels, or can I merely force an axis for time, even if the axis is length=1?
191
191
  if waveform.shape[axisChannels] == 1:
192
192
  waveform = cast('Waveform', numpy.repeat(waveform, 2, axis=axisChannels))
193
193
  return cast('Waveform', numpy.transpose(waveform, axes=(axisChannels, axisTime)))
@@ -342,7 +342,7 @@ def writeWAV(pathFilename: str | PathLike[Any] | BinaryIO, waveform: Waveform, s
342
342
  """
343
343
  if sampleRate is None:
344
344
  sampleRate = parametersUniversal['sampleRate']
345
- # makeDirsSafely(pathFilename)
345
+ makeDirectorySafely(pathFilename)
346
346
  soundfile.write(file=pathFilename, data=waveform.T, samplerate=int(sampleRate), subtype='FLOAT', format='WAV')
347
347
 
348
348
  @overload # stft 1 ndarray
@@ -352,10 +352,10 @@ def stft(arrayTarget: Waveform, *, sampleRate: float | None = None, lengthHop: i
352
352
  def stft(arrayTarget: ArrayWaveforms, *, sampleRate: float | None = None, lengthHop: int | None = None, windowingFunction: WindowingFunction | None = None, lengthWindowingFunction: int | None = None, lengthFFT: int | None = None, inverse: Literal[False] = False, lengthWaveform: None = None, indexingAxis: int = -1) -> ArraySpectrograms: ...
353
353
 
354
354
  @overload # istft 1 ndarray
355
- def stft(arrayTarget: Spectrogram, *, sampleRate: float | None = None, lengthHop: int | None = None, windowingFunction: WindowingFunction | None = None, lengthWindowingFunction: int | None = None, lengthFFT: int | None = None, inverse: Literal[True] = True, lengthWaveform: int, indexingAxis: None = None) -> Waveform: ...
355
+ def stft(arrayTarget: Spectrogram, *, sampleRate: float | None = None, lengthHop: int | None = None, windowingFunction: WindowingFunction | None = None, lengthWindowingFunction: int | None = None, lengthFFT: int | None = None, inverse: Literal[True], lengthWaveform: int, indexingAxis: None = None) -> Waveform: ...
356
356
 
357
357
  @overload # istft many ndarray
358
- def stft(arrayTarget: ArraySpectrograms, *, sampleRate: float | None = None, lengthHop: int | None = None, windowingFunction: WindowingFunction | None = None, lengthWindowingFunction: int | None = None, lengthFFT: int | None = None, inverse: Literal[True] = True, lengthWaveform: int, indexingAxis: int = -1) -> ArrayWaveforms: ...
358
+ def stft(arrayTarget: ArraySpectrograms, *, sampleRate: float | None = None, lengthHop: int | None = None, windowingFunction: WindowingFunction | None = None, lengthWindowingFunction: int | None = None, lengthFFT: int | None = None, inverse: Literal[True], lengthWaveform: int, indexingAxis: int = -1) -> ArrayWaveforms: ...
359
359
 
360
360
  def stft(arrayTarget: Waveform | ArrayWaveforms | Spectrogram | ArraySpectrograms
361
361
  , *
@@ -16,10 +16,10 @@ from typing import Any, TYPE_CHECKING, TypeAlias, TypedDict, TypeVar
16
16
  if TYPE_CHECKING:
17
17
  from scipy.signal._short_time_fft import _FFTMode, _PadType, _ScaleTo
18
18
 
19
- 个 = TypeVar('个', covariant=True)
20
19
  ArrayType = TypeVar('ArrayType', bound=ndarray[tuple[Any, ...], dtype[Any]], covariant=True)
21
20
  WindowingFunctionDtype: TypeAlias = floating[Any]
22
21
  WindowingFunction: TypeAlias = ndarray[tuple[int], dtype[WindowingFunctionDtype]]
22
+ callableReturnsNDArray = TypeVar('callableReturnsNDArray', bound=Callable[..., WindowingFunction])
23
23
  WaveformDtype: TypeAlias = floating[Any]
24
24
  Waveform: TypeAlias = ndarray[tuple[int, int], dtype[WaveformDtype]]
25
25
  """Two-axes NumPy `ndarray` representing audio waveforms.
@@ -1,13 +1,12 @@
1
1
  """Create PyTorch tensor windowing functions."""
2
2
  from __future__ import annotations
3
3
 
4
- from collections.abc import Callable
5
- from hunterHearsPy import cosineWings, equalPower, halfsine, tukey, WindowingFunction
6
- from torch.types import Device
7
- from typing import Any, TypeVar
4
+ from hunterHearsPy import callableReturnsNDArray, cosineWings, equalPower, halfsine, tukey
5
+ from typing import Any, TYPE_CHECKING
8
6
  import torch
9
7
 
10
- callableReturnsNDArray = TypeVar('callableReturnsNDArray', bound=Callable[..., WindowingFunction])
8
+ if TYPE_CHECKING:
9
+ from torch.types import Device
11
10
 
12
11
  def _convertToTensor(*arguments: Any, callableTarget: callableReturnsNDArray, device: Device, **keywordArguments: Any) -> torch.Tensor:
13
12
  arrayTarget = callableTarget(*arguments, **keywordArguments)
@@ -29,7 +28,7 @@ def cosineWingsTensor(lengthWindow: int, ratioTaper: float | None=None, device:
29
28
  Ratio of taper length to windowing-function length. The value must be between 0 and 1,
30
29
  inclusive.
31
30
  device : Device = torch.device(device='cpu')
32
- PyTorch device for tensor allocation.
31
+ PyTorch device for `Tensor`.
33
32
 
34
33
  Returns
35
34
  -------
@@ -70,7 +69,7 @@ def equalPowerTensor(lengthWindow: int, ratioTaper: float | None=None, device: D
70
69
  Ratio of taper length to windowing-function length. The value must be between 0 and 1,
71
70
  inclusive.
72
71
  device : Device = torch.device(device='cpu')
73
- PyTorch device for tensor allocation.
72
+ PyTorch device for `Tensor`.
74
73
 
75
74
  Returns
76
75
  -------
@@ -107,7 +106,7 @@ def halfsineTensor(lengthWindow: int, device: Device | None=None) -> torch.Tenso
107
106
  lengthWindow : int
108
107
  Total length of the windowing function.
109
108
  device : Device = torch.device(device='cpu')
110
- PyTorch device for tensor allocation.
109
+ PyTorch device for `Tensor`.
111
110
 
112
111
  Returns
113
112
  -------
@@ -150,7 +149,7 @@ def tukeyTensor(lengthWindow: int, ratioTaper: float | None=None, device: Device
150
149
  Additional keyword arguments. `alpha` overrides `ratioTaper` when provided, matching SciPy's
151
150
  API.
152
151
  device : Device = torch.device(device='cpu')
153
- PyTorch device for tensor allocation.
152
+ PyTorch device for `Tensor`.
154
153
 
155
154
  Returns
156
155
  -------
File without changes
File without changes