psychopy.org | Reference | Downloads | Github

Microphone creating file but no sound

PsychoPy2 v1.85.4

I’m trying to get the microphone to work without any luck. I’ve got it to the point where a .wav file is saved. The file is the appropriate duration, but it is silent (just as has been reported here and here). I’ve even tried the hacky solution I found here but couldn’t get it to work either (I end up with a zero-byte wav file). Does anyone have a solution to this?

I have had the same issue and have had no luck finding a solution either :frowning: Waiting for one!

This is might be helpful and is also a follow up to my post “Need voicekey working code (psychopy3)” . With help from many posts here, in stack exchange, and other places, I have the following code working to get sound from a mic, establish a primitive threshold, and use the mic signal live as a voice key. See if you can get this running to establish that the mic stream is working and then we can work on writing the file(s). (note this is for psychopy3, python3, and linux). I modified some of the borrowed code from python2. Note: I make no claims and assume no liability for the following (and yes, I use nonstandard full 8 tabs and my coding style is ugly… there may be irrelevant variables and code here because I am building on it. Trust anything Jon Peirce or other capable people say about this. Hope nothing broke in the paste)

#!/usr/bin/python3                                                                                                                                  
import pyaudio
import struct
import math
import numpy

import psychopy
from psychopy import visual, core, event, sound

# https://stackoverflow.com/questions/4160175/detect-tap-with-pyaudio-from-live-mic
### FOR MICROPHONE
INITIAL_TAP_THRESHOLD = 0.010
FORMAT = pyaudio.paInt16
SHORT_NORMALIZE = (1.0/32768.0)
CHANNELS = 2
RATE = 44100
INPUT_BLOCK_TIME = 0.005
INPUT_FRAMES_PER_BLOCK = int(RATE*INPUT_BLOCK_TIME)
###################################################

def get_rms(block):

   # RMS amplitude is defined as the square root of the 
   # mean over time of the square of the amplitude.
   # so we need to convert this string of bytes into 
   # a string of 16-bit samples...

   # we will get one short out for each 
   # two chars in the string.
   count = len(block)/2
   format = "%dh"%(count)
   shorts = struct.unpack( format, block )

   # iterate over the block.
   sum_squares = 0.0
   for sample in shorts:
   # sample is a signed short in +/- 32768. 
   # normalize it to 1.0
       n = sample * SHORT_NORMALIZE
       sum_squares += n*n

   return math.sqrt( sum_squares / count )

timer1=core.Clock()
sw1=timer1.getTime()
sw2=timer1.getTime()

pa = pyaudio.PyAudio()          
                                                    
micstream = pa.open(format = FORMAT,               
        channels = CHANNELS,                    
        rate = RATE,                               
        input = True, output=False,                 
        frames_per_buffer = INPUT_FRAMES_PER_BLOCK)  

#  calibrate 500 samples in background
print ("calib starting: \nfinding ceiling of silence noise ...")

amps=[]
for i in range(500):
   try:                                                   
       block = micstream.read(INPUT_FRAMES_PER_BLOCK)        
   except IOError as e:                                     
       print( "(%d) Error recording: %s"%(errorcount,e) )

   amplitude = get_rms(block)
   amps.append(amplitude)

print ( "%9.6f"% numpy.mean(amps) )
print ( "%9.6f"% numpy.min(amps) )
print ( "%9.6f"% numpy.max(amps) )

MULTIPLIER=1.500
nfloor=MULTIPLIER*numpy.max(amps)
print ("calib complete: \nsetting threshold to 2.0 x silence maxnoise (%7.4f)"%nfloor)

print (" mic is live for a while " )
sw1=timer1.getTime()
sw2=timer1.getTime()
sw3=timer1.getTime()
core.wait(0.5000)

#stream.stop_stream()
#stream.start_stream()
print (" trial  amplitude   streamstart    RT " )
vk=0
for i in range(5):        # run 5 test trials
   core.wait(1.0000)
   amplitude=0.000
   vk=0                                                                                                                                             
   bracket=2000.00    # resp timeout
   ET=0.0
   print ("trial")
   sw1=timer1.getTime()
   micstream.start_stream()
   sw2=timer1.getTime()
   while vk==0 and ET < bracket:
       block = micstream.read(INPUT_FRAMES_PER_BLOCK)        
       amplitude = get_rms(block)
       #print ( amplitude)
       ET=(timer1.getTime()-sw2) * 1000.000
       if amplitude > nfloor:
           sw3=timer1.getTime()
           print("%4d    %8.6f  %8.2f  %8.2f"%( i, amplitude,  1000.0*(sw2-sw1),  1000.0*(sw3-sw2) ) )
           vk=1
           micstream.stop_stream()
   if vk==0 and ET > bracket:
       print( ET, "timeout: no resp")
       RT=99999.99
   else:
       RT= 1000.0*(sw3-sw2)

   print ("\t\t\t\t\tWR:  %12.4f\n"%RT)                                                                                                             
                                                                                                         

AFAIK, if you can get this much working, then you will just need to convert the “blocks” to wav and write the file.