Sounddevice error in Windows 7, using 1.85.0

This is somewhat related to Sarah’s post, but I’m getting a different error.

Some background: I’m using psychopy to display audio and video files for an EEG experiment, and I have sox doing some audio mixing. The script worked fine using pyo on a Mac, but when transferring to Windows, pyo worked at first and now gives a windows error “pythonw.exe has stopped working”, with no other psychopy error message. I am trying to switch to sounddevice to get around the pyo failure, but now running into this issue:

Traceback (most recent call last):
  File "E:\WordsInNoiseEEGKMDrive\LIPREAD_65_formatTest.py", line 1014, in <module>
    exp.run_experiment()
  File "E:\WordsInNoiseEEGKMDrive\LIPREAD_65_formatTest.py", line 215, in run_experiment
    self.do_task('baseline staircase')
  File "E:\WordsInNoiseEEGKMDrive\LIPREAD_65_formatTest.py", line 494, in do_task
    self.intertrial_interval(this_loudness, this_step)
  File "E:\WordsInNoiseEEGKMDrive\LIPREAD_65_formatTest.py", line 629, in intertrial_interval
    self.preload_stimulus(trial_volume, trial_params)
  File "E:\WordsInNoiseEEGKMDrive\LIPREAD_65_formatTest.py", line 879, in preload_stimulus
    self.THIS_TRIAL_SOUND.setSound(which_sound_file)
  File "C:\Program Files (x86)\PsychoPy2\lib\site-packages\psychopy\sound\backend_sounddevice.py", line 336, in setSound
    raise SoundFormatError(err)
psychopy.exceptions.SoundFormatError: Tried to create audio stream 48000_1_128 but 44100_1_128 already exists and win32 doesn't support multiple portaudio streams
From cffi callback <function callback_wrapper at 0x13AC7770>:
Traceback (most recent call last):

I saw one previous post stating that portaudio doesn’t support multiple streams (What would it take to replace pyo? - #8 by matthias.geier)
Is there a way around this? I was able to install pygame and got that working, but I’m noticing an issue with latency. Sounddevice supposedly has much better latencies - any ideas on how I can get it to work?

Thanks, let me know if you need more info!

1 Like

From the error messages I think you’ve got multiple sounds with different bit rates in your experiment. One has 48kHz and one has 44kHz. On a mac that’s fine but under windows we need a single format of sounds at one time. You’ll need to check your sound files and get them all in one sample rate.

Thanks Jon!

I’m pretty new to coding, so my apologies if these issues seem like an obvious fix.

I made sure all my files are the same sample rate, and most things seem to be working fine. However, I am having a problem with getDuration.

In my task, I need to get the duration of each sound file to the hundredth of a second. Right now, sounddevice (using both getDuration and the duration attribute) will only give me the duration of the file rounded down to the nearest integer.

For example, for sound files with the following lengths, sounddevice outputs:

1.401sec - sd output = 1
.978sec - sd output = 0
1.23sec - sd output = 1
5.00sec - sd output = 5

I can’t figure out a way to ask it to calculate more decimal points, and I need that level of precision or it messes up the whole task. Any ideas?

For the record, I also tried using pygame, and I’m getting a different error with getDuration. With pygame, files of the following lengths output the following durations:

1.401sec - sd output = .000145
.978sec - sd output = .000125
1.23sec - sd output = .000125
5.00sec - sd output = .0008333

Please help! Also, this is in Windows 7, psychopy version 1.85.0.

Thanks!

For pygame I have no idea what it returns. For sounddevice we’re simply using whatever soundfile returns, so maybe soundfile is doing some rounding (possibly accidentally).
One thing to try is adding the line:

from __future__ import division

to the top of your script. It might be that soundfile is assuming that its division is automatically converting to a float when needed (which happens in Python 3 but not in Python 2.7). This line at the top will use the Python3 style division in 2.7 (which means 1/3=0.33 rather than 1/3=0)

If that doesn’t work then maybe we need to claculate duration ourselves rather than trusting soundfile. We can do it with:

import soundfile as sf
f = sf.SoundFile(pathToMySound)
print('samples = {}'.format(len(f)))
print('sample rate = {}'.format(f.samplerate))
print('seconds = {}'.format(float(len(f)) / f.samplerate))
1 Like

This is indeed a bug in the soundfile module (only for Python 2.x), you should report it!

Independent of that, it doesn’t really make sense to open the file a second time with sf.info() when you already have a SoundFile object. You can simply calculate the duration as you mentioned.

Or you could suggest a duration attribute (or rather a property) for the soundfile.SoundFile class!

1 Like

I submitted a bugfix here so SoundFile here:
https://github.com/bastibe/PySoundFile/pull/196

But yes, I had assumed (by the fact that SoundInfo exists that it was useful ;-). Specifically I had assumed it as fetching the info without opening the file in the same way (e.g. reading some metadata). Now I look at the source code you’re quite right - we should just ignore it in PsychoPy and calculate ourselves.

@keis the long and short of it for you is that using the line I suggested at the top of your script:
from __future__ import division
should fix th problem for you, and is a good thing to do anyway. But hopefully we’ll fix this for future versions of psychopy too.

Thanks for raising it

Thank you Jon and Matthias!

I tried inserting from __future__ import division and that by itself wasn’t enough to fix it, but method of calculating it directly worked just fine. Since I was already using sox to mix sounds, I was also able to figure out how to get sox to get the duration of the file, which is the method I think I’ll end up using.

Thank you so much for you help though, and glad we were able to identify a bug