#! lua local struct = require "struct" -- today's date in (almost) ISO-8601 format local function isodate() return os.date"%Y%m%d-%H%M%S" end -- Implement a buffer of samples. For simplicity, let the -- index increment without bound. Note that this will have -- a problem after 2^53 samples, which is about 30 million -- years at 10 samples per second. local recent = { depth=100, n=1, add=function(self,s) local n = self.n self[n] = s self[n-self.depth] = nil self.n = n + 1 end, buffer=function(self) local n1,n2 = self.n-self.depth, self.n-1 if n1 <= 0 or n2 <= 0 then return end return table.concat(self,'',self.n-self.depth,self.n-1) end } local function auheader(buf, rate) local fmt = ">c4LLLLLL" local hdr = struct.pack(fmt, ".snd", -- 0 magic number struct.size(fmt), -- 1 data offset #buf, -- 2 length or -1 1, -- 3 encoding uLaw rate, -- 4 8152 Hz sample rate 1, -- 5 mono 0) -- 6 empty metadata string return hdr end local function writeau(au, buf) local f = assert(io.open(au,"wb")) f:write(auheader(buf, 8152), buf) f:close() end function writemp3(name, udata) local soxgate = 'compand .1,.2 -inf,-55.1,-inf,-55,-55 0 -90 .1 ' local soxcompand = 'compand 0.3,1 6:-70,-60,-20 -5 -90 0.2 ' local soxcmd = 'sox -t au - -t wav -b 16 - ' .. soxgate .. soxcompand ..'| lame - '..name print(soxcmd) local fp = assert(io.popen('sh -c "'..soxcmd..'"', 'w')) fp:write(auheader(udata, 8152), udata) fp:close() end -- Quick and dirty way to force the UART to have the -- tty driver settings we need for clean raw access -- to the port. os.execute("stty -F /dev/ttyAMA0 115200" .." pass8 raw -iexten" .." -echo -echoe -echok -echoke -echoctl") -- Open the UART for both reading and writing, and send -- the SPLear command to go into uLaw recording mode. The -- output must be unbuffered because the current SPLear -- firmware would revert to 0.5 Hz summary mode if it -- receives a newline. local port = assert(io.open('/dev/ttyAMA0','r+')) port:setvbuf"no" -- no output buffer at all port:write"R" -- so this write is immediate -- Loop reading the audio stream and watching for loud -- noises, keeping a log of recent samples as we go. -- When a loud noise is heard, keep logging for a bit -- before sending email. Include the log in the email. while true do local buf = port:read(1000) -- sampled at 8153 Hz probably recent:add(buf) if recent.n % 8 == 0 then io.write(tostring(recent.n),"\r") io.flush() end if recent.n > recent.depth then local eek = "rec-"..isodate() --writeau(eek..".au", recent:buffer()) writemp3(eek..".mp3", recent:buffer()) return end end