Ctrl K
ComunidadGuías…

rex/wake_acknowledgment.py

Rama master · réplica de lectura del repositorio original.

Archivo original ↗Preguntar a KiBot
"""Utilities for generating the wake confirmation sound on demand."""

from __future__ import annotations

import math
import os
import struct
import wave

DEFAULT_WAKE_ACK_RELATIVE_PATH = os.path.join("assets", "wake_acknowledgment.wav")
_LEGACY_WAKE_ACK_RELATIVE_PATHS = (
    os.path.join("assets", "rex_wake_acknowledgment.wav"),
    os.path.join("assets", "rex_wake_acknowledgment (1).wav"),
)
_SAMPLE_RATE = 24_000
_DURATION_SECONDS = 0.35
_AMPLITUDE = 12_000
_FREQUENCIES = (880.0, 660.0)
_FADE_DURATION = 0.02


def _envelope(time_seconds: float) -> float:
    """Compute a simple fade-in/fade-out envelope to avoid clicks."""

    fade_in = min(time_seconds / _FADE_DURATION, 1.0)
    fade_out = min(max((_DURATION_SECONDS - time_seconds) / _FADE_DURATION, 0.0), 1.0)
    return min(fade_in, fade_out)


def _cleanup_legacy_acknowledgment_samples(base_directory: str) -> None:
    """Delete outdated wake-acknowledgment audio files if they linger."""

    for relative_path in _LEGACY_WAKE_ACK_RELATIVE_PATHS:
        candidate = os.path.join(base_directory, relative_path)
        try:
            if os.path.exists(candidate):
                os.remove(candidate)
        except OSError:
            # If we cannot remove the file (e.g., permissions), fall back to the
            # safer option of leaving it in place. The repository integrity test
            # will still flag the tracked artifact.
            continue


def ensure_wake_acknowledgment_sound(
    path: str | None = None,
    *,
    repo_root: str | None = None,
) -> str:
    """Return the absolute path to the wake confirmation sound sample.

    The sample is generated as a short dual-tone sine wave if it does not
    already exist. The target location defaults to ``assets/wake_acknowledgment.wav``
    within the repository, but callers can override ``path`` to create it elsewhere
    (useful for tests).
    """

    if repo_root is None:
        repo_root = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))

    if path is None:
        target_path = os.path.join(repo_root, DEFAULT_WAKE_ACK_RELATIVE_PATH)
    elif os.path.isabs(path):
        target_path = path
    else:
        target_path = os.path.join(repo_root, path)

    _cleanup_legacy_acknowledgment_samples(repo_root)

    os.makedirs(os.path.dirname(target_path), exist_ok=True)

    if os.path.exists(target_path) and os.path.getsize(target_path) > 0:
        return target_path

    total_frames = int(_DURATION_SECONDS * _SAMPLE_RATE)

    with wave.open(target_path, "w") as wav_file:
        wav_file.setnchannels(1)
        wav_file.setsampwidth(2)
        wav_file.setframerate(_SAMPLE_RATE)

        for index in range(total_frames):
            time_seconds = index / _SAMPLE_RATE
            envelope = _envelope(time_seconds)
            sample = 0.0
            for frequency in _FREQUENCIES:
                sample += math.sin(2.0 * math.pi * frequency * time_seconds)
            sample /= len(_FREQUENCIES)
            value = int(_AMPLITUDE * envelope * sample)
            wav_file.writeframes(struct.pack("<h", value))

    return target_path


__all__ = [
    "DEFAULT_WAKE_ACK_RELATIVE_PATH",
    "ensure_wake_acknowledgment_sound",
]