DLSound.pas
上传用户:yj_qiu
上传日期:2022-08-08
资源大小:23636k
文件大小:7k
源码类别:

游戏引擎

开发平台:

Delphi

  1. (*
  2.  @Abstract(Simple Audiere-based audio unit)
  3.  (C) 2006-2008 George "Mirage" Bakhtadze. <a href="http://www.casteng.com">www.casteng.com</a> <br>
  4.  The source code may be used under either MPL 1.1 or LGPL 2.1 license. See included license.txt file <br>
  5.  Created: May 16, 2007 <br>
  6.  Unit contains simple audiere-based sound and music implementation
  7. *)
  8. {$Include GDefines.inc}
  9. unit DLSound;
  10. interface
  11. uses
  12.   BaseMsg, Basics,
  13.   Timer,
  14.   SysUtils,
  15.   TextFile,
  16.   Audiere;
  17. const
  18.   // Sounds collection capacity increment step
  19.   SoundsCapacityStep = 16;
  20.   // Default minimal delay between sound play
  21.   DefaultDelayMs = 0.150;
  22. type
  23.   TAdrSound = packed record
  24.     Name: string[43];
  25.     LastPlayed, MinDelay: TSecond;
  26.     Volume: Single;
  27.     Device: TAdrAudioDevice;
  28.     Stream: TAdrOutputStream;
  29.     Source: TAdrSampleSource;
  30.   end;
  31.   // Sound management class
  32.   TAudiereSound = class(TSubsystem)
  33.   private
  34.     FTimer: TTimer;
  35.     MasterVolume: Single;
  36.     FSounds: array of TAdrSound;
  37.     TotalSounds: Integer;
  38.     function IndexOf(const Name: string): Integer;
  39.     procedure UnloadByIndex(Index: Integer);
  40.   public
  41.     constructor Create(ATimer: TTimer);
  42.     destructor Destroy; override;
  43.     procedure HandleMessage(const Msg: TMessage); override;
  44.     { Loads a sound from file FileName. If AStreamin is false the file will completely loaded into memory.
  45.       The loaded sound later can be referenced by Name. }
  46.     procedure Load(const Name, FileName: string; AStreaming: Boolean);
  47.     // Frees a sound with the given name
  48.     procedure UnLoad(const Name: string);
  49.     // Sets volume of the named sound in percents. If name is empty master (affecting all sounds) volume will be changed.
  50.     procedure SetVolume(const Name: string; Value: Integer);
  51.     // Enables or disables repeating of the named sound
  52.     procedure SetRepeat(const Name: string; Value: Boolean);
  53.     // Sets minimal delay between two possible subsequent Play() calls of the named sound
  54.     procedure SetDelay(const Name: string; Value: Double);
  55.     // Plays the named sound. Many instances of the same sound can be played simultaneously.
  56.     procedure Play(const Name: string);
  57.     // Stops the sound playback
  58.     procedure Stop(const Name: string);
  59.   end;
  60. implementation
  61. { TAudiereSound }
  62. function TAudiereSound.IndexOf(const Name: string): Integer;
  63. begin
  64.   Result := TotalSounds-1;
  65.   while (Result >= 0) and (FSounds[Result].Name <> Name) do Dec(Result);
  66. end;
  67. procedure TAudiereSound.UnloadByIndex(Index: Integer);
  68. begin
  69.   Assert((Index >= 0) and (Index < TotalSounds), '');
  70.   if (Index < 0) or (Index >= TotalSounds) then Exit;
  71.   
  72.   FSounds[Index].Stream.Stop;
  73. //  if Assigned(FSounds[Index].Stream) then FreeAndNil(FSounds[Index].Stream);
  74. //  if Assigned(FSounds[Index].Source) then FreeAndNil(FSounds[Index].Source);
  75. //  if Assigned(FSounds[Index].Device) then FreeAndNil(FSounds[Index].Device);
  76.   Dec(TotalSounds);
  77.   FSounds[Index] := FSounds[TotalSounds];
  78. end;
  79. constructor TAudiereSound.Create(ATimer: TTimer);
  80. var s: PChar;
  81. begin
  82. //  Assert(Assigned(ATimer), 'TAudiereSound.Create: ATimer should be assigned');
  83.   MasterVolume := 0.5;
  84.   {$IFDEF LOGGING}
  85.   s := AdrGetVersion;
  86.   Log.Log('Audiere version: ' + s, lkNotice);
  87.   s := AdrGetSupportedFileFormats;   Log.Log('  formats supported: ' + s);   s := AdrGetSupportedAudioDevices;   Log.Log('  devices supported: ' + s);   {$ENDIF}   FTimer := ATimer; end;
  88. destructor TAudiereSound.Destroy;
  89. var i: Integer;
  90. begin
  91.   for i := TotalSounds-1 downto 0 do UnloadByIndex(i);
  92.   inherited;
  93. end;
  94. procedure TAudiereSound.Load(const Name, FileName: string; AStreaming: Boolean);
  95. begin
  96.   if IndexOf(Name) <> -1 then begin
  97.     Log.Log('TAudiereSound.Load: Sound "' + Name + '" already defined', lkError);
  98.     Exit;
  99.   end;
  100.   if Length(FSounds) <= TotalSounds then SetLength(FSounds, Length(FSounds) + SoundsCapacityStep);
  101.   FSounds[TotalSounds].Stream := nil;
  102.   FSounds[TotalSounds].Name   := Name;
  103.   FSounds[TotalSounds].Volume := 0.5;
  104.   FSounds[TotalSounds].Device := AdrOpenDevice('', '');
  105.   if Assigned(FSounds[TotalSounds].Device) then begin
  106.     FSounds[TotalSounds].Source := AdrOpenSampleSource(PChar(Filename), FF_AUTODETECT);
  107.     if Assigned(FSounds[TotalSounds].Source) then
  108.       FSounds[TotalSounds].Stream := AdrOpenSound(FSounds[TotalSounds].Device, FSounds[TotalSounds].Source, AStreaming);
  109.   end;
  110.   if FSounds[TotalSounds].Stream = nil then begin
  111. //    if Assigned(FSounds[TotalSounds].Source) then FreeAndNil(FSounds[TotalSounds].Source);
  112. //    if Assigned(FSounds[TotalSounds].Device) then FreeAndNil(FSounds[TotalSounds].Device);
  113.     Log.Log('TAudiereSound.Load: Error loading sound file "' + FileName + '"', lkError);
  114.   end else begin
  115.     FSounds[TotalSounds].Stream.SetVolume(FSounds[TotalSounds].Volume * MasterVolume);
  116.     FSounds[TotalSounds].LastPlayed := 0;
  117.     FSounds[TotalSounds].MinDelay   := DefaultDelayMs;
  118.     Inc(TotalSounds);
  119.   end;
  120. end;
  121. procedure TAudiereSound.UnLoad(const Name: string);
  122. var i: Integer;
  123. begin
  124.   i := IndexOf(Name);
  125.   if i >= 0 then UnloadByIndex(i) else begin
  126.     {$IFDEF LOGGING} Log.Log('TAudiereSound.UnLoad: Sound "' + Name + '" not found', lkWarning); {$ENDIF}
  127.   end;
  128. end;
  129. procedure TAudiereSound.SetVolume(const Name: string; Value: Integer);
  130. var i: Integer;
  131. begin
  132.   if Name = '' then begin
  133.     MasterVolume := MinS(1, Value/100);
  134.     for i := 0 to TotalSounds-1 do FSounds[i].Stream.SetVolume(FSounds[i].Volume * MasterVolume);
  135.   end else begin
  136.     i := IndexOf(Name);
  137.     if i >= 0 then begin
  138.       FSounds[i].Volume := MinS(1, Value/100);
  139.       FSounds[i].Stream.SetVolume(FSounds[i].Volume * MasterVolume);
  140.     end else begin
  141.       {$IFDEF LOGGING} Log.Log('TAudiereSound.SetVolume: Sound "' + Name + '" not found', lkWarning); {$ENDIF}
  142.     end;
  143.   end;
  144. end;
  145. procedure TAudiereSound.SetRepeat(const Name: string; Value: Boolean);
  146. var i: Integer;
  147. begin
  148.   i := IndexOf(Name);
  149.   if i >= 0 then
  150.     FSounds[i].Stream.SetRepeat(Value) else begin
  151.       {$IFDEF LOGGING} Log.Log('TAudiereSound.SetRepeat: Sound "' + Name + '" not found', lkWarning); {$ENDIF}
  152.     end;
  153. end;
  154. procedure TAudiereSound.SetDelay(const Name: string; Value: Double);
  155. var i: Integer;
  156. begin
  157.   i := IndexOf(Name);
  158.   if i >= 0 then
  159.     FSounds[i].MinDelay := Value else begin
  160.       {$IFDEF LOGGING} Log.Log('TAudiereSound.SetDelay: Sound "' + Name + '" not found', lkWarning); {$ENDIF}
  161.     end;
  162. end;
  163. procedure TAudiereSound.Play(const Name: string);
  164. var i: Integer;
  165. begin
  166.   i := IndexOf(Name);
  167.   if i >= 0 then begin
  168.     if (FSounds[i].LastPlayed = 0) or not Assigned(FTimer) or (FTimer.Time - FSounds[i].LastPlayed > FSounds[i].MinDelay) then begin
  169.       FSounds[i].Stream.Reset;
  170.       FSounds[i].Stream.Play;
  171.       if Assigned(FTimer) then FSounds[i].LastPlayed := FTimer.LastTime;
  172.     end;
  173.   end else
  174.     Log.Log('TAudiereSound.Play: Sound "' + Name + '" not found', lkWarning);
  175. end;
  176. procedure TAudiereSound.Stop(const Name: string);
  177. var i: Integer;
  178. begin
  179.   i := IndexOf(Name);
  180.   if i >= 0 then
  181.     FSounds[i].Stream.Stop else begin
  182.       Log.Log('TAudiereSound.Stop: Sound "' + Name + '" not found', lkWarning);
  183.     end;
  184. end;
  185. procedure TAudiereSound.HandleMessage(const Msg: TMessage);
  186. begin
  187. //  if
  188. end;
  189. end.