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

    {

     SoundS.INC  5-27-93  by Steven Tallent

    This is a Unit to play 8-bit raw Sound Files on any PC, up to 64k
    large.  It supports the PC speaker or a DAC (LPT1 or LPT2), although
    I do plan to upgrade it to support the SoundBlaster and Adlib Sound
    cards.  It is Object-oriented in nature, With one instance of a
    speaker defined automatically.  This Unit is public domain, With
    code and ideas captured from this echo and Dr. Dobbs Journal.

    Using the code is simple.  Just setup the the Speaker.Kind,
    Speaker.Silent, and Speaker.DisINT to the appropriate values, then
    just use the methods included.  The SoundBoard Object is very
    flexible For your own code.

    SoundBoard.Play  - Plays 8-bit music in What^ For Size length, With
                       Speed milliseconds between each Byte, and SampleRate
                       as the sample rate (in Hz).  Speed will need to be
                       changed on different computers (of course).

    SoundBoard.Sound - Plays a Sound at HZ Hertz, Duration in ms, on
                       VOICE voice.  The code included is useable on
                       the PC speaker (1 voice) or the Tandy speaker
                       (3 voices!).

    SoundBoard.Reset - Resets the Sound board.

    SoundBoard.Silent- Convenient Variable that disables all PLAY and Sound
                       if set to True.

    SoundBoard.DisINT- Disables all interrupts (except during Delays)
                       While using PLAY.

    This code may be freely distributed, changed, or included in your
    own commercial or shareware code, as long as this isn't all your code
    does.  This code may be included in commercial or shareware code
    libraries only With my permission (I'd like to see someone get some
    use out of it).
    }

    Unit Sounds;

    Interface

    Type
      BigArray    = Array[0..0] of Byte;
      PBigArray   = ^BigArray;
      KSoundBoard = (PCspeaker, Tandy, DAC1, DAC2, AdLib, SB, SBpro, SB16);

      SoundBoard  = Object
        Kind   : KSoundBoard;
        Silent : Boolean;
        DisINT : Boolean;
        Procedure Play(What : PBigArray; Size : Word; Speed : Byte;
                        SampleRate : Word);
        Procedure Sound(Hz, Duration : Word; Voice, Volume : Byte);
        Procedure Reset;
      end;

    Var
      Speaker : SoundBoard;

    Procedure Delay(ms : Word);

    Implementation

    Procedure SoundBoard.Reset;
    begin
      Case Kind of
        PCspeaker, Tandy : Port[97] := Port[97] and $FC;
      end;
      end;

    Procedure SoundBoard.Sound(Hz, Duration : Word; Voice, Volume : Byte);
    Var
      Count   : Word;
      SendByte,
      VoiceID : Byte;
    begin
      Case Kind of
        PCspeaker :
          begin
            Count := 1193180 div Hz;
            Port[97] := Port[97] or 3;
            Port[67] := 182;
            Port[66] := Lo(Count);
            Port[66] := Hi(Count);
            Delay(Duration);
            Port[97] := Port[97] and $FC;
          end;
        Tandy :
          begin
            if Voice = 1 then
              VoiceId := 0
            else
            if Voice = 2 then
              VoiceId := 32
            else
              VoiceId := 64;
            Count := 111861 div Hz;
            SendByte := 128 + VoiceId + (Count mod 16);
            Port [$61] := $68;
            Port [$C0] := SendByte;
            Port [$C0] := Count div 16;
            if Voice = 1 then
              VoiceId := 16
            else
            if Voice = 2 then
              VoiceId := 48
            else
              VoiceId := 96;
            SendByte := 128 + VoiceId + (15 - Volume);
            Port [$61] := $68;
            Port [$C0] := SendByte;
            Delay(Duration);
            SendByte := 128 + VoiceId + 15;
            Port [$61] := $68;
            Port [$C0] := SendByte;
        DAC1:;
        DAC2:;
        AdLib:;
        SB:;
        SBPro:;
        SB16:;
      end;

    Procedure SoundBoard.Play(What : PBigArray; Size : Word;
                              Speed : Byte; SampleRate : Word);
    Var
      Loop,
      Count,
      Data  : Word;
    begin
      if not Silent then
      begin
        Case Kind of
          PCspeaker, Tandy :
            begin
              Port[97] := Port[97] or 3;
              Count := 1193180 div (SampleRate div 256);
              For Loop := 1 to Size do
              begin
                Data := Count div (What^[Loop] + 1);
                Port[67] := 182;
                Port[66] := Lo(Data);
                Port[66] := Hi(Data);
                Delay(Speed);
                if DisINT then
                Asm
                  CLI
                end;
              end;
              Port[97] := Port[97] and $FC;
            end;

            DAC1:
              For Loop := 1 to Size do
              begin
                Port [$0378] := What^[Loop];
                Delay (Speed);
                if DisINT then
                Asm
                  CLI
                end;
              end;

            DAC2:
              For Loop := 1 to Size do
              begin
                Port [$0278] := What^[Loop];
                Delay (Speed);
                if DisINT then
                Asm
                  CLI
                end;
              end;

            AdLib:;
            SB:;
            SBPro:;
            SB16:;
          end;
          Asm
            STI
          end;
      end;
    end;

    Procedure Delay(ms : Word); Assembler;
    Asm
      STI
      MOV AH, $86
      MOV CX, 0
      MOV DX, [ms]
      INT $15
    end;

    end.

    {-----------------------------------------------------------------
    Here's a Program that will accept three values from the command
    line, the File, its speed, and the sample rate, and plays it
    through the PC speaker.  I've tried in on WAV, VOC, SAM, and even
    Amiga sampled Files, With no problems (limited to 64k). I've even
    played MOD Files to hear all the sampled instruments!  This Program
    does not strip header information, but plays it too, but I can't
    hear the difference on WAV and VOC Files.
    }
    Program TestSnd;
    Uses
      Sounds;
    Var
      I2   : PBigArray;
      spd  : Integer;
      samp : Word;
      res  : Word;
      siz  : Word;
      s    : String;
      f1   : File of Byte;
      F    : File;
    begin
      Speaker.Kind   := PCspeaker;
      Speaker.DisINT := True;
      Speaker.Silent := False;
      s := ParamStr(1);
      Assign(f1,s);  {Get size of File}
      Reset(f1);
      Val (ParamStr(2), Spd, Res);
      Val (ParamStr(3), samp, Res);
      siz := FileSize(f1);
      close(f1);
      Assign(f,s);
      Reset(f);
      getmem (I2,siz);  {Allocate Memory For Sound File}
      BlockRead(f,I2^,siz,res);  {Load Sound into Memory}
      Speaker.Play (i2, siz, spd, samp);
      FreeMem (I2, siz);
    end.

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