    ͻ
  Ŀ
ͼ                                              ͻ   Release 3f     
    ModWave : Module and Wave Player for Euphoria                     
ͻ           by Pete Eberlein                   ͼ   Apr. 22, 1998  
  
    ͼ
   For Euphoria 2.0,
   supports Sound Blaster (dsp 2.00 or greater) and PC speaker


   Features in this release:
        Totally background playback.
        Plays wave files too.
        Correctly plays more mod files than before.
        Can play a mod file and multiple wave files simultaneously.
        A mod player program and wave demo are included.

   What's *NEW* in this release:
        Don't ask me, I just work here...
        Debugging like crazy, added some error checking (at last)
        Fix memory corruption bug discovered by PatRat and Einar Mogen
        Fixed lost keypresses when used with with Michael Bolin's keyread.e
        
   What was new in the previous release(s):
        PC speaker mode in event of no soundblaster (won't run under windows)
        wave effects reworked into separate procedures
        fixed minor bugs here and there (crashes due to lack of low memory)
        combined sound.e and doswrap.e into modwave.e
        Fixed a bug that caused slow playback on sb pro cards.
        Let the user program decide what to do if the sound card
        cannot be initialized or is not present.


 How to use ModWave:

   First, include the file "modwave.e" in your Euphoria program.  This 
   automatically includes the neccessary SoundBlaster interface file 
   called "sound.e".  Now you must initialize the sound system using the
   function init_modwave(mode, playback_rate, mixing_channels), which
   returns a non-zero value if the sound card could not be initialized.
   Values for mode must be MONO or STEREO.  Values for playback_rate can
   be anywhere from 4000 hz. to 45454 hz.  (Some older sound cards do not
   support playback rates above 22khz for STEREO output, so playback rate
   will automatically be lowered if necessary.)  Mixing_channels tells how
   many channels will be set aside for playback.  An average mod file takes
   up about 4-8 channels, and the remaining channels can be used for playing
   wave files.  init_modwave now returns a value indicating whether or not
   the sound system was initialized.  You can use this value to decide
   whether to halt your progam or not to play any sound files.  (Previously,
   modwave always aborted the program if there was no soundcard.)
   Note: the modwave system does not yet support 16-bit playback.

       include modwave.e

       if init_modwave(STEREO, 44100, 20) then  -- just about CD-quality
                                                -- 20 channels allocated
           puts(1, "Could not initialize sound system.")
           abort(1)
       end if

       -- or --

       integer sound_on
       sound_on = not init_modwave(STEREO, 44100, 20)
   
   Next, load the mod file you want to play using the function 
   load_mod(filename), which returns a non-zero value if the mod could not 
   be loaded.  (You must call init_modwave before attempting to load a mod.)
   load_mod will always return non-zero if init_modwave returned non-zero.

       -- this will abort only if the mod file is not found.
       -- if the sound card is not present, it will not abort.
       if sound_on and load_mod("appeal.mod") then
           puts(1, "Could not load appeal.mod\n")
           close_modwave()
           abort(1)
       end if

   The mod will start playing automatically as soon as it is loaded.
   Loading another mod will unload the current mod first, and then
   play the new one.  There is no way to load multiple mods at the same
   time and quickly switch between them.

   ModWave hooks the SoundBlaster interrupt so that the buffer is
   automatically updated whenever necessary.  The mod will play through
   to the end and automatically loop back to the beginning or whereever
   a jump effect directs.  There is currently no way to tell if a mod
   has played to the end or looped.

   See below or modplay.ex for some things you can do to a mod while it
   is playing.

   When you are done playing the song, be sure to call unload_mod() to free
   up all the memory used by the mod.  (unload_mod() will pause sound output
   using pause_sound(), so if you are still playing wave files, call
   unpause_sound() after unload_mod() to keep playing them.)

       unload_mod()

   If you wanted to play another mod file, you could just load a new one
   using load_mod() as before.  If you call load_mod() before unloading
   the current mod, unload_mod() will be called automatically.

   If you are totally finished, you should call close_modwave() before
   exiting your program to leave the soundblaster card in a sane state.
   You should only call close_modwave once during the program, after all
   sound operations have been completed.

       close_modwave()  -- Now we can exit our program

   There are many things you can do while a module is playing. See 
   modplay.ex for specific examples.  

   You can change the volume with the set_volume(which, value) procedure.

       set_volume(MASTER, #F0)  -- one speaker full on
       set_volume(MASTER, #0F)  -- other speaker full on
       set_volume(MASTER, #99)  -- both speakers on

       volume_up()    -- increments MASTER volume
       volume_down()  -- decrements MASTER volume
   
   Pause_sound, unpause_sound and toggle_sound affect both mod and wave
   playback.  Next_track simply skips to the next track in the mod.

       pause_sound()    -- halts sound playback
       unpause_sound()  -- continues paused sound
       toggle_sound()   -- unpauses if paused, pauses if playing

       next_track()   -- skips to the next track and starts at row 0
       select_trace() -- skips to any track in the song (may have adverse
                         effects due to skipped commands)

       get_mod_info() -- returns a sequence of tracking information
                         (write your own tracking viewer?)


 Advice for the day

    Never, ever, under any circumstances, write a mod player, unless you are
    a programming masochist.  The code *will* come back to haunt you,
    guaranteed.


 NEW!  Wave files

   To load a wave file, use load_wave(filename).  If the wave file was
   loaded successfully, a wave info sequence is returned, otherwise the
   constant LOAD_WAVE_FAIL is returned.  The wave info sequence can be
   passed to start_wave() to play the wave.  Stereo and mono wave files
   are supported.  Since ModWave plays back only in 8-bits, 16-bit waves
   will automatically be converted to 8-bit.

       object wave_info, wave2_info
       wave_info = load_wave("mywave.wav")
       wave2_info = load_wave("alt_wave.wav")
       if compare(wave_info, LOAD_WAVE_FAIL) = 0      -- check to make sure
       or compare(wave2_info, LOAD_WAVE_FAIL) = 0 then  -- they loaded
           puts(1, "Error loading wave files.\n")
           abort(1)
       end if
        
   To play the wave, use play_wave(wave_info, loop, volume), where
   wave_info is the sequence returned by load_wave(), loop is a boolean
   value indicating whether the wave should loop at the end, and volume
   is an integer in the range of 0 to 255.  Returned by play_wave is a
   sequence containing the channels that the wave is playing in.  A mono
   wave will return a length=1 sequence, stereo length=2, and if no 
   channels were available, a length=0 sequence is returned.  Also be
   sure to initialize the modwave system with init_modwave() as before.

       sequence chan_info, chan2_info
       chan_id = play_wave(wave_info, 0, 200)
          -- play wave described by wave_info, doesn't loop, volume 200
       chan2_id = play_wave(wave_info, 1, 255)
          -- play wave described by wave_info, does loop, maximum volume

   Now that there is a wave or two playing, we can use the chan_info
   returned by play_wave to perform effects on the wave.  The following
   procedures and functions are used to manipulate how waves are playing.

         stop_wave(chan_id)
         set_wave_volume(chan_id, volume)
         set_wave_volume(chan_id, {left_volume, right_volume})
         set_wave_hertz(chan_id, frequency)
         set_wave_offset(chan_id, offset)  -- offset is in bytes

         x = is_wave_playing(chan_id)
           -- x will be 1 is the wave on that channel is playing or looped,
           -- x will be 0 is the wave has stopped
           -- this may not always work correctly if another wave has reused
           --   the channels

         chan_id = switch_wave(chan_id, wave_info, loop, volume)
         -- this basically stops the wave and starts a new one using play_wave

   Don't forget to unload the wave file with unload_wave() when you are
   finished with it.  This will free all the memory used by the wave.  It is
   recommend to make sure that any waves currently playing are stopped before
   unloading the wave file.
   
       unload_wave(wave_info)
       
   You can load multiple wave infos into a sequence using load_waves with a
   sequence of file names.  You can unload those waves with a single call to
   unload_waves.
       
       sounds = load_waves({"sound1.wav","sound2.wav","sound3.wav"})
       
       -- play_wave(sounds[1], loop, volume), etc.
       
       unload_waves(sounds)
       
   Also remember to call close_modwave() before your program exits in 
   order to leave the sound card in a sane state.

   See wavedemo.ex for a simple wave file example.

 Notes on using the PC speaker:

   ModWave will always try to use the Soundblaster card if it is present
   and working.  In the event that there is no sound card or the BLASTER
   environment variable is not correct or missing, ModWave will attempt
   to play through the PC speaker.  Due to the speaker playing at
   effectively 1-bit MONO, sound quality will be severly reduced.  High 
   playback rates are also not recommended due to the fact that a high 
   rate of interrupts will impact total system performance.  Windows will 
   not allow high speed interrupts and may suggest pure dos mode.
   If the pc speaker sounds get really annoying, just set the master volume
   to 0 for some peace and quiet.

   The high speed interrupt required for pc speaker sound overrides
   the Euphoria tick_rate() procedure.  Plan your program accordingly.
   

 Misc.

   <AUTHOR NAME="Lucius Hilley">
      Pete's mod player.
      Fully background.
      You can't run Euphoria programs from the shell.
      Fully background capable as long as you have your win95 sounds disabled.
   </AUTHOR>

   Thanks Lucius.  You've been a real help.  :)

   Unfortunately there are some conflicts with the windows 95 sounds and
   other programs executed through dos Shell.  Running ex.exe has been
   reported to crash with a Causeway error under modplay's dos shell.
   (This hasn't happened to me lately, so I wonder if it's fixed ???)
   Modplay also tends to stop playback when task-switching in a win95
   dos window, except it works ok if win95 sounds are disabled.  Don't
   hold your breath waiting for the win32 version.


   You can use this mod player in your programs if you want, just be sure
   to give me credit, and send any bug reports you find to my email address
   below.  Also, I want a free registered copy of any softwares that use my
   ModWave system.  I cannot be held responsible for any damage, destruction,
   abnormal occurrences, or other things that you didn't expect to happen
   resulting from the use of ModWave or any programs that incorporate ModWave.

   Greets and Credits:
       Firelight for their mod tutorial,
       Draeden for his,
       Jacques Deschenes whose SFX2 I learned from, and for doswrap.e,
       Ethan Brodsky whose work I also studied,
       Oxygen whose web site I got SB stuff from,
       Jorian's crap module player,
       and fellow Euphorians: Lucius Hilley, Greg Harris and David Cuny
          for all their help debugging and testing my code.  Thanks guys!
       and now Einar Mogen and PatRat, who both plan to use ModWave in
          in their upcoming games.  Thanks for putting up with buggy code!

   I apologize if this documentation has been unclear, inaccurate or just
   plain boring... but I've been a little rushed of late.  And I want to
   get the game that I started into high gear.  But I still want feedback!
   Please send suggestions, questions, comments, and/or bug reports to the
   email address below.

   oh yeah, visit http://www.harborside.com/home/x/xseal/euphoria/

 Enjoy!
                   _____         _____        _____
    ________      /\    \       /\    \      /\    \
   /   \    \    /  \____\     /  \____\    /  \____\
  /  _  \____\  /   / ___/_   /   /____/   /   / ___/_
 /  / \  |____|/   / /\____\ /    \    \  /   / /\____\
 \  \_/ /    / \   \/ / ___/_\     \    \ \   \/ / ___/_
  \    /____/   \    / /\    \\/\   \    \ \    / /\    \
   \   \    \    \   \/  \____\  \   \    \ \   \/  \____\
    \   \    \    \      /    /   \   \____\ \      /    /
     \   \____\    \    /    /     \  /    /  \    /    /
      \  /    /     \  /    /       \/____/    \  /    /
       \/____/       \/____/xseal@harborside.com\/____/


                                                           

