initial commit
--- /dev/null
+++ b/scannr.py
@@ -1,1 +1,32 @@
+import snd
+import time
+from datetime import date
+import threading
+filename = ""
+def worker(filename):
+ """thread worker function
+ http://www.doughellmann.com/PyMOTW/threading/
+
+ https://github.com/uskr/pynma"""
+ print 'Worker for '+filename
+ return
+
+def filenameMaker():
+ global filename
+ while True:
+ filename = date.today().isoformat()+'-'+str(time.time())+'-demo.wav'
+ time.sleep(5)
+
+
+
+threads = []
+fm = threading.Thread(target=filenameMaker)
+fm.daemon = True
+fm.start()
+print "Scannr started..."
+while True:
+ print "ready to record"
+ snd.record_to_file(filename)
+ t = threading.Thread(target=worker,args=(filename,))
+ t.start()
--- /dev/null
+++ b/snd.py
@@ -1,1 +1,135 @@
+""" Record a few seconds of audio and save to a WAVE file.
+Based on http://stackoverflow.com/questions/892199/detect-record-audio-in-python/6743593#6743593
+"""
+import pyaudio
+import wave
+import sys
+import audioop # http://docs.python.org/library/audioop
+from os.path import exists
+from array import array
+from struct import unpack, pack
+import threading
+
+CHANNELS = 1
+THRESHOLD = 500
+CHUNK_SIZE = 1024
+FORMAT = pyaudio.paInt16
+RATE = 44100
+
+def is_silent(L):
+ "Returns `True` if below the 'silent' threshold"
+ "print max(L)"
+ "print max(L) < THRESHOLD"
+ return max(L) < THRESHOLD
+
+def normalize(L):
+ "Average the volume out"
+ MAXIMUM = 16384
+ times = float(MAXIMUM)/max(abs(i) for i in L)
+
+ LRtn = array('h')
+ for i in L:
+ LRtn.append(int(i*times))
+ return LRtn
+
+def trim(L):
+ "Trim the blank spots at the start and end"
+ def _trim(L):
+ snd_started = False
+ LRtn = array('h')
+
+ for i in L:
+ if not snd_started and abs(i)>THRESHOLD:
+ snd_started = True
+ LRtn.append(i)
+
+ elif snd_started:
+ LRtn.append(i)
+ return LRtn
+
+ # Trim to the left
+ L = _trim(L)
+
+ # Trim to the right
+ L.reverse()
+ L = _trim(L)
+ L.reverse()
+ return L
+
+def add_silence(L, seconds):
+ "Add silence to the start and end of `L` of length `seconds` (float)"
+ LRtn = array('h', [0 for i in xrange(int(seconds*RATE))])
+ LRtn.extend(L)
+ LRtn.extend([0 for i in xrange(int(seconds*RATE))])
+ return LRtn
+
+def record():
+ """
+ Record a word or words from the microphone and
+ return the data as an array of signed shorts.
+
+ Normalizes the audio, trims silence from the
+ start and end, and pads with 0.5 seconds of
+ blank sound to make sure VLC et al can play
+ it without getting chopped off.
+ """
+ p = pyaudio.PyAudio()
+ stream = p.open(format=FORMAT, channels=1, rate=RATE,
+ input=True, output=True,
+ frames_per_buffer=CHUNK_SIZE)
+
+ num_silent = 0
+ snd_started = False
+
+ LRtn = array('h')
+
+ while 1:
+ data = stream.read(CHUNK_SIZE)
+ L = unpack('<' + ('h'*(len(data)/2)), data) # little endian, signed short
+ L = array('h', L)
+ LRtn.extend(L)
+
+ silent = is_silent(L)
+ #print silent, num_silent, L[:10]
+
+ if silent and snd_started:
+ num_silent += 1
+ print num_silent
+ elif not silent and not snd_started:
+ snd_started = True
+ print snd_started
+ if snd_started and num_silent > 30:
+ break
+
+ sample_width = p.get_sample_size(FORMAT)
+ stream.stop_stream()
+ stream.close()
+ p.terminate()
+
+ LRtn = normalize(LRtn)
+ LRtn = trim(LRtn)
+ LRtn = add_silence(LRtn, 0.5)
+ return sample_width, LRtn
+
+def record_to_file(path):
+ "Records from the microphone and outputs the resulting data to `path`"
+ sample_width, data = record()
+ data = pack('<' + ('h'*len(data)), *data)
+
+ wf = wave.open(path, 'wb')
+ wf.setnchannels(1)
+ wf.setsampwidth(sample_width)
+ wf.setframerate(RATE)
+ wf.writeframes(data)
+ wf.close()
+ print("done - result written to "+path)
+
+
+
+
+if __name__ == '__main__':
+ filename = 'demo.wav'
+ record_to_file(filename)
+ print("done - result written to "+filename)
+