Project1

标题: [RMXP] 扩展音频模块 v1.03 [打印本页]

作者: 紫苏    时间: 2009-4-24 19:13
标题: [RMXP] 扩展音频模块 v1.03
本帖最后由 紫苏 于 2009-11-20 13:26 编辑

扩展音频模块v1.03.rar (2.17 MB, 下载次数: 1703) 2009/04/25 v1.01:

2009/05/14 v1.02:

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")


完整源代码:
  1. #==============================================================================
  2. # 本脚本来自www.66RPG.com,使用和转载请保留此信息
  3. # 作者:紫苏
  4. #==============================================================================

  5. $mciSendString = Win32API.new("winmm", "mciSendStringW", ['P', 'P', 'I', 'L'], 'L')
  6. $mciGetErrorString = Win32API.new("winmm", "mciGetErrorStringW", ['L', 'P', 'I'], 'L')
  7. $: << Dir.getwd

  8. #==============================================================================
  9. # ■ AudioEx
  10. #------------------------------------------------------------------------------
  11. #  进行有关音乐,声音处理的扩展音频模块。
  12. #==============================================================================

  13. module AudioEx
  14.   #--------------------------------------------------------------------------
  15.   # ● 快速播放(集合打开、播放设备、设置音量、速度、淡入等操作)
  16.   #     device          : 设备名称(标识)
  17.   #     filename        : 文件路径
  18.   #     volume          : 音量(0-1000)
  19.   #     speed           : 速度(500-1500)
  20.   #     fade            : 淡入(true | false)
  21.   #--------------------------------------------------------------------------
  22.   def self.quickPlay(device, filename, volume = 1000, speed = 1000, fade = 0)
  23.     open(device, filename)
  24.     play(device)
  25.     setVolume(device, volume)
  26.     setSpeed(device, speed)
  27.     fade_in(device, fade, 0, volume)
  28.   end
  29.   #--------------------------------------------------------------------------
  30.   # ● 暂停一个设备的播放(可淡出)
  31.   #     device          : 设备名称(标识)
  32.   #     fade            : 淡出时间(秒)
  33.   #--------------------------------------------------------------------------
  34.   def self.suspend(device, fade = 1)
  35.     fade_out(device, fade, getVolume(device), 0, 1)
  36.   end
  37.   #--------------------------------------------------------------------------
  38.   # ● 恢复一个设备的播放(可淡入)
  39.   #     device          : 设备名称(标识)
  40.   #     fade            : 淡入时间(秒)
  41.   #--------------------------------------------------------------------------
  42.   def self.continue(device, fade = 1)
  43.     resume(device)
  44.     fade_in(device, fade, 0, getVolume(device))
  45.   end
  46.   #--------------------------------------------------------------------------
  47.   # ● 发送 open 命令,从文件打开一个设备
  48.   #     device          : 设备名称(标识)
  49.   #     filename        : 文件路径
  50.   #--------------------------------------------------------------------------
  51.   def self.open(device, filename)
  52.     error = $mciSendString.call("open \"#{filename}\" type mpegvideo alias #{device} wait".to_unicode, 0, 0, 0)
  53.     raise AudioExException.new(error) if error != 0
  54.     set(device, "time format milliseconds")
  55.     # 准备播放
  56.     cue(device)
  57.   end
  58.   #--------------------------------------------------------------------------
  59.   # ● 向 MCI 设备发送 play 命令,播放设备
  60.   #     device          : 设备名称(标识)
  61.   #     flags           : 命令标记
  62.   #--------------------------------------------------------------------------
  63.   def self.play(device, flags = "")
  64.     # 如果设备无法播放就抛出异常
  65.     if capability(device, "can play") == "false"
  66.       raise AudioExException, "设备无法播放。"
  67.     end
  68.     error = $mciSendString.call("play #{device} #{flags}".to_unicode, 0, 0, 0)
  69.     raise AudioExException.new(error) if error != 0
  70.   end
  71.   #--------------------------------------------------------------------------
  72.   # ● 淡入一个设备(音量从低到高的渐变)
  73.   #     device          : 设备名称(标识)
  74.   #     sec             : 淡入的时间(秒,近似值)
  75.   #     from            : 开始淡入的音量
  76.   #     to              : 淡入后的音量
  77.   #--------------------------------------------------------------------------
  78.   def self.fade_in(device, sec = 1, from = 0, to = 1000)
  79.     return if sec == 0
  80.     # 开启调节音量的线程
  81.     Thread.new {
  82.       begin
  83.         increment = to / sec / 10
  84.         volume = from
  85.         while volume < to
  86.           setVolume(device, volume)
  87.           volume += increment
  88.           sleep 0.08
  89.         end
  90.         setVolume(device, to)
  91.       rescue Exception => ex
  92.         p "淡出时发生了异常:", ex
  93.       end
  94.     }
  95.   end
  96.   #--------------------------------------------------------------------------
  97.   # ● 淡出一个设备(音量从高到低的渐变)
  98.   #     device          : 设备名称(标识)
  99.   #     sec             : 淡出的时间(秒,近似值)
  100.   #     from            : 开始淡出的音量
  101.   #     to              : 淡出后的音量
  102.   #     end_proc        : 淡出结束后的操作
  103.   #                       ※ 0 = 关闭, 1 = 暂停, 2 = 停止, 其它 = 无操作
  104.   #--------------------------------------------------------------------------
  105.   def self.fade_out(device, sec = 1, from = 1000, to = 0, end_proc = 0)
  106.     # 开启调节音量的线程
  107.     Thread.new {
  108.       begin
  109.         if sec != 0
  110.           volume = from
  111.           decrement = volume / sec / 10
  112.           while volume > to
  113.             setVolume(device, volume)
  114.             volume -= decrement
  115.             sleep 0.08
  116.           end
  117.           setVolume(device, to)
  118.         end
  119.         case end_proc
  120.         when 0: close(device)               # 淡出后关闭设备
  121.         when 1: setVolume(device, from)     # 将音量调整回淡出之前
  122.                 pause(device)               # 淡出后暂停设备
  123.         when 2: stop(device)                # 淡出后停止设备
  124.         end
  125.       rescue Exception => ex
  126.         p "淡出时发生了异常:", ex
  127.       end
  128.     }
  129.   end
  130.   #--------------------------------------------------------------------------
  131.   # ● 向 MCI 设备发送 pause 命令,暂停设备
  132.   #     device          : 设备名称(标识)
  133.   #--------------------------------------------------------------------------
  134.   def self.pause(device)
  135.     error = $mciSendString.call("pause #{device}".to_unicode, 0, 0, 0)
  136.     raise AudioExException.new(error) if error != 0
  137.   end
  138.   #--------------------------------------------------------------------------
  139.   # ● 向 MCI 设备发送 resume 命令,恢复设备
  140.   #     device          : 设备名称(标识)
  141.   #--------------------------------------------------------------------------
  142.   def self.resume(device)
  143.     error = $mciSendString.call("resume #{device}".to_unicode, 0, 0, 0)
  144.     raise AudioExException.new(error) if error != 0
  145.   end
  146.   #--------------------------------------------------------------------------
  147.   # ● 向MCI 设备发送 seek 命令,移动当前位置指针
  148.   #     device          : 设备名称(标识)
  149.   #     pos             : 位置(毫秒)
  150.   #--------------------------------------------------------------------------
  151.   def self.seek(device, pos)
  152.     error = $mciSendString.call(
  153.       (case pos
  154.       when -1
  155.         "seek #{device} to end"
  156.       when 0
  157.         "seek #{device} to start"
  158.       else
  159.         "seek #{device} to #{pos}"
  160.       end).to_unicode,
  161.     0, 0, 0)
  162.     raise AudioExException.new(error) if error != 0
  163.     play(device)
  164.   end
  165.   #--------------------------------------------------------------------------
  166.   # ● 设置 MCI 设备左右声道平均音量
  167.   #     device          : 设备名称(标识)
  168.   #     volume          : 音量(0-1000)
  169.   #--------------------------------------------------------------------------
  170.   def self.setVolume(device, volume)
  171.     volume = [[volume, 0].max, 1000].min
  172.     setAudio(device, "volume to #{volume}")
  173.   end
  174.   #--------------------------------------------------------------------------
  175.   # ● 获取 MCI 设备左右声道平均音量
  176.   #     device          : 设备名称(标识)
  177.   #--------------------------------------------------------------------------
  178.   def self.getVolume(device)
  179.     return status(device, "volume").to_i
  180.   end
  181.   #--------------------------------------------------------------------------
  182.   # ● 设置 MCI 设备播放速度
  183.   #     device          : 设备名称(标识)
  184.   #     speed           : 速度(500-1500)
  185.   #--------------------------------------------------------------------------
  186.   def self.setSpeed(device, speed)
  187.     speed = [[speed, 500].max, 1500].min
  188.     set(device, "speed #{speed}")
  189.   end
  190.   #--------------------------------------------------------------------------
  191.   # ● 设置 MCI 设备暂停超时
  192.   #     device          : 设备名称(标识)
  193.   #     time            : 超时(毫秒)
  194.   #--------------------------------------------------------------------------
  195.   def self.timeout(device, time)
  196.     set(device, "pause #{time}")
  197.   end
  198.   #--------------------------------------------------------------------------
  199.   # ● 向 MCI 设备发送 stop 命令,停止设备
  200.   #     device          : 设备名称(标识)
  201.   #--------------------------------------------------------------------------
  202.   def self.stop(device)
  203.     error = $mciSendString.call("stop #{device}".to_unicode, 0, 0, 0)
  204.     raise AudioExException.new(error) if error != 0
  205.   end
  206.   #--------------------------------------------------------------------------
  207.   # ● 向 MCI 设备发送 close 命令,关闭设备
  208.   #     device          : 设备名称(标识)
  209.   #--------------------------------------------------------------------------
  210.   def self.close(device)
  211.     error = $mciSendString.call("close #{device}".to_unicode, 0, 0, 0)
  212.     raise AudioExException.new(error) if error != 0
  213.   end
  214.   #--------------------------------------------------------------------------
  215.   # ● 获取 MCI 设备当前位置(毫秒)
  216.   #     device          : 设备名称(标识)
  217.   #--------------------------------------------------------------------------
  218.   def self.position(device)
  219.     return status(device, "position").to_i
  220.   end
  221.   #--------------------------------------------------------------------------
  222.   # ● 获取 MCI 设备媒体长度(毫秒)
  223.   #     device          : 设备名称(标识)
  224.   #--------------------------------------------------------------------------
  225.   def self.length(device)
  226.     return status(device, "length").to_i
  227.   end
  228.   #--------------------------------------------------------------------------
  229.   # ● 获取 MCI 设备状态("not ready", "paused", "playing", and "stopped")
  230.   #     device          : 设备名称(标识)
  231.   #--------------------------------------------------------------------------
  232.   def self.mode(device)
  233.     return status(device, "mode")
  234.   end
  235.   #--------------------------------------------------------------------------
  236.   # ● 向 MCI 设备发送 status 命令,获取设备状态信息
  237.   #     device          : 设备名称(标识)
  238.   #     flags           : 命令标记
  239.   #--------------------------------------------------------------------------
  240.   def self.status(device, flags)
  241.     buf = " " * 256
  242.     error = $mciSendString.call("status #{device} #{flags}".to_unicode, buf, 256, 0)
  243.     raise AudioExException.new(error) if error != 0
  244.     buf.strip!
  245.     # 返回 UTF-8 编码格式的设备状态信息
  246.     return buf.to_UTF8
  247.   end

  248. ###############################################################################
  249. #                                                                             #
  250. #       以下函数在普通情况下不需要直接调用,仅供有兴者参考、试验。           #
  251. #    使用方法请自行参考 MSDN 有关 MCI Command String(命令字符串)的部分。    #
  252. #                                                                             #
  253. ###############################################################################

  254.   #--------------------------------------------------------------------------
  255.   # ● 向 MCI 设备发送 setaudio 命令,设置音频相关信息
  256.   #     device          : 设备名称(标识)
  257.   #     flags           : 命令标记
  258.   #--------------------------------------------------------------------------
  259.   def self.setAudio(device, flags)
  260.     error = $mciSendString.call("setaudio #{device} #{flags}".to_unicode,
  261.       0, 0, 0)
  262.     raise AudioExException.new(error) if error != 0
  263.   end
  264.   #--------------------------------------------------------------------------
  265.   # ● 向 MCI 设备发送 cue 命令,准备播放
  266.   #     device          : 设备名称(标识)
  267.   #     flags           : 命令标记
  268.   #--------------------------------------------------------------------------
  269.   def self.cue(device)
  270.     error = $mciSendString.call("cue #{device}".to_unicode, 0, 0, 0)
  271.     raise AudioExException.new(error) if error != 0
  272.   end
  273.   #--------------------------------------------------------------------------
  274.   # ● 向 MCI 设备发送 capability 命令,获取设备兼容性相关信息
  275.   #     device          : 设备名称(标识)
  276.   #     flags           : 命令标记
  277.   #--------------------------------------------------------------------------
  278.   def self.capability(device, flags)
  279.     buf = " " * 256
  280.     error = $mciSendString.call("capability #{device} #{flags}".to_unicode,
  281.       buf, 256, 0)
  282.     raise AudioExException.new(error) if error != 0
  283.     buf.strip!
  284.     return buf.to_UTF8
  285.   end
  286.   #--------------------------------------------------------------------------
  287.   # ● 向 MCI 设备发送 info 命令,获取设备信息
  288.   #     device          : 设备名称(标识)
  289.   #     flags           : 命令标记
  290.   #--------------------------------------------------------------------------
  291.   def self.info(device, flags)
  292.     buf = " " * 256
  293.     error = $mciSendString.call("info #{device} #{flags}".to_unicode,
  294.       buf, 256, 0)
  295.     raise AudioExException.new(error) if error != 0
  296.     buf.strip!
  297.     return buf.to_UTF8
  298.   end
  299.   #--------------------------------------------------------------------------
  300.   # ● 向 MCI 设备发送 set 命令,设置设备相关属性
  301.   #     device          : 设备名称(标识)
  302.   #     flags           : 命令标记
  303.   #--------------------------------------------------------------------------
  304.   def self.set(device, flags)
  305.     error = $mciSendString.call("set #{device} #{flags}".to_unicode, 0, 0, 0)
  306.     raise AudioExException.new(error) if error != 0
  307.   end
  308. end


  309. #==============================================================================
  310. # ■ AudioExException
  311. #------------------------------------------------------------------------------
  312. #  扩展音频模块异常类。
  313. #==============================================================================

  314. class AudioExException < Exception
  315.   #--------------------------------------------------------------------------
  316.   # ● 初始化异常类对象
  317.   #     code : MCI 错误代码
  318.   #--------------------------------------------------------------------------
  319.   def initialize(code)
  320.     return super if code.class == String
  321.     @msg = " " * 512
  322.     # 返回 MCI 错误信息
  323.     $mciGetErrorString.call(code, @msg, 256)
  324.     @msg = @msg.to_UTF8
  325.   end
  326.   #--------------------------------------------------------------------------
  327.   # ● 返回异常对象的字符串描述
  328.   #--------------------------------------------------------------------------
  329.   def to_s
  330.     # 如果没有传递 MCI 错误代码的话就返回父类的错误信息
  331.     return @msg if @msg
  332.     return super
  333.   end
  334. end


  335. #==============================================================================
  336. # ■ String
  337. #------------------------------------------------------------------------------
  338. #  字符串类。可处理任意长度的字节串。(追加编码转换的定义)
  339. #==============================================================================

  340. class String
  341.   #--------------------------------------------------------------------------
  342.   # ● 用来编码 Ruby 字符串、解码 unicode 的 两个 Windows API 函数
  343.   #--------------------------------------------------------------------------
  344.   @@MultiByteToWideChar = Win32API.new("kernel32", "MultiByteToWideChar", ['I', 'L', 'P', 'I', 'P', 'I'], 'I')
  345.   @@WideCharToMultiByte = Win32API.new("kernel32", "WideCharToMultiByte", ['I', 'L', 'P', 'I', 'P', 'I', 'P', 'P'], 'I')
  346.   #--------------------------------------------------------------------------
  347.   # ● 返回将 Ruby UTF-8 字符串对象(本身)编码为 unicode 后的字符串
  348.   #--------------------------------------------------------------------------
  349.   def to_unicode
  350.     # 65001: UTF-8 字符集编码(代码页)
  351.     len = @@MultiByteToWideChar.call(65001, 0, self, -1, 0, 0) << 1
  352.     buf =" " * len
  353.     @@MultiByteToWideChar.call(65001, 0, self, -1, buf, len)
  354.     return buf
  355.   end
  356.   #--------------------------------------------------------------------------
  357.   # ● 返回将编码为 unicode 的字符串对象(本身)解码为 UTF-8 后的字符串
  358.   #--------------------------------------------------------------------------
  359.   def to_UTF8
  360.     len = @@WideCharToMultiByte.call(65001, 0, self, -1, 0, 0, 0, 0)
  361.     buf =" " * len
  362.     @@WideCharToMultiByte.call(65001, 0, self, -1, buf, len, 0, 0)
  363.     # 去掉 '\0' 字符串结束符(因为转换之后仅仅用于 Ruby 字符串)
  364.     buf.slice!(-1, 1)
  365.     return buf
  366.   end
  367. end
  368. #==============================================================================
  369. # 本脚本来自www.66RPG.com,使用和转载请保留此信息
  370. # 作者:紫苏
  371. #==============================================================================
复制代码

作者: 灼眼的夏娜    时间: 2009-4-24 19:48
不错 支持下!!~ {/qiang}


作者: 小叽    时间: 2009-4-24 19:55
这个东西有实际的应用价值!  如果可以对OGG支持将更完美!  

OGG是我比较常用的格式!游戏的大小会影响下载量.用OGG格式可以大大减少游戏体积.
作者: 迅雷進    时间: 2009-4-24 20:14
实在是太棒啦~
前辈的实力实在是不得不膜拜的说! {/ll} {/ll}
作者: 紫苏    时间: 2009-4-24 20:17
以下引用灼眼的夏娜于2009-4-24 11:48:41的发言:

不错 支持下!!~

没想到会把众神之首引出来~{/cy}
想请教下夏娜,我在 MSDN 里找到了调整 MIDI 节奏的 MCI 命令:
set tempo tempo_value
但是实际测试时没有任何效果(也没有异常),{/pz}
这是什么缘故呢?

以下引用小叽于2009-4-24 11:55:41的发言:

这个东西有实际的应用价值!  如果可以对OGG支持将更完美!  

OGG是我比较常用的格式!游戏的大小会影响下载量.用OGG格式可以大大减少游戏体积.

由于没有现成的 API 可以直接播放 OGG,所以……
理论上俺知道用 OGG 过滤器 + DirectShow 就能实现,不过由于这方面的知识十分浅薄,能力有限,所以还是留待夏娜等神级人物来解决了 o.o

以下引用迅雷進于2009-4-24 12:14:56的发言:

实在是太棒啦~
前辈的实力实在是不得不膜拜的说!   

感谢你的支持{/wx}
作者: redant    时间: 2009-4-24 20:26
每次看到都是 觉得 过于强大{/qiang}

虽然还不是很理解 但绝对是好东西先下载再说
作者: tommay    时间: 2009-4-24 20:31
先存下了,多谢紫苏大大!
作者: 迅雷進    时间: 2009-4-24 20:32
对了,
那个重复音乐是怎样做的呢?
小弟看了很久还是无法看个头绪出来的说… {/gg} {/gg}
请前辈指教~
作者: 紫苏    时间: 2009-4-24 20:42
以下引用迅雷進于2009-4-24 12:32:43的发言:

对了,
那个重复音乐是怎样做的呢?
小弟看了很久还是无法看个头绪出来的说…  
请前辈指教~

地图右上角的并行事件循环判断《浏阳河》当前的位置,单位是毫秒,当大于 20000 毫秒(20 秒)的时候就 seek 跳转回 17000 毫秒(17秒)的位置继续播放,这样播放位置又会在3秒后到达 20 秒的位置,再次跳回 17 秒,这就是个循环了~
作者: 迅雷進    时间: 2009-4-24 21:07
以下引用紫苏于2009-4-24 12:42:42的发言:
地图右上角的并行事件循环判断《浏阳河》当前的位置,单位是毫秒,当大于 20000 毫秒(20 秒)的时候就 seek 跳转回 17000 毫秒(17秒)的位置继续播放,这样播放位置又会在3秒后到达 20 秒的位置,再次跳回 17 秒,这就是个循环了~
看到了~ {/wx} {/wx}
再来一个问题,
只要是那个重复的开关没关上的话,
无论到哪一个地图的话音乐还是一样一直重复的吗?
作者: TERENCE    时间: 2009-4-24 23:30
LZ的扩展音频模块实在太强了,
本龙仔做的BGM前奏+无限循环主旋律就整个弱掉了
(http://rpg.blue/viewthread.php?tid=123326)

好想哭啊~~

作者: 一路一风尘    时间: 2009-4-25 01:55
提示: 作者被禁止或删除 内容自动屏蔽
作者: 紫苏    时间: 2009-4-25 05:51
以下引用迅雷進于2009-4-24 13:07:20的发言:

看到了~  
再来一个问题,
只要是那个重复的开关没关上的话,
无论到哪一个地图的话音乐还是一样一直重复的吗?

到了另外一个地图那个并行事件就不会执行了,音乐就会一直播放到结束……
当然可以用并行公共事件一直重复

以下引用TERENCE于2009-4-24 15:30:47的发言:

LZ的扩展音频模块实在太强了,
本龙仔做的BGM前奏+无限循环主旋律就整个弱掉了
(http://rpg.blue/viewthread.php?tid=123326)

好想哭啊~~

呵呵,两种不同的做法而已~

以下引用一路一风尘于2009-4-24 17:55:46的发言:

记得以前用MCI在播放一些midi音乐时与RM本身播放的声音存在差异,好像多通道播放会出现噪音?印象很浅淡了。

确实是这样,如果我没理解错的话, RM 播放 MIDI 是立体声,而 MCI 调用的 MIDI sequencer 设备(其实就是双击托盘里的喇叭,音量控制属性里的 SW Synth 设备,Windows Media Player 也是用的这个设备播放 MIDI)播放的 MIDI 很容易就能听出不是立体声的,也不知道能否用 MCI 实现立体声~
作者: swabwind    时间: 2009-4-25 08:03
以下引用TERENCE于2009-4-24 15:30:47的发言:

LZ的扩展音频模块实在太强了,
本龙仔做的BGM前奏+无限循环主旋律就整个弱掉了
(http://rpg.blue/viewthread.php?tid=123326)

好想哭啊~~



[本贴由作者于 2009-4-24 15:39:03 最后编辑]


汗,龙哥的那个脚本完全被取代了= =
而且没隔几天。。。囧
LZ你强。。。{/qiang}
作者: 威廉华莱士    时间: 2009-4-25 20:47
不错,楼主很有心,写的很详细...支持!{/qiang}{/qiang}
作者: TERENCE    时间: 2009-4-25 21:04
以下引用swabwind于2009-4-25 0:03:43的发言:
汗,龙哥的那个脚本完全被取代了= =
而且没隔几天。。。囧
LZ你强。。。

再度被打击......

作者: 灼眼的夏娜    时间: 2009-4-26 00:44
tempo tempo_value:
驱动程序无法识别指定的命令参数 异常- -bb

话说mciGetErrorString 还是用W函数吧= =还有@msg 转UTF8  - -b
作者: 紫苏    时间: 2009-4-26 09:11
以下引用威廉华莱士于2009-4-25 12:47:35的发言:

不错,楼主很有心,写的很详细...支持!

感谢

以下引用灼眼的夏娜于2009-4-25 16:44:57的发言:

tempo tempo_value:
驱动程序无法识别指定的命令参数 异常- -bb

话说mciGetErrorString 还是用W函数吧= =还有@msg 转UTF8  - -b

呃,忘了说了,要把 open 的时候设备类型改为 sequencer 才能测试~

错误信息那个已经修正了,忘了错误信息可以是中文……感谢夏娜的指点
作者: 赛露休斯    时间: 2009-4-27 01:20
我为什么范例一打开就出现错误。。。。。


作者: 紫苏    时间: 2009-4-27 06:52
以下引用赛露休斯于2009-4-26 17:20:54的发言:

我为什么范例一打开就出现错误。。。。。

刚发现 1.01 的范例有 BUG,已经修复了,请重新下载一次吧~

另外,请问你的操作系统是否 vista?
作者: 赛露休斯    时间: 2009-4-27 07:10
以下引用紫苏于2009-4-26 22:52:01的发言:
刚发现 1.01 的范例有 BUG,已经修复了,请重新下载一次吧~

另外,请问你的操作系统是否 vista?

XP的操作系统,1.0和1.01 的范例都试过了,依然是同样的错误。。
作者: niji    时间: 2009-4-27 14:31
作为新人虽然不是特别明白,但应该能够学习。{/tp}
作者: 紫苏    时间: 2009-4-27 14:41
以下引用赛露休斯于2009-4-26 23:10:14的发言:

XP的操作系统,1.0和1.01 的范例都试过了,依然是同样的错误。。

所有事件都出错?试试播放 ME 的那个,还有换一首 mp3 播放试试看~
作者: 迅雷進    时间: 2009-4-27 17:20
紫苏君,
当使用循环MP3的功能重复MP3的时候是会停顿一下的吗?
作者: 紫苏    时间: 2009-4-27 19:27
以下引用迅雷進于2009-4-27 9:20:56的发言:

紫苏君,
当使用循环MP3的功能重复MP3的时候是会停顿一下的吗?

seek 命令之后会暂停播放,而 AudioEx 的 seek 函数在发送了 seek 命令,暂停播放后又立刻调用了播放,所以可能会有点停顿~

如果只是想让整首音乐重复的话可以:
AudioEx.open("ME",
"Audio/ME/006-Defeat02.mid")
AudioEx.play("ME", "repeat")


这样 006-Defeat02.mid 就会一直重复播放了
作者: 赛露休斯    时间: 2009-4-28 01:53
以下引用紫苏于2009-4-27 6:41:49的发言:
所有事件都出错?试试播放 ME 的那个,还有换一首 mp3 播放试试看~

每个事件都出错,已经发现问题了,原来是我RMXP无法播放mp3,不过换了平时能正常播放的mid也出同样的错误,换成wma则"Game.exe遇到问题需要关闭"
作者: aecher    时间: 2009-5-11 01:43
有个问题:读档之后上次正在播放的音乐就没了。但是设备名依然被占用着。
作者: 后知后觉    时间: 2009-5-11 22:38
看功能介绍貌似比夏娜以前些的那个强大{/hx}
这下子我的【高精度计时器】也省了,蛤蛤蛤{/cy}


我发现了一个应该算是BUG的东西吧
就拿 浏阳河 这3字来说吧
如果用1000的速度唱这3字
当唱玩浏阳的时候立刻把速度改成1500
这个时候效果正常,接下来唱的是河
但是如果把速度交换一下
一开始用1500的速度唱,唱玩浏阳然后立刻把速度改回1000
这个时候唱的就不是河了,而是不知道唱到哪一段去了
作者: 紫苏    时间: 2009-5-14 18:55
以下引用aecher于2009-5-10 17:43:26的发言:

有个问题:读档之后上次正在播放的音乐就没了。但是设备名依然被占用着。

更新了范例工程,参考给 Game_System 添加的函数吧~
其实这个脚本就是一个库,和 Audio 的性质一样的,所以你说的这个不能算是脚本本身的问题,只是需要去修改 RGSS 的系统来运用这个模块~默认系统的 Game_System 中要是没有记录当前正在播放的音乐,读档后还是不能再次播放之前的音乐的……
以下引用后知后觉于2009-5-11 14:38:39的发言:

我发现了一个应该算是BUG的东西吧
就拿 浏阳河 这3字来说吧
如果用1000的速度唱这3字
当唱玩浏阳的时候立刻把速度改成1500
这个时候效果正常,接下来唱的是河
但是如果把速度交换一下
一开始用1500的速度唱,唱玩浏阳然后立刻把速度改回1000
这个时候唱的就不是河了,而是不知道唱到哪一段去了

感谢汇报,感觉这个应该是因为比特率改变后指针错位的问题,测试了下,从低速变到高速有时也会错位……明天再来研究下这个问题~
作者: 小lim    时间: 2009-5-22 05:56
提示: 作者被禁止或删除 内容自动屏蔽
作者: 玄月    时间: 2009-5-29 23:28
紫苏大……膜拜一下,我终于可以从用coolpro切开音频的噩梦中走出来了
作者: 96310376    时间: 2009-6-1 22:04
提示: 作者被禁止或删除 内容自动屏蔽
作者: 后知后觉    时间: 2009-6-2 12:40
以下引用玄月于2009-5-29 15:28:01的发言:

紫苏大……膜拜一下,我终于可以从用coolpro切开音频的噩梦中走出来了

我用的是 GoldWave感觉还不错

作者: 尤莉斯    时间: 2009-6-3 20:06
{/hx}用这个东西+六之一的Bitmap#marshal+rmxppatch 就可以把RMXP图像和声音部分重新了。。= =
懒惰人的 遁走。。
作者: 月夜驃鱈    时间: 2009-6-5 03:34
提示: 作者被禁止或删除 内容自动屏蔽
作者: 后知后觉    时间: 2009-11-20 12:04
本帖最后由 后知后觉 于 2009-11-20 15:19 编辑

1.03版了啊- -
标题还是1.02呢~!

其实龙仔的那个脚本并没有被完全替代
因为 OGG




欢迎光临 Project1 (https://rpg.blue/) Powered by Discuz! X3.1