If you want to be able to play multiple simultaneous audio files across all platforms in Delphi XE6 Firemonkey you should check out this TGameAudioManager class. I had it built by a professional developer through oDesk and it is architected for playing lots of short sound files (like game sound effects) in Firemonkey. I had need of this class when I was building the Flappy Bird clone and finally got around to having it built. It uses the native sound API from each of the supported platforms which are Windows, Android, IOS, and OSX. The least amount of testing has been done on the OSX implementation but overall it feels pretty solid. For music (long running audio files) you should stick with the built in TMediaPlayer component. The TGameAudioManager class is built so that you pre-register the sounds that you are going to play with AddSound() and then you play them with PlaySound(). It is written in Object Pascal and should also compile in AppMethod (and probably Delphi XE5) without much trouble. There is a mobile and a desktop demo included in the archive. Here is the class type information:
TGameAudioManager = Class
fSoundsList : TList;
fAudioMgr : JAudioManager;
fSoundPool : JSoundPool;
function GetSoundsCount : integer;
function GetSoundFromIndex(Aindex : integer) : PSoundRec;
function AddSound(ASoundFile: string) : integer;
procedure DeleteSound(AName : String); overload;
procedure DeleteSound(AIndex : integer); overload;
procedure PlaySound(AName : String);overload;
procedure PlaySound(AIndex : integer);overload;
property SoundsCount : Integer read GetSoundsCount;
property Sounds[AIndex : integer] : PSoundRec read GetSoundFromIndex ;
Download TGameAudioManager, the free audio manager wrapper class in Delphi XE6 Firemonkey for Android, IOS, Windows, and OSX.
A procedure to play audio from resources in windows could be a nice addition to this class:
procedure TGameAudioManager.PlayRCSound(AIndex: integer);
if AIndex < fSoundsList.Count then
wRec := fSoundsList[AIndex];
MMSystem.PlaySound(Pchar(wRec.SFilename), hInstance, SND_RESOURCE or SND_ASYNC);
On E:Exception do
Raise Exception.create('[Unknown Name] : '+E.message);
Sadly, this code is incompatible with Delphi 10.2 (Tokyo) at least under Android (windows works fine), the onLoadComplete is never triggered for Android, causing GLoaded to remain false and the app to freeze.
If anyone has a fix for this, I would appreciate it.
I think I managed to solve the problem in Android. You need to change the code en the assignment of the listener. They are assigning a type not an instance.
Find this code:
wOnAndroidSndComplete := TJSoundPool_OnLoadCompleteListener.Wrap((TOnSpoolLoadCallBack.Create as ILocalObject).GetObjectID);
and use something like this:
OnSpoolLoadCallBack : TOnSpoolLoadCallBack;
OnSpoolLoadCallBack := TOnSpoolLoadCallBack.Create;
wOnAndroidSndComplete := TJSoundPool_OnLoadCompleteListener.Wrap(
(OnSpoolLoadCallBack as ILocalObject).GetObjectID);
GLoaded := False;
GLoaded := Not False;
It avoid the wait loop. I know is not the best solution but it work for me this way.
I also moved the ding?.wav files to another location in my phone and modified the path in UNIT8 just in case that the demo folder is locked or whatever.
The sample will work and you will have sound.
You are such a genius! Changed what you told. Also changed the wav paths to home and made deployments accordingly. Just needed some launcher screen things. It ran on android. Thanks FMXexpress! This blog is unique and wonderful!