Sound Feedback, playing back just recorded sound file

OS (e.g. Win10): Win10
PsychoPy version (e.g. 1.84.x): 2022.2.4
Standard Standalone? (y/n) If not then what?:
What are you trying to achieve?: I’m building an experiment, where participants will have to give verbal answers via a microphone. To make sure, the microphone is working every time and to see, if sounds are stored correctly, I want to play the recorded sound back to them in the next routine usind Sound.
I build the experiment using Builder. To get the just recorded sound I set sound = mic_PAS.getRecording() and marked the source of the sound with $sound. (mic_PAS is the name of the routine where Participants have to talk into the microphone.) I have honestly no idea if this is working or even how it’s supposed to be done. But I can’t really check, because I get this error message:
File “C:\Program Files\PsychoPy\lib\site-packages\psychtoolbox\audio.py”, line 249, in init
self.handle = PsychPortAudio(‘FillBuffer’, self.stream.handle,
SyntaxError: Missing argument

That’s baffeling for me because, of course, I didn’t write the audio.py code, so it’s not customized. My only guess is, that there is a setting somewhere I have to change to provide the code snippet with the missing argument?

I’d be really grateful for help!
Kind Regards
Lotti

Hi @Lotti,

what you could do other than trying to internally pass the recording from the mic to the sound component is forcing PsychoPy to save the recording immediately when it’s done and point the sound component to the file that has just been written.

Here is an example of what that could look like:
mictest.psyexp (11.2 KB)

Hi ajus,

thank you for your quick answer!
I tried your code and changed it as follows:

for tag in mic_PAS.clips:
for i, clip in enumerate(mic_PAS.clips[tag]):
clipFilename = ‘recording_mic_PAS_%s.ogg’ % tag
# if there’s more than 1 clip with this tag, append a counter for all > beyond the first
if i > 0:
clipFilename += ‘%s_%s_%s’ % i
clip.save(os.path.join(‘%s_%s_%s_mic_PAS_recorded’ % tag, > clipFilename))

sound_file = os.path.join(‘%s_%s_%s_mic_PAS_recorded’ % tag, > clipFilename)

I used %s_%s_%s to indivate all the components that are flexibel. The folder’s name is made up of the participant number, which changes of course with every participant number, the experiment data, which is a fixed name (metacontrast_feedback) and the date, which of course changes to (since it also provides the time at which the experiment was run).
The names for the folder and file seem to be correctly called upon. I was worried about how to indicate the right names, since they’re changing from participant to participant (and date to date).
Now I get this error message:
TypeError: not enough arguments for format string

Do you know how I could fix this?
I hope I provided enough information…

Kind regards
Lotti

Maybe this helps: String Formatting - Learn Python - Free Interactive Python Tutorial

Dear ajus,

I changed the code again, because I noticed the name for my file folder was wrong.
That’s how the code’s looking now:

for tag in mic_PAS.clips:
for i, clip in enumerate(mic_PAS.clips[tag]):
clipFilename = ‘recording_mic_PAS_%s.ogg’ % tag
# if there’s more than 1 clip with this tag, append a counter for all > > beyond the first
if i > 0:
clipFilename += ‘%s_%s_%s’ % i
clip.save(os.path.join(mic_PASRecFolder, clipFilename))

sound_file = os.path.join(mic_PASRecFolder, clipFilename)

Incredibly, the experiment didn’t crash, which I take as a win.
However, the sound that was played back to me was empty.

I noticed that I had indicated the sound name wrong and changed it to $sound_file, to match the code.

Now I’m getting this error message:
ValueError: setSound: could not find a sound file named U:\PsychoPy\metacontrast_masking\data\77_metacontrast_feedback_2022-09-30_13h09.00.383_mic_PAS_recorded\recording_mic_PAS_2022-09-30_13h09.16.535.ogg

The names are correct: that’s how the files should be stored. But the folder is empty. I had this problem before and the solution was to run the experiment till the end, then all the files were stored. But in this particular setting, I need the files before.
I know, your original idea was to make psychopy store the just recorded sound file. I just haven’t succeeded in making it do that yet…

Thanks so much again.

Kind regards
Lotti

Hi @lotti, I am sorry to say that don’t really get what you are trying to do. Are you trying to change the file name and the directory? If so, why?

If it’s just about adapting my code to your experiment and you don’t want to do anything extra, you can just open your .py file with a text editor and search for “# save mic recordings”. There you find the code that usually runs at the end of the experiment and which you can copy-paste to the correct location.

Ah, ok, thank you.

I opened the .py file with the text editor and pasted the code snippet to the correct location, but now psychopy won’t open that skript to run it.
I tried to change the code in the coder directly, but then I get the following error message:
“U:\PsychoPy\metacontrast_masking\metacontrast_masking_withFeedback.py”, line 1320
for tag in
^
SyntaxError: invalid syntax
but that’s acutally nothing I changed or even touched, soo…

I’m a big noob when it comes to psychopy. I hope, I’m gonna figure this out eventually :slight_smile:
Thank you so much for your help!

Kind regards
Lotti

Sorry, let me be more clear: Copy it and paste it into the code component (in the builder!) where you were working on the code that came from me originally.

Hello Ajus,

haha yes, that should have been obvious.

I was able to make the experiment run with a lot of help from a software devolper over the weekend (my husband :))
I’m posting the code here in case it’s helpful for someone else. We inserted it into a code component in the routine of the sound feedback.

what sound to play

get the last element from dictionary mic_PAS.clips

tag = list(mic_PAS.clips)[-1]

get the clip name, need to unpack the clip list

clip = mic_PAS.clips[tag][0]

clip cntr based on length of dictionary mic_PAS.clips

clip_counter = len(mic_PAS.clips)

join file name and path

curr_clip_filename = f’recording_mic_PAS_{tag}_{clip_counter}.ogg’
feedback_sound_file = os.path.join(mic_PASRecFolder, curr_clip_filename)
clip.save(feedback_sound_file)

It’s probably obvious, but the hardware setting of the microphone needs to match the actual microphone you’re using. We had a lot of crashes because hardware was set to 48kHz instead of 44.1kHz. I use a different microphone in the office than we used at home to fix the experiment.

Kind regards
Lotti

Hi @ajus, how are you, you know I am using your code to play the replay (feedback) of the recording (mictest.psyexp file). Everything works fine, but when I add another trial. The program does not run. Can you help me?

Hi Francisco, do you mean when you add a loop? Is there an error?


As shown in the picture, it works, also with the loop!! The error is when I want to add another trial but with the sound with different intensity.

And what kind of error do you get?

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’

Hi Lotti, could this code be used online/on Pavlovia? I’d like to do similar things - play the audio recording from the last trial back to the participants during the test, but I am hoping to do this online. So far, the microphone cannot save the real-time recording immediately until the end of the whole test online. In this case, I could not play back the audio file to the participant right after they made response to a trial.