从资源播放 .wav 文件
Playing .wav file from resource
我正在使用 Firemonkey 编写 android 应用程序。
因此我无法使用 MMSystem 的函数 sndPlaySound 从资源文件播放,因为那只是 Windows。
Firemonkey 支持媒体播放器工作和资源。但是媒体播放器不能直接使用资源文件。
如何使用 TMediaPlayer 播放资源中的声音?
正在播放不在文件中的媒体
TMediaPlayer does not natively implement any non-filesystem data sources,
so you will have to implement your own custom codec/media classes to access
(and play) the resource data however you want. TMediaPlayer itself does
not care if its FileName exists on a filesystem or not. It simply asks the
TMediaCodecManager class to retreive a suitable TMedia object to access and
play the data from whatever source the FileName refers to.
Create a custom class that derives from FMX.Media.TMedia and implement its
abstract methods as needed (DoPlay(), DoStop(), GetDuration(), etc). This
class accesses and plays the actual media data, so you can pass the desired
FileName to it and have it load/access your resource stream as needed. Look
at the default TMedia implementations for examples (FMX.Media.Win.TWindowsMedia,
FMX.Media.Mac.TQTMedia, etc).
Create a custom class that derives from FMX.Media.TCustomMediaCodec and implement
its abstract CreateFromFile() method to return an instance of your custom
TMedia class. You can then register this class at program startup using
FMX.Media.TMediaCodecManager.RegisterMediaCodecClass(). The trick is that
you have to register the class using a file extension, so pick something
that is unique and cannot be confused for a real file.
例如:
unit PlayMediaFromResource;
uses
..., FMX.Media;
type
TMyResourceMedia = class(TMedia)
...
protected
function GetDuration: TMediaTime; override;
function GetCurrent: TMediaTime; override;
procedure SetCurrent(const Value: TMediaTime); override;
function GetVideoSize: TPointF; override;
function GetMediaState: TMediaState; override;
function GetVolume: Single; override;
procedure SetVolume(const Value: Single); override;
procedure UpdateMediaFromControl; override;
procedure DoPlay; override;
procedure DoStop; override;
public
constructor Create(const AFileName: string); override;
destructor Destroy; override;
end;
TMyResourceMediaCodec = class(TCustomMediaCodec)
public
function CreateFromFile(const AFileName: string): TMedia; override;
end;
function TMyResourceMediaCodec.CreateFromFile(const AFileName: string): TMedia;
begin
Result := TMyResourceMedia.Create(AFileName);
end;
constructor TMyResourceMedia.Create(const AFileName: string);
var
ResName: string;
begin
ResName := ChangeFileExt(AFileName, ''); // strip off '.myres' file extension
// load resource identified by ResName as needed...
end;
....
initialization
TMediaCodecManager.RegisterMediaCodecClass('.myres', 'My Resource Stream',
TMediaType.Audio, TMyResourceMediaCodec);
那么你可以这样做:
MediaPlayer1.FileName := 'MyResourceName.myres';
MediaPlayer1.Play;
end;
--
或者您可以将资源保存到文件中
如果您能以某种方式将资源保存到文件并从那里播放,那么一切都会容易得多。您可以只使用股票 TMediaPlayer。
播放完毕不要忘记删除文件,否则会占满磁盘。
我正在使用 Firemonkey 编写 android 应用程序。
因此我无法使用 MMSystem 的函数 sndPlaySound 从资源文件播放,因为那只是 Windows。
Firemonkey 支持媒体播放器工作和资源。但是媒体播放器不能直接使用资源文件。
如何使用 TMediaPlayer 播放资源中的声音?
正在播放不在文件中的媒体
TMediaPlayer does not natively implement any non-filesystem data sources, so you will have to implement your own custom codec/media classes to access (and play) the resource data however you want. TMediaPlayer itself does not care if its FileName exists on a filesystem or not. It simply asks the TMediaCodecManager class to retreive a suitable TMedia object to access and play the data from whatever source the FileName refers to.
Create a custom class that derives from FMX.Media.TMedia and implement its abstract methods as needed (DoPlay(), DoStop(), GetDuration(), etc). This class accesses and plays the actual media data, so you can pass the desired FileName to it and have it load/access your resource stream as needed. Look at the default TMedia implementations for examples (FMX.Media.Win.TWindowsMedia, FMX.Media.Mac.TQTMedia, etc).
Create a custom class that derives from FMX.Media.TCustomMediaCodec and implement its abstract CreateFromFile() method to return an instance of your custom TMedia class. You can then register this class at program startup using FMX.Media.TMediaCodecManager.RegisterMediaCodecClass(). The trick is that you have to register the class using a file extension, so pick something that is unique and cannot be confused for a real file.
例如:
unit PlayMediaFromResource;
uses
..., FMX.Media;
type
TMyResourceMedia = class(TMedia)
...
protected
function GetDuration: TMediaTime; override;
function GetCurrent: TMediaTime; override;
procedure SetCurrent(const Value: TMediaTime); override;
function GetVideoSize: TPointF; override;
function GetMediaState: TMediaState; override;
function GetVolume: Single; override;
procedure SetVolume(const Value: Single); override;
procedure UpdateMediaFromControl; override;
procedure DoPlay; override;
procedure DoStop; override;
public
constructor Create(const AFileName: string); override;
destructor Destroy; override;
end;
TMyResourceMediaCodec = class(TCustomMediaCodec)
public
function CreateFromFile(const AFileName: string): TMedia; override;
end;
function TMyResourceMediaCodec.CreateFromFile(const AFileName: string): TMedia;
begin
Result := TMyResourceMedia.Create(AFileName);
end;
constructor TMyResourceMedia.Create(const AFileName: string);
var
ResName: string;
begin
ResName := ChangeFileExt(AFileName, ''); // strip off '.myres' file extension
// load resource identified by ResName as needed...
end;
....
initialization
TMediaCodecManager.RegisterMediaCodecClass('.myres', 'My Resource Stream',
TMediaType.Audio, TMyResourceMediaCodec);
那么你可以这样做:
MediaPlayer1.FileName := 'MyResourceName.myres';
MediaPlayer1.Play;
end;
--
或者您可以将资源保存到文件中
如果您能以某种方式将资源保存到文件并从那里播放,那么一切都会容易得多。您可以只使用股票 TMediaPlayer。
播放完毕不要忘记删除文件,否则会占满磁盘。