Skip to content

Instantly share code, notes, and snippets.

@cfillion
Last active March 15, 2024 01:22
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save cfillion/aeeb38701160d9933d737cf2eeea0add to your computer and use it in GitHub Desktop.
Save cfillion/aeeb38701160d9933d737cf2eeea0add to your computer and use it in GitHub Desktop.
Lua WAV file reader (chunk parser)
-- http://www-mmsp.ece.mcgill.ca/Documents/AudioFormats/WAVE/WAVE.html
-- usage example at the end
local WavReader = {}
WavReader.__index = WavReader
function WavReader.new(fn)
local self = setmetatable({}, WavReader)
self.file, err = io.open(fn)
if not self.file then error(err) end
-- is this a WAV file?
self.bytesToEOC = 12
local ckID, cksize, WAVEID = self:read(nil, '<c4 I c4')
if ckID ~= 'RIFF' or WAVEID ~= "WAVE" then
error(string.format('%s: not a WAV file (got ckID=%s, WAVEID=%s)', fn, ckID, WAVEID))
end
return self
end
function WavReader.nextChunk(self)
if self.bytesToEOC > 0 then
self:skip(self.bytesToEOC)
end
self.bytesToEOC = 8
self.chunkID, self.bytesToEOC = self:read(nil, '<c4 I')
return self.chunkID, self.bytesToEOC
end
function WavReader.skip(self, size)
assert(size > 0, 'negative or null skip size')
assert(size <= self.bytesToEOC, 'skip would exceed chunk boundary')
self.bytesToEOC = self.bytesToEOC - size
return self.file:seek('cur', size)
end
function WavReader.read(self, size, fmt)
if not size then
size = self.bytesToEOC
end
assert(size > 0, 'negative or null read size')
assert(size <= self.bytesToEOC, 'read would exceed chunk boundary')
self.bytesToEOC = self.bytesToEOC - size
local data = self.file:read(size)
if data:len() < size then
return false -- EOF
elseif fmt then
return string.unpack(fmt, data)
else
return data
end
end
function WavReader.close(self)
self.file:close()
end
-- usage example
function getChanCountAndBitDepth(fn)
local wav = WavReader.new(fn)
while wav:nextChunk() do
if wav.chunkID == "fmt " then
local fmtData = {wav:read(16, '<H H I I H H')}
wav:close()
return fmtData[2], fmtData[6]
end
end
wav:close()
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment