搜索附件  

扩展音频模块v1.03.rar

 

[RMXP] 扩展音频模块 v1.03:
2009/04/25 v1.01:
    修正了中文错误信息不能显示的问题

2009/05/14 v1.02:
    修正了范例工程中的一些问题 添加了一个保存播放中的 BGM 到存档文件的应用实例(详见范例工程)

2009/10/19 v1.03:
    修正了转码函数没有准确获取缓冲区大小的问题


写在前面:

首先,这个脚本不像其它外挂脚本那样一旦插入就能立刻见效。这是一个扩展库(模块)脚本,面向的对象是有点脚本基础(至少知道什么是整数、字符串、函数及其基本用法)的人~
一般游戏使用 RGSS 的 Audio 模块便已足够。但如果你的游戏需要实现以下功能,那就可以调用这个 AudioEx 模块中的函数:
1、淡入音乐的效果
2、在音乐播放结束时的操作
3、获取一首音乐的状态——没准备好、正在播放、暂停、停止
4、改变 MIDI 的播放速度
5、播放时改变音乐节奏(不包括改变 MIDI 的声调)
6、播放时随时移动播放位置的指针
7、同时播放多首音乐


脚本的实现:

AudioEx 调用的是 Windows 的 MCI(Multimedia Control Interface,多媒体控制接口)中的一个函数 mciSendString。MCI 是一个高层 API,它为多媒体设备的访问提供了一种十分方便快捷的方式,只要发送一个简单的命令,就能完成对多媒体设备的一系列复杂操作。这个脚本仅仅用到了 MCI 部分处理音频的命令,实际上 MCI 的功能远远不止于此。

AudioEx 支持 RMXP 常用的音频格式,但不支持 OGG
在我的电脑上,用 AudioEx 播放 MIDI 的话,同时只能播放一个;而其它格式的音频则可以同时播放多个(可以配合原来的播放模块 Audio 同时播放两个 MIDI 文件)。
AudioEx 没有 RMXP 中改变 MIDI 节奏的功能(希望知道的高手能指点一下),但支持其它格式的播放速度(声音频率)的改变。

关于音乐是否播放结束的判断,mciSendString 本来可以在播放结束时发送一个通知消息通知窗口,但因为在 RMXP 游戏窗口中捕获消息比较麻烦,所以这个脚本没有采用这种方式来判断是否播结束(详见范例工程)。

AudioEx 调用的是 mciSendString 的 unicode 版本 mciSendStringW,否则无法解析包含中文的文件路径。Ruby 的字符串编码是 UTF-8,所以在调用的时候做了相应的转换。

MCI 还支持视频的播放,其针对于视频的功能比起音频来还更多、更繁杂。本站播放 AVI 的脚本就是直接调用了 MCI 来实现的~


常用函数:

这里介绍一些最常用的函数用法。
AudioEx 的函数的第一个参数总是一个字符串,它标识着要操作的设备。不同的音频可以在不同的设备上播放,而唯有通过一个唯一的标识,程序才知道你想要访问哪个设备,就好比公民都有一个唯一的身份证号。这个标识可以在调用的时候任意取,但不要包含双引号等特殊字符。
AudioEx.quickPlay(device, filename, volume, speed, fade)

这个函数可以快速的播放指定的音频文件,仅仅用于第一次打开音频文件(设备)。

device 是设备的标识
filanme 是文件路径(相对/绝对)
volume 是音量,取值范围 0-1000,1000 是默认值,表示最大音量
speed 是播放速度,取值范围 500-1500,1000 是默认值,表示正常速度
fade 是音频淡入的秒数(近似值),默认是 0

例子:
AudioEx.quickPlay("我的音乐1", "Audio/BGM/神奇的九寨.mp3")
AudioEx.quickPlay("我的音乐2", "C:/越剧 天上掉下个林妹妹.mp3", 1000)
AudioEx.quickPlay("我的音乐3", "avril lavigne-girlfriend", 500, 1000)
AudioEx.quickPlay("我的音乐4", "F:/音乐/许嵩 - 断桥残雪.mp3", 1000, 1200, 3)
AudioEx.continue(device, fade)

这个函数从暂停状态恢复一个设备的播放。

device 是设备的标识
fade 是音频淡入的秒数(近似值),默认是 1

例子:
AudioEx.continue("我的音乐1")
AudioEx.continue("我的音乐2", 3)
AudioEx.fade_out(device, sec, from, to, end_proc)

这个函数淡出一个设备的音量。直接调用的话常用于淡出后关闭音频设备(停止播放)。

device 是设备的标识
sec 是淡出的秒数秒数(近似值),默认是 1
from 是开始淡出的音量(0-1000),默认是 1000
to 是淡出结束时的音量(0-1000),默认是 0
end_proc 是淡出后需要进行的操作,默认是 0:
0 表示关闭设备(释放内存,该设备之后无法通过设备标识访问)
1 表示暂停设备(不释放内存,稍后通过设备标识可以恢复播放)
2 表示停止设备(不释放内存,稍后通过设备标识可以重新播放)

例子:
AudioEx.fade_out("我的音乐1")
AudioEx.fade_out("我的音乐2", 5)
AudioEx.fade_out("我的音乐3", 5, 1000)
AudioEx.fade_out("我的音乐4", 5, 800, 0)
AudioEx.fade_out("我的音乐5", 5, 1000, 200, 1)
AudioEx.position(device)

这个函数返回一个设备当前播放(指针)位置的整数,单位是毫秒。

device 是设备的标识

例子:
p "当前播放位置为:" + AudioEx.position("我的音乐1") + "毫秒"
AudioEx.length(device)

这个函数返回一个设备音频长度的整数,单位是毫秒。

device 是设备的标识

例子:
len = AudioEx.length("我的音乐1")
print "音乐长度为:" + len / 1000 / 60 + "分" + len / 1000 % 60 + "秒"
AudioEx.mode(device)

这个函数返回一个设备当前状态的字符串,可以是以下几种:
"not ready" = 还未准备好播放
"paused"    = 暂停中
"playing"   = 播放中
"stopped"   = 播放停止了(除非调用了 AudioEx.stop,否则 stopped 表示播放结束)

device 是设备的标识

例子:
if AudioEx.mode("我的音乐1") == "stopped"
  print "音乐播放结束!"
end
AudioEx.timeout(device, time)

这个函数设置一个设备的暂停状态最大持续时间(超时),如果设为 0 则没有超时。

device 是设备的标识
time 是持续时间(毫秒)
自动循环音乐,只要在调用 play 函数的时候传递一个 "repeat" 给它的第二个参数即可:
AudioEx.open("music", "1.mp3")
AudioEx.play("music", "repeat")

完整源代码:[code]#==============================================================================# 本脚本来自www.66RPG.com,使用和转载请保留此信息# 作者:紫苏#==============================================================================$mciSendString = Win32API.new("winmm", "mciSendStringW", ['P', 'P', 'I', 'L'], 'L')$mciGetErrorString = Win32API.new("winmm", "mciGetErrorStringW", ['L', 'P', 'I'], 'L')$:  ex        p "淡出时发生了异常:", ex      end    }  end  #--------------------------------------------------------------------------  # ● 淡出一个设备(音量从高到低的渐变)  #     device          : 设备名称(标识)  #     sec             : 淡出的时间(秒,近似值)  #     from            : 开始淡出的音量  #     to              : 淡出后的音量  #     end_proc        : 淡出结束后的操作  #                       ※ 0 = 关闭, 1 = 暂停, 2 = 停止, 其它 = 无操作  #--------------------------------------------------------------------------  def self.fade_out(device, sec = 1, from = 1000, to = 0, end_proc = 0)    # 开启调节音量的线程    Thread.new {      begin        if sec != 0          volume = from          decrement = volume / sec / 10          while volume > to            setVolume(device, volume)            volume -= decrement            sleep 0.08          end          setVolume(device, to)        end        case end_proc        when 0: close(device)               # 淡出后关闭设备        when 1: setVolume(device, from)     # 将音量调整回淡出之前                pause(device)               # 淡出后暂停设备        when 2: stop(device)                # 淡出后停止设备        end      rescue Exception => ex        p "淡出时发生了异常:", ex      end    }  end  #--------------------------------------------------------------------------  # ● 向 MCI 设备发送 pause 命令,暂停设备  #     device          : 设备名称(标识)  #--------------------------------------------------------------------------  def self.pause(device)    error = $mciSendString.call("pause #{device}".to_unicode, 0, 0, 0)    raise AudioExException.new(error) if error != 0  end  #--------------------------------------------------------------------------  # ● 向 MCI 设备发送 resume 命令,恢复设备  #     device          : 设备名称(标识)  #--------------------------------------------------------------------------  def self.resume(device)    error = $mciSendString.call("resume #{device}".to_unicode, 0, 0, 0)    raise AudioExException.new(error) if error != 0  end  #--------------------------------------------------------------------------  # ● 向MCI 设备发送 seek 命令,移动当前位置指针  #     device          : 设备名称(标识)  #     pos             : 位置(毫秒)  #--------------------------------------------------------------------------  def self.seek(device, pos)    error = $mciSendString.call(      (case pos      when -1        "seek #{device} to end"      when 0        "seek #{device} to start"      else        "seek #{device} to #{pos}"      end).to_unicode,    0, 0, 0)    raise AudioExException.new(error) if error != 0    play(device)  end  #--------------------------------------------------------------------------  # ● 设置 MCI 设备左右声道平均音量  #     device          : 设备名称(标识)  #     volume          : 音量(0-1000)  #--------------------------------------------------------------------------  def self.setVolume(device, volume)    volume = [[volume, 0].max, 1000].min    setAudio(device, "volume to #{volume}")  end  #--------------------------------------------------------------------------  # ● 获取 MCI 设备左右声道平均音量  #     device          : 设备名称(标识)  #--------------------------------------------------------------------------  def self.getVolume(device)    return status(device, "volume").to_i  end  #--------------------------------------------------------------------------  # ● 设置 MCI 设备播放速度  #     device          : 设备名称(标识)  #     speed           : 速度(500-1500)  #--------------------------------------------------------------------------  def self.setSpeed(device, speed)    speed = [[speed, 500].max, 1500].min    set(device, "speed #{speed}")  end  #--------------------------------------------------------------------------  # ● 设置 MCI 设备暂停超时  #     device          : 设备名称(标识)  #     time            : 超时(毫秒)  #--------------------------------------------------------------------------  def self.timeout(device, time)    set(device, "pause #{time}")  end  #--------------------------------------------------------------------------  # ● 向 MCI 设备发送 stop 命令,停止设备  #     device          : 设备名称(标识)  #--------------------------------------------------------------------------  def self.stop(device)    error = $mciSendString.call("stop #{device}".to_unicode, 0, 0, 0)    raise AudioExException.new(error) if error != 0  end  #--------------------------------------------------------------------------  # ● 向 MCI 设备发送 close 命令,关闭设备  #     device          : 设备名称(标识)  #--------------------------------------------------------------------------  def self.close(device)    error = $mciSendString.call("close #{device}".to_unicode, 0, 0, 0)    raise AudioExException.new(error) if error != 0  end  #--------------------------------------------------------------------------  # ● 获取 MCI 设备当前位置(毫秒)  #     device          : 设备名称(标识)  #--------------------------------------------------------------------------  def self.position(device)    return status(device, "position").to_i  end  #--------------------------------------------------------------------------  # ● 获取 MCI 设备媒体长度(毫秒)  #     device          : 设备名称(标识)  #--------------------------------------------------------------------------  def self.length(device)    return status(device, "length").to_i  end  #--------------------------------------------------------------------------  # ● 获取 MCI 设备状态("not ready", "paused", "playing", and "stopped")  #     device          : 设备名称(标识)  #--------------------------------------------------------------------------  def self.mode(device)    return status(device, "mode")  end  #--------------------------------------------------------------------------  # ● 向 MCI 设备发送 status 命令,获取设备状态信息  #     device          : 设备名称(标识)  #     flags           : 命令标记  #--------------------------------------------------------------------------  def self.status(device, flags)    buf = " " * 256    error = $mciSendString.call("status #{device} #{flags}".to_unicode, buf, 256, 0)    raise AudioExException.new(error) if error != 0    buf.strip!    # 返回 UTF-8 编码格式的设备状态信息     return buf.to_UTF8  end################################################################################                                                                             ##       以下函数在普通情况下不需要直接调用,仅供有兴者参考、试验。           ##    使用方法请自行参考 MSDN 有关 MCI Command String(命令字符串)的部分。    ##                                                                             ################################################################################  #--------------------------------------------------------------------------  # ● 向 MCI 设备发送 setaudio 命令,设置音频相关信息  #     device          : 设备名称(标识)  #     flags           : 命令标记  #--------------------------------------------------------------------------  def self.setAudio(device, flags)    error = $mciSendString.call("setaudio #{device} #{flags}".to_unicode,      0, 0, 0)    raise AudioExException.new(error) if error != 0  end  #--------------------------------------------------------------------------  # ● 向 MCI 设备发送 cue 命令,准备播放  #     device          : 设备名称(标识)  #     flags           : 命令标记  #--------------------------------------------------------------------------  def self.cue(device)    error = $mciSendString.call("cue #{device}".to_unicode, 0, 0, 0)    raise AudioExException.new(error) if error != 0  end  #--------------------------------------------------------------------------  # ● 向 MCI 设备发送 capability 命令,获取设备兼容性相关信息  #     device          : 设备名称(标识)  #     flags           : 命令标记  #--------------------------------------------------------------------------  def self.capability(device, flags)    buf = " " * 256    error = $mciSendString.call("capability #{device} #{flags}".to_unicode,      buf, 256, 0)    raise AudioExException.new(error) if error != 0    buf.strip!    return buf.to_UTF8  end  #--------------------------------------------------------------------------  # ● 向 MCI 设备发送 info 命令,获取设备信息  #     device          : 设备名称(标识)  #     flags           : 命令标记  #--------------------------------------------------------------------------  def self.info(device, flags)    buf = " " * 256    error = $mciSendString.call("info #{device} #{flags}".to_unicode,      buf, 256, 0)    raise AudioExException.new(error) if error != 0    buf.strip!    return buf.to_UTF8  end  #--------------------------------------------------------------------------  # ● 向 MCI 设备发送 set 命令,设置设备相关属性  #     device          : 设备名称(标识)  #     flags           : 命令标记  #--------------------------------------------------------------------------  def self.set(device, flags)    error = $mciSendString.call("set #{device} #{flags}".to_unicode, 0, 0, 0)    raise AudioExException.new(error) if error != 0  endend#==============================================================================# ■ AudioExException#------------------------------------------------------------------------------#  扩展音频模块异常类。#==============================================================================class AudioExException < Exception  #--------------------------------------------------------------------------  # ● 初始化异常类对象  #     code : MCI 错误代码  #--------------------------------------------------------------------------  def initialize(code)    return super if code.class == String    @msg = " " * 512    # 返回 MCI 错误信息    $mciGetErrorString.call(code, @msg, 256)    @msg = @msg.to_UTF8  end  #--------------------------------------------------------------------------  # ● 返回异常对象的字符串描述  #--------------------------------------------------------------------------  def to_s    # 如果没有传递 MCI 错误代码的话就返回父类的错误信息    return @msg if @msg    return super  endend#==============================================================================# ■ String#------------------------------------------------------------------------------#  字符串类。可处理任意长度的字节串。(追加编码转换的定义)#==============================================================================class String  #--------------------------------------------------------------------------  # ● 用来编码 Ruby 字符串、解码 unicode 的 两个 Windows API 函数  #--------------------------------------------------------------------------  @@MultiByteToWideChar = Win32API.new("kernel32", "MultiByteToWideChar", ['I', 'L', 'P', 'I', 'P', 'I'], 'I')  @@WideCharToMultiByte = Win32API.new("kernel32", "WideCharToMultiByte", ['I', 'L', 'P', 'I', 'P', 'I', 'P', 'P'], 'I')  #--------------------------------------------------------------------------  # ● 返回将 Ruby UTF-8 字符串对象(本身)编码为 unicode 后的字符串  #--------------------------------------------------------------------------  def to_unicode    # 65001: UTF-8 字符集编码(代码页)    len = @@MultiByteToWideChar.call(65001, 0, self, -1, 0, 0)
Loading...

QQ|Archiver|手机版|小黑屋|同能RPG制作大师 ( 沪ICP备12027754号-3 )

GMT+8, 2024-11-24 01:25 , Processed in 0.066747 second(s), 22 queries .

Powered by Discuz! X3.4

Copyright © 2001-2020, Tencent Cloud.

返回顶部