查看: 3327|回复: 17

[讨论] 【关于Audio模块】有没有可能让它更智能一些?

[复制链接]
梦石
24
星屑
8942
在线时间
248 小时
注册时间
2020-12-4
回帖
259

极短24获奖极短23获奖极短22获奖

发表于 2022-8-2 13:26:01 | 显示全部楼层 |阅读模式

加入我们,或者,欢迎回来。

您需要 登录 才可以下载或查看,没有账号?注册会员

×
本帖最后由 纯属小虫 于 2022-8-20 21:56 编辑

玩了很多华丽的画面效果之后,却发现自己在音乐方面的研究还是一片空白
甚至连简单的【改变音乐正在播放的时刻】都做不到

按下F1,搜索Audio,查看模块方法:

[fold=Audio 模块方法]Audio.bgm_play(filename[, volume[, pitch]])
开始 BGM 的播放。其顺序为文件名,音量,指定节拍。

Audio.bgm_stop
停止 BGM 的播放。

Audio.bgm_fade(time)
开始 BGM 的淡出。time 指定淡出的时间,单位为毫秒。

Audio.bgs_play(filename[, volume[, pitch]])
开始 BGS 的播放。其顺序为文件名,音量,指定节拍。

Audio.bgs_stop
停止 BGS 的播放。

Audio.bgs_fade(time)
开始 BGS 的淡出。time 指定淡出的时间,单位为毫秒。

Audio.me_play(filename[, volume[, pitch]])
开始 ME 的播放。其顺序为文件名,音量,指定节拍。

Audio.me_stop
停止 ME 的播放。

Audio.me_fade(time)
开始 ME 的淡出。time 指定淡出的时间,单位为毫秒。。

Audio.se_play(filename[, volume[, pitch]])
开始 SE 的播放。其顺序为文件名,音量,指定节拍。

Audio.se_stop
停止全部 SE 的播放。[/fold]

可以发现,这个远古的老小可爱,只给了【播放】【停止】【淡出】三个指令
看来不是我不会拖动播放滑块,而是它没给啊!
(好吧,自己菜不能怪工具......)

一直想要做一个效果:
在BGM不更换的情况下,进入战斗或脱离战斗,地图BGM或战斗BGM能够从上次结束的位置继续播放
这样一来,在频繁战斗的情况下,就不会被两首BGM的开头疯狂洗脑了(有一种听起床铃的既视感)
如果BGM比较长的话,每次都从头播放...甚至游戏结束了都没听到过这首BGM之后的旋律,实在是尴尬...

这里想了一个实现这个效果的逻辑:
1、战斗开始时,记录当前【地图BGM】名称,当前【地图BGM】时刻
2、战斗开始时,播放【战斗BGM】,如果【战斗BGM】与被记录的【战斗BGM】名称相同,则从被记录的【战斗BGM】时刻开始播放
3、战斗结束时,记录【战斗BGM】名称,当前【战斗BGM】时刻
4、战斗结束时,播放【地图BGM】,如果【地图BGM】与被记录的【地图BGM】名称相同,则从被记录的【地图BGM】时刻开始播放

具体在脚本中实现方法如下:(该脚本已经作废)
[fold=拟写效果代码][pre lang="ruby"]# 目的:尝试让 BGM 在【战斗】和【地图】之间切换的时候,不会从头开始!

# 每次打开游戏都会初始化的音频临时变量
module Xiao虫
  BGM_上次地图 = nil
  BGM_上次地图seek = 0
  BGM_上次战斗 = nil
  BGM_上次战斗seek = 0
end


class Game_System
  #--------------------------------------------------------------------------
  # ● 演奏 BGM
  #     bgm : 演奏的 BGM
  #--------------------------------------------------------------------------
  def bgm_play(bgm)
    if bgm != nil and bgm.name != ""
      # 如果即将播放的是地图BGM
      if bgm == $game_temp.map_bgm
        # 如果没有记录音乐,或者地图的音乐发生了改变;则计时器初始化
        if Xiao虫::BGM_上次地图 == nil or Xiao虫::BGM_上次地图 != bgm
          Xiao虫::BGM_上次地图 = bgm
          Xiao虫::BGM_上次地图seek = 0
        end
        # 记录战斗音乐
        Xiao虫::BGM_上次战斗 = $game_system.battle_bgm
        Xiao虫::BGM_上次战斗seek = 【获取当前播放BGM的时刻】
        # 播放地图音乐
        Audio.bgm_play("Audio/BGM/" + bgm.name, bgm.volume, bgm.pitch)
        【将播放的BGM时刻移动至】 Xiao虫::BGM_上次地图seek
      # 如果即将播放的是战斗BGM
      elsif bgm == $game_system.battle_bgm
        # 如果没有记录音乐,或者地图的音乐发生了改变;则计时器初始化
        if Xiao虫::BGM_上次战斗 == nil or Xiao虫::BGM_上次战斗 != bgm
          Xiao虫::BGM_上次战斗 = bgm
          Xiao虫::BGM_上次战斗seek = 0
        end
        # 记录地图音乐
        Xiao虫::BGM_上次地图 = $game_temp.map_bgm
        Xiao虫::BGM_上次地图seek = 【获取当前播放BGM的时刻】
        # 播放战斗音乐
        Audio.bgm_play("Audio/BGM/" + bgm.name, bgm.volume, bgm.pitch)
        【将播放的BGM时刻移动至】 Xiao虫::BGM_上次地图seek
      # 如果仅仅是正常播放(上述都不是)
      else
        Audio.bgm_play("Audio/BGM/" + bgm.name, bgm.volume, bgm.pitch)
      end
    else
      Audio.bgm_stop
    end
    Graphics.frame_reset
  end
end
[/pre][/fold]

可见,如果能够有 【获取当前播放BGM的时刻】 和 【将播放的BGM时刻移动至】 这两个Audio的方法的话,可能就可以实现这种效果了

害...可是要怎么解析Audio模块并为其添加新的方法呢...
欢迎各位大佬前来讨论




2022.08.20
可喜可贺! 制作出来一个能够实现上述功能的实例了!

工程范例:(附件太大没法上传)
链接:https://pan.baidu.com/s/1v1twJ6TkkNdSd41rzxc0yg?pwd=6666
提取码:6666
--来自百度网盘超级会员V6的分享

[fold=实际运用的实例脚本][pre lang="ruby"]# 目的:尝试让 BGM 在【战斗】和【地图】之间切换的时候,不会从头开始!

# 每次打开游戏都会初始化的音频临时变量
module Xiao虫
  $上次地图_bgm = nil
  $上次地图_bgm_pos = 0
  $上次战斗_bgm = nil
  $上次战斗_bgm_pos = 0
end

#==============================================================================
# ■ Scene_Title
#------------------------------------------------------------------------------
#  标题界面关闭所有拓展
#==============================================================================
class Scene_Title
  alias main_音频拓展 main
  def main
    Audio.bgm_stop
    main_音频拓展
  end
end

class Game_System
  #--------------------------------------------------------------------------
  # ● 演奏 BGM
  #     bgm : 演奏的 BGM
  #--------------------------------------------------------------------------
  def bgm_play(bgm)
    # =====================================================================
    # 如果即将播放的是地图BGM(战斗结束)
    #======================================================================
    if $game_temp != nil and bgm == $game_temp.map_bgm
      # 记录战斗的BGM和时刻
      $上次战斗_bgm = $game_system.playing_bgm.name if $game_system.playing_bgm != nil
      $上次战斗_bgm_pos = Audio.bgm_pos
      $上次战斗_bgm_pos = 0 if $上次战斗_bgm_pos == nil
      # 如果bgm是空的,则停止播放
      if bgm == nil or bgm.name == ""
        Audio.bgm_stop
      # 如果记录的地图BGM为空,则正常播放
      elsif $上次地图_bgm == nil
        Audio.bgm_play("Audio/BGM/" + bgm.name,bgm.volume,bgm.pitch)
      # 如果记录了地图BGM,且记录的与要播放的【不同】,则正常播放
      elsif $上次地图_bgm != nil and $上次地图_bgm != bgm.name
        Audio.bgm_play("Audio/BGM/" + bgm.name,bgm.volume,bgm.pitch)
      # 如果记录了地图BGM,且记录的与要播放的【相同】,则承接播放
      elsif $上次地图_bgm != nil and $上次地图_bgm == bgm.name
        Audio.bgm_play("Audio/BGM/" + bgm.name,bgm.volume,bgm.pitch,-$上次地图_bgm_pos)
      # 其他情况,正常播放
      else
        Audio.bgm_play("Audio/BGM/" + bgm.name,bgm.volume,bgm.pitch)
      end
    # =====================================================================
    # 如果即将播放的是战斗BGM(战斗开始)
    #======================================================================
    elsif $game_temp != nil and bgm == $game_system.battle_bgm
      # 记录地图的BGM和时刻
      $上次地图_bgm = $game_system.playing_bgm.name if $game_system.playing_bgm != nil
      $上次地图_bgm_pos = Audio.bgm_pos
      $上次地图_bgm_pos = 0 if $上次地图_bgm_pos == nil
      # 如果bgm是空的,则停止播放
      if bgm == nil or bgm.name == ""
        Audio.bgm_stop
      # 如果记录的战斗BGM为空,则正常播放
      elsif $上次战斗_bgm == nil
        Audio.bgm_play("Audio/BGM/" + bgm.name,bgm.volume,bgm.pitch)
      # 如果记录了战斗BGM,且记录的与要播放的【不同】,则正常播放
      elsif $上次战斗_bgm != nil and $上次战斗_bgm != bgm.name
        Audio.bgm_play("Audio/BGM/" + bgm.name,bgm.volume,bgm.pitch)
      # 如果记录了战斗BGM,且记录的与要播放的【相同】,则承接播放
      elsif $上次战斗_bgm != nil and $上次战斗_bgm == bgm.name
        Audio.bgm_play("Audio/BGM/" + bgm.name,bgm.volume,bgm.pitch,-$上次战斗_bgm_pos)
      # 其他情况,正常播放
      else
        Audio.bgm_play("Audio/BGM/" + bgm.name,bgm.volume,bgm.pitch)
      end
    # =====================================================================
    # 其他情况,播放的既不是战斗也不是地图(标题,强制BGM之类)
    #======================================================================
    else
      if bgm == nil or bgm.name == ""
        Audio.bgm_stop
      else
        Audio.bgm_play("Audio/BGM/" + bgm.name,bgm.volume,bgm.pitch)
      end
    end
    # =====================================================================
    # 后续处理
    # =====================================================================
    # 更新正在播放的BGM
    @playing_bgm = bgm
    Graphics.frame_reset
=begin
    p "$上次地图_bgm【" + $上次地图_bgm.to_s + "】" + "$上次地图_bgm_pos【"  + $上次地图_bgm_pos.to_s + "】"
    p "$上次战斗_bgm【" + $上次战斗_bgm.to_s + "】" + "$上次战斗_bgm_pos【"  + $上次战斗_bgm_pos.to_s + "】"
=end
  end
end

# 重新定义一下调用战斗的处理(避免地图BGM被停止而无法在play里被记忆)
class Scene_Map
  #--------------------------------------------------------------------------
  # ● 调用战斗
  #--------------------------------------------------------------------------
  def call_battle
    # 清除战斗调用标志
    $game_temp.battle_calling = false
    # 清除菜单调用标志
    $game_temp.menu_calling = false
    $game_temp.menu_beep = false
    # 生成遇敌计数
    $game_player.make_encounter_count
    # 记忆地图 BGM 、停止 BGM
    $game_temp.map_bgm = $game_system.playing_bgm
    # $game_system.bgm_stop
    # 演奏战斗开始 SE
    $game_system.se_play($data_system.battle_start_se)
    # 演奏战斗 BGM
    $game_system.bgm_play($game_system.battle_bgm)
    # 矫正主角姿势
    $game_player.straighten
    # 切换到战斗画面
    $scene = Scene_Battle.new
  end
end[/pre][/fold]

[fold=API插件(需要搭配dll使用!)][pre lang="ruby"]
#=begin
# fmod很强,API很多,但我对音频不了解,也不太关注,通常玩游戏都是静音的
# 所以只写了很基(简)本(陋)的功能

# 文件格式为官方原文的网页翻译
# - 支持内置超过 20 种音频格式
# FMOD Core API 具有本机/内置代码,以支持许多开箱即用的文件格式。
# 默认支持 WAV、MP3 和 Ogg Vorbis,但也支持更多模糊格式,如 AIFF、FLAC 等。
# 包括使用实时音序器实时回放的音序格式。MIDI/MOD/S3M/XM/IT 就是这些例子。

# 尽管F12不会直接报错,但内存泄漏了,具体屏蔽F12方法论坛搜索

module FmodLite
  # fmodLite.dll依赖的dll
  # 方法1:预先手动LoadLibrary,fmod.dll可存放目录自由
  Win32API.new('kernel32', 'LoadLibrary', 'P', 'L').call("fmod.dll")
  # 方法2:fmod.dll与Game.exe同目录,可注释上一行代码


  #—————————————————————————————————
  # 适用于BGM/BGS,和 RMXP Audio 一样,窗口非激活也继续播放音频
  # bug:API并没有太多的参数检查
  # 基本:首先创建系统
  #         创建单元(每个都是独立的,该音频持续期间保留该单元字符串)
  #           api操作该单元
  #             需手动结束该单元
  #       最后释放系统(基本就是结束游戏了)
  #—————————————————————————————————
  dll = "fmodLite.dll"

  # 【系统相关】
  # ◆创建系统
  # 参数1:系统指针,至少4字节字符串;
  # 参数2:Fmod的范围[0, 4095],可以理解为同时播放的单元数目;
  Init  = Win32API.new(dll, 'fmod_init', 'PL', 'L')
  # ◆释放系统
  Close = Win32API.new(dll, 'fmod_close', 'V', 'V')

  # 【单元相关】
  # ◆创建并播放
  # 参数1:音频文件名;
  # 参数2:节拍,100为正常;
  # 参数3:音量,100为正常;
  # 参数4:播放位置,单位毫秒,如果需要“音量淡入”,设为负值(0写为-1);
  # 参数5:循环标志,0不循环,非0循环;
  # 参数6:单元指针,个人定义的结构,至少12字节字符串;
  Play = Win32API.new(dll, 'fmod_play', 'PLLLLP', 'L')
  # ◆结束
  # 参数1:单元指针,传其字符串即可;
  Stop = Win32API.new(dll, 'fmod_stop', 'P', 'L')
  # ◆淡出
  # 参数1:单元指针,传其字符串即可;
  # 参数2:淡出时间,单位毫秒;
  Fade = Win32API.new(dll, 'fmod_fade', 'PL', 'L')
  # ◆获取播放的时间位置,单位毫秒
  # 参数1:单元指针,传其字符串即可;
  Pos  = Win32API.new(dll, 'fmod_pos', 'P', 'L')
  # ◆延迟以播放另一个音效
  # 参数1:音效文件名;
  # 参数2:节拍;
  # 参数3:音量;
  # 参数4:该音效的单元指针;
  # 参数5:被延迟播放的单元指针;
  PlayDelay = Win32API.new(dll, 'fmod_play_delay', 'PLLPP', 'L')

  # 创建fmod_system
  PPSys = "\0" * 4
  Init.call(PPSys, 32)
  PPSys.freeze

  #————————
  # 读取RTP目录
  #————————
  ini, section, rtp_flag = "Game.ini", "[Game]", "RTP"
  get_section, rtps = false, []

  File.open(ini).each_line do |line|
    line.chop!
    next if line.empty?
    if line == section
      get_section = true
      next
    end
    next if get_section == false
    rtps << line.split("=")[1] if line.include?(rtp_flag)
  end

  rtps.uniq!
  RTP = []
  rtps.each do |i|
    if i != nil
      if i == "Standard"

        dll = "Advapi32.dll"
        regOpenKeyExA = Win32API.new(dll, 'RegOpenKeyExA', 'LPLLP', 'L')
        regCloseKey = Win32API.new(dll, 'RegCloseKey', 'L', 'L')
        regQueryValueExA = Win32API.new(dll, 'RegQueryValueExA', 'LPLLPP', 'L')

sub_key = "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\App Paths\\RPGXP.exe"

        buf = "\0" * 4
        # HKEY_LOCAL_MACHINE = 0x8000_0002
        # KEY_READ  = 0x20019
        regOpenKeyExA.call(0x8000_0002, sub_key, 0, 0x20019, buf)

        hKey = buf.unpack('L')[0]        
        regQueryValueExA.call(hKey, nil, 0, 0, nil, buf)
        path = "\0" * buf.unpack('L')[0]
        regQueryValueExA.call(hKey, nil, 0, 0, path, buf)
        regCloseKey.call(hKey)

        RTP << (File.dirname(path.chop!).gsub("\\", "/") << "/RGSS/Standard")
      else
        RTP << i if File.directory?(i)
      end
    end
  end

  module_function

  # filename 是指相对路径 如 "Audio/BGM/abc"
  # 编辑器保存的音乐文件名没有扩展名……( ̄_ ̄|||)

  def find_rtp_file(filename)
    RTP.each do |path|
      name = Dir["#{File.join(path, filename)}.**"][0]
      return name if name != nil
    end
    return
  end

  def get_file(filename)
    name = Dir["#{filename}.**"][0]
    name ||= find_rtp_file(filename)
  end   
end


END {FmodLite::Close.call()}


# 简单示例,这部分就自由发挥吧
class << Audio

  @@bgm = "\0" * 12
  @@me = "\0" * 12
  @@bgm_file_name = ""
  @@me_file_name = ""

  def bgm_play(filename, volume = 100, pitch = 100, pos = 0, loop = 1)

    if filename == @@bgm_file_name
      return
    else
      self.bgm_stop
    end

    if (name = FmodLite.get_file(filename)) == nil
      self.bgm_stop
      return
    end

    @@bgm_file_name = filename
    FmodLite::Play.call(name, volume, pitch, pos, loop, @@bgm)
  end

  def bgm_stop
    return if @@bgm_file_name.empty?
    FmodLite::Stop.call(@@bgm)
    @@bgm_file_name = ""
  end

  def bgm_fade(ms)
    return if @@bgm_file_name.empty?
    FmodLite::Fade.call(@@bgm, ms)
  end

  # 获取bgm当前的时间
  def bgm_pos
    return if @@bgm_file_name.empty?
    FmodLite::Pos.call(@@bgm)
  end

  # 重新定义me的播放,以让bgm播放能够暂停
  def me_play(filename, volume = 100, pitch = 100)

    if filename == @@bgm_file_name
      return
    else
      self.me_stop
    end

    if (name = FmodLite.get_file(filename)) == nil
      self.me_stop
      return
    end

    @@me_file_name = filename
    FmodLite::PlayDelay.call(name ,volume ,pitch ,@@me ,@@bgm)
  end
end
#=end
[/pre][/fold]

音频拓展dll.zip (731.14 KB, 下载次数: 11)

感谢 【RPGzh500223】伙伴的资源!!!

评分

参与人数 1赞 +1 收起 理由
89444640 + 1 塞糖

查看全部评分

梦石
0
星屑
29896
在线时间
5733 小时
注册时间
2016-3-8
回帖
1653
发表于 2022-8-2 13:34:59 | 显示全部楼层
本帖最后由 alexncf125 于 2022-8-8 13:47 编辑

Audio.bgm_play(filename[, volume[, pitch[, pos]]])
开始播放 BGM。依次指定文件名、音量、音调和起始位置。
起始位置  只对 ogg 和 wav 有效。

Audio.bgm_pos
获取 BGM 的播放位置。只对 ogg 和 wav 有效。无效时返回 0。

点评

感激涕零!不过ogg、wav... TAT得批量转格式了!  发表于 2022-8-2 21:33
回复

使用道具 举报

梦石
1
星屑
24088
在线时间
3339 小时
注册时间
2011-7-8
回帖
3862

开拓者

发表于 2022-8-2 15:07:14 | 显示全部楼层
好的,马上在新runtime里加上这个功能

点评

很nice 我常用的都是MP3和wav ^.^  发表于 2022-8-3 10:16
mid不行,MP3应该可以  发表于 2022-8-2 22:23
如果还能对ogg wav之外的音频有效,那可谓普天同庆~  发表于 2022-8-2 22:10
熟悉rgss和ruby,xp区版主~
正在填坑:《膜拜组传奇》讲述膜拜组和学霸们的故事。
已上steam:与TXBD合作的Reformers《变革者》
* 战斗调用公共事件 *
* RGSOS 网络脚本 *
回复

使用道具 举报

梦石
0
星屑
6483
在线时间
119 小时
注册时间
2020-1-8
回帖
205
发表于 2022-8-19 18:20:12 | 显示全部楼层
[pre lang="ruby"]#=begin
# fmod很强,API很多,但我对音频不了解,也不太关注,通常玩游戏都是静音的
# 所以只写了很基(简)本(陋)的功能

# 文件格式为官方原文的网页翻译
# - 支持内置超过 20 种音频格式
# FMOD Core API 具有本机/内置代码,以支持许多开箱即用的文件格式。
# 默认支持 WAV、MP3 和 Ogg Vorbis,但也支持更多模糊格式,如 AIFF、FLAC 等。
# 包括使用实时音序器实时回放的音序格式。MIDI/MOD/S3M/XM/IT 就是这些例子。

# 尽管F12不会直接报错,但内存泄漏了,具体屏蔽F12方法论坛搜索

module FmodLite
  # fmodLite.dll依赖的dll
  # 方法1:预先手动LoadLibrary,fmod.dll可存放目录自由
  Win32API.new('kernel32', 'LoadLibrary', 'P', 'L').call("fmod.dll")
  # 方法2:fmod.dll与Game.exe同目录,可注释上一行代码

  
  #—————————————————————————————————
  # 适用于BGM/BGS,和 RMXP Audio 一样,窗口非激活也继续播放音频
  # bug:API并没有太多的参数检查
  # 基本:首先创建系统
  #         创建单元(每个都是独立的,该音频持续期间保留该单元字符串)
  #           api操作该单元
  #             需手动结束该单元
  #       最后释放系统(基本就是结束游戏了)
  #—————————————————————————————————
  dll = "fmodLite.dll"
  
  # 【系统相关】
  # ◆创建系统
  # 参数1:系统指针,至少4字节字符串;
  # 参数2:Fmod的范围[0, 4095],可以理解为同时播放的单元数目;
  Init  = Win32API.new(dll, 'fmod_init', 'PL', 'L')
  # ◆释放系统
  Close = Win32API.new(dll, 'fmod_close', 'V', 'V')
  
  # 【单元相关】
  # ◆创建并播放
  # 参数1:音频文件名;
  # 参数2:节拍,100为正常;
  # 参数3:音量,100为正常;
  # 参数4:播放位置,单位毫秒,如果需要“音量淡入”,设为负值(0写为-1);
  # 参数5:循环标志,0不循环,非0循环;
  # 参数6:单元指针,个人定义的结构,至少12字节字符串;
  Play = Win32API.new(dll, 'fmod_play', 'PLLLLP', 'L')
  # ◆结束
  # 参数1:单元指针,传其字符串即可;
  Stop = Win32API.new(dll, 'fmod_stop', 'P', 'L')
  # ◆淡出
  # 参数1:单元指针,传其字符串即可;
  # 参数2:淡出时间,单位毫秒;
  Fade = Win32API.new(dll, 'fmod_fade', 'PL', 'L')
  # ◆获取播放的时间位置,单位毫秒
  # 参数1:单元指针,传其字符串即可;
  Pos  = Win32API.new(dll, 'fmod_pos', 'P', 'L')
  
  
  # 创建fmod_system
  PPSys = "\0" * 4
  Init.call(PPSys, 32)
  PPSys.freeze
  
  #————————
  # 读取RTP目录
  #————————
  ini, section, rtp_flag = "Game.ini", "[Game]", "RTP"
  get_section, rtps = false, []
  
  File.open(ini).each_line do |line|
    line.chop!
    next if line.empty?
    if line == section
      get_section = true
      next
    end
    next if get_section == false
    rtps << line.split("=")[1] if line.include?(rtp_flag)
  end
  
  rtps.uniq!
  RTP = []
  rtps.each do |i|
    if i != nil
      if i == "Standard"
        
        dll = "Advapi32.dll"
        regOpenKeyExA = Win32API.new(dll, 'RegOpenKeyExA', 'LPLLP', 'L')
        regCloseKey = Win32API.new(dll, 'RegCloseKey', 'L', 'L')
        regQueryValueExA = Win32API.new(dll, 'RegQueryValueExA', 'LPLLPP', 'L')
        
sub_key = "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\App Paths\\RPGXP.exe"

        buf = "\0" * 4
        # HKEY_LOCAL_MACHINE = 0x8000_0002
        # KEY_READ  = 0x20019
        regOpenKeyExA.call(0x8000_0002, sub_key, 0, 0x20019, buf)
        
        hKey = buf.unpack('L')[0]        
        regQueryValueExA.call(hKey, nil, 0, 0, nil, buf)
        path = "\0" * buf.unpack('L')[0]
        regQueryValueExA.call(hKey, nil, 0, 0, path, buf)
        regCloseKey.call(hKey)

        RTP << (File.dirname(path.chop!).gsub("\\", "/") << "/RGSS/Standard")
      else
        RTP << i if File.directory?(i)
      end
    end
  end
  
  module_function
  
  # filename 是指相对路径 如 "Audio/BGM/abc"
  # 编辑器保存的音乐文件名没有扩展名……( ̄_ ̄|||)
   
  def find_rtp_file(filename)
    RTP.each do |path|
      name = Dir["#{File.join(path, filename)}.**"][0]
      return name if name != nil
    end
    return
  end
  
  def get_file(filename)
    name = Dir["#{filename}.**"][0]
    name ||= find_rtp_file(filename)
  end   
end


END {FmodLite::Close.call()}


# 简单示例,这部分就自由发挥吧
class << Audio
  
  @@bgm = "\0" * 12
  @@bgm_file_name = ""
  
  def bgm_play(filename, volume = 100, pitch = 100, pos = 0, loop = 1)
   
    if filename == @@bgm_file_name
      return
    else
      self.bgm_stop
    end
      
    if (name = FmodLite.get_file(filename)) == nil
      self.bgm_stop
      return
    end

    @@bgm_file_name = filename
    FmodLite::Play.call(name, volume, pitch, pos, loop, @@bgm)
  end
  
  def bgm_stop
    return if @@bgm_file_name.empty?
    FmodLite::Stop.call(@@bgm)
    @@bgm_file_name = ""
  end
  
  def bgm_fade(ms)
    return if @@bgm_file_name.empty?
    FmodLite::Fade.call(@@bgm, ms)
  end
  
  def bgm_pos
    return if @@bgm_file_name.empty?
    FmodLite::Pos.call(@@bgm)
  end
end
#=end[/pre]

dll.zip

711.58 KB, 下载次数: 8

fmod.dll和fmodLite.dll

点评

不过好像有一个小瑕疵,就是播放ME的时候,不会像原RGSS那样暂停BGM  发表于 2022-8-20 14:55
好强大,居然支持这么多种音频,回头试试效果!  发表于 2022-8-19 18:59

评分

参与人数 2赞 +2 收起 理由
89444640 + 1 精品文章
纯属小虫 + 1 塞糖

查看全部评分

回复 1 0

使用道具 举报

梦石
24
星屑
8942
在线时间
248 小时
注册时间
2020-12-4
回帖
259

极短24获奖极短23获奖极短22获奖

 楼主| 发表于 2022-8-19 20:09:43 | 显示全部楼层
RPGzh500223 发表于 2022-8-19 18:20
#=begin
# fmod很强,API很多,但我对音频不了解,也不太关注,通常玩游戏都是静音的
# 所以只写了很基(简) ...

试了下,确实很强大!!!

MP3文件成功从中间开始播放
不过,有没有什么方法能够获取【当前播放的BGM的名称】以及【当前BGM所播放到的时刻】?

点评

感谢感谢!!!!!!!我要成功了!  发表于 2022-8-20 13:26
FmodLite::Pos就是当前播放时刻啊,至于名称你传参时保存一下不就行了吗,参考示例中@@bgm_file_name ……  发表于 2022-8-19 20:50
回复

使用道具 举报

梦石
24
星屑
8942
在线时间
248 小时
注册时间
2020-12-4
回帖
259

极短24获奖极短23获奖极短22获奖

 楼主| 发表于 2022-8-20 13:41:11 | 显示全部楼层
可喜可贺!!! 多亏了 RPGzh500223 的 API插件,终于实现了期待了一个月的效果!

具体的脚本和实现方法放在楼顶了

BGM在地图与战斗之间能够承接播放!
工程范例:(附件太大,没法上传,用百度链接了!)
链接:https://pan.baidu.com/s/1GBWJX_wgmr-Y6TP4sohXgQ?pwd=6666
提取码:6666
--来自百度网盘超级会员V6的分享

因为测试的场景太少,可能会有BUG,不过能用!
回复

使用道具 举报

梦石
0
星屑
6483
在线时间
119 小时
注册时间
2020-1-8
回帖
205
发表于 2022-8-20 18:52:07 | 显示全部楼层
[pre lang="ruby"]module FmodLite
  # ◆延迟以播放另一个音效
  # 参数1:音效文件名;
  # 参数2:节拍;
  # 参数3:音量;
  # 参数4:该音效的单元指针;
  # 参数5:被延迟播放的单元指针;
  PlayDelay = Win32API.new(dll, 'fmod_play_delay', 'PLLPP', 'L')
end[/pre]

没打算写成完整的Audio……前面就写明了适用于BGM/BGS
勉强模拟BGM时延迟以播放ME

fmodLite.zip

4.23 KB, 下载次数: 8

fmodLite.dll

点评

感谢!!!成功实现了!  发表于 2022-8-20 21:49

评分

参与人数 1赞 +1 收起 理由
纯属小虫 + 1 塞糖

查看全部评分

回复

使用道具 举报

梦石
0
星屑
39236
在线时间
11155 小时
注册时间
2009-3-15
回帖
4768
发表于 2022-8-20 21:03:48 | 显示全部楼层
本帖最后由 soulsaga 于 2022-8-21 10:20 编辑

用了第三方音频脚本F1设定关BGM等都没效了..

点评

想关bgm直接把音量变成0也行?  发表于 2022-8-22 21:58
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 注册会员

本版积分规则

Powered by Discuz! X5.0 © 2001-2026 Discuz! Team.

在本版发帖返回顶部