use real sounds from kbsim
This commit is contained in:
+27
-14
@@ -3,20 +3,18 @@ from pathlib import Path
|
||||
|
||||
from pydub import AudioSegment
|
||||
|
||||
from backend.models import ExportRequest, SwitchType
|
||||
from backend.key_sound_map import (
|
||||
MANIFEST,
|
||||
marker_release_time,
|
||||
resolve_marker_samples,
|
||||
sample_path,
|
||||
)
|
||||
from backend.models import ExportRequest
|
||||
|
||||
SAMPLE_RATE = 48000
|
||||
SAMPLES_DIR = Path(__file__).resolve().parent.parent / "assets" / "samples"
|
||||
|
||||
SWITCH_FILES: dict[SwitchType, str] = {
|
||||
"cherry-mx-blue": "cherry-mx-blue.wav",
|
||||
"cherry-mx-red": "cherry-mx-red.wav",
|
||||
"cherry-mx-brown": "cherry-mx-brown.wav",
|
||||
}
|
||||
|
||||
|
||||
def _load_sample(switch: SwitchType) -> AudioSegment:
|
||||
path = SAMPLES_DIR / SWITCH_FILES[switch]
|
||||
def _load_sample(path: Path) -> AudioSegment:
|
||||
if not path.exists():
|
||||
raise FileNotFoundError(f"Sample not found: {path}")
|
||||
sample = AudioSegment.from_file(path)
|
||||
@@ -24,14 +22,29 @@ def _load_sample(switch: SwitchType) -> AudioSegment:
|
||||
|
||||
|
||||
def export_keyboard_audio(request: ExportRequest) -> bytes:
|
||||
if request.switch not in MANIFEST:
|
||||
raise FileNotFoundError(f"Unknown switch: {request.switch}")
|
||||
|
||||
duration_ms = int(request.duration * 1000)
|
||||
base = AudioSegment.silent(duration=duration_ms, frame_rate=SAMPLE_RATE)
|
||||
click = _load_sample(request.switch)
|
||||
|
||||
for marker in sorted(request.markers, key=lambda m: m.time):
|
||||
position_ms = int(marker.time * 1000)
|
||||
if position_ms < duration_ms:
|
||||
base = base.overlay(click, position=position_ms)
|
||||
press_key, release_key = resolve_marker_samples(
|
||||
request.switch,
|
||||
marker.key,
|
||||
marker.code,
|
||||
)
|
||||
press_sample = _load_sample(sample_path(request.switch, "press", press_key))
|
||||
release_sample = _load_sample(sample_path(request.switch, "release", release_key))
|
||||
|
||||
press_ms = int(marker.time * 1000)
|
||||
if press_ms < duration_ms:
|
||||
base = base.overlay(press_sample, position=press_ms)
|
||||
|
||||
release_time = marker_release_time(marker.time, marker.release_time)
|
||||
release_ms = int(release_time * 1000)
|
||||
if release_ms < duration_ms:
|
||||
base = base.overlay(release_sample, position=release_ms)
|
||||
|
||||
buffer = io.BytesIO()
|
||||
base.export(buffer, format="wav")
|
||||
|
||||
Reference in New Issue
Block a user