Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- # Audio Pump Up: FMOD Ex v. 1.4
- # VX 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 = false # User can disable channels 1+ audio with F1?
- # Note: in VX, F1 settings are written only after application closing. :(
- end
- # For a correct application of the script in VX, you should insert in the Main
- # script a line for disposing the FMod module on exit. The code is just:
- # FMod::dispose
- # and should be pasted in Main, before the "rescue" one.
- # 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 = '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\RGSS2\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] << self.play(name, volume, pitch, 0, false, false)
- 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, c, position = 0,
- 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, c, position = 0)
- 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\RGSS2', 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] != 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] != 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.bgs_play() <- aliased
- #module Audio#def self.bgs_stop() <- aliased
- #module Audio#def self.bgs_fade() <- 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
- args << $game_variables[APU::CURRENT_CHANNEL_VARIABLE]
- FMod::Audio.method(old).call(*args)
- end
- }
- }
- end
- # Let's update in Scene_Base!
- class Scene_Base
- alias_method(:update_b4_apu, :update) unless method_defined?(:update_b4_apu)
- #class Scene_Base#def update() <- aliased
- def update
- if !@audio_sleep || @audio_sleep == 4
- FMod::Audio.update
- @audio_sleep = 0
- else
- @audio_sleep += 1
- end
- update_b4_apu
- end
- end
- FMod::stop_all # Stop all the playing audio at start (think about F12)
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement