                            VARMINT'S AUDIO TOOLS
                             VERSION 0.52  (beta)

                      Sound Blaster programming library

DISCLAIMER

  This software and documentation is provided as-is and is not
  garanteed to do or be anything.  Use at your own risk.

INTRODUCTION

  Varmint's Audio Tools (VAT) is a small Sound Blaster programming Kit.
  It's primary feature is a DSP interrupt driven core that handles
  real-time mixing and playing of digital sounds, background MIDI
  music, and backgroun MOD music.   It supports many FM chip routines, 
  input functions for WAVE samples and MIDI music files, true MPU-401
  MIDI output, auto recognition and setup of Sound Blaster compatable 
  cards, and  4.5 (adjustable) millisecond clock and microsecond accuracy 
  timers. VAT is Freeware and comes with source and example code (Turbo C).

  VAT was originally adapted from Peter Sprenger's SoundX library.  
  Original versions of VAT contained lots of code written by Peter, but  
  in the process of imroving and debugging the library, I have removed or
  replaced nearly all of Peter's original code. I offer special thanks to 
  Peter for his effort and the information he has provided.

SO WHO NEEDS IT?

  VAT is intended for any programmer who wants to add sound effects
  and music to their programs quickly and easily.  
  Like so many other programmers, I've been very dissappointed by the
  sound library offerings out there.  I have designed VAT to be very easy
  to use and as versatile as possible, and I hope that it is useful to you.

  When dealing with routines that run in the background, most programmers
  are concerned about how many CPU processing cycles the routines use up.  
  Here are the numbers that I get on my 486 DX2/66:

  Base overhead:  2.1 %
  Midi overhead:  1.0 % (average)
  Sample overhead: 1.0% per sample

  So, let's say that your program is playing some midi music and 4 digital
  samples in the background.  The total overhead would be: 2.1% (base) +
  1% (midi) + 4 * 1.0% (samples) = 7.1%.  That means that
  if you were animating some graphics at 30 FPS, it would slow down to
  27.6 FPS.  Pretty acceptable, especially considering that these numbers
  can be improved with compiler optimizations.


BETA VERSION

  This is the beta version of VAT, so it is a little scant on
  documentation, but I have tried to make up for that by commenting
  the code heavily and providing an example program.

  BETA also means bugs.  I am trying very hard to get rid of bugs in
  VAT, but this is especially tricky when I am trying to get it to 
  work with so many Sound Blaster configurations on so many platforms.
  I am relying heavily on people like you to try out VAT and report
  any problems.  Please help me make this a great tool!

HOW TO CONTACT THE AUTHOR(S)

  Any suggestions or bug reports are very welcome.  (The demo program
  creates the file "survey.txt" to make this process easier you.) Please 
  send them to one of these email addresses:

            smeagol@rt66.com
            ejorgensen@rr5.intel.com

  Peter Sprenger can be reached at:

            Pete@amber.dinoco.de


FREEWARE (LISCENCING)

  VAT is freeware, so you are free to copy and distribute this library
  as much as you like as long as you charge no fee for it's distribution.
  (The exception to this is if VAT is distributed as part of a large
  collection of shareware/freeware packages.) You are NOT restricted, 
  however, from charging money for games or other programs that use 
  VAT to produce sound.  All I ask is that you send me a complimentary 
  copy.  (Peter Sprenger would like one too.)  This helps me as a 
  developer to know who is using my software and for what.  It is also 
  a good way to make friends!

  In other words:

    Q: Can put any of the programs or example code from VAT into my
       own shareware that I am going to sell for money?

    A: Absolutely not.

    Q: If I use VAT to generate sounds in my game, can I sell my game
       for money?

    A: Yes!  (Please send Eric Jorgensen and Peter Sprenger complimentary
       copies of your game!)

FEATURES

  - Background DMA digital playback with real time mixing and
    unlimited channels.
  - Background Playing of MIDI music with easy control of tempo and volume.
  - Background Playing of MOD music with easy control of tempo and volume.
  - Routines to access the FM chip.
  - MPU-401 true MIDI output.
  - Vertical retrace checking functions for animators.
  - 4.5 millisecond (adjustable) clock plus microsecond accuracy timers.
  - AUto recognition and setup of Sound Blaster or Sound Blaster
    compatable sound cards.
  - Does not disturb the system clock (does not use int08)
  - Comes with heavily commented source code and demo.
  - Comes with an FM voice editor

VARMINT'S HOME FTP SITE

  I have a home site for all of my software:

      mack.rt66.com:/users/smeagol

  Here you can find my other shareware and freeware offerings:

    tmkr11.zip          Terrain Maker - A random Terrain generator/
                        editor for the freeware raytracer Persistence
                        of Vision (POV).

    vpova10.zip          Varmint's POV animator - A POV scene file parser
                        that allows the inclusion of functions and
                        animation commands.

    svgadiag.zip        Free SVGA diagnostic utility

    survey_results.txt  Compiled results of a large survey of SVGA cards
                        that I performed in December of 1994.

-----------------------------<*>----------------------------------------

VOICEED.EXE  - The FM voice editor

  This is a simple package to make editing FM voices a little easier
  for you.  To use it, you will need a VGA capable graphics card and a mouse.
  The interface is fairly simple and should be self-explanatory. Here is
  some lame, rudimentary documentation:

  To change the name of a voice or a filename, just click on the text and
  the program will let you type in a new name.

  To toggle a radio button, just click on it.

  To operate a slider, either click and drag the slider tool with the mouse
  or click on the arrows on the sides.  (The arrows move the slider one
  unit.)

  Highlighted letters on butons are hot keys.  A button can be accessed
  from the keyboard by pressing the hotkey letter.

  Be sure to save the file before you quit the program!


  More documentation will show up in version 1.0.


-----------------------------<*>----------------------------------------



USING VARMINT'S AUDIO TOOLS:  A CRASH COURSE

  Compiling the source code:

    The sound routines are desinged around FAR or HUGE pointers, so
    you need to compile under a large or huge memory model.  If you
    are using Turbo C and you wnat more memore under the debugger,
    you can request more by selecting "Debugger" from the options menu.

    Make sure that stack checking is turned OFF.

  Starting up the mixing kernel (ie: the sound engine):

    #include "sound.h"

    main()
    {
      if(SB_Setup()) {
        Go_Varmint();                // THis starts up the background handler
                                    // and enables you to play sounds and
                                    // MIDI music.
        do_some_stuff();

        Dropdead_Varmint();          // THis removes Varmint's interrupt and
                                    // puts the regular system clock
                                    // interrupt back.
      }
      else {
        printf("You don't have a sound Blaster.  EGAD!");
      }
    }

    ***  IMPORTANT ******  IMPORTANT ******  IMPORTANT ******  IMPORTANT ***

    - Do not call Go_Varmint() if SB_Setup() fails.

    - If you call Go_Varmint() and your program breaks or crashes before
    Dropdead_Varmint() is called, you should reboot your computer, or
    you might get a system crash next time you run your program.

    - If you call Go_Varmint(), you MUST call Dropdead_Varmint() before
    your program exits.  If you don't, you might not be able to run
    your program again without rebooting the system.

    - As a general rule, you should only have one Go_Varmint and one
    Dropdead_Varmint() in your code.

    ***  IMPORTANT ******  IMPORTANT ******  IMPORTANT ******  IMPORTANT ***


  Playing Sounds

    Once Go_Varmint has been called, you are free to play sounds.  You will
    first need to load the sound (8bit mono WAVE format.) and stick
    it onto a type SAMPLE pointer.  

    (You can use the function SetRate() to change the playback rate of the
    sounds.  Also see information about the global variables vclock and 
    dma_bufferlen below.)

    void somefunc()
    {
      unsigned char huge *sounddata;
      unsigned long int sound_length;

      sounddata = loadwave("shwoop.wav",&sound_length);
      if(!sounddata) {
        printf("Error loading wave.");
        exit(0);
      }

      playsound(sounddata,sound_length);
    }

    You only have to load the sound once, and since playsound() handles 
    things intelligently, you can call playsound()
    as many times with as many different samples as you want without  
    having to worry about conflicts. 
    
    playsound() will not cause any problems if Go_Varmint() has not 
    been called, but it won't play anything, either. :)

  Playing MIDI files

    To play a midi file, you don't actually call a funtion, but you
    instead set values to a few global variables.

    unsigned char  inst[1][11] = { 0x03,0x01,0x80,0x80,0xF7,0xF7,
                                  0x13,0x13,0x02,0x01,0x03},  // Harpsichord

    void mididemo(void)
    {
      int i,j,k,err;
      char *errstring[256],r=0;
      static MIDI *bach  = NULL;

      FM_Reset();

      for(i = 0 ; i < 9; i++) {           // Set up FM voices
        FM_SetVol(i,0);
        FM_SetVoice ( i,inst[0]) ;
      }

                                          // load a midi file
      err = ReadMidi("bach.mid",&bach,errstring);
      if(err) {
        printf("MIDI read ERROR: %s\n",errstring);
        printf("Exit?\n");
        r = getch();
        if(r != 'n') exit(1);
      }

      midi_data = bach;                   // assign the music
      midi_reset = TRUE;                  // reset internal midi variables
      midi_on = TRUE;                      // Turn on the midi player now!
    }

    You can adjust the volume by changing the value of the global
    variable "music_volume". (Min = 0, max = 63, default = 50)

    You can adjust the tempo by changing the value of the global
    variable "midi_usertempo".  (default = 2.0,  0 = fastest
    50.0 = come back wednesday) See also information about dma_bufferlen
    and midi_tempoadjust below.

    Voices can be altered while a song is playing without any problems.

    You can turn on MPU-401 output by setting the value of the global
    variable midi_mpuout to TRUE;

  Playing MOD files

    Playing a MOD file is almost exactly the same as playing a MIDI file.

    To play a MOD file, you don't actually call a funtion, but you
    instead set values to a few global variables.

    void moddemo(void)
    {
      int i,j,k,err;
      char *errstring[256],r=0;
      static MOD *modfile  = NULL;

                                           // load a mod file
      modfile = ReadMod("noname.mod");
      if(!modfile) {
        printf("MOD read ERROR\n");
        exit(1);
      }

      mod_data = bach;                   // assign the music
      mod_reset = TRUE;                  // reset internal MOD variables
      mod_on = TRUE;                     // Turn on the MOD player now!
    }

    You can adjust the volume by changing the value of the global
    variable "mod_volume". (Min =16, max = 0, default = 7)

    You can adjust the tempo by changing the value of the global
    variable "mod_bytespertick".  (default = 220,  60* = fastest
    500 = come back wednesday) See also information about dma_bufferlen
    and midi_tempoadjust below. (* mod_bytespertick can never be
    smaller than dma_bufferlen.  If it is, mod_on will automatically
    be set to false.)

  Using VarmintVSync

    VarmintVSync() is a function that can check for a vertical retrace
    without being disturbed by the mixing kernel.  It is designed to
    be used by game animators who time their animations by the vertical
    retrace signal.

    void animate()
    {
      ...

      sync_on = TRUE;                     

      while(foo) {

        prepare_graphics();               

        VarmintVSync();                   // Wait for next retrace

        dump_graphics();
      }
    }

    sync_on is a global variable that use use to turn on/off vsync
    checking within the mixing kernel.  Turning this off will cause 
    VarmintVSync to behave like a normal vsync  function, and will 
    reduce the CPU overhead by a tiny bit.

    You will want to call the function TimeVSync() simetime after
    SB_setup() and before Go_Varmint().  This will set the variable
    vsync_toolong based on the actual retrace frequency.

    
  Miscellaneous Functions and Variables

    extern unsigned _stklen          
      It seems that VAT is rather stack hungry.  This variable is    
      currently set to 16000, but you may want to play with larger
      values if you start getting stack overflow crashes.

     void SetRate(int rate)
      This function allows you to dynamically change the playback rate.
      Changing setrate will affect the frequency at which vclock is
      incremented.  It will also affect the midi playback tempo.

    long int vclock
      This isn't a function.  It is a global varibable that contains
      the current clock tick from the sound handler.  The frequency
      at which is incremented can be calculated like this:

          sample_rate / dma_bufferlen
 
      With library default settings, this is every 5.45 milliseconds.

    long int dma_bufferlen
      This is another global variable, and it controls the size of
      the DMA mixing buffer.  The default is 60 bytes.  If you want to 
      change this number, you should do so before you call SB_Setup()
      By making this number bigger, you will lower the frequency that
      sb_int is called.  You might want to do this if you think the sound
      routines are messing up some other time sensitive functions 
      those that look for the VGA verticle sync.

      If you increase dma_bufferlen, bbe sure to increase midi_tempoadjust 
      by the same ratio, or your midi flies will play at the wrong speed.

    float midi_tempoadjust
      This global variable changes the midi tempo by reducing the delay time
      between notes.  The default value for this is 2.0. Bigger numbers
      make the music faster.  You should only have to mess with this number
      if you cahnge the value of dma_bufferlen.

    WORD DSP_overhead
      This is another global variable.  It always holds the number of
      clock ticks that elapsed during the most previous sound handler
      interrupt.  Each clock tick is 0.858 microseconds.  Setting
      DSP_overhead to 0 will turn DSP overhead checking off. Giving
      it any kind of a value will turn it back on again.

    void timer_on()
    WORD timer_off()
      This a hyperaccurate suit of timer funcs.  Start by calling
      timer_on() and the read the result from timer_off().  Each tick
      is about 0.838 *micro*seconds.  These functions are only good
      for measuring times shorter than about 50 milliseconds.

    msdelay(int milliseconds)
      Standard millisecond delay function.  I mention this becasue VAT
      seems to cause problems with the delay() function included with
      Turbo C.

    void load_instruments(char *filename,BYTE inst[128][11])
      This loads 128 instruments definitions from a file of your choosing.

    void freemidi(MIDI *m)
    void freemod(MOD *m)
      These functions are for convenience.  They free all the internal
      data structures and then the parent structure itself.

  A FEW WORDS ABOUT MIDI

    The MIDI standard specifies that a midi compliant instument needs to
    have something like 24 voices available for playback.  Since the
    Sound blaster FM chip only offers 9 (even less if you implement
    percussion), You should be wary of playing midi files that play more
    than 9 voices simultaneously.  Here are some general tips:

      - use midi files that have only 5-6 voices max.

      - Unless you implement rythm voices, chop off the rythm track
        with a midi editor.

ON THE HORIZON

  Better docs
  Cooler Demo
  Midi Loopback
  New sound functions to allow looping, frequency and volume control



-----------------------------<*>----------------------------------------



Here is a note from Peter Sprenger's SoundX library: ------------------

                 Pete@amber.dinoco.de


Why I made this library: I was myself in a search of a good library
for soundblaster programming. What I encountered was the SBF, that
was a nice idea but written in a such a hurry, that it was still
useless. I has still bugs, too. Some other packages looked
interesting but are quite expensive. I just bought the original SBK
from Creative Labs and was disappointed. It was expensive and bad!
In their design I lost control of Timer 0, that I needed for my other
programming.
So I decided to make a good freeware soundblaster bibleothek. Up to
now I spent about 200 hours working time in this project. It is my
hope that their will be other people who make freeware that can be
used. If every programmer would spend about 100 hours for freeware in
the lifetime, not everybody had to reinvent the wheel again. Look at
the guys from GNU and OSF they are doing a great job!

If you can use this routines use them! There must be non false shame.
I wrote this stuff that not everybody has to write his own routines.
But it would be nice, that when you make something commercial with my
routines, that you send me a copy of your project or send me some bucks,
just enough for pizza and coke to support my night programming sessions.
If you send me nothing, ok. But USE the stuff, if you can need it!

Have fun with SoundX,

      Pete

Germany, 27-Jun-93

------------------------------------------------------------------------


