Documentation
#! 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