2023-04-25 23:17:13 -04:00
|
|
|
( wave.tal )
|
|
|
|
( )
|
|
|
|
( currently reads PCM data )
|
|
|
|
|
2023-04-29 21:24:45 -04:00
|
|
|
( WAV format (number byte order is little-endian) )
|
2023-04-25 23:17:13 -04:00
|
|
|
( )
|
|
|
|
( 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 )
|
2023-04-29 21:24:45 -04:00
|
|
|
( )
|
|
|
|
( 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 )
|
2023-04-25 23:17:13 -04:00
|
|
|
|
2023-04-29 21:24:45 -04:00
|
|
|
( |00 @System [ &vec $2 &wst $1 &rst $1 &pad $4 &r $2 &g $2 &b $2 &dbg $1 &halt $1 ] )
|
|
|
|
|10 @Console [ &vec $2 &read $1 &pad $5 &out $1 &err $1 ]
|
2023-11-27 22:26:43 -05:00
|
|
|
|30 @Audio0 [ &vec $2 &pos $2 &out $1 &dur $2 &pad $1 &adsr $2 &len $2 &addr $2 &vol $1 &pitch $1 ]
|
2023-04-29 21:24:45 -04:00
|
|
|
|a0 @File [ &vec $2 &ok $2 &stat $2 &del $1 &append $1 &name $2 &len $2 &r $2 &w $2 ]
|
2023-04-25 23:17:13 -04:00
|
|
|
|
|
|
|
|0000
|
|
|
|
@done $1
|
2023-04-29 21:24:45 -04:00
|
|
|
@pos $2
|
|
|
|
@is-stereo $1
|
|
|
|
@is-8bit $1
|
2023-11-27 22:26:43 -05:00
|
|
|
@bytes-per-ms $2
|
2023-04-25 23:17:13 -04:00
|
|
|
|
|
|
|
|0100
|
2023-04-29 21:24:45 -04:00
|
|
|
;filename .pos STZ2
|
|
|
|
;read-filename .Console/vec DEO2
|
|
|
|
BRK
|
|
|
|
|
|
|
|
@read-filename ( -> )
|
|
|
|
#12 DEI ( c^ )
|
|
|
|
DUP #0a EQU ?&exec ( c^ )
|
|
|
|
DUP #00 EQU ?&exec ( c^ )
|
|
|
|
.pos LDZ2 STA ( ; $pos<-c )
|
|
|
|
.pos LDZ2 INC2 .pos STZ2 ( ; pos<-pos+1 )
|
|
|
|
BRK ( )
|
|
|
|
&exec ( c^ -> )
|
|
|
|
POP #00 .pos LDZ2 STA ( ; $pos<-0 )
|
|
|
|
!start ( )
|
|
|
|
|
|
|
|
@start ( -> )
|
|
|
|
;filename .File/name DEO2
|
2023-04-25 23:17:13 -04:00
|
|
|
parse
|
2023-04-29 21:24:45 -04:00
|
|
|
.is-stereo LDZ ?&stereo
|
2023-07-22 13:39:22 -04:00
|
|
|
.is-8bit LDZ ?&mono-8bit LITr 01 ;mono-s16-to-u8 !&done
|
|
|
|
&mono-8bit LITr 00 ;mono-u8-to-u8 !&done
|
2023-04-29 21:24:45 -04:00
|
|
|
&stereo
|
2023-07-22 13:39:22 -04:00
|
|
|
.is-8bit LDZ ?&stereo-8bit LITr 02 ;stereo-s16-to-u8 !&done
|
|
|
|
&stereo-8bit LITr 01 ;stereo-u8-to-u8 !&done
|
2023-04-29 21:24:45 -04:00
|
|
|
&done
|
2023-07-22 13:39:22 -04:00
|
|
|
LIT2 =reload/resample STA2 ( ; save resample function )
|
|
|
|
LIT2r =reload/sft STAr ( ; save shift size )
|
2023-11-27 22:26:43 -05:00
|
|
|
#2274 .File/len DEO2
|
|
|
|
#2274 ;len0 STA2 #2274 ;buf0 zero-buf-u8
|
|
|
|
#2274 ;len1 STA2 #2274 ;buf1 zero-buf-u8
|
2023-04-25 23:17:13 -04:00
|
|
|
!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 ( )
|
|
|
|
|
2023-04-29 21:24:45 -04:00
|
|
|
( TODO: validate PCM, freq (44.1 kHz), etc. )
|
|
|
|
( TODO: debug/error messages )
|
2023-04-25 23:17:13 -04:00
|
|
|
@parse ( -> )
|
|
|
|
#002c .File/len DEO2
|
2023-04-29 21:24:45 -04:00
|
|
|
;header .File/r DEO2
|
2023-04-25 23:17:13 -04:00
|
|
|
.File/ok DEI2
|
2023-04-29 21:24:45 -04:00
|
|
|
#002c EQU2k ?&ok #0000 DIV
|
|
|
|
&ok POP2 POP2
|
2023-07-22 13:39:22 -04:00
|
|
|
#0016 #0200 hdr-eq2 .is-stereo STZ ( ; hdr+22 )
|
|
|
|
#0022 #0800 hdr-eq2 .is-8bit STZ ( ; hdr+34 )
|
2023-04-29 21:24:45 -04:00
|
|
|
JMP2r
|
|
|
|
|
2023-07-22 13:39:22 -04:00
|
|
|
@hdr-eq2 ( offset* v* -> eq^ )
|
|
|
|
STH2 ;header ADD2 LDA2 STH2r EQU2 JMP2r
|
|
|
|
|
2023-04-29 21:24:45 -04:00
|
|
|
@reload ( l-addr* b-addr* -> )
|
2023-04-25 23:17:13 -04:00
|
|
|
.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* )
|
2023-04-29 21:24:45 -04:00
|
|
|
DUP2 LIT &sft $1 SFT2 ( b-addr* l-addr* read* read>>sft )
|
|
|
|
ROT2 STA2 ( b-addr* read* ; l-addr<-read>>sft )
|
2023-11-27 22:26:43 -05:00
|
|
|
DUP2 #2274 EQU2 ?&end ( b-addr* read* ; if we read 0x2274 we are not done )
|
2023-04-25 23:17:13 -04:00
|
|
|
#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*] )
|
2023-04-29 21:24:45 -04:00
|
|
|
INC2 ( limit* scratch+1* [b-addr*] )
|
2023-04-25 23:17:13 -04:00
|
|
|
&loop ( limit* pos* [bpos*] )
|
2023-04-29 21:24:45 -04:00
|
|
|
LIT2 &resample $2 JSR2 ( limit* pos+n* sample^ [bpos*] )
|
|
|
|
STH2kr STA ( limit* pos+n* [bpos*] ; bpos<-sample )
|
|
|
|
INC2r GTH2k ?&loop ( limit* pos+n* [bpos+1*] )
|
|
|
|
POP2r ( limit* pos+n* )
|
|
|
|
POP2 POP2 JMP2r
|
|
|
|
&skip ( )
|
2023-11-27 22:26:43 -05:00
|
|
|
#2274 SWP2 zero-buf-u8 ( )
|
|
|
|
#2274 SWP2 STA2 JMP2r ( )
|
2023-04-29 21:24:45 -04:00
|
|
|
|
|
|
|
@mono-u8-to-u8 ( pos* -> pos+1* sample^ )
|
|
|
|
LDAk STH INC2 STHr JMP2r
|
|
|
|
|
|
|
|
@mono-s16-to-u8 ( pos* -> pos+2* sample^ )
|
2023-11-27 22:26:43 -05:00
|
|
|
LDAk #80 ADD STH INC2 INC2 STHr JMP2r
|
2023-04-29 21:24:45 -04:00
|
|
|
|
|
|
|
@stereo-u8-to-u8 ( pos* -> pos+2* sample^ )
|
2023-11-27 22:26:43 -05:00
|
|
|
LDAk LITr 00 STH INC2
|
|
|
|
LDAk LITr 00 STH INC2
|
2023-04-29 21:24:45 -04:00
|
|
|
ADD2r LITr 01 SFT2r NIPr STHr JMP2r
|
|
|
|
|
|
|
|
@stereo-s16-to-u8 ( pos* -> pos+4* sample^ )
|
|
|
|
LDAk #80 EOR #00 SWP STH2 INC2 INC2
|
|
|
|
LDAk #80 EOR #00 SWP STH2 INC2 INC2
|
|
|
|
ADD2r LITr 01 SFT2r NIPr STHr JMP2r
|
2023-04-25 23:17:13 -04:00
|
|
|
|
|
|
|
@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 )
|
2023-04-29 21:24:45 -04:00
|
|
|
reload ( next* ; load more data )
|
2023-04-25 23:17:13 -04:00
|
|
|
.Audio0/vec DEO2 ( ; Audio0/vec<-next )
|
|
|
|
BRK ( )
|
|
|
|
|
2023-11-27 22:26:43 -05:00
|
|
|
@bytes-to-millis ( samples* -> ms* )
|
|
|
|
#01b9 DIV2 #000a MUL2 JMP2r
|
|
|
|
|
2023-04-25 23:17:13 -04:00
|
|
|
@output ( len* addr* -> )
|
2023-11-27 22:26:43 -05:00
|
|
|
.Audio0/addr DEO2 ( ; <- write buf addr )
|
|
|
|
DUP2 .Audio0/len DEO2 ( ; <- write length in bytes/samples )
|
|
|
|
bytes-to-millis .Audio0/dur DEO2 ( ; <- write duration in milliseconds )
|
|
|
|
#00f0 .Audio0/adsr DEO2 ( ; <- write ignore envelope )
|
|
|
|
#ff .Audio0/vol DEO ( ; <- play 100% volume )
|
|
|
|
#bc .Audio0/pitch DEO ( ; <- play standard sample once )
|
2023-04-25 23:17:13 -04:00
|
|
|
JMP2r
|
|
|
|
|
2023-11-27 22:26:43 -05:00
|
|
|
( buffer size is 0x2274, i.e. 8820. )
|
|
|
|
( this is an important number: 8820 = 4 * 5 * 441. )
|
|
|
|
( since it is divisible by 4 we know that the buffer will read )
|
|
|
|
( an exact number of samples, even with 16-bit stereo. and since )
|
|
|
|
( it is divisble by 441 we know it will always contain a multiple )
|
|
|
|
( 10 milliseconds of audio. these assumptions help ensure we don't )
|
|
|
|
( end up with static, popping, or other problems. )
|
2023-04-29 21:24:45 -04:00
|
|
|
@filename $100
|
|
|
|
@header $2c
|
2023-11-27 22:26:43 -05:00
|
|
|
@len0 $2 @buf0 $2274
|
|
|
|
@len1 $2 @buf1 $2274
|
|
|
|
@scratch $2274
|