diff --git a/sounddevice.py b/sounddevice.py index 1a91b27..0d4040c 100644 --- a/sounddevice.py +++ b/sounddevice.py @@ -1165,45 +1165,8 @@ def close(self, ignore_errors=True): _check(err, 'Error closing stream') -class RawInputStream(_StreamBase): - """Raw stream for recording only. See __init__() and RawStream.""" - - def __init__(self, samplerate=None, blocksize=None, - device=None, channels=None, dtype=None, latency=None, - extra_settings=None, callback=None, finished_callback=None, - clip_off=None, dither_off=None, never_drop_input=None, - prime_output_buffers_using_stream_callback=None): - """PortAudio input stream (using buffer objects). - - This is the same as `InputStream`, except that the *callback* - function and `~RawStream.read()` work on plain Python buffer - objects instead of on NumPy arrays. - NumPy is not necessary for using this. - - Parameters - ---------- - dtype : str - See `RawStream`. - callback : callable - User-supplied function to consume audio data in response to - requests from an active stream. - The callback must have this signature: - - .. code-block:: text - - callback(indata: buffer, frames: int, - time: CData, status: CallbackFlags) -> None - - The arguments are the same as in the *callback* parameter of - `RawStream`, except that *outdata* is missing. - - See Also - -------- - RawStream, Stream - - """ - _StreamBase.__init__(self, kind='input', wrap_callback='buffer', - **_remove_self(locals())) +class _InputStreamBase(_StreamBase): + """Base class for input stream classes.""" @property def read_available(self): @@ -1215,7 +1178,7 @@ def read_available(self): """ return _check(_lib.Pa_GetStreamReadAvailable(self._ptr)) - def read(self, frames): + def _raw_read(self, frames): """Read samples from the stream into a buffer. This is the same as `Stream.read()`, except that it returns @@ -1251,19 +1214,19 @@ def read(self, frames): return _ffi.buffer(data), overflowed -class RawOutputStream(_StreamBase): - """Raw stream for playback only. See __init__() and RawStream.""" +class RawInputStream(_InputStreamBase): + """Raw stream for recording only. See __init__() and RawStream.""" def __init__(self, samplerate=None, blocksize=None, device=None, channels=None, dtype=None, latency=None, extra_settings=None, callback=None, finished_callback=None, clip_off=None, dither_off=None, never_drop_input=None, prime_output_buffers_using_stream_callback=None): - """PortAudio output stream (using buffer objects). + """PortAudio input stream (using buffer objects). - This is the same as `OutputStream`, except that the *callback* - function and `~RawStream.write()` work on plain Python - buffer objects instead of on NumPy arrays. + This is the same as `InputStream`, except that the *callback* + function and `~RawStream.read()` work on plain Python buffer + objects instead of on NumPy arrays. NumPy is not necessary for using this. Parameters @@ -1271,26 +1234,32 @@ def __init__(self, samplerate=None, blocksize=None, dtype : str See `RawStream`. callback : callable - User-supplied function to generate audio data in response to + User-supplied function to consume audio data in response to requests from an active stream. The callback must have this signature: .. code-block:: text - callback(outdata: buffer, frames: int, + callback(indata: buffer, frames: int, time: CData, status: CallbackFlags) -> None The arguments are the same as in the *callback* parameter of - `RawStream`, except that *indata* is missing. + `RawStream`, except that *outdata* is missing. See Also -------- RawStream, Stream """ - _StreamBase.__init__(self, kind='output', wrap_callback='buffer', + _StreamBase.__init__(self, kind='input', wrap_callback='buffer', **_remove_self(locals())) + read = _InputStreamBase._raw_read + + +class _OutputStreamBase(_StreamBase): + """Base class for output stream classes.""" + @property def write_available(self): """The number of frames that can be written without waiting. @@ -1301,7 +1270,7 @@ def write_available(self): """ return _check(_lib.Pa_GetStreamWriteAvailable(self._ptr)) - def write(self, data): + def _raw_write(self, data): """Write samples to the stream. This is the same as `Stream.write()`, except that it expects @@ -1348,6 +1317,49 @@ def write(self, data): return underflowed +class RawOutputStream(_OutputStreamBase): + """Raw stream for playback only. See __init__() and RawStream.""" + + def __init__(self, samplerate=None, blocksize=None, + device=None, channels=None, dtype=None, latency=None, + extra_settings=None, callback=None, finished_callback=None, + clip_off=None, dither_off=None, never_drop_input=None, + prime_output_buffers_using_stream_callback=None): + """PortAudio output stream (using buffer objects). + + This is the same as `OutputStream`, except that the *callback* + function and `~RawStream.write()` work on plain Python + buffer objects instead of on NumPy arrays. + NumPy is not necessary for using this. + + Parameters + ---------- + dtype : str + See `RawStream`. + callback : callable + User-supplied function to generate audio data in response to + requests from an active stream. + The callback must have this signature: + + .. code-block:: text + + callback(outdata: buffer, frames: int, + time: CData, status: CallbackFlags) -> None + + The arguments are the same as in the *callback* parameter of + `RawStream`, except that *indata* is missing. + + See Also + -------- + RawStream, Stream + + """ + _StreamBase.__init__(self, kind='output', wrap_callback='buffer', + **_remove_self(locals())) + + write = _OutputStreamBase._raw_write + + class RawStream(RawInputStream, RawOutputStream): """Raw stream for playback and recording. See __init__().""" @@ -1402,7 +1414,7 @@ def __init__(self, samplerate=None, blocksize=None, **_remove_self(locals())) -class InputStream(RawInputStream): +class InputStream(_InputStreamBase): """Stream for input only. See __init__() and Stream.""" def __init__(self, samplerate=None, blocksize=None, @@ -1472,12 +1484,12 @@ def read(self, frames): """ dtype, _ = _split(self._dtype) channels, _ = _split(self._channels) - data, overflowed = RawInputStream.read(self, frames) + data, overflowed = _InputStreamBase._raw_read(self, frames) data = _array(data, channels, dtype) return data, overflowed -class OutputStream(RawOutputStream): +class OutputStream(_OutputStreamBase): """Stream for output only. See __init__() and Stream.""" def __init__(self, samplerate=None, blocksize=None, @@ -1562,7 +1574,7 @@ def write(self, data): data.dtype.name, dtype)) if not data.flags.c_contiguous: raise TypeError('data must be C-contiguous') - return RawOutputStream.write(self, data) + return _OutputStreamBase._raw_write(self, data) class Stream(InputStream, OutputStream):