【问题标题】:Crossplatform audio support in DelphiDelphi 中的跨平台音频支持
【发布时间】:2018-05-15 03:41:54
【问题描述】:

我正在运行 Delphi Tokyo,我正在寻找一种在 Windows 和 Android 上播放音频的方法(也许在某些时候 iOS)。

在 Windows 上,我可以使用 PlaySound(PChar(ResourceName), 0, SND_RESOURCE or SND_ASYNC) 之类的东西,但我被困在 Android 上。我试过 TMediaPlayer,但它开始播放大约需要一秒钟,这对于鼠标单击或屏幕点击来说太长了。

基本上我已经构建了一个扫雷克隆,我正在寻找声音支持(如果你想知道背景)。

建议?

【问题讨论】:

  • 您没有展示您如何使用媒体播放器 - 您只向我们展示了有效的代码!请提供minimal reproducible example
  • MediaPlayer 为我立即播放 mp3(即没有延迟)。也许您可能想分享您正在使用的声音文件和/或代码
  • 我应该推荐你使用 Delphi Berlin for Android,而不是 Tokyo,因为它有问题。

标签: android delphi audio firemonkey


【解决方案1】:

有一些街机游戏演示具有可以使用的音频类。见https://github.com/Embarcadero/DelphiArcadeGames

您还可以查看Is there an alternative to TMediaPlayer for multi platform rapid sound effects?,了解这些演示中使用音频管理类在 Android 上遇到的一些问题。

使用游戏示例中提供的最新版本的音频管理器,开发人员只需删除所有通知/检查音频文件是否已实际加载并准备好播放。我个人不喜欢仅仅期待音频可以播放的想法。

我的音频管理课程有点过于复杂,无法简单地发布,但如果您需要此功能,希望这段伪代码可以提供一些线索,说明我如何解决游戏演示中提供的 AudioManager 的缺点。

这个想法是在我的主应用程序中创建一个回调,当音频文件准备好播放时调用该回调。通过一些网络搜索,我发现以下链接对我的实现很有帮助:

https://developer.android.com/reference/android/media/SoundPool

https://www.101apps.co.za/articles/using-android-s-soundpool-class-a-tutorial.html

1 - 定义一个通知类型,它将提供有关准备播放的音频文件的足够信息。我的看起来像这样:

TSoundLoadedEvent = procedure(Sender: TObject; ASoundID: integer; AStatus: Integer) of object;

2 - 根据文档,定义一个处理 JSoundPool_OnLoadCompleteListener 的类。请注意,该类使用了我们定义为TSoundLoadedEvent 的自定义事件,这意味着AudioManager 必须实现此回调:

TMyAudioLoadedListener = class(TJavaLocal, JSoundPool_OnLoadCompleteListener)
  private
    FSoundPool       : JSoundPool;
    FOnJLoadCompleted : TSoundLoadedEvent;
  public
    procedure onLoadComplete(soundPool: JSoundPool; sampleId,status: Integer); cdecl;
    property  OnLoadCompleted: TSoundLoadedEvent read FOnJLoadCompleted write FOnJLoadCompleted;
    property  SoundPool: JSoundPool read FSoundPool;
  end;

...

procedure TMyAudioLoadedListener.onLoadComplete(soundPool: JSoundPool; sampleId, status: Integer);
begin
  FSoundPool := soundPool;
  if Assigned(FOnJLoadCompleted) then
    FOnJLoadCompleted(Self, sampleID, status);
end;

3 - 修改音频管理器类以实现监听器:

  TAudioManager = Class
    Private
      fAudioMgr              : JAudioManager;
      fSoundPool             : JSoundPool;
      fmyAudioLoadedListener : TMyAudioLoadedListener;
      fOnPlatformLoadComplete : TSoundLoadedEvent;
    Public
      Constructor Create; override;
      ...
      procedure DoOnLoadComplete(Sender: TObject; sampleId: Integer; status: Integer);
      ...
      property  OnLoadComplete: TSoundLoadedEvent read fOnPlatformLoadComplete write fOnPlatformLoadComplete;

4 - 实现JSoundPool 监听器并将回调从监听器连接到我们的AudioManager

constructor TAudioManger.Create;
begin
  ...
  //create our listener
  fmyAudioLoadedListener := TMyAudioLoadedListener.Create;

  // set the listener callback 
  fmyAudioLoadedListener.OnLoadCompleted := DoOnLoadComplete;

  // inform JSoundPool that we have a listener
  fSoundPool.setOnLoadCompleteListener( fmyAudioLoadedListener ); 
  ...

procedure TAudioManager.DoOnLoadComplete(Sender: TObject; sampleId: Integer; status: Integer);
begin
  if Succeeded(status) then  //remove this if you want all notifications
  begin
    if Assigned(Self.fOnPlatformLoadComplete) then
      fOnPlatformLoadComplete( self, sampleID, status );
  end;
end;

5 - 最后一件事是在主应用程序中实现回调:

TMainForm = class(TForm)
  ...
  fAudioMgr   :  TAudioManager;
  ...
  procedure OnSoundLoaded(Sender: TObject; ASoundID: integer; AStatus: integer);

然后,在您创建AudioManager 的地方,将新的TSoundLoadedEvent 分配给我称为OnSoundLoaded 的本地过程:

procedure TMainForm.FormCreate(Sender: TObject);
...
begin
  ...
  fAudioMgr := TAudioManager.Create;
  fAudioMgr.OnSoundLoaded := OnSoundLoaded;

现在,当音频文件准备好播放时,您应该会收到通知:

procedure TMainForm.OnSoundLoaded(Sender: TObject; ASoundID: integer; AStatus: integer);
begin
  // track IDs when loading sounds to identify which one is ready
  // check status to confirm that the audio was loadded successfully
end;

这绝对只​​是零碎的,但希望能有所帮助。

【讨论】:

    猜你喜欢
    • 2010-09-07
    • 2022-09-23
    • 2011-03-11
    • 2014-08-02
    • 2023-03-14
    • 2011-11-13
    • 2019-03-14
    • 2021-09-04
    • 1970-01-01
    相关资源
    最近更新 更多