From a85f1d280057ea5f047ee4a2214ed60430c41e23 Mon Sep 17 00:00:00 2001 From: Matthias Geier Date: Sat, 22 Aug 2026 08:49:19 +0200 Subject: [PATCH 1/3] Replace assignment to .shape by np.reshape() --- src/sounddevice.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sounddevice.py b/src/sounddevice.py index a47e1e3..469ce5f 100644 --- a/src/sounddevice.py +++ b/src/sounddevice.py @@ -2792,7 +2792,7 @@ def _array(buffer, channels, dtype): """Create NumPy array from a buffer object.""" import numpy as np data = np.frombuffer(buffer, dtype=dtype) - data.shape = -1, channels + data = np.reshape(data, (-1, channels), copy=False) return data From 8a8ccec539a3c5901b3f279915d86f6d98bd0568 Mon Sep 17 00:00:00 2001 From: Matthias Geier Date: Sat, 22 Aug 2026 09:51:47 +0200 Subject: [PATCH 2/3] Use more obscure implementation using a sub-array dtype This restores the original behavior of .base pointing directly to the CFFI backend buffer. --- src/sounddevice.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/sounddevice.py b/src/sounddevice.py index 469ce5f..5a9c460 100644 --- a/src/sounddevice.py +++ b/src/sounddevice.py @@ -2791,9 +2791,7 @@ def _buffer(ptr, frames, channels, samplesize): def _array(buffer, channels, dtype): """Create NumPy array from a buffer object.""" import numpy as np - data = np.frombuffer(buffer, dtype=dtype) - data = np.reshape(data, (-1, channels), copy=False) - return data + return np.frombuffer(buffer, dtype=np.dtype((dtype, (channels,)))) def _split(value): From 626fcb071638ebbb631ccd40f3307f8dce68af63 Mon Sep 17 00:00:00 2001 From: Matthias Geier Date: Sat, 22 Aug 2026 10:42:36 +0200 Subject: [PATCH 3/3] Less obscure, slightly more complicated but maybe faster implementation --- src/sounddevice.py | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/src/sounddevice.py b/src/sounddevice.py index 5a9c460..b3268cb 100644 --- a/src/sounddevice.py +++ b/src/sounddevice.py @@ -859,7 +859,7 @@ def callback_ptr(iptr, optr, frames, time, status, _): def callback_ptr(iptr, optr, frames, time, status, _): data = _array( _buffer(iptr, frames, self._channels, self._samplesize), - self._channels, self._dtype) + self._channels, self._dtype, self._samplesize) return _wrap_callback(callback, data, frames, time, status) elif kind == 'output' and wrap_callback == 'buffer': @@ -875,7 +875,7 @@ def callback_ptr(iptr, optr, frames, time, status, _): def callback_ptr(iptr, optr, frames, time, status, _): data = _array( _buffer(optr, frames, self._channels, self._samplesize), - self._channels, self._dtype) + self._channels, self._dtype, self._samplesize) return _wrap_callback(callback, data, frames, time, status) elif kind == 'duplex' and wrap_callback == 'buffer': @@ -896,10 +896,12 @@ def callback_ptr(iptr, optr, frames, time, status, _): ichannels, ochannels = self._channels idtype, odtype = self._dtype isize, osize = self._samplesize - idata = _array(_buffer(iptr, frames, ichannels, isize), - ichannels, idtype) - odata = _array(_buffer(optr, frames, ochannels, osize), - ochannels, odtype) + idata = _array( + _buffer(iptr, frames, ichannels, isize), + ichannels, idtype, isize) + odata = _array( + _buffer(optr, frames, ochannels, osize), + ochannels, odtype, osize) return _wrap_callback( callback, idata, odata, frames, time, status) @@ -1490,8 +1492,9 @@ def read(self, frames): """ dtype, _ = _split(self._dtype) channels, _ = _split(self._channels) + samplesize, _ = _split(self._samplesize) data, overflowed = _InputStreamBase._raw_read(self, frames) - data = _array(data, channels, dtype) + data = _array(data, channels, dtype, samplesize) return data, overflowed @@ -2788,10 +2791,11 @@ def _buffer(ptr, frames, channels, samplesize): return _ffi.buffer(ptr, frames * channels * samplesize) -def _array(buffer, channels, dtype): +def _array(buffer, channels, dtype, samplesize): """Create NumPy array from a buffer object.""" import numpy as np - return np.frombuffer(buffer, dtype=np.dtype((dtype, (channels,)))) + shape = len(buffer) // (samplesize * channels), channels + return np.ndarray(shape, dtype=dtype, buffer=buffer) def _split(value):