【问题标题】:Is there an alternative to TMediaPlayer for multi platform rapid sound effects?是否有替代 TMediaPlayer 的多平台快速音效?
【发布时间】:2018-04-09 13:19:33
【问题描述】:

我正在寻找一种在多平台游戏(Android 和 Windows)中以低开销播放多种快速音效(WAV 格式)的方法。

我尝试使用 TMediaPlayer 组件,但创建多个实例会增加启动和关闭时间的大量开销。

我研究并发现此代码提供了一种低开销的方法。遗憾的是,该代码与 Android 下的 Delphi 10.2 (Tokyo) 不兼容(windows 工作正常)。在 Android 下,永远不会触发 onLoadComplete,导致 GLoaded 标志保持为 false 并且应用程序冻结。 http://www.fmxexpress.com/free-game-audio-manager-wrapper-class-in-delphi-xe6-firemonkey-for-android-ios-windows-and-osx/

有谁知道替代解决方案或能理解为什么 GameAudioManager 回调函数无法触发?

【问题讨论】:

  • 它可能有助于提供您如何实际使用 TGameAudioManager 的代码。我猜如果文件不存在就不会调用onLoadComplete,例如
  • GameAudioManager 存档中包含的多平台示例代码(包括多个 wav 文件)冻结。我还仔细检查了“fileexists”是否返回 true。这是存档fmxexpress.com/wp-content/uploads/2014/08/GameAudioManager.7z
  • 您检查过 BASS 音频库 (un4seen.com)。现在它不是免费的,但它确实支持 Delphi 支持的所有平台。更不用说它还支持大量不同的文件格式。与游戏音频管理器不同的是,您提到 BASS 音频适用于播放短音频文件或较长音频文件,您可以自行控制是否要从内存或直接从磁盘播放某些文件。
  • 我不确定我的游戏的任何收入是否能支付许可费用,所以现在我正在尝试寻找免费的替代方案,但如果情况发生变化,我已将您的建议添加为书签.
  • 对于 android/ios,您可以尝试 ALvideoPlayer (github.com/Zeus64/alcinoe) 并使用它来播放声音。我在启动时在不到 100 毫秒的时间内加载了大约 10 个视频播放器

标签: delphi firemonkey


【解决方案1】:

编辑:我的初始测试是在柏林完成的,而 OP 使用的是东京。以下结果适用于柏林。请进一步了解东京。

我很好奇为什么您提供的 FMXExpress 链接中的代码不起作用,因为我在我的多平台音频类中使用了非常相似的代码。所以我决定下载代码并试一试。

演示应用程序查找 3 个特定文件 ding1.wav、ding2.wav 和 ding3.wav;在 Windows 上,它会在文档文件夹中查找文件,而在 Android 上,它会在 assets\internal 中查找文件

对于 Windows,我必须将一些音频文件复制到文档文件夹并相应地重命名它们。正如您所报告的那样,该应用程序运行良好。 (Windows 10 版本 1709)。

对于 Android,我首先查看了项目的部署设置。列出了 3x 音频文件,但本地路径为空白。我只是取消选中现有条目并从我的文档文件夹中重新添加它们,并将每个条目的 远程路径 设置为 assets\internal。直接在我连接的设备上编译应用程序,它运行良好。 Android SDK 24.3.3 32 位,运行 Android 7.0 的 LG-V522 G-Pad III

编辑 - 东京问题描述:

OP 是正确的;使用 Tokyo 10.2.3 编译时,链接的示例代码不起作用

简单的调试表明从未调用回调TOnSpoolLoadCallBack.onLoadComplete,这是将全局GLoaded 设置为True 所必需的。效果是应用程序在以下代码中无限循环:

TGameAudioManager.AddSound

while not GLoaded do
begin
  Sleep(10);
  Application.ProcessMessages;
end;

为了使代码工作,(这是一个 hack)添加一个计数器来限制循环可以运行的次数。像这样的...

procedure TGameAudioManager.AddSound(...)
const
  MaxWaitLoop = 10;
var
  ...
  loopCount : integer;
Begin
  ...
  loopCount := 0;
  while not GLoaded AND (loopCount < MaxWaitLoop) do
  begin
    inc(loopCount);
    Sleep(10);
    Application.ProcessMessages;
  end;
  ...

通过一些逻辑来防止无限循环,应用程序现在可以运行,并且可以在 Android 设备上听到音频。

注意事项:

  • 您现在需要弄清楚为什么回调在东京不起作用。在快速检查并与柏林进行比较后,这对我来说并不明显。
  • 您不应在生产中使用此代码。 Application.ProcessMessages 几乎总是指向不好 执行。相反,回调应该冒泡到您的主应用程序中,例如,您可以在其中启用 UI 元素

【讨论】:

  • 我很困惑,部署中的 3x wav 文件的本地路径为空白,因为它们与项目文件位于同一路径中。我正在使用与您相同版本的 Android SDK。即便如此,我取消选中部署条目,将音频文件复制到“我的文档”,然后从“我的文档”添加它们并设置远程路径。我在 2 台设备(Galaxy S2、Galaxy Note4)和 NOX 模拟器上进行了测试,没有任何区别。请注意,原始代码甚至在尝试添加声音之前都会检查“文件存在”,所以这不是问题。对我来说,只要单击“添加声音”按钮,示例应用就会冻结。
  • 很高兴您能够复制我的发现(由于未调用回调而导致冻结)。问题是,如果我没有可靠的回调函数让我知道音频已加载,我怎么知道音频何时准备好播放?我一直无法弄清楚为什么在东京没有触发回调。
  • 我认为这是东京的一个错误,所以我在这里创建了一个质量控制报告quality.embarcadero.com/browse/RSP-20370。您现在可以使用 Berlin,等待 QC 报告的回复和/或专门针对未触发的回调发布另一个问题。
  • 我目前没有时间更深入地研究您的问题,但有一些提示:Tokyo 在 Android 上更改了线程模型。上面的代码将不再起作用。以前回调和你的阻塞循环在不同的线程上运行,现在你用循环阻塞线程,回调根本没有机会。忘记同步编程,删除阻塞循环并使用回调,因为它旨在通过将需要在回调之后运行的逻辑添加到回调中来使用。即使这意味着您需要添加将运行自定义代码的额外事件,
【解决方案2】:

似乎有更新版本的“GameAudioManager”单元(现在称为“AudioManager”)与 Delphi Tokyo 上的 Android 兼容。我查看了代码,它似乎只是删除了“onload”回调和“loaded”检查循环。

这是更新后的代码: https://github.com/Embarcadero/DelphiArcadeGames/blob/master/Full/AlienInvasion/AudioManager.pas

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-06-21
    • 1970-01-01
    • 1970-01-01
    • 2018-04-11
    • 2020-02-27
    • 1970-01-01
    相关资源
    最近更新 更多