pysilentmic 0.1.0__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.
@@ -0,0 +1,65 @@
1
+ Metadata-Version: 2.4
2
+ Name: pysilentmic
3
+ Version: 0.1.0
4
+ Summary: Python bindings for SilentMic-RT: Deterministic, Zero-Allocation Sub-3ms Hard Real-Time Neural Voice Isolator
5
+ Author-email: "Shah Md. Mahi" <shahmdmahi15@gmail.com>
6
+ License: MIT
7
+ Project-URL: Homepage, https://shahmdmahi.dpdns.org
8
+ Project-URL: Repository, https://github.com/shahmdmahi15/silentmic-rt
9
+ Project-URL: Documentation, https://github.com/shahmdmahi15/silentmic-rt#python-quickstart
10
+ Keywords: audio,dsp,noise-suppression,real-time,voice-isolation,pipewire
11
+ Classifier: Development Status :: 4 - Beta
12
+ Classifier: Intended Audience :: Developers
13
+ Classifier: Intended Audience :: Science/Research
14
+ Classifier: License :: OSI Approved :: MIT License
15
+ Classifier: Programming Language :: Python :: 3
16
+ Classifier: Programming Language :: Rust
17
+ Classifier: Topic :: Multimedia :: Sound/Audio :: Speech
18
+ Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
19
+ Requires-Python: >=3.8
20
+ Description-Content-Type: text/markdown
21
+ Requires-Dist: numpy>=1.20.0
22
+
23
+ # pysilentmic: Python Real-Time Voice Isolator
24
+
25
+ Python C-FFI bindings for **SilentMic-RT** — the deterministic, zero-allocation sub-3ms hard real-time neural voice isolator and virtual microphone driver.
26
+
27
+ ## Features
28
+ - **Ultra-Low Latency**: 1.33 ms frame hop (64 samples at 48,000 Hz).
29
+ - **Sub-3ms Total Latency**: Complete input-to-output algorithmic delay under 2.67 ms.
30
+ - **Zero Allocation**: Lock-free, zero heap memory allocations on audio worker threads.
31
+ - **Pure Offline SIMD**: Operates entirely on CPU SIMD instructions with zero network or cloud latency.
32
+ - **NumPy Integration**: Seamlessly denoises NumPy arrays and streaming audio generators.
33
+
34
+ ## Installation
35
+
36
+ ```bash
37
+ pip install pysilentmic
38
+ ```
39
+
40
+ ## Quickstart
41
+
42
+ ```python
43
+ import numpy as np
44
+ from pysilentmic import SilentMic
45
+
46
+ # Initialize SilentMic engine at 48kHz
47
+ mic = SilentMic(sample_rate=48000, attenuation_db=-48.0)
48
+
49
+ # Process 64-sample audio frame in real time (< 30 us)
50
+ raw_frame = np.random.randn(64).astype(np.float32)
51
+ clean_frame = mic.process_frame(raw_frame)
52
+
53
+ # Denoise complete audio file / NumPy array
54
+ noisy_audio = np.random.randn(48000 * 5).astype(np.float32)
55
+ isolated_voice = mic.process(noisy_audio)
56
+
57
+ # Access hardware telemetry
58
+ print(mic.get_stats())
59
+ ```
60
+
61
+ ## Author & Maintainer
62
+ - **Author**: Shah Md. Mahi
63
+ - **Email**: shahmdmahi15@gmail.com
64
+ - **Website**: [https://shahmdmahi.dpdns.org](https://shahmdmahi.dpdns.org)
65
+ - **License**: MIT
@@ -0,0 +1,43 @@
1
+ # pysilentmic: Python Real-Time Voice Isolator
2
+
3
+ Python C-FFI bindings for **SilentMic-RT** — the deterministic, zero-allocation sub-3ms hard real-time neural voice isolator and virtual microphone driver.
4
+
5
+ ## Features
6
+ - **Ultra-Low Latency**: 1.33 ms frame hop (64 samples at 48,000 Hz).
7
+ - **Sub-3ms Total Latency**: Complete input-to-output algorithmic delay under 2.67 ms.
8
+ - **Zero Allocation**: Lock-free, zero heap memory allocations on audio worker threads.
9
+ - **Pure Offline SIMD**: Operates entirely on CPU SIMD instructions with zero network or cloud latency.
10
+ - **NumPy Integration**: Seamlessly denoises NumPy arrays and streaming audio generators.
11
+
12
+ ## Installation
13
+
14
+ ```bash
15
+ pip install pysilentmic
16
+ ```
17
+
18
+ ## Quickstart
19
+
20
+ ```python
21
+ import numpy as np
22
+ from pysilentmic import SilentMic
23
+
24
+ # Initialize SilentMic engine at 48kHz
25
+ mic = SilentMic(sample_rate=48000, attenuation_db=-48.0)
26
+
27
+ # Process 64-sample audio frame in real time (< 30 us)
28
+ raw_frame = np.random.randn(64).astype(np.float32)
29
+ clean_frame = mic.process_frame(raw_frame)
30
+
31
+ # Denoise complete audio file / NumPy array
32
+ noisy_audio = np.random.randn(48000 * 5).astype(np.float32)
33
+ isolated_voice = mic.process(noisy_audio)
34
+
35
+ # Access hardware telemetry
36
+ print(mic.get_stats())
37
+ ```
38
+
39
+ ## Author & Maintainer
40
+ - **Author**: Shah Md. Mahi
41
+ - **Email**: shahmdmahi15@gmail.com
42
+ - **Website**: [https://shahmdmahi.dpdns.org](https://shahmdmahi.dpdns.org)
43
+ - **License**: MIT
@@ -0,0 +1,33 @@
1
+ [build-system]
2
+ requires = ["setuptools>=61.0", "wheel"]
3
+ build-backend = "setuptools.build_meta"
4
+
5
+ [project]
6
+ name = "pysilentmic"
7
+ version = "0.1.0"
8
+ authors = [
9
+ { name = "Shah Md. Mahi", email = "shahmdmahi15@gmail.com" }
10
+ ]
11
+ description = "Python bindings for SilentMic-RT: Deterministic, Zero-Allocation Sub-3ms Hard Real-Time Neural Voice Isolator"
12
+ readme = "README.md"
13
+ license = { text = "MIT" }
14
+ requires-python = ">=3.8"
15
+ keywords = ["audio", "dsp", "noise-suppression", "real-time", "voice-isolation", "pipewire"]
16
+ classifiers = [
17
+ "Development Status :: 4 - Beta",
18
+ "Intended Audience :: Developers",
19
+ "Intended Audience :: Science/Research",
20
+ "License :: OSI Approved :: MIT License",
21
+ "Programming Language :: Python :: 3",
22
+ "Programming Language :: Rust",
23
+ "Topic :: Multimedia :: Sound/Audio :: Speech",
24
+ "Topic :: Scientific/Engineering :: Artificial Intelligence"
25
+ ]
26
+ dependencies = [
27
+ "numpy>=1.20.0"
28
+ ]
29
+
30
+ [project.urls]
31
+ Homepage = "https://shahmdmahi.dpdns.org"
32
+ Repository = "https://github.com/shahmdmahi15/silentmic-rt"
33
+ Documentation = "https://github.com/shahmdmahi15/silentmic-rt#python-quickstart"
@@ -0,0 +1,10 @@
1
+ """
2
+ pysilentmic: High-performance Python bindings for SilentMic-RT.
3
+ Deterministic, Zero-Allocation Sub-3ms Hard Real-Time Neural Voice Isolator.
4
+ """
5
+
6
+ from .engine import SilentMic
7
+
8
+ __version__ = "0.1.0"
9
+ __author__ = "Shah Md. Mahi <shahmdmahi15@gmail.com>"
10
+ __all__ = ["SilentMic"]
@@ -0,0 +1,211 @@
1
+ """
2
+ SilentMic-RT Python ctypes binding.
3
+ Ultra-low latency sub-3ms neural voice isolator & noise suppressor.
4
+ """
5
+
6
+ import ctypes
7
+ import os
8
+ import sys
9
+ from typing import Optional, Union, Dict, Any, List
10
+
11
+ try:
12
+ import numpy as np
13
+ HAS_NUMPY = True
14
+ except ImportError:
15
+ HAS_NUMPY = False
16
+
17
+ class SilentMicStatsC(ctypes.Structure):
18
+ _fields_ = [
19
+ ("frames_processed", ctypes.c_uint64),
20
+ ("samples_processed", ctypes.c_uint64),
21
+ ("last_frame_micros", ctypes.c_double),
22
+ ("max_frame_micros", ctypes.c_double),
23
+ ("avg_frame_micros", ctypes.c_double),
24
+ ("cpu_budget_pct", ctypes.c_double),
25
+ ]
26
+
27
+ def _find_library() -> str:
28
+ """Locates the compiled SilentMic dynamic library."""
29
+ lib_names = []
30
+ if sys.platform.startswith("linux"):
31
+ lib_names = ["libsilentmic.so"]
32
+ elif sys.platform == "darwin":
33
+ lib_names = ["libsilentmic.dylib"]
34
+ elif sys.platform == "win32":
35
+ lib_names = ["silentmic.dll", "libsilentmic.dll"]
36
+ else:
37
+ lib_names = ["libsilentmic.so"]
38
+
39
+ search_dirs = [
40
+ os.path.dirname(os.path.abspath(__file__)),
41
+ os.path.join(os.path.dirname(os.path.abspath(__file__)), "..", "..", "target", "release"),
42
+ os.path.join(os.path.dirname(os.path.abspath(__file__)), "..", "..", "target", "debug"),
43
+ "/usr/local/lib",
44
+ "/usr/lib",
45
+ ]
46
+
47
+ for d in search_dirs:
48
+ for name in lib_names:
49
+ path = os.path.join(d, name)
50
+ if os.path.isfile(path):
51
+ return os.path.abspath(path)
52
+
53
+ return lib_names[0]
54
+
55
+ class SilentMic:
56
+ """
57
+ SilentMic Real-Time Neural Voice Isolator Engine.
58
+
59
+ Processes 48kHz audio in 64-sample frames with deterministic sub-3ms algorithmic latency.
60
+ """
61
+ FRAME_SIZE = 64
62
+ SAMPLE_RATE = 48000
63
+
64
+ def __init__(self, sample_rate: int = 48000, attenuation_db: float = -48.0, lib_path: Optional[str] = None):
65
+ if sample_rate != self.SAMPLE_RATE:
66
+ raise ValueError(f"SilentMic requires sample_rate={self.SAMPLE_RATE} Hz, received {sample_rate} Hz")
67
+
68
+ dll_path = lib_path or _find_library()
69
+ self._lib = ctypes.CDLL(dll_path)
70
+
71
+ # Declare function signatures
72
+ self._lib.silentmic_create.argtypes = [ctypes.c_uint32]
73
+ self._lib.silentmic_create.restype = ctypes.c_void_p
74
+
75
+ self._lib.silentmic_process_frame.argtypes = [
76
+ ctypes.c_void_p,
77
+ ctypes.POINTER(ctypes.c_float),
78
+ ctypes.POINTER(ctypes.c_float),
79
+ ]
80
+ self._lib.silentmic_process_frame.restype = ctypes.c_int
81
+
82
+ self._lib.silentmic_set_attenuation_db.argtypes = [ctypes.c_void_p, ctypes.c_float]
83
+ self._lib.silentmic_set_attenuation_db.restype = ctypes.c_int
84
+
85
+ self._lib.silentmic_reset.argtypes = [ctypes.c_void_p]
86
+ self._lib.silentmic_reset.restype = ctypes.c_int
87
+
88
+ self._lib.silentmic_get_stats.argtypes = [ctypes.c_void_p, ctypes.POINTER(SilentMicStatsC)]
89
+ self._lib.silentmic_get_stats.restype = ctypes.c_int
90
+
91
+ self._lib.silentmic_destroy.argtypes = [ctypes.c_void_p]
92
+ self._lib.silentmic_destroy.restype = None
93
+
94
+ self._lib.silentmic_version.argtypes = []
95
+ self._lib.silentmic_version.restype = ctypes.c_char_p
96
+
97
+ self._handle = self._lib.silentmic_create(sample_rate)
98
+ if not self._handle:
99
+ raise RuntimeError("Failed to create native SilentMic-RT engine instance")
100
+
101
+ self.set_attenuation_db(attenuation_db)
102
+
103
+ def set_attenuation_db(self, db: float) -> None:
104
+ """Sets the maximum noise floor attenuation in decibels (e.g. -48.0 dB)."""
105
+ ret = self._lib.silentmic_set_attenuation_db(self._handle, ctypes.c_float(db))
106
+ if ret != 0:
107
+ raise RuntimeError("Failed to set attenuation level")
108
+
109
+ def reset(self) -> None:
110
+ """Resets all internal delay lines and recurrent states."""
111
+ self._lib.silentmic_reset(self._handle)
112
+
113
+ def process_frame(self, in_frame: Union[Any, List[float]]) -> Union[Any, List[float]]:
114
+ """
115
+ Processes an exact 64-sample float32 array or list.
116
+ """
117
+ if HAS_NUMPY and isinstance(in_frame, np.ndarray):
118
+ if in_frame.shape != (self.FRAME_SIZE,) or in_frame.dtype != np.float32:
119
+ in_frame = np.ascontiguousarray(in_frame, dtype=np.float32)
120
+ if in_frame.shape != (self.FRAME_SIZE,):
121
+ raise ValueError(f"in_frame must have shape ({self.FRAME_SIZE},), got {in_frame.shape}")
122
+
123
+ out_frame = np.empty(self.FRAME_SIZE, dtype=np.float32)
124
+ in_ptr = in_frame.ctypes.data_as(ctypes.POINTER(ctypes.c_float))
125
+ out_ptr = out_frame.ctypes.data_as(ctypes.POINTER(ctypes.c_float))
126
+
127
+ ret = self._lib.silentmic_process_frame(self._handle, in_ptr, out_ptr)
128
+ if ret != 0:
129
+ raise RuntimeError(f"silentmic_process_frame returned error code {ret}")
130
+ return out_frame
131
+ else:
132
+ in_list = list(in_frame)
133
+ if len(in_list) != self.FRAME_SIZE:
134
+ raise ValueError(f"in_frame must have length {self.FRAME_SIZE}, got {len(in_list)}")
135
+
136
+ c_in = (ctypes.c_float * self.FRAME_SIZE)(*in_list)
137
+ c_out = (ctypes.c_float * self.FRAME_SIZE)()
138
+
139
+ ret = self._lib.silentmic_process_frame(self._handle, c_in, c_out)
140
+ if ret != 0:
141
+ raise RuntimeError(f"silentmic_process_frame returned error code {ret}")
142
+ return [float(x) for x in c_out]
143
+
144
+ def process(self, audio: Union[Any, List[float]]) -> Union[Any, List[float]]:
145
+ """
146
+ Denoises an arbitrary length audio array in streaming 64-sample hops.
147
+ """
148
+ if HAS_NUMPY and isinstance(audio, np.ndarray):
149
+ arr = np.ascontiguousarray(audio, dtype=np.float32).flatten()
150
+ total_len = len(arr)
151
+ output = np.empty(total_len, dtype=np.float32)
152
+
153
+ full_hops = total_len // self.FRAME_SIZE
154
+ for i in range(full_hops):
155
+ start = i * self.FRAME_SIZE
156
+ end = start + self.FRAME_SIZE
157
+ output[start:end] = self.process_frame(arr[start:end])
158
+
159
+ rem = total_len % self.FRAME_SIZE
160
+ if rem > 0:
161
+ pad_frame = np.zeros(self.FRAME_SIZE, dtype=np.float32)
162
+ pad_frame[:rem] = arr[full_hops * self.FRAME_SIZE :]
163
+ cleaned_pad = self.process_frame(pad_frame)
164
+ output[full_hops * self.FRAME_SIZE :] = cleaned_pad[:rem]
165
+
166
+ return output
167
+ else:
168
+ arr = list(audio)
169
+ total_len = len(arr)
170
+ output = [0.0] * total_len
171
+
172
+ full_hops = total_len // self.FRAME_SIZE
173
+ for i in range(full_hops):
174
+ start = i * self.FRAME_SIZE
175
+ end = start + self.FRAME_SIZE
176
+ cleaned = self.process_frame(arr[start:end])
177
+ output[start:end] = cleaned
178
+
179
+ rem = total_len % self.FRAME_SIZE
180
+ if rem > 0:
181
+ pad = arr[full_hops * self.FRAME_SIZE :] + [0.0] * (self.FRAME_SIZE - rem)
182
+ cleaned = self.process_frame(pad)
183
+ output[full_hops * self.FRAME_SIZE :] = cleaned[:rem]
184
+
185
+ return output
186
+
187
+ def get_stats(self) -> Dict[str, Any]:
188
+ """Returns real-time execution telemetry and latency profiling metrics."""
189
+ stats = SilentMicStatsC()
190
+ ret = self._lib.silentmic_get_stats(self._handle, ctypes.byref(stats))
191
+ if ret != 0:
192
+ return {}
193
+ return {
194
+ "frames_processed": stats.frames_processed,
195
+ "samples_processed": stats.samples_processed,
196
+ "last_frame_micros": stats.last_frame_micros,
197
+ "max_frame_micros": stats.max_frame_micros,
198
+ "avg_frame_micros": stats.avg_frame_micros,
199
+ "cpu_budget_pct": stats.cpu_budget_pct,
200
+ }
201
+
202
+ @property
203
+ def version(self) -> str:
204
+ """Returns the native library version string."""
205
+ ver = self._lib.silentmic_version()
206
+ return ver.decode("utf-8") if ver else "unknown"
207
+
208
+ def __del__(self):
209
+ if hasattr(self, "_handle") and self._handle:
210
+ self._lib.silentmic_destroy(self._handle)
211
+ self._handle = None
@@ -0,0 +1,65 @@
1
+ Metadata-Version: 2.4
2
+ Name: pysilentmic
3
+ Version: 0.1.0
4
+ Summary: Python bindings for SilentMic-RT: Deterministic, Zero-Allocation Sub-3ms Hard Real-Time Neural Voice Isolator
5
+ Author-email: "Shah Md. Mahi" <shahmdmahi15@gmail.com>
6
+ License: MIT
7
+ Project-URL: Homepage, https://shahmdmahi.dpdns.org
8
+ Project-URL: Repository, https://github.com/shahmdmahi15/silentmic-rt
9
+ Project-URL: Documentation, https://github.com/shahmdmahi15/silentmic-rt#python-quickstart
10
+ Keywords: audio,dsp,noise-suppression,real-time,voice-isolation,pipewire
11
+ Classifier: Development Status :: 4 - Beta
12
+ Classifier: Intended Audience :: Developers
13
+ Classifier: Intended Audience :: Science/Research
14
+ Classifier: License :: OSI Approved :: MIT License
15
+ Classifier: Programming Language :: Python :: 3
16
+ Classifier: Programming Language :: Rust
17
+ Classifier: Topic :: Multimedia :: Sound/Audio :: Speech
18
+ Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
19
+ Requires-Python: >=3.8
20
+ Description-Content-Type: text/markdown
21
+ Requires-Dist: numpy>=1.20.0
22
+
23
+ # pysilentmic: Python Real-Time Voice Isolator
24
+
25
+ Python C-FFI bindings for **SilentMic-RT** — the deterministic, zero-allocation sub-3ms hard real-time neural voice isolator and virtual microphone driver.
26
+
27
+ ## Features
28
+ - **Ultra-Low Latency**: 1.33 ms frame hop (64 samples at 48,000 Hz).
29
+ - **Sub-3ms Total Latency**: Complete input-to-output algorithmic delay under 2.67 ms.
30
+ - **Zero Allocation**: Lock-free, zero heap memory allocations on audio worker threads.
31
+ - **Pure Offline SIMD**: Operates entirely on CPU SIMD instructions with zero network or cloud latency.
32
+ - **NumPy Integration**: Seamlessly denoises NumPy arrays and streaming audio generators.
33
+
34
+ ## Installation
35
+
36
+ ```bash
37
+ pip install pysilentmic
38
+ ```
39
+
40
+ ## Quickstart
41
+
42
+ ```python
43
+ import numpy as np
44
+ from pysilentmic import SilentMic
45
+
46
+ # Initialize SilentMic engine at 48kHz
47
+ mic = SilentMic(sample_rate=48000, attenuation_db=-48.0)
48
+
49
+ # Process 64-sample audio frame in real time (< 30 us)
50
+ raw_frame = np.random.randn(64).astype(np.float32)
51
+ clean_frame = mic.process_frame(raw_frame)
52
+
53
+ # Denoise complete audio file / NumPy array
54
+ noisy_audio = np.random.randn(48000 * 5).astype(np.float32)
55
+ isolated_voice = mic.process(noisy_audio)
56
+
57
+ # Access hardware telemetry
58
+ print(mic.get_stats())
59
+ ```
60
+
61
+ ## Author & Maintainer
62
+ - **Author**: Shah Md. Mahi
63
+ - **Email**: shahmdmahi15@gmail.com
64
+ - **Website**: [https://shahmdmahi.dpdns.org](https://shahmdmahi.dpdns.org)
65
+ - **License**: MIT
@@ -0,0 +1,10 @@
1
+ README.md
2
+ pyproject.toml
3
+ pysilentmic/__init__.py
4
+ pysilentmic/engine.py
5
+ pysilentmic.egg-info/PKG-INFO
6
+ pysilentmic.egg-info/SOURCES.txt
7
+ pysilentmic.egg-info/dependency_links.txt
8
+ pysilentmic.egg-info/requires.txt
9
+ pysilentmic.egg-info/top_level.txt
10
+ tests/test_pysilentmic.py
@@ -0,0 +1 @@
1
+ numpy>=1.20.0
@@ -0,0 +1 @@
1
+ pysilentmic
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+
@@ -0,0 +1,41 @@
1
+ """
2
+ Unit and integration tests for pysilentmic.
3
+ """
4
+
5
+ import unittest
6
+ import math
7
+ from pysilentmic import SilentMic
8
+
9
+ class TestPySilentMic(unittest.TestCase):
10
+ def setUp(self):
11
+ self.mic = SilentMic(sample_rate=48000, attenuation_db=-48.0)
12
+
13
+ def test_version(self):
14
+ self.assertEqual(self.mic.version, "0.1.0")
15
+
16
+ def test_process_frame(self):
17
+ in_frame = [0.1] * 64
18
+ out_frame = self.mic.process_frame(in_frame)
19
+ self.assertEqual(len(out_frame), 64)
20
+ for val in out_frame:
21
+ self.assertTrue(math.isfinite(val))
22
+
23
+ def test_process_stream(self):
24
+ # 1000 samples of synthetic audio at 48kHz
25
+ audio = [
26
+ 0.5 * math.sin(2 * math.pi * 440 * (i / 48000.0)) + 0.05 * ((i % 13) / 13.0)
27
+ for i in range(1280)
28
+ ]
29
+
30
+ cleaned = self.mic.process(audio)
31
+ self.assertEqual(len(cleaned), len(audio))
32
+ for val in cleaned:
33
+ self.assertTrue(math.isfinite(val))
34
+
35
+ stats = self.mic.get_stats()
36
+ self.assertGreater(stats["frames_processed"], 15)
37
+ self.assertGreater(stats["avg_frame_micros"], 0.0)
38
+ print(f"\n[PySilentMic Verified] Telemetry: {stats}")
39
+
40
+ if __name__ == "__main__":
41
+ unittest.main()