DEADSOFTWARE

can load non-looping music; fixed looping ROUNDMUS
[d2df-sdl.git] / src / engine / e_sound_fmod.inc
index ceb0c0fc5f4b3d3c9caacbae0dd5028517315c9e..36d4932387d1f73e120a12368b460dc9079aba10 100644 (file)
@@ -1,9 +1,25 @@
+(* Copyright (C)  Doom 2D: Forever Developers
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *)
 interface
 
 uses
   fmod,
   fmodtypes,
   fmoderrors,
+  {$IFDEF USE_MEMPOOL}mempool,{$ENDIF}
   e_log,
   SysUtils;
 
@@ -15,7 +31,7 @@ type
     nRefs: Integer;
   end;
 
-  TBasicSound = class (TObject)
+  TBasicSound = class{$IFDEF USE_MEMPOOL}(TPoolObject){$ENDIF}
   private
     FChannel: FMOD_CHANNEL;
 
@@ -50,10 +66,10 @@ type
 const
   NO_SOUND_ID = DWORD(-1);
 
-function e_InitSoundSystem(): Boolean;
+function e_InitSoundSystem(NoOutput: Boolean = False): Boolean;
 
-function e_LoadSound(FileName: string; var ID: DWORD; bLoop: Boolean): Boolean;
-function e_LoadSoundMem(pData: Pointer; Length: Integer; var ID: DWORD; bLoop: Boolean): Boolean;
+function e_LoadSound(FileName: string; var ID: DWORD; isMusic: Boolean; ForceNoLoop: Boolean = False): Boolean;
+function e_LoadSoundMem(pData: Pointer; Length: Integer; var ID: DWORD; isMusic: Boolean; ForceNoLoop: Boolean = False): Boolean;
 
 function e_PlaySound(ID: DWORD): Integer;
 function e_PlaySoundPan(ID: DWORD; Pan: Single): Integer;
@@ -75,7 +91,7 @@ var
 implementation
 
 uses
-  g_window, g_options, BinEditor;
+  g_window, g_options, utils;
 
 const
   N_CHANNELS = 512;
@@ -117,24 +133,24 @@ end;
 
 function TryInitWithOutput(Output: FMOD_OUTPUTTYPE; OutputName: String): FMOD_RESULT;
 begin
-  e_WriteLog('Trying with ' + OutputName + '...', MSG_WARNING);
+  e_WriteLog('Trying with ' + OutputName + '...', TMsgType.Warning);
   Result := FMOD_System_SetOutput(F_System, Output);
   if Result <> FMOD_OK then
   begin
-    e_WriteLog('Error setting FMOD output to ' + OutputName + '!', MSG_WARNING);
-    e_WriteLog(FMOD_ErrorString(Result), MSG_WARNING);
+    e_WriteLog('Error setting FMOD output to ' + OutputName + '!', TMsgType.Warning);
+    e_WriteLog(FMOD_ErrorString(Result), TMsgType.Warning);
     Exit;
   end;
   Result := FMOD_System_Init(F_System, N_CHANNELS, FMOD_INIT_NORMAL, nil);
   if Result <> FMOD_OK then
   begin
-    e_WriteLog('Error initializing FMOD system!', MSG_WARNING);
-    e_WriteLog(FMOD_ErrorString(Result), MSG_WARNING);
+    e_WriteLog('Error initializing FMOD system!', TMsgType.Warning);
+    e_WriteLog(FMOD_ErrorString(Result), TMsgType.Warning);
     Exit;
   end;
 end;
 
-function e_TrySS (Freq: Integer; forceNoSound: Boolean): Boolean;
+function e_TrySS (Freq: Integer; forceNoSound: Integer): Boolean;
 var
   res: FMOD_RESULT;
   ver: Cardinal;
@@ -143,89 +159,106 @@ var
 
 begin
   Result := False;
-  e_WriteLog(Format('Trying to initialize FMOD with %d', [Freq]), MSG_NOTIFY);
+  e_WriteLog(Format('Trying to initialize FMOD with %d', [Freq]), TMsgType.Notify);
 
   res := FMOD_System_Create(F_System);
   if res <> FMOD_OK then
   begin
-    e_WriteLog('Error creating FMOD system:', MSG_FATALERROR);
-    e_WriteLog(FMOD_ErrorString(res), MSG_FATALERROR);
+    e_WriteLog('Error creating FMOD system:', TMsgType.Fatal);
+    e_WriteLog(FMOD_ErrorString(res), TMsgType.Fatal);
     Exit;
   end;
 
   res := FMOD_System_GetVersion(F_System, ver);
   if res <> FMOD_OK then
   begin
-    e_WriteLog('Error getting FMOD version:', MSG_FATALERROR);
-    e_WriteLog(FMOD_ErrorString(res), MSG_FATALERROR);
+    e_WriteLog('Error getting FMOD version:', TMsgType.Fatal);
+    e_WriteLog(FMOD_ErrorString(res), TMsgType.Fatal);
     Exit;
   end;
 
   if ver < FMOD_VERSION then
   begin
-    e_WriteLog('FMOD library version is too old! Need '+IntToStr(FMOD_VERSION), MSG_FATALERROR);
+    e_WriteLog('FMOD library version is too old! Need '+IntToStr(FMOD_VERSION), TMsgType.Fatal);
     Exit;
   end;
 
   res := FMOD_System_SetSoftwareFormat(F_System, Freq, FMOD_SOUND_FORMAT_PCM16, 0, 0, FMOD_DSP_RESAMPLER_LINEAR);
   if res <> FMOD_OK then
   begin
-    e_WriteLog('Error setting FMOD software format!', MSG_FATALERROR);
-    e_WriteLog(FMOD_ErrorString(res), MSG_FATALERROR);
+    e_WriteLog('Error setting FMOD software format!', TMsgType.Fatal);
+    e_WriteLog(FMOD_ErrorString(res), TMsgType.Fatal);
     Exit;
   end;
 
-  res := FMOD_System_Init(F_System, N_CHANNELS, FMOD_INIT_NORMAL, nil);
-  if res <> FMOD_OK then
+  if forceNoSound = 2 then
   begin
-    e_WriteLog('Error initializing FMOD system!', MSG_WARNING);
-    e_WriteLog(FMOD_ErrorString(res), MSG_WARNING);
-
-    {$IFDEF LINUX}
-    res := TryInitWithOutput(FMOD_OUTPUTTYPE_ALSA, 'OUTPUTTYPE_ALSA');
-    if res <> FMOD_OK then
-      res := TryInitWithOutput(FMOD_OUTPUTTYPE_OSS, 'OUTPUTTYPE_OSS');
-    {$ENDIF}
-    if (res <> FMOD_OK) and not forceNoSound then Exit;
-    if res <> FMOD_OK then
-      res := TryInitWithOutput(FMOD_OUTPUTTYPE_NOSOUND, 'OUTPUTTYPE_NOSOUND');
+    res := TryInitWithOutput(FMOD_OUTPUTTYPE_NOSOUND, 'OUTPUTTYPE_NOSOUND');
     if res <> FMOD_OK then
     begin
-      e_WriteLog('FMOD: Giving up, can''t init any output.', MSG_FATALERROR);
+      e_WriteLog('FMOD: Giving up, can''t init with NOSOUND.', TMsgType.Fatal);
       Exit;
     end;
+  end
+  else
+  begin
+    res := FMOD_System_Init(F_System, N_CHANNELS, FMOD_INIT_NORMAL, nil);
+    if res <> FMOD_OK then
+    begin
+      e_WriteLog('Error initializing FMOD system!', TMsgType.Warning);
+      e_WriteLog(FMOD_ErrorString(res), TMsgType.Warning);
+
+      {$IFDEF LINUX}
+      res := TryInitWithOutput(FMOD_OUTPUTTYPE_ALSA, 'OUTPUTTYPE_ALSA');
+      if res <> FMOD_OK then
+        res := TryInitWithOutput(FMOD_OUTPUTTYPE_OSS, 'OUTPUTTYPE_OSS');
+      {$ENDIF}
+      if (res <> FMOD_OK) and (forceNoSound <> 1) then Exit;
+      if res <> FMOD_OK then
+        res := TryInitWithOutput(FMOD_OUTPUTTYPE_NOSOUND, 'OUTPUTTYPE_NOSOUND');
+      if res <> FMOD_OK then
+      begin
+        e_WriteLog('FMOD: Giving up, can''t init any output.', TMsgType.Fatal);
+        Exit;
+      end;
+    end;
   end;
 
   res := FMOD_System_GetOutput(F_System, output);
   if res <> FMOD_OK then
-    e_WriteLog('Error getting FMOD output!', MSG_WARNING)
+    e_WriteLog('Error getting FMOD output!', TMsgType.Warning)
   else
     case output of
-      FMOD_OUTPUTTYPE_NOSOUND: e_WriteLog('FMOD Output Method: NOSOUND', MSG_NOTIFY);
-      FMOD_OUTPUTTYPE_NOSOUND_NRT: e_WriteLog('FMOD Output Method: NOSOUND_NRT', MSG_NOTIFY);
-      FMOD_OUTPUTTYPE_DSOUND: e_WriteLog('FMOD Output Method: DSOUND', MSG_NOTIFY);
-      FMOD_OUTPUTTYPE_WINMM: e_WriteLog('FMOD Output Method: WINMM', MSG_NOTIFY);
-      FMOD_OUTPUTTYPE_OPENAL: e_WriteLog('FMOD Output Method: OPENAL', MSG_NOTIFY);
-      FMOD_OUTPUTTYPE_WASAPI: e_WriteLog('FMOD Output Method: WASAPI', MSG_NOTIFY);
-      FMOD_OUTPUTTYPE_ASIO: e_WriteLog('FMOD Output Method: ASIO', MSG_NOTIFY);
-      FMOD_OUTPUTTYPE_OSS:  e_WriteLog('FMOD Output Method: OSS', MSG_NOTIFY);
-      FMOD_OUTPUTTYPE_ALSA: e_Writelog('FMOD Output Method: ALSA', MSG_NOTIFY);
-      else e_WriteLog('FMOD Output Method: Unknown', MSG_NOTIFY);
+      FMOD_OUTPUTTYPE_NOSOUND: e_WriteLog('FMOD Output Method: NOSOUND', TMsgType.Notify);
+      FMOD_OUTPUTTYPE_NOSOUND_NRT: e_WriteLog('FMOD Output Method: NOSOUND_NRT', TMsgType.Notify);
+      FMOD_OUTPUTTYPE_DSOUND: e_WriteLog('FMOD Output Method: DSOUND', TMsgType.Notify);
+      FMOD_OUTPUTTYPE_WINMM: e_WriteLog('FMOD Output Method: WINMM', TMsgType.Notify);
+      FMOD_OUTPUTTYPE_OPENAL: e_WriteLog('FMOD Output Method: OPENAL', TMsgType.Notify);
+      FMOD_OUTPUTTYPE_WASAPI: e_WriteLog('FMOD Output Method: WASAPI', TMsgType.Notify);
+      FMOD_OUTPUTTYPE_ASIO: e_WriteLog('FMOD Output Method: ASIO', TMsgType.Notify);
+      FMOD_OUTPUTTYPE_OSS:  e_WriteLog('FMOD Output Method: OSS', TMsgType.Notify);
+      FMOD_OUTPUTTYPE_ALSA: e_Writelog('FMOD Output Method: ALSA', TMsgType.Notify);
+      else e_WriteLog('FMOD Output Method: Unknown', TMsgType.Notify);
     end;
 
   res := FMOD_System_GetDriver(F_System, drv);
   if res <> FMOD_OK then
-    e_WriteLog('Error getting FMOD driver!', MSG_WARNING)
+    e_WriteLog('Error getting FMOD driver!', TMsgType.Warning)
   else
-    e_WriteLog('FMOD driver id: '+IntToStr(drv), MSG_NOTIFY);
+    e_WriteLog('FMOD driver id: '+IntToStr(drv), TMsgType.Notify);
 
   Result := True;
 end;
 
-function e_InitSoundSystem(): Boolean;
+function e_InitSoundSystem(NoOutput: Boolean = False): Boolean;
 begin
-  Result := e_TrySS(48000, False);
-  if not Result then Result := e_TrySS(44100, True);
+  if NoOutput then
+  begin
+    Result := e_TrySS(48000, 2);
+    Exit;
+  end;
+  Result := e_TrySS(48000, 0);
+  if not Result then Result := e_TrySS(44100, 1);
 end;
 
 function FindESound(): DWORD;
@@ -253,7 +286,7 @@ begin
     end;
 end;
 
-function e_LoadSound(FileName: String; var ID: DWORD; bLoop: Boolean): Boolean;
+function e_LoadSound(FileName: String; var ID: DWORD; isMusic: Boolean; ForceNoLoop: Boolean = False): Boolean;
 var
   find_id: DWORD;
   res: FMOD_RESULT;
@@ -263,16 +296,16 @@ var
 begin
   Result := False;
 
-  e_WriteLog('Loading sound '+FileName+'...', MSG_NOTIFY);
+  e_WriteLog('Loading sound '+FileName+'...', TMsgType.Notify);
 
   find_id := FindESound();
 
-  if bLoop then
+  if isMusic and not ForceNoLoop then
     bt := FMOD_LOOP_NORMAL
   else
     bt := FMOD_LOOP_OFF;
 
-  if not bLoop then
+  if not isMusic then
     res := FMOD_System_CreateSound(F_System, PAnsiChar(FileName),
              bt + FMOD_2D + FMOD_HARDWARE,
              nil, e_SoundsArray[find_id].Sound)
@@ -296,7 +329,7 @@ begin
   end;
 
   e_SoundsArray[find_id].Data := nil;
-  e_SoundsArray[find_id].isMusic := bLoop;
+  e_SoundsArray[find_id].isMusic := isMusic;
   e_SoundsArray[find_id].nRefs := 0;
 
   ID := find_id;
@@ -304,7 +337,7 @@ begin
   Result := True;
 end;
 
-function e_LoadSoundMem(pData: Pointer; Length: Integer; var ID: DWORD; bLoop: Boolean): Boolean;
+function e_LoadSoundMem(pData: Pointer; Length: Integer; var ID: DWORD; isMusic: Boolean; ForceNoLoop: Boolean = False): Boolean;
 var
   find_id: DWORD;
   res: FMOD_RESULT;
@@ -323,12 +356,12 @@ begin
   soundExInfo.cbsize := sz;
   soundExInfo.length := Length;
 
-  if bLoop then
+  if isMusic and not ForceNoLoop then
     bt := FMOD_LOOP_NORMAL
   else
     bt := FMOD_LOOP_OFF;
 
-  if not bLoop then
+  if not isMusic then
     res := FMOD_System_CreateSound(F_System, pData,
              bt + FMOD_2D + FMOD_HARDWARE + FMOD_OPENMEMORY,
              @soundExInfo, e_SoundsArray[find_id].Sound)
@@ -352,7 +385,7 @@ begin
   end;
 
   e_SoundsArray[find_id].Data := pData;
-  e_SoundsArray[find_id].isMusic := bLoop;
+  e_SoundsArray[find_id].isMusic := isMusic;
   e_SoundsArray[find_id].nRefs := 0;
 
   ID := find_id;
@@ -553,8 +586,8 @@ begin
   res := FMOD_Sound_Release(e_SoundsArray[ID].Sound);
   if res <> FMOD_OK then
   begin
-    e_WriteLog('Error releasing sound:', MSG_WARNING);
-    e_WriteLog(FMOD_ErrorString(res), MSG_WARNING);
+    e_WriteLog('Error releasing sound:', TMsgType.Warning);
+    e_WriteLog(FMOD_ErrorString(res), TMsgType.Warning);
   end;
 
   e_SoundsArray[ID].Sound := nil;
@@ -669,16 +702,16 @@ begin
   res := FMOD_System_Close(F_System);
   if res <> FMOD_OK then
   begin
-    e_WriteLog('Error closing FMOD system!', MSG_FATALERROR);
-    e_WriteLog(FMOD_ErrorString(res), MSG_FATALERROR);
+    e_WriteLog('Error closing FMOD system!', TMsgType.Fatal);
+    e_WriteLog(FMOD_ErrorString(res), TMsgType.Fatal);
     Exit;
   end;
 
   res := FMOD_System_Release(F_System);
   if res <> FMOD_OK then
   begin
-    e_WriteLog('Error releasing FMOD system!', MSG_FATALERROR);
-    e_WriteLog(FMOD_ErrorString(res), MSG_FATALERROR);
+    e_WriteLog('Error releasing FMOD system!', TMsgType.Fatal);
+    e_WriteLog(FMOD_ErrorString(res), TMsgType.Fatal);
   end;
 end;
 
@@ -720,17 +753,15 @@ var
   res: FMOD_RESULT;
 
 begin
+  Result := False;
+  if FID = NO_SOUND_ID then Exit;
+
   if e_SoundsArray[FID].nRefs >= gMaxSimSounds then
   begin
     Result := True;
     Exit;
   end;
 
-  Result := False;
-
-  if FID = NO_SOUND_ID then
-    Exit;
-
   res := FMOD_System_PlaySound(F_System, FMOD_CHANNEL_FREE,
            e_SoundsArray[FID].Sound, False, FChannel);
   if res <> FMOD_OK then