parallelise serial port usage and I/O for writing sounds files
--- a/scannr.py
+++ b/scannr.py
@@ -12,60 +12,102 @@
#python -m serial.tools.miniterm -p COM20 -e -b 115200 --cr
import psycopg2
import csv
-import sys,os
+import sys
+import os
sys.path.insert(0, os.path.join(os.path.dirname(__file__) or '.', 'pynma'))
import pynma
filename = "demo.wav"
+last_call = (None, None, None)
MIN_LENGTH = 90000
+lock = threading.RLock()
-def worker(filename, length):
+def get_call():
+ global lock
+ with lock:
+ ser.write("GLG\r")
+ line = ser.readline() # read a '\n' terminated line
+ print line
+ reader = csv.reader([line])
+ for row in reader:
+ #GLG,40078,NFM,0,0,CanberraBlackMnt,AustralianCapita,SES Ops 1,1,0
+ #,NONE,NONE,NONE
+ if (row[0] != 'GLG' or row[1] == ''):
+ print "uh oh"
+ return (None, None, None)
+ if (row[1] != ''):
+ tgid = row[1]
+ #nma.push("scannr", "ping", filename, "http://www.google.com")
+ tgname = row[7]
+ sitename = row[5]
+ return (tgid, tgname, sitename)
+
+def log_recording(tgid, tgname, sitename, filename, length):
+ cur = conn.cursor()
+ cur.execute("INSERT INTO recordings \
+ (tgid, tgname, sitename, filename, length)\
+ VALUES (%s, %s, %s, %s, %s)",( tgid, tgname, sitename, filename, length))
+ conn.commit()
+ cur.close()
+
+
+def tgid_worker():
+ global last_call
+ last_call = get_call()
+
+
+def save_worker(filename, length):
+ global last_call
"""thread worker function
http://www.doughellmann.com/PyMOTW/threading/
https://github.com/uskr/pynma
ffmpeg -i 2012-09-29-1348911268.34-demo.wav -ar 8000 -ab 4.75k test.3gp
-http://stackoverflow.com/questions/2559746/getting-error-while-converting-wav-to-amr-using-ffmpeg
+http://stackoverflow.com/questions/2559746/getting-error-while-converting-
+wav-to-amr-using-ffmpeg
"""
- print 'Worker for '+filename
- ser.write("GLG\r")
- line = ser.readline() # read a '\n' terminated line
- print line
- reader = csv.reader([line])
- for row in reader:
- #GLG,40078,NFM,0,0,CanberraBlackMnt,AustralianCapita,SES Ops 1,1,0,NONE,NONE,NONE
- if (row[0] != 'GLG'):
- print "uh oh"
- if (row[1] != ''):
- tgid = row[1]
- #nma.push("scannr", "ping", filename, "http://www.google.com")
- tgname = row[7]
- sitename = row[5]
- """http://initd.org/psycopg/docs/usage.html"""
- cur = conn.cursor()
- cur.execute("INSERT INTO recordings (filename,tgid,tgname,sitename,length) VALUES (%s, %s,%s, %s, %s)",(filename,tgid,tgname,sitename, length))
- conn.commit()
- cur.close()
+ print 'Worker for ' + filename
+ (oldtgid, oldtgname, oldsitename) = last_call
+ (tgid, tgname, sitename) = get_call()
+ if oldtgid == tgid:
+ if tgid == None or tgid == '':
+ print filename + " has no TGID"
else:
- print filename+" has no TGID"
+ log_recording(tgid, tgname, sitename, filename, length)
+ else:
+ if tgid == None or tgid == '':
+ print filename + " has no TGID"
+ else:
+ log_recording(tgid, tgname, sitename, filename, length)
+ if oldtgid == None or oldtgid == '':
+ print filename + " has no old TGID"
+ else:
+ log_recording(oldtgid, oldtgname, oldsitename, filename, length)
+ return
- return
def filenameMaker():
global filename
filename = date.today().isoformat()+'-'+str(time.time())+'-demo.wav'
-def record_to_async_file():
- "Records from the microphone and outputs the resulting data to `path`"
+def do_record():
sample_width, data = snd.record()
- print str(len(data))
+ thr = threading.Thread(target=record_to_async_file, args=(sample_width,data,filename))
+ thr.start()
+
+
+def record_to_async_file(sample_width,data,filename):
+ "Records from the microphone and outputs the resulting data to `filename`"
+ print "Recording complete"
if len(data) > MIN_LENGTH:
+ print "Recording being saved..."
+ dispatcher.send( signal='FILE_CREATED', sender=filename, filename=filename, length=len(data))
+ print str(len(data))
data = snd.pack('<' + ('h'*len(data)), *data)
path = "./data/"+filename
- dispatcher.send( signal='FILE_CREATED', sender=filename, filename=filename, length=len(data))
wf = wave.open(path, 'wb')
wf.setnchannels(2)
wf.setsampwidth(sample_width)
@@ -77,20 +119,23 @@
del data
dispatcher.connect( filenameMaker, signal='SND_STARTED', sender=dispatcher.Any )
-dispatcher.connect( worker, signal='FILE_CREATED', sender=dispatcher.Any )
+dispatcher.connect( tgid_worker, signal='SND_STARTED', sender=dispatcher.Any )
+dispatcher.connect( save_worker, signal='FILE_CREATED', sender=dispatcher.Any )
print "Opening serial port..."
if sys.platform.startswith('darwin'):
- ser = serial.Serial('/dev/tty.usbserial-FTB3VL83', 112500, timeout=1)
+ ser = serial.Serial('/dev/tty.usbserial-FTB3VL83', 112500, timeout=1)
elif sys.platform.startswith('win32'):
- ser = serial.Serial('COM20', 112500, timeout=1)
+ ser = serial.Serial('COM20', 112500, timeout=1)
print "Loading notifymyandroid..."
-nma = pynma.PyNMA( "a6f50f76119eda33befe4325b4b9e1dd25eef7bad2868e4f")
+nma = pynma.PyNMA( "a6f50f76119eda33befe4325b4b9e1dd25eef7bad2868e4f")
print "Connecting database..."
conn = psycopg2.connect("dbname=scannr user=postgres password=snmc")
print "Scannr started."
while True:
print "ready to record again"
- record_to_async_file()
+ do_record()
ser.close()
+
+
--- a/snd.py
+++ b/snd.py
@@ -1,15 +1,12 @@
-""" Record a few seconds of audio and save to a WAVE file.
+""" 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
from pydispatch import dispatcher
THRESHOLD = 500
@@ -21,7 +18,7 @@
elif sys.platform.startswith('win32'):
CHANNELS = 1
-MAX_SILENT = 60
+MAX_SILENT = 80
def is_silent(L):
"Returns `True` if below the 'silent' threshold"
@@ -72,16 +69,16 @@
def record():
"""
- Record a word or words from the microphone and
+ 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
+ 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=CHANNELS, rate=RATE,
+ stream = p.open(format=FORMAT, channels=CHANNELS, rate=RATE,
input=True,
frames_per_buffer=CHUNK_SIZE)
@@ -110,6 +107,8 @@
dispatcher.send( signal='SND_STARTED')
snd_started = True
print snd_started
+ if snd_started and not silent:
+ num_silent = 0
if snd_started:
LRtn.extend(L)
if snd_started and num_silent > MAX_SILENT: