[python] Detect, Record Audio in Python

Viewer

copydownloadembedprintName: Detect, Record Audio in Python
  1. from sys import byteorder
  2. from array import array
  3. from struct import pack
  4.  
  5. import pyaudio
  6. import wave
  7.  
  8. THRESHOLD = 500
  9. CHUNK_SIZE = 1024
  10. FORMAT = pyaudio.paInt16
  11. RATE = 44100
  12.  
  13. def is_silent(snd_data):
  14.     "Returns 'True' if below the 'silent' threshold"
  15.     return max(snd_data) < THRESHOLD
  16.  
  17. def normalize(snd_data):
  18.     "Average the volume out"
  19.     MAXIMUM = 16384
  20.     times = float(MAXIMUM)/max(abs(i) for i in snd_data)
  21.  
  22.     r = array('h')
  23.     for i in snd_data:
  24.         r.append(int(i*times))
  25.     return r
  26.  
  27. def trim(snd_data):
  28.     "Trim the blank spots at the start and end"
  29.     def _trim(snd_data):
  30.         snd_started = False
  31.         r = array('h')
  32.  
  33.         for i in snd_data:
  34.             if not snd_started and abs(i) > THRESHOLD:
  35.                 snd_started = True
  36.                 r.append(i)
  37.  
  38.             elif snd_started:
  39.                 r.append(i)
  40.         return r
  41.  
  42.     # Trim to the left
  43.     snd_data = _trim(snd_data)
  44.  
  45.     # Trim to the right
  46.     snd_data.reverse()
  47.     snd_data = _trim(snd_data)
  48.     snd_data.reverse()
  49.     return snd_data
  50.  
  51. def add_silence(snd_data, seconds):
  52.     "Add silence to the start and end of 'snd_data' of length 'seconds' (float)"
  53.     silence = [0] * int(seconds * RATE)
  54.     r = array('h', silence)
  55.     r.extend(snd_data)
  56.     r.extend(silence)
  57.     return r
  58.  
  59. def record():
  60.     """
  61.     Record a word or words from the microphone and 
  62.     return the data as an array of signed shorts.
  63.  
  64.     Normalizes the audio, trims silence from the 
  65.     start and end, and pads with 0.5 seconds of 
  66.     blank sound to make sure VLC et al can play 
  67.     it without getting chopped off.
  68.     """
  69.     p = pyaudio.PyAudio()
  70.     stream = p.open(format=FORMAT, channels=1, rate=RATE,
  71.         input=True, output=True,
  72.         frames_per_buffer=CHUNK_SIZE)
  73.  
  74.     num_silent = 0
  75.     snd_started = False
  76.  
  77.     r = array('h')
  78.  
  79.     while 1
  80.         # little endian, signed short
  81.         snd_data = array('h', stream.read(CHUNK_SIZE))
  82.         if byteorder == 'big':
  83.             snd_data.byteswap()
  84.         r.extend(snd_data)
  85.  
  86.         silent = is_silent(snd_data)
  87.  
  88.         if silent and snd_started:
  89.             num_silent += 1
  90.         elif not silent and not snd_started:
  91.             snd_started = True
  92.  
  93.         if snd_started and num_silent > 300:
  94.             break
  95.  
  96.     sample_width = p.get_sample_size(FORMAT)
  97.     stream.stop_stream()
  98.     stream.close()
  99.     p.terminate()
  100.  
  101.     r = normalize(r)
  102.     r = trim(r)
  103.     r = add_silence(r, 0.5)
  104.     return sample_width, r
  105.  
  106. def record_to_file(path):
  107.     "Records from the microphone and outputs the resulting data to 'path'"
  108.     sample_width, data = record()
  109.     data = pack('<' + ('h'*len(data)), *data)
  110.  
  111.     wf = wave.open(path, 'wb')
  112.     wf.setnchannels(1)
  113.     wf.setsampwidth(sample_width)
  114.     wf.setframerate(RATE)
  115.     wf.writeframes(data)
  116.     wf.close()
  117.  
  118. if __name__ == '__main__':
  119.     print("please speak a word into the microphone")
  120.     record_to_file('demo.wav')
  121.     print("done - result written to demo.wav")
  122.  

Editor

You can edit this paste and save as new:


File Description
  • Detect, Record Audio in Python
  • Paste Code
  • 22 Oct-2020
  • 3.02 Kb
You can Share it: