test: add pitch shifting and modulator tests

Covers PitchShifter passthrough, frequency shift direction, output
length preservation, semitone clamping.  AudioPipeline tests verify
pitch property defaults, get/set, clamping, and dequeue integration.
This commit is contained in:
Username
2026-02-28 13:55:40 +01:00
parent 26695e6e70
commit f94f94907d
2 changed files with 120 additions and 0 deletions

View File

@@ -2,6 +2,8 @@
import struct
import numpy as np
from tuimble.audio import FRAME_SIZE, AudioPipeline, _apply_gain
@@ -227,3 +229,43 @@ def test_playback_callback_applies_output_gain():
ap._playback_callback(outdata, 2, None, None)
result = struct.unpack("<2h", bytes(outdata))
assert result == (500, -500)
# -- pitch property tests ----------------------------------------------------
def test_pitch_default():
ap = AudioPipeline()
assert ap.pitch == 0.0
def test_pitch_set_and_get():
ap = AudioPipeline()
ap.pitch = 5.0
assert ap.pitch == 5.0
ap.pitch = -3.0
assert ap.pitch == -3.0
def test_pitch_clamping():
ap = AudioPipeline()
ap.pitch = 20.0
assert ap.pitch == 12.0
ap.pitch = -20.0
assert ap.pitch == -12.0
def test_pitch_applied_on_dequeue():
"""Pitch shifting runs in get_capture_frame, not the callback."""
ap = AudioPipeline()
ap.capturing = True
ap.pitch = 4.0
t = np.arange(FRAME_SIZE) / 48000.0
pcm = (np.sin(2 * np.pi * 440.0 * t) * 16000).astype(np.int16).tobytes()
ap._capture_callback(pcm, FRAME_SIZE, None, None)
frame = ap.get_capture_frame()
assert frame is not None
assert len(frame) == len(pcm)
assert frame != pcm