modusa 0.3.41__py3-none-any.whl → 0.3.43__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.
@@ -0,0 +1,115 @@
1
+ #!/usr/bin/env python3
2
+
3
+ #---------------------------------
4
+ # Author: Ankit Anand
5
+ # Date: 22/08/25
6
+ # Email: ankit0.anand0@gmail.com
7
+ #---------------------------------
8
+
9
+
10
+ import sounddevice as sd
11
+ import numpy as np
12
+ import ipywidgets as widgets
13
+ from IPython.display import display, clear_output, Audio
14
+
15
+ def record():
16
+ """
17
+ Create a UI to record audio in jupyter notebook, the
18
+ recorded signal is available as array.
19
+
20
+ .. code-block:: python
21
+
22
+ import modusa as ms
23
+ result = ms.record()
24
+ y, sr, title = result() # Keep it in the next cell
25
+
26
+ Returns
27
+ -------
28
+ Callable
29
+ A lambda function that returns y(audio signal), sr(sampling rate), title(title set in the UI)
30
+ """
31
+ devices = sd.query_devices()
32
+ device_options = [(d['name'][:30], i) for i, d in enumerate(devices) if d['max_input_channels'] > 0]
33
+
34
+ # Controls
35
+ device_dropdown = widgets.Dropdown(
36
+ options=device_options,
37
+ description="Microphone:",
38
+ layout=widgets.Layout(width="300px")
39
+ )
40
+
41
+ sr_dropdown = widgets.Dropdown(
42
+ options=[('16 Khz', 16000), ('22.05 Khz', 22050), ('44.1 Khz', 44100)],
43
+ value=22050,
44
+ description="Sample Rate:",
45
+ layout=widgets.Layout(width="300px")
46
+ )
47
+
48
+ title_box = widgets.Text(
49
+ placeholder="Title",
50
+ description="Title:",
51
+ layout=widgets.Layout(width="300px")
52
+ )
53
+
54
+ toggle_button = widgets.Button(
55
+ description="Record",
56
+ button_style="",
57
+ )
58
+
59
+ status = widgets.HTML(value="")
60
+ out = widgets.Output()
61
+
62
+ # State
63
+ recording = {"data": None, "sr": None, "title": None}
64
+ stream = {"obj": None, "frames": [], "recording": False}
65
+
66
+ def callback(indata, frames, time, status):
67
+ if not status:
68
+ stream["frames"].append(indata.copy())
69
+
70
+ def on_toggle(b):
71
+ if not stream["recording"]:
72
+ stream["frames"].clear()
73
+ sr = sr_dropdown.value
74
+ device_id = device_dropdown.value
75
+
76
+ stream["obj"] = sd.InputStream(callback=callback, channels=1, samplerate=sr, device=device_id)
77
+ stream["obj"].start()
78
+ stream["recording"] = True
79
+
80
+ toggle_button.description = "Stop"
81
+ toggle_button.button_style = "danger"
82
+ status.value = "Recording..."
83
+ else:
84
+ stream["obj"].stop()
85
+ stream["obj"].close()
86
+
87
+ sr = sr_dropdown.value
88
+ y = np.concatenate(stream["frames"], axis=0).flatten()
89
+ title = title_box.value.strip() or "Recording"
90
+
91
+ recording["data"], recording["sr"], recording["title"] = y, sr, title
92
+ record.result = (y, sr, title)
93
+ stream["recording"] = False
94
+
95
+ toggle_button.description = "Record"
96
+ toggle_button.button_style = "success"
97
+
98
+ with out:
99
+ clear_output()
100
+ display(Audio(y, rate=sr))
101
+
102
+ toggle_button.on_click(on_toggle)
103
+
104
+ # Layout
105
+ ui = widgets.VBox([
106
+ device_dropdown,
107
+ sr_dropdown,
108
+ title_box,
109
+ widgets.HBox([toggle_button]),
110
+ out
111
+ ])
112
+
113
+ display(ui)
114
+ record.result = None
115
+ return lambda: record.result