[Back to SOUND SWAG index] [Back to Main SWAG index] [Original]
program player;
uses dos;
VAR
Param:string[63];
BytesRead,BlockSize,BlockRest:Word;
dataptr,pp:pointer;
f:file;
I:Integer;
SampRateDiv,times:byte;
reverse,wavinfo:boolean;
fmt: record
wFormatTag:word;
nChannels:word;
nSamplesPerSec:longint;
nAvgBytesPerSec:longint;
nBlockAlign:word;
wBitsPerSample:word;
end;
PROCEDURE PlaySound(bufptr:pointer;bufctr:longint;ratediv,times:word)
;{assember;}
var
old_int8 : pointer;
timesleft :word;
savemask:byte;
begin;
ASM
jmp @PlayMain
@int8_out_spk:
xor al,al
out 42h,al
mov al,cl
out 42h,al
mov ax,dx
or ax,si
jz @ready
dec bl
jnz @skip
mov bl,bh
mov al,es:[di]
shr al,1
shr al,1
inc al
mov cl,al
inc di
jnz @noseg
mov ax,es
add ax,1000h
mov es,ax
@noseg:
sub si,+01
sbb dx,+00
@skip:
mov al,20h
out 20h,al
iret
@ready:
mov ch,0ffh
jmp @skip
@PlayMain:
cli
mov ax,3508h
int 21h { get int vector 08 in es:bx }
mov word ptr old_int8,bx
mov word ptr old_int8+2,es
in al,21h { interruptmask }
mov savemask,al
mov al,0ffh { disable all interrupts }
out 21h,al
sti
push ds
mov ax,cs
mov ds,ax
mov dx,offset @int8_out_spk
mov ax,2508h
int 21h { set int vector 08 to ds:dx }
pop ds
mov al,34h
out 43h,al { timer 0 mode }
mov al,36h { 22khz }
out 40h,al
xor al,al
out 40h,al
mov al,90h
out 43h,al { timer 2 mode }
in al,61h { enable speaker }
or al,3
out 61h,al
mov cx,times
mov timesleft,cx
mov cl,20h
mov bx,ratediv
mov bh,bl
les si,bufctr
mov dx,es
les di,bufptr
@nexttime:
push di { bufptrlo }
push es { bufptrhi }
push si { bufctrlo }
push dx { bufctrhi }
push bx { ratediv }
xor ch,ch { readyflag = false }
mov al,0feh { enable timerinterrupt }
out 21h,al
@notready:
or ch,ch
jz @notready
cli
mov al,0ffh { disable all interrupts }
out 21h,al
sti
pop bx { ratediv }
pop dx { bufctrhi }
pop si { bufctrlo }
pop es { bufptrhi }
pop di { bufptrlo }
dec word ptr timesleft { more times ? }
jnz @nexttime
in al,61h { disable speaker }
and al,0fch
out 61h,al
mov al,34h
out 43h,al { timer 0 mode }
mov al,0
out 40h,al { timer 0 clock }
out 40h,al { timer 0 clock }
mov al,0b6h
out 43h,al { timer mode }
mov ax,533h
out 42h,al { timer 2 spkr }
mov al,ah
out 42h,al { timer 2 spkr }
push ds
lds dx,dword ptr old_int8
mov ax,2508h
int 21h { set intrpt vector al to ds:dx }
pop ds
mov al,savemask { enable timer and keyboard }
out 21h,al
END;
end;
{ The following procedure is also used to half the samplerate }
PROCEDURE Stereo2Mono(bufptr:pointer;bufctr:longint); assembler;
ASM
les si,bufctr
mov dx,es
les di,bufptr
push ds
mov ax,es
mov ds,ax
mov bx,di
@s2mNext:
mov ax,dx
or ax,si
jz @s2mRdy
xor ah,ah
mov al,es:[di]
mov cx,ax
mov al,es:[di+1]
add ax,cx
shr ax,1
mov ds:[bx],al
inc di
jnz @noseg1
mov ax,es
add ax,1000h
mov es,ax
@noseg1:
inc di
jnz @noseg2
mov ax,es
add ax,1000h
mov es,ax
@noseg2:
inc bx
jnz @noseg3
mov ax,ds
add ax,1000h
mov ds,ax
@noseg3:
sub si,+01
sbb dx,+00
jmp @s2mNext
@s2mRdy:
pop ds
END;
PROCEDURE ReverseData(bufptr:pointer;bufctr:longint); assembler;
ASM
push ds
les bx,bufctr
mov dx,es
les di,bufptr
mov si,di
add si,bx { offset=offset+bufctrlo }
mov ax,dx
adc ax,0 { bufctrhi=bufctrhi+carry }
mov cl,12
shl ax,cl
mov cx,ax
mov ax,es
add ax,cx
mov ds,ax {ds = segment of end of buffer}
shr dx,1
rcr bx,1 { Bufctr = Bufctr / 2 }
@RevNext:
mov ax,bx
or ax,dx
jz @RevRdy
sub si,+01
jnc @Rnoseg1
mov ax,ds
sub ax,1000h
mov ds,ax
@Rnoseg1:
mov al,es:[di] { swap bytes }
xchg al,ds:[si]
mov es:[di],al
inc di
jnz @Rnoseg2
mov ax,es
add ax,1000h
mov es,ax
@Rnoseg2:
sub bx,+01
sbb dx,+00
jmp @RevNext
@RevRdy:
pop ds
END;
PROCEDURE ReadFormat(var f:file);
var
str:string[4];
chunksize:longint;
BEGIN
blockread(f,str[1],4);
str[0]:=#4;
if str='fmt ' then begin
blockread(f,chunksize,4);
if wavinfo then writeln(' ''fmt '' size=',chunksize);
if chunksize=16 then begin
blockread(f,fmt,sizeof(fmt));
if wavinfo then with fmt do begin
writeln(' wFormatTag=',wFormatTag);
writeln(' nChannels=',nChannels);
writeln(' nSamplesPerSec=',nSamplesPerSec);
writeln(' nAvgBytesPerSec=',nAvgBytesPerSec);
writeln(' nBlockAlign=',nBlockAlign);
writeln(' wBitsPerSample=',wBitsPerSample);
end;
if fmt.wFormatTag<>1 then begin
writeln('Unknown Format (',fmt.wFormatTag,')!');
halt;
end;
case word(fmt.nSamplesPerSec) of
33075..65535:sampratediv:=0;
16538..33074:sampratediv:=1;
9188..16537:sampratediv:=2;
6432..9187:sampratediv:=3;
4962..6431:sampratediv:=4;
4043..4961:sampratediv:=5;
3413..4042:sampratediv:=6;
else halt;
end;
end
else writeln('''fmt '' chunksize error (',chunksize,')!');
end
else writeln('''fmt'' chunk not found!');
END;
PROCEDURE PlayWAVE(var f:file;sampratediv,times:byte);
var
str:string[4];
DataSize,l1:longint;
p1,p2:pointer;
s,o:word;
BEGIN
blockread(f,str[1],4);
str[0]:=#4;
if str='data' then begin
blockread(f,DataSize,4);
if wavinfo then writeln(' ''data'' size=',Datasize);
If MaxAvail>DataSize THEN BEGIN
if DataSize<$FFF0 then Blocksize:=DataSize else Blocksize:=$8000;
GetMem(pp,BlockSize);
DataPtr:=pp;
blockread(f,pp^,BlockSize,bytesread);
if BlockSize<DataSize then begin
For I:=1 to pred(DataSize div BlockSize) do begin
GetMem(pp,BlockSize);
blockread(f,pp^,Blocksize,bytesread);
end;
BlockRest:=DataSize mod BlockSize;
if BlockRest<>0 then begin
GetMem(pp,BlockRest);
blockread(f,pp^,BlockRest,bytesread);
end;
end;
if fmt.nChannels=2 then begin
if wavinfo then Write('Converting to mono..');
Stereo2Mono(DataPtr,DataSize);
DataSize:=DataSize shr 1;
if wavinfo then writeln;
end;
if sampratediv=0 then begin
sampratediv:=1;
if wavinfo then Write('Dividing to half samplerate..');
Stereo2Mono(DataPtr,DataSize);
DataSize:=DataSize shr 1;
if wavinfo then writeln;
end;
if reverse then ReverseData(DataPtr,DataSize);
PlaySound(DataPtr,DataSize,SampRateDiv,Times);
end
else Writeln('Not enough memory!');
end
else writeln('''data'' chunk not found!');
END;
PROCEDURE ReadRIFF(var f:file);
var
str:string[4];
RIFFsize,Chunksize:longint;
BEGIN
blockread(f,str[1],4);
str[0]:=#4;
if str='RIFF' then begin
blockread(f,RIFFsize,4);
if wavinfo then writeln('''RIFF'' size=',RIFFsize);
REPEAT
blockread(f,str[1],4);
if str='WAVE' then begin
ReadFormat(f);
PlayWAVE(f,sampratediv,times);
end
else begin
blockread(f,Chunksize,4);
seek(f,filepos(f)+Chunksize);
end;
until filepos(f)>=RIFFsize+8;
end
else Writeln('No RIFF header found!');
END;
PROCEDURE ShowHelp;
BEGIN
Writeln('PLAYWAV Bengt Holgersson 1991');
Writeln('Use: PLAYWAV filename [/N:times] [/R] [/I]');
Writeln(' /N:4 Play WAV 4 times');
Writeln(' /R Play WAV backwards');
Writeln(' /I Show info about WAV');
END;
procedure Getoption(s:string);
var
ch:char;
W:word;
begin
if length(s)<2 then exit;
ch:=s[2];
case upcase(ch) of
'R':reverse:=true;
'N':begin
if s[3]<>':' then exit;
val(copy(s,4,255),times,w);
if (w>0) or (times<1) then begin
writeln('times should be in the range 1-65535');
end;
end;
'I':wavinfo:=true;
'?':showhelp;
end;
end;
BEGIN
IF paramcount <1 then begin
showhelp;
halt;
end;
wavinfo:=false;
reverse:=false;
Times:=1;
if paramcount >1 then begin
for i:=2 to paramcount do getoption(paramstr(i));
end;
filemode:=0;
Param:=paramstr(1);
if Param[1]='/' then begin
getoption(Param);
halt;
end;
if pos('.',Param)=0 then Param:=Param+'.WAV';
assign(f,Param);
reset(f,1);
IF Ioresult=0 then ReadRIFF(f)
else writeln('File not found!');
END.
[Back to SOUND SWAG index] [Back to Main SWAG index] [Original]