aboutsummaryrefslogtreecommitdiff
path: root/samples/wave.lua
diff options
context:
space:
mode:
Diffstat (limited to 'samples/wave.lua')
-rwxr-xr-xsamples/wave.lua81
1 files changed, 81 insertions, 0 deletions
diff --git a/samples/wave.lua b/samples/wave.lua
new file mode 100755
index 0000000..9fd5adb
--- /dev/null
+++ b/samples/wave.lua
@@ -0,0 +1,81 @@
+#!/usr/bin/lua
+
+require "lspipat"
+
+function uint(bytes, val) -- binary integer decoding
+ return Len(bytes) % function(bin)
+ bin = littleEndian and bin or bin:reverse()
+
+ local n = 0
+ local base = 1
+
+ for _, c in ipairs{bin:byte(1, bytes)} do
+ n = n + base * c
+ base = base * 256
+ end
+
+ val(n)
+ end
+end
+
+function _uint(bytes, name) return uint(bytes, function(n) _G[name] = n end) end
+function _uint16(name) return _uint(2, name) end
+function _uint32(name) return _uint(4, name) end
+
+hnd = assert(io.open(arg[1]))
+
+file = hnd:read("*a")
+
+hnd:close()
+
+-- WAVE file "grammar"
+
+format = "fmt "
+ * _uint32 "FmtChunkSize"
+ * _Setcur "FmtStartPos"
+ * _uint16 "AudioFormat"
+ * _uint16 "NumChannels"
+ * _uint32 "SampleRate"
+ * _uint32 "ByteRate"
+ * _uint16 "BlockAlign"
+ * _uint16 "BitsPerSample"
+ * ( -function() return AudioFormat == 1 end
+ + _uint16 "ExtraParamSize"
+ * _Len "ExtraParamSize" )
+ * Pos(function() return FmtStartPos + FmtChunkSize end)
+ * -function() return BitsPerSample % 8 == 0 and
+ BlockAlign == NumChannels * BitsPerSample/8 and
+ ByteRate == SampleRate * BlockAlign end
+
+data = "data"
+ * _uint32 "DataChunkSize"
+ * _Len "DataChunkSize"
+
+misc = Len(4)
+ * _uint32 "MiscChunkSize"
+ * _Len "MiscChunkSize"
+
+wave = (topattern("RIFF") + "RIFX")
+ % function(id) littleEndian = id == "RIFF" end
+ * _uint32 "ChunkSize"
+ * _Setcur "StartPos"
+ * "WAVE"
+ * Arbno(format + data + misc)
+ * Pos(function() return StartPos + ChunkSize end)
+ * -function() return DataChunkSize % BlockAlign == 0 end
+ * RPos(0)
+
+assert(file:smatch(wave, spipat.match_anchored),
+ arg[1].." is not a valid WAVE file!")
+
+print(string.format(
+"%s\
+Format: %u\
+Channels: %u\
+Samplerate: %u Hz\
+Byterate: %u Hz\
+Bits/Sample: %u\
+Samples: %u",
+arg[1],
+AudioFormat, NumChannels, SampleRate, ByteRate, BitsPerSample, DataChunkSize / BlockAlign))
+print(os.date("Length:\t\t%T", DataChunkSize / ByteRate + 60*60*23))