audio: add gain control to capture and playback
This commit is contained in:
@@ -1,6 +1,8 @@
|
||||
"""Tests for AudioPipeline."""
|
||||
|
||||
from tuimble.audio import FRAME_SIZE, SAMPLE_RATE, AudioPipeline
|
||||
import struct
|
||||
|
||||
from tuimble.audio import FRAME_SIZE, SAMPLE_RATE, AudioPipeline, _apply_gain
|
||||
|
||||
|
||||
def test_default_construction():
|
||||
@@ -125,3 +127,79 @@ def test_stop_without_start():
|
||||
"""Stop on unstarted pipeline should not raise."""
|
||||
ap = AudioPipeline()
|
||||
ap.stop()
|
||||
|
||||
|
||||
# -- _apply_gain tests -------------------------------------------------------
|
||||
|
||||
|
||||
def test_apply_gain_unity():
|
||||
"""Gain 1.0 returns identical samples."""
|
||||
pcm = struct.pack("<4h", 100, -200, 32767, -32768)
|
||||
assert _apply_gain(pcm, 1.0) == pcm
|
||||
|
||||
|
||||
def test_apply_gain_double():
|
||||
"""Gain 2.0 doubles sample values."""
|
||||
pcm = struct.pack("<2h", 100, -100)
|
||||
result = struct.unpack("<2h", _apply_gain(pcm, 2.0))
|
||||
assert result == (200, -200)
|
||||
|
||||
|
||||
def test_apply_gain_clips():
|
||||
"""Values exceeding int16 range are clipped."""
|
||||
pcm = struct.pack("<2h", 20000, -20000)
|
||||
result = struct.unpack("<2h", _apply_gain(pcm, 2.0))
|
||||
assert result == (32767, -32768)
|
||||
|
||||
|
||||
def test_apply_gain_zero():
|
||||
"""Gain 0.0 produces silence."""
|
||||
pcm = struct.pack("<2h", 1000, -1000)
|
||||
result = struct.unpack("<2h", _apply_gain(pcm, 0.0))
|
||||
assert result == (0, 0)
|
||||
|
||||
|
||||
def test_apply_gain_empty():
|
||||
"""Empty buffer returns empty."""
|
||||
assert _apply_gain(b"", 2.0) == b""
|
||||
|
||||
|
||||
# -- gain property tests ------------------------------------------------------
|
||||
|
||||
|
||||
def test_gain_defaults():
|
||||
ap = AudioPipeline()
|
||||
assert ap.input_gain == 1.0
|
||||
assert ap.output_gain == 1.0
|
||||
|
||||
|
||||
def test_gain_clamping():
|
||||
ap = AudioPipeline()
|
||||
ap.input_gain = 3.0
|
||||
assert ap.input_gain == 2.0
|
||||
ap.output_gain = -1.0
|
||||
assert ap.output_gain == 0.0
|
||||
|
||||
|
||||
def test_capture_callback_applies_input_gain():
|
||||
"""Input gain is applied to captured PCM."""
|
||||
ap = AudioPipeline()
|
||||
ap.capturing = True
|
||||
ap.input_gain = 0.5
|
||||
pcm = struct.pack("<2h", 1000, -1000)
|
||||
ap._capture_callback(pcm, 2, None, None)
|
||||
frame = ap.get_capture_frame()
|
||||
result = struct.unpack("<2h", frame)
|
||||
assert result == (500, -500)
|
||||
|
||||
|
||||
def test_playback_callback_applies_output_gain():
|
||||
"""Output gain is applied during playback."""
|
||||
ap = AudioPipeline()
|
||||
ap.output_gain = 0.5
|
||||
pcm = struct.pack("<2h", 1000, -1000)
|
||||
ap.queue_playback(pcm)
|
||||
outdata = bytearray(4)
|
||||
ap._playback_callback(outdata, 2, None, None)
|
||||
result = struct.unpack("<2h", bytes(outdata))
|
||||
assert result == (500, -500)
|
||||
|
||||
Reference in New Issue
Block a user