Created
September 14, 2015 14:23
-
-
Save Oldes/2ead960c4134a9799b0a to your computer and use it in GitHub Desktop.
Experimental WAV file parser
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Red/System [ | |
Title: "Red/System stream-io test - WAV reader" | |
Author: "Oldes" | |
] | |
#define handle! [pointer! [integer!]] | |
#define GENERIC_WRITE 40000000h | |
#define GENERIC_READ 80000000h | |
#define FILE_SHARE_READ 00000001h | |
#define FILE_SHARE_WRITE 00000002h | |
#define OPEN_ALWAYS 00000004h | |
#define OPEN_EXISTING 00000003h | |
#define CREATE_ALWAYS 00000002h | |
#define FILE_ATTRIBUTE_NORMAL 00000080h | |
#define FILE_ATTRIBUTE_DIRECTORY 00000010h | |
#import [ | |
"kernel32.dll" stdcall [ | |
CreateFileA: "CreateFileA" [ ;-- temporary needed by Red/System | |
filename [c-string!] | |
access [integer!] | |
share [integer!] | |
security [int-ptr!] | |
disposition [integer!] | |
flags [integer!] | |
template [int-ptr!] | |
return: [handle!] | |
] | |
ReadFile: "ReadFile" [ | |
file [handle!] | |
buffer [byte-ptr!] | |
bytes [integer!] | |
read [int-ptr!] | |
overlapped [int-ptr!] | |
return: [integer!] | |
] | |
CloseHandle: "CloseHandle" [ | |
obj [handle!] | |
return: [integer!] | |
] | |
GetFileSize: "GetFileSize" [ | |
file [handle!] | |
FileSizeHigh [int-ptr!] ;A pointer to the variable where the high-order doubleword of the file size is returned. This parameter can be NULL if the application does not require the high-order doubleword. | |
return: [integer!] | |
] | |
] | |
] | |
#define ID_RIFF 46464952h | |
#define ID_WAVE 45564157h | |
#define ID_WAVE_FMT 20746D66h | |
#define ID_WAVE_DATA 61746164h | |
#define ID_WAVE_CUE 20657563h | |
#define ID_WAVE_LIST 5453494Ch | |
io: context [ | |
port: as handle! 0 | |
buffer: as byte-ptr! 0 | |
buffer-head: as byte-ptr! 0 | |
buffer-tail: as byte-ptr! 0 | |
buffer-size: 0 | |
open: func[ | |
filename [c-string!] | |
/local | |
read-sz [integer!] | |
res [integer!] | |
][ | |
port: CreateFileA filename GENERIC_READ FILE_SHARE_READ NULL OPEN_EXISTING FILE_ATTRIBUTE_NORMAL null | |
buffer-size: GetFileSize port null | |
buffer: allocate buffer-size | |
buffer-tail: buffer + buffer-size | |
read-sz: -1 | |
res: ReadFile port buffer buffer-size :read-sz null | |
buffer-head: buffer | |
] | |
close: does [ | |
CloseHandle port | |
free buffer | |
buffer: as byte-ptr! 0 | |
buffer-head: as byte-ptr! 0 | |
buffer-tail: as byte-ptr! 0 | |
buffer-size: 0 | |
] | |
readUI16: func[ | |
return: [integer!] | |
][ | |
buffer: buffer + 2 | |
(as integer! buffer/-1) + ((as integer! buffer/0) << 8) | |
] | |
readUI32: func[ | |
return: [integer!] | |
/local ptr [pointer! [integer!]] | |
][ | |
ptr: as pointer! [integer!] buffer | |
buffer: buffer + 4 | |
ptr/1 | |
] | |
tail?: func[return: [logic!]][buffer >= buffer-tail] | |
seek-to-RIFF: func[ | |
return: [logic!] | |
][ | |
while [buffer < buffer-tail][ | |
if ID_RIFF = readUI32 [ | |
print-line "RIFF" | |
return true | |
] | |
] | |
false | |
] | |
parse-WAV: func[ | |
return: [logic!] | |
/local | |
id [integer!] | |
size [integer!] | |
compression [integer!] | |
channels [integer!] | |
sampleRate [integer!] | |
bytesPerSec [integer!] | |
blockAlign [integer!] | |
bitsPerSample [integer!] | |
][ | |
if not seek-to-RIFF [ | |
print-line "RIFF not found" | |
return false | |
] | |
size: readUI32 | |
id: readUI32 | |
if ID_WAVE <> id [ | |
print-line "WAV not found" | |
return false | |
] | |
while [buffer < (buffer-tail - 8)][ | |
id: readUI32 | |
size: readUI32 | |
assert buffer-tail >= (buffer + size) ;-- security check | |
switch id [ | |
ID_WAVE_FMT [ | |
print-line "fmt" | |
compression: readUI16 | |
channels: readUI16 | |
sampleRate: readUI32 | |
bytesPerSec: readUI32 | |
blockAlign: readUI16 | |
bitsPerSample: readUI16 | |
buffer: buffer + size - 16 ;skip extra bytes | |
print-line ["channels: " channels " sampleRate: " sampleRate " bytesPerSec: " bytesPerSec " blockAlign: " blockAlign " bitsPerSample: " bitsPerSample] | |
] | |
ID_WAVE_DATA [ | |
print-line "DATA" | |
print-line ["samples:" size / (bitsPerSample / 8)] | |
buffer: buffer + size | |
] | |
ID_WAVE_LIST [ | |
print-line "LIST" | |
buffer: buffer + size | |
] | |
ID_WAVE_CUE [ | |
print-line "cue" | |
buffer: buffer + size | |
] | |
default [ | |
buffer: buffer + size | |
] | |
] | |
] | |
true | |
] | |
] | |
io/open "test.wav" | |
io/parse-WAV | |
io/close |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment