modusa 0.2.22__py3-none-any.whl → 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.
- modusa/.DS_Store +0 -0
- modusa/__init__.py +8 -1
- modusa/decorators.py +4 -4
- modusa/devtools/generate_docs_source.py +96 -0
- modusa/devtools/generate_template.py +13 -13
- modusa/devtools/main.py +4 -3
- modusa/devtools/templates/generator.py +1 -1
- modusa/devtools/templates/io.py +1 -1
- modusa/devtools/templates/{signal.py → model.py} +18 -11
- modusa/devtools/templates/plugin.py +1 -1
- modusa/devtools/templates/test.py +2 -3
- modusa/devtools/templates/{engine.py → tool.py} +3 -8
- modusa/generators/__init__.py +9 -1
- modusa/generators/audio.py +188 -0
- modusa/generators/audio_waveforms.py +22 -13
- modusa/generators/base.py +1 -1
- modusa/generators/ftds.py +298 -0
- modusa/generators/s1d.py +270 -0
- modusa/generators/s2d.py +300 -0
- modusa/generators/s_ax.py +102 -0
- modusa/generators/t_ax.py +64 -0
- modusa/generators/tds.py +267 -0
- modusa/main.py +0 -30
- modusa/models/__init__.py +14 -0
- modusa/models/__pycache__/signal1D.cpython-312.pyc.4443461152 +0 -0
- modusa/models/audio.py +90 -0
- modusa/models/base.py +70 -0
- modusa/models/data.py +457 -0
- modusa/models/ftds.py +584 -0
- modusa/models/s1d.py +578 -0
- modusa/models/s2d.py +619 -0
- modusa/models/s_ax.py +448 -0
- modusa/models/t_ax.py +335 -0
- modusa/models/tds.py +465 -0
- modusa/plugins/__init__.py +3 -1
- modusa/tmp.py +98 -0
- modusa/tools/__init__.py +7 -0
- modusa/tools/audio_converter.py +73 -0
- modusa/tools/audio_loader.py +90 -0
- modusa/tools/audio_player.py +89 -0
- modusa/tools/base.py +43 -0
- modusa/tools/math_ops.py +335 -0
- modusa/tools/plotter.py +351 -0
- modusa/tools/youtube_downloader.py +72 -0
- modusa/utils/excp.py +15 -42
- modusa/utils/np_func_cat.py +44 -0
- modusa/utils/plot.py +142 -0
- {modusa-0.2.22.dist-info → modusa-0.3.dist-info}/METADATA +5 -16
- modusa-0.3.dist-info/RECORD +60 -0
- modusa/engines/.DS_Store +0 -0
- modusa/engines/__init__.py +0 -3
- modusa/engines/base.py +0 -14
- modusa/io/__init__.py +0 -9
- modusa/io/audio_converter.py +0 -76
- modusa/io/audio_loader.py +0 -214
- modusa/io/audio_player.py +0 -72
- modusa/io/base.py +0 -43
- modusa/io/plotter.py +0 -430
- modusa/io/youtube_downloader.py +0 -139
- modusa/signals/__init__.py +0 -7
- modusa/signals/audio_signal.py +0 -483
- modusa/signals/base.py +0 -34
- modusa/signals/frequency_domain_signal.py +0 -329
- modusa/signals/signal_ops.py +0 -158
- modusa/signals/spectrogram.py +0 -465
- modusa/signals/time_domain_signal.py +0 -309
- modusa-0.2.22.dist-info/RECORD +0 -47
- {modusa-0.2.22.dist-info → modusa-0.3.dist-info}/WHEEL +0 -0
- {modusa-0.2.22.dist-info → modusa-0.3.dist-info}/entry_points.txt +0 -0
- {modusa-0.2.22.dist-info → modusa-0.3.dist-info}/licenses/LICENSE.md +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: modusa
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.3
|
|
4
4
|
Summary: A modular signal analysis python library.
|
|
5
5
|
Author-Email: Ankit Anand <ankit0.anand0@gmail.com>
|
|
6
6
|
License: MIT
|
|
@@ -8,23 +8,14 @@ Requires-Python: >=3.12
|
|
|
8
8
|
Requires-Dist: numpy>=2.2.6
|
|
9
9
|
Requires-Dist: matplotlib>=3.10.3
|
|
10
10
|
Requires-Dist: yt-dlp>=2025.6.30
|
|
11
|
-
Requires-Dist: librosa==0.
|
|
11
|
+
Requires-Dist: librosa==0.11.0
|
|
12
12
|
Requires-Dist: IPython>=8.0.0
|
|
13
|
+
Requires-Dist: pyloudnorm>=0.1.1
|
|
13
14
|
Description-Content-Type: text/markdown
|
|
14
15
|
|
|
15
16
|
# modusa
|
|
16
17
|
|
|
17
|
-
[**modusa**](https://meluron-toolbox.github.io/modusa/) is a
|
|
18
|
-
|
|
19
|
-
---
|
|
20
|
-
|
|
21
|
-
## Core Components
|
|
22
|
-
|
|
23
|
-
- ⚙️ **modusa Signals**
|
|
24
|
-
- 🧩 **modusa Plugins**
|
|
25
|
-
- 📊 **modusa Genetators**
|
|
26
|
-
- 📥 **modusa I/O**
|
|
27
|
-
- ♻️ **modusa Engines**
|
|
18
|
+
[**modusa**](https://meluron-toolbox.github.io/modusa/) is a library with utility tools especially for audio signals.
|
|
28
19
|
|
|
29
20
|
---
|
|
30
21
|
|
|
@@ -33,9 +24,7 @@ Description-Content-Type: text/markdown
|
|
|
33
24
|
> modusa is under active development. You can install the latest version via:
|
|
34
25
|
|
|
35
26
|
```bash
|
|
36
|
-
|
|
37
|
-
cd modusa
|
|
38
|
-
pdm install
|
|
27
|
+
pip install modusa
|
|
39
28
|
```
|
|
40
29
|
|
|
41
30
|
---
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
modusa-0.3.dist-info/METADATA,sha256=4haDvOLjhY_sygHcMExMqMNXEVsUkNHfgoHpXWaX1PU,1236
|
|
2
|
+
modusa-0.3.dist-info/WHEEL,sha256=9P2ygRxDrTJz3gsagc0Z96ukrxjr-LFBGOgv3AuKlCA,90
|
|
3
|
+
modusa-0.3.dist-info/entry_points.txt,sha256=fmKpleVXj6CdaBVL14WoEy6xx7JQCs85jvzwTi3lePM,73
|
|
4
|
+
modusa-0.3.dist-info/licenses/LICENSE.md,sha256=JTaXAjx5awk76VArKCx5dUW8vmLEWsL_ZlR7-umaHbA,1078
|
|
5
|
+
modusa/.DS_Store,sha256=_gm6qJREwfMi8dE7n5S89_RG46u5t3xHyD-smNhtNoM,6148
|
|
6
|
+
modusa/__init__.py,sha256=AALG_17vibpDZbo0MymvGoQroaLp3uVm_onZaESONQA,257
|
|
7
|
+
modusa/config.py,sha256=bTqK4t00FZqERVITrxW_q284aDDJAa9aMSfFknfR-oU,280
|
|
8
|
+
modusa/decorators.py,sha256=8zeNX_wE37O6Vp0ysR4-WCZaEL8mq8dyCF_I5DHOzks,5905
|
|
9
|
+
modusa/devtools/generate_docs_source.py,sha256=qqxr3UgTeM4iotarQGRN_q2QXwAzGH7ha9bVjs8D4GQ,3409
|
|
10
|
+
modusa/devtools/generate_template.py,sha256=0sT_5-SjMLXyvePRDaIxr1RCz_9v6zFH9OoJqpuD2zI,5204
|
|
11
|
+
modusa/devtools/list_authors.py,sha256=FWBQKOLznVthvMYMASrx2Gw5lqKHEOccQpBisDZ53Dw,24
|
|
12
|
+
modusa/devtools/list_plugins.py,sha256=g-R5hoaCzHfClY_Sfa788IQ9CAKzQGTfyqmthXDZQqw,1729
|
|
13
|
+
modusa/devtools/main.py,sha256=zIB7x6km4RkV3A9P26NWpQberLn_3PWKbABxqAmzlzI,1993
|
|
14
|
+
modusa/devtools/templates/generator.py,sha256=ATEEgf0UtQ_eM_iA7colVBrlilIqViYC1CzNVUlXzRM,449
|
|
15
|
+
modusa/devtools/templates/io.py,sha256=yYU41zMpE204xRsqBxsRqLs3sH1LF6KgtJvzCNKNbhY,388
|
|
16
|
+
modusa/devtools/templates/model.py,sha256=iwmXadLMA4IAMgOEktdCWKZsceLgaaZkTWcJHqjQZzI,954
|
|
17
|
+
modusa/devtools/templates/plugin.py,sha256=MWqrxBxfRKVw2zjEgfAG0RYUAMjuazhqC5PXIb0gJi4,868
|
|
18
|
+
modusa/devtools/templates/test.py,sha256=CjZ_oqwJFhltNYzqfK1pcz1ShgeJXZLOnYpmOawfASs,244
|
|
19
|
+
modusa/devtools/templates/tool.py,sha256=2iQfHbFKtTELPvNoX42rHr9_5lXRrXpwxb9z5OL96Xc,435
|
|
20
|
+
modusa/generators/__init__.py,sha256=xQUsOObRhTEPzdZsBGd4nT_9AWaL8uE_bisFAN_Wp9Q,236
|
|
21
|
+
modusa/generators/audio.py,sha256=91CnBDPZhagfJOx-cDoBBj3NrE92m70PmFmv7T8aQco,4477
|
|
22
|
+
modusa/generators/audio_waveforms.py,sha256=x-r4_kDi2xieQNBCo11qY2uk2bFcvzeNOppfJnj2oYs,6105
|
|
23
|
+
modusa/generators/base.py,sha256=Kd3eAYOU8PDE28hz0uXfnrmgYSK2lGgHcr5NqeExxbE,938
|
|
24
|
+
modusa/generators/ftds.py,sha256=BkELukm5zbDwUxQVoylrlT9irIUUB2ZGfBc5pH5LUDc,6704
|
|
25
|
+
modusa/generators/s1d.py,sha256=M05oU22qkuLd9ycTSoOyfDtC4w2DEBebRZ4VTkUJRQo,5756
|
|
26
|
+
modusa/generators/s2d.py,sha256=kU67dZj4tdIDSUFJeheXm_JKbyHpZZOGmW5jya6w0wo,6874
|
|
27
|
+
modusa/generators/s_ax.py,sha256=4CTFp_KwYnl4HDno-ATpTXOfKR9WEVOV45nwuk2OoVk,2221
|
|
28
|
+
modusa/generators/t_ax.py,sha256=X-XOJuGWw99dPAVsCVzNTfBFr81Vw56aZlGDmcl5q3k,1478
|
|
29
|
+
modusa/generators/tds.py,sha256=eGvzcjXyWaw5NVzM3D098r3xkoMcX8Ma9YoDUdL30Mo,5960
|
|
30
|
+
modusa/main.py,sha256=v9oOhnPcbw8ULfkKRoantEfHw7MqOETJwXC-odx3dnA,25
|
|
31
|
+
modusa/models/__init__.py,sha256=G8sNOnBnTKqPmC4Z46ximBhc_pfBOF_G6AIfxT8DFzw,271
|
|
32
|
+
modusa/models/__pycache__/signal1D.cpython-312.pyc.4443461152,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
33
|
+
modusa/models/audio.py,sha256=IcNx3h8tb5Jt6KZug_TQKM5iufVk3i7Ug37iKG4gsJ0,2411
|
|
34
|
+
modusa/models/base.py,sha256=1qAXj69VsmrjGqShl5b27Jvt7OADHmPY0L9fBtpB_1E,1621
|
|
35
|
+
modusa/models/data.py,sha256=ds5zM0NOCwGImdxNdx27OnVpgKZ6kXUJMYBUqFWshXY,11368
|
|
36
|
+
modusa/models/ftds.py,sha256=5rd-3h1tzuy3OdD-pb66T0trPo77AvseZt3dy1zdZpg,16182
|
|
37
|
+
modusa/models/s1d.py,sha256=Hm2woUn9wcuwq1RYuEwlAWQPOLoRtnJoFD0mofW67mo,15550
|
|
38
|
+
modusa/models/s2d.py,sha256=10XXpZveFW6OY-v7O3xRy6xDNS5lzJi9UjJMqywyuYE,16782
|
|
39
|
+
modusa/models/s_ax.py,sha256=kKUOwZU9wV-w1ZJyOmdkcLMGtSOXA2gYzZ5f1FsHSEg,10793
|
|
40
|
+
modusa/models/t_ax.py,sha256=ZUhvZPUW1TkdZYuUd6Ucm-vsv0JqtZ9yEe3ab67Ma6w,8022
|
|
41
|
+
modusa/models/tds.py,sha256=FAGfibjyyE_lkEuQp-vSCuqQnopOjmy_IXqUjRlg9kc,11677
|
|
42
|
+
modusa/plugins/__init__.py,sha256=r1Bf5mnrVKRIwxboutY1iGzDy4EPQhqpk1kSW7iJj_Q,54
|
|
43
|
+
modusa/plugins/base.py,sha256=Bh_1Bja7fOymFsCgwhXDbV6ys3D8muNrPwrfDrG_G_A,2382
|
|
44
|
+
modusa/tmp.py,sha256=zPwgFVk5Oh6Rp6GUCbWJdkmwo6vYvhSqI35QVhW5xQM,3180
|
|
45
|
+
modusa/tools/__init__.py,sha256=jOFL7PJ1IztN6F7aMdrVKNMTid2yUmoSlSST-WFf0Cc,199
|
|
46
|
+
modusa/tools/audio_converter.py,sha256=415qBoPm2sBIuBSI7m1XBKm0AbmVmPydIPPr-uO8D3c,1778
|
|
47
|
+
modusa/tools/audio_loader.py,sha256=DrCzq0pdiQrUDIG-deLJGcu8EaylO5yRtwT4lr8WSf8,2166
|
|
48
|
+
modusa/tools/audio_player.py,sha256=GP04TWW4jBwQBjANkfR_cJtEy7cIhvbu8RTwnf9hD6E,2817
|
|
49
|
+
modusa/tools/base.py,sha256=C0ESJ0mIfjjRlAkRbSetNtMoOfS6IrHBjexRp3l_Mh4,1293
|
|
50
|
+
modusa/tools/math_ops.py,sha256=ZZ7U4DgqT7cOeE7_Lzi_Qq-48WYfwR9_osbZwTmE9eg,8690
|
|
51
|
+
modusa/tools/plotter.py,sha256=HaiIyP0Ll-Rk8Nw54g-R-AY9aAZxSAtnviYFnfuln_w,10552
|
|
52
|
+
modusa/tools/youtube_downloader.py,sha256=hB_X8-7nOHXOlxg6vv3wyhBLoAsWyomrULP6_uCQL7s,1698
|
|
53
|
+
modusa/utils/.DS_Store,sha256=nLXMwF7QJNuglLI_Gk74F7vl5Dyus2Wd74Mgowijmdo,6148
|
|
54
|
+
modusa/utils/__init__.py,sha256=1oLL20yLB1GL9IbFiZD8OReDqiCpFr-yetIR6x1cNkI,23
|
|
55
|
+
modusa/utils/config.py,sha256=cuGbqbovx5WDQq5rw3hIKcv3CnE5NttjacSOWnP1yu4,576
|
|
56
|
+
modusa/utils/excp.py,sha256=L9vhaGjKpv9viJYdmC9n5ndmk2GVbUBuFyZyhAQZmWY,906
|
|
57
|
+
modusa/utils/logger.py,sha256=K0rsnObeNKCxlNeSnVnJeRhgfmob6riB2uyU7h3dDmA,571
|
|
58
|
+
modusa/utils/np_func_cat.py,sha256=TyIFgRc6bARRMDnZxlVURO5Z0I-GWhxRONYyIv-Vwxs,1007
|
|
59
|
+
modusa/utils/plot.py,sha256=s_vNdxvKfwxEngvJPgrF1PcmxZNnNaaXPViHWjyjJ-c,5335
|
|
60
|
+
modusa-0.3.dist-info/RECORD,,
|
modusa/engines/.DS_Store
DELETED
|
Binary file
|
modusa/engines/__init__.py
DELETED
modusa/engines/base.py
DELETED
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env python3
|
|
2
|
-
|
|
3
|
-
from abc import ABC, abstractmethod
|
|
4
|
-
from typing import Any
|
|
5
|
-
|
|
6
|
-
class ModusaEngine(ABC):
|
|
7
|
-
"""
|
|
8
|
-
Base class for all core logic components in the Modusa system.
|
|
9
|
-
Every subclass must implement the `run` method.
|
|
10
|
-
"""
|
|
11
|
-
|
|
12
|
-
@abstractmethod
|
|
13
|
-
def run(self, *args, **kwargs) -> Any:
|
|
14
|
-
pass
|
modusa/io/__init__.py
DELETED
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env python3
|
|
2
|
-
|
|
3
|
-
from .base import ModusaIO
|
|
4
|
-
|
|
5
|
-
from .audio_loader import AudioLoader
|
|
6
|
-
from .audio_converter import AudioConverter
|
|
7
|
-
from .youtube_downloader import YoutubeDownloader
|
|
8
|
-
from .plotter import Plotter
|
|
9
|
-
from .audio_player import AudioPlayer
|
modusa/io/audio_converter.py
DELETED
|
@@ -1,76 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env python3
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
from modusa import excp
|
|
5
|
-
from modusa.decorators import validate_args_type
|
|
6
|
-
from modusa.io.base import ModusaIO
|
|
7
|
-
from typing import Any
|
|
8
|
-
import subprocess
|
|
9
|
-
from pathlib import Path
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
class AudioConverter(ModusaIO):
|
|
13
|
-
"""
|
|
14
|
-
Converts audio using FFmpeg.
|
|
15
|
-
|
|
16
|
-
Note
|
|
17
|
-
----
|
|
18
|
-
- Use `convert()` to perform the actual format conversion.
|
|
19
|
-
- Requires FFMPEG to be installed on the system.
|
|
20
|
-
"""
|
|
21
|
-
|
|
22
|
-
#--------Meta Information----------
|
|
23
|
-
_name = "Audio Converter"
|
|
24
|
-
_description = "Convert audio files using ffmpeg"
|
|
25
|
-
_author_name = "Ankit Anand"
|
|
26
|
-
_author_email = "ankit0.anand0@gmail.com"
|
|
27
|
-
_created_at = "2025-07-05"
|
|
28
|
-
#----------------------------------
|
|
29
|
-
|
|
30
|
-
@staticmethod
|
|
31
|
-
@validate_args_type()
|
|
32
|
-
def convert(inp_audio_fp: str | Path, output_audio_fp: str | Path) -> Path:
|
|
33
|
-
"""
|
|
34
|
-
Converts an audio file from one format to another using FFmpeg.
|
|
35
|
-
|
|
36
|
-
.. code-block:: python
|
|
37
|
-
|
|
38
|
-
from modusa.engines import AudioConverter
|
|
39
|
-
converted_audio_fp = AudioConverter.convert(
|
|
40
|
-
inp_audio_fp="path/to/input/audio.webm",
|
|
41
|
-
output_audio_fp="path/to/output/audio.wav"
|
|
42
|
-
)
|
|
43
|
-
|
|
44
|
-
Parameters
|
|
45
|
-
----------
|
|
46
|
-
inp_audio_fp: str | Path
|
|
47
|
-
Filepath of audio to be converted.
|
|
48
|
-
output_audio_fp: str | Path
|
|
49
|
-
Filepath of the converted audio. (e.g. name.mp3)
|
|
50
|
-
|
|
51
|
-
Returns
|
|
52
|
-
-------
|
|
53
|
-
Path:
|
|
54
|
-
Filepath of the converted audio.
|
|
55
|
-
|
|
56
|
-
Note
|
|
57
|
-
----
|
|
58
|
-
- The conversion takes place based on the extensions of the input and output audio filepath.
|
|
59
|
-
"""
|
|
60
|
-
inp_audio_fp = Path(inp_audio_fp)
|
|
61
|
-
output_audio_fp = Path(output_audio_fp)
|
|
62
|
-
|
|
63
|
-
cmd = [
|
|
64
|
-
"ffmpeg",
|
|
65
|
-
"-y", # Overwrite output
|
|
66
|
-
"-i", str(inp_audio_fp),
|
|
67
|
-
"-vn", # No video
|
|
68
|
-
str(output_audio_fp)
|
|
69
|
-
]
|
|
70
|
-
|
|
71
|
-
try:
|
|
72
|
-
subprocess.run(cmd, check=True, stdout=subprocess.DEVNULL, stderr=subprocess.STDOUT)
|
|
73
|
-
except subprocess.CalledProcessError:
|
|
74
|
-
raise RuntimeError(f"FFmpeg failed to convert {inp_audio_fp} to {output_audio_fp}")
|
|
75
|
-
|
|
76
|
-
return output_audio_fp
|
modusa/io/audio_loader.py
DELETED
|
@@ -1,214 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env python3
|
|
2
|
-
|
|
3
|
-
from modusa.io import ModusaIO
|
|
4
|
-
from modusa.signals import AudioSignal
|
|
5
|
-
from modusa.decorators import validate_args_type
|
|
6
|
-
from pathlib import Path
|
|
7
|
-
import tempfile
|
|
8
|
-
import numpy as np
|
|
9
|
-
|
|
10
|
-
class AudioLoader(ModusaIO):
|
|
11
|
-
"""
|
|
12
|
-
Loads audio from various sources like filepath, YouTube, etc.
|
|
13
|
-
|
|
14
|
-
Note
|
|
15
|
-
----
|
|
16
|
-
- All `from_` methods return :class:`~modusa.signals.AudioSignal` instance.
|
|
17
|
-
|
|
18
|
-
"""
|
|
19
|
-
|
|
20
|
-
#--------Meta Information----------
|
|
21
|
-
_name = "Audio Loader"
|
|
22
|
-
_description = "Loads audio from various sources."
|
|
23
|
-
_author_name = "Ankit Anand"
|
|
24
|
-
_author_email = "ankit0.anand0@gmail.com"
|
|
25
|
-
_created_at = "2025-07-05"
|
|
26
|
-
#----------------------------------
|
|
27
|
-
|
|
28
|
-
def __init__(self):
|
|
29
|
-
super().__init__()
|
|
30
|
-
|
|
31
|
-
@staticmethod
|
|
32
|
-
@validate_args_type()
|
|
33
|
-
def from_youtube(url: str, sr: int | None = None) -> "AudioSignal":
|
|
34
|
-
"""
|
|
35
|
-
Loads audio from youtube url using :class:`~modusa.io.YoutubeDownloader`,
|
|
36
|
-
:class:`~modusa.io.AudioConverter` and `librosa`.
|
|
37
|
-
|
|
38
|
-
.. code-block:: python
|
|
39
|
-
|
|
40
|
-
from modusa.io import AudioSignalLoader
|
|
41
|
-
|
|
42
|
-
# From youtube
|
|
43
|
-
audio_signal = AudioSignalLoader.from_youtube(
|
|
44
|
-
url="https://www.youtube.com/watch?v=lIpw9-Y_N0g",
|
|
45
|
-
sr=None
|
|
46
|
-
)
|
|
47
|
-
|
|
48
|
-
PARAMETERS
|
|
49
|
-
----------
|
|
50
|
-
url: str
|
|
51
|
-
Link to the YouTube video.
|
|
52
|
-
sr: int
|
|
53
|
-
Sampling rate to load the audio in.
|
|
54
|
-
|
|
55
|
-
Returns
|
|
56
|
-
-------
|
|
57
|
-
|
|
58
|
-
AudioSignal:
|
|
59
|
-
`Audio signal` instance with loaded audio content from YouTube.
|
|
60
|
-
"""
|
|
61
|
-
|
|
62
|
-
from modusa.io import YoutubeDownloader, AudioConverter
|
|
63
|
-
import librosa
|
|
64
|
-
|
|
65
|
-
# Download the audio in temp directory using tempfile module
|
|
66
|
-
with tempfile.TemporaryDirectory() as tmpdir:
|
|
67
|
-
audio_fp: Path = YoutubeDownloader.download(url=url, content_type="audio", output_dir=Path(tmpdir))
|
|
68
|
-
|
|
69
|
-
# Convert the audio to ".wav" form for loading
|
|
70
|
-
wav_audio_fp: Path = AudioConverter.convert(inp_audio_fp=audio_fp, output_audio_fp=audio_fp.with_suffix(".wav"))
|
|
71
|
-
|
|
72
|
-
# Load the audio in memory and return that
|
|
73
|
-
audio_data, audio_sr = librosa.load(wav_audio_fp, sr=sr)
|
|
74
|
-
|
|
75
|
-
audio = AudioSignal(y=audio_data, sr=audio_sr, title=audio_fp.stem)
|
|
76
|
-
|
|
77
|
-
return audio
|
|
78
|
-
|
|
79
|
-
@staticmethod
|
|
80
|
-
@validate_args_type()
|
|
81
|
-
def from_fp(fp: str | Path, sr: int | None = None) -> AudioSignal:
|
|
82
|
-
"""
|
|
83
|
-
Loads audio from a filepath using `librosa`.
|
|
84
|
-
|
|
85
|
-
.. code-block:: python
|
|
86
|
-
|
|
87
|
-
from modusa.io import AudioSignalLoader
|
|
88
|
-
|
|
89
|
-
# From file
|
|
90
|
-
audio_signal = AudioSignalLoader.from_fp(
|
|
91
|
-
fp="path/to/audio.wav",
|
|
92
|
-
sr=None
|
|
93
|
-
)
|
|
94
|
-
|
|
95
|
-
Parameters
|
|
96
|
-
----------
|
|
97
|
-
fp: str | Path
|
|
98
|
-
Local filepath of the audio.
|
|
99
|
-
sr: int | None
|
|
100
|
-
Sampling rate to load the audio in.
|
|
101
|
-
|
|
102
|
-
Returns
|
|
103
|
-
-------
|
|
104
|
-
AudioSignal
|
|
105
|
-
`Audio signal` instance with loaded audio content from filepath.
|
|
106
|
-
|
|
107
|
-
"""
|
|
108
|
-
import librosa
|
|
109
|
-
import warnings
|
|
110
|
-
warnings.filterwarnings("ignore", message="pkg_resources is deprecated as an API.")
|
|
111
|
-
|
|
112
|
-
fp = Path(fp)
|
|
113
|
-
y, sr = librosa.load(fp, sr=sr)
|
|
114
|
-
|
|
115
|
-
audio_signal = AudioSignal(y=y, sr=sr, title=fp.name)
|
|
116
|
-
|
|
117
|
-
return audio_signal
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
@staticmethod
|
|
121
|
-
def from_array(y: np.ndarray, t: np.ndarray | None = None) -> AudioSignal:
|
|
122
|
-
"""
|
|
123
|
-
Loads audio from numpy arrays.
|
|
124
|
-
|
|
125
|
-
.. code-block:: python
|
|
126
|
-
|
|
127
|
-
from modusa.io import AudioSignalLoader
|
|
128
|
-
import numpy as np
|
|
129
|
-
|
|
130
|
-
# From numpy array
|
|
131
|
-
audio_signal = AudioSignalLoader.from_array(
|
|
132
|
-
x=np.random.random((100, )),
|
|
133
|
-
t = None # Automatically creates time index (integer)
|
|
134
|
-
)
|
|
135
|
-
|
|
136
|
-
Parameters
|
|
137
|
-
----------
|
|
138
|
-
y: np.ndarray
|
|
139
|
-
Data of the audio signal.
|
|
140
|
-
t: np.ndarray | None
|
|
141
|
-
Corresponding time stamps of the audio signal.
|
|
142
|
-
|
|
143
|
-
Returns
|
|
144
|
-
-------
|
|
145
|
-
AudioSignal
|
|
146
|
-
`Audio signal` instance with loaded audio content from arrays.
|
|
147
|
-
"""
|
|
148
|
-
|
|
149
|
-
return AudioSignal(y=y, t=t)
|
|
150
|
-
|
|
151
|
-
@staticmethod
|
|
152
|
-
def from_array_with_sr(y: np.ndarray, sr: int) -> AudioSignal:
|
|
153
|
-
"""
|
|
154
|
-
Loads audio with a given sampling rate.
|
|
155
|
-
|
|
156
|
-
.. code-block:: python
|
|
157
|
-
|
|
158
|
-
from modusa.io import AudioSignalLoader
|
|
159
|
-
import numpy as np
|
|
160
|
-
|
|
161
|
-
# From numpy array
|
|
162
|
-
audio_signal = AudioSignalLoader.from_array_with_sr(
|
|
163
|
-
x=np.random.random((100, )),
|
|
164
|
-
sr = 100 # Automatically generates time index
|
|
165
|
-
)
|
|
166
|
-
|
|
167
|
-
Parameters
|
|
168
|
-
----------
|
|
169
|
-
y: np.ndarray
|
|
170
|
-
Data of the audio signal.
|
|
171
|
-
sr: int
|
|
172
|
-
Sampling rate of the audio signal.
|
|
173
|
-
|
|
174
|
-
Returns
|
|
175
|
-
-------
|
|
176
|
-
AudioSignal
|
|
177
|
-
`Audio signal` instance with loaded audio content from sampling rate.
|
|
178
|
-
"""
|
|
179
|
-
|
|
180
|
-
return AudioSignal(y=y, sr=sr)
|
|
181
|
-
|
|
182
|
-
@staticmethod
|
|
183
|
-
def from_list(y: list, t: list) -> AudioSignal:
|
|
184
|
-
"""
|
|
185
|
-
Loads `AudioSignal` instance from python list.
|
|
186
|
-
|
|
187
|
-
.. code-block:: python
|
|
188
|
-
|
|
189
|
-
from modusa.io import AudioSignalLoader
|
|
190
|
-
|
|
191
|
-
# From list
|
|
192
|
-
audio_signal = AudioSignalLoader.from_list(
|
|
193
|
-
y=[1, 2, 3, 2, 3],
|
|
194
|
-
t = [0.1, 0.2, 0.3, 0.4, 0.5]
|
|
195
|
-
)
|
|
196
|
-
|
|
197
|
-
Parameters
|
|
198
|
-
----------
|
|
199
|
-
y: list
|
|
200
|
-
Data of the audio signal.
|
|
201
|
-
t: np.ndarray | None
|
|
202
|
-
Corresponding time stamps of the audio signal.
|
|
203
|
-
|
|
204
|
-
Returns
|
|
205
|
-
-------
|
|
206
|
-
AudioSignal
|
|
207
|
-
`Audio signal` instance with loaded audio content from python list.
|
|
208
|
-
"""
|
|
209
|
-
y = np.array(y)
|
|
210
|
-
t = np.array(t)
|
|
211
|
-
|
|
212
|
-
return AudioSignal(y=y, t=t)
|
|
213
|
-
|
|
214
|
-
|
modusa/io/audio_player.py
DELETED
|
@@ -1,72 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env python3
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
from modusa import excp
|
|
5
|
-
from modusa.decorators import validate_args_type
|
|
6
|
-
from modusa.io import ModusaIO
|
|
7
|
-
from IPython.display import display, HTML, Audio
|
|
8
|
-
import numpy as np
|
|
9
|
-
|
|
10
|
-
class AudioPlayer(ModusaIO):
|
|
11
|
-
"""
|
|
12
|
-
|
|
13
|
-
"""
|
|
14
|
-
|
|
15
|
-
#--------Meta Information----------
|
|
16
|
-
_name = "Audio Player"
|
|
17
|
-
_description = ""
|
|
18
|
-
_author_name = "Ankit Anand"
|
|
19
|
-
_author_email = "ankit0.anand0@gmail.com"
|
|
20
|
-
_created_at = "2025-07-08"
|
|
21
|
-
#----------------------------------
|
|
22
|
-
|
|
23
|
-
@staticmethod
|
|
24
|
-
def play(
|
|
25
|
-
y: np.ndarray,
|
|
26
|
-
sr: int,
|
|
27
|
-
regions: list[tuple[float, float]] | None = None,
|
|
28
|
-
title: str | None = None
|
|
29
|
-
) -> None:
|
|
30
|
-
"""
|
|
31
|
-
Plays audio clips for given regions in Jupyter Notebooks.
|
|
32
|
-
|
|
33
|
-
Parameters
|
|
34
|
-
----------
|
|
35
|
-
y : np.ndarray
|
|
36
|
-
Audio time series.
|
|
37
|
-
sr : int
|
|
38
|
-
Sampling rate.
|
|
39
|
-
regions : list of (float, float), optional
|
|
40
|
-
Regions to extract and play (in seconds).
|
|
41
|
-
title : str, optional
|
|
42
|
-
Title to display above audio players.
|
|
43
|
-
|
|
44
|
-
Returns
|
|
45
|
-
-------
|
|
46
|
-
None
|
|
47
|
-
"""
|
|
48
|
-
if not AudioPlayer._in_notebook():
|
|
49
|
-
return
|
|
50
|
-
|
|
51
|
-
if title:
|
|
52
|
-
display(HTML(f"<h4>{title}</h4>"))
|
|
53
|
-
|
|
54
|
-
if regions:
|
|
55
|
-
for i, (start_sec, end_sec) in enumerate(regions):
|
|
56
|
-
start_sample = int(start_sec * sr)
|
|
57
|
-
end_sample = int(end_sec * sr)
|
|
58
|
-
clip = y[start_sample:end_sample]
|
|
59
|
-
|
|
60
|
-
display(HTML(f"<b>Clip {i+1}</b>: {start_sec:.2f}s → {end_sec:.2f}s"))
|
|
61
|
-
display(Audio(data=clip, rate=sr))
|
|
62
|
-
else:
|
|
63
|
-
display(Audio(data=y, rate=sr))
|
|
64
|
-
|
|
65
|
-
@staticmethod
|
|
66
|
-
def _in_notebook() -> bool:
|
|
67
|
-
try:
|
|
68
|
-
from IPython import get_ipython
|
|
69
|
-
shell = get_ipython()
|
|
70
|
-
return shell and shell.__class__.__name__ == "ZMQInteractiveShell"
|
|
71
|
-
except ImportError:
|
|
72
|
-
return False
|
modusa/io/base.py
DELETED
|
@@ -1,43 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env python3
|
|
2
|
-
|
|
3
|
-
from abc import ABC, abstractmethod
|
|
4
|
-
|
|
5
|
-
class ModusaIO(ABC):
|
|
6
|
-
"""
|
|
7
|
-
Base class for all I/O components: loaders, savers, recorders, etc.
|
|
8
|
-
|
|
9
|
-
>>> modusa-dev create io
|
|
10
|
-
|
|
11
|
-
.. code-block:: python
|
|
12
|
-
|
|
13
|
-
# General template of a subclass of ModusaIO
|
|
14
|
-
from modusa.io import ModusaIO
|
|
15
|
-
|
|
16
|
-
class MyCustomIOClass(ModusaIO):
|
|
17
|
-
#--------Meta Information----------
|
|
18
|
-
_name = "My Custom I/O"
|
|
19
|
-
_description = "My custom class for I/O."
|
|
20
|
-
_author_name = "Ankit Anand"
|
|
21
|
-
_author_email = "ankit0.anand0@gmail.com"
|
|
22
|
-
_created_at = "2025-07-06"
|
|
23
|
-
#----------------------------------
|
|
24
|
-
|
|
25
|
-
@staticmethod
|
|
26
|
-
def do_something():
|
|
27
|
-
pass
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
Note
|
|
31
|
-
----
|
|
32
|
-
- This class is intended to be subclassed by any IO related tools built for the modusa framework.
|
|
33
|
-
- In order to create an IO tool, you can use modusa-dev CLI to generate an IO template.
|
|
34
|
-
- It is recommended to treat subclasses of ModusaIO as namespaces and define @staticmethods with control parameters, rather than using instance-level __init__ methods.
|
|
35
|
-
"""
|
|
36
|
-
|
|
37
|
-
#--------Meta Information----------
|
|
38
|
-
_name: str = "Modusa I/O"
|
|
39
|
-
_description: str = "Base class for any I/O in the Modusa framework."
|
|
40
|
-
_author_name = "Ankit Anand"
|
|
41
|
-
_author_email = "ankit0.anand0@gmail.com"
|
|
42
|
-
_created_at = "2025-07-06"
|
|
43
|
-
#----------------------------------
|