Skip to content

Commit e8253a6

Browse files
committed
DOC: Documentation overhaul
1 parent f5d8fd5 commit e8253a6

File tree

8 files changed

+185
-58
lines changed

8 files changed

+185
-58
lines changed

CONTRIBUTING.rst

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,14 @@ please create an issue or a pull request at
66
https://github.com/spatialaudio/python-sounddevice/.
77
Contributions are always welcome!
88

9-
Instead of pip-installing the latest release from PyPI, you should get the
9+
Instead of pip-installing the latest release from PyPI_, you should get the
1010
newest development version from Github_::
1111

1212
git clone --recursive https://github.com/spatialaudio/python-sounddevice.git
1313
cd python-sounddevice
1414
python3 setup.py develop --user
1515

16+
.. _PyPI: https://pypi.org/project/sounddevice/
1617
.. _Github: https://github.com/spatialaudio/python-sounddevice/
1718

1819
This way, your installation always stays up-to-date, even if you pull new

NEWS.rst

Lines changed: 13 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -11,44 +11,43 @@
1111
* Change the way how the PortAudio library is located
1212

1313
0.3.9 (2017-10-25):
14-
* Add `sounddevice.Stream.closed`
14+
* Add `Stream.closed`
1515
* Switch CFFI usage to "out-of-line ABI" mode
1616

1717
0.3.8 (2017-07-11):
1818
* Add more ``ignore_errors`` arguments
19-
* Add `sounddevice.PortAudioError.args`
20-
* Add `sounddevice.CoreAudioSettings`
19+
* Add `PortAudioError.args`
20+
* Add `CoreAudioSettings`
2121

2222
0.3.7 (2017-02-16):
23-
* Add `sounddevice.get_stream()`
23+
* Add `get_stream()`
2424
* Support for CData function pointers as callbacks
2525

2626
0.3.6 (2016-12-19):
2727
* Example application ``play_long_file.py``
2828

2929
0.3.5 (2016-09-12):
3030
* Add ``extra_settings`` option for host-API-specific stream settings
31-
* Add `sounddevice.AsioSettings` and `sounddevice.WasapiSettings`
31+
* Add `AsioSettings` and `WasapiSettings`
3232

3333
0.3.4 (2016-08-05):
3434
* Example application ``rec_unlimited.py``
3535

3636
0.3.3 (2016-04-11):
37-
* Add ``loop`` argument to `sounddevice.play()`
37+
* Add ``loop`` argument to `play()`
3838

3939
0.3.2 (2016-03-16):
4040
* ``mapping=[1]`` works now on all host APIs
4141
* Example application ``plot_input.py`` showing the live microphone signal(s)
42-
* Device substrings are now allowed in `sounddevice.query_devices()`
42+
* Device substrings are now allowed in `query_devices()`
4343

4444
0.3.1 (2016-01-04):
45-
* Add `sounddevice.check_input_settings()` and
46-
`sounddevice.check_output_settings()`
45+
* Add `check_input_settings()` and `check_output_settings()`
4746
* Send PortAudio output to ``/dev/null`` (on Linux and OSX)
4847

4948
0.3.0 (2015-10-28):
50-
* Remove `sounddevice.print_devices()`, `sounddevice.query_devices()` can be
51-
used instead, since it now returns a `sounddevice.DeviceList` object.
49+
* Remove `print_devices()`, `query_devices()` can be used instead,
50+
since it now returns a `DeviceList` object.
5251

5352
0.2.2 (2015-10-21):
5453
* Devices can now be selected by substrings of device name and host API name
@@ -61,10 +60,9 @@
6160
* Support for wheels including a dylib for Mac OS X and DLLs for Windows.
6261
The code for creating the wheels is largely taken from PySoundFile_.
6362
* Remove logging (this seemed too intrusive)
64-
* Return callback status from `sounddevice.wait()` and add the new function
65-
`sounddevice.get_status()`
66-
* `sounddevice.playrec()`: Rename the arguments *input_channels* and
67-
*input_dtype* to *channels* and *dtype*, respectively
63+
* Return callback status from `wait()` and add the new function `get_status()`
64+
* `playrec()`: Rename the arguments *input_channels* and *input_dtype*
65+
to *channels* and *dtype*, respectively
6866

6967
.. _PySoundFile: https://github.com/bastibe/SoundFile/
7068

_sounddevice_data/README

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
This directory contains a Git submodule with the .dylib and .dll files
2+
of the PortAudio library for macOS and Windows, respectively.
3+
If needed, you can download the submodule with:
4+
5+
git submodule update --init

doc/README

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
This directory contains the source files for the user documentation.
2+
The rendered result can be found at https://python-sounddevice.readthedocs.io/

doc/usage.rst

Lines changed: 74 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
.. currentmodule:: sounddevice
2+
13
Usage
24
=====
35

@@ -12,21 +14,28 @@ Playback
1214

1315
Assuming you have a NumPy array named ``myarray`` holding audio data with a
1416
sampling frequency of ``fs`` (in the most cases this will be 44100 or 48000
15-
frames per second), you can play it back with `sounddevice.play()`:
17+
frames per second), you can play it back with `play()`:
1618

1719
.. code:: python
1820
1921
sd.play(myarray, fs)
2022
2123
This function returns immediately but continues playing the audio signal in the
22-
background. You can stop playback with `sounddevice.stop()`:
24+
background. You can stop playback with `stop()`:
2325

2426
.. code:: python
2527
2628
sd.stop()
2729
30+
If you want to block the Python interpreter until playback is finished,
31+
you can use `wait()`:
32+
33+
.. code:: python
34+
35+
sd.wait()
36+
2837
If you know that you will use the same sampling frequency for a while, you can
29-
set it as default using `sounddevice.default.samplerate`:
38+
set it as default using `default.samplerate`:
3039

3140
.. code:: python
3241
@@ -38,18 +47,23 @@ After that, you can drop the *samplerate* argument:
3847
3948
sd.play(myarray)
4049
50+
.. note::
51+
52+
If you don't specify the correct sampling frequency,
53+
the sound might be played back too slow or too fast!
54+
4155
Recording
4256
---------
4357

44-
To record audio data from your sound device into a NumPy array, use
45-
`sounddevice.rec()`:
58+
To record audio data from your sound device into a NumPy array,
59+
you can use `rec()`:
4660

4761
.. code:: python
4862
4963
duration = 10.5 # seconds
5064
myrecording = sd.rec(int(duration * fs), samplerate=fs, channels=2)
5165
52-
Again, for repeated use you can set defaults using `sounddevice.default`:
66+
Again, for repeated use you can set defaults using `default`:
5367

5468
.. code:: python
5569
@@ -62,41 +76,35 @@ After that, you can drop the additional arguments:
6276
6377
myrecording = sd.rec(int(duration * fs))
6478
65-
This function also returns immediately but continues recording in the
66-
background. In the meantime, you can run other commands. If you want to check
67-
if the recording is finished, you should use `sounddevice.wait()`:
79+
This function also returns immediately but continues recording in the background.
80+
In the meantime, you can run other commands.
81+
If you want to check if the recording is finished, you should use `wait()`:
6882

6983
.. code:: python
7084
7185
sd.wait()
7286
73-
If the recording was already finished, this returns immediately; if not, it
74-
waits and returns as soon as the recording is finished.
87+
If the recording was already finished, this returns immediately;
88+
if not, it waits and returns as soon as the recording is finished.
7589

76-
Alternatively, you could have used the *blocking* argument in the first place:
90+
By default, the recorded array has the data type ``'float32'``
91+
(see `default.dtype`), but this can be changed with the *dtype* argument:
7792

7893
.. code:: python
7994
80-
myrecording = sd.rec(duration * fs, blocking=True)
81-
82-
By default, the recorded array has the data type ``'float32'`` (see
83-
`sounddevice.default.dtype`), but this can be changed with the *dtype* argument:
84-
85-
.. code:: python
86-
87-
myrecording = sd.rec(duration * fs, dtype='float64')
95+
myrecording = sd.rec(int(duration * fs), dtype='float64')
8896
8997
Simultaneous Playback and Recording
9098
-----------------------------------
9199

92-
To play back an array and record at the same time, use `sounddevice.playrec()`:
100+
To play back an array and record at the same time, you can use `playrec()`:
93101

94102
.. code:: python
95103
96104
myrecording = sd.playrec(myarray, fs, channels=2)
97105
98-
The number of output channels is obtained from ``myarray``, but the number of
99-
input channels still has to be specified.
106+
The number of output channels is obtained from ``myarray``,
107+
but the number of input channels still has to be specified.
100108

101109
Again, default values can be used:
102110

@@ -107,26 +115,27 @@ Again, default values can be used:
107115
myrecording = sd.playrec(myarray)
108116
109117
In this case the number of output channels is still taken from ``myarray``
110-
(which may or may not have 2 channels), but the number of input channels is
111-
taken from `sounddevice.default.channels`.
118+
(which may or may not have 2 channels),
119+
but the number of input channels is taken from `default.channels`.
112120

113121
Device Selection
114122
----------------
115123

116124
In many cases, the default input/output device(s) will be the one(s) you want,
117125
but it is of course possible to choose a different device.
118-
Use `sounddevice.query_devices()` to get a list of supported devices.
126+
Use `query_devices()` to get a list of supported devices.
119127
The same list can be obtained from a terminal by typing the command ::
120128

121129
python3 -m sounddevice
122130

123131
You can use the corresponding device ID to select a desired device by assigning
124-
to `sounddevice.default.device` or by passing it as *device* argument to
125-
`sounddevice.play()`, `sounddevice.Stream()` etc.
132+
to `default.device` or by passing it as *device* argument to
133+
`play()`, `Stream()` etc.
126134

127135
Instead of the numerical device ID, you can also use a space-separated list of
128-
case-insensitive substrings of the device name (and the host API name, if
129-
needed). See `sounddevice.default.device` for details.
136+
case-insensitive substrings of the device name
137+
(and the host API name, if needed).
138+
See `default.device` for details.
130139

131140
.. code:: python
132141
@@ -138,7 +147,25 @@ needed). See `sounddevice.default.device` for details.
138147
Callback Streams
139148
----------------
140149

141-
Callback "wire" with `sounddevice.Stream`:
150+
The aforementioned convenience functions `play()`, `rec()` and `playrec()`
151+
(as well as the related functions `wait()`, `stop()`, `get_status()` and
152+
`get_stream()`) are designed for small scripts and interactive use
153+
(e.g. in a Jupyter_ notebook).
154+
They are supposed to be simple and convenient,
155+
but their use cases are quite limited.
156+
157+
If you need more control (e.g. continuous recording, realtime processing, ...),
158+
you should use the lower-level "stream" classes
159+
(e.g. `Stream`, `InputStream`, `RawInputStream`),
160+
either with the "non-blocking" callback interface or with the "blocking"
161+
`Stream.read()` and `Stream.write()` methods, see `Blocking Read/Write Streams`_.
162+
163+
As an example for the "non-blocking" interface,
164+
the following code creates a `Stream` with a callback function
165+
that obtains audio data from the input channels
166+
and simply forwards everything to the output channels
167+
(be careful with the output volume, because this might cause acoustic feedback
168+
if your microphone is close to your loudspeakers):
142169

143170
.. code:: python
144171
@@ -153,7 +180,8 @@ Callback "wire" with `sounddevice.Stream`:
153180
with sd.Stream(channels=2, callback=callback):
154181
sd.sleep(int(duration * 1000))
155182
156-
Same thing with `sounddevice.RawStream`:
183+
The same thing can be done with `RawStream`
184+
(NumPy_ doesn't have to be installed):
157185

158186
.. code:: python
159187
@@ -171,11 +199,20 @@ Same thing with `sounddevice.RawStream`:
171199
.. note:: We are using 24-bit samples here for no particular reason
172200
(just because we can).
173201

202+
You can of course extend the callback functions
203+
to do arbitrarily more complicated stuff.
204+
You can also use streams without inputs (e.g. `OutputStream`)
205+
or streams without outputs (e.g. `InputStream`).
206+
207+
See :doc:`examples` for more examples.
208+
174209
Blocking Read/Write Streams
175210
---------------------------
176211

177-
Instead of using a callback function, you can also use the blocking methods
178-
`sounddevice.Stream.read()` and `sounddevice.Stream.write()` (and of course the
179-
corresponding methods in `sounddevice.InputStream`, `sounddevice.OutputStream`,
180-
`sounddevice.RawStream`, `sounddevice.RawInputStream` and
181-
`sounddevice.RawOutputStream`).
212+
Instead of using a callback function,
213+
you can also use the "blocking" methods `Stream.read()` and `Stream.write()`
214+
(and of course the corresponding methods in `InputStream`, `OutputStream`,
215+
`RawStream`, `RawInputStream` and `RawOutputStream`).
216+
217+
.. _Jupyter: https://jupyter.org/
218+
.. _NumPy: https://numpy.org/

doc/version-history.rst

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
Version History
22
===============
33

4+
.. currentmodule:: sounddevice
5+
46
.. default-role:: py:obj
57

68
.. include:: ../NEWS.rst

setup.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@
4848
else:
4949
class bdist_wheel_half_pure(bdist_wheel):
5050
"""Create OS-dependent, but Python-independent wheels."""
51+
5152
def get_tag(self):
5253
pythons = 'py2.py3.' + PYTHON_INTERPRETERS
5354
if system == 'Darwin':

0 commit comments

Comments
 (0)