Jump to content
mikb89

Audio Pump Up: FMOD Ex 1.4

Recommended Posts

Audio Pump Up: FMOD Ex 1.4

Hiretsukan, Cowlol, mikb89

 

Introduction

VX Ace porting of Cowlol rewritten Hiretsukan's FMOD Ex Audio for Rpg Maker XP.

The original script let you play audio through FMOD libraries, adding support for more file formats, advanced play/pause functions, etc.

My porting offer a better integration with VX Ace system, and also let you use both original audio system and new, to have more compatibility.

Also, you can have multiple audio channel, which can be controlled also with a variable.

This variable will point the current channel. Each music and sound will use that.

Channel 0 respond to standard system, channels from 1 to max utilize FMOD.

I suggest to don't exagerate with channels. 3 or 4 should be ok in most cases.

 

In FMOD channel you can also use effects called DSP like echo, reverber, tremolo, equalizers etc.

 

Features

  • multiple audio channel;
  • standard audio system still available;
  • DSP special effect applicable;
  • functions like set_loop_points available;
  • many audio formats supported;
  • the script can detect F1 mute options.

 

Screenshots

It's an audio system.

 

How to Use

Copy the script under Modules to use.

You need the FMOD library, a .dll file to insert in the System folder where you have the RGSS30X.dll (not Graphics\System!!!).

To use the script just set a channel variable from script options and change its value.

Additional functions (like FMod.bgm_set_loop_points(first, second)) can be used with Call script, see the demo.

Other infos in the comments.

 

Demo

Multilanguage demo v. 1.4 (3.37 MB)

http://www.mediafire.com/?mwqys4h1a2rh0c2

 

FModEx libraries v. 0.4.40.5 (509 KB)

http://www.mediafire.com/?ybuas9ervddetp2

 

FModEx libraries v. 0.4.18.3 (307 KB)

http://www.mediafire.com/?nb17boudfmuwo3d

 

You can download latest version of the FMOD (with the developer kit) from the official website: http://www.fmod.org/

 

Script

 

# Audio Pump Up: FMOD Ex v. 1.4
# VX Ace version
# by mikb89

# Details:
#  Audio module rewrite using FMOD library (http://www.fmod.org/).
# 
#  I was trying to develop this using MCI, but I ended up porting the XP version
#   of the Cowlol's edited Hiretsukan's FMOD Ex Audio script.
# 
#  This script is intended to offer enhanced audio capabilities, without
#   replacing the standard ones. You'll have various audio channel that you can
#   control with a variable. If variable is 0, controls are related to the 0
#   channel, if variable is 1, controls are related to channel 1, etc.
#  Channel 0 is the default audio system.
#  Channel from 1 to the max number specified, works like the standard system
#   (if you play another BGM, the previous one will stop) but you can play many
#   audios, using many channels. Simple.
# 
#  Do not exagerate with the max channel number! Use just the channels you need.
#  Please notice that different audio channels means different audios of the same
#   type (BGM or BGS or ME) playing also at the SAME TIME. You'll need about 3 or
#   4 channels even if you're planning to create very special effects, so.

# Configurations:
module APU
 CURRENT_CHANNEL_VARIABLE = 1 # Which variable use to choose current channel?
 MAX_CHANNELS = 4 # How many channels do you plan to have in your game?
 READ_F1_SETTINGS = true # User can disable channels 1+ audio with F1?
end

# Others:
#
#  * Modified to be fully compatible with VX/Ace
#  * Modified to have multiple channels
#  * Modified to optionally read F1 audio settings
#  * Modified to support awesome audio effects (DSP, read documentation)
#  * Modified to make the pan function (balance) usable
#
#  Differences with standard audio system (channel 0).
#  In channel 1+:
#   - MIDIs sound differently;
#   - on memorize/replay event commands, the position is also memorized;
#   - same SE file can be played more than once at the same time;
#   - fading doesn't continue if game window isn't active.


# Original script comment following:
#==============================================================================
# ** FMOD Ex Audio
#------------------------------------------------------------------------------
#  Script by            :   Hiretsukan (Kevin Gadd)
#                           janus@luminance.org
#  Modified by:         :   RPG/Cowlol (Firas Assad)
#                           ArePeeGee (AIM name)
#  Last Update          :   September 23rd, 2008
#  Version              :   1.5
#------------------------------------------------------------------------------
# Usage:
#
# You need to copy the file fmodex.dll to your game folder (folder where
# your Game.exe and project file are). I've provided the DLL with the
# demo, and you can also get the latest version from FMOD's official
# website (http://www.fmod.org/index.php/download).
#
# You can access the FMod module also via script for more options, such as
# setting loop points (FMod.bgm_set_loop_points(first, second) in
# milliseconds) and getting current BGS position (FMod.bgs_position) to
# name a few.
#------------------------------------------------------------------------------
# Version Info:
#   - Version 1.5:
#       - Made the Volume and Pitch paramters to Audio ME/SE playing
#         methods optional. (Thanks panchokoster!)
#       - Script now uses FMOD's software mixer instead of hardware
#         acceleration. This solves issues with certain sound cards.
#       - A message is now displayed when a file isn't found, instead
#         of just throwing the error number.
#       - Added an independent thread to handle updating Audio module,
#         instead of calling it in $game_system#update. This should
#         ensure that it's called in all scenes. (Thanks Zeriab!)
#       - Updated fading calculations to depend on seconds instead
#         of game frames.
#   - Version 1.4:
#       - Fixed a bug where file isn't found if RTP path doesn't end
#         with a backslash (thanks Atoa!).
#       - Added BGM fading in after a ME is done playing to mimic
#         original Audio class behavior, the volume increment when
#         fading is specified by constant Audio::BGM_FADE_IN_INCREMENT.
#       - Several minor bug fixes and minor behavior changes relating
#         to fading out and stopping sounds.
#   - Version 1.3:
#       - Fixed a bug with ME fading out.
#       - Added methods to get BGM and BGS length.
#       - Providing -1 as loop end point to set_loop_points methods
#         makes the sound file's end the loop end point.
#       - Changed implementation of set_loop_points a bit.
#       - Position of BGM/BGS to be played after fading is now
#         remembered instead of starting all over.
#   - Version 1.2:
#       - Fully documented the script, and fixed some bugs.
#       - Completely rewrote Audio module, allowing FMOD to handle
#         BGMs, BGSs, MEs, and SEs except of just BGMs.
#       - Fixed RTP reading to use registry instead of special files..
#   - Version 1.1:
#       - Added position tracking and adjusting.
#       - Added loop point support.
#       - Implemented BGM fading.
#   - Version 1.0:
#       - Hiretsukan (Kevin Gadd)'s initial release.
#------------------------------------------------------------------------------
# Known bugs:
#
#   - MIDI abrupt start when seeking or restoring from position
#   - Found a bug or have some ideas for the next version? Please tell me!
#------------------------------------------------------------------------------
# Terms of Use:
#
#   Use of this script is subject to the permissive BSD-like license below.
#   That basically means you could use it in any way you like as long
#   as you keep the following copyright and license unchanged and available,
#   and don't use name of copyright holder to promote products based on
#   this software. Note, however, that this license only applies to the
#   script, and not to the FMOD library. For more information about FMOD
#   licenses consult FMOD website: http://www.fmod.org/index.php/sales
#   It's free for non-commercial use, and they provide several types
#   of licenses for different types of developers.
#
# Copyright (c) 2005, Kevin Gadd
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
#     * Redistributions of source code must retain the above copyright
#       notice, this list of conditions and the following disclaimer.
#     * Redistributions in binary form must reproduce the above copyright
#       notice, this list of conditions and the following disclaimer in the
#       documentation and/or other materials provided with the distribution.
#     * The name of the contributors may not be used to endorse or promote 
#       products derived from this software without specific prior written 
#       permission.
#
# THIS SOFTWARE IS PROVIDED BY Kevin Gadd ''AS IS'' AND ANY
# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
# DISCLAIMED. IN NO EVENT SHALL Kevin Gadd BE LIABLE FOR ANY
# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#==============================================================================

#Codename: apu

($imported ||= {})[:mikb89_apu_fmod] = true

# License:
# - You can ask me to include support for other scripts as long as these scripts
#   use the $imported[script] = true;
# - You can modify and even repost my scripts, after having received a response
#   by me. For reposting it, anyway, you must have done heavy edit or porting,
#   you can't do a post with the script as is;
# - You can use my scripts for whatever you want, from free to open to
#   commercial games. I'd appreciate by the way if you let me know about what
#   you're doing;
# - You must credit me, if you use this script or part of it.

#==============================================================================
# ** FModEx
#------------------------------------------------------------------------------
#  FMOD Ex binding by Kevin Gadd (janus@luminance.org)
#==============================================================================

module FModEx
 #--------------------------------------------------------------------------
 # * Constants
 #--------------------------------------------------------------------------
 # FMOD_INITFLAGS flags
 FMOD_INIT_NORMAL = 0
 # FMOD_RESULT flags
 FMOD_OK = 0
 FMOD_ERR_CHANNEL_STOLEN = 11
 FMOD_ERR_FILE_NOT_FOUND = 23
 FMOD_ERR_INVALID_HANDLE = 36
 # FMOD_MODE flags
 FMOD_DEFAULT = 0
 FMOD_LOOP_OFF = 1
 FMOD_LOOP_NORMAL = 2
 FMOD_LOOP_BIDI = 4
 FMOD_LOOP_BITMASK = 7
 FMOD_2D = 8
 FMOD_3D = 16
 FMOD_HARDWARE = 32
 FMOD_SOFTWARE = 64
 FMOD_CREATESTREAM = 128
 FMOD_CREATESAMPLE = 256
 FMOD_OPENUSER = 512
 FMOD_OPENMEMORY = 1024
 FMOD_OPENRAW = 2048
 FMOD_OPENONLY = 4096
 FMOD_ACCURATETIME = 8192
 FMOD_MPEGSEARCH = 16384
 FMOD_NONBLOCKING = 32768
 FMOD_UNIQUE = 65536
 # The default mode that the script uses
 FMOD_DEFAULT_SOFTWARWE = FMOD_LOOP_OFF | FMOD_2D | FMOD_SOFTWARE
 # FMOD_CHANNELINDEX flags
 FMOD_CHANNEL_FREE = -1
 FMOD_CHANNEL_REUSE = -2
 # FMOD_TIMEUNIT_flags
 FMOD_TIMEUNIT_MS = 1
 FMOD_TIMEUNIT_PCM = 2
 # The default time unit the script uses
 FMOD_DEFAULT_UNIT = FMOD_TIMEUNIT_MS
 # Types supported by FMOD Ex
 FMOD_FILE_TYPES = ['ogg', 'aac', 'wma', 'mp3', 'wav', 'it', 'xm', 'mod', 's3m', 'mid', 'midi']
 #add
 FMOD_DSP_TYPES = ["UNKNOWN", "MIXER", "OSCILLATOR", "LOWPASS", "ITLOWPASS",
                   "HIGHPASS", "ECHO", "FLANGE", "DISTORTION", "NORMALIZE",
                   "PARAMEQ", "PITCHSHIFT", "CHORUS", "VSTPLUGIN",
                   "WINAMPPLUGIN", "ITECHO", "COMPRESSOR", "SFXREVERB",
                   "LOWPASS_SIMPLE", "DELAY", "TREMOLO", "LADSPAPLUGIN",
                   "HIGHPASS_SIMPLE"]

 #============================================================================
 # ** DLL
 #----------------------------------------------------------------------------
 #  A class that manages importing functions from the DLL
 #============================================================================

 class DLL
   #--------------------------------------------------------------------------
   # * Public Instance Variables
   #--------------------------------------------------------------------------
   attr_accessor :filename           # DLL file name for instance    
   attr_accessor :functions          # hash of functions imported (by name)
   #--------------------------------------------------------------------------
   # * Object Initialization
   #     filename  : Name of the DLL
   #--------------------------------------------------------------------------
   def initialize(filename = 'System/fmodex.dll')
     @@filename = filename
     @@functions = {}
     @handle = 0            # Handle to the DLL
     # Load specified library into the address space of game process
     w32_LL = Win32API.new('kernel32.dll', 'LoadLibrary', 'p', 'l')
     @handle = w32_LL.call(filename)
     # System functions:
     self.import('System_Create', 'p')
     self.import('System_Init', 'llll')
     self.import('System_Close', 'l')
     self.import('System_Release', 'l')
     self.import('System_CreateSound', 'lpllp')
     self.import('System_CreateStream', 'lpllp')
     self.import('System_PlaySound', 'llllp')
     #add
     self.import('System_CreateDSPByType', 'llp')
     # Sound functions:
     self.import('Sound_Release', 'l')
     self.import('Sound_GetMode', 'lp')
     self.import('Sound_SetMode', 'll')
     self.import('Sound_SetLoopPoints', 'lllll')
     self.import('Sound_GetLength', 'lpl')
     # Channel functions:
     self.import('Channel_Stop', 'l')
     self.import('Channel_IsPlaying', 'lp')
     self.import('Channel_GetPaused', 'lp')
     self.import('Channel_SetPaused', 'll')
     self.import('Channel_GetVolume', 'lp')
     self.import('Channel_SetVolume', 'll')
     self.import('Channel_GetPan', 'lp')
     self.import('Channel_SetPan', 'll')
     self.import('Channel_GetFrequency', 'lp')
     self.import('Channel_SetFrequency', 'll')
     self.import('Channel_GetPosition', 'lpl')
     self.import('Channel_SetPosition', 'lll')
     #add
     self.import('Channel_SetMute', 'll')
     self.import('Channel_AddDSP', 'llp')
#~       # Channel group functions:
#~       self.import('ChannelGroup_SetMute', 'll')
     #add
     # DSP functions:
     self.import('DSP_SetParameter', 'lll')
     self.import('DSP_Release', 'l')
     self.import('DSP_Remove', 'l')
     self.import('DSP_GetNumParameters', 'lp')
     self.import('DSP_GetParameter', 'llppl')
     self.import('DSP_GetType', 'lp')
   end
   #--------------------------------------------------------------------------
   # * Create a Win32API Object And Add it to Hashtable
   #     name      : Function name
   #     args      : Argument types (p = pointer, l = int, v = void)
   #     returnType: Type of value returned by function
   #--------------------------------------------------------------------------
   def import(name, args = '', returnType = 'l')
     @@functions[name] = Win32API.new(@@filename, 'FMOD_' + name, args, returnType)
   end
   #--------------------------------------------------------------------------
   # * Get Function by Name
   #     key       : Function name
   #--------------------------------------------------------------------------
   def [](key)
     return @@functions[key]
   end
   #--------------------------------------------------------------------------
   # * Call a Function With Passed Arguments
   #     name      : Function name
   #     args      : Argument to function
   #--------------------------------------------------------------------------
   def invoke(name, *args)
     fn = @@functions[name]
     raise "function not imported: #{name}" if fn.nil?
     result = fn.call(*args)
     unless result == FMOD_OK or result == FMOD_ERR_CHANNEL_STOLEN or
       result == FMOD_ERR_FILE_NOT_FOUND
       raise "FMOD Ex returned error #{result}"
     end
     return result
   end
   #--------------------------------------------------------------------------
   # * Store Float as Binary Int Because Floats Can't be Passed Directly
   #     f         : Float to convert
   #--------------------------------------------------------------------------
   def convertFloat(f)
     # First pack the float in a string as a native binary float
     temp = [f].pack('f')
     # Then unpack the native binary float as an integer
     return unpackInt(temp)
   end
   #--------------------------------------------------------------------------
   # * Unpack Binary Data to Integer
   #     s         : String containing binary data
   #--------------------------------------------------------------------------
   def unpackInt(s)
     return s.unpack('l')[0]
   end
   #--------------------------------------------------------------------------
   # * Unpack Binary Data to Float
   #     s         : String containing binary data
   #--------------------------------------------------------------------------
   def unpackFloat(s)
     return s.unpack('f')[0]
   end
   #--------------------------------------------------------------------------
   # * Unpack Binary Data to Boolean
   #     s         : String containing binary data
   #--------------------------------------------------------------------------
   def unpackBool(s)
     return s.unpack('l')[0] != 0
   end
 end

 #============================================================================
 # ** System
 #----------------------------------------------------------------------------
 #  A class that manages an instance of FMOD::System
 #============================================================================

 class System
   #--------------------------------------------------------------------------
   # * Public Instance Variables
   #-------------------------------------------------------------------------- 
   attr_accessor :fmod               # Instance of DLL class (fmodex.dll)
   attr_accessor :handle             # Handle (pointer) to System object
   attr_accessor :maxChannels        # Maximum number of channels
   #--------------------------------------------------------------------------
   # * Object Initialization
   #     fmod            : An instance of DLL class
   #     maxChannels     : Maximum number of used channels
   #     flags           : FMOD_INITFLAGS
   #     extraDriverData : Driver specific data
   #--------------------------------------------------------------------------
   def initialize(theDLL, maxChannels = 32, flags = FMOD_INIT_NORMAL, extraDriverData = 0)
     @fmod = theDLL
     @maxChannels = maxChannels
     # Create and initialize FMOD::System
     temp = 0.chr * 4
     @fmod.invoke('System_Create', temp)
     @handle = @fmod.unpackInt(temp)
     @fmod.invoke('System_Init', @handle, maxChannels, flags, extraDriverData)
   end
   #--------------------------------------------------------------------------
   # * Create FMOD::DSP (fully loaded into memory by default)
   #     type            : Type of the DSP
   #--------------------------------------------------------------------------
   def createDSPByType(type)
     temp = 0.chr * 4
     @fmod.invoke('System_CreateDSPByType', @handle, type, temp)
     newDSP = DSP.new(self, @fmod.unpackInt(temp))
     return newDSP
   end
   #--------------------------------------------------------------------------
   # * Create FMOD::Sound (fully loaded into memory by default)
   #     filename        : Name of file to open
   #     mode            : FMOD_MODE flags
   #--------------------------------------------------------------------------
   def createSound(filename, mode = FMOD_DEFAULT_SOFTWARWE)
     # Create sound and return it
     temp = 0.chr * 4
     result = @fmod.invoke('System_CreateSound', @handle, filename, mode, 0, temp)
     raise "File not found: \"#{filename}\"" if result == FMOD_ERR_FILE_NOT_FOUND
     newSound = Sound.new(self, @fmod.unpackInt(temp))
     return newSound
   end
   #--------------------------------------------------------------------------
   # * Create Streamed FMOD::Sound (chunks loaded on demand)
   #     filename        : Name of file to open
   #     mode            : FMOD_MODE flags
   #--------------------------------------------------------------------------
   def createStream(filename, mode = FMOD_DEFAULT_SOFTWARWE)
     # Create sound and return it
     temp = 0.chr * 4
     result = @fmod.invoke('System_CreateStream', @handle, filename, mode, 0, temp)
     raise "File not found: \"#{filename}\"" if result == FMOD_ERR_FILE_NOT_FOUND
     newSound = Sound.new(self, @fmod.unpackInt(temp))
     return newSound
   end
   #--------------------------------------------------------------------------
   # * Close And Release System
   #--------------------------------------------------------------------------
   def dispose
     if (@handle > 0)
       @fmod.invoke('System_Close', @handle)
       @fmod.invoke('System_Release', @handle)
       @handle = 0
     end
     @fmod = nil
   end
 end

 #============================================================================
 # ** Sound
 #----------------------------------------------------------------------------
 #  A class that manages an instance of FMOD::Sound
 #============================================================================

 class Sound
   #--------------------------------------------------------------------------
   # * Public Instance Variables
   #-------------------------------------------------------------------------- 
   attr_accessor :system             # System that created this Sound
   attr_accessor :fmod               # Instance of DLL class (fmodex.dll)
   attr_accessor :handle             # Handle (pointer) to Sound object
   #--------------------------------------------------------------------------
   # * Object Initialization
   #     theSystem       : The System that created this Sound object
   #     handle          : Handle to the FMOD::Sound object
   #--------------------------------------------------------------------------
   def initialize(theSystem, theHandle)
     @system = theSystem
     @fmod = theSystem.fmod
     @handle = theHandle
   end
   #--------------------------------------------------------------------------
   # * Play Sound
   #     paused          : Start paused?
   #     channel         : Channel allocated to sound (nil for automatic)
   #--------------------------------------------------------------------------
   def play(paused = false, channel = nil)
     # If channel wasn't specified, let FMOD pick a free one,
     # otherwise use the passed channel (id from 0 to maxChannels)
     unless channel
       temp = 0.chr * 4
     else
       temp = [channel].pack('l')
     end
     @fmod.invoke('System_PlaySound', @system.handle, 
               (channel == nil) ? FMOD_CHANNEL_FREE : FMOD_CHANNEL_REUSE, 
               @handle,
               (paused == true) ? 1 : 0, 
               temp)
     theChannel = @fmod.unpackInt(temp)
     # Create a Channel object based on returned channel
     newChannel = Channel.new(self, theChannel)
     return newChannel
   end
   #--------------------------------------------------------------------------
   # * Get FMOD_MODE Bits
   #--------------------------------------------------------------------------
   def mode
     temp = 0.chr * 4
     @fmod.invoke('Sound_GetMode', @handle, temp)
     return @fmod.unpackInt(temp)
   end
   #--------------------------------------------------------------------------
   # * Set FMOD_MODE Bits
   #--------------------------------------------------------------------------
   def mode=(newMode)
     @fmod.invoke('Sound_SetMode', @handle, newMode)
   end
   #--------------------------------------------------------------------------
   # * Get FMOD_LOOP_MODE
   #--------------------------------------------------------------------------  
   def loopMode
     temp = 0.chr * 4
     @fmod.invoke('Sound_GetMode', @handle, temp)
     return @fmod.unpackInt(temp) & FMOD_LOOP_BITMASK
   end
   #--------------------------------------------------------------------------
   # * Set FMOD_LOOP_MODE
   #--------------------------------------------------------------------------  
   def loopMode=(newMode)
     @fmod.invoke('Sound_SetMode', @handle, (self.mode & ~FMOD_LOOP_BITMASK) | newMode)
   end
   #--------------------------------------------------------------------------
   # * Return Sound Length
   #-------------------------------------------------------------------------- 
   def length(unit = FMOD_DEFAULT_UNIT)
     temp = 0.chr * 4
     @fmod.invoke('Sound_GetLength', @handle, temp, unit)
     return @fmod.unpackInt(temp)
   end
   #--------------------------------------------------------------------------
   # * Set Loop Points
   #     first           : Loop start point in milliseconds
   #     second          : Loop end point in milliseconds
   #     unit            : FMOD_TIMEUNIT for points
   #--------------------------------------------------------------------------    
   def setLoopPoints(first, second, unit = FMOD_DEFAULT_UNIT)
     @fmod.invoke('Sound_SetLoopPoints', @handle, first, unit, second, unit)
   end
   #--------------------------------------------------------------------------
   # * Release Sound
   #-------------------------------------------------------------------------- 
   def dispose
     if (@handle > 0)
       @fmod.invoke('Sound_Release', @handle)
       @handle = 0
     end
     @fmod = nil
     @system = nil
   end
 end

 #============================================================================
 # ** DSP (add)
 #----------------------------------------------------------------------------
 #  A class that manages an instance of FMOD::DSP
 #============================================================================

 class DSP
   #--------------------------------------------------------------------------
   # * Public Instance Variables
   #--------------------------------------------------------------------------
   attr_accessor :system             # System that created this DSP
   attr_accessor :fmod               # Instance of DLL class (fmodex.dll)
   attr_accessor :handle             # Handle (pointer) to DSP object
   #--------------------------------------------------------------------------
   # * Object Initialization
   #     theSystem       : The System that created this DSP object
   #     handle          : Handle to the FMOD::DSP object
   #--------------------------------------------------------------------------
   def initialize(theSystem, theHandle)
     @system = theSystem
     @fmod = theSystem.fmod
     @handle = theHandle
   end
   #--------------------------------------------------------------------------
   # * Get the type of this DSP effect (0 -> FMOD_DSP_TYPE.size - 1)
   #--------------------------------------------------------------------------
   def getType
     temp = 0.chr * 4
     @fmod.invoke('DSP_GetType', @handle, temp) if (@handle > 0)
     return @fmod.unpackInt(temp)
   end
   #--------------------------------------------------------------------------
   # * Get the name of this DSP effect type
   #--------------------------------------------------------------------------
   def getTypeName
     return FModEx::FMOD_DSP_TYPES[getType]
   end
   #--------------------------------------------------------------------------
   # * Get the positive integer number of parameters this DSP type supports
   #--------------------------------------------------------------------------
   def getNumParameters
     temp = 0.chr * 4
     @fmod.invoke('DSP_GetNumParameters', @handle, temp) if (@handle > 0)
     return @fmod.unpackInt(temp)
   end
   #--------------------------------------------------------------------------
   # * Get the float value of the specified parameter
   #--------------------------------------------------------------------------
   def getParameter(which = 0)
     temp = 0.chr * 4
     tempstr = 0.chr * 256
     value = -1
     @fmod.invoke('DSP_GetParameter', @handle, which, temp, tempstr, value) if (@handle > 0)
     return @fmod.unpackFloat(temp)
   end
   #--------------------------------------------------------------------------
   # * Set the value for a parameter
   #     param           : The ID of the parameter
   #     value           : The float value to set
   #--------------------------------------------------------------------------
   def setParameter(param, value)
     if param >= 0
       @fmod.invoke('DSP_SetParameter', @handle, param, @fmod.convertFloat(value)) if (@handle > 0)
     end
   end
   #--------------------------------------------------------------------------
   # * Remove DSP effect
   #--------------------------------------------------------------------------
   def remove
     if (@handle > 0)
       @fmod.invoke('DSP_Remove', @handle)
       dispose
     end
   end
   #--------------------------------------------------------------------------
   # * Release DSP
   #--------------------------------------------------------------------------
   def dispose
     if (@handle > 0)
       @fmod.invoke('DSP_Release', @handle)
       @handle = 0
     end
     @fmod = nil
     @system = nil
   end
 end

 #============================================================================
 # ** Channel
 #----------------------------------------------------------------------------
 #  A class that represents an FMOD::Channel
 #============================================================================

 class Channel
   #--------------------------------------------------------------------------
   # * Public Instance Variables
   #-------------------------------------------------------------------------- 
   attr_accessor :system             # System that created the Sound
   attr_accessor :sound              # Sound using the Channel
   attr_accessor :fmod               # Instance of DLL class (fmodex.dll)
   attr_accessor :handle             # Handle (pointer) to Sound object
   attr_accessor :dsps               # Array of DSP effects
   #--------------------------------------------------------------------------
   # * Object Initialization
   #     theSound        : The Sound using this Channel object
   #     handle          : Handle to the FMOD::Channel object
   #--------------------------------------------------------------------------
   def initialize(theSound, theHandle)
     @sound = theSound
     @system = theSound.system
     @fmod = theSound.system.fmod
     @handle = theHandle
     @dsps = []
   end
   #--------------------------------------------------------------------------
   # * Stop Channel and Make it Available for Other Sounds
   #--------------------------------------------------------------------------
   def stop
     @fmod.invoke('Channel_Stop', @handle)
   end
   #--------------------------------------------------------------------------
   # * Is the Channel Handle Valid?
   #--------------------------------------------------------------------------
   def valid?
     temp = 0.chr * 4
     begin
       result = @fmod.invoke('Channel_IsPlaying', @handle, temp)
     rescue
       if (result == FMOD_ERR_INVALID_HANDLE)
         return false
       else
         raise
       end
     end
     # If we get here then it's valid
     return true
   end
   #--------------------------------------------------------------------------
   # * Is the Channel Playing?
   #--------------------------------------------------------------------------
   def playing?
     temp = 0.chr * 4
     @fmod.invoke('Channel_IsPlaying', @handle, temp)
     return @fmod.unpackBool(temp)
   end
   #--------------------------------------------------------------------------
   # * Get Channel Volume Level (0.0 -> 1.0)
   #--------------------------------------------------------------------------
   def volume
     temp = 0.chr * 4
     @fmod.invoke('Channel_GetVolume', @handle, temp)
     return @fmod.unpackFloat(temp)
   end
   #--------------------------------------------------------------------------
   # * Set Channel Volume Level (0.0 -> 1.0)
   #--------------------------------------------------------------------------
   def volume=(newVolume)
     @fmod.invoke('Channel_SetVolume', @handle, @fmod.convertFloat(newVolume))
   end
   #--------------------------------------------------------------------------
   # * Set Channel Mute
   #--------------------------------------------------------------------------
   def mute
     @fmod.invoke('Channel_SetMute', @handle, 1)
   end
   #--------------------------------------------------------------------------
   # * Set Channel Unmute
   #--------------------------------------------------------------------------
   def unmute
     @fmod.invoke('Channel_SetMute', @handle, 0)
   end
   #--------------------------------------------------------------------------
   # * Get Channel Pan Position (-1.0 -> 1.0)
   #--------------------------------------------------------------------------
   def pan
     temp = 0.chr * 4
     @fmod.invoke('Channel_GetPan', @handle, temp)
     return @fmod.unpackFloat(temp)
   end
   #--------------------------------------------------------------------------
   # * Set Channel Pan Position (-1.0 -> 1.0)
   #--------------------------------------------------------------------------
   def pan=(newPan)
     @fmod.invoke('Channel_SetPan', @handle, @fmod.convertFloat(newPan))
   end
   #--------------------------------------------------------------------------
   # * Get Channel Frequency in HZ (Speed/Pitch)
   #--------------------------------------------------------------------------
   def frequency
     temp = 0.chr * 4
     @fmod.invoke('Channel_GetFrequency', @handle, temp)
     return @fmod.unpackFloat(temp)
   end
   #--------------------------------------------------------------------------
   # * Set Channel Frequency in HZ (Speed/Pitch)
   #--------------------------------------------------------------------------
   def frequency=(newFrequency)
     @fmod.invoke('Channel_SetFrequency', @handle, @fmod.convertFloat(newFrequency))
   end
   #--------------------------------------------------------------------------
   # * Is Channel Paused?
   #--------------------------------------------------------------------------
   def paused
     temp = 0.chr * 4
     @fmod.invoke('Channel_GetPaused', @handle, temp)
     return @fmod.unpackBool(temp)
   end
   #--------------------------------------------------------------------------
   # * Pause Channel
   #--------------------------------------------------------------------------
   def paused=(newPaused)
     @fmod.invoke('Channel_SetPaused', @handle, (newPaused == true) ? 1 : 0)
   end
   #--------------------------------------------------------------------------
   # * Get Current Playback Position
   #     unit            : FMOD_TIMEUNIT to return position in
   #--------------------------------------------------------------------------   
   def position(unit = FMOD_DEFAULT_UNIT)
     temp = 0.chr * 4
     @fmod.invoke('Channel_GetPosition', @handle, temp, unit)
     return @fmod.unpackInt(temp)
   end
   #--------------------------------------------------------------------------
   # * Set Current Playback Position
   #     newPosition     : New playback position
   #     unit            : FMOD_TIMEUNIT to use when setting position
   #--------------------------------------------------------------------------    
   def position=(newPosition, unit = FMOD_DEFAULT_UNIT)
     @fmod.invoke('Channel_SetPosition', @handle, newPosition, unit)
   end
   #--------------------------------------------------------------------------
   # * Add a DSP by type
   #     type            : Type of DSP effect
   #--------------------------------------------------------------------------    
   def addDSP(type)
     dsp = @system.createDSPByType(type)
     @fmod.invoke('Channel_AddDSP', @handle, dsp.handle, nil)
     @dsps << dsp
     return @dsps.size - 1
   end
   #--------------------------------------------------------------------------
   # * Remove a DSP
   #     id              : The index of the DSP effect
   #--------------------------------------------------------------------------    
   def removeDSP(id)
     return false if @dsps.size <= id
     dsp = @dsps[id]
     dsp.remove
     @dsps.delete_at(id)
     return @dsps.compact! != nil
   end
   #--------------------------------------------------------------------------
   # * Get a DSP for settings
   #     id              : The index of the DSP effect
   #--------------------------------------------------------------------------  
   def DSP(id)
     return @dsps[id]
   end
   #--------------------------------------------------------------------------
   # * Dispose of Channel
   #--------------------------------------------------------------------------  
   def dispose
     for dsp in @dsps
       dsp.dispose
     end
     @handle = 0
     @sound = nil
     @system = nil
     @fmod = nil
   end
 end

end

#==============================================================================
# ** FMod
#------------------------------------------------------------------------------
#  A higher level module to access FMOD Ex
#==============================================================================

module FMod

 #============================================================================
 # ** SoundFile
 #----------------------------------------------------------------------------
 #  Represents a Sound file (BGM, BGS, SE, etc.) and associated Channel
 #============================================================================

 class SoundFile
   #--------------------------------------------------------------------------
   # * Public Instance Variables
   #--------------------------------------------------------------------------
   attr_accessor :name                     # File name
   attr_accessor :sound                    # FModEx::Sound object
   attr_accessor :channel                  # Channel playing sound
   attr_accessor :volume                   # Volume in RPG::AudioFile format
   attr_accessor :pitch                    # Pitch in RPG::AudioFile format
   attr_accessor :looping                  # Sound loops
   attr_accessor :streaming                # Sound is streamed
   attr_accessor :length                   # Sound length in milliseconds
   #--------------------------------------------------------------------------
   # * Object Initialization
   #--------------------------------------------------------------------------
   def initialize(name, sound, channel, volume, pitch, looping, streaming, length)
     @name = name
     @sound = sound
     @channel = channel
     @volume = volume
     @pitch = pitch
     @looping = looping
     @streaming = streaming
     @length = length
   end
 end
 #--------------------------------------------------------------------------
 # * Instance Variables
 #--------------------------------------------------------------------------
 @fmod_dll = FModEx::DLL.new               # The FMOD Ex DLL
 @fmod = FModEx::System.new(@fmod_dll)     # The global System object
 @@fmod_bgm = []                             # Array of Sound Effects
 @@fmod_bgs = []                             # Array of Sound Effects
 @@fmod_me = []                             # Array of Sound Effects
 @@fmod_se = []                             # Array of Sound Effects
 @@rtp_folder = nil                         # Name of RTP folder
 #--------------------------------------------------------------------------
 # * Get Path of RTP Folder From Registry
 #-------------------------------------------------------------------------- 
 def self.getRTPFolder
   return @@rtp_folder if @@rtp_folder
   open_key = Win32API.new('advapi32.dll', 'RegOpenKeyExA', 'LPLLP', 'L')
   query_value = Win32API.new('advapi32.dll', 'RegQueryValueExA', 'LPLPPP', 'L')
   close_key = Win32API.new('advapi32', 'RegCloseKey', 'L', 'L')
   key = 0.chr * 4
   # Open a HKEY_LOCAL_MACHINE with KEY_READ attribute and save handle in key
   open_key.call(0x80000002, 'Software\Enterbrain\RGSS3\RTP', 0, 0x20019, key)
   key = @fmod_dll.unpackInt(key)
   type = 0.chr * 4
   size = 0.chr * 4
   # Read RTP folder to use from setting in Game.ini
   rtp = self.read_ini("RTP")
   # Query to get string size
   query_value.call(key, rtp, 0, type, 0, size)
   data = ' ' * @fmod_dll.unpackInt(size)
   # Query the string value itself using size
   query_value.call(key, rtp, 0, type, data, size)
   @@rtp_folder = data.chop
   close_key.call(key)
   # Convert the addres to the RGSS standard
   @@rtp_folder.gsub!(/\\/, "/")
   @@rtp_folder += "/" if @@rtp_folder[-1] != "/"
   return @@rtp_folder
 end
 #--------------------------------------------------------------------------
 # * Read data from ini file
 #     variable        : Data to read
 #     filename        : Name without extension
 #-------------------------------------------------------------------------- 
 def self.read_ini(variable,filename="Game")
   reg = /^#{variable}=(.*)$/
   File.foreach(filename+'.ini') { |line| break($1) if line =~ reg }
 end
 #--------------------------------------------------------------------------
 # * Return Proper File Name (With Extensions)
 #     name            : Name of the file
 #     extensions      : Extensions to add to file name
 #-------------------------------------------------------------------------- 
 def self.checkExtensions(name, extensions)
   if FileTest.exist?(name)
     return name
   end
   # Add extension if needed
   extensions.each do |ext|
     if FileTest.exist?(name + '.' + ext)
       return name + '.' + ext
     end
   end
   # File doesn't exist
   return name
 end
 #--------------------------------------------------------------------------
 # * Get Valid File Name
 #     name            : Name of the file
 #-------------------------------------------------------------------------- 
 def self.selectBGMFilename(name, likeRTP = true)
   return Dir.glob(name+'.*')[0] || Dir.glob(name)[0] ||
          Dir.glob(self.getRTPFolder+name+'.*')[0] ||
          Dir.glob(self.getRTPFolder+name)[0] if likeRTP
   # See if file exists in game folder
   localname = self.checkExtensions(name, FModEx::FMOD_FILE_TYPES)
   if FileTest.exist?(localname)
     return localname
   end
   # See if file exists in RTP
   commonname = self.checkExtensions(self.getRTPFolder + name, FModEx::FMOD_FILE_TYPES)
   if FileTest.exist?(commonname)
     return commonname
   end
   # An invalid name was provided
   raise name
 end
 #--------------------------------------------------------------------------
 # * Play a Sound File Then Return it
 #     name            : Name of the file
 #     volume          : Channel volume
 #     pitch           : Channel frequency
 #     position        : Starting position in milliseconds
 #     looping         : Does the sound loop?
 #     streaming       : Stream sound or load whole thing to memory?
 #-------------------------------------------------------------------------- 
 def self.play(name, volume, pitch, position, looping, streaming)
   # Get a valid file name
   filename = self.selectBGMFilename(name)
   # Create Sound or Stream and set initial values
   sound = streaming ? @fmod.createStream(filename) : @fmod.createSound(filename)
   sound.loopMode = looping ? FModEx::FMOD_LOOP_NORMAL : FModEx::FMOD_LOOP_OFF
   channel = sound.play
   volume = volume * 1.0
   pitch = pitch * 1.0
   file_length = sound.length(FModEx::FMOD_DEFAULT_UNIT)
   sound_file = SoundFile.new(filename, sound, channel, volume, 
                               pitch, looping, streaming, file_length)
   sound_file.channel.volume = volume / 100.0
   sound_file.channel.frequency = sound_file.channel.frequency * pitch / 100
   sound_file.channel.position = position
   self.play_operations(sound_file)
   return sound_file
 end
 #--------------------------------------------------------------------------
 # * Do something on new Sound File
 #-------------------------------------------------------------------------- 
 def self.play_operations(sound_file)
   # alias this if you want to do something on the newly played files 
 end
 #--------------------------------------------------------------------------
 # * Replay of Sound File
 #-------------------------------------------------------------------------- 
 def self.replay(sound_file, volume = 100, pitch = 100, position = 0, reset = false)
   self.set_volume(sound_file, volume)
   self.set_pitch(sound_file, pitch)
   self.set_position(sound_file, position) if position != 0 || (position == 0 && reset)
 end
 #--------------------------------------------------------------------------
 # * Stop and Dispose of Sound File
 #-------------------------------------------------------------------------- 
 def self.stop(sound_file)
   unless sound_file and sound_file.channel
     return
   end
   # Stop channel, then clear variables and dispose of bgm
   sound_file.channel.stop
   sound_file.channel = nil
   sound_file.sound.dispose
 end
 #--------------------------------------------------------------------------
 # * Return Length in Milliseconds
 #-------------------------------------------------------------------------- 
 def self.get_length(sound_file, unit = FModEx::FMOD_DEFAULT_UNIT)
   return sound_file.length(unit)
 end
 #--------------------------------------------------------------------------
 # * Check if Another Sound File is Playing
 #-------------------------------------------------------------------------- 
 def self.already_playing?(sound_file, name, position = 0)
   # Get a valid file name
   filename = self.selectBGMFilename(name)
   if (sound_file)
     # If the same sound file is already playing don't play it again
     if (sound_file.name == filename and position == 0)
       return true
     end
     # If another sound file is playing, stop it
     if sound_file.channel
       self.stop(sound_file)
     end
   end
   # No sound file is playing or it was already stopped
   return false
 end
 #--------------------------------------------------------------------------
 # * Check if this Sound File is Playing
 #-------------------------------------------------------------------------- 
 def self.playing_this?(sound_file, name)    
   if (sound_file)
     if (sound_file.name == name)
       return true
     end
   end
   return false
 end
 #--------------------------------------------------------------------------
 # * Check if Sound File is Playing
 #--------------------------------------------------------------------------  
 def self.playing?(sound_file)
   unless sound_file and sound_file.channel
     return false
   end
   return sound_file.channel.playing?
 end
 #--------------------------------------------------------------------------
 # * Get Current Sound File Playing Position
 #-------------------------------------------------------------------------- 
 def self.get_position(sound_file)
   unless sound_file and sound_file.channel
     return 0
   end
   return sound_file.channel.position
 end
 #--------------------------------------------------------------------------
 # * Seek to a New Sound File Playing Position
 #-------------------------------------------------------------------------- 
 def self.set_position(sound_file, new_pos)
   unless sound_file and sound_file.channel
     return
   end
   sound_file.channel.position = new_pos
 end
 #--------------------------------------------------------------------------
 # * Get Current Sound File Volume
 #-------------------------------------------------------------------------- 
 def self.get_volume(sound_file)
   unless sound_file
     return 0
   end
   return sound_file.volume
 end
 #--------------------------------------------------------------------------
 # * Set Sound File Volume
 #-------------------------------------------------------------------------- 
 def self.set_volume(sound_file, volume)
   unless sound_file and sound_file.channel
     return
   end
   sound_file.volume = volume * 1.0
   sound_file.channel.volume = volume / 100.0
 end
 #--------------------------------------------------------------------------
 # * Set Sound File Mute
 #-------------------------------------------------------------------------- 
 def self.set_mute(sound_file)
   unless sound_file and sound_file.channel
     return
   end
   sound_file.channel.mute
 end
 #--------------------------------------------------------------------------
 # * Set Sound File Unmute
 #-------------------------------------------------------------------------- 
 def self.set_unmute(sound_file)
   unless sound_file and sound_file.channel
     return
   end
   sound_file.channel.unmute
 end
 #--------------------------------------------------------------------------
 # * Get Current Sound File Pitch
 #-------------------------------------------------------------------------- 
 def self.get_pitch(sound_file)
   unless sound_file
     return 0
   end
   return sound_file.pitch
 end
 #--------------------------------------------------------------------------
 # * Set Sound File Pitch
 #-------------------------------------------------------------------------- 
 def self.set_pitch(sound_file, pitch)
   unless sound_file and sound_file.channel
     return
   end
   sound_file.pitch = pitch * 1.0
   sound_file.channel.frequency = sound_file.channel.frequency * pitch / 100.0
 end
 #--------------------------------------------------------------------------
 # * Get Current Sound File Pan
 #-------------------------------------------------------------------------- 
 def self.get_pan(sound_file)
   unless sound_file and sound_file.channel
     return 0
   end
   return sound_file.channel.pan
 end
 #--------------------------------------------------------------------------
 # * Set Sound File Pan
 #-------------------------------------------------------------------------- 
 def self.set_pan(sound_file, pan)
   unless sound_file and sound_file.channel
     return
   end
   sound_file.channel.pan = pan
 end
 #--------------------------------------------------------------------------
 # * Set Loop Points
 #     first           : Loop start point in milliseconds
 #     second          : Loop end point in milliseconds (-1 for file end)
 #     unit            : FMOD_TIMEUNIT for points
 #-------------------------------------------------------------------------- 
 def self.set_loop_points(sound_file, first, second, unit = FModEx::FMOD_DEFAULT_UNIT)
   unless sound_file and sound_file.channel
     return
   end
   # If second is -1 then set loop end to the file end
   if second == -1
     second = sound_file.length - 1
   end
   # Set loop points and reflush stream buffer
   sound_file.channel.sound.setLoopPoints(first, second, unit)
   sound_file.channel.position = sound_file.channel.position
   return sound_file
 end
 #--------------------------------------------------------------------------
 # * Play BGM (or ME)
 #     name            : Name of the file
 #     volume          : Channel volume
 #     pitch           : Channel frequency
 #     position        : Starting position in milliseconds
 #     looping         : Does the BGM loop?
 #-------------------------------------------------------------------------- 
 def self.bgm_play(name, volume, pitch, c, position = 0, looping = true)
   al_pl = self.already_playing?(@@fmod_bgm[c], name, position)
   self.bgm_set_volume(volume, c) if al_pl
   return if al_pl
   # Now play the new BGM as a stream
   @@fmod_bgm[c] = self.play(name, volume, pitch, position, looping, true)
 end
 #--------------------------------------------------------------------------
 # * Stop and Dispose of BGM
 #-------------------------------------------------------------------------- 
 def self.bgm_stop(c)
   self.stop(@@fmod_bgm[c])
   @@fmod_bgm[c] = nil
 end
 #--------------------------------------------------------------------------
 # * Return BGM Length in Milliseconds
 #-------------------------------------------------------------------------- 
 def self.bgm_length(c)
   self.get_length(@@fmod_bgm[c])
 end
 #--------------------------------------------------------------------------
 # * Check if a BGM is Playing
 #--------------------------------------------------------------------------  
 def self.bgm_playing?(c)
   return self.playing?(@@fmod_bgm[c])
 end
 #--------------------------------------------------------------------------
 # * Get Current BGM Playing Position
 #-------------------------------------------------------------------------- 
 def self.bgm_position(c)
   return self.get_position(@@fmod_bgm[c])
 end
 #--------------------------------------------------------------------------
 # * Seek to New BGM Playing Position
 #-------------------------------------------------------------------------- 
 def self.bgm_set_position(new_pos, c)
   self.set_position(@@fmod_bgm[c], new_pos)
 end
 #--------------------------------------------------------------------------
 # * Get Current BGM Volume
 #-------------------------------------------------------------------------- 
 def self.bgm_volume(c)
   return self.get_volume(@@fmod_bgm[c])
 end
 #--------------------------------------------------------------------------
 # * Set BGM Volume
 #-------------------------------------------------------------------------- 
 def self.bgm_set_volume(volume, c)
   self.set_volume(@@fmod_bgm[c], volume)
 end
 #--------------------------------------------------------------------------
 # * Set BGM Mute
 #-------------------------------------------------------------------------- 
 def self.bgm_set_mute(c)
   self.set_mute(@@fmod_bgm[c])
 end
 #--------------------------------------------------------------------------
 # * Set BGM Unmute
 #-------------------------------------------------------------------------- 
 def self.bgm_set_unmute(c)
   self.set_unmute(@@fmod_bgm[c])
 end
 #--------------------------------------------------------------------------
 # * Get Current BGM Pan
 #-------------------------------------------------------------------------- 
 def self.bgm_pan(c)
   return self.get_pan(@@fmod_bgm[c])
 end
 #--------------------------------------------------------------------------
 # * Set BGM Pan
 #-------------------------------------------------------------------------- 
 def self.bgm_set_pan(pan, c)
   self.set_pan(@@fmod_bgm[c], pan)
 end
 #--------------------------------------------------------------------------
 # * Set ME Volume
 #-------------------------------------------------------------------------- 
 def self.me_set_volume(volume, c)
   self.set_volume(@@fmod_me[c], volume)
 end
 #--------------------------------------------------------------------------
 # * Set ME Mute
 #-------------------------------------------------------------------------- 
 def self.me_set_mute(c)
   self.set_mute(@@fmod_me[c])
 end
 #--------------------------------------------------------------------------
 # * Set ME Unmute
 #-------------------------------------------------------------------------- 
 def self.me_set_unmute(c)
   self.set_unmute(@@fmod_me[c])
 end
 #--------------------------------------------------------------------------
 # * Get Current ME Pan
 #-------------------------------------------------------------------------- 
 def self.me_pan(c)
   return self.get_pan(@@fmod_me[c])
 end
 #--------------------------------------------------------------------------
 # * Set ME Pan
 #-------------------------------------------------------------------------- 
 def self.me_set_pan(pan, c)
   self.set_pan(@@fmod_me[c], pan)
 end
 #--------------------------------------------------------------------------
 # * Set Loop Points
 #     first           : Loop start point in milliseconds
 #     second          : Loop end point in milliseconds
 #     unit            : FMOD_TIMEUNIT for points
 #-------------------------------------------------------------------------- 
 def self.bgm_set_loop_points(first, second, c, unit = FModEx::FMOD_DEFAULT_UNIT)
   @@fmod_bgm[c] = self.set_loop_points(@@fmod_bgm[c], first, second, unit)
 end
 #--------------------------------------------------------------------------
 # * Play BGS
 #     name            : Name of the file
 #     volume          : Channel volume
 #     pitch           : Channel frequency
 #     position        : Starting position in milliseconds
 #     looping         : Does the BGS loop?
 #-------------------------------------------------------------------------- 
 def self.bgs_play(name, volume, pitch, c, position = 0, looping = true)
   al_pl = self.already_playing?(@@fmod_bgs[c], name, position)
   self.bgs_set_volume(volume, c) if al_pl
   return if al_pl
   # Now play the new BGS as a stream
   @@fmod_bgs[c] = self.play(name, volume, pitch, position, looping, true)
 end
 #--------------------------------------------------------------------------
 # * Stop and Dispose of BGS
 #-------------------------------------------------------------------------- 
 def self.bgs_stop(c)
   self.stop(@@fmod_bgs[c])
   @@fmod_bgs[c] = nil
 end
 #--------------------------------------------------------------------------
 # * Return BGS Length in Milliseconds
 #-------------------------------------------------------------------------- 
 def self.bgm_length(c)
   self.get_length(@@fmod_bgs[c])
 end
 #--------------------------------------------------------------------------
 # * Check if a BGS is Playing
 #--------------------------------------------------------------------------  
 def self.bgs_playing?(c)
   return self.playing?(@@fmod_bgs[c])
 end
 #--------------------------------------------------------------------------
 # * Get Current BGS Playing Position
 #-------------------------------------------------------------------------- 
 def self.bgs_position(c)
   return self.get_position(@@fmod_bgs[c])
 end
 #--------------------------------------------------------------------------
 # * Seek to New BGS Playing Position
 #-------------------------------------------------------------------------- 
 def self.bgs_set_position(new_pos, c)
   self.set_position(@@fmod_bgs[c], new_pos)
 end
 #--------------------------------------------------------------------------
 # * Get Current BGS Volume
 #-------------------------------------------------------------------------- 
 def self.bgs_volume(c)
   return self.get_volume(@@fmod_bgs[c])
 end
 #--------------------------------------------------------------------------
 # * Set BGS Volume
 #-------------------------------------------------------------------------- 
 def self.bgs_set_volume(volume, c)
   self.set_volume(@@fmod_bgs[c], volume)
 end
 #--------------------------------------------------------------------------
 # * Set BGS Mute
 #-------------------------------------------------------------------------- 
 def self.bgs_set_mute(c)
   self.set_mute(@@fmod_bgs[c])
 end
 #--------------------------------------------------------------------------
 # * Set BGS Unmute
 #-------------------------------------------------------------------------- 
 def self.bgs_set_unmute(c)
   self.set_unmute(@@fmod_bgs[c])
 end
 #--------------------------------------------------------------------------
 # * Get Current BGS Pan
 #-------------------------------------------------------------------------- 
 def self.bgs_pan(c)
   return self.get_pan(@@fmod_bgs[c])
 end
 #--------------------------------------------------------------------------
 # * Set BGS Pan
 #-------------------------------------------------------------------------- 
 def self.bgs_set_pan(pan, c)
   self.set_pan(@@fmod_bgs[c], pan)
 end
 #--------------------------------------------------------------------------
 # * Set Loop Points
 #     first           : Loop start point in milliseconds
 #     second          : Loop end point in milliseconds
 #     unit            : FMOD_TIMEUNIT for points
 #-------------------------------------------------------------------------- 
 def self.bgs_set_loop_points(first, second, c, unit = FModEx::FMOD_DEFAULT_UNIT)
   @@fmod_bgs[c] = self.set_loop_points(@@fmod_bgs[c], first, second, unit)
 end
 #--------------------------------------------------------------------------
 # * Play SE
 #     name            : Name of the file
 #     volume          : Channel volume
 #     pitch           : Channel frequency
 #-------------------------------------------------------------------------- 
 def self.se_play(name, volume, pitch, c)
   if (@@fmod_se[c] ||= []).size > @fmod.maxChannels
     se = @@fmod_se[c].shift
     self.stop(se)
   end
   # Load SE into memory and play it
   @@fmod_se[c] << last_se = self.play(name, volume, pitch, 0, false, false)
   if @@fmod_se.size > 1
     for dsp in @@fmod_se[c][0].channel.dsps
       n = self.addDSP(last_se, dsp.getType)
       if n >= 0
         for par in 0...dsp.getNumParameters
           last_se.channel.DSP(n).setParameter(par, dsp.getParameter(par))
         end
       end
     end
   end
 end
 #--------------------------------------------------------------------------
 # * Stop and Dispose of all SEs
 #-------------------------------------------------------------------------- 
 def self.se_stop(c)
   for se in (@@fmod_se[c] ||= [])
     self.stop(se)
   end
   @@fmod_se[c].clear
 end
 #--------------------------------------------------------------------------
 # * Set SE Volume
 #-------------------------------------------------------------------------- 
 def self.se_set_volume(volume, c)
   for se in (@@fmod_se[c] ||= [])
     self.set_volume(se, volume)
   end
 end
 #--------------------------------------------------------------------------
 # * Set SE Mute
 #-------------------------------------------------------------------------- 
 def self.se_set_mute(c)
   for se in (@@fmod_se[c] ||= [])
     self.set_mute(se)
   end
 end
 #--------------------------------------------------------------------------
 # * Set SE Unmute
 #-------------------------------------------------------------------------- 
 def self.se_set_unmute(c)
   for se in (@@fmod_se[c] ||= [])
     self.set_unmute(se)
   end
 end
 #--------------------------------------------------------------------------
 # * Get Pan of one of the Current SEs
 #-------------------------------------------------------------------------- 
 def self.se_pan(c, n)
   return self.get_pan(@@fmod_se[c][n])
 end
 #--------------------------------------------------------------------------
 # * Set Pan for one of the Current SEs
 #-------------------------------------------------------------------------- 
 def self.se_set_pan(pan, c, n)
   self.set_pan(@@fmod_se[c][n], pan)
 end
 #--------------------------------------------------------------------------
 # * Get Rid of Non-Playing SEs
 #--------------------------------------------------------------------------  
 def self.se_clean(c)
   for se in (@@fmod_se[c] ||= [])
     unless self.playing?(se)
       self.stop(se)
       @@fmod_se[c].delete(se)
     end
   end
 end
 #--------------------------------------------------------------------------
 # * Check if There's Some SE in SE Array
 #--------------------------------------------------------------------------  
 def self.se_list_empty?(c)
   return (@@fmod_se[c] ||= []).empty?
 end
 #--------------------------------------------------------------------------
 # * Dispose of Everything
 #--------------------------------------------------------------------------  
 def self.dispose
   self.stop_all
   @fmod.dispose
 end
 #--------------------------------------------------------------------------
 # * Stop Everything
 #--------------------------------------------------------------------------  
 def self.stop_all
   for c in 1...APU::MAX_CHANNELS
     self.bgm_stop(c)
     self.bgs_stop(c)
     self.se_stop(c)
   end
 end

 #==============================================================================
 # ** Audio
 #------------------------------------------------------------------------------
 #  The module that carries out music and sound processing.
 #==============================================================================

 module Audio
   #--------------------------------------------------------------------------
   # * Constants
   #--------------------------------------------------------------------------
   BGM_FADE_IN_INCREMENT = 5     # BGM volume incremented 0.2 seconds
   #--------------------------------------------------------------------------
   # * Instance Variables
   #--------------------------------------------------------------------------
   @@bgm_fading_out = []#false       # BGM started fading out
   @@bgm_fade_decrement = []#0.0     # BGM volume decremented each update
   @@bgs_fading_out = []#false       # BGS started fading out
   @@bgs_fade_decrement = []#0.0     # BGS volume decremented each update
   @@me_fading_out = []#false        # ME started fading out
   @@me_fade_decrement = []#0.0      # ME volume decremented each update
   @@me_playing = []#false           # Is some ME playing?
   @@playing_bgm = []#nil            # BGM currently being played
   @@next_bgm = []#nil               # The BGM to be played after fading out
   @@next_bgm_position = []#0        # Starting position of next bgm
   @@next_bgs = []#nil               # The BGS to be played after fading out
   @@next_bgs_position = []#0        # Starting position of next bgm
   @@next_me = []#nil                # The ME to be played after fading
   @@memorized_bgm = []
   @@memorized_bgm_position = []
   @@bgm_fading_in = []
   #--------------------------------------------------------------------------
   # * Starts BGM Playback
   #     name            : Name of the file
   #     volume          : Channel volume
   #     pitch           : Channel frequency
   #     position        : Starting position in milliseconds
   #-------------------------------------------------------------------------- 
   def Audio.bgm_play(filename, volume, pitch, position, c,
                       fade_in = false)
     if @@bgm_fading_out[c] and !fade_in
       @@next_bgm[c] = RPG::AudioFile.new(filename, volume, pitch)
       @@next_bgm_position[c] = position
       return
     end
     start_volume = volume
     if fade_in
       @@bgm_target_volume[c] = volume unless @@bgm_fading_in[c]
       @@bgm_fading_in[c] = true
       start_volume = 0
     end
     @@bgm_fading_out[c] = false
     # If a ME is playing we wait until it's over before playing BGM
     unless @@me_playing[c]
       FMod::bgm_play(filename, start_volume, pitch, c, position)
     end
     @@playing_bgm[c] = RPG::AudioFile.new(filename, volume, pitch)
     @@memorized_bgm[c] = @@playing_bgm[c]
     @@memorized_bgm_position[c] = position
   end
   #--------------------------------------------------------------------------
   # * Stops BGM Playback
   #-------------------------------------------------------------------------- 
   def Audio.bgm_stop(c)
     @@memorized_bgm[c] = nil
     @@playing_bgm[c] = nil
     @@bgm_fading_in[c] = false
     @@bgm_fading_out[c] = false
     # MEs are internally BGMs, but are stopped with me_stop instead
     if @@me_playing[c]
       return
     end
     FMod::bgm_stop(c)
   end
   #--------------------------------------------------------------------------
   # * Starts BGM fadeout.
   #     time            : Length of the fadeout in milliseconds.
   #-------------------------------------------------------------------------- 
   def Audio.bgm_fade(time, c)
     return if @@me_playing[c] or !FMod::bgm_playing?(c)
     @@bgm_fading_out[c] = true
     time = time / 1000
     @@bgm_fade_decrement[c] = FMod::bgm_volume(c) / (time * 10)
   end
   #--------------------------------------------------------------------------
   # * Get BGM Position
   #-------------------------------------------------------------------------- 
   def Audio.bgm_pos(c)
     FMod::bgm_position(c)
   end
   #--------------------------------------------------------------------------
   # * Starts BGS Playback
   #     name            : Name of the file
   #     volume          : Channel volume
   #     pitch           : Channel frequency
   #     position        : Starting position in milliseconds
   #-------------------------------------------------------------------------- 
   def Audio.bgs_play(filename, volume, pitch, position, c)
     if @@bgs_fading_out[c]
       @@next_bgs[c] = RPG::AudioFile.new(filename, volume, pitch)
       @@next_bgs_position[c] = position
       return
     end
     FMod::bgs_play(filename, volume, pitch, c, position)
   end
   #--------------------------------------------------------------------------
   # * Stops BGS Playback
   #-------------------------------------------------------------------------- 
   def Audio.bgs_stop(c)
     FMod::bgs_stop(c)
     @@bgs_fading_out[c] = false
   end
   #--------------------------------------------------------------------------
   # * Starts BGS fadeout.
   #     time            : Length of the fadeout in milliseconds.
   #-------------------------------------------------------------------------- 
   def Audio.bgs_fade(time, c)
     return unless FMod::bgs_playing?(c)
     @@bgs_fading_out[c] = true
     time = time / 1000
     @@bgs_fade_decrement[c] = FMod::bgs_volume(c) / (time * 10)
   end
   #--------------------------------------------------------------------------
   # * Get BGS Position
   #-------------------------------------------------------------------------- 
   def Audio.bgs_pos(c)
     FMod::bgs_position(c)
   end
   #--------------------------------------------------------------------------
   # * Starts ME Playback
   #     name            : Name of the file
   #     volume          : Channel volume
   #     pitch           : Channel frequency
   #-------------------------------------------------------------------------- 
   def Audio.me_play(filename, volume, pitch, c)
     if @@me_fading_out[c]
       @@next_me[c] = RPG::AudioFile.new(filename, volume, pitch)
       return
     end
     if @@bgm_fading_out[c]
       self.bgm_stop(c)
     end
     # Memorize playing bgm
     if @@playing_bgm[c] and !@@me_playing[c]
       bgm = @@playing_bgm[c]
       @@playing_bgm[c] = RPG::AudioFile.new(bgm.name, FMod::bgm_volume(c), bgm.pitch)
       @@memorized_bgm[c] = @@playing_bgm[c]
       @@memorized_bgm_position[c] = FMod::bgm_position(c)
     end
     @@me_playing[c] = true
     FMod::bgm_play(filename, volume, pitch, c, 0, false)
   end
   #--------------------------------------------------------------------------
   # * Stops ME Playback
   #-------------------------------------------------------------------------- 
   def Audio.me_stop(c)
     return unless @@me_playing[c]
     @@me_playing[c] = false
     @@me_fading_out[c] = false
     # Play memorized bgm, fading in
     if @@memorized_bgm[c] and !@@bgm_fading_out[c]
       bgm = @@memorized_bgm[c]
       self.bgm_play(bgm.name, bgm.volume, bgm.pitch, @@memorized_bgm_position[c], true)
     else
       self.bgm_stop(c)
     end
   end
   #--------------------------------------------------------------------------
   # * Starts ME fadeout.
   #     time            : Length of the fadeout in milliseconds.
   #-------------------------------------------------------------------------- 
   def Audio.me_fade(time, c)
     return unless FMod::bgm_playing?(c)
     @@me_fading_out[c] = true
     time = time / 1000
     @@bgm_fade_decrement[c] = FMod::bgm_volume(c) / (time * 10)
   end
   #--------------------------------------------------------------------------
   # * Starts SE Playback
   #     name            : Name of the file
   #     volume          : Channel volume
   #     pitch           : Channel frequency
   #-------------------------------------------------------------------------- 
   def Audio.se_play(filename, volume, pitch, c) 
     FMod::se_play(filename, volume, pitch, c)
   end
   #--------------------------------------------------------------------------
   # * Stops SE Playback
   #-------------------------------------------------------------------------- 
   def Audio.se_stop(c)
     FMod::se_stop(c)
   end
   #--------------------------------------------------------------------------
   # * Check whether in F1 settings music and/or sounds are disabled
   #-------------------------------------------------------------------------- 
   def Audio.check_sound
     open_key = Win32API.new('advapi32.dll', 'RegOpenKeyExA', 'LPLLP', 'L')
     query_value = Win32API.new('advapi32.dll', 'RegQueryValueExA', 'LPLPPP', 'L')
     close_key = Win32API.new('advapi32', 'RegCloseKey', 'L', 'L')
     key = 0.chr * 4
     # Open a HKEY_CURRENT_USER with KEY_READ attribute and save handle in key
     open_key.call(0x80000001, 'Software\Enterbrain\RGSS3', 0, 0x20019, key)
     key = key.unpack('l')[0]
     type = 0.chr * 4
     size = 0.chr * 4
     # Query to get string size
     query_value.call(key, "PlayMusic", 0, type, 0, size)
     data = ' ' * size.unpack('l')[0]
     # Query the string value itself using size
     query_value.call(key, "PlayMusic", 0, type, data, size)
     pm = data[0].ord != 0
     # Query to get string size
     query_value.call(key, "PlaySound", 0, type, 0, size)
     data = ' ' * size.unpack('l')[0]
     # Query the string value itself using size
     query_value.call(key, "PlaySound", 0, type, data, size)
     ps = data[0].ord != 0
     close_key.call(key)
     if (@@last_music_play_state ||= !pm) != pm
       for c in 1...APU::MAX_CHANNELS
         FMod::bgm_set_mute(c) if !pm
         FMod::me_set_mute(c) if !pm
         FMod::bgm_set_unmute(c) if pm
         FMod::me_set_unmute(c) if pm
       end
       @@last_music_play_state = pm
     end
     if (@@last_sound_play_state ||= !ps) != ps
       for c in 1...APU::MAX_CHANNELS
         FMod::bgs_set_mute(c) if !ps
         FMod::se_set_mute(c) if !ps
         FMod::bgs_set_unmute(c) if ps
         FMod::se_set_unmute(c) if ps
       end
       @@last_sound_play_state = ps
     end
   end
   #--------------------------------------------------------------------------
   # * Update ME Playback, SE Disposal and Fading, Called Each Frame
   #-------------------------------------------------------------------------- 
   def Audio.update
     self.check_sound if APU::READ_F1_SETTINGS
     for c in 1...APU::MAX_CHANNELS
       # Stop ME when it's over (and continue playing BGM)
       if @@me_playing[c]
         unless FMod::bgm_playing?(c)
           self.me_stop(c)
         end
       end
       # Remove any finished SEs
       unless FMod::se_list_empty?(c)
         FMod::se_clean(c)
       end
       if @@bgm_fading_in[c]
         # Stop fading when target is reached, otherwise increase volume
         if FMod::bgm_volume(c) >= @@bgm_target_volume[c]
           @@bgm_fading_in[c] = false
         else
           current_volume = FMod::bgm_volume(c) + BGM_FADE_IN_INCREMENT
           FMod::bgm_set_volume(current_volume, c)
         end
       end
       if FMod::bgm_playing?(c) and @@bgm_fading_out[c] and 
           !@@me_playing[c]
         if FMod::bgm_volume(c) <= 0
           @@bgm_fading_out[c] = false
           self.bgm_stop(c)
           # If another BGM played while fading out, play it (most recent)
           if @@next_bgm[c]
             self.bgm_play(@@next_bgm[c].name, @@next_bgm[c].volume,
                           @@next_bgm[c].pitch, c, @@next_bgm_position[c])
             @@next_bgm[c] = nil
           end
         else
           current_volume = FMod::bgm_volume(c) - @@bgm_fade_decrement[c]
           FMod::bgm_set_volume(current_volume, c)
         end
       end
       if FMod::bgs_playing?(c) and @@bgs_fading_out[c]
         if FMod::bgs_volume(c) <= 0
           @@bgs_fading_out[c] = false
           self.bgs_stop(c)
           # If another BGS played while fading out, play it (most recent)
           if @@next_bgs[c]
             self.bgs_play(@@next_bgs[c].name, @@next_bgs[c].volume, 
                           @@next_bgs[c].pitch, c, @@next_bgs_position[c])
             @@next_bgs[c] = nil
           end
         else
           current_volume = FMod::bgs_volume(c) - @@bgs_fade_decrement[c]
           FMod::bgs_set_volume(current_volume, c)
         end
       end
       if FMod::bgm_playing?(c) and @@me_fading_out[c]
         if FMod::bgm_volume(c) <= 0
           # If another ME played while fading out, play it (most recent)
           if @@next_me[c]
             self.me_play(@@next_me[c].name, @@next_me[c].volume, @@next_me[c].pitch, c)
             @@next_me[c] = nil
           else
             @@me_fading_out[c] = false
             self.me_stop(c)
           end
         else
           current_volume = FMod::bgm_volume(c) - @@bgm_fade_decrement[c]
           FMod::bgm_set_volume(current_volume, c)
         end
       end
     end
   end
 end
end

# Addition to let the DSP effects work.
module FMod
 def self.addDSP(sound_file, type)
   return -1 if type <= 0
   unless sound_file and sound_file.channel
     return -1
   end
   return sound_file.channel.addDSP(type)
 end
 def self.bgm_addDSP(c, type)
   return nil if c <= 0
   return nil unless @@fmod_bgm[c]
   return @@fmod_bgm[c].channel.DSP(self.addDSP(@@fmod_bgm[c], type))
 end
 def self.bgs_addDSP(c, type)
   return nil if c <= 0
   return nil unless @@fmod_bgs[c]
   return @@fmod_bgs[c].channel.DSP(self.addDSP(@@fmod_bgs[c], type))
 end
 def self.me_addDSP(c, type)
   return nil if c <= 0
   return nil unless @@fmod_me[c]
   return @@fmod_me[c].channel.DSP(self.addDSP(@@fmod_me[c], type))
 end
 def self.se_total(c)
   return 0 if c <= 0
   (@@fmod_se[c] ||= []).size
 end
 def self.se_addDSP(n, c, type)
   return nil if c <= 0
   return nil unless @@fmod_se[c][n]
   return @@fmod_se[c][n].channel.DSP(self.addDSP(@@fmod_se[c][n], type))
 end
 def self.removeDSP(sound_file, id)
   unless sound_file and sound_file.channel
     return
   end
   sound_file.channel.removeDSP(id)
 end
 def self.bgm_removeDSP(c, id)
   self.removeDSP(@@fmod_bgm[c], id)
 end
 def self.bgs_removeDSP(c, id)
   self.removeDSP(@@fmod_bgs[c], id)
 end
 def self.me_removeDSP(c, id)
   self.removeDSP(@@fmod_me[c], id)
 end
 def self.se_removeDSP(c, id)
   for se in (@@fmod_se[c] ||= [])
     self.removeDSP(se, id)
   end
 end
 def self.bgm_DSP(c)
   return 0 if c <= 0
   return 0 unless @@fmod_bgm[c]
   return @@fmod_bgm[c].channel.dsps.size
 end
 def self.bgs_DSP(c)
   return 0 if c <= 0
   return 0 unless @@fmod_bgs[c]
   return @@fmod_bgs[c].channel.dsps.size
 end
 def self.me_DSP(c)
   return 0 if c <= 0
   return 0 unless @@fmod_me[c]
   return @@fmod_me[c].channel.dsps.size
 end
 def self.se_DSP(c)
   return 0 if c <= 0
   return 0 unless @@fmod_se[c]
   return 0 unless @@fmod_se[c][0]
   return @@fmod_se[c][0].channel.dsps.size
 end
 def self.setParameter(sound_file, dsp_id, param_id, value)
   unless sound_file and sound_file.channel
     return
   end
   dsp = sound_file.channel.DSP(dsp_id)
   return if dsp.nil?
   dsp.setParameter(param_id, value)
 end
 def self.bgm_setParameter(c, dsp_id, param_id, value)
   self.setParameter(@@fmod_bgm[c], dsp_id, param_id, value)
 end
 def self.bgs_setParameter(c, dsp_id, param_id, value)
   self.setParameter(@@fmod_bgs[c], dsp_id, param_id, value)
 end
 def self.me_setParameter(c, dsp_id, param_id, value)
   self.setParameter(@@fmod_me[c], dsp_id, param_id, value)
 end
 def self.se_setParameter(c, dsp_id, param_id, value)
   for se in (@@fmod_se[c] ||= [])
     self.setParameter(se, dsp_id, param_id, value)
   end
 end
 def self.getParameter(sound_file, dsp_id, param_id = 0)
   unless sound_file and sound_file.channel
     return - 1
   end
   dsp = sound_file.channel.DSP(dsp_id)
   return -1 if dsp.nil?
   dsp.getParameter(param_id)
 end
 def self.bgm_getParameter(c, dsp_id, param_id = 0)
   self.getParameter(@@fmod_bgm[c], dsp_id, param_id)
 end
 def self.bgs_getParameter(c, dsp_id, param_id = 0)
   self.getParameter(@@fmod_bgs[c], dsp_id, param_id)
 end
 def self.me_getParameter(c, dsp_id, param_id = 0)
   self.getParameter(@@fmod_me[c], dsp_id, param_id)
 end
 def self.se_getParameter(c, dsp_id, param_id = 0)
   self.getParameter(@@fmod_se[c][0], dsp_id, param_id)
 end
 def self.getNumParameters(sound_file, dsp_id)
   unless sound_file and sound_file.channel
     return 0
   end
   dsp = sound_file.channel.DSP(dsp_id)
   return 0 if dsp.nil?
   dsp.getNumParameters
 end
 def self.bgm_getNumParameters(c, dsp_id)
   self.getNumParameters(@@fmod_bgm[c], dsp_id)
 end
 def self.bgs_getNumParameters(c, dsp_id)
   self.getNumParameters(@@fmod_bgs[c], dsp_id)
 end
 def self.me_getNumParameters(c, dsp_id)
   self.getNumParameters(@@fmod_me[c], dsp_id)
 end
 def self.se_getNumParameters(c, dsp_id)
   self.getNumParameters(@@fmod_se[c][0], dsp_id)
 end
 def self.getType(sound_file, dsp_id)
   unless sound_file and sound_file.channel
     return 0
   end
   dsp = sound_file.channel.DSP(dsp_id)
   return 0 if dsp.nil?
   dsp.getType
 end
 def self.bgm_getType(c, dsp_id)
   self.getType(@@fmod_bgm[c], dsp_id)
 end
 def self.bgs_getType(c, dsp_id)
   self.getType(@@fmod_bgs[c], dsp_id)
 end
 def self.me_getType(c, dsp_id)
   self.getType(@@fmod_me[c], dsp_id)
 end
 def self.se_getType(c, dsp_id)
   self.getType(@@fmod_se[c][0], dsp_id)
 end
 def self.getDSPTypeByName(effect)
   return FModEx::FMOD_DSP_TYPES.index(effect.upcase)
 end
 def self.addEffect(dsp, type, *params)
   return if dsp.nil? || type.nil? || type == 0
   max_p = dsp.getNumParameters
   if params.size > max_p
     p "This effect requires max #{max_p.to_s} arguments, you passed #{params.size.to_s}."
     p "Default will be used."
     return
   end
   id = 0
   for par in params
     dsp.setParameter(id, par) if par != nil
     id += 1
   end
 end
 module Audio
   def self.bgm_add_effect(effect, c, *params)
     t = FMod::getDSPTypeByName(effect)
     FMod::addEffect(dsp = FMod::bgm_addDSP(c, t), t, *params)
     return dsp
   end
   def self.bgs_add_effect(effect, c, *params)
     t = FMod::getDSPTypeByName(effect)
     FMod::addEffect(dsp = FMod::bgs_addDSP(c, t), t, *params)
     return dsp
   end
   def self.me_add_effect(effect, c, *params)
     t = FMod::getDSPTypeByName(effect)
     FMod::addEffect(dsp = FMod::me_addDSP(c, t), t, *params)
     return dsp
   end
   def self.se_add_effect(effect, c, *params)
     t = FMod::getDSPTypeByName(effect)
     for n in 0...FMod::se_total(c)
       FMod::addEffect(FMod::se_addDSP(n, c, t), t, *params)
     end
   end
 end
end

# Methods: (following comments are for searching purposes)
class << Audio
#module Audio#def self.bgm_play() <- aliased
#module Audio#def self.bgm_stop() <- aliased
#module Audio#def self.bgm_fade() <- aliased
#module Audio#def self.bgm_pos() <- aliased
#module Audio#def self.bgs_play() <- aliased
#module Audio#def self.bgs_stop() <- aliased
#module Audio#def self.bgs_fade() <- aliased
#module Audio#def self.bgs_pos() <- aliased
#module Audio#def self.me_play() <- aliased
#module Audio#def self.me_stop() <- aliased
#module Audio#def self.me_fade() <- aliased
#module Audio#def self.se_play() <- aliased
#module Audio#def self.se_stop() <- aliased
 ["bgm_play","bgm_stop","bgm_fade","bgm_pos",
  "bgs_play","bgs_stop","bgs_fade","bgs_pos",
  "me_play","me_stop","me_fade",
  "se_play","se_stop"].each { |m|
   new = (m+"_b4_apu").to_sym
   old = m.to_sym
   alias_method(new, old) unless method_defined?(new)
   define_method(old){ |*args|
     if $game_variables[APU::CURRENT_CHANNEL_VARIABLE] == 0 || APU::CURRENT_CHANNEL_VARIABLE > APU::MAX_CHANNELS
       self.method(new).call(*args)
     else
       FMod::Audio.method(old).call(*args, $game_variables[APU::CURRENT_CHANNEL_VARIABLE])
     end
     }
   }
end

# Let's update in Scene_Base!
class Scene_Base
 alias_method(:update_basic_b4_apu, :update_basic) unless method_defined?(:update_basic_b4_apu)
#class Scene_Base#def update_basic() <- aliased
 def update_basic
   if !@audio_sleep || @audio_sleep == 4
     FMod::Audio.update
     @audio_sleep = 0
   else
     @audio_sleep += 1
   end
   update_basic_b4_apu
 end
end

# Disposing the FMod audio
class << SceneManager
 alias_method(:run_b4_apu, :run) unless method_defined?(:run_b4_apu)
#class SceneManager#def self.run() <- aliased
 def run
   FMod::stop_all # Stop all the playing audio at start (think about F12)
   run_b4_apu # Default running initialization and loop
   FMod::dispose # Dispose at exit (not executed on F12 press)
 end
end

 

Also visible on Pastebin.

 

FAQ

N/A

 

Credit and Thanks

Hiretsukan and Cowlol for the original script.

FMOD libraries authors.

 

Author's Notes

Important: FMOD has its own license, check it at the official website. Also the original version of this script belongs to Hiretsukan and Cowlol, so you have to credit them too and read the license you can find in the script.

Share this post


Link to post
Share on other sites

Very awesome! Now I can put my tracking music skills to good use! ^_^

 

I do, however, have a bug report. I placed an IT Module file as battle music and it sounded just fine and the victory ME played just fine as well. However, when the battle was ending and it was fading back to the map, it generated and error saying:

 

 

Script 'Audio Pump Up: FMOD Ex 1.4' Line 1504: TypeError occured.

 

can't convert true into Integer

 

 

This was while the channel was on 1. Hope that helps any!

Share this post


Link to post
Share on other sites
Very awesome! Now I can put my tracking music skills to good use! ^_^

 

I do, however, have a bug report. I placed an IT Module file as battle music and it sounded just fine and the victory ME played just fine as well. However, when the battle was ending and it was fading back to the map, it generated and error saying:

 

 

Script 'Audio Pump Up: FMOD Ex 1.4' Line 1504: TypeError occured.

 

can't convert true into Integer

 

 

This was while the channel was on 1. Hope that helps any!

This topic was highly inactive, and I don't think this script is even supported due to it being made in July

and the user hasn't even logged in since "Last Active Oct 27 2012 10:33 AM"

 

You also necro-posted to, Requesting to be closed.

Share this post


Link to post
Share on other sites

@Levi. in future don't reply to a necropost. Just report it and leave it. 

Also @djDarkX  Don't spam, and try and look at the date of the last post before replying. If you are looking for support on this script feel free to post in the RGSS3 Support Thread 

Thread Closed. If the OP wants this thread re-open PM me. 

Share this post


Link to post
Share on other sites
Guest
This topic is now closed to further replies.

  • Recently Browsing   0 members

    No registered users viewing this page.

×