prog8/examples/cx16/pcmaudio/wavfile.p8

61 lines
2.2 KiB
Lua

;
; module to parse the header data of a .wav file
;
; note: the sample rate in hz can be converted to a vera rate via:
; const float vera_freq_factor = 25e6 / 65536.0
; vera_rate = (wavfile.sample_rate as float / vera_freq_factor) + 1.0 as ubyte
; vera_rate_hz = (vera_rate as float) * vera_freq_factor as uword
;
wavfile {
const ubyte WAVE_FORMAT_PCM = $1
const ubyte WAVE_FORMAT_ADPCM = $2
const ubyte WAVE_FORMAT_IEEE_FLOAT = $3
const ubyte WAVE_FORMAT_ALAW = $6
const ubyte WAVE_FORMAT_MULAW = $7
const ubyte WAVE_FORMAT_DVI_ADPCM = $11
uword sample_rate
ubyte bits_per_sample
uword data_offset
ubyte wavefmt
ubyte nchannels
uword block_align
uword data_size_hi
uword data_size_lo
sub parse_header(uword wav_data) -> bool {
; "RIFF" , filesize (int32) , "WAVE", "fmt ", fmtsize (int32)
uword @zp header = wav_data
if header[0]!=iso:'R' or header[1]!=iso:'I' or header[2]!=iso:'F' or header[3]!=iso:'F'
or header[8]!=iso:'W' or header[9]!=iso:'A' or header[10]!=iso:'V' or header[11]!=iso:'E'
or header[12]!=iso:'f' or header[13]!=iso:'m' or header[14]!=iso:'t' or header[15]!=iso:' ' {
return false
}
; uword filesize = peekw(header+4)
uword chunksize = peekw(header+16)
wavefmt = peek(header+20)
nchannels = peek(header+22)
sample_rate = peekw(header+24) ; we assume sample rate <= 65535 so we can ignore the upper word
block_align = peekw(header+32)
bits_per_sample = peek(header+34)
if wavefmt==WAVE_FORMAT_DVI_ADPCM or wavefmt==WAVE_FORMAT_ADPCM
bits_per_sample *= 4
; skip chunks until we reach the 'data' chunk
header += chunksize + 20
repeat {
chunksize = peekw(header+4) ; assume chunk size never exceeds 64kb so ignore upper word
if header[0]==iso:'d' and header[1]==iso:'a' and header[2]==iso:'t' and header[3]==iso:'a'
break
header += 8 + chunksize
}
data_size_lo = chunksize
data_size_hi = peekw(header+6)
data_offset = header + 8 - wav_data
return true
}
}