1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77
|
#!/usr/bin/env python3
"""An example for using a stream in an asyncio coroutine.
This example shows how to create a stream in a coroutine and how to wait for
the completion of the stream.
You need Python 3.7 or newer to run this.
"""
import asyncio
import sys
import numpy as np
import sounddevice as sd
async def record_buffer(buffer, **kwargs):
loop = asyncio.get_event_loop()
event = asyncio.Event()
idx = 0
def callback(indata, frame_count, time_info, status):
nonlocal idx
if status:
print(status)
remainder = len(buffer) - idx
if remainder == 0:
loop.call_soon_threadsafe(event.set)
raise sd.CallbackStop
indata = indata[:remainder]
buffer[idx:idx + len(indata)] = indata
idx += len(indata)
stream = sd.InputStream(callback=callback, dtype=buffer.dtype,
channels=buffer.shape[1], **kwargs)
with stream:
await event.wait()
async def play_buffer(buffer, **kwargs):
loop = asyncio.get_event_loop()
event = asyncio.Event()
idx = 0
def callback(outdata, frame_count, time_info, status):
nonlocal idx
if status:
print(status)
remainder = len(buffer) - idx
if remainder == 0:
loop.call_soon_threadsafe(event.set)
raise sd.CallbackStop
valid_frames = frame_count if remainder >= frame_count else remainder
outdata[:valid_frames] = buffer[idx:idx + valid_frames]
outdata[valid_frames:] = 0
idx += valid_frames
stream = sd.OutputStream(callback=callback, dtype=buffer.dtype,
channels=buffer.shape[1], **kwargs)
with stream:
await event.wait()
async def main(frames=150_000, channels=1, dtype='float32', **kwargs):
buffer = np.empty((frames, channels), dtype=dtype)
print('recording buffer ...')
await record_buffer(buffer, **kwargs)
print('playing buffer ...')
await play_buffer(buffer, **kwargs)
print('done')
if __name__ == "__main__":
try:
asyncio.run(main())
except KeyboardInterrupt:
sys.exit('\nInterrupted by user')
|