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

    {
    If anyone can fill me in on how to output in stereo, I'd be very
    appreciative... I've heard that port $220/$221 is for left channel,
    $222/$223 is for the right, but that doesn't make any sense...does it?

    This code makes R2D2 noises on a SoundBlaster until you press ESC.

    {adapted from SS4CH.PAS by Frank Hirsch}
    USES Crt;

    const sampleSize=4096;
    var sampleData:array[0..sampleSize-1]of byte;
    const samplePos:longint=0;
    var sampleSpeed:longint;
    var sampleDelta:longint;

    const resetPort =$226;
    const readPort  =$22A;
    const writePort =$22C;
    const dataAvailPort=$22E;

    function readByte:byte;begin
     repeat until shortInt(port[dataAvailPort])<0;
     readByte:=port[readPort];
     end;

    procedure initDSP;begin
     port[resetPort]:=1;
     delay(1);
     port[resetPort]:=0;
     repeat until readByte=$AA;
     end;

    var counter:longint;

    procedure timerInt;assembler;asm
      push ax
      push bx
      push dx
      push di
      push ds
      push es
      mov ax,seg @DATA
      mov ds,ax

      mov es,[segB800]
      xor byte ptr es:[0],$21

      mov bx,[word ptr samplePos+2]
      mov ah,byte ptr sampleData[bx]
      mov dx,[word ptr sampleSpeed]    {next sample byte}
      add [word ptr samplePos],dx
      adc bx,[word ptr sampleSpeed+2]
      and bx,[sampleSize-1]
      mov [word ptr samplePos+2],bx
      mov bx,[word ptr sampleDelta]
      add [word ptr sampleSpeed],bx
      mov bx,[word ptr sampleDelta+2]
      adc [word ptr sampleSpeed+2],bx
      mov dx,writePort
     @P2:              {ready for output byte?}
      in al,dx
      test al,$80
      jnz @P2
      mov al,ah
      out dx,al

      mov al,$20       {process interrupt}
      out $20,al
    {  sti}
                       {prep NEXT output}
     @P1:              {ready for command?}
      in al,dx
      test al,$80
      jnz @P1
      mov al,$10       {set up a DAC output}
      out dx,al

      db $66; inc word ptr [counter]

      pop es
      pop ds
      pop di
      pop dx
      pop bx
      pop ax
      iret
      end;

    var
      vec08:pointer absolute 0:8*4;
      old08:pointer;

    procedure setTimerTics(tics:word);begin
      asm cli; end;
      port[$43]:=$36;
      port[$40]:=lo(tics);
      port[$40]:=hi(tics);
      asm sti end;
      end;

    procedure setTimerFreq(freq:word);begin
      setTimerTics(succ(word($1234DC div freq)));
      end;

    procedure stopTimer;begin setTimerTics(0); end;

    procedure writeByte(b:byte);begin
      repeat until shortInt(port[writePort])>=0;
      port[writePort]:=b;
      end;

    procedure speaker(onOff:boolean);begin
      if onOff then writeByte($D1)
      else writeByte($D3);
      end;

    var i,j,n:word;

    const rate=16384;

    procedure note(freq,dur,slide:longint);
    begin
      counter:=0;
      sampleSpeed:=freq*sampleSize*(65536 div rate);
      sampleDelta:=slide;
      dur:=(dur*rate)div 1000;
      repeat
        if port[$60]=$81 then break;
        until counter>=dur;
      end;

    begin
     initDSP;
     for i:=0 to sampleSize-1 do
       sampleData[i]:=round(sin(i*pi/(sampleSize shr 1))*127.5+127.5);
     old08:=vec08;
     speaker(true);
     writeByte($10);  {prep sb for data}
     asm cli end;
     vec08:=@timerInt;
     asm sti end;
     setTimerFreq(rate);
     repeat
       case random(4) of
         0:note(random(1900)+60,(random(2)*80)+40,integer(random(3))-1);
         1:note(random(800)+450,(random(2)*80)+140,integer(random(2049))
                                                                  -1024);
         2:note(0,(random(2)+1)*40,0);
         3:note(random(30)+15,(random(2)*80)+40,random(2));
         end;
       until port[$60]=$81;
     stopTimer;
     asm cli end;
     vec08:=old08;
     asm sti end;
     speaker(false);  {it's probably gonna eat this as data}
     speaker(false);
     end.

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