modusa 0.4.28__py3-none-any.whl → 0.4.30__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/__init__.py +9 -8
- modusa/tools/__init__.py +7 -2
- modusa/tools/ann_saver.py +30 -0
- modusa/tools/audio_recorder.py +0 -1
- modusa/tools/synth.py +2 -0
- modusa/tools/youtube_downloader.py +1 -4
- {modusa-0.4.28.dist-info → modusa-0.4.30.dist-info}/METADATA +2 -2
- modusa-0.4.30.dist-info/RECORD +21 -0
- pyproject.toml +2 -2
- modusa/config.py +0 -18
- modusa/decorators.py +0 -176
- modusa/devtools/generate_docs_source.py +0 -92
- modusa/devtools/generate_template.py +0 -144
- modusa/devtools/list_authors.py +0 -2
- modusa/devtools/list_plugins.py +0 -60
- modusa/devtools/main.py +0 -45
- modusa/devtools/templates/generator.py +0 -24
- modusa/devtools/templates/io.py +0 -24
- modusa/devtools/templates/model.py +0 -47
- modusa/devtools/templates/plugin.py +0 -41
- modusa/devtools/templates/test.py +0 -10
- modusa/devtools/templates/tool.py +0 -24
- modusa/generators/__init__.py +0 -13
- modusa/generators/audio.py +0 -188
- modusa/generators/audio_waveforms.py +0 -236
- modusa/generators/base.py +0 -29
- modusa/generators/ftds.py +0 -298
- modusa/generators/s1d.py +0 -270
- modusa/generators/s2d.py +0 -300
- modusa/generators/s_ax.py +0 -102
- modusa/generators/t_ax.py +0 -64
- modusa/generators/tds.py +0 -267
- modusa/models/__init__.py +0 -14
- modusa/models/audio.py +0 -90
- modusa/models/base.py +0 -70
- modusa/models/data.py +0 -457
- modusa/models/ftds.py +0 -584
- modusa/models/s1d.py +0 -578
- modusa/models/s2d.py +0 -619
- modusa/models/s_ax.py +0 -448
- modusa/models/t_ax.py +0 -335
- modusa/models/tds.py +0 -465
- modusa/plugins/__init__.py +0 -3
- modusa/plugins/base.py +0 -100
- modusa/tools/_plotter_old.py +0 -629
- modusa/tools/audio_saver.py +0 -30
- modusa/tools/base.py +0 -43
- modusa/tools/math_ops.py +0 -335
- modusa/utils/__init__.py +0 -1
- modusa/utils/config.py +0 -25
- modusa/utils/excp.py +0 -49
- modusa/utils/logger.py +0 -18
- modusa/utils/np_func_cat.py +0 -44
- modusa/utils/plot.py +0 -142
- modusa-0.4.28.dist-info/RECORD +0 -65
- {modusa-0.4.28.dist-info → modusa-0.4.30.dist-info}/WHEEL +0 -0
- {modusa-0.4.28.dist-info → modusa-0.4.30.dist-info}/entry_points.txt +0 -0
- {modusa-0.4.28.dist-info → modusa-0.4.30.dist-info}/licenses/LICENSE.md +0 -0
modusa/devtools/main.py
DELETED
@@ -1,45 +0,0 @@
|
|
1
|
-
#!/usr/bin/env python3
|
2
|
-
|
3
|
-
|
4
|
-
from .generate_template import TemplateGenerator
|
5
|
-
from .generate_docs_source import generate_docs_source
|
6
|
-
from .list_plugins import list_plugins
|
7
|
-
from . import list_authors
|
8
|
-
|
9
|
-
import argparse
|
10
|
-
import sys
|
11
|
-
|
12
|
-
def main():
|
13
|
-
try:
|
14
|
-
parser = argparse.ArgumentParser(
|
15
|
-
prog="modusa-dev",
|
16
|
-
description="Modusa CLI Tools"
|
17
|
-
)
|
18
|
-
subparsers = parser.add_subparsers(dest="group", required=True)
|
19
|
-
|
20
|
-
# --- CREATE group ---
|
21
|
-
create_parser = subparsers.add_parser("create", help="Create new Modusa components")
|
22
|
-
create_subparsers = create_parser.add_subparsers(dest="what", required=True)
|
23
|
-
|
24
|
-
create_subparsers.add_parser("tool", help="Create a new tool class").set_defaults(func=lambda:TemplateGenerator.create_template("tool"))
|
25
|
-
create_subparsers.add_parser("plugin", help="Create a new plugin class").set_defaults(func=lambda:TemplateGenerator.create_template("plugin"))
|
26
|
-
create_subparsers.add_parser("model", help="Create a new model class").set_defaults(func=lambda:TemplateGenerator.create_template("model"))
|
27
|
-
create_subparsers.add_parser("generator", help="Create a new signal generator class").set_defaults(func=lambda:TemplateGenerator.create_template("generator"))
|
28
|
-
create_subparsers.add_parser("io", help="Create a new IO class").set_defaults(func=lambda:TemplateGenerator.create_template("io"))
|
29
|
-
create_subparsers.add_parser("docs", help="Generate the docs").set_defaults(func=lambda:generate_docs_source())
|
30
|
-
|
31
|
-
# --- LIST group ---
|
32
|
-
list_parser = subparsers.add_parser("list", help="List information about Modusa components")
|
33
|
-
list_subparsers = list_parser.add_subparsers(dest="what", required=True)
|
34
|
-
|
35
|
-
list_subparsers.add_parser("plugins", help="List available plugins").set_defaults(func=list_plugins)
|
36
|
-
list_subparsers.add_parser("authors", help="List plugin authors").set_defaults(func=list_authors)
|
37
|
-
|
38
|
-
# --- Parse and execute ---
|
39
|
-
args = parser.parse_args()
|
40
|
-
args.func()
|
41
|
-
|
42
|
-
except KeyboardInterrupt:
|
43
|
-
print("\n❌ Aborted by user.")
|
44
|
-
sys.exit(1)
|
45
|
-
|
@@ -1,24 +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.generators.base import ModusaGenerator
|
7
|
-
|
8
|
-
|
9
|
-
class {class_name}(ModusaGenerator):
|
10
|
-
"""
|
11
|
-
|
12
|
-
"""
|
13
|
-
|
14
|
-
#--------Meta Information----------
|
15
|
-
_name = ""
|
16
|
-
_description = ""
|
17
|
-
_author_name = "{author_name}"
|
18
|
-
_author_email = "{author_email}"
|
19
|
-
_created_at = "{date_created}"
|
20
|
-
#----------------------------------
|
21
|
-
|
22
|
-
def __init__(self):
|
23
|
-
super().__init__()
|
24
|
-
|
modusa/devtools/templates/io.py
DELETED
@@ -1,24 +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
|
-
|
8
|
-
|
9
|
-
class {class_name}(ModusaIO):
|
10
|
-
"""
|
11
|
-
|
12
|
-
"""
|
13
|
-
|
14
|
-
#--------Meta Information----------
|
15
|
-
_name = ""
|
16
|
-
_description = ""
|
17
|
-
_author_name = "{author_name}"
|
18
|
-
_author_email = "{author_email}"
|
19
|
-
_created_at = "{date_created}"
|
20
|
-
#----------------------------------
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
@@ -1,47 +0,0 @@
|
|
1
|
-
#!/usr/bin/env python3
|
2
|
-
|
3
|
-
|
4
|
-
from modusa import excp
|
5
|
-
from modusa.decorators import immutable_property, validate_args_type
|
6
|
-
from modusa.signals.base import ?
|
7
|
-
from typing import Self, Any
|
8
|
-
import numpy as np
|
9
|
-
|
10
|
-
class {class_name}():
|
11
|
-
"""
|
12
|
-
|
13
|
-
"""
|
14
|
-
|
15
|
-
#--------Meta Information----------
|
16
|
-
_name = ""
|
17
|
-
_nickname = "" # This is to be used in repr/str methods
|
18
|
-
_description = ""
|
19
|
-
_author_name = "{author_name}"
|
20
|
-
_author_email = "{author_email}"
|
21
|
-
_created_at = "{date_created}"
|
22
|
-
#----------------------------------
|
23
|
-
|
24
|
-
@validate_args_type()
|
25
|
-
def __init__(self):
|
26
|
-
super().__init__() # Instantiating `ModusaSignal` class
|
27
|
-
|
28
|
-
self.title = "" # This title will be used as plot title by default
|
29
|
-
|
30
|
-
#-----------------------------------
|
31
|
-
# Properties
|
32
|
-
#-----------------------------------
|
33
|
-
|
34
|
-
|
35
|
-
#===================================
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
#-----------------------------------
|
43
|
-
# Tools
|
44
|
-
#-----------------------------------
|
45
|
-
|
46
|
-
|
47
|
-
#===================================
|
@@ -1,41 +0,0 @@
|
|
1
|
-
#!/usr/bin/env python3
|
2
|
-
|
3
|
-
|
4
|
-
from modusa import excp
|
5
|
-
from modusa.decorators import immutable_property, validate_args_type, plugin_safety_check
|
6
|
-
from modusa.plugins.base import ModusaPlugin
|
7
|
-
|
8
|
-
|
9
|
-
class {class_name}(ModusaPlugin):
|
10
|
-
"""
|
11
|
-
|
12
|
-
"""
|
13
|
-
|
14
|
-
#--------Meta Information----------
|
15
|
-
_name = ""
|
16
|
-
_description = ""
|
17
|
-
_author_name = "{author_name}"
|
18
|
-
_author_email = "{author_email}"
|
19
|
-
_created_at = "{date_created}"
|
20
|
-
#----------------------------------
|
21
|
-
|
22
|
-
def __init__(self):
|
23
|
-
super().__init__()
|
24
|
-
|
25
|
-
@immutable_property(error_msg="Mutation not allowed.")
|
26
|
-
def allowed_input_signal_types(self) -> tuple[type, ...]:
|
27
|
-
return ()
|
28
|
-
|
29
|
-
|
30
|
-
@immutable_property(error_msg="Mutation not allowed.")
|
31
|
-
def allowed_output_signal_types(self) -> tuple[type, ...]:
|
32
|
-
return ()
|
33
|
-
|
34
|
-
|
35
|
-
@plugin_safety_check()
|
36
|
-
@validate_args_type()
|
37
|
-
def apply(self, signal: "") -> "":
|
38
|
-
|
39
|
-
# Run the engine here
|
40
|
-
|
41
|
-
return
|
@@ -1,10 +0,0 @@
|
|
1
|
-
#!/usr/bin/env python3
|
2
|
-
|
3
|
-
from modusa import excp
|
4
|
-
|
5
|
-
#--------Meta Information----------
|
6
|
-
_class_name = "{class_name}"
|
7
|
-
_author_name = "{author_name}"
|
8
|
-
_author_email = "{author_email}"
|
9
|
-
_created_at = "{date_created}"
|
10
|
-
#----------------------------------
|
@@ -1,24 +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.tools.base import ModusaTool
|
7
|
-
|
8
|
-
|
9
|
-
class {class_name}(ModusaTool):
|
10
|
-
"""
|
11
|
-
|
12
|
-
"""
|
13
|
-
|
14
|
-
#--------Meta Information----------
|
15
|
-
_name = ""
|
16
|
-
_description = ""
|
17
|
-
_author_name = "{author_name}"
|
18
|
-
_author_email = "{author_email}"
|
19
|
-
_created_at = "{date_created}"
|
20
|
-
#----------------------------------
|
21
|
-
|
22
|
-
def __init__(self):
|
23
|
-
super().__init__()
|
24
|
-
|
modusa/generators/__init__.py
DELETED
@@ -1,13 +0,0 @@
|
|
1
|
-
#!/usr/bin/env python3
|
2
|
-
|
3
|
-
from .base import ModusaGenerator
|
4
|
-
|
5
|
-
from .s_ax import SAxGen
|
6
|
-
from .t_ax import TAxGen
|
7
|
-
|
8
|
-
from .s1d import S1DGen
|
9
|
-
from .tds import TDSGen
|
10
|
-
from .audio import AudioGen
|
11
|
-
|
12
|
-
from .s2d import S2DGen
|
13
|
-
from .ftds import FTDSGen
|
modusa/generators/audio.py
DELETED
@@ -1,188 +0,0 @@
|
|
1
|
-
#!/usr/bin/env python3
|
2
|
-
|
3
|
-
|
4
|
-
from modusa import excp
|
5
|
-
from modusa.decorators import validate_args_type
|
6
|
-
from .base import ModusaGenerator
|
7
|
-
from modusa.models.t_ax import TAx
|
8
|
-
from modusa.models.audio import Audio
|
9
|
-
from modusa.models.data import Data
|
10
|
-
import numpy as np
|
11
|
-
from pathlib import Path
|
12
|
-
|
13
|
-
class AudioGen(ModusaGenerator):
|
14
|
-
"""
|
15
|
-
Provides user friendly APIs to generate instances of different
|
16
|
-
`AudioSignal` instances.
|
17
|
-
"""
|
18
|
-
|
19
|
-
#--------Meta Information----------
|
20
|
-
_name = ""
|
21
|
-
_description = ""
|
22
|
-
_author_name = "Ankit Anand"
|
23
|
-
_author_email = "ankit0.anand0@gmail.com"
|
24
|
-
_created_at = "2025-07-27"
|
25
|
-
#----------------------------------
|
26
|
-
|
27
|
-
@staticmethod
|
28
|
-
def from_array(
|
29
|
-
y: np.ndarray,
|
30
|
-
sr: float | int = 1.0,
|
31
|
-
t0: float | int = 0.0,
|
32
|
-
y_label: str = "Amplitude",
|
33
|
-
t_label: str = "Time (sec)",
|
34
|
-
title: str = "Audio Signal"
|
35
|
-
) -> Audio:
|
36
|
-
"""
|
37
|
-
Create `AudioSignal` instance from basic data structures.
|
38
|
-
|
39
|
-
.. code-block:: python
|
40
|
-
|
41
|
-
import modusa as ms
|
42
|
-
t = ms.tds.from_array([1, 2, 3])
|
43
|
-
print(t)
|
44
|
-
t.print_info()
|
45
|
-
|
46
|
-
Parameters
|
47
|
-
----------
|
48
|
-
y: np.ndarray
|
49
|
-
- Audio data array.
|
50
|
-
sr: float | int
|
51
|
-
- Sampling rate.
|
52
|
-
t0: float | int
|
53
|
-
- Start timestamp.
|
54
|
-
y_label: str
|
55
|
-
- Y label for the signal.
|
56
|
-
- Default: "Y"
|
57
|
-
t_label: str
|
58
|
-
- T label for the signal.
|
59
|
-
- Default: "Time (sec)"
|
60
|
-
title: str
|
61
|
-
- Title for the signal.
|
62
|
-
- Default: "1D Signal"
|
63
|
-
Returns
|
64
|
-
-------
|
65
|
-
Audio
|
66
|
-
An instance of Audio.
|
67
|
-
"""
|
68
|
-
assert isinstance(y, np.ndarray)
|
69
|
-
assert isinstance(sr, (int, float)) and isinstance(t0, (int, float))
|
70
|
-
assert isinstance(y_label, str) and isinstance(t_label, str) and isinstance(title, str)
|
71
|
-
|
72
|
-
assert y.ndim == 1
|
73
|
-
|
74
|
-
sr = float(sr)
|
75
|
-
t0 = float(t0)
|
76
|
-
|
77
|
-
t = TAx(n_points=y.shape[0], sr=sr, t0=t0, label=t_label) # Creating a signal axis instance
|
78
|
-
y = Data(values=y, label=y_label)
|
79
|
-
|
80
|
-
return Audio(y=y, t=t, title=title)
|
81
|
-
|
82
|
-
@classmethod
|
83
|
-
def from_youtube(cls, url: str, sr: int | float = None):
|
84
|
-
"""
|
85
|
-
Loads audio from youtube at a given sr.
|
86
|
-
The audio is deleted from the device
|
87
|
-
after loading.
|
88
|
-
|
89
|
-
.. code-block:: python
|
90
|
-
|
91
|
-
import modusa as ms
|
92
|
-
audio = ms.audio.from_youtube(
|
93
|
-
url="https://www.youtube.com/watch?v=lIpw9-Y_N0g",
|
94
|
-
sr=None
|
95
|
-
)
|
96
|
-
|
97
|
-
PARAMETERS
|
98
|
-
----------
|
99
|
-
url: str
|
100
|
-
Link to the YouTube video.
|
101
|
-
sr: int
|
102
|
-
Sampling rate to load the audio in.
|
103
|
-
|
104
|
-
Returns
|
105
|
-
-------
|
106
|
-
Audio:
|
107
|
-
An `Audio` instance with loaded audio content from YouTube.
|
108
|
-
"""
|
109
|
-
|
110
|
-
from modusa.tools.youtube_downloader import YoutubeDownloader
|
111
|
-
from modusa import convert
|
112
|
-
import soundfile as sf
|
113
|
-
from scipy.signal import resample
|
114
|
-
import tempfile
|
115
|
-
|
116
|
-
# Download the audio in temp directory using tempfile module
|
117
|
-
with tempfile.TemporaryDirectory() as tmpdir:
|
118
|
-
audio_fp: Path = YoutubeDownloader.download(url=url, content_type="audio", output_dir=Path(tmpdir))
|
119
|
-
|
120
|
-
# Convert the audio to ".wav" form for loading
|
121
|
-
wav_audio_fp: Path = convert(inp_audio_fp=audio_fp, output_audio_fp=audio_fp.with_suffix(".wav"))
|
122
|
-
|
123
|
-
# Load the audio in memory
|
124
|
-
audio_data, audio_sr = sf.read(wav_audio_fp)
|
125
|
-
|
126
|
-
# Convert to mono if it's multi-channel
|
127
|
-
if audio_data.ndim > 1:
|
128
|
-
audio_data = audio_data.mean(axis=1)
|
129
|
-
|
130
|
-
# Resample if needed
|
131
|
-
if sr is not None:
|
132
|
-
if audio_sr != sr:
|
133
|
-
n_samples = int(len(audio_data) * sr / audio_sr)
|
134
|
-
audio_data = resample(audio_data, n_samples)
|
135
|
-
audio_sr = sr
|
136
|
-
|
137
|
-
audio = cls.from_array(y=audio_data, sr=audio_sr, title=audio_fp.stem)
|
138
|
-
|
139
|
-
return audio
|
140
|
-
|
141
|
-
@classmethod
|
142
|
-
def from_filepath(cls, fp: str | Path, sr: int | float = None):
|
143
|
-
"""
|
144
|
-
Loads audio from filepath at a given sr.
|
145
|
-
|
146
|
-
.. code-block:: python
|
147
|
-
|
148
|
-
import modusa as ms
|
149
|
-
audio = ms.audio.from_filepath(
|
150
|
-
fp="path/to/audio.wav",
|
151
|
-
sr=None
|
152
|
-
)
|
153
|
-
|
154
|
-
PARAMETERS
|
155
|
-
----------
|
156
|
-
fp: str | Path
|
157
|
-
Audio file path.
|
158
|
-
sr: int
|
159
|
-
Sampling rate to load the audio in.
|
160
|
-
|
161
|
-
Returns
|
162
|
-
-------
|
163
|
-
Audio:
|
164
|
-
An `Audio` instance with loaded audio content.
|
165
|
-
"""
|
166
|
-
import soundfile as sf
|
167
|
-
from scipy.signal import resample
|
168
|
-
from pathlib import Path
|
169
|
-
|
170
|
-
fp = Path(fp)
|
171
|
-
# Load the audio in memory
|
172
|
-
audio_data, audio_sr = sf.read(fp)
|
173
|
-
|
174
|
-
# Convert to mono if it's multi-channel
|
175
|
-
if audio_data.ndim > 1:
|
176
|
-
audio_data = audio_data.mean(axis=1)
|
177
|
-
|
178
|
-
# Resample if needed
|
179
|
-
if sr is not None:
|
180
|
-
if audio_sr != sr:
|
181
|
-
n_samples = int(len(audio_data) * sr / audio_sr)
|
182
|
-
audio_data = resample(audio_data, n_samples)
|
183
|
-
audio_sr = sr
|
184
|
-
|
185
|
-
audio = cls.from_array(y=audio_data, sr=audio_sr, title=fp.stem)
|
186
|
-
|
187
|
-
return audio
|
188
|
-
|
@@ -1,236 +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.generators.base import ModusaGenerator
|
7
|
-
from modusa.models.audio_signal import AudioSignal
|
8
|
-
import numpy as np
|
9
|
-
|
10
|
-
class AudioWaveformGenerator(ModusaGenerator):
|
11
|
-
"""
|
12
|
-
Generates different kinds of audio waveforms particulary helpful
|
13
|
-
in teaching signal processing concepts and testing out newly
|
14
|
-
created tools.
|
15
|
-
"""
|
16
|
-
|
17
|
-
#--------Meta Information----------
|
18
|
-
_name = "Audio Waveform Generator"
|
19
|
-
_description = "Generates different kind of audio waveforms."
|
20
|
-
_author_name = "Ankit Anand"
|
21
|
-
_author_email = "ankit0.anand0@gmail.com"
|
22
|
-
_created_at = "2025-07-07"
|
23
|
-
#----------------------------------
|
24
|
-
|
25
|
-
@staticmethod
|
26
|
-
def generate_example() -> "AudioSignal":
|
27
|
-
"""
|
28
|
-
Generates a simple sine wave audio signal as an example.
|
29
|
-
|
30
|
-
Returns
|
31
|
-
-------
|
32
|
-
AudioSignal
|
33
|
-
A 600 Hz sine wave lasting 2 seconds, sampled at 10,000 Hz.
|
34
|
-
"""
|
35
|
-
|
36
|
-
sr = 10000 # Hz
|
37
|
-
duration = 2 # sec
|
38
|
-
freq = 600 # Hz
|
39
|
-
|
40
|
-
t = np.arange(0, duration, 1 / sr)
|
41
|
-
y = np.sin(2 * np.pi * freq * t)
|
42
|
-
|
43
|
-
signal = AudioSignal(y=y, sr=sr, title="Example") # assuming AudioSignal accepts y and t
|
44
|
-
|
45
|
-
return signal
|
46
|
-
|
47
|
-
|
48
|
-
@staticmethod
|
49
|
-
def generate_random(duration: float = 1.0, sr: int = 10000) -> "AudioSignal":
|
50
|
-
"""
|
51
|
-
Generates a random audio signal of given duration and sample rate.
|
52
|
-
|
53
|
-
Parameters
|
54
|
-
----------
|
55
|
-
duration : float, optional
|
56
|
-
Duration of the signal in seconds (default is 1.0).
|
57
|
-
sr : int, optional
|
58
|
-
Sampling rate in Hz (default is 10,000).
|
59
|
-
|
60
|
-
Returns
|
61
|
-
-------
|
62
|
-
AudioSignal
|
63
|
-
A randomly generated signal of the specified duration and sample rate.
|
64
|
-
"""
|
65
|
-
num_samples = int(duration * sr)
|
66
|
-
t = np.linspace(0, duration, num=num_samples, endpoint=False)
|
67
|
-
y = np.random.uniform(low=-1.0, high=1.0, size=num_samples) # use uniform [-1, 1] for audio-like signal
|
68
|
-
|
69
|
-
signal = AudioSignal(y=y, t=t, title="Random")
|
70
|
-
|
71
|
-
return signal
|
72
|
-
|
73
|
-
@staticmethod
|
74
|
-
@validate_args_type()
|
75
|
-
def generate_sinusoid(
|
76
|
-
A: float | int = 1.0,
|
77
|
-
f: float | int = 10.0,
|
78
|
-
phi: float | int = 0.0,
|
79
|
-
duration: float | int = 1.0,
|
80
|
-
sr: int = 1000,
|
81
|
-
) -> "AudioSignal":
|
82
|
-
"""
|
83
|
-
Generates a sinusoid audio signal with specified
|
84
|
-
amplitude, frequency, phase, duration, and sample rate.
|
85
|
-
|
86
|
-
Parameters
|
87
|
-
----------
|
88
|
-
A : float
|
89
|
-
Amplitude of the sinusoid (default: 1.0)
|
90
|
-
f : float
|
91
|
-
Frequency in Hz (default: 10.0)
|
92
|
-
phi : float
|
93
|
-
Phase in radians (default: 0.0)
|
94
|
-
duration : float
|
95
|
-
Duration of the signal in seconds (default: 1.0)
|
96
|
-
sr : int
|
97
|
-
Sampling rate in Hz (default: 1000)
|
98
|
-
|
99
|
-
Returns
|
100
|
-
-------
|
101
|
-
AudioSignal
|
102
|
-
A sinusoidal signal with the given parameters.
|
103
|
-
"""
|
104
|
-
A, f, phi, duration, sr = float(A), float(f), float(phi), float(duration), int(sr)
|
105
|
-
|
106
|
-
t = np.arange(0, duration, 1 / sr)
|
107
|
-
y = A * np.sin(2 * np.pi * f * t + phi)
|
108
|
-
|
109
|
-
signal = AudioSignal(y=y, sr=sr, title=f"Sinusoid ({f} Hz)")
|
110
|
-
|
111
|
-
return signal
|
112
|
-
|
113
|
-
@staticmethod
|
114
|
-
@validate_args_type()
|
115
|
-
def generate_square(
|
116
|
-
A: float | int = 1.0,
|
117
|
-
f: float | int = 10.0,
|
118
|
-
phi: float | int = 0.0,
|
119
|
-
duration: float | int = 1.0,
|
120
|
-
sr: int = 1000,
|
121
|
-
) -> "AudioSignal":
|
122
|
-
"""
|
123
|
-
Generates a square wave audio signal with specified
|
124
|
-
amplitude, frequency, phase, duration, and sample rate.
|
125
|
-
|
126
|
-
Parameters
|
127
|
-
----------
|
128
|
-
A : float
|
129
|
-
Amplitude of the square wave (default: 1.0)
|
130
|
-
f : float
|
131
|
-
Frequency in Hz (default: 10.0)
|
132
|
-
phi : float
|
133
|
-
Phase in radians (default: 0.0)
|
134
|
-
duration : float
|
135
|
-
Duration of the signal in seconds (default: 1.0)
|
136
|
-
sr : int
|
137
|
-
Sampling rate in Hz (default: 1000)
|
138
|
-
|
139
|
-
Returns
|
140
|
-
-------
|
141
|
-
AudioSignal
|
142
|
-
A square wave signal of the specified parameters.
|
143
|
-
"""
|
144
|
-
A, f, phi, duration, sr = float(A), float(f), float(phi), float(duration), int(sr)
|
145
|
-
t = np.arange(0, duration, 1 / sr)
|
146
|
-
|
147
|
-
y = A * np.sign(np.sin(2 * np.pi * f * t + phi))
|
148
|
-
|
149
|
-
signal = AudioSignal(y=y, sr=sr, title=f"Square ({f} Hz)")
|
150
|
-
|
151
|
-
return signal
|
152
|
-
|
153
|
-
|
154
|
-
@staticmethod
|
155
|
-
@validate_args_type()
|
156
|
-
def generate_sawtooth(
|
157
|
-
A: float | int = 1.0,
|
158
|
-
f: float | int = 10.0,
|
159
|
-
phi: float | int = 0.0,
|
160
|
-
duration: float | int = 1.0,
|
161
|
-
sr: int = 1000,
|
162
|
-
) -> "AudioSignal":
|
163
|
-
"""
|
164
|
-
Generates a sawtooth wave AudioSignal with specified amplitude, frequency, phase, duration, and sample rate.
|
165
|
-
|
166
|
-
Parameters
|
167
|
-
----------
|
168
|
-
A : float
|
169
|
-
Amplitude of the sawtooth wave (default: 1.0)
|
170
|
-
f : float
|
171
|
-
Frequency in Hz (default: 10.0)
|
172
|
-
phi : float
|
173
|
-
Phase in radians (default: 0.0)
|
174
|
-
duration : float
|
175
|
-
Duration of the signal in seconds (default: 1.0)
|
176
|
-
sr : int
|
177
|
-
Sampling rate in Hz (default: 1000)
|
178
|
-
|
179
|
-
Returns
|
180
|
-
-------
|
181
|
-
AudioSignal
|
182
|
-
A sawtooth wave signal of the specified parameters.
|
183
|
-
"""
|
184
|
-
A, f, phi, duration, sr = float(A), float(f), float(phi), float(duration), int(sr)
|
185
|
-
t = np.arange(0, duration, 1 / sr)
|
186
|
-
|
187
|
-
# Convert phase from radians to fractional cycle offset
|
188
|
-
phase_offset = phi / (2 * np.pi)
|
189
|
-
y = A * (2 * ((f * t + phase_offset) % 1) - 1)
|
190
|
-
|
191
|
-
signal = AudioSignal(y=y, sr=sr, title=f"Sawtooth ({f} Hz)")
|
192
|
-
return signal
|
193
|
-
|
194
|
-
|
195
|
-
@staticmethod
|
196
|
-
@validate_args_type()
|
197
|
-
def generate_triangle(
|
198
|
-
A: float | int = 1.0,
|
199
|
-
f: float | int = 10.0,
|
200
|
-
phi: float | int = 0.0,
|
201
|
-
duration: float | int = 1.0,
|
202
|
-
sr: int = 1000,
|
203
|
-
) -> "AudioSignal":
|
204
|
-
"""
|
205
|
-
Generates a triangle wave AudioSignal with specified
|
206
|
-
amplitude, frequency, phase, duration, and sample rate.
|
207
|
-
|
208
|
-
Parameters
|
209
|
-
----------
|
210
|
-
A : float
|
211
|
-
Amplitude of the triangle wave (default: 1.0)
|
212
|
-
f : float
|
213
|
-
Frequency in Hz (default: 10.0)
|
214
|
-
phi : float
|
215
|
-
Phase in radians (default: 0.0)
|
216
|
-
duration : float
|
217
|
-
Duration of the signal in seconds (default: 1.0)
|
218
|
-
sr : int
|
219
|
-
Sampling rate in Hz (default: 1000)
|
220
|
-
|
221
|
-
Returns
|
222
|
-
-------
|
223
|
-
AudioSignal
|
224
|
-
A triangle wave signal of the specified parameters.
|
225
|
-
"""
|
226
|
-
A, f, phi, duration, sr = float(A), float(f), float(phi), float(duration), int(sr)
|
227
|
-
t = np.arange(0, duration, 1 / sr)
|
228
|
-
phase_offset = phi / (2 * np.pi) # Convert radians to cycle offset
|
229
|
-
|
230
|
-
# Triangle wave formula: 2 * abs(2 * frac(x) - 1) - 1 scaled to amplitude
|
231
|
-
y = A * (2 * np.abs(2 * ((f * t + phase_offset) % 1) - 1) - 1)
|
232
|
-
|
233
|
-
signal = AudioSignal(y=y, sr=sr, title=f"Triangle ({f} Hz)")
|
234
|
-
|
235
|
-
return signal
|
236
|
-
|
modusa/generators/base.py
DELETED
@@ -1,29 +0,0 @@
|
|
1
|
-
#!/usr/bin/env python3
|
2
|
-
|
3
|
-
from modusa import excp
|
4
|
-
from modusa.decorators import validate_args_type, immutable_property
|
5
|
-
from modusa.models.base import ModusaSignal
|
6
|
-
from abc import ABC, abstractmethod
|
7
|
-
from typing import Any
|
8
|
-
|
9
|
-
class ModusaGenerator(ABC):
|
10
|
-
"""
|
11
|
-
Base class for any type of signal generators for modusa framework.
|
12
|
-
|
13
|
-
Note
|
14
|
-
----
|
15
|
-
- This class is intended to be subclassed by any Generator related tools built for the modusa framework.
|
16
|
-
- In order to create a generator tool, you can use modusa-dev CLI to generate an generator template.
|
17
|
-
- It is recommended to treat subclasses of ModusaGenerator as namespaces and define @staticmethods with control parameters, rather than using instance-level __init__ methods.
|
18
|
-
|
19
|
-
|
20
|
-
"""
|
21
|
-
|
22
|
-
#--------Meta Information----------
|
23
|
-
_name = ""
|
24
|
-
_description = ""
|
25
|
-
_author_name = "Ankit Anand"
|
26
|
-
_author_email = "ankit0.anand0@gmail.com"
|
27
|
-
_created_at = "2025-07-04"
|
28
|
-
#----------------------------------
|
29
|
-
|