[Back to SOUND SWAG index]  [Back to Main SWAG index]  [Original]

UNIT vocdecl;  { see demo at end of document }

INTERFACE

function reset_dsp(base:word):boolean;
procedure write_dac(level:byte);
function read_dac:byte;
function speaker_on:byte;

function speaker_off:byte;

procedure dma_pause;
procedure dma_continue;

procedure play_back(sound:pointer;size:word;frequency:word);
procedure play_voc(filename:string;buf:pointer);
function  done_playing:boolean;
function  play_raw(filename:string;buf:pointer):word;

IMPLEMENTATION

uses crt;

type
  iDsound=record
             dunno,
             rate,
             num_samples,
             dunno2:word;
           end;

var
  dsp_reset:word;
  dsp_read_data:word;
  dsp_write_data:word;
  dsp_write_status:word;
  dsp_data_avail:word;

  since_midnight:longint absolute $40:$6C;
  playing_till:longint;


function reset_dsp(base:word):boolean;
begin
  base:=base*$10;

  dsp_reset:=base+$206;
  dsp_read_data:=base+$20a;
  dsp_write_data:=base+$20c;
  dsp_write_status:=base+$20c;
  dsp_data_avail:=base+$20e;

  port[dsp_reset]:=1;
  delay(10);

  port[dsp_reset]:=0;
  delay(10);

  reset_dsp:=(port[dsp_data_avail]and $80=$80)and(port[dsp_read_data]=$aa);
end;

procedure write_dsp(value:byte);
begin
  while port[dsp_write_status] and $80<>0 do;
  port[dsp_write_data]:=value;
end;

function read_dsp:byte;
begin
  while port[dsp_data_avail]and $80=0 do;
  read_dsp:=port[dsp_read_data];
end;

procedure write_dac(level:byte);
begin
  write_dsp($10);
  write_dsp(level);
end;

function read_dac:byte;
begin
  write_dsp($20);
  read_dac:=read_dsp;
end;

function speaker_on:byte;
begin
  write_dsp($d1);
end;

function speaker_off:byte;
begin
  write_dsp($d3);
end;

procedure dma_continue;
begin
  playing_till:=since_midnight+playing_till;
  write_dsp($d4);
end;

procedure dma_pause;
begin
  playing_till:=playing_till-since_midnight;
  write_dsp($d0);
end;

procedure play_back(sound:pointer;size:word;frequency:word);
var
  time_constant:word;
  page:word;
  offset:word;
begin
  speaker_on;
  size:=size-1;
 { set up the dma chip }
  offset:=seg(sound^)shl 4+ofs(sound^);
  page:=(seg(sound^)+ofs(sound^)shr 4)shr 12;
  port[$0a]:=5;
  port[$0c]:=0;
  port[$0b]:=$49;
  port[$02]:=lo(offset);
  port[$02]:=hi(offset);
  port[$83]:=page;
  port[$03]:=lo(size);
  port[$03]:=hi(size);
  port[$0a]:=1;

 { set the playback frequency }
  time_constant:=256-1000000 div frequency;
  write_dsp($40);
  write_dsp(time_constant);

 { set the playback type (8-bit) }
  write_dsp($14);
  write_dsp(lo(size));
  write_dsp(hi(size));
end;

procedure play_voc(filename:string;buf:pointer);
var
  f:file;
  s:word;
  freq:word;

  h:record
      signature:array[1..20]of char;
      data_start:word;
      version:integer;
      id:integer;
    end;
  d:record
      id:byte;
      len:array[1..3]of byte;
      sr:byte;
      pack:byte;
    end;

begin
  {$i-}
{  if pos('.',filename)=0 then filename:=filename+'.voc';}
  assign(f,filename);
  reset(f,1);
  blockread(f,h,26);
  blockread(f,d,6);
  freq:=round(1000000/(256-d.sr));
  s:=ord(d.len[3])+ord(d.len[2])*256+ord(d.len[1])*256*256;
 { writeln('-----------header----------');
  writeln('signature: ', h.signature);
  writeln('data_start: ', h.data_start);
  writeln('version: ', hi(h.version), '.', lo(h.version));
  writeln('id: ', h.id);
  writeln;
  writeln('------------data-----------');
  writeln('id: ', d.id);
  writeln('len: ', s);
  writeln('sr: ', d.sr);
  writeln('freq: ', freq);
  writeln('pack: ', d.pack);}
  blockread(f,buf^,s);
  close(f);
  {$i-}
  if ioresult<>0 then
  begin
    writeln('Can''t find voc file "',filename,'".');
    halt(1);
  end;
  playing_till:=since_midnight+round(s/freq*18.20648193);
  play_back(buf,s,freq);
end;

function done_playing:boolean;
begin
  done_playing:=since_midnight>playing_till;
end;

function play_raw(filename:string;buf:pointer):word;
var
  f:file;
  s:word;
  head:idSound;
begin
  play_raw:=0;
  if pos('.',filename)=0 then filename:=filename+'.raw';
  assign(f,filename);
  {$i-} reset(f,1); {$i+}
  if(ioresult<>0)then
    exit;

  blockread(f,head,sizeof(head));
  if(maxavail<head.num_samples)then exit;

  getmem(buf,head.num_samples);

  s:=head.num_samples;
  blockread(f,buf^,s);
  close(f);

  play_back(buf,s,head.rate);
  playing_till:=since_midnight+round(s/head.rate*18.20648193);
  play_raw:=head.num_samples;
  freemem(buf,head.num_samples);
end;

begin
 if not reset_dsp(2)then
 begin
   writeln('SoundBlaster not found at 220h');
   halt(1);
 end else writeln('SoundBlaster found at 220h');
end.

{ ------------------------  DEMO --------------------- }

uses utils,vocdecl;

var
  buf:pointer;

begin
  if(paramcount<1)then
  begin
    writeln('Syntax: P [file].voc');
    halt;
  end;
  getmem(buf,fsize(paramstr(1)));
  play_voc(paramstr(1),buf);
end.

[Back to SOUND SWAG index]  [Back to Main SWAG index]  [Original]