Skip to content

Commit a82b9b5

Browse files
committed
DOC: Update examples
1 parent e8253a6 commit a82b9b5

File tree

12 files changed

+224
-130
lines changed

12 files changed

+224
-130
lines changed

doc/examples.rst

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
1-
Example Programs
2-
================
1+
.. include:: ../examples/README.rst
32

43
Play a Sound File
54
-----------------

examples/README.rst

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
Example Programs
2+
================
3+
4+
Most of these examples use the `argparse` module to handle command line
5+
arguments.
6+
To show a help text explaining all available arguments,
7+
use the ``--help`` argument.
8+
9+
For example::
10+
11+
python3 play_file.py --help

examples/asyncio_coroutines.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
99
"""
1010
import asyncio
11+
import sys
1112

1213
import numpy as np
1314
import sounddevice as sd
@@ -70,4 +71,7 @@ async def main(frames=150_000, channels=1, dtype='float32', **kwargs):
7071

7172

7273
if __name__ == "__main__":
73-
asyncio.run(main())
74+
try:
75+
asyncio.run(main())
76+
except KeyboardInterrupt:
77+
sys.exit('\nInterrupted by user')

examples/asyncio_generators.py

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
"""
1111
import asyncio
1212
import queue
13+
import sys
1314

1415
import numpy as np
1516
import sounddevice as sd
@@ -36,7 +37,7 @@ async def stream_generator(blocksize, *, channels=1, dtype='float32',
3637
3738
The output blocks are uninitialized and have to be filled with
3839
appropriate audio signals.
39-
40+
4041
"""
4142
assert blocksize != 0
4243
q_in = asyncio.Queue()
@@ -97,8 +98,11 @@ async def main(**kwargs):
9798
try:
9899
await audio_task
99100
except asyncio.CancelledError:
100-
print('wire was cancelled')
101+
print('\nwire was cancelled')
101102

102103

103104
if __name__ == "__main__":
104-
asyncio.run(main(blocksize=1024))
105+
try:
106+
asyncio.run(main(blocksize=1024))
107+
except KeyboardInterrupt:
108+
sys.exit('\nInterrupted by user')

examples/play_file.py

Lines changed: 27 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
#!/usr/bin/env python3
22
"""Load an audio file into memory and play its contents.
33
4-
NumPy and the soundfile module (http://PySoundFile.rtfd.io/) must be
5-
installed for this to work.
4+
NumPy and the soundfile module (https://PySoundFile.readthedocs.io/)
5+
must be installed for this to work.
66
77
This example program loads the whole file into memory before starting
88
playback.
@@ -11,6 +11,9 @@
1111
"""
1212
import argparse
1313

14+
import sounddevice as sd
15+
import soundfile as sf
16+
1417

1518
def int_or_str(text):
1619
"""Helper function for argument parsing."""
@@ -19,21 +22,34 @@ def int_or_str(text):
1922
except ValueError:
2023
return text
2124

22-
parser = argparse.ArgumentParser(description=__doc__)
23-
parser.add_argument('filename', help='audio file to be played back')
24-
parser.add_argument('-d', '--device', type=int_or_str,
25-
help='output device (numeric ID or substring)')
26-
args = parser.parse_args()
25+
26+
parser = argparse.ArgumentParser(add_help=False)
27+
parser.add_argument(
28+
'-l', '--list-devices', action='store_true',
29+
help='show list of audio devices and exit')
30+
args, remaining = parser.parse_known_args()
31+
if args.list_devices:
32+
print(sd.query_devices())
33+
parser.exit(0)
34+
parser = argparse.ArgumentParser(
35+
description=__doc__,
36+
formatter_class=argparse.RawDescriptionHelpFormatter,
37+
parents=[parser])
38+
parser.add_argument(
39+
'filename', metavar='FILENAME',
40+
help='audio file to be played back')
41+
parser.add_argument(
42+
'-d', '--device', type=int_or_str,
43+
help='output device (numeric ID or substring)')
44+
args = parser.parse_args(remaining)
2745

2846
try:
29-
import sounddevice as sd
30-
import soundfile as sf
3147
data, fs = sf.read(args.filename, dtype='float32')
3248
sd.play(data, fs, device=args.device)
3349
status = sd.wait()
34-
if status:
35-
parser.exit('Error during playback: ' + str(status))
3650
except KeyboardInterrupt:
3751
parser.exit('\nInterrupted by user')
3852
except Exception as e:
3953
parser.exit(type(e).__name__ + ': ' + str(e))
54+
if status:
55+
parser.exit('Error during playback: ' + str(status))

examples/play_long_file.py

Lines changed: 33 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,41 +1,60 @@
11
#!/usr/bin/env python3
22
"""Play an audio file using a limited amount of memory.
33
4-
The soundfile module (http://PySoundFile.rtfd.io/) must be installed for
5-
this to work. NumPy is not needed.
4+
The soundfile module (https://PySoundFile.readthedocs.io/) must be
5+
installed for this to work. NumPy is not needed.
66
77
In contrast to play_file.py, which loads the whole file into memory
88
before starting playback, this example program only holds a given number
99
of audio blocks in memory and is therefore able to play files that are
1010
larger than the available RAM.
1111
12+
A similar example could of course be implemented using NumPy,
13+
but this example shows what can be done when NumPy is not available.
14+
1215
"""
13-
from __future__ import division, print_function
1416
import argparse
15-
try:
16-
import queue # Python 3.x
17-
except ImportError:
18-
import Queue as queue # Python 2.x
17+
import queue
1918
import sys
2019
import threading
2120

21+
import sounddevice as sd
22+
import soundfile as sf
23+
24+
2225
def int_or_str(text):
2326
"""Helper function for argument parsing."""
2427
try:
2528
return int(text)
2629
except ValueError:
2730
return text
2831

29-
parser = argparse.ArgumentParser(description=__doc__)
30-
parser.add_argument('filename', help='audio file to be played back')
31-
parser.add_argument('-d', '--device', type=int_or_str,
32-
help='output device (numeric ID or substring)')
33-
parser.add_argument('-b', '--blocksize', type=int, default=2048,
34-
help='block size (default: %(default)s)')
32+
33+
parser = argparse.ArgumentParser(add_help=False)
34+
parser.add_argument(
35+
'-l', '--list-devices', action='store_true',
36+
help='show list of audio devices and exit')
37+
args, remaining = parser.parse_known_args()
38+
if args.list_devices:
39+
print(sd.query_devices())
40+
parser.exit(0)
41+
parser = argparse.ArgumentParser(
42+
description=__doc__,
43+
formatter_class=argparse.RawDescriptionHelpFormatter,
44+
parents=[parser])
45+
parser.add_argument(
46+
'filename', metavar='FILENAME',
47+
help='audio file to be played back')
48+
parser.add_argument(
49+
'-d', '--device', type=int_or_str,
50+
help='output device (numeric ID or substring)')
51+
parser.add_argument(
52+
'-b', '--blocksize', type=int, default=2048,
53+
help='block size (default: %(default)s)')
3554
parser.add_argument(
3655
'-q', '--buffersize', type=int, default=20,
3756
help='number of blocks used for buffering (default: %(default)s)')
38-
args = parser.parse_args()
57+
args = parser.parse_args(remaining)
3958
if args.blocksize == 0:
4059
parser.error('blocksize must not be zero')
4160
if args.buffersize < 1:
@@ -65,16 +84,12 @@ def callback(outdata, frames, time, status):
6584

6685

6786
try:
68-
import sounddevice as sd
69-
import soundfile as sf
70-
7187
with sf.SoundFile(args.filename) as f:
7288
for _ in range(args.buffersize):
7389
data = f.buffer_read(args.blocksize, dtype='float32')
7490
if not data:
7591
break
7692
q.put_nowait(data) # Pre-fill queue
77-
7893
stream = sd.RawOutputStream(
7994
samplerate=f.samplerate, blocksize=args.blocksize,
8095
device=args.device, channels=f.channels, dtype='float32',

examples/play_sine.py

Lines changed: 20 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,9 @@
33
import argparse
44
import sys
55

6+
import numpy as np
7+
import sounddevice as sd
8+
69

710
def int_or_str(text):
811
"""Helper function for argument parsing."""
@@ -12,31 +15,33 @@ def int_or_str(text):
1215
return text
1316

1417

15-
parser = argparse.ArgumentParser(description=__doc__)
18+
parser = argparse.ArgumentParser(add_help=False)
1619
parser.add_argument(
1720
'-l', '--list-devices', action='store_true',
1821
help='show list of audio devices and exit')
19-
parser.add_argument(
20-
'-d', '--device', type=int_or_str,
21-
help='output device (numeric ID or substring)')
22+
args, remaining = parser.parse_known_args()
23+
if args.list_devices:
24+
print(sd.query_devices())
25+
parser.exit(0)
26+
parser = argparse.ArgumentParser(
27+
description=__doc__,
28+
formatter_class=argparse.RawDescriptionHelpFormatter,
29+
parents=[parser])
2230
parser.add_argument(
2331
'frequency', nargs='?', metavar='FREQUENCY', type=float, default=500,
2432
help='frequency in Hz (default: %(default)s)')
33+
parser.add_argument(
34+
'-d', '--device', type=int_or_str,
35+
help='output device (numeric ID or substring)')
2536
parser.add_argument(
2637
'-a', '--amplitude', type=float, default=0.2,
2738
help='amplitude (default: %(default)s)')
28-
args = parser.parse_args()
39+
args = parser.parse_args(remaining)
2940

30-
try:
31-
import numpy as np
32-
import sounddevice as sd
33-
34-
if args.list_devices:
35-
print(sd.query_devices())
36-
parser.exit(0)
41+
start_idx = 0
3742

43+
try:
3844
samplerate = sd.query_devices(args.device, 'output')['default_samplerate']
39-
start_idx = 0
4045

4146
def callback(outdata, frames, time, status):
4247
if status:
@@ -53,5 +58,7 @@ def callback(outdata, frames, time, status):
5358
print('press Return to quit')
5459
print('#' * 80)
5560
input()
61+
except KeyboardInterrupt:
62+
parser.exit('')
5663
except Exception as e:
5764
parser.exit(type(e).__name__ + ': ' + str(e))

examples/plot_input.py

Lines changed: 18 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,11 @@
88
import queue
99
import sys
1010

11+
from matplotlib.animation import FuncAnimation
12+
import matplotlib.pyplot as plt
13+
import numpy as np
14+
import sounddevice as sd
15+
1116

1217
def int_or_str(text):
1318
"""Helper function for argument parsing."""
@@ -17,10 +22,21 @@ def int_or_str(text):
1722
return text
1823

1924

20-
parser = argparse.ArgumentParser(description=__doc__)
25+
parser = argparse.ArgumentParser(add_help=False)
2126
parser.add_argument(
2227
'-l', '--list-devices', action='store_true',
2328
help='show list of audio devices and exit')
29+
args, remaining = parser.parse_known_args()
30+
if args.list_devices:
31+
print(sd.query_devices())
32+
parser.exit(0)
33+
parser = argparse.ArgumentParser(
34+
description=__doc__,
35+
formatter_class=argparse.RawDescriptionHelpFormatter,
36+
parents=[parser])
37+
parser.add_argument(
38+
'channels', type=int, default=[1], nargs='*', metavar='CHANNEL',
39+
help='input channels to plot (default: the first)')
2440
parser.add_argument(
2541
'-d', '--device', type=int_or_str,
2642
help='input device (numeric ID or substring)')
@@ -37,10 +53,7 @@ def int_or_str(text):
3753
parser.add_argument(
3854
'-n', '--downsample', type=int, default=10, metavar='N',
3955
help='display every Nth sample (default: %(default)s)')
40-
parser.add_argument(
41-
'channels', type=int, default=[1], nargs='*', metavar='CHANNEL',
42-
help='input channels to plot (default: the first)')
43-
args = parser.parse_args()
56+
args = parser.parse_args(remaining)
4457
if any(c < 1 for c in args.channels):
4558
parser.error('argument CHANNEL: must be >= 1')
4659
mapping = [c - 1 for c in args.channels] # Channel numbers start with 1
@@ -77,14 +90,6 @@ def update_plot(frame):
7790

7891

7992
try:
80-
from matplotlib.animation import FuncAnimation
81-
import matplotlib.pyplot as plt
82-
import numpy as np
83-
import sounddevice as sd
84-
85-
if args.list_devices:
86-
print(sd.query_devices())
87-
parser.exit(0)
8893
if args.samplerate is None:
8994
device_info = sd.query_devices(args.device, 'input')
9095
args.samplerate = device_info['default_samplerate']

examples/rec_gui.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@ class RecGui(tk.Tk):
8282
stream = None
8383

8484
def __init__(self):
85-
tk.Tk.__init__(self)
85+
super().__init__()
8686

8787
self.title('Recording GUI')
8888

0 commit comments

Comments
 (0)