aboutsummaryrefslogtreecommitdiff
path: root/samples/wave.lua
blob: 9fd5adbf0da0cb76da1bed17a46a94b09135a6ce (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
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))