精度実験用スクリプトの角度知らせ機能の音声を符号と数字に分割

This commit is contained in:
agomizi1cm committed 2026-10-05 15:53:29 +09:00
1 parent 38bdea0c2a
commit a7cf0d33a0
1 file changed
+48 -20
+48 -20
View File
@@ -44,20 +44,19 @@ INTERVAL_AUDIO = {
"block": Path("assets/audio/block.wav"),
"auto": Path("assets/audio/auto_interval.wav"),
}
# One prepared announcement file per target yaw angle.
# Angle announcement is composed from separate sign and number WAV files.
# Prepare these files under assets/audio/ using exactly these names.
ANGLE_AUDIO = {
0.0: Path("assets/audio/yaw_0.wav"),
5.0: Path("assets/audio/yaw_plus_5.wav"),
-5.0: Path("assets/audio/yaw_minus_5.wav"),
10.0: Path("assets/audio/yaw_plus_10.wav"),
-10.0: Path("assets/audio/yaw_minus_10.wav"),
15.0: Path("assets/audio/yaw_plus_15.wav"),
-15.0: Path("assets/audio/yaw_minus_15.wav"),
20.0: Path("assets/audio/yaw_plus_20.wav"),
-20.0: Path("assets/audio/yaw_minus_20.wav"),
30.0: Path("assets/audio/yaw_plus_30.wav"),
-30.0: Path("assets/audio/yaw_minus_30.wav"),
ANGLE_SIGN_AUDIO = {
"plus": Path("assets/audio/plus.wav"),
"minus": Path("assets/audio/minus.wav"),
}
ANGLE_NUMBER_AUDIO = {
0: Path("assets/audio/0.wav"),
5: Path("assets/audio/5.wav"),
10: Path("assets/audio/10.wav"),
15: Path("assets/audio/15.wav"),
20: Path("assets/audio/20.wav"),
30: Path("assets/audio/30.wav"),
}
LOGGER = logging.getLogger(__name__)
DEFAULT_ANGLES = (0.0, 5.0, -5.0, 10.0, -10.0, 15.0, -15.0, 20.0, -20.0, 30.0, -30.0)
@@ -185,14 +184,22 @@ class IntervalAudioPlayer:
self._sounds[kind] = mixer.Sound(str(path))
except Exception as exc:
LOGGER.error("Failed to load interval audio %s: %s", path, exc)
for angle, path in ANGLE_AUDIO.items():
for sign, path in ANGLE_SIGN_AUDIO.items():
if not path.is_file():
LOGGER.warning("Angle announcement audio file does not exist (%+g deg): %s", angle, path)
LOGGER.warning("Angle sign audio file does not exist (%s): %s", sign, path)
continue
try:
self._sounds[f"angle:{angle:g}"] = mixer.Sound(str(path))
self._sounds[f"angle_sign:{sign}"] = mixer.Sound(str(path))
except Exception as exc:
LOGGER.error("Failed to load angle announcement audio (%+g deg) %s: %s", angle, path, exc)
LOGGER.error("Failed to load angle sign audio (%s) %s: %s", sign, path, exc)
for number, path in ANGLE_NUMBER_AUDIO.items():
if not path.is_file():
LOGGER.warning("Angle number audio file does not exist (%d): %s", number, path)
continue
try:
self._sounds[f"angle_number:{number}"] = mixer.Sound(str(path))
except Exception as exc:
LOGGER.error("Failed to load angle number audio (%d) %s: %s", number, path, exc)
except Exception as exc:
LOGGER.error("Failed to initialize pygame mixer for interval audio: %s", exc)
self._initialized = False
@@ -210,9 +217,30 @@ class IntervalAudioPlayer:
return False
def play_angle(self, angle: float) -> bool:
"""Announce the target yaw angle using the prepared per-angle WAV file."""
key = f"angle:{angle:g}"
return self.play(key)
"""Announce the target yaw as separate sign + number WAV files."""
value = float(angle)
if value == 0:
return self.play("angle_number:0")
number = int(abs(value)) if abs(value).is_integer() else None
if number is None:
LOGGER.warning("No integer angle audio is defined for %+g deg", value)
return False
sign = "plus" if value > 0 else "minus"
sign_played = self.play(f"angle_sign:{sign}")
# Wait until the sign audio has finished before starting the number.
# pygame Sound.play() is asynchronous, so use the sound length when available.
sign_sound = self._sounds.get(f"angle_sign:{sign}")
if sign_played and sign_sound is not None:
try:
duration_ms = max(0, int(float(sign_sound.get_length()) * 1000)) # type: ignore[attr-defined]
if duration_ms:
time.sleep(duration_ms / 1000.0)
except Exception:
pass
number_played = self.play(f"angle_number:{number}")
return sign_played and number_played
def close(self) -> None:
if self._closed: