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
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
|
{WAV processing}
unit fmt_WAV;
{$include compilers.inc}
interface
uses wat_api;
function ReadWAV(var Info:tSongInfo):boolean; cdecl;
implementation
uses windows,common,io,tags,srv_format;
const
wavRIFF = $46464952;
wavWAVE = $45564157;
wavfmt_ = $20746D66;
wavfact = $74636166;
wavdata = $61746164;
type
tWAVChunk = packed record
id :dword;
size:dword;
end;
type
tWAVFormatChunk = packed record
Codec :word;
Channels :word;
SampleRate :dword;
AvgBPS :dword;
BlockAlign :word;
BitsPerSample:word;
end;
const
WavPackID = $6B707677;
type
// ckID :dword; // "wvpk"
// ckSize :dword; // size of entire frame (minus 8, of course)
tWavPackHeader = packed record
version :word; // 0x403 for now
track_no :byte; // track number (0 if not used, like now)
index_no :byte; // track sub-index (0 if not used, like now)
total_samples:dword; // for entire file (-1 if unknown)
block_index :dword; // index of first sample in block (to file begin)
block_samples:dword; // # samples in This block
flags :dword; // various flags for id and decoding
crc :dword; // crc for actual decoded data
end;
function ReadWAV(var Info:tSongInfo):boolean; cdecl;
var
f:THANDLE;
chunk:tWAVChunk;
fmtchunk:tWAVFormatChunk;
tmp:dword;
WPH:tWavPackHeader;
fsize:dword;
begin
result:=false;
f:=Reset(Info.mfile);
if f=THANDLE(INVALID_HANDLE_VALUE) then
exit;
BlockRead(f,chunk,SizeOf(chunk));
if chunk.id=WavPackID then
begin
BlockRead(f,WPH,SizeOf(tWavPackHeader));
BlockRead(f,tmp,2); //!! $1621 33,22
BlockRead(f,chunk,SizeOf(chunk));
end
else
begin
WPH.version:=0;
integer(WPH.total_samples):=-1;
end;
if chunk.id<>wavRIFF then
exit;
BlockRead(f,chunk,SizeOf(dword));
if chunk.id<>wavWAVE then
exit;
BlockRead(f,chunk,SizeOf(chunk));
if chunk.id<>wavfmt_ then
exit;
BlockRead(f,fmtchunk,SizeOf(tWAVFormatChunk));
Info.channels:=fmtchunk.Channels;
Info.khz :=fmtchunk.SampleRate div 1000;
if chunk.size>SizeOf(tWAVFormatChunk) then
Skip(f,chunk.size-SizeOf(tWAVFormatChunk));
fsize:=FileSize(f);
while FilePos(f)<fsize do
begin
BlockRead(f,chunk,SizeOf(chunk));
if chunk.id=wavfact then
begin
BlockRead(f,tmp,4);
break;
end;
if chunk.id=wavdata then
begin
tmp:=chunk.size;
break;
end;
Skip(f,chunk.size);
end;
if WPH.version<>0 then
begin
ReadAPEv2(f,Info);
ReadID3v1(f,Info);
end;
if integer(WPH.total_samples)=-1 then
if (fmtchunk.BitsPerSample<>0) and (fmtchunk.Channels<>0) then
WPH.total_samples:=(tmp*8) div (fmtchunk.Channels*fmtchunk.BitsPerSample);
if fmtchunk.SampleRate<>0 then
Info.total:= WPH.total_samples div fmtchunk.SampleRate;
if Info.total<>0 then
Info.kbps:=tmp*8 div Info.total div 1000;
CloseHandle(f);
result:=true;
end;
var
LocalFormatLinkWAV,
LocalFormatLinkWV:twFormat;
procedure InitLink;
begin
LocalFormatLinkWAV.Next:=FormatLink;
LocalFormatLinkWAV.This.proc :=@ReadWAV;
LocalFormatLinkWAV.This.ext :='WAV';
LocalFormatLinkWAV.This.flags:=0;
FormatLink:=@LocalFormatLinkWAV;
LocalFormatLinkWV.Next:=FormatLink;
LocalFormatLinkWV.This.proc :=@ReadWAV;
LocalFormatLinkWV.This.ext :='WV';
LocalFormatLinkWV.This.flags:=0;
FormatLink:=@LocalFormatLinkWV;
end;
initialization
InitLink;
end.
|