basic WAV support

This commit is contained in:
~d6 2023-04-25 23:17:13 -04:00
parent 6ee7adad4d
commit dab32fea09
1 changed files with 137 additions and 0 deletions

137
wave.tal Normal file
View File

@ -0,0 +1,137 @@
( wave.tal )
( )
( currently reads PCM data )
( WAV format (number byte order is LE) )
( )
( BYTES EXAMPLE BYTES DESCRIPTION )
( 0-3 "RIFF" 52 49 46 46 riff string )
( 4-7 10248036 64 5f 9c 00 overall file size - 8 bytes )
( 8-11 "WAVE" 57 41 56 45 wave string )
( 12-15 "fmt " 66 6d 74 20 fmt string )
( 16-19 1 01 00 00 00 length of format data? [???] )
( 20-21 1 01 00 type of data, 1 is PCM )
( 22-23 1 01 00 number of channels, 1 is mono )
( 24-27 44100 44 ac 00 00 sample-rate, 44100 is 44.1 kHz )
( 28-31 44100 44 ac 00 00 [rate * channels * bits/channel]/8 )
( 32-33 1 01 00 [bitrate*channels]/8 )
( 34-35 8 08 00 bitrate, i.e. bits per sample )
( 36-39 "data" 64 61 74 61 data string )
( 40-43 10248000 40 5f 9c 00 data size in bytes )
( 44+ PCM data, little endian byte order )
( )
( more complex WAV files may have other structures. )
( )
( we can validate whether the WAV is a format we can handle )
( by comparing byes 4-7 with bytes 40-43. if the former is )
( 36 bytes larger than the latter, the file has a standard )
( structure which we can easily parse. )
( )
( s16 -> u8: hi-byte + 0x80 )
( stereo -> mono, take second sample )
|30 @Audio0 [ &vec $2 &pos $2 &out $1 &pad $3 &adsr $2 &len $2 &addr $2 &vol $1 &pitch $1 ]
|40 @Audio1 [ &vec $2 &pos $2 &out $1 &pad $3 &adsr $2 &len $2 &addr $2 &vol $1 &pitch $1 ]
|50 @Audio2 [ &vec $2 &pos $2 &out $1 &pad $3 &adsr $2 &len $2 &addr $2 &vol $1 &pitch $1 ]
|60 @Audio3 [ &vec $2 &pos $2 &out $1 &pad $3 &adsr $2 &len $2 &addr $2 &vol $1 &pitch $1 ]
|a0 @File [ &vec $2 &ok $2 &stat $2 &del $1 &append $1 &name $2 &len $2 &r $2 &w $2 ]
|0000
@done $1
|0100
;path .File/name DEO2
parse
#2000 .File/len DEO2
#2000 ;len0 STA2 #2000 ;buf0 zero-buf-u8
#2000 ;len1 STA2 #2000 ;buf1 zero-buf-u8
!play0
@zero-buf-u8 ( len* buf* -> )
STH2k ADD2 STH2 SWP2r ( [limit=buf+len* buf*] )
#80 ( 80^ [limit* buf*] )
&loop ( 80^ [limit* pos*] )
DUP STH2kr STA ( 80^ [limit* pos*] ; pos<-80 )
INC2r GTH2kr STHr ?&loop ( 80^ [limit* pos+1*] )
POP POP2r POP2r JMP2r ( )
( data created using: )
( lame --decode tokyo-skies.mp3 # produced tokyo-skies.wav )
( sox tokyo-skies.wav -c 1 -e unsigned-integer -b 8 tokyo-skies-mono-u8.wav )
( sox tokyo-skies-mono-u8.wav tokyo-skies.raw )
( @path "tokyo-skies.raw 00 )
@path "tokyo-skies-mono-u8.wav 00
( @path "tokyo-skies.wav 00 )
( TODO: actually parse )
@parse ( -> )
#002c .File/len DEO2
;buf0 .File/r DEO2
.File/ok DEI2
#002c EQU2 ?&ok #0000 DIV &ok JMP2r
@reload-mono-u8 ( l-addr* b-addr* -> )
.done LDZ ?&skip ( l-addr* b-addr* )
.File/r DEO2 ( l-addr* )
.File/ok DEI2 ( l-addr* read* )
DUP2 ROT2 STA2 ( read* ; l-addr<-read )
#2000 EQU2 ?&end ( ; if we read 0x2000 we are not done )
#01 .done STZ ( ; done<-1 )
&end JMP2r ( )
&skip POP2 POP2 JMP2r ( )
@reload-stereo-s16 ( l-addr* b-addr* -> )
.done LDZ ?&skip ( l-addr* b-addr* )
SWP2 ( b-addr* l-addr* )
;scratch .File/r DEO2 ( b-addr* l-addr* )
.File/ok DEI2 ( b-addr* l-addr* read* )
DUP2 #02 SFT2 ROT2 STA2 ( b-addr* read* ; l-addr<-read/4 )
DUP2 #2000 EQU2 ?&end ( b-addr* read* ; if we read 0x2000 we are not done )
#01 .done STZ ( b-addr* read* ; done<-1 )
&end ( b-addr* read* )
SWP2 STH2 ;scratch ( read* scratch* [b-addr*] )
DUP2 ROT2 ADD2 SWP2 ( limit=scratch+read* scratch* [b-addr*] )
INC2 ( limit* scratch+3* [b-addr*] )
&loop ( limit* pos* [bpos*] )
s16-to-u8 ( limit* pos+4* sample^ [bpos*] )
STH2kr STA ( limit* pos* [bpos*] ; bpos<-sample )
INC2r ( limit* pos+4* [bpos+1*] )
GTH2k ?&loop ( limit* pos+4* [bpos+1*] )
POP2r ( limit* pos+4* )
&skip POP2 POP2 JMP2r ( )
@s16-to-u8 ( pos* -> pos+4* sample^ )
LDAk #80 ADD #00 SWP STH2
INC2 INC2
LDAk #80 ADD #00 SWP STH2
ADD2r LITr 01 SFT2r NIPr
INC2 INC2
STHr JMP2r
@play0 ( -> ) ;play1 ;len0 ;buf0 !play
@play1 ( -> ) ;play0 ;len1 ;buf1 !play
@play ( next* l-addr* b-addr* -> )
OVR2 LDA2 ORAk ?&nonzero ( next* l-addr* b-addr* n* )
POP2 POP2 POP2 POP2 ( ; clear stack )
#010f BRK ( ; exit )
&nonzero ( next* l-addr b-addr* n* )
OVR2 output ( next* l-addr b-addr* ; play buf1 )
reload-mono-u8 ( next* ; load more data )
( reload-stereo-s16 ) ( next* ; load more data )
.Audio0/vec DEO2 ( ; Audio0/vec<-next )
BRK ( )
@output ( len* addr* -> )
.Audio0/addr DEO2 ( ; <- write buf addr )
.Audio0/len DEO2 ( ; <- write len )
#0000 .Audio0/adsr DEO2 ( ; <- write ignore envelope )
#ff .Audio0/vol DEO ( ; <- play 100% volume )
#bc .Audio0/pitch DEO ( ; <- play standard sample once )
JMP2r
@len0 $2 @buf0 $2000
@len1 $2 @buf1 $2000
@scratch $2000