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

    {---------------------------------------------------------------------------
                       Unit SBVoice (v1.10) For Turbo Pascal 6.0
           For interfacing With the SoundBlaster's digitized voice channel.
               Copyright (c) 1991, Amit K. Mathur, Windsor, Ontario.

                            By: Amit K. Mathur
                                3215 St. Patrick's Drive
                                Windsor, Ontario
                                N9E 3H2 CANADA
                            Ph: (519) 966-6924

     Networks:  RIME(tm) R/O ->WinDSor, ILink (Shareware), NA-Net (Gaming),
                WWIVNet (#198@5950), or direct on NorthSTAR (519)735-1504.

     These routines are released to the public domain.  However I will gladly
     accept contributions towards further development of this and other products.
     Please send any changes or improvements my way.  and I'm interested in
     other SoundBlaster utilities and Programming tools.  Thanks in advance.
     --------------------------------------------------------------------------}

    {$O+,F+}
    { Allow this Unit to Be Overlayed (doesn't affect Compilation if you decide
      not to overlay it), and Force Far calls.                                 }

    Unit SBVoice;

    Interface

    Uses MemAlloc;                                    { Memory Allocation Proc }

    Var
    {$ifNDEF NoSBVoiceArray}                          { to use your own        }
         SoundFile: Array[1..64000] of Byte;          { whatever size you want }
    {$endif}
         sgSBDriver, ofSBDriver: Word;                { seg and ofs of Driver  }
         SBDriver: Pointer;                           { Pointer to the driver  }
         StatusWord: Word;                            { stores SB status       }
         SBFound: Boolean;                            { whether Init worked    }

    Procedure loaddriver(fi:String);
    { Loads CT-VOICE.DRV into memory.  'fi' is the path to the driver.         }

    Procedure closedriver;
    { Clean up routine.  not Really necessary if your Program is over.         }

    Procedure loadvoice(f:String;start,size:Word);
    { Load 'f' into memory.  Start is the start of the area within
      'f' to load and size is the amount to laod.  if you set size to 0
      then it will load the entire File.                                      }

    Function sb_getversion:Integer;
    { Get the version number of the CT-VOICE.DRV
      Returns the Version number                                              }

    Function sb_init:Integer;
    { Initialize the SoundBlaster.  Call this right after load driver, unless
      you have to change the BaseIOAddress or Interrupt number and haven't
      changed the CT-VOICE.DRV File itself.
      Returns:  0 - no problem
                1 - Sound card failiure
                2 - I/O failiure
                3 - DMA interrupt failiure                                    }

    Procedure sb_output(sg,os:Word);
    { Output the digitized Sound.  You must load the Sound first!
      sg and os are the segment and offset of either SoundFile or whatever
      Array you use to store the Sound.  if you use a .VOC File then call
      With 26 added to the offset.                                            }

    Procedure sb_setstatusWord(sg,os:Word);
    { Sets the location of the status Word.  This is the third thing you should
      do, after loading the driver and initializing it.
      The StatusWord will contain $0FFFF if input/output is in output, and
      0 when it's done.  It will also hold the values of the markers in voice
      Files if any are encounterred, allowing you to coordinate output with
      your Programs.                                                          }

    Procedure sb_speaker(mode:Word);
    { Set the speaker on/off.  off is mode 0, and On is anything else.  This
      is the fourth thing you should do in your initialization.               }

    Procedure sb_uninstall;
    { Uninstall the driver from memory.   Used by CloseDriver.                }

    Procedure sb_setIOaddress(add:Word);
    { Override the IOaddress found inside the CT-VOICE.DRV File.  Add is the
      new IO address.                                                         }

    Procedure sb_setinterruptnumber(intno:Word);
    { Allows you to override the Interrupt number in the driver.  IntNo is your
      new interrupt number (3, 5, 7 or 9).                                    }

    Procedure sb_stopoutput;
    { Stops the output in progress                                            }

    Function sb_pauseoutput: Integer;
    { PaUses the output in progress.
      Returns:  0 - success
                1 - fail                                                      }

    Function sb_continueoutput: Integer;
    { Continues a paused output.
      Returns:  0 - success
                1 - fail (nothing to continue)                                }

    Function sb_breakloop(mode:Word): Integer;
    { Breaks out of the currect output loop.
      Modes:  0 - continue round, stop when done
              1 - stop immediately
      Returns:  0 - success
                1 - not in loop                                               }

    Procedure sb_input(highlength,lowlength,seginputbuff,ofsinputbuff:Word);
    { Input digitized Sound.
      HighLength: The high Byte of the length of the input buffer.
      LowLength:  The low Byte of the length of the input buffer.
      SegInputBuff: The Segment of the start of the input buffer.
      ofsInputBuff: The offset of the start of the input buffer.              }

    Procedure sb_setuserFunction(segaddress,ofsaddress:Word);
    { Sets up a user Function that the SB calls when it encounters a new data
      block.  It must perForm a Far ret, preserve DS,DI,SI and flag register.
      Clear Carry flag if you want the driver to process the block, or set it
      if your routine will.  It must be clear if the block Type is 0, that
      is the terminate block.
      SegAddress is the segment of your user Function in memory.
      ofsAddress is the ofset of your user Function in memory.                }

    Implementation

    Uses Dos;

    Procedure Abort(s:String);
    begin
      Writeln('The Following Error Has Occurred: ',s);
      Writeln('Remedy and try again.  We apologize For any inconvenience.');
      halt(1);
    end;

    Procedure loaddriver(fi:String);
    Var f: File;
        k: Integer;
        t: String[8];
    begin
        assign(f,fi+'CT-VOICE.DRV');
        {$I-} Reset(f,1); {$I+}
        if Ioresult <> 0 then
            Abort('Cannot Open '+fi+'CT-VOICE.DRV');
        blockread(f,Mem[sgSBDriver:ofSBDriver],Filesize(f));
        close(f);
        t:='';
        For k:=0 to 7 do
            t:=t+chr(Mem[sgSBDriver:ofSBDriver+k+3]);
        if t<>'CT-VOICE' then
            abort('Invalid CT-VOICE Driver!');
    end;

    Procedure closedriver;
    begin
        sb_uninstall;
        if dalloc(sbdriver)=0 then
            abort('Uninstall Error!');
    end;

    Procedure loadvoice(f:String;start,size:Word);
    Var fi: File;
        k: Word;
    begin
        assign(fi,f);
        {$I-} Reset(fi,1); {$I+}
        if Ioresult <> 0 then
           abort('Cannot Open '+f+'!');
        k:=0;
        seek(fi,start);
        if size=0 then size:=Filesize(fi);
        blockread(fi,Mem[seg(SoundFile):ofs(SoundFile)],size);
        close(fi);
    end;

    Function sb_getversion: Integer; Assembler;
    Asm
       push  bp
       mov   bx,0
       call  SBDriver
       pop   bp
    end;

    Procedure sb_setIOaddress(add:Word); Assembler;
    Asm
       push  bp
       mov   bx,1
       mov   ax,add
       call  SBDriver
       pop   bp
    end;

    Procedure sb_setinterruptnumber(intno:Word); Assembler;
    Asm
       push  bp
       mov   bx,2
       mov   ax,intno
       call  SBDriver
       pop   bp
    end;

    Procedure sb_stopoutput; Assembler;
    Asm
       push  bp
       mov   bx,8
       call  SBDriver
       pop   bp
    end;

    Function sb_init: Integer; Assembler;
    Asm
       push  bp
       mov   bx, 3
       call  SBDriver
       pop   bp
    end;

    Function sb_pauseoutput: Integer; Assembler;
    Asm
       push  bp
       mov   bx,10
       call  SBDriver
       pop   bp
    end;

    Function sb_continueoutput: Integer; Assembler;
    Asm
       push  bp
       mov   bx,11
       call  SBDriver
       pop   bp
    end;

    Function sb_breakloop(mode:Word): Integer; Assembler;
    Asm
       push  bp
       mov   bx,12
       mov   ax,mode
       call  SBDriver
       pop   bp
    end;

    Procedure sb_output(sg,os:Word); Assembler;
    Asm
        push bp
        push di
        mov  bx,6
        mov  di,os             { offset of voice  }
        mov  es,sg             { segment of voice }
        call SBDriver
        pop  di
        pop  bp
    end;

    Procedure sb_input(highlength,lowlength,seginputbuff,ofsinputbuff:Word);
    Assembler;
    Asm
        push bp
        push di
        mov  bx,7
        mov  dx,highlength
        mov  cx,lowlength
        mov  es,seginputbuff
        mov  di,ofsinputbuff
        call SBDriver
        pop  di
        pop  bp
    end;

    Procedure sb_setstatusWord(sg,os:Word); Assembler;
    Asm
        push bp
        push di
        mov  bx,5
        mov  di,os
        mov  es,sg
        call SBDriver
        pop  di
        pop  bp
    end;

    Procedure sb_speaker(mode:Word); Assembler;
    Asm
       push  bp
       mov   bx,4
       mov   ax,mode
       call  SBDriver
       pop   bp
    end;

    Procedure sb_uninstall; Assembler;
    Asm
       push  bp
       mov   bx,9
       call  SBDriver
       pop   bp
    end;

    Procedure sb_setuserFunction(segaddress,ofsaddress:Word); Assembler;
    Asm
       push  bp
       mov   dx,segaddress
       mov   ax,ofsaddress
       mov   bx,13
       call  SBDriver
       pop   bp
    end;

    begin {set up SB}

      if DosMemAvail < 5000 then                           { lower the heap   }
          abort('not Enough Memory');                      { With $M to fix   }
      StatusWord:=MAlloc(SBDriver,5000);
      if StatusWord<>0 then
          abort('Memory Allocation Error');

      sgSBDriver:=MemW[seg(SBDriver):ofs(SBDriver)+2];
      ofSBDriver:=MemW[seg(SBDriver):ofs(SBDriver)];

      Loaddriver('');                                      { change at will   }
      if sb_init<>0 then                                   { or stick in your }
          SBFound:=False                                   { own Program init }
      else
          SBFound:=True;

      if SBFound then begin
          sb_setstatusWord(seg(statusWord),ofs(statusWord));
          sb_speaker(1);                                   { turn SB on       }
      end;
    end.

    {There's the Unit For .VOC playing.}

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