kenenet 1.1.3__py3-none-any.whl → 1.1.4__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.
- kenenet/__init__.py +90 -96
- {kenenet-1.1.3.dist-info → kenenet-1.1.4.dist-info}/METADATA +1 -1
- kenenet-1.1.4.dist-info/RECORD +5 -0
- kenenet-1.1.3.dist-info/RECORD +0 -5
- {kenenet-1.1.3.dist-info → kenenet-1.1.4.dist-info}/WHEEL +0 -0
- {kenenet-1.1.3.dist-info → kenenet-1.1.4.dist-info}/top_level.txt +0 -0
kenenet/__init__.py
CHANGED
@@ -208,105 +208,99 @@ import time
|
|
208
208
|
import zhmiscellany
|
209
209
|
|
210
210
|
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
|
216
|
-
|
211
|
+
class load_audio:
|
212
|
+
def __init__(self):
|
213
|
+
pygame.mixer.init()
|
214
|
+
self.handles = []
|
215
|
+
self.cached_audios = {}
|
216
|
+
|
217
|
+
def change_speed(self, sound, speed=1.0):
|
218
|
+
new_frame_rate = int(sound.frame_rate * speed)
|
219
|
+
new_sound = sound._spawn(sound.raw_data, overrides={"frame_rate": new_frame_rate})
|
220
|
+
# Resample back to the original frame rate for compatibility
|
221
|
+
return new_sound.set_frame_rate(sound.frame_rate)
|
222
|
+
|
223
|
+
class SoundHandle:
|
224
|
+
def __init__(self, thread, stop_event, sound_channel=None):
|
225
|
+
self.thread = thread
|
226
|
+
self.stop_event = stop_event
|
227
|
+
self.sound_channel = sound_channel
|
217
228
|
|
218
|
-
def
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
|
229
|
+
def stop(self):
|
230
|
+
self.stop_event.set()
|
231
|
+
if self.sound_channel is not None:
|
232
|
+
self.sound_channel.stop()
|
233
|
+
if hasattr(self.thread, 'kill'):
|
234
|
+
self.thread.kill()
|
235
|
+
self.thread.join(timeout=1.0)
|
236
|
+
|
237
|
+
def play(self, file_path, volume=1.0, speed=1, loop=False):
|
238
|
+
# Handle random speed selection
|
239
|
+
if isinstance(speed, tuple):
|
240
|
+
speed = random.uniform(speed[0], speed[1])
|
223
241
|
|
224
|
-
|
225
|
-
|
226
|
-
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
def stop(self):
|
231
|
-
self.stop_event.set()
|
232
|
-
if self.sound_channel is not None:
|
233
|
-
self.sound_channel.stop()
|
234
|
-
if hasattr(self.thread, 'kill'):
|
235
|
-
self.thread.kill()
|
236
|
-
self.thread.join(timeout=1.0)
|
242
|
+
# Load or use cached audio
|
243
|
+
if file_path not in self.cached_audios:
|
244
|
+
sound = AudioSegment.from_file(file_path)
|
245
|
+
self.cached_audios[file_path] = sound
|
246
|
+
else:
|
247
|
+
sound = self.cached_audios[file_path]
|
237
248
|
|
238
|
-
|
239
|
-
|
240
|
-
|
241
|
-
|
242
|
-
|
243
|
-
|
244
|
-
|
245
|
-
|
246
|
-
|
247
|
-
|
248
|
-
|
249
|
-
|
250
|
-
|
251
|
-
|
252
|
-
|
253
|
-
|
254
|
-
|
255
|
-
|
256
|
-
|
257
|
-
|
258
|
-
|
259
|
-
|
260
|
-
|
261
|
-
|
262
|
-
|
263
|
-
|
264
|
-
|
265
|
-
|
266
|
-
|
267
|
-
|
268
|
-
|
269
|
-
|
270
|
-
|
271
|
-
|
272
|
-
|
273
|
-
|
274
|
-
|
275
|
-
|
276
|
-
|
277
|
-
|
278
|
-
|
279
|
-
|
280
|
-
|
281
|
-
|
282
|
-
|
283
|
-
|
284
|
-
|
285
|
-
|
286
|
-
|
287
|
-
|
288
|
-
|
289
|
-
|
290
|
-
|
291
|
-
|
292
|
-
|
293
|
-
except Exception as e:
|
294
|
-
print(f"Error playing sound: {e}")
|
295
|
-
if channel:
|
296
|
-
channel.stop()
|
297
|
-
|
298
|
-
# Start playback in a separate thread so it's nonblocking
|
299
|
-
thread = threading.Thread(target=play_sound, daemon=True)
|
300
|
-
thread.start()
|
301
|
-
|
302
|
-
handle = self.SoundHandle(thread, stop_event, channel)
|
303
|
-
self.handles.append(handle)
|
304
|
-
return handle
|
305
|
-
|
306
|
-
if sandbox_pygame:
|
307
|
-
return zhmiscellany.processing.synchronous_class_multiprocess(SoundEngine)
|
308
|
-
else:
|
309
|
-
return SoundEngine()
|
249
|
+
# Adjust volume: pydub uses decibels.
|
250
|
+
# To convert a multiplier to dB change, use: gain = 20 * log10(volume)
|
251
|
+
if volume <= 0:
|
252
|
+
gain = -120
|
253
|
+
else:
|
254
|
+
gain = 20 * math.log10(volume)
|
255
|
+
sound = sound.apply_gain(gain)
|
256
|
+
|
257
|
+
# Apply speed change if needed
|
258
|
+
if speed != 1.0:
|
259
|
+
sound = self.change_speed(sound, speed)
|
260
|
+
|
261
|
+
# Convert to in-memory file object that pygame can read
|
262
|
+
buffer = io.BytesIO()
|
263
|
+
sound.export(buffer, format="wav")
|
264
|
+
buffer.seek(0)
|
265
|
+
|
266
|
+
# Create a pygame Sound object
|
267
|
+
pygame_sound = pygame.mixer.Sound(buffer)
|
268
|
+
|
269
|
+
# Set volume (pygame uses 0.0 to 1.0)
|
270
|
+
pygame_sound.set_volume(min(1.0, max(0.0, volume)))
|
271
|
+
|
272
|
+
stop_event = threading.Event()
|
273
|
+
channel = None
|
274
|
+
|
275
|
+
def play_sound():
|
276
|
+
nonlocal channel
|
277
|
+
try:
|
278
|
+
# Find an available channel
|
279
|
+
channel = pygame.mixer.find_channel()
|
280
|
+
if channel is None:
|
281
|
+
# If no channel is available, create a new one
|
282
|
+
current_channels = pygame.mixer.get_num_channels()
|
283
|
+
pygame.mixer.set_num_channels(current_channels + 1)
|
284
|
+
channel = pygame.mixer.Channel(current_channels)
|
285
|
+
|
286
|
+
# Start playing
|
287
|
+
channel.play(pygame_sound, loops=-1 if loop else 0)
|
288
|
+
|
289
|
+
# Wait until sound is done or stopped
|
290
|
+
while channel.get_busy() and not stop_event.is_set():
|
291
|
+
time.sleep(0.1)
|
292
|
+
except Exception as e:
|
293
|
+
print(f"Error playing sound: {e}")
|
294
|
+
if channel:
|
295
|
+
channel.stop()
|
296
|
+
|
297
|
+
# Start playback in a separate thread so it's nonblocking
|
298
|
+
thread = threading.Thread(target=play_sound, daemon=True)
|
299
|
+
thread.start()
|
300
|
+
|
301
|
+
handle = self.SoundHandle(thread, stop_event, channel)
|
302
|
+
self.handles.append(handle)
|
303
|
+
return handle
|
310
304
|
|
311
305
|
def time_func(func, loop=10000, *args, **kwargs):
|
312
306
|
func_name = getattr(func, '__name__', repr(func))
|
@@ -0,0 +1,5 @@
|
|
1
|
+
kenenet/__init__.py,sha256=5-SKuJjlAWkWWuiU9_kt-DAYtShtvdCzUMdRaRzM1W8,21162
|
2
|
+
kenenet-1.1.4.dist-info/METADATA,sha256=WXWFu4xBAQEVIFY99rlDoM82hNNX7DzWVgUGGlEz5BU,1693
|
3
|
+
kenenet-1.1.4.dist-info/WHEEL,sha256=tZoeGjtWxWRfdplE7E3d45VPlLNQnvbKiYnx7gwAy8A,92
|
4
|
+
kenenet-1.1.4.dist-info/top_level.txt,sha256=gUsWXLrM0jF4b4nbYJZdksdFewIx_F3xOF-zER8fMuQ,8
|
5
|
+
kenenet-1.1.4.dist-info/RECORD,,
|
kenenet-1.1.3.dist-info/RECORD
DELETED
@@ -1,5 +0,0 @@
|
|
1
|
-
kenenet/__init__.py,sha256=gRg62hDZd49s-OwmwTPnCrcZ9Ww2OrJTa5GdVP9eTj0,21730
|
2
|
-
kenenet-1.1.3.dist-info/METADATA,sha256=rbBX7ov2MHlVbz4hcTIDQK4sy8Gi2fH1d0EU2J1hfdA,1693
|
3
|
-
kenenet-1.1.3.dist-info/WHEEL,sha256=tZoeGjtWxWRfdplE7E3d45VPlLNQnvbKiYnx7gwAy8A,92
|
4
|
-
kenenet-1.1.3.dist-info/top_level.txt,sha256=gUsWXLrM0jF4b4nbYJZdksdFewIx_F3xOF-zER8fMuQ,8
|
5
|
-
kenenet-1.1.3.dist-info/RECORD,,
|
File without changes
|
File without changes
|