random-tone-generator 0.0.1__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,60 @@
1
+ Metadata-Version: 2.4
2
+ Name: random_tone_generator
3
+ Version: 0.0.1
4
+ Summary: Random sweep/hold tone generator with explicit-duration playback.
5
+ Author: Sithu Ye Htun
6
+ License: MIT
7
+ Project-URL: Homepage, https://github.com/leo007-htun/random_tone_generator
8
+ Project-URL: Repository, https://github.com/leo007-htun/random_tone_generator
9
+ Project-URL: Issues, https://github.com/leo007-htun/random_tone_generator/issues
10
+ Keywords: audio,tone,signal,generator,sweep,sound
11
+ Classifier: Development Status :: 3 - Alpha
12
+ Classifier: Intended Audience :: Developers
13
+ Classifier: License :: OSI Approved :: MIT License
14
+ Classifier: Operating System :: OS Independent
15
+ Classifier: Programming Language :: Python :: 3
16
+ Classifier: Programming Language :: Python :: 3 :: Only
17
+ Classifier: Programming Language :: Python :: 3.9
18
+ Classifier: Programming Language :: Python :: 3.10
19
+ Classifier: Programming Language :: Python :: 3.11
20
+ Classifier: Programming Language :: Python :: 3.12
21
+ Classifier: Topic :: Multimedia :: Sound/Audio
22
+ Requires-Python: >=3.9
23
+ Description-Content-Type: text/markdown
24
+ Requires-Dist: numpy>=1.23
25
+ Requires-Dist: sounddevice>=0.4.6
26
+
27
+ # random_tone_generator
28
+
29
+ A small Python utility to generate randomized tone sweeps and holds in real time.
30
+
31
+ ## Features
32
+
33
+ - Real-time audio output via `sounddevice`
34
+ - Random sweep patterns:
35
+ - `base -> random -> base`
36
+ - `base -> random -> random -> base`
37
+ - Adjustable:
38
+ - playback speed
39
+ - min/max frequency
40
+ - amplitude
41
+ - Explicit playback duration with `play_for(seconds)`
42
+
43
+ ## function calls
44
+ gen.set_speed(speed) # float, must be > 0
45
+ gen.set_max_freq(max_freq) # float, must be >= min_freq
46
+ gen.set_min_freq(min_freq) # float, must be <= max_freq (if implemented)
47
+ gen.set_base_freq(base_freq) # float (if implemented)
48
+ gen.set_amplitude(amplitude) # float in [0.0, 1.0] (if implemented)
49
+ state = gen.get_state() # returns dict of current settings
50
+ gen.play_for(seconds) # play for N seconds (explicit mode)
51
+
52
+ ---
53
+
54
+ ## Installation
55
+
56
+ ```bash
57
+ pip install random_tone_generator
58
+
59
+
60
+
@@ -0,0 +1,34 @@
1
+ # random_tone_generator
2
+
3
+ A small Python utility to generate randomized tone sweeps and holds in real time.
4
+
5
+ ## Features
6
+
7
+ - Real-time audio output via `sounddevice`
8
+ - Random sweep patterns:
9
+ - `base -> random -> base`
10
+ - `base -> random -> random -> base`
11
+ - Adjustable:
12
+ - playback speed
13
+ - min/max frequency
14
+ - amplitude
15
+ - Explicit playback duration with `play_for(seconds)`
16
+
17
+ ## function calls
18
+ gen.set_speed(speed) # float, must be > 0
19
+ gen.set_max_freq(max_freq) # float, must be >= min_freq
20
+ gen.set_min_freq(min_freq) # float, must be <= max_freq (if implemented)
21
+ gen.set_base_freq(base_freq) # float (if implemented)
22
+ gen.set_amplitude(amplitude) # float in [0.0, 1.0] (if implemented)
23
+ state = gen.get_state() # returns dict of current settings
24
+ gen.play_for(seconds) # play for N seconds (explicit mode)
25
+
26
+ ---
27
+
28
+ ## Installation
29
+
30
+ ```bash
31
+ pip install random_tone_generator
32
+
33
+
34
+
@@ -0,0 +1,43 @@
1
+ [build-system]
2
+ requires = ["setuptools>=69", "wheel"]
3
+ build-backend = "setuptools.build_meta"
4
+
5
+ [project]
6
+ name = "random_tone_generator"
7
+ version = "0.0.1"
8
+ description = "Random sweep/hold tone generator with explicit-duration playback."
9
+ readme = "README.md"
10
+ requires-python = ">=3.9"
11
+ license = { text = "MIT" }
12
+ authors = [
13
+ { name = "Sithu Ye Htun" }
14
+ ]
15
+ keywords = ["audio", "tone", "signal", "generator", "sweep", "sound"]
16
+ classifiers = [
17
+ "Development Status :: 3 - Alpha",
18
+ "Intended Audience :: Developers",
19
+ "License :: OSI Approved :: MIT License",
20
+ "Operating System :: OS Independent",
21
+ "Programming Language :: Python :: 3",
22
+ "Programming Language :: Python :: 3 :: Only",
23
+ "Programming Language :: Python :: 3.9",
24
+ "Programming Language :: Python :: 3.10",
25
+ "Programming Language :: Python :: 3.11",
26
+ "Programming Language :: Python :: 3.12",
27
+ "Topic :: Multimedia :: Sound/Audio"
28
+ ]
29
+ dependencies = [
30
+ "numpy>=1.23",
31
+ "sounddevice>=0.4.6"
32
+ ]
33
+
34
+ [project.urls]
35
+ Homepage = "https://github.com/leo007-htun/random_tone_generator"
36
+ Repository = "https://github.com/leo007-htun/random_tone_generator"
37
+ Issues = "https://github.com/leo007-htun/random_tone_generator/issues"
38
+
39
+ [tool.setuptools]
40
+ py-modules = ["random_tone_generator"]
41
+
42
+ [tool.setuptools.packages.find]
43
+ where = ["."]
@@ -0,0 +1,60 @@
1
+ Metadata-Version: 2.4
2
+ Name: random_tone_generator
3
+ Version: 0.0.1
4
+ Summary: Random sweep/hold tone generator with explicit-duration playback.
5
+ Author: Sithu Ye Htun
6
+ License: MIT
7
+ Project-URL: Homepage, https://github.com/leo007-htun/random_tone_generator
8
+ Project-URL: Repository, https://github.com/leo007-htun/random_tone_generator
9
+ Project-URL: Issues, https://github.com/leo007-htun/random_tone_generator/issues
10
+ Keywords: audio,tone,signal,generator,sweep,sound
11
+ Classifier: Development Status :: 3 - Alpha
12
+ Classifier: Intended Audience :: Developers
13
+ Classifier: License :: OSI Approved :: MIT License
14
+ Classifier: Operating System :: OS Independent
15
+ Classifier: Programming Language :: Python :: 3
16
+ Classifier: Programming Language :: Python :: 3 :: Only
17
+ Classifier: Programming Language :: Python :: 3.9
18
+ Classifier: Programming Language :: Python :: 3.10
19
+ Classifier: Programming Language :: Python :: 3.11
20
+ Classifier: Programming Language :: Python :: 3.12
21
+ Classifier: Topic :: Multimedia :: Sound/Audio
22
+ Requires-Python: >=3.9
23
+ Description-Content-Type: text/markdown
24
+ Requires-Dist: numpy>=1.23
25
+ Requires-Dist: sounddevice>=0.4.6
26
+
27
+ # random_tone_generator
28
+
29
+ A small Python utility to generate randomized tone sweeps and holds in real time.
30
+
31
+ ## Features
32
+
33
+ - Real-time audio output via `sounddevice`
34
+ - Random sweep patterns:
35
+ - `base -> random -> base`
36
+ - `base -> random -> random -> base`
37
+ - Adjustable:
38
+ - playback speed
39
+ - min/max frequency
40
+ - amplitude
41
+ - Explicit playback duration with `play_for(seconds)`
42
+
43
+ ## function calls
44
+ gen.set_speed(speed) # float, must be > 0
45
+ gen.set_max_freq(max_freq) # float, must be >= min_freq
46
+ gen.set_min_freq(min_freq) # float, must be <= max_freq (if implemented)
47
+ gen.set_base_freq(base_freq) # float (if implemented)
48
+ gen.set_amplitude(amplitude) # float in [0.0, 1.0] (if implemented)
49
+ state = gen.get_state() # returns dict of current settings
50
+ gen.play_for(seconds) # play for N seconds (explicit mode)
51
+
52
+ ---
53
+
54
+ ## Installation
55
+
56
+ ```bash
57
+ pip install random_tone_generator
58
+
59
+
60
+
@@ -0,0 +1,8 @@
1
+ README.md
2
+ pyproject.toml
3
+ random_tone_generator.py
4
+ random_tone_generator.egg-info/PKG-INFO
5
+ random_tone_generator.egg-info/SOURCES.txt
6
+ random_tone_generator.egg-info/dependency_links.txt
7
+ random_tone_generator.egg-info/requires.txt
8
+ random_tone_generator.egg-info/top_level.txt
@@ -0,0 +1,2 @@
1
+ numpy>=1.23
2
+ sounddevice>=0.4.6
@@ -0,0 +1,2 @@
1
+ dist
2
+ random_tone_generator
@@ -0,0 +1,148 @@
1
+ import random
2
+ import numpy as np
3
+ import sounddevice as sd
4
+
5
+
6
+ class RandomToneGenerator:
7
+ def __init__(
8
+ self,
9
+ sample_rate=44100,
10
+ base_freq=100.0,
11
+ min_freq=100.0,
12
+ max_freq=8000.0,
13
+ amplitude=0.2,
14
+ speed=1.0,
15
+ base_sweep_min=0.04,
16
+ base_sweep_max=0.25,
17
+ base_hold_min=0.00,
18
+ base_hold_max=0.05,
19
+ min_duration_floor=0.003,
20
+ ):
21
+ self.sample_rate = sample_rate
22
+ self.base_freq = float(base_freq)
23
+ self.min_freq = float(min_freq)
24
+ self.max_freq = float(max_freq)
25
+ self.amplitude = float(amplitude)
26
+ self.speed = float(speed)
27
+
28
+ self.base_sweep_min = float(base_sweep_min)
29
+ self.base_sweep_max = float(base_sweep_max)
30
+ self.base_hold_min = float(base_hold_min)
31
+ self.base_hold_max = float(base_hold_max)
32
+ self.min_duration_floor = float(min_duration_floor)
33
+
34
+ self._phase = 0.0
35
+
36
+ def set_speed(self, speed: float):
37
+ if speed <= 0:
38
+ raise ValueError("speed must be > 0")
39
+ self.speed = float(speed)
40
+
41
+ def set_max_freq(self, max_freq: float):
42
+ if max_freq < self.min_freq:
43
+ raise ValueError("max_freq must be >= min_freq")
44
+ self.max_freq = float(max_freq)
45
+
46
+ def get_state(self):
47
+ return {
48
+ "base_freq": self.base_freq,
49
+ "min_freq": self.min_freq,
50
+ "max_freq": self.max_freq,
51
+ "amplitude": self.amplitude,
52
+ "speed": self.speed,
53
+ }
54
+
55
+ def _scaled_times(self):
56
+ sweep_min = max(self.min_duration_floor, self.base_sweep_min / self.speed)
57
+ sweep_max = max(self.min_duration_floor, self.base_sweep_max / self.speed)
58
+ hold_min = max(0.0, self.base_hold_min / self.speed)
59
+ hold_max = max(0.0, self.base_hold_max / self.speed)
60
+ return sweep_min, sweep_max, hold_min, hold_max
61
+
62
+ def _sweep(self, f0, f1, dur):
63
+ n = max(1, int(self.sample_rate * dur))
64
+ freq_curve = np.linspace(f0, f1, n, endpoint=False)
65
+ phase_inc = 2 * np.pi * freq_curve / self.sample_rate
66
+ phase_curve = self._phase + np.cumsum(phase_inc)
67
+ y = self.amplitude * np.sin(phase_curve)
68
+
69
+ fade_len = min(256, n // 8)
70
+ if fade_len > 1:
71
+ fade = np.linspace(0, 1, fade_len)
72
+ y[:fade_len] *= fade
73
+ y[-fade_len:] *= fade[::-1]
74
+
75
+ self._phase = float(phase_curve[-1] % (2 * np.pi))
76
+ return y.astype(np.float32)
77
+
78
+ def _hold(self, f, dur):
79
+ n = max(1, int(self.sample_rate * dur))
80
+ phase_inc = 2 * np.pi * f / self.sample_rate
81
+ phase_curve = self._phase + phase_inc * np.arange(1, n + 1)
82
+ y = self.amplitude * np.sin(phase_curve)
83
+ self._phase = float(phase_curve[-1] % (2 * np.pi))
84
+ return y.astype(np.float32)
85
+
86
+ def _write(self, stream, block):
87
+ stream.write(block.reshape(-1, 1))
88
+
89
+ def play_for(self, seconds: float):
90
+ """
91
+ Plays only for `seconds`, then returns.
92
+ Pattern:
93
+ 1) 100 -> rand -> 100
94
+ 2) 100 -> rand -> rand -> 100
95
+ """
96
+ if seconds <= 0:
97
+ return
98
+
99
+ sweep_min, sweep_max, hold_min, hold_max = self._scaled_times()
100
+
101
+ elapsed = 0.0
102
+ with sd.OutputStream(samplerate=self.sample_rate, channels=1, dtype="float32") as stream:
103
+ while elapsed < seconds:
104
+ # Pattern 1
105
+ a = random.uniform(self.min_freq, self.max_freq)
106
+
107
+ d = random.uniform(sweep_min, sweep_max)
108
+ b = self._sweep(self.base_freq, a, d); self._write(stream, b); elapsed += d
109
+ if elapsed >= seconds: break
110
+
111
+ h = random.uniform(hold_min, hold_max)
112
+ if h > 0:
113
+ b = self._hold(a, h); self._write(stream, b); elapsed += h
114
+ if elapsed >= seconds: break
115
+
116
+ d = random.uniform(sweep_min, sweep_max)
117
+ b = self._sweep(a, self.base_freq, d); self._write(stream, b); elapsed += d
118
+ if elapsed >= seconds: break
119
+
120
+ h = random.uniform(hold_min, hold_max)
121
+ if h > 0:
122
+ b = self._hold(self.base_freq, h); self._write(stream, b); elapsed += h
123
+ if elapsed >= seconds: break
124
+
125
+ # Pattern 2
126
+ bfreq = random.uniform(self.min_freq, self.max_freq)
127
+ cfreq = random.uniform(self.min_freq, self.max_freq)
128
+
129
+ d = random.uniform(sweep_min, sweep_max)
130
+ b = self._sweep(self.base_freq, bfreq, d); self._write(stream, b); elapsed += d
131
+ if elapsed >= seconds: break
132
+
133
+ h = random.uniform(hold_min, hold_max)
134
+ if h > 0:
135
+ b = self._hold(bfreq, h); self._write(stream, b); elapsed += h
136
+ if elapsed >= seconds: break
137
+
138
+ d = random.uniform(sweep_min, sweep_max)
139
+ b = self._sweep(bfreq, cfreq, d); self._write(stream, b); elapsed += d
140
+ if elapsed >= seconds: break
141
+
142
+ h = random.uniform(hold_min, hold_max)
143
+ if h > 0:
144
+ b = self._hold(cfreq, h); self._write(stream, b); elapsed += h
145
+ if elapsed >= seconds: break
146
+
147
+ d = random.uniform(sweep_min, sweep_max)
148
+ b = self._sweep(cfreq, self.base_freq, d); self._write(stream, b); elapsed += d
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+