精度実験用スクリプトの角度知らせ機能の音声を符号と数字に分割
This commit is contained in:
1 parent
38bdea0c2a
commit
a7cf0d33a0
1 file changed
+48
-20
+48
-20
@@ -44,20 +44,19 @@ INTERVAL_AUDIO = {
|
|||||||
"block": Path("assets/audio/block.wav"),
|
"block": Path("assets/audio/block.wav"),
|
||||||
"auto": Path("assets/audio/auto_interval.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.
|
# Prepare these files under assets/audio/ using exactly these names.
|
||||||
ANGLE_AUDIO = {
|
ANGLE_SIGN_AUDIO = {
|
||||||
0.0: Path("assets/audio/yaw_0.wav"),
|
"plus": Path("assets/audio/plus.wav"),
|
||||||
5.0: Path("assets/audio/yaw_plus_5.wav"),
|
"minus": Path("assets/audio/minus.wav"),
|
||||||
-5.0: Path("assets/audio/yaw_minus_5.wav"),
|
}
|
||||||
10.0: Path("assets/audio/yaw_plus_10.wav"),
|
ANGLE_NUMBER_AUDIO = {
|
||||||
-10.0: Path("assets/audio/yaw_minus_10.wav"),
|
0: Path("assets/audio/0.wav"),
|
||||||
15.0: Path("assets/audio/yaw_plus_15.wav"),
|
5: Path("assets/audio/5.wav"),
|
||||||
-15.0: Path("assets/audio/yaw_minus_15.wav"),
|
10: Path("assets/audio/10.wav"),
|
||||||
20.0: Path("assets/audio/yaw_plus_20.wav"),
|
15: Path("assets/audio/15.wav"),
|
||||||
-20.0: Path("assets/audio/yaw_minus_20.wav"),
|
20: Path("assets/audio/20.wav"),
|
||||||
30.0: Path("assets/audio/yaw_plus_30.wav"),
|
30: Path("assets/audio/30.wav"),
|
||||||
-30.0: Path("assets/audio/yaw_minus_30.wav"),
|
|
||||||
}
|
}
|
||||||
LOGGER = logging.getLogger(__name__)
|
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)
|
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))
|
self._sounds[kind] = mixer.Sound(str(path))
|
||||||
except Exception as exc:
|
except Exception as exc:
|
||||||
LOGGER.error("Failed to load interval audio %s: %s", path, 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():
|
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
|
continue
|
||||||
try:
|
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:
|
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:
|
except Exception as exc:
|
||||||
LOGGER.error("Failed to initialize pygame mixer for interval audio: %s", exc)
|
LOGGER.error("Failed to initialize pygame mixer for interval audio: %s", exc)
|
||||||
self._initialized = False
|
self._initialized = False
|
||||||
@@ -210,9 +217,30 @@ class IntervalAudioPlayer:
|
|||||||
return False
|
return False
|
||||||
|
|
||||||
def play_angle(self, angle: float) -> bool:
|
def play_angle(self, angle: float) -> bool:
|
||||||
"""Announce the target yaw angle using the prepared per-angle WAV file."""
|
"""Announce the target yaw as separate sign + number WAV files."""
|
||||||
key = f"angle:{angle:g}"
|
value = float(angle)
|
||||||
return self.play(key)
|
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:
|
def close(self) -> None:
|
||||||
if self._closed:
|
if self._closed:
|
||||||
|
|||||||
Reference in new issue
Block a user