Microphone does not work in multiple routines

If this template helps then use it. If not then just delete and start from scratch.

OS (e.g. Win10): Win10
PsychoPy version (e.g. 1.84.x): 2022.2.2
Standard Standalone? (y/n) If not then what?: Yes
What are you trying to achieve?: using microphone to record each production in multiple routines

What did you try to make it work?: I was able to record when there was only one routine, but the exp failed as soon as I added in another routine.

What specifically went wrong when you tried that?: When i tried to use the PTB driver, here is the error message that I encountered:

PTB-ERROR: Failed to open audio device 8. PortAudio reports this error: Invalid device
Traceback (most recent call last):
File “C:\Users\labuser\Desktop\hsc_dissertation\production\practice_session\run_psychopy_minimal_working_example_lastrun.py”, line 184, in
q1_mic = sound.microphone.Microphone(
File “C:\Program Files\PsychoPy\lib\site-packages\psychopy\sound\microphone.py”, line 478, in init
self._stream = audio.Stream(
File “C:\Program Files\PsychoPy\lib\site-packages\psychtoolbox\audio.py”, line 97, in init
self.handle = PsychPortAudio(‘Open’, device_id, mode,
Exception: Failed to open PortAudio audio device due to unsupported combination of audio parameters.
Exception ignored in: <function Stream.del at 0x000001F957A7AF70>
Traceback (most recent call last):
File “C:\Program Files\PsychoPy\lib\site-packages\psychtoolbox\audio.py”, line 236, in del
self.close()
File “C:\Program Files\PsychoPy\lib\site-packages\psychtoolbox\audio.py”, line 146, in close
raise err
File “C:\Program Files\PsychoPy\lib\site-packages\psychtoolbox\audio.py”, line 139, in close
PsychPortAudio(‘Close’, self.handle)
AttributeError: ‘Stream’ object has no attribute ‘handle’
################ Experiment ended with exit code 1 [pid:12824] #################

I have encountered similar error as well when I used sounddevice as the driver.

File “C:\Users\labuser\Desktop\hsc_dissertation\production\practice_session\run_psychopy_minimal_working_example_lastrun.py”, line 184, in
q1_mic = sound.microphone.Microphone(
File “C:\Program Files\PsychoPy\lib\site-packages\psychopy\sound\microphone.py”, line 478, in init
self._stream = audio.Stream(
File “C:\Program Files\PsychoPy\lib\site-packages\psychtoolbox\audio.py”, line 97, in init
self.handle = PsychPortAudio(‘Open’, device_id, mode,
Exception: Failed to open PortAudio audio device due to unsupported combination of audio parameters.
Exception ignored in: <function Stream.del at 0x000001697F73CF70>
Traceback (most recent call last):
File “C:\Program Files\PsychoPy\lib\site-packages\psychtoolbox\audio.py”, line 236, in del
self.close()
File “C:\Program Files\PsychoPy\lib\site-packages\psychtoolbox\audio.py”, line 146, in close
raise err
File “C:\Program Files\PsychoPy\lib\site-packages\psychtoolbox\audio.py”, line 139, in close
PsychPortAudio(‘Close’, self.handle)
AttributeError: ‘Stream’ object has no attribute ‘handle’
0.9432 WARNING Monitor specification not found. Creating a temporary one…
################ Experiment ended with exit code 1 [pid:12664] #################

It really does seem to me that somehow PsychoPy cannot open another microphone even though the recording parameters are entirely the same as the first microphone. I have attached my PsychoPy minimal working example below.

working_exp_2022_08_15.zip (101.3 KB)

Any help is appreciated given that I am in a time crunch and I would love to use this recording function for my experiment.

Hello HungShao,

Since the main issue appears to be that PTB cannot get a device with the audio parameters you are using. Try setting your microphone’s sample rate to 44.1KHz under the “Hardware” tab of the microphone component.

Hi @mdc, thank you for the reply. I have set the sampling rate to 44.1 KHZ in the microphone component before and it did not work (when there was only one routine). Turned out the audio interface I am using only allows me to record using sampling rate of 48K. But this worked when there was only one routine.

more update: i was able to switch the sampling rate from 48K to 44.1 in the audio interface. I still get the same error about not being able to use the second microphone.

Hi, @mdc . I am having the same issue. Having more than one routine with mic component worked fine using Mac OS, but giving me the error on Windows. I’ve seen people reporting the same issue here and there, but haven’t found any solutions other than having one mic. However, I need to have multiple routines with a mic. Any solutions?

Hi @deh10 unfortunately i don’t think there is a solution yet. I have been trying to debug this. Here is what I have been doing – rather than adding the microphone component in GUI for the second routine, I inserted a code chunk and putting relevant code for the microphone.

While the error in my original post is gone, when I checked the recording, not all sound files were saved. There should be 3 wav files but only 2 were saved. The first production in the first routine did not get saved. I wonder if its due to an error in the code chunk. I am attaching an updated zip folder that contains the working minimal example here.

For the second routine, here is what I added:

At the begin routine:

mic_q1 = sound.microphone.Microphone(
    device=8, channels=1, 
    sampleRateHz=44100, maxRecordingSize=24000.0)

At each frame:

if mic_q1.status == NOT_STARTED and t >= 0.4-frameTolerance:
    # keep track of start time/frame for later
    mic_q1.frameNStart = frameN  # exact frame index
    mic_q1.tStart = t  # local t and not account for scr refresh
    mic_q1.tStartRefresh = tThisFlipGlobal  # on global time
    win.timeOnFlip(mic_q1, 'tStartRefresh')  # time at next scr refresh
    # add timestamp to datafile
    thisExp.addData('mic_q1.started', t)
    # start recording with mic
    mic_q1.start()
    mic_q1.status = STARTED
if mic_q1.status == STARTED:
    # update recorded clip for mic
    mic_q1.poll()
if mic_q1.status == STARTED:
    # is it time to stop? (based on global clock, using actual start)
    if tThisFlipGlobal > mic_q1.tStartRefresh + 4.55-frameTolerance:
        # keep track of stop time/frame for later
        mic_q1.tStop = t  # not accounting for scr refresh
        mic_q1.frameNStop = frameN  # exact frame index
        # add timestamp to datafile
        thisExp.addData('mic_q1.stopped', t)
        # stop recording with mic
        mic_q1.stop()
        mic_q1.status = FINISHED

At end routine:

# tell mic to keep hold of current recording in mic.clips and transcript (if applicable) in mic.scripts
# this will also update mic.lastClip and mic.lastScript
mic_q1.stop()
tag_q1 = data.utils.getDateStr()
micClip = mic_q1.bank(tag=tag, 
    transcribe='None',
    config=None
)   
q1_trials.addData('mic_q1.clip', os.path.join(micRecFolder, 'recording_mic_%s.wav' % tag_q1))

At end experiment:

for tag_q1 in mic_q1.clips:
    for i, clip in enumerate(mic_q1.clips[tag_q1]):
        clipFilename = 'recording_mic_%s.wav' % tag_q1
        print(i)
        print(clip)
        # if there's more than 1 clip with this tag, append a counter for all beyond the first
        if i > 0:
            clipFilename += '_%s' % i
        clip.save(os.path.join(micRecFolder, clipFilename))```

working_exp_2022_08_17.zip (134.0 KB)

see my solution on this post:

Dear Hung Shao,

thank you very much for your solution. I have a similar problem.
I dowloaded your experiment and it works perfectly. However, when I transfer the exact setting to my experiment, where I too need a second microphone component in another routine, I still get this error message:
PsychPortAudio(‘Close’, self.handle)
AttributeError: ‘Stream’ object has no attribute ‘handle’

Any idea why this could be the case?^^

Thanks a lot
Kind regards

Hi there,

I can see the issue here - Builder is trying to initialise the the script isn’t allowing the mic to be initialised twice because it appears in 2 Routines. We know the steps we need to fix this and we’re working on it.

In the meantime, there are 2 solutions. The main one is that you can try to find a way to take a single Routine and simply use it twice in the Flow. That’s the right thing to do in general anyway - a lot of people create their Routine more than once even when the structure of the Routine differs very little (e.g. to present some house images, or to present some face images, just use a single Routine and change the contents of the image don’t create 2 different Routines). If you’re able to do that then your problem will go away.

If your Routines do differ a lot in structure but both need a mic then you will need to do something like the above, where the 2nd Routine to use the device needs to have a code component instead of a standard mic component… until we have a fix in place in a PsychoPy release for you

best wishes
Jon

Hi, I’ve got a bug fix in now so that will be in the next release :slight_smile: What will happen in future is, rather than creating one psychopy.sound.Microphone object per component, Builder will create one per device and then will assign the name of the corresponding components to the device object - meaning the component will function as normal but there won’t be multiple initialisations for the same device.

1 Like

We were able to fix the issue by using code components in both routines with a microphone, and it was initialised only once.
That also worked in another experiment, where I used three microphone components.

Very nice to hear that this will be fixed in the next release! :smiley: