mirror of
https://github.com/infinitefusion/infinitefusion-e18.git
synced 2025-12-06 06:01:46 +00:00
515 lines
13 KiB
Ruby
515 lines
13 KiB
Ruby
def getPlayMusic
|
|
return MiniRegistry.get(MiniRegistry::HKEY_CURRENT_USER,
|
|
"SOFTWARE\\Enterbrain\\RGSS","PlayMusic",true)
|
|
end
|
|
|
|
def getPlaySound
|
|
return MiniRegistry.get(MiniRegistry::HKEY_CURRENT_USER,
|
|
"SOFTWARE\\Enterbrain\\RGSS","PlaySound",true)
|
|
end
|
|
|
|
|
|
|
|
class AudioContext
|
|
attr_reader :context
|
|
|
|
def initialize
|
|
init = Win32API.new("audio.dll", "AudioContextInitialize", '', 'l')
|
|
@context=init.call
|
|
end
|
|
|
|
def dispose
|
|
if @context!=0
|
|
init = Win32API.new("audio.dll", "AudioContextFree", 'l', '')
|
|
init.call(context)
|
|
@context=0
|
|
end
|
|
end
|
|
end
|
|
|
|
|
|
|
|
#####################################
|
|
# Needed because RGSS doesn't call at_exit procs on exit
|
|
# Exit is not called when game is reset (using F12)
|
|
$AtExitProcs=[] if !$AtExitProcs
|
|
|
|
def exit(code=0)
|
|
for p in $AtExitProcs
|
|
p.call
|
|
end
|
|
raise SystemExit.new(code)
|
|
end
|
|
|
|
def at_exit(&block)
|
|
$AtExitProcs.push(Proc.new(&block))
|
|
end
|
|
|
|
|
|
|
|
module AudioState
|
|
w32_LL = Win32API.new("kernel32.dll", "LoadLibrary", 'p', 'l') # :nodoc:
|
|
w32_FL = Win32API.new("kernel32.dll", "FreeLibrary", 'p', 'l')# :nodoc:
|
|
|
|
if safeExists?("audio.dll")
|
|
@handle = w32_LL.call("audio.dll")
|
|
at_exit { w32_FL.call(@handle) }
|
|
AudioContextIsActive = Win32API.new("audio.dll","AudioContextIsActive","l","l")# :nodoc:
|
|
AudioContextPlay = Win32API.new("audio.dll","AudioContextPlay","lpllll","")# :nodoc:
|
|
AudioContextStop = Win32API.new("audio.dll","AudioContextStop","l","")# :nodoc:
|
|
AudioContextFadeOut = Win32API.new("audio.dll","AudioContextFadeOut","ll","")# :nodoc:
|
|
AudioContextGetPosition = Win32API.new("audio.dll","AudioContextGetPosition","l","l")# :nodoc:
|
|
AudioContextFadeIn = Win32API.new("audio.dll","AudioContextFadeIn","ll","")# :nodoc:
|
|
AudioContextSetVolume = Win32API.new("audio.dll","AudioContextSetVolume","ll","")# :nodoc:
|
|
AudioContextSEPlay = Win32API.new("audio.dll","AudioContextSEPlay","lplll","")# :nodoc:
|
|
if !@MEContext
|
|
@MEContext=AudioContext.new
|
|
at_exit { @MEContext.dispose }
|
|
end
|
|
if !@BGMContext
|
|
@BGMContext=AudioContext.new
|
|
at_exit { @BGMContext.dispose }
|
|
end
|
|
if !@BGSContext
|
|
@BGSContext=AudioContext.new
|
|
at_exit { @BGSContext.dispose }
|
|
end
|
|
if !@SEContext
|
|
@SEContext=AudioContext.new
|
|
at_exit { @SEContext.dispose }
|
|
end
|
|
else
|
|
AudioContextIsActive = nil # :nodoc:
|
|
AudioContextPlay = nil # :nodoc:
|
|
AudioContextStop = nil # :nodoc:
|
|
AudioContextFadeOut = nil # :nodoc:
|
|
AudioContextGetPosition = nil # :nodoc:
|
|
AudioContextFadeIn = nil # :nodoc:
|
|
AudioContextSetVolume = nil # :nodoc:
|
|
AudioContextSEPlay = nil # :nodoc:
|
|
end
|
|
|
|
@channel = nil
|
|
@bgm = nil
|
|
@name = ""
|
|
@pitch = 100
|
|
@bgmVolume = 100.0
|
|
@meVolume = 100.0
|
|
@bgsVolume = 100.0
|
|
@seVolume = 100.0
|
|
|
|
def self.setWaitingBGM(bgm,volume,pitch,position)
|
|
@waitingBGM=[bgm,volume,pitch,position]
|
|
end
|
|
|
|
def self.bgmActive?
|
|
return !@BGMContext ? false : (AudioContextIsActive.call(@BGMContext.context)!=0)
|
|
end
|
|
|
|
def self.meActive?
|
|
return !@MEContext ? false : (AudioContextIsActive.call(@MEContext.context)!=0)
|
|
end
|
|
|
|
def self.waitingBGM; @waitingBGM; end
|
|
def self.context; @BGMContext ? @BGMContext.context : nil; end
|
|
def self.meContext; @MEContext ? @MEContext.context : nil; end
|
|
def self.bgsContext; @BGSContext ? @BGSContext.context : nil; end
|
|
def self.seContext; @SEContext ? @SEContext.context : nil; end
|
|
def self.system; @system; end
|
|
def self.bgm; @bgm; end
|
|
def self.name; @name; end
|
|
def self.pitch; @pitch; end
|
|
def self.volume; @volume; end
|
|
|
|
def self.waitingBGM=(value);
|
|
@waitingBGM = value
|
|
end
|
|
|
|
def self.volume=(value); @volume=value; end
|
|
def self.bgm=(value); @bgm=value; end
|
|
def self.name=(value); @name=value; end
|
|
def self.pitch=(value); @pitch=value; end
|
|
end
|
|
|
|
|
|
|
|
def Audio_bgm_playing?
|
|
AudioState.channel!=nil
|
|
end
|
|
|
|
def Audio_bgm_name
|
|
AudioState.name
|
|
end
|
|
|
|
def Audio_bgm_pitch
|
|
AudioState.pitch
|
|
end
|
|
|
|
def Audio_bgm_play(name, volume, pitch, position = 0)
|
|
volume=0 if !getPlayMusic
|
|
begin
|
|
filename = canonicalize(RTP.getAudioPath(name))
|
|
if AudioState.meActive?
|
|
AudioState.setWaitingBGM(filename,volume,pitch,position)
|
|
return
|
|
end
|
|
AudioState::AudioContextPlay.call(AudioState.context,filename,volume,pitch,position,1)
|
|
AudioState.name=filename
|
|
AudioState.volume=volume
|
|
AudioState.pitch=pitch
|
|
rescue Hangup
|
|
rescue
|
|
p $!.message,$!.backtrace
|
|
end
|
|
end
|
|
|
|
def Audio_bgm_fadein(ms)
|
|
AudioState::AudioContextFadeIn.call(AudioState.context,ms.to_i)
|
|
end
|
|
|
|
def Audio_bgm_fade(ms)
|
|
AudioState::AudioContextFadeOut.call(AudioState.context,ms.to_i)
|
|
end
|
|
|
|
def Audio_bgm_stop
|
|
begin
|
|
AudioState::AudioContextStop.call(AudioState.context)
|
|
AudioState.waitingBGM=nil
|
|
AudioState.name = ""
|
|
rescue
|
|
p $!.message,$!.backtrace
|
|
end
|
|
end
|
|
|
|
def Audio_bgm_get_position
|
|
return AudioState::AudioContextGetPosition.call(AudioState.context)
|
|
end
|
|
|
|
def Audio_bgm_get_volume
|
|
return 0 if !AudioState.bgmActive?
|
|
return AudioState.volume
|
|
end
|
|
|
|
def Audio_bgm_set_volume(volume)
|
|
return if !AudioState.bgmActive?
|
|
AudioState.volume = volume * 1.0
|
|
AudioState::AudioContextSetVolume.call(AudioState.context,volume.to_i)
|
|
end
|
|
|
|
def Audio_me_play(name, volume, pitch, position = 0)
|
|
volume=0 if !getPlayMusic
|
|
begin
|
|
filename = canonicalize(RTP.getAudioPath(name))
|
|
if AudioState.bgmActive?
|
|
bgmPosition=Audio_bgm_get_position
|
|
AudioState.setWaitingBGM(
|
|
AudioState.name,
|
|
AudioState.volume,
|
|
AudioState.pitch,
|
|
bgmPosition
|
|
)
|
|
AudioState::AudioContextStop.call(AudioState.context)
|
|
end
|
|
AudioState::AudioContextPlay.call(AudioState.meContext,filename,
|
|
volume,pitch,position,0)
|
|
rescue
|
|
p $!.message,$!.backtrace
|
|
end
|
|
end
|
|
|
|
def Audio_me_fade(ms)
|
|
AudioState::AudioContextFadeOut.call(AudioState.meContext,ms)
|
|
end
|
|
|
|
def Audio_me_stop
|
|
AudioState::AudioContextStop.call(AudioState.meContext)
|
|
end
|
|
|
|
def Audio_bgs_play(name, volume, pitch, position = 0)
|
|
volume=0 if !getPlaySound
|
|
begin
|
|
filename = canonicalize(RTP.getAudioPath(name))
|
|
AudioState::AudioContextPlay.call(AudioState.bgsContext,filename,
|
|
volume,pitch,position,0)
|
|
rescue
|
|
p $!.message,$!.backtrace
|
|
end
|
|
end
|
|
|
|
def Audio_bgs_fade(ms)
|
|
AudioState::AudioContextFadeOut.call(AudioState.bgsContext,ms)
|
|
end
|
|
|
|
def Audio_bgs_stop
|
|
AudioState::AudioContextStop.call(AudioState.bgsContext)
|
|
end
|
|
|
|
def Audio_se_play(name, volume, pitch, position = 0)
|
|
volume=0 if !getPlaySound
|
|
begin
|
|
filename = canonicalize(RTP.getAudioPath(name))
|
|
AudioState::AudioContextSEPlay.call(AudioState.seContext,filename,
|
|
volume,pitch,position)
|
|
rescue
|
|
p $!.message,$!.backtrace
|
|
end
|
|
end
|
|
|
|
def Audio_se_stop
|
|
AudioState::AudioContextStop.call(AudioState.seContext)
|
|
end
|
|
|
|
|
|
|
|
####################################################
|
|
if safeExists?("audio.dll")
|
|
module Graphics
|
|
if !defined?(audiomodule_update)
|
|
class << self
|
|
alias audiomodule_update update
|
|
end
|
|
end
|
|
|
|
def self.update
|
|
Audio.update
|
|
audiomodule_update
|
|
end
|
|
end
|
|
|
|
|
|
|
|
module Audio
|
|
@@musicstate = nil
|
|
@@soundstate = nil
|
|
|
|
def self.update
|
|
return if Graphics.frame_count%10!=0
|
|
if AudioState.waitingBGM && !AudioState.meActive?
|
|
waitbgm=AudioState.waitingBGM
|
|
AudioState.waitingBGM=nil
|
|
bgm_play(waitbgm[0],waitbgm[1],waitbgm[2],waitbgm[3])
|
|
end
|
|
end
|
|
|
|
def self.bgm_play(name,volume=80,pitch=100,position=nil)
|
|
begin
|
|
if position==nil || position==0
|
|
Audio_bgm_play(name,volume,pitch,0)
|
|
else
|
|
Audio_bgm_play(name,volume,pitch,position)
|
|
Audio_bgm_fadein(500)
|
|
end
|
|
rescue Hangup
|
|
bgm_play(name,volume,pitch,position)
|
|
end
|
|
end
|
|
|
|
def self.bgm_fade(ms)
|
|
Audio_bgm_fade(ms)
|
|
end
|
|
|
|
def self.bgm_stop
|
|
Audio_bgm_stop
|
|
end
|
|
|
|
def self.bgm_position
|
|
return Audio_bgm_get_position
|
|
end
|
|
|
|
def self.me_play(name,volume=80,pitch=100)
|
|
Audio_me_play(name,volume,pitch,0)
|
|
end
|
|
|
|
def self.me_fade(ms)
|
|
Audio_me_fade(ms)
|
|
end
|
|
|
|
def self.me_stop
|
|
Audio_me_stop
|
|
end
|
|
|
|
def self.bgs_play(name,volume=80,pitch=100)
|
|
Audio_bgs_play(name,volume,pitch,0)
|
|
end
|
|
|
|
def self.bgs_fade(ms)
|
|
Audio_bgs_fade(ms)
|
|
end
|
|
|
|
def self.bgs_stop
|
|
Audio_bgs_stop
|
|
end
|
|
|
|
=begin
|
|
def self.se_play(name,volume=80,pitch=100)
|
|
Audio_se_play(name,volume,pitch,0)
|
|
end
|
|
|
|
def self.se_stop
|
|
Audio_se_stop
|
|
end
|
|
=end
|
|
end
|
|
end # safeExists?("audio.dll")
|
|
|
|
|
|
|
|
#===============================================================================
|
|
# Methods that determine the duration of an audio file.
|
|
#===============================================================================
|
|
def getOggPage(file)
|
|
fgetdw = proc { |file|
|
|
(file.eof? ? 0 : (file.read(4).unpack("V")[0] || 0))
|
|
}
|
|
dw = fgetdw.call(file)
|
|
return nil if dw != 0x5367674F
|
|
header = file.read(22)
|
|
bodysize = 0
|
|
hdrbodysize = (file.read(1)[0] rescue 0)
|
|
hdrbodysize.times do
|
|
bodysize += (file.read(1)[0] rescue 0)
|
|
end
|
|
ret = [header, file.pos, bodysize, file.pos + bodysize]
|
|
return ret
|
|
end
|
|
|
|
# internal function
|
|
def oggfiletime(file)
|
|
fgetdw = proc { |file|
|
|
(file.eof? ? 0 : (file.read(4).unpack("V")[0] || 0))
|
|
}
|
|
fgetw = proc { |file|
|
|
(file.eof? ? 0 : (file.read(2).unpack("v")[0] || 0))
|
|
}
|
|
pages = []
|
|
page = nil
|
|
loop do
|
|
page = getOggPage(file)
|
|
break if !page
|
|
pages.push(page)
|
|
file.pos = page[3]
|
|
end
|
|
return -1 if pages.length == 0
|
|
curserial = nil
|
|
i = -1
|
|
pcmlengths = []
|
|
rates = []
|
|
for page in pages
|
|
header = page[0]
|
|
serial = header[10, 4].unpack("V")
|
|
frame = header[2, 8].unpack("C*")
|
|
frameno = frame[7]
|
|
frameno = (frameno << 8) | frame[6]
|
|
frameno = (frameno << 8) | frame[5]
|
|
frameno = (frameno << 8) | frame[4]
|
|
frameno = (frameno << 8) | frame[3]
|
|
frameno = (frameno << 8) | frame[2]
|
|
frameno = (frameno << 8) | frame[1]
|
|
frameno = (frameno << 8) | frame[0]
|
|
if serial != curserial
|
|
curserial = serial
|
|
file.pos = page[1]
|
|
packtype = (file.read(1)[0] rescue 0)
|
|
string = file.read(6)
|
|
return -1 if string != "vorbis"
|
|
return -1 if packtype != 1
|
|
i += 1
|
|
version = fgetdw.call(file)
|
|
return -1 if version != 0
|
|
rates[i] = fgetdw.call(file)
|
|
end
|
|
pcmlengths[i] = frameno
|
|
end
|
|
ret = 0.0
|
|
for i in 0...pcmlengths.length
|
|
ret += pcmlengths[i].to_f / rates[i]
|
|
end
|
|
return ret
|
|
end
|
|
|
|
# Gets the length of an audio file in seconds. Supports WAV, MP3, and OGG files.
|
|
def getPlayTime(filename)
|
|
if safeExists?(filename)
|
|
return [getPlayTime2(filename), 0].max
|
|
elsif safeExists?(filename + ".wav")
|
|
return [getPlayTime2(filename + ".wav"), 0].max
|
|
elsif safeExists?(filename + ".mp3")
|
|
return [getPlayTime2(filename + ".mp3"), 0].max
|
|
elsif safeExists?(filename + ".ogg")
|
|
return [getPlayTime2(filename + ".ogg"), 0].max
|
|
end
|
|
return 0
|
|
end
|
|
|
|
def getPlayTime2(filename)
|
|
return -1 if !safeExists?(filename)
|
|
time = -1
|
|
fgetdw = proc { |file|
|
|
(file.eof? ? 0 : (file.read(4).unpack("V")[0] || 0))
|
|
}
|
|
fgetw = proc { |file|
|
|
(file.eof? ? 0 : (file.read(2).unpack("v")[0] || 0))
|
|
}
|
|
File.open(filename, "rb") { |file|
|
|
file.pos = 0
|
|
fdw = fgetdw.call(file)
|
|
if fdw == 0x46464952 # "RIFF"
|
|
filesize = fgetdw.call(file)
|
|
wave = fgetdw.call(file)
|
|
return -1 if wave != 0x45564157 # "WAVE"
|
|
fmt = fgetdw.call(file)
|
|
return -1 if fmt != 0x20746d66 # "fmt "
|
|
fmtsize = fgetdw.call(file)
|
|
format = fgetw.call(file)
|
|
channels = fgetw.call(file)
|
|
rate = fgetdw.call(file)
|
|
bytessec = fgetdw.call(file)
|
|
return -1 if bytessec == 0
|
|
bytessample = fgetw.call(file)
|
|
bitssample = fgetw.call(file)
|
|
data = fgetdw.call(file)
|
|
return -1 if data != 0x61746164 # "data"
|
|
datasize = fgetdw.call(file)
|
|
time = (datasize*1.0)/bytessec
|
|
return time
|
|
elsif fdw == 0x5367674F # "OggS"
|
|
file.pos = 0
|
|
time = oggfiletime(file)
|
|
return time
|
|
end
|
|
file.pos = 0
|
|
# Find the length of an MP3 file
|
|
while true
|
|
rstr = ""
|
|
ateof = false
|
|
while !file.eof?
|
|
if (file.read(1)[0] rescue 0) == 0xFF
|
|
begin
|
|
rstr = file.read(3)
|
|
rescue
|
|
ateof = true
|
|
end
|
|
break
|
|
end
|
|
end
|
|
break if ateof || !rstr || rstr.length != 3
|
|
if rstr[0] == 0xFB
|
|
t = rstr[1] >> 4
|
|
next if t == 0 || t == 15
|
|
freqs = [44100, 22050, 11025, 48000]
|
|
bitrates = [32, 40, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320]
|
|
bitrate = bitrates[t]
|
|
t = (rstr[1] >> 2) & 3
|
|
freq = freqs[t]
|
|
t = (rstr[1] >> 1) & 1
|
|
filesize = FileTest.size(filename)
|
|
frameLength = ((144000 * bitrate) / freq) + t
|
|
numFrames = filesize / (frameLength + 4)
|
|
time = (numFrames * 1152.0 / freq)
|
|
break
|
|
end
|
|
end
|
|
}
|
|
return time
|
|
end
|