fix(classroom): audio speed slider now actually changes playback speed with pitch correction

- Fix client: playbackRate was set to 1 for non-native-speed providers (Speaches/Piper),
  making the speed slider ineffective in the main Pizzicato audio path
- Fix server: pass speed parameter to Speaches TTS API
- Add pitch-preserving playback via MediaElementSourceNode when rate != 1,
  routing through the same Web Audio effects chain (radio filters, distortion, etc.)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
itsrubberduck
2026-02-15 01:01:02 +01:00
parent 56bd770a13
commit 46f95baf9e
3 changed files with 108 additions and 28 deletions

View File

@@ -4143,9 +4143,8 @@ async function playAudioSource(source: CachedAudio, targetRate: number, token: n
const basePlaybackRate = supportsNativeSpeed
? clampRate(desiredRate / (nativeRate || 1), 0.5, 2)
: desiredRate
const needsRateFallback = !supportsNativeSpeed && Math.abs(basePlaybackRate - 1) > 0.0001
const playbackRate = needsRateFallback ? 1 : basePlaybackRate
const htmlPlaybackRate = needsRateFallback ? basePlaybackRate : playbackRate
const playbackRate = basePlaybackRate
const htmlPlaybackRate = basePlaybackRate
const playWithoutEffects = async () => {
if (token !== activePlaybackToken) return
@@ -4179,7 +4178,7 @@ async function playAudioSource(source: CachedAudio, targetRate: number, token: n
throw new Error('Audio engine unavailable')
}
const sound = await pizzicato.createSoundFromBase64(ctx, source.base64)
const sound = await pizzicato.createSoundFromBase64(ctx, source.base64, mime)
if (token !== activePlaybackToken) {
sound.clearEffects()
return