Comments (68)
from python-sounddevice.
yes, I would love to test it. The wasapi exclusive mode is supposed to have
low latency and I would like to test this with an oscilloscope...
2016-08-16 19:47 GMT+02:00 Matthias Geier [email protected]:
Not yet. But if you are willing to test it, I can try to implement it.
—
You are receiving this because you authored the thread.
Reply to this email directly, view it on GitHub
#35 (comment),
or mute the thread
https://github.com/notifications/unsubscribe-auth/ANHZpp2NXvKtH4-jCBFBdgviFa41N7gkks5qgfekgaJpZM4Jk5TB
.
from python-sounddevice.
Great! I'll implement this next week and let you know when there's something
to test.
from python-sounddevice.
See also #4.
from python-sounddevice.
@piotx I've implemented this in #39. Can you please check if it works?
from python-sounddevice.
I've installed the wasapi-settings
branch, but get the following error,
when running wasapi_exclusive = sd.WasapiSettings(exclusive=True)
:
c:\python27\lib\site-packages\sounddevice-0.3.4-py2.7.egg\sounddevice.pyc
in **i
nit**(self, exclusive)
2321 flags = 0x0
2322 if exclusive:
-> 2323 flags |= paWinWasapiExclusive
2324 self._streaminfo = _ffi.new('PaWasapiStreamInfo*', dict(
2325 size=_ffi.sizeof('PaWasapiStreamInfo'),
NameError: global name 'paWinWasapiExclusive' is not defined
I have no experience with cffi and don't know how to fix it.
from python-sounddevice.
Sorry, my bad!
I've updated the last commit, can you please try again?
from python-sounddevice.
so I got:
In [9]: sd.default.extra_settings = wasapi_exclusive
---------------------------------------------------------------------------
NameError Traceback (most recent call last)
<ipython-input-9-5cc895cc08f4> in <module>()
----> 1 sd.default.extra_settings = wasapi_exclusive
c:\python27\lib\site-packages\sounddevice-0.3.4-py2.7.egg\sounddevice.pyc in __s
etattr__(self, name, value)
2175 def __setattr__(self, name, value):
2176 """Only allow setting existing attributes."""
-> 2177 if name in _pairs:
2178 getattr(self, name)._pair[:] = _split(value)
2179 elif name in dir(self) and name != 'reset':
NameError: global name '_pairs' is not defined
from python-sounddevice.
Silly me. I made another mistake. Can you try again, please?
from python-sounddevice.
mhm.. I tried also to change _pairs
to self._pairs
but the first error is
still there..
File "wasapi_test.py", line 9, in <module>
sd.play(data, fs, device = 9)
File
"C:\Python27\lib\site-packages\sounddevice-0.3.4-py2.7.egg\sounddevice.py
", line 387, in play
*_kwargs)
File
"C:\Python27\lib\site-packages\sounddevice-0.3.4-py2.7.egg\sounddevice.py
", line 2461, in start_stream
*_kwargs)
File
"C:\Python27\lib\site-packages\sounddevice-0.3.4-py2.7.egg\sounddevice.py
", line 1540, in **init**
prime_output_buffers_using_stream_callback)
File
"C:\Python27\lib\site-packages\sounddevice-0.3.4-py2.7.egg\sounddevice.py
", line 911, in **init**
'Error opening {0}'.format(self.**class**.**name**))
File
"C:\Python27\lib\site-packages\sounddevice-0.3.4-py2.7.egg\sounddevice.py
", line 2598, in _check
raise PortAudioError(msg)
sounddevice.PortAudioError: Error opening OutputStream: Incompatible hostAPI specific stream info
from python-sounddevice.
but actually wasapi just doesn't work anymore at all. I had this behavior before, but I really don't understand it; no idea, why. I'll test it on the pc
from python-sounddevice.
on win8, I get the same error as before:
Traceback (most recent call last):
File "sd2.py", line 11, in <module>
sd.play(data, fs, device=14)
File "C:\Python27\lib\site-packages\sounddevice-0.3.4-py2.7.egg\sounddevice.py
", line 385, in play
**kwargs)
File "C:\Python27\lib\site-packages\sounddevice-0.3.4-py2.7.egg\sounddevice.py
", line 2459, in start_stream
**kwargs)
File "C:\Python27\lib\site-packages\sounddevice-0.3.4-py2.7.egg\sounddevice.py
", line 1538, in __init__
prime_output_buffers_using_stream_callback)
File "C:\Python27\lib\site-packages\sounddevice-0.3.4-py2.7.egg\sounddevice.py
", line 909, in __init__
'Error opening {0}'.format(self.__class__.__name__))
File "C:\Python27\lib\site-packages\sounddevice-0.3.4-py2.7.egg\sounddevice.py
", line 2596, in _check
raise PortAudioError(msg)
sounddevice.PortAudioError: Error opening OutputStream: Incompatible host API sp
ecific stream info
from python-sounddevice.
and on my laptop wasapi juest doesn't work anymore, it says invalid device, although I'm using the same device, same drivers etc.. wdm/ks still works; that's so strange..
from python-sounddevice.
OK, I guess now we are down to the real problem ...
Please make sure that you are using the correct DLL, see #36 (comment).
You could also try the DLL from https://github.com/adfernandes/precompiled-portaudio-windows instead of the bundled DLL. Or the one from pyo.
Can you please try it with WasapiSettings(exclusive=False)
?
Probably the error is related to hostApiType
. It's supposed to be paWASAPI
, which stands for the number 13, but you could try other numbers from 0 to 14.
On the computers where WASAPI doesn't work, does it work with other PortAudio applications, e.g. Audacity?
from python-sounddevice.
yes, I'm using the correct dll (I need to specify it each time in
sounddevice.py, otherwise some other version of portaudio is loaded, which
has only 5 devices (mme and wasapi hosts); I don't know where it is
located, it's not the pyo one, because I have uninstalled pyo beforehand);
I'm using windows 7 on my laptop. The wasapi drivers worked with
sounddevice before on this machine, now they don't. I get the same error
with Fernandes' dlls; Now I tried it out with pyo and get the same error as
in sounddevice.
Loopback recording with wasapi host under audacity however works well on
the same machine. So maybe it's something python specific.. I don't know
from python-sounddevice.
I don't know why WASAPI doesn't work anymore. Did you try an older version of python-sounddevice for comparison?
You could search your hard disk for portaudio.dll
to find out where the unwanted DLL is located.
from python-sounddevice.
ok, when I run wasapi_exclusive = sd.WasapiSettings(exclusive=False), I get
the same error, as with exclusive = True on win8:
sounddevice.PortAudioError: Error opening OutputStream: Incompatible host
API sp
ecific stream info
same error with Fernandes' libraries
from python-sounddevice.
ok, I've tried to set hostApiType in the WasapiSettings class to any number
from 0 to 14, but got the same error. Is there an easy way to access
self._streaminfo to print the hostApiType?
from python-sounddevice.
This should do it:
wasapi_exclusive._streaminfo.hostApiType
If you want to get the host API type from an existing stream, you'll need Pa_GetStreamHostApiType
, which isn't implemented in python-sounddevice.
You can add this to the cdef()
string:
PaHostApiTypeId Pa_GetStreamHostApiType( PaStream* stream );
And then you should be able to use it like this:
mystream = sd.OutputStream(...)
ha_type = sd._lib.Pa_GetStreamHostApiType(mystream._ptr)
from python-sounddevice.
I've merged #39 into master to make it easier for others to try out the extra WASAPI settings.
For your convenience, I've also added the C definition mentioned above, see eaede7f.
from python-sounddevice.
regarding wasapi not working, I've tried it out with pysounddevice and it didn't work...
the portaudio.dll on the win8 was actually located in the psychopy folder (c:\programfiles (x86)\psychopy), I didn't expect cffi to search there... Maybe the path was added to my local python installation...
from python-sounddevice.
@piotx Any news? Did you get it to work in the meantime?
from python-sounddevice.
Hello Matthias,
I didn't try it out any more, I would linke to do it again after
reinstallinh Windows..
from python-sounddevice.
Hello,
on a Windows 7 system, I get the same error message as Piotr.
import sounddevice as sd
sd.default.device = 10
wasapi_exclusive = sd.WasapiSettings(exclusive=True)
sd.default.extra_settings = wasapi_exclusive
sd.play(sound1)
Traceback (most recent call last):
File "<input>", line 1, in <module>
File "C:\Program Files (x86)\Anaconda2\Lib\site-packages\sounddevice.py", line 392, in play
**kwargs)
File "C:\Program Files (x86)\Anaconda2\Lib\site-packages\sounddevice.py", line 2466, in start_stream
**kwargs)
File "C:\Program Files (x86)\Anaconda2\Lib\site-packages\sounddevice.py", line 1545, in __init__
prime_output_buffers_using_stream_callback)
File "C:\Program Files (x86)\Anaconda2\Lib\site-packages\sounddevice.py", line 916, in __init__
'Error opening {0}'.format(self.__class__.__name__))
File "C:\Program Files (x86)\Anaconda2\Lib\site-packages\sounddevice.py", line 2603, in _check
raise PortAudioError(msg)
PortAudioError: Error opening OutputStream: Incompatible host API specific stream info
Cheers
Stefan
from python-sounddevice.
@stefanrepplinger Can you please try with exclusive=False
and different numbers for hostApiType
? See #35 (comment) for details.
I have no clue what's going wrong here ...
Is WASAPI working at all on your computer?
What is ha_type
as mentioned in #35 (comment)?
from python-sounddevice.
Hello,
setting exclusive=False
results in the same error.
The default value of wasapi_exclusive._streaminfo.hostApiType
is is 13L. Trying different values from 0 to 14 does not change anything.
Running the code without the following lines, a sound is played but not in exclusive mode:
wasapi_exclusive = sd.WasapiSettings(exclusive=True)
sd.default.extra_settings = wasapi_exclusive
Trying what you proposed above to find out the ha_type
leads to the following error:
mystream = sd.OutputStream()
ha_type = sd._lib.Pa_GetStreamHostApiType(mystream._ptr)
Traceback (most recent call last):
File "<ipython-input-2-59077e7350c2>", line 2, in <module>
ha_type = sd._lib.Pa_GetStreamHostApiType(mystream._ptr)
File "C:\Program Files (x86)\PsychoPy2\Lib\site-packages\cffi\api.py", line 850, in __getattr__
make_accessor(name)
File "C:\Program Files (x86)\PsychoPy2\Lib\site-packages\cffi\api.py", line 846, in make_accessor
accessors[name](name)
File "C:\Program Files (x86)\PsychoPy2\Lib\site-packages\cffi\api.py", line 791, in accessor_function
raise AttributeError('%s: %s' % (name, e))
AttributeError: Pa_GetStreamHostApiType: "function 'Pa_GetStreamHostApiType' not found in library 'C:\\Anaconda2\\lib\\site-packages\\_sounddevice_data\\libportaudio32bit.dll': error 0x7f"
from python-sounddevice.
@stefanrepplinger Thanks for checking this out. For the last thing to work, you need a version that has eaede7f included, which should be the case for the latest release. Did you upgrade?
Anyway, I'm not sure if that leads anywhere, I'm just shooting in the dark.
I guess the next thing to try would be to create a little test program in C using the PortAudio API directly to see if it shows the same behavior.
from python-sounddevice.
Hi, I upgraded to the latest version using pip. It makes no difference, same error. Thank you for your help so far. In the moment, I don't have the time to try out your last suggestion, sorry.
from python-sounddevice.
It makes no difference, same error.
Hmmm, there seem to be some versions of the PortAudio library that don't have Pa_GetStreamHostApiType()
. Are you using the bundled DLL? Do you have a file called portaudio.dll
somewhere in your Python path?
In the moment, I don't have the time to try out your last suggestion, sorry.
No problem, probably someone else who needs WASAPI exclusive mode will do it. @piotx?
from python-sounddevice.
@stefanrepplinger See also #36 (comment).
from python-sounddevice.
Hey Matthias,
sorry, but right now I'm also too busy with other things...
Best wishes
Piotr
from python-sounddevice.
Hi, I have the same problem. It appears that the thread below is related to the issue.
http://sites.music.columbia.edu/pipermail/portaudio/2015-March/016614.html
It looks like Audacity is using a patched version of PortAudio.
Pa_GetStreamHostApiType()
was added to their version but not to the official PortAudio source. This
looks like the patch:
I hope it helps.
Katsuya
from python-sounddevice.
@cosacog Thanks for the hint!
The non-existence of Pa_GetStreamHostApiType()
isn't our problem. We actually don't need it. I was just suggesting to use it to try to find out what's going wrong.
There may be a bug in PortAudio, but to find that out, it would be necessary to create a little C program that tries to select WASAPI exclusive mode.
from python-sounddevice.
@stefanrepplinger and @cosacog Just to make sure, did you actually select a WASAPI device with device='my WASAPI device name'
or device=X
where X
is the device ID of a WASAPI device?
from python-sounddevice.
@mgeier Thank you for your comment.
I selected WASAPi device by sd.default.device = [ID1, ID2], where ID1 and ID2 is available by sd.query_hostapis() or sd.query_devices().
I hope WASAPi exclusive mode will be available. Until then I try to use wdm-ks or asio.
from python-sounddevice.
I installed "sounddevice-0.3.5-py2.py3.cp26.cp27.cp32.cp33.cp34.cp35.cp36.pp27.pp32.pp33.pp34.pp35.pp36-none-win_amd64.whl" in 64-bit WinPython 3.5.2.3Qt5 distribution on Windows 8.1. While WinPython has PyAudio installed, which also uses the PortAudio library, there is no portaudio.dll anywhere in the WinPython folders. Also, the follow code throws an error:
import sounddevice as sd
a = _ffi.dlopen('portaudio')
Therefore, I am confident sounddevice is loading the bundled dll, which does not throw an error.
I used sd.query_devices() for find the device number of the WASAPI version of my USB external DAC device. I used sd.default.device = ID to configure sounddevice to use this device. I am able to use sounddevice to play a WAV file through this device.
The problem I am having is that either of the following commands cause the error "PortAudioError: Error opening OutputStream: Incompatible host API specific stream info"
sd.default.extra_settings = sd.WasapiSettings(exclusive=True)
sd.default.extra_settings = sd.WasapiSettings(exclusive=False)
In fact, changing sd.default.extra_settings with WASAPI settings causes the same error for all host API types.
The problem is the same using the 64-bit release DLL from https://github.com/adfernandes/precompiled-portaudio-windows
I have JRiver Media Center v22, and my USB external DAC sounds great with WASAPI exclusive mode, but distorted with WASAPI shared mode and other host APIs. Therefore I sounddevice isn't useful for me unless it supports WASAPI exclusive mode.
from python-sounddevice.
Maybe we need a separate DLL where WASAPI is forced to exclusive mode. I would be satisfied to use different DLLs for WASAPI exclusive mode and WASAPI shared mode. Does this link provide the needed info on how to modify the PortAudio code and configure the build (--enable-shared=no)?
http://stackoverflow.com/questions/31306010/how-to-enable-wasapi-exclusive-mode-in-pyaudio
from python-sounddevice.
Probably it works only if the thread priority is changed to eThreadPriorityProAudio
? I thought that was the default behavior anyway, but probably I misunderstood the documentation.
There is no need for a separate DLL to try this, it can be directly done in Python code.
The flags are set here:
python-sounddevice/sounddevice.py
Line 2325 in 861f3ae
You'll see that it looks already quite similar to the code in the stackoverflow answer.
There you could add another line like this:
flags |= _lib.paWinWasapiThreadPriority
And a few lines below, you could add:
threadPriority=_lib.eThreadPriorityProAudio,
Does that work?
from python-sounddevice.
and on my laptop wasapi juest doesn't work anymore, it says invalid device, although I'm using the same device, same drivers etc.. wdm/ks still works; that's so strange..
@piotx : I reproduced and diagnosed this problem, and I created a new issue #52 for it.
from python-sounddevice.
@mgeier - I modified sounddevice.py to add the two lines as you suggested. Did I do it correctly?
if exclusive:
flags |= _lib.paWinWasapiExclusive
flags |= _lib.paWinWasapiThreadPriority
self._streaminfo = _ffi.new('PaWasapiStreamInfo*', dict(
size=_ffi.sizeof('PaWasapiStreamInfo'),
hostApiType=_lib.paWASAPI,
version=1,
threadPriority=_lib.eThreadPriorityProAudio,
flags=flags,
))
I still get the same problem as before the edit, which is that either of the following commands cause the error "PortAudioError: Error opening OutputStream: Incompatible host API specific stream info"
sd.default.extra_settings = sd.WasapiSettings(exclusive=True)
sd.default.extra_settings = sd.WasapiSettings(exclusive=False)
from python-sounddevice.
A reminder to Windows users: for WASAPI exclusive mode to work, you must do the following:
Control Panel > Sound > device > Properties > Advanced tab > Exclusive Mode
Enable checkboxes:
"Allow applications to take exclusive control of this device"
"Give exclusive mode applications priority"
from python-sounddevice.
@hiccup7 Thanks for checking this out!
The code is now equivalent to what is shown in the stackoverflow answer you brought up: http://stackoverflow.com/questions/31306010/how-to-enable-wasapi-exclusive-mode-in-pyaudio
The compiler option --enable-shared=no
doesn't have anything to do with WASAPI "shared" mode, it is about "shared" libraries.
I'm out of ideas, what else could we try?
from python-sounddevice.
sd.get_portaudio_version()
returns a string beginning with 1899 using the DLL bundled in sounddevice. If I understand correctly, 1899 is the SVN revision from the PortAudio repository. I looked here today:
https://app.assembla.com/spaces/portaudio/subversion/commits/list
I see that PortAudio is now up to SVN revision 1968. Revisions 1961-1963 had to do with WASAPI.
Want to try updating the DLLs bundled in sounddevice? I volunteer to test.
from python-sounddevice.
Good idea! Actually, I was already working on updating to the new PortAudio release, some testing would be very welcome!
For now, there is a branch called portaudio-19.6.0-win
including the new DLLs. Would be great if you could check it out!
from python-sounddevice.
I would like to download files from GitHub manually. Can I just replace libportaudio64bit.dll and sounddevice.py in my present sounddevice installation in WinPython with the files from the portaudio-19.6.0-win
branch?
from python-sounddevice.
Yes, this should work, too.
You don't even need sounddevice.py
, the DLL should be enough.
from python-sounddevice.
Thank you mgeier. I installed new DLL and played without error.
wasapi_exclusive = sd.WasapiSettings(exclusive=True)
sd.play(mysnd, extra_settings=wasapi_exclusive)
I will report the performance aftertime.
from python-sounddevice.
I've just checked it out on win8 and it works for me as well! Pretty cool!
I'll test the latency with an oscilloscope...
from python-sounddevice.
ok, so wasapi (exclusive=True) works with sd.play. that's pretty cool! The latency seems to be great (as measured with an oscilloscope and parallel port triggers), but only 37ms of the 50ms sound are played back on one of my machines (win8 with onboard soundcard)
OutputStream.write() works only with exclusive=False; when using exclusive=True, there is only strange noise.
here is the code used:
from ctypes import windll
import time
import sounddevice as sd
import soundfile as sf
#exclusive = True
audio_dev = 18 #14
data, fs = sf.read('d:\snd_scripts_f\startle50ms.wav', dtype='float32')
wasapi_exclusive = sd.WasapiSettings(exclusive=True)
stream = sd.OutputStream(device = audio_dev,extra_settings=wasapi_exclusive)
stream.start()
#sd.query_devices()
p = windll.inpout32
duration = 0.05
pause = 0.1
repeat = 10000
address = 0xDC00
for i in range(1,repeat+1):
#sd.play(data,fs,device=audio_dev,extra_settings=wasapi_exclusive)
stream.write(data)
p.Out32(address, 255)
target_time = time.clock() + duration
while time.clock() < target_time:
pass
p.Out32(address, 0)
time.sleep(pause)
from python-sounddevice.
@piotx Thanks for testing this, nice that it (mostly) works!
only 37ms of the 50ms sound are played back
This sounds similar to #44, doesn't it?
I also experienced that in some situations the last few frames are not played with ALSA. This might as well depend on the hardware. With JACK, however, this never happened.
when using
exclusive=True
, there is only strange noise
Does this only happen with the new PortAudio version?
Either way, this sounds like a PortAudio issue.
@hiccup7 @stefanrepplinger Do you want to try it, too?
I've created a PR for the new dylib/DLL version: #53.
Does anyone have an ASIO device to test?
I guess this could also be tested with ASIO4ALL.
Does anyone of you happen to use 32-bit Windows?
This DLL is yet untested.
from python-sounddevice.
I can do some tests, when I'll be back in one week or so. Exclusive mode
didn't work with the previous PortAudio version, as far as I've
understood... or am I wrong?
btw. I just replaced the portaudio.dll with the new one... I'm using the
32-bit version of portaudio, although I'm on win 64 bit..
from python-sounddevice.
Test conditions:
- libportaudio64bit.dll from the portaudio-19.6.0-win branch
- USB external DAC
- Control Panel > Sound > device > Properties > Advanced tab > Exclusive Mode > enable checkboxes
- 44.1 kHz WAV file data
- sd.default.dtype = 'int24'
- sd.RawOutputStream()
- sounddevice.py from the master branch modified to contain the following code:
if exclusive:
flags |= _lib.paWinWasapiExclusive
flags |= _lib.paWinWasapiThreadPriority
self._streaminfo = _ffi.new('PaWasapiStreamInfo*', dict(
size=_ffi.sizeof('PaWasapiStreamInfo'),
hostApiType=_lib.paWASAPI,
version=1,
threadPriority=_lib.eThreadPriorityProAudio,
flags=flags,
))
The following applies when the WASAPI host API device is used:
sd.default.extra_settings = sd.WasapiSettings(exclusive=False)
no longer raises an exception, and the Windows volume control has an effect (as expected for shared mode).
sd.default.extra_settings = sd.WasapiSettings(exclusive=True)
no longer raises an exception, and the Windows volume control has no effect (as expected for exclusive mode).
Congratulations @mgeier !
With the WDM-KS and ASIO host API devices are used for the same USB external DAC, sd.default.extra_settings = sd.WasapiSettings(exclusive=False)
and sd.default.extra_settings = sd.WasapiSettings(exclusive=True)
cause sd.RawOutputStream()
to raise an exception. Without sd.default.extra_settings
, these host APIs play fine.
from python-sounddevice.
@hiccup7 Thanks for the thorough test! That's good news!
Did you also try it without modifying sounddevice.py
? As far as I understand, it shouldn't be necessary to explicitly change the thread priority.
from python-sounddevice.
I tested with the Realtek sound card on my laptop. It works with WASAPI shared mode, but not with exclusive mode. However, JRiver Media Center v22 outputs noise with exclusive mode on the same device. Therefore, I suspect that this sound card is the problem for exclusive mode.
I haven't yet tested any other conditions. I plan to test with the original sounddevice.py
file as well as the one from the portaudio-19.6.0-win branch.
Christoph Gohlke added sounddevice to his Windows builds using the same Microsoft compiler as each version of Python uses: http://www.lfd.uci.edu/~gohlke/pythonlibs/#sounddevice
I wonder if he used portaudio v19.6.0. This is another thing to test.
We can expect that a lot more Windows Python users will be using sounddevice now that Christoph has added this support.
from python-sounddevice.
FYI, the file sounddevice.py
is unchanged in the portaudio-19.6.0-win
branch. The only changes are in the submodule with the DLLs.
It's great that the sounddevice
module is now part of the Gohlke collection!
I had a look at the textual contents of his DLL, and it seems to use the newest PortAudio release (PortAudio V19.6.0-devel, revision 396fe4b6699ae929d3a685b3ef8a7e97396139a4
).
from python-sounddevice.
I tested the original sounddevice.py
using the same conditions as my post yesterday, and WASAPI exclusive mode works fine.
I documented my testing result just now for cgohlke's wheel at winpython/winpython#428
cgohlke's wheels are most important to the WinPython project because a WinPython bug prevents simple installation of @mgeier wheels in WinPython and inclusion in the next build of WinPython. See winpython/winpython#423
from python-sounddevice.
That's great, so there is no need to change sounddevice.py
.
I will make a new release soon, but I would like to hear first if the new 32-bit DLL works.
@piotx confirmed that it works when used on 64-bit Windows, but it would be nice if somebody could try it on an actual 32-bit Windows.
from python-sounddevice.
I have tested sounddevice with the new 32bit DLL on 32bit Windows 7.
WASAPI exclusive mode works fine and better than shared mode, but WDM-KS was more accurate.
I recorded the data in 1000 Hz, so 1 ms error is the sampling error.
"With window" means that a window is opened using psychopy. I've experienced before that jitter increases with a window, but there was no difference this time.
Thank you anyway! The performance is good enough.
from python-sounddevice.
@cosacog Thanks for testing, it's good to know that the 32bit DLLs work.
Would you also be able to test if ASIO works?
I don't understand those plots, what are they supposed to show?
from python-sounddevice.
I played just one time with ASIO, but it failed. It was wired to me that the device number for ASIO was only 14. The other apis like WASAPI and MME had more than one device numbers for input and output.
By the way, each histogram shows the difference between a trigger and a sound with psychopy. With MME, the delay of sound is around 270 ms while the jitter is 5-6 ms. When recording EEG responses after sound, the jitter is a problem because brain responses (evoked potentials) are time locked to the stimulus, and the potentials are blurred by the jitter. Now I am happy to see that the jitter is 1 ms or less with WDM-KS.
from python-sounddevice.
I played just one time with ASIO, but it failed.
How did it fail?
... the device number for ASIO was only 14. The other apis like WASAPI and MME had more than one device numbers for input and output.
That's normal, and that's actually an advantage!
With ASIO, you can use all channels at the same time, see also #29.
That's also the reason why I would really like for ASIO to work.
Thanks for explaining the histograms, I think I understand them now. That's really interesting.
How do you create and record the trigger?
How did you play the sounds? Did you use the blocking or the callback method?
Can you provide the code you used? Probably as a Gist?
I would expect that the jitter is highly dependent on the audio block size, right?
Which block sizes/latency settings did you use?
I'd expect the jitter to be in the order of magnitude as the blocksize, so I'm wondering how the jitter can even get as low as 1 ms.
from python-sounddevice.
How did it fail?
The error log when playin with asio is as follows:
In [4]: sd.default.device=[14,14]
In [6]: sd.play(mysnd)
------------------------------------------------------------------------
PortAudioError Traceback (most recent call last)
<ipython-input-6-c38c2d60cef7> in <module>()
----> 1 sd.play(mysnd)
C:\Users\kyu\Anaconda2\lib\site-packages\sounddevice.pyc in play(data, samplerate, mapping, blocking, loop, **kwargs)
392 ctx.output_dtype, callback, blocking,
393 prime_output_buffers_using_stream_callback=False,
--> 394 **kwargs)
395
396
C:\Users\kyu\Anaconda2\lib\site-packages\sounddevice.pyc in start_stream(self, StreamClass, samplerate, channels, dtype,
callback, blocking, **kwargs)
2467 finished_callback=self.finished_callback,
2468 **kwargs)
-> 2469 self.stream.start()
2470 global _last_callback
2471 _last_callback = self
C:\Users\kyu\Anaconda2\lib\site-packages\sounddevice.pyc in start(self)
1119 err = _lib.Pa_StartStream(self._ptr)
1120 if err != _lib.paStreamIsNotStopped:
-> 1121 _check(err, 'Error starting stream')
1122
1123 def stop(self):
C:\Users\kyu\Anaconda2\lib\site-packages\sounddevice.pyc in _check(err, msg)
2603 else:
2604 msg += _ffi.string(_lib.Pa_GetErrorText(err)).decode()
-> 2605 raise PortAudioError(msg)
2606 return err
2607
PortAudioError: Error starting stream: Unanticipated host API 2 error -1000: u'Hardware input or output is not present or available'
How do you create and record the trigger?
I created trigger through parallel port with psychopy. The script to create trigger and to play sound is here in Gist.
I recorded the trigger out of parallel port and the sound through RCA plug of the PCI-e sound card, using AD converter of EEG measurement system.
I played click (square wave) sound. The plot image of the sound is shown below. The plot means that 441 points out of 88200 points (at 44100 hz) are the sound, so the sound duration is 10 ms.
plt.plot(mysnd)
How did you play the sounds?
Please see the script above. I am sorry but I do not understand the blocking or the callback method enough. I think I used the blocking method.
Which block sizes/latency settings did you use?
I'm sorry again. I don't understand block sizes. The duration of the sound is 10 ms, but maybe it's not the answer.
I tested on default settings, and I don't know how I can check the block sizes for wdm-ks or wasapi.
The buffer size for asio settings is 4 ms.
how the jitter can even get as low as 1 ms.
The delay and jitter is repoted on another thread of psychopy as you know.
The data is better than mine. I also don't know why, but the performance is satisfactory with wdm-ks.
I hope this good performance is retained in future versions.
from python-sounddevice.
The ASIO error is unfortunate, but I have no clue what's its cause. Does the same ASIO device work with other PortAudio applications, e.g. Audacity?
Thanks for the Gist, that's very helpful.
So you were using sd.play()
, which defines its own callback function. Therefore, you were using the callback API.
To use the "blocking" API, you could use the method OutputStream.write()
. This would probably yield different results in your measurements.
I suspect that you jitter measurements may be biased because you repeat the measurements regularly.
I think you should add a pause of random duration between each of the measurements.
If possible, it would also be better to use more than 50 repetitions.
Your while
loop looks a bit complicated, couldn't you just use something like this?
p_port.setData(int(1))
sd.play(mysnd, blocking=True)
p_port.setData(int(0))
Whenever you want to wait some time, you can just use time.sleep().
BTW, I just found out that Jon added a sounddevice
backend to PsychoPy: https://github.com/psychopy/psychopy/blob/master/psychopy/sound/backend_sounddevice.py
You could probably also try that?
I don't understand block sizes.
The audio drivers and audio frameworks normally don't process the sound sample by sample. They typically work on a bunch of samples at once, which I would call a "block", but there are different names in use.
PortAudio of course also uses blocks internally, and with sounddevice
you can e.g. specify the block size with:
sd.default.blocksize = 1024
The blocksize will have an immediate effect on the latency.
The blocksize is typically a power of 2, but you can also choose different numbers.
You should try a few different block sizes and see how your measurements change.
Apart from the blocksize
, there is another setting named latency
.
TBH, I'm not sure how this is handled in detail in PortAudio, and it may well be platform-dependent.
By default, sounddevice
uses the "high latency" settings of PortAudio, to get the low settings, use:
sd.default.latency = 'low'
For some devices, however, the default "high" and "low" settings are actually the same.
You can find this out with sounddevice.query_devices().
You can also specify an arbitrary latency in seconds, e.g.:
sd.default.latency = 0.005
Of course, only a certain range of latencies is physically possible, PortAudio will try to get as close as possible to the value you specified.
Once you have created an OutputStream
object, you can get an estimation for the actual latency with http://python-sounddevice.readthedocs.io/en/latest/#sounddevice.Stream.latency.
It would be interesting to know if your measured latencies are similar to those estimated by PortAudio.
from python-sounddevice.
I reported ASIO results with the 64-bit DLL a week ago:
With the WDM-KS and ASIO host API devices are used for the same USB external DAC, sd.default.extra_settings = sd.WasapiSettings(exclusive=False) and sd.default.extra_settings = sd.WasapiSettings(exclusive=True) cause sd.RawOutputStream() to raise an exception. Without sd.default.extra_settings, these host APIs play fine.
I would like to set sd.default.extra_settings = sd.WasapiSettings(exclusive=True)
as my normal default. It is not intuitive to me that WASAPI settings should cause an exception for WDM-KS and ASIO host API devices. I expect WDM-KS and ASIO host API devices to ignore WASAPI settings.
@mgeier : Would you consider this a bug, an enhancement or not worth the effort to change?
from python-sounddevice.
@hiccup7 TBH, I don't know yet. Probably I should change the API completely ...
Can you please open a new issue for that where we can discuss further?
from python-sounddevice.
Done. See #55
from python-sounddevice.
@mgeier Thank you for a lot of comments and advises. They are very helpful for me to understand the settings.
I will test the measurements according to your advice and the new psychopy sounddevice backend. I am busy for some time, so it will be in a few weeks.
from python-sounddevice.
I'm closing this because I think there are no more open questions. Thanks for the discussions!
If there are any more problems/comments/suggestions/..., feel free to create new issues.
from python-sounddevice.
Related Issues (20)
- Enhancement Request: Integrate Playback Status Check into Simple `play`/`stop` API in `sounddevice` HOT 4
- Feature request for loopback of output device. HOT 3
- 设备解码错误?utf-8' codec can't decode byte 0xc2 in position 6: invalid continuation byte HOT 4
- Sounddevice + big dict + OOP = Segfault / Bus Error HOT 11
- Update device list by reloading portaudio dll HOT 1
- Won't be able to import sounddevice due to unknown issue with `libportaudio64bit.dll` HOT 5
- Error opening OutputStream: Unanticipated host error', -9999, (2, 0, 'Failed to load ASIO driver
- Use sounddevice with virtual audio device and minimize latency HOT 1
- Achieving stable latency between calls of "playrec" HOT 8
- sounddevice not recognize all devices?
- Issues with playing concurrently with Youtube HOT 1
- Latency 30mSec HOT 9
- Advice on asynchronous playback HOT 7
- docker node minimal image
- Can I continue recording until the volume drops below a threshold? HOT 4
- Simultaneous audio playback datatype issue HOT 2
- Does sd.wait() block all other threads? HOT 1
- OSERROR portaudio library not found
- Advice on detecting when Sounddevice has stopped playing audio (and using multiple OutputStreams)
- Inconsistent order of channels HOT 2
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from python-sounddevice.