Skip to content

Commit d353fbf

Browse files
committed
DOC: more low-level implementation of play_file.py example
1 parent b2a311d commit d353fbf

File tree

1 file changed

+36
-6
lines changed

1 file changed

+36
-6
lines changed

examples/play_file.py

+36-6
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,28 @@
11
#!/usr/bin/env python3
22
"""Load an audio file into memory and play its contents.
33
4-
NumPy and the soundfile module (https://PySoundFile.readthedocs.io/)
4+
NumPy and the soundfile module (https://python-soundfile.readthedocs.io/)
55
must be installed for this to work.
66
77
This example program loads the whole file into memory before starting
88
playback.
99
To play very long files, you should use play_long_file.py instead.
1010
11+
This example could simply be implemented like this::
12+
13+
import sounddevice as sd
14+
import soundfile as sf
15+
16+
data, fs = sf.read('my-file.wav')
17+
sd.play(data, fs)
18+
sd.wait()
19+
20+
... but in this example we show a more low-level implementation
21+
using a callback stream.
22+
1123
"""
1224
import argparse
25+
import threading
1326

1427
import sounddevice as sd
1528
import soundfile as sf
@@ -43,13 +56,30 @@ def int_or_str(text):
4356
help='output device (numeric ID or substring)')
4457
args = parser.parse_args(remaining)
4558

59+
event = threading.Event()
60+
4661
try:
47-
data, fs = sf.read(args.filename, dtype='float32')
48-
sd.play(data, fs, device=args.device)
49-
status = sd.wait()
62+
data, fs = sf.read(args.filename, always_2d=True)
63+
64+
current_frame = 0
65+
66+
def callback(outdata, frames, time, status):
67+
global current_frame
68+
if status:
69+
print(status)
70+
chunksize = min(len(data) - current_frame, frames)
71+
outdata[:chunksize] = data[current_frame:current_frame + chunksize]
72+
if chunksize < frames:
73+
outdata[chunksize:] = 0
74+
raise sd.CallbackStop()
75+
current_frame += chunksize
76+
77+
stream = sd.OutputStream(
78+
samplerate=fs, device=args.device, channels=data.shape[1],
79+
callback=callback, finished_callback=event.set)
80+
with stream:
81+
event.wait() # Wait until playback is finished
5082
except KeyboardInterrupt:
5183
parser.exit('\nInterrupted by user')
5284
except Exception as e:
5385
parser.exit(type(e).__name__ + ': ' + str(e))
54-
if status:
55-
parser.exit('Error during playback: ' + str(status))

0 commit comments

Comments
 (0)