|
9 | 9 | import numpy as np |
10 | 10 | import time |
11 | 11 | from pathlib import Path |
| 12 | +from collections import OrderedDict |
12 | 13 |
|
13 | 14 | from .generator import WaveSamplesBuilder |
14 | 15 | from .effects import * |
@@ -426,10 +427,20 @@ def play_wav(self, wav_file: str) -> tuple[bytes, float]: |
426 | 427 | if not file_path.exists() or not file_path.is_file(): |
427 | 428 | raise FileNotFoundError(f"WAV file not found: {wav_file}") |
428 | 429 |
|
| 430 | + wav_cache = OrderedDict() |
| 431 | + |
| 432 | + if wav_file in wav_cache: |
| 433 | + return wav_cache[wav_file] |
| 434 | + |
429 | 435 | with wave.open(wav_file, "rb") as wav: |
430 | 436 | # Read all frames (raw PCM data) |
431 | 437 | duration = wav.getnframes() / wav.getframerate() |
432 | | - return (wav.readframes(wav.getnframes()), duration) |
| 438 | + wav_data = wav.readframes(wav.getnframes()) |
| 439 | + if len(wav_cache) < 250 * 1024: # 250 KB cache limit |
| 440 | + wav_cache[wav_file] = (wav_data, duration) |
| 441 | + if len(wav_cache) > 10: |
| 442 | + wav_cache.popitem(last=False) |
| 443 | + return (wav_data, duration) |
433 | 444 |
|
434 | 445 | return (None, None) |
435 | 446 |
|
@@ -585,7 +596,13 @@ def play_abc(self, abc_string: str, volume: float = None, block: bool = False): |
585 | 596 | if block: |
586 | 597 | time.sleep(overall_duration) |
587 | 598 |
|
588 | | - def play_wav(self, wav_file: str, volume: float = None, block: bool = False): |
| 599 | + def play_wav(self, wav_file: str, block: bool = False): |
| 600 | + """ |
| 601 | + Play a WAV audio data block. |
| 602 | + Args: |
| 603 | + wav_file (str): The WAV audio file path. |
| 604 | + block (bool): If True, block until the entire WAV file has been played. |
| 605 | + """ |
589 | 606 | to_play, duration = super().play_wav(wav_file) |
590 | 607 | self._output_device.play(to_play, block_on_queue=False) |
591 | 608 | if block and duration > 0.0: |
|
0 commit comments