[本机音频 Transport]:完成真实设备检查和sounddevice输入输出,包含device-check、RawInputStream和播放错误恢复
This commit is contained in:
@@ -65,6 +65,82 @@ class TransportTests(unittest.TestCase):
|
||||
self.assertIsInstance(health.input_available, bool)
|
||||
self.assertIsInstance(health.output_available, bool)
|
||||
|
||||
def test_sounddevice_transport_reads_from_raw_input_stream(self) -> None:
|
||||
fake = FakeSoundDevice()
|
||||
transport = SoundDeviceAudioTransport(sounddevice_module=fake)
|
||||
transport.start_input(sample_rate=16000, channels=1)
|
||||
frames = transport.read_frames(10)
|
||||
transport.stop()
|
||||
|
||||
self.assertEqual(len(frames), 1)
|
||||
self.assertEqual(frames[0].pcm, b"\x01\x00\x02\x00")
|
||||
self.assertEqual(frames[0].sample_rate, 16000)
|
||||
|
||||
def test_sounddevice_transport_plays_pcm_to_raw_output_stream(self) -> None:
|
||||
fake = FakeSoundDevice()
|
||||
transport = SoundDeviceAudioTransport(sounddevice_module=fake)
|
||||
result = transport.play_pcm(AudioSegment(b"\x00\x00\x01\x00", 16000, 1, 0, 20))
|
||||
|
||||
self.assertTrue(result.played)
|
||||
self.assertEqual(fake.output_writes, [b"\x00\x00\x01\x00"])
|
||||
|
||||
def test_sounddevice_device_report_uses_query_devices(self) -> None:
|
||||
fake = FakeSoundDevice()
|
||||
report = SoundDeviceAudioTransport(sounddevice_module=fake).device_report()
|
||||
|
||||
self.assertTrue(report["ok"])
|
||||
self.assertEqual(len(report["devices"]), 2)
|
||||
|
||||
|
||||
class FakeInputStream:
|
||||
def __init__(self, callback, **kwargs) -> None:
|
||||
self.callback = callback
|
||||
self.kwargs = kwargs
|
||||
self.started = False
|
||||
self.closed = False
|
||||
|
||||
def start(self) -> None:
|
||||
self.started = True
|
||||
self.callback(b"\x01\x00\x02\x00", 2, None, "")
|
||||
|
||||
def stop(self) -> None:
|
||||
self.started = False
|
||||
|
||||
def close(self) -> None:
|
||||
self.closed = True
|
||||
|
||||
|
||||
class FakeOutputStream:
|
||||
def __init__(self, owner, **kwargs) -> None:
|
||||
self.owner = owner
|
||||
self.kwargs = kwargs
|
||||
|
||||
def __enter__(self):
|
||||
return self
|
||||
|
||||
def __exit__(self, *args) -> None:
|
||||
return None
|
||||
|
||||
def write(self, data: bytes) -> None:
|
||||
self.owner.output_writes.append(bytes(data))
|
||||
|
||||
|
||||
class FakeSoundDevice:
|
||||
def __init__(self) -> None:
|
||||
self.output_writes: list[bytes] = []
|
||||
|
||||
def RawInputStream(self, **kwargs):
|
||||
return FakeInputStream(**kwargs)
|
||||
|
||||
def RawOutputStream(self, **kwargs):
|
||||
return FakeOutputStream(self, **kwargs)
|
||||
|
||||
def query_devices(self):
|
||||
return [
|
||||
{"name": "Mic", "max_input_channels": 1, "max_output_channels": 0, "default_samplerate": 16000},
|
||||
{"name": "Speaker", "max_input_channels": 0, "max_output_channels": 2, "default_samplerate": 48000},
|
||||
]
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
|
||||
Reference in New Issue
Block a user