I am using OpenSesame (an experiment builder using Python) to collect participants' voice response to specific stimuli using PyAudio.
What I want to achieve is the following :
- Start recording sound for X seconds (timeout).
- Compute "loudness" of sound and compare to a pre-defined threshold.
- Get the time when the sound reaches the threshold if it does.
- Save the sound in a
.wav
file when recording is done.
It's working quite well except that the sound recorded stops when the threshold is reached.
How could I continue recording the sound (and compute the loudness) when the threshold is reached (until timeout, for example)?
The code was adapted from [here][1]. Here is my code:
import pyaudio
import struct
import math
import wave
timeout = 5000
sound_threshold = 0.001
CHUNK = 1024
SHORT_NORMALIZE = (1.0/32768.0)
FORMAT = pyaudio.paInt16
CHANNELS = 2
RATE = 44100
RECORD_SECONDS = 5
WAVE_OUTPUT_FILENAME = "output.wav"
p = pyaudio.PyAudio()
def get_rms(block):
"""Get root mean square as a measure of loudness"""
count = len(block)/2
format = "%dh" % (count)
shorts = struct.unpack( format, block )
sum_squares = 0.0
for sample in shorts:
n = sample * SHORT_NORMALIZE
sum_squares += n*n
return math.sqrt( sum_squares / count )
stream = p.open(format=FORMAT,
channels=CHANNELS,
rate=RATE,
input=True,
frames_per_buffer=CHUNK)
print("* recording")
frames = []
start_time = clock.time()
while True:
if clock.time() - start_time >= timeout:
var.response_time = timeout
var.response = u'timeout'
var.loudness = None
var.in_clock_time = clock.time()
var.start = start_time
break
try:
block = stream.read(CHUNK)
frames.append(block)
except IOError as e:
print(e)
loudness = get_rms(block)
print(loudness)
if loudness > sound_threshold:
var.response_time = clock.time() - start_time
var.response = u'detected'
var.in_clock_time = clock.time()
var.start = start_time
var.loudness = loudness
break
print(response)
print(response_time)
print("* done recording")
stream.stop_stream()
stream.close()
p.terminate()
wf = wave.open(WAVE_OUTPUT_FILENAME, 'wb')
wf.setnchannels(CHANNELS)
wf.setsampwidth(p.get_sample_size(FORMAT))
wf.setframerate(RATE)
wf.writeframes(b''.join(frames))
wf.close()
´´´
[1]: https://forum.cogsci.nl/discussion/1772/detecting-voice-onsets-voicekey