Chaos Project

RPG Maker => RPG Maker Scripts => Script Troubleshooting => Topic started by: Simon Greedwell on August 13, 2013, 11:36:03 am

Title: [RESOLVED][XP] Problems with Stormtronics CMS and Hiretsukan's FMOD
Post by: Simon Greedwell on August 13, 2013, 11:36:03 am
EDIT: How embarrassing. Let me try this again:

I'm trying to use both Blizzard's Stormtronics CMS and Hiretsukan's FMOD script but the following erros occurs when finishing a battle:

Script 'Other Classes*' line 60 Argument Error ocurred

wrong number of arguments (2 for 1)


This is the FmoDEX script:

#==============================================================================
# ** 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
#------------------------------------------------------------------------------
# A rewrite of the built-in Audio module to extend its functionality
# using the FMOD Ex library (http://www.fmod.org/). In particular,
# it supports several new formats and has the ability to get current
# playing position and seek to a new one, and to set loop points.
# Extensions to Game_System and Scene_Battle makes the memorize BGM/BGS
# event command remember position as well, and map music to resume
# playing from the position it stopped at before a battle, instead
# of starting all over like default RMXP behavior.
#------------------------------------------------------------------------------
# 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).
#
# There are three scripts that could be used, the real script is only
# the first one, but the other scripts are provided for convenience:
#
# FModEx
#           This includes the core functionality and the Audio module
#           rewrite. It's the main script and should be placed on
#           top of all scripts using it. Most people would just add a
#           new section above the Game_System or Game_Temp section at
#           the very top of the script editor and paste script there.
# Game_System
#           This script rewrites parts of the Game_System class to
#           allow memorize_bgm to support remembering position,
#           and to allow the play methods to take an extra parameter
#           specifying position to start playing from.
#           Add it anywhere under the Game_System script section.
#           If you don't need any of these features you don't need this
#           script.
# Other Classes
#           This is really an optional script that modifies the default
#           battle system to memorize map BGM and position instead of
#           starting over after the battle. Add it anywhere under
#           the Scene_Battle classes.
#
# Aside from integration with RMXP's default scripts, you can use
# this script the same way you used the old Audio class You could also
# access the FMod module for more options at a lower level, 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.
#------------------------------------------------------------------------------
# Compatibility:
#
# This script has different levels of compatibility depending on what
# scripts you use:
#
# FModEx
#           This script overwrites the Audio module, but since
#           few if any other scripts would do that, it's pretty
#           much compatible with the majority of other scripts
#           without modifications.
# Game_System
#           The following methods of Game_System are redefined:
#             bgm_play, bgm_restore, bgs_play, bgs_restore
#           Any other script that redefines these methods may
#           not work well with this one. Most scripts wouldn't
#           do that, except ones dealing with audio as well.
#           I've marked the areas in the script where I made
#           changes to help you resolve any conflicts
#           The following methods of Game_System are aliased:
#             bgm_memorize, bgs_memorize
#           Other scripts that redefine these methods should
#           be placed above the Game_System script.
# Other Classes
#           The following methods of Scene_Battle are redefined:
#             judge, start_phase5, update_phase5
#           Any other script that redefines these methods may
#           not work well with this one. Custom battle system
#           scripts may do that, so you might consider not
#           including the Other Classes section and just
#           manually add position memorizing functionality.
#           I've marked the areas in the script where I made
#           changes to help you resolve any conflicts
#           The following methods of Game_Temp/Scene_Map are aliased:
#             Game_Temp#initialize, Scene_Map #call_battle
#           Other scripts that redefine these methods should
#           be placed above the Other Classes script.
#
# So in other words, FModEx is the most compatible, followed by
# Game_System, and finally the last and optional Other Classes.
# If you use a custom battle system you probably shouldn't include
# Other Classes anyway. This isn't an SDK script and I never tested
# it with the SDK. It'll probably work, but refer to SDK documentation
# for more information.
#------------------------------------------------------------------------------
# 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.
#==============================================================================

#==============================================================================
# ** 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']
 
 #============================================================================
 # ** 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 = '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')
     # 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')
   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::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

 #============================================================================
 # ** 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
   #--------------------------------------------------------------------------
   # * 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
   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
   #--------------------------------------------------------------------------
   # * 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
   #--------------------------------------------------------------------------
   # * Dispose of Channel
   #--------------------------------------------------------------------------  
   def dispose
     @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_se = []                             # Array of Sound Effects
 @rtp_folder = nil                         # Name of RTP folder
 #--------------------------------------------------------------------------
 # * Get Path of RTP Folder From Registry
 #--------------------------------------------------------------------------
 def self.getRTPFolder
   if @rtp_folder
     return @rtp_folder
   end
   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\RGSS\RTP', 0, 0x20019, key)
   key = @fmod_dll.unpackInt(key)
   type = 0.chr * 4
   size = 0.chr * 4
   # Query to get string size
   query_value.call(key, 'Standard', 0, type, 0, size)
   data = ' ' * @fmod_dll.unpackInt(size)
   # Query the string value itself using size
   query_value.call(key, 'Standard', 0, type, data, size)
   @rtp_folder = data.chop
   close_key.call(key)
   # Make sure the directory ends with a backslash
   @rtp_folder += "\\" if @rtp_folder[-1].chr != "\\"
   return @rtp_folder
 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)
   name = name.gsub("/", "\\")
   # See if file exists in game folder
   localname = self.checkExtensions(name, FModEx::FMOD_FILE_TYPES)
   # See if file exists in RTP
   commonname = self.checkExtensions(getRTPFolder + name, FModEx::FMOD_FILE_TYPES)
   if FileTest.exist?(localname)
     return localname
   end
   if FileTest.exist?(commonname)
     return commonname
   end
   # An invalid name was provided
   return 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
   return sound_file
 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 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 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, position = 0, looping = true)
   return if self.already_playing?(@fmod_bgm, name, position)
   # Now play the new BGM as a stream
   @fmod_bgm = self.play(name, volume, pitch, position, looping, true)
 end
 #--------------------------------------------------------------------------
 # * Stop and Dispose of BGM
 #--------------------------------------------------------------------------
 def self.bgm_stop
   self.stop(@fmod_bgm)
   @fmod_bgm = nil
 end
 #--------------------------------------------------------------------------
 # * Return BGM Length in Milliseconds
 #--------------------------------------------------------------------------
 def self.bgm_length(sound_file)
   self.get_length(@fmod_bgm)
 end
 #--------------------------------------------------------------------------
 # * Check if a BGM is Playing
 #--------------------------------------------------------------------------  
 def self.bgm_playing?
   return self.playing?(@fmod_bgm)
 end
 #--------------------------------------------------------------------------
 # * Get Current BGM Playing Position
 #--------------------------------------------------------------------------
 def self.bgm_position
   return self.get_position(@fmod_bgm)
 end
 #--------------------------------------------------------------------------
 # * Seek to New BGM Playing Position
 #--------------------------------------------------------------------------
 def self.bgm_position=(new_pos)
   self.set_position(@fmod_bgm, new_pos)
 end
 #--------------------------------------------------------------------------
 # * Get Current BGM Volume
 #--------------------------------------------------------------------------
 def self.bgm_volume
   return self.get_volume(@fmod_bgm)
 end
 #--------------------------------------------------------------------------
 # * Set BGM Volume
 #--------------------------------------------------------------------------
 def self.bgm_volume=(volume)
   self.set_volume(@fmod_bgm, volume)
 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, unit = FModEx::FMOD_DEFAULT_UNIT)
   @fmod_bgm = self.set_loop_points(@fmod_bgm, 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, position = 0, looping = true)
   return if self.already_playing?(@fmod_bgs, name, position)
   # Now play the new BGS as a stream
   @fmod_bgs = self.play(name, volume, pitch, position, looping, true)
 end
 #--------------------------------------------------------------------------
 # * Stop and Dispose of BGS
 #--------------------------------------------------------------------------
 def self.bgs_stop
   self.stop(@fmod_bgs)
   @fmod_bgs = nil
 end
 #--------------------------------------------------------------------------
 # * Return BGS Length in Milliseconds
 #--------------------------------------------------------------------------
 def self.bgm_length(sound_file)
   self.get_length(@fmod_bgs)
 end
 #--------------------------------------------------------------------------
 # * Check if a BGS is Playing
 #--------------------------------------------------------------------------  
 def self.bgs_playing?
   return self.playing?(@fmod_bgs)
 end
 #--------------------------------------------------------------------------
 # * Get Current BGS Playing Position
 #--------------------------------------------------------------------------
 def self.bgs_position
   return self.get_position(@fmod_bgs)
 end
 #--------------------------------------------------------------------------
 # * Seek to New BGS Playing Position
 #--------------------------------------------------------------------------
 def self.bgs_position=(new_pos)
   self.set_position(@fmod_bgs, new_pos)
 end
 #--------------------------------------------------------------------------
 # * Get Current BGS Volume
 #--------------------------------------------------------------------------
 def self.bgs_volume
   return self.get_volume(@fmod_bgs)
 end
 #--------------------------------------------------------------------------
 # * Set BGS Volume
 #--------------------------------------------------------------------------
 def self.bgs_volume=(volume)
   self.set_volume(@fmod_bgs, volume)
 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, unit = FModEx::FMOD_DEFAULT_UNIT)
   @fmod_bgs = self.set_loop_points(@fmod_bgs, first, second, unit)
 end
 #--------------------------------------------------------------------------
 # * Play SE
 #     name            : Name of the file
 #     volume          : Channel volume
 #     pitch           : Channel frequency
 #--------------------------------------------------------------------------
 def self.se_play(name, volume, pitch)
   if @fmod_se.size > @fmod.maxChannels
     se = @fmod_se.shift
     self.stop(se)
   end
   # Load SE into memory and play it
   @fmod_se << self.play(name, volume, pitch, 0, false, false)
 end
 #--------------------------------------------------------------------------
 # * Stop and Dispose of all SEs
 #--------------------------------------------------------------------------
 def self.se_stop
   for se in @fmod_se
     self.stop(se)
   end
   @fmod_se.clear
 end
 #--------------------------------------------------------------------------
 # * Get Rid of Non-Playing SEs
 #--------------------------------------------------------------------------  
 def self.se_clean
   for se in @fmod_se
     unless self.playing?(se)
       self.stop(se)
       @fmod_se.delete(se)
     end
   end
 end
 #--------------------------------------------------------------------------
 # * Check if There's Some SE in SE Array
 #--------------------------------------------------------------------------  
 def self.se_list_empty?
   return @fmod_se.empty?
 end
 #--------------------------------------------------------------------------
 # * Dispose of Everything
 #--------------------------------------------------------------------------  
 def self.dispose
   self.bgm_stop
   self.bgs_stop
   self.se_stop
   @fmod.dispose
 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
 #--------------------------------------------------------------------------
 # * 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 = 100, pitch = 100, position = 0,
                     fade_in = false)
   if @bgm_fading_out and !fade_in
     @next_bgm = RPG::AudioFile.new(filename, volume, pitch)
     @next_bgm_position = position
     return
   end
   start_volume = volume
   if fade_in
     @bgm_target_volume = volume unless @bgm_fading_in
     @bgm_fading_in = true
     start_volume = 0
   end
   @bgm_fading_out = false
   # If a ME is playing we wait until it's over before playing BGM
   unless @me_playing
     FMod::bgm_play(filename, start_volume, pitch, position)
   end
   @playing_bgm = RPG::AudioFile.new(filename, volume, pitch)
   @memorized_bgm = @playing_bgm
   @memorized_bgm_position = position
 end
 #--------------------------------------------------------------------------
 # * Stops BGM Playback
 #--------------------------------------------------------------------------
 def Audio.bgm_stop
   @memorized_bgm = nil
   @playing_bgm = nil
   @bgm_fading_in = false
   @bgm_fading_out = false
   # MEs are internally BGMs, but are stopped with me_stop instead
   if @me_playing
     return
   end
   FMod::bgm_stop
 end
 #--------------------------------------------------------------------------
 # * Starts BGM fadeout.
 #     time            : Length of the fadeout in milliseconds.
 #--------------------------------------------------------------------------
 def Audio.bgm_fade(time)
   return if @me_playing or !FMod::bgm_playing?
   @bgm_fading_out = true
   time = time / 1000
   @bgm_fade_decrement = FMod::bgm_volume / (time * 5)
 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 = 100, pitch = 100, position = 0)
   if @bgs_fading_out
     @next_bgs = RPG::AudioFile.new(filename, volume, pitch)
     @next_bgs_position = position
     return
   end
   FMod::bgs_play(filename, volume, pitch, position)
 end
 #--------------------------------------------------------------------------
 # * Stops BGS Playback
 #--------------------------------------------------------------------------
 def Audio.bgs_stop
   FMod::bgs_stop
   @bgs_fading_out = false
 end
 #--------------------------------------------------------------------------
 # * Starts BGS fadeout.
 #     time            : Length of the fadeout in milliseconds.
 #--------------------------------------------------------------------------
 def Audio.bgs_fade(time)
   return unless FMod::bgs_playing?
   @bgs_fading_out = true
   time = time / 1000
   @bgs_fade_decrement = FMod::bgs_volume / (time * 5)
 end
 #--------------------------------------------------------------------------
 # * Starts ME Playback
 #     name            : Name of the file
 #     volume          : Channel volume
 #     pitch           : Channel frequency
 #--------------------------------------------------------------------------
 def Audio.me_play(filename, volume = 100, pitch = 100)
   if @me_fading_out
     @next_me = RPG::AudioFile.new(filename, volume, pitch)
     return
   end
   if @bgm_fading_out
     self.bgm_stop
   end
   # Memorize playing bgm
   if @playing_bgm and !@me_playing
     bgm = @playing_bgm
     @playing_bgm = RPG::AudioFile.new(bgm.name, FMod::bgm_volume, bgm.pitch)
     @memorized_bgm = @playing_bgm
     @memorized_bgm_position = FMod::bgm_position
   end
   @me_playing = true
   FMod::bgm_play(filename, volume, pitch, 0, false)
 end
 #--------------------------------------------------------------------------
 # * Stops ME Playback
 #--------------------------------------------------------------------------
 def Audio.me_stop
   return unless @me_playing
   @me_playing = false
   @me_fading_out = false
   # Play memorized bgm, fading in
   if @memorized_bgm and !@bgm_fading_out
     bgm = @memorized_bgm
     self.bgm_play(bgm.name, bgm.volume, bgm.pitch, @memorized_bgm_position, true)
   else
     self.bgm_stop
   end
 end
 #--------------------------------------------------------------------------
 # * Starts ME fadeout.
 #     time            : Length of the fadeout in milliseconds.
 #--------------------------------------------------------------------------
 def Audio.me_fade(time)
   return unless FMod::bgm_playing?
   @me_fading_out = true
   time = time / 1000
   @bgm_fade_decrement = FMod::bgm_volume / (time * 5)
 end
 #--------------------------------------------------------------------------
 # * Starts SE Playback
 #     name            : Name of the file
 #     volume          : Channel volume
 #     pitch           : Channel frequency
 #--------------------------------------------------------------------------
 def Audio.se_play(filename, volume = 100, pitch = 100)
   FMod::se_play(filename, volume, pitch)
 end
 #--------------------------------------------------------------------------
 # * Stops SE Playback
 #--------------------------------------------------------------------------
 def Audio.se_stop
   FMod::se_stop
 end
 #--------------------------------------------------------------------------
 # * Update ME Playback, SE Disposal and Fading, Called Each Frame
 #--------------------------------------------------------------------------
 def Audio.update
   # Stop ME when it's over (and continue playing BGM)
   if @me_playing
     unless FMod::bgm_playing?
       self.me_stop
     end
   end
   # Remove any finished SEs
   unless FMod::se_list_empty?
     FMod::se_clean
   end
   if @bgm_fading_in
     # Stop fading when target is reached, otherwise increase volume
     if FMod::bgm_volume >= @bgm_target_volume
       @bgm_fading_in = false
     else
       current_volume = FMod::bgm_volume + BGM_FADE_IN_INCREMENT
       FMod::bgm_volume = current_volume
     end
   end
   if FMod::bgm_playing? and @bgm_fading_out and
       !@me_playing
     if FMod::bgm_volume <= 0
       @bgm_fading_out = false
       self.bgm_stop
       # If another BGM played while fading out, play it (most recent)
       if @next_bgm
         self.bgm_play(@next_bgm.name, @next_bgm.volume,
                       @next_bgm.pitch, @next_bgm_position)
         @next_bgm = nil
       end
     else
       current_volume = FMod::bgm_volume - @bgm_fade_decrement
       FMod::bgm_volume = current_volume
     end
   end
   if FMod::bgs_playing? and @bgs_fading_out
     if FMod::bgs_volume <= 0
       @bgs_fading_out = false
       self.bgs_stop
       # If another BGS played while fading out, play it (most recent)
       if @next_bgs
         self.bgs_play(@next_bgs.name, @next_bgs.volume,
                       @next_bgs.pitch, @next_bgs_position)
         @next_bgs = nil
       end
     else
       current_volume = FMod::bgs_volume - @bgs_fade_decrement
       FMod::bgs_volume = current_volume
     end
   end
   if FMod::bgm_playing? and @me_fading_out
     if FMod::bgm_volume <= 0
       # If another ME played while fading out, play it (most recent)
       if @next_me
         self.me_play(@next_me.name, @next_me.volume, @next_me.pitch)
         @next_me = nil
       else
         @me_fading_out = false
         self.me_stop
       end
     else
       current_volume = FMod::bgm_volume - @bgm_fade_decrement
       FMod::bgm_volume = current_volume
     end
   end
 end
end

# Create an endless loop to update Audio module
Thread.new do
 loop do
   sleep 0.2
   Audio.update
 end
end


And this the script that causes the error:

class Game_Temp
 attr_accessor :map_bgm_pos
 alias :fmodex_old_temp_initialize :initialize unless $@
 def initialize
   fmodex_old_temp_initialize
   @map_bgm_pos = 0
 end
end

class Scene_Map
 alias :fmodex_old_map_call_battle :call_battle unless $@
 def call_battle
   $game_temp.map_bgm_pos = FMod.bgm_position
   fmodex_old_map_call_battle
 end
end

class Scene_Battle
 def judge
   # If all dead determinant is true, or number of members in party is 0
   if $game_party.all_dead? or $game_party.actors.size == 0
     # If possible to lose
     if $game_temp.battle_can_lose
############################################################################
#   ADDED $game_temp.map_bgm_pos AS 2ND PARAMETE TO bgm_play
############################################################################
       # Return to BGM before battle starts
       $game_system.bgm_play($game_temp.map_bgm, $game_temp.map_bgm_pos)
############################################################################        
       # Battle ends
       battle_end(2)
       # Return true
       return true
     end
     # Set game over flag
     $game_temp.gameover = true
     # Return true
     return true
   end
   # Return false if even 1 enemy exists
   for enemy in $game_troop.enemies
     if enemy.exist?
       return false
     end
   end
   # Start after battle phase (win)
   start_phase5
   # Return true
   return true
 end
 
 def start_phase5
   # Shift to phase 5
   @phase = 5
############################################################################
#   ADDED $game_temp.map_bgm_pos AS 2ND PARAMETE TO bgm_play
#   AND SWITCHED PLAY ORDER SO BGM IS PLAYED FIRST
############################################################################
   # Return to BGM before battle started
   $game_system.bgm_play($game_temp.map_bgm, $game_temp.map_bgm_pos)
   # Play battle end ME
   $game_system.me_play($game_system.battle_end_me)
############################################################################
   # Initialize EXP, amount of gold, and treasure
   exp = 0
   gold = 0
   treasures = []
   # Loop
   for enemy in $game_troop.enemies
     # If enemy is not hidden
     unless enemy.hidden
       # Add EXP and amount of gold obtained
       exp += enemy.exp
       gold += enemy.gold
       # Determine if treasure appears
       if rand(100) < enemy.treasure_prob
         if enemy.item_id > 0
           treasures.push($data_items[enemy.item_id])
         end
         if enemy.weapon_id > 0
           treasures.push($data_weapons[enemy.weapon_id])
         end
         if enemy.armor_id > 0
           treasures.push($data_armors[enemy.armor_id])
         end
       end
     end
   end
   # Treasure is limited to a maximum of 6 items
   treasures = treasures[0..5]
   # Obtaining EXP
   for i in 0...$game_party.actors.size
     actor = $game_party.actors[i]
     if actor.cant_get_exp? == false
       last_level = actor.level
       actor.exp += exp
       if actor.level > last_level
         @status_window.level_up(i)
       end
     end
   end
   # Obtaining gold
   $game_party.gain_gold(gold)
   # Obtaining treasure
   for item in treasures
     case item
     when RPG::Item
       $game_party.gain_item(item.id, 1)
     when RPG::Weapon
       $game_party.gain_weapon(item.id, 1)
     when RPG::Armor
       $game_party.gain_armor(item.id, 1)
     end
   end
   # Make battle result window
   @result_window = Window_BattleResult.new(exp, gold, treasures)
   # Set wait count
   @phase5_wait_count = 100
 end

 
 def update_phase5
   # If wait count is larger than 0
   if @phase5_wait_count > 0
     # Decrease wait count
     @phase5_wait_count -= 1
     # If wait count reaches 0
     if @phase5_wait_count == 0
       # Show result window
       @result_window.visible = true
       # Clear main phase flag
       $game_temp.battle_main_phase = false
       # Refresh status window
       @status_window.refresh
     end
     return
   end
   # If C button was pressed
   if Input.trigger?(Input::C)
############################################################################
#   REMOVED $game_system.play_bgm BECAUSE IT'S DONE AUTOMATICALLY
#   WHEN ME IS DONE PLAYING
############################################################################
############################################################################
     # Battle ends
     battle_end(0)
   end
 end
end
Title: Re: [XP] Problems with Blizzard's Stormtronics CMS and Hiretsukan's FMOD Script
Post by: Zexion on August 13, 2013, 01:03:28 pm
First, fix this script because it's not complete :P
Second, "[ /code]" (no space)
Third, the error doesn't seem to be in this script o.o
Title: Re: [XP] Problems with Blizzard's Stormtronics CMS and Hiretsukan's FMOD Script
Post by: KK20 on August 13, 2013, 02:42:13 pm
The error is pointing at this line?
$game_system.bgm_play($game_temp.map_bgm, $game_temp.map_bgm_pos)

If that's the case, I see why. That method should only have one parameter in it: the filename of the music. Unless one of your scripts rewrites this method to hold two parameters, this is an invalid call. Looking at the scripts you posted, I don't see this method being rewritten.

It could also be a matter of script order. SHIFT + CTRL + F for the item "def bgm_play" and see if you get more than one result. The first item it finds should be from 'Game_System'.
Title: Re: [XP] Problems with Blizzard's Stormtronics CMS and Hiretsukan's FMOD Script
Post by: Simon Greedwell on August 13, 2013, 03:33:00 pm
Quote from: KK20 on August 13, 2013, 02:42:13 pm
The error is pointing at this line?
$game_system.bgm_play($game_temp.map_bgm, $game_temp.map_bgm_pos)

If that's the case, I see why. That method should only have one parameter in it: the filename of the music. Unless one of your scripts rewrites this method to hold two parameters, this is an invalid call. Looking at the scripts you posted, I don't see this method being rewritten.


Perhaps this script does it? It's the Game _System* script described in FmoDEX:

#==============================================================================
# ** Game_System
#------------------------------------------------------------------------------
#  This class handles data surrounding the system. Backround music, etc.
#  is managed here as well. Refer to "$game_system" for the instance of
#  this class.
#==============================================================================

class Game_System
  #--------------------------------------------------------------------------
  # * Play Background Music
  #     bgm : background music to be played
  #--------------------------------------------------------------------------
############################################################################
#   ADDED pos (POSITION) AS PARAMETER TO METHOD
############################################################################
  def bgm_play(bgm, pos = 0)
    @playing_bgm = bgm
    if bgm != nil and bgm.name != ""
      Audio.bgm_play("Audio/BGM/" + bgm.name, bgm.volume, bgm.pitch, pos)
############################################################################
    else
      Audio.bgm_stop
    end
    Graphics.frame_reset
  end
  #--------------------------------------------------------------------------
  # * Memorize Background Music
  #--------------------------------------------------------------------------
  alias :fmodex_old_system_bgm_memorize :bgm_memorize unless $@
  def bgm_memorize
    fmodex_old_system_bgm_memorize
    @bgm_memorized_position = FMod::bgm_position
  end
  #--------------------------------------------------------------------------
  # * Restore Background Music
  #--------------------------------------------------------------------------
  def bgm_restore
############################################################################
#   ADDED @bgm_memorized_position AS PARAMETER TO METHOD
############################################################################
    bgm_play(@memorized_bgm, @bgm_memorized_position)
############################################################################
  end
  #--------------------------------------------------------------------------
  # * Play Background Sound
  #     bgs : background sound to be played
  #--------------------------------------------------------------------------
############################################################################
#   ADDED pos (POSITION) AS PARAMETER TO METHOD
############################################################################
  def bgs_play(bgs, pos = 0)
    @playing_bgs = bgs
    if bgs != nil and bgs.name != ""
      Audio.bgs_play("Audio/BGS/" + bgs.name, bgs.volume, bgs.pitch, pos)
############################################################################
    else
      Audio.bgs_stop
    end
    Graphics.frame_reset
  end
  #--------------------------------------------------------------------------
  # * Stop Background Sound
  #--------------------------------------------------------------------------
  def bgs_stop
    @playing_bgs = nil
    Audio.bgs_stop
  end
  #--------------------------------------------------------------------------
  # * Memorize Background Sound
  #--------------------------------------------------------------------------
  alias :fmodex_old_system_bgs_memorize :bgs_memorize unless $@
  def bgs_memorize
    fmodex_old_system_bgs_memorize
    @bgs_memorized_position = FMod::bgs_position
  end
  #--------------------------------------------------------------------------
  # * Restore Background Sound
  #--------------------------------------------------------------------------
  def bgs_restore
############################################################################
#   ADDED @bgs_memorized_position AS PARAMETER TO METHOD
############################################################################
    bgs_play(@memorized_bgs, @bgs_memorized_position)
############################################################################
  end
end


QuoteIt could also be a matter of script order. SHIFT + CTRL + F for the item "def bgm_play" and see if you get more than one result. The first item it finds should be from 'Game_System'.


I found this:

Game_System (44) def bgm_play (bgm)
Game System * (17) def bgm_play (bgm, pos = 0)


Title: Re: [XP] Problems with Blizzard's Stormtronics CMS and Hiretsukan's FMOD Script
Post by: KK20 on August 14, 2013, 10:14:50 pm
Looks like FMod is below Game_System...not sure what's going on then.
Is 'Other Classes*' below FMod? How about Stormtronics? Try shifting the script orders around and see.
Title: Re: [XP] Problems with Blizzard's Stormtronics CMS and Hiretsukan's FMOD Script
Post by: Simon Greedwell on August 15, 2013, 10:03:35 am
Quote from: KK20 on August 14, 2013, 10:14:50 pm
Looks like FMod is below Game_System...not sure what's going on then.
Is 'Other Classes*' below FMod? How about Stormtronics?


In the FMod script it is stated that it must be placed above all other scripts at the top of the list so other_classes* Stormtronics are indeed below it.

QuoteTry shifting the script orders around and see.


I tried putting Stormtronics above both Game_System* and Other_Classes* and this error took place:

Script 'Game_System*' Line 19: NoMethodError Occurred

undefined method 'name' for 16476:fixnum


I tried putting the Fmod script above Game_System* and Other_Classes* but not at the top of the list and then this happened:

Script '(*) STCMS - Hybrid Edition' line 449: NoMethodError occurred. 

undefined method 'name' for 8490:fixnum


I tried putting Stormtronics above Fmod, Game_System* and Other_Classes*and following happened:

Script 'Game_System*' Line 19: NoMethodError Occurred

undefined method 'name' for 10944:fixnum


I tried putting Stormtronics above Other_Classes* but below FMod and Game_System* and then... you know the drill:

Script '(*) STCMS - Hybrid Edition' line 449: NoMethodError occurred. 

undefined method 'name' for 9109:fixnum
Title: Re: [XP] Problems with Blizzard's Stormtronics CMS and Hiretsukan's FMOD Script
Post by: KK20 on August 15, 2013, 03:02:12 pm
I've put all the scripts into an empty project and was able to get it to work under the following order:
FMod, all of RMXP's default scripts (except main), Stormtronics, FMod Game_System edit, FMod other classes, Main

Those errors you posted are saying that you are passing a number instead of a filename. Those numbers are probably the saved audio positions. Did you make any edits to the scripts?
Title: Re: [XP] Problems with Blizzard's Stormtronics CMS and Hiretsukan's FMOD Script
Post by: Simon Greedwell on August 15, 2013, 08:59:03 pm
Quote from: KK20 on August 15, 2013, 03:02:12 pm
I've put all the scripts into an empty project and was able to get it to work under the following order:
FMod, all of RMXP's default scripts (except main), Stormtronics, FMod Game_System edit, FMod other classes, Main

Those errors you posted are saying that you are passing a number instead of a filename. Those numbers are probably the saved audio positions. Did you make any edits to the scripts?

It seems that the scripts I was using either cointained a typo or were corrupted. When I copy the Fmod scripts directly from the demo, eveything worked just prefectly when I put them in the order you mentioned.

Thanks for the help, I really appreciate it. Guess this one is solved.
Title: Re: [RESOLVED][XP] Problems with Stormtronics CMS and Hiretsukan's FMOD
Post by: Zexion on August 15, 2013, 09:07:22 pm
A word of warning, watch out whenever something is highlighted. I've messed up many scripts by replacing lines with random letters and not even realizing it...