index 654969e8ccd4a75335f910ab09e70e207ffb1d91..9436cec6b42dee983b3ce2d5ae2aef01c68e5082 100644 (file)
+(* 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, version 3 of the License ONLY.
+ *
+ * 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
- sdl2,
- SDL2_mixer,
- e_log,
- SysUtils;
+ {$IFDEF USE_MEMPOOL}mempool,{$ENDIF}
+ SDL2, SDL2_mixer, envvars,
+ e_log, SysUtils;
type
TSoundRec = record
Sound: PMix_Chunk;
Music: PMix_Music;
isMusic: Boolean;
+ Loops: Boolean;
nRefs: Integer;
end;
- TBasicSound = class (TObject)
+ TBasicSound = class{$IFDEF USE_MEMPOOL}(TPoolObject){$ENDIF}
private
FChanNum: Integer; // <0: no channel allocated
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; isMusic: Boolean): Boolean;
-function e_LoadSoundMem(pData: Pointer; Length: Integer; var ID: DWORD; isMusic: 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;
// returns channel number or -1
function e_PlaySound(ID: DWORD): Integer;
implementation
uses
- g_window, g_options, BinEditor;
+ g_window, g_options;
const
N_CHANNELS = 512;
procedure chanFinished (chan: Integer); cdecl;
begin
- //e_WriteLog(Format('chanFinished: %d', [chan]), MSG_NOTIFY);
+ //e_WriteLog(Format('chanFinished: %d', [chan]), TMsgType.Notify);
if (chan >= 0) and (chan < N_CHANNELS) then
begin
if ChanSIds[chan].id <> NO_SOUND_ID then
begin
if ms = nil then
begin
- e_WriteLog('MUSIC FORMAT: NONE', MSG_NOTIFY);
+ e_WriteLog('MUSIC FORMAT: NONE', TMsgType.Notify);
end
else
begin
case Mix_GetMusicType(ms^) of
TMix_MusicType.MUS_NONE:
- e_WriteLog('MUSIC FORMAT: NONE', MSG_NOTIFY);
+ e_WriteLog('MUSIC FORMAT: NONE', TMsgType.Notify);
TMix_MusicType.MUS_CMD:
- e_WriteLog('MUSIC FORMAT: CMD', MSG_NOTIFY);
+ e_WriteLog('MUSIC FORMAT: CMD', TMsgType.Notify);
TMix_MusicType.MUS_WAV:
- e_WriteLog('MUSIC FORMAT: WAV', MSG_NOTIFY);
+ e_WriteLog('MUSIC FORMAT: WAV', TMsgType.Notify);
TMix_MusicType.MUS_MOD:
- e_WriteLog('MUSIC FORMAT: MOD', MSG_NOTIFY);
+ e_WriteLog('MUSIC FORMAT: MOD', TMsgType.Notify);
TMix_MusicType.MUS_MID:
- e_WriteLog('MUSIC FORMAT: MID', MSG_NOTIFY);
+ e_WriteLog('MUSIC FORMAT: MID', TMsgType.Notify);
TMix_MusicType.MUS_OGG:
- e_WriteLog('MUSIC FORMAT: OGG', MSG_NOTIFY);
+ e_WriteLog('MUSIC FORMAT: OGG', TMsgType.Notify);
TMix_MusicType.MUS_MP3:
- e_WriteLog('MUSIC FORMAT: MP3', MSG_NOTIFY);
+ e_WriteLog('MUSIC FORMAT: MP3', TMsgType.Notify);
TMix_MusicType.MUS_MP3_MAD:
- e_WriteLog('MUSIC FORMAT: MP3_MAD', MSG_NOTIFY);
+ e_WriteLog('MUSIC FORMAT: MP3_MAD', TMsgType.Notify);
TMix_MusicType.MUS_FLAC:
- e_WriteLog('MUSIC FORMAT: FLAC', MSG_NOTIFY);
+ e_WriteLog('MUSIC FORMAT: FLAC', TMsgType.Notify);
TMix_MusicType.MUS_MODPLUG:
- e_WriteLog('MUSIC FORMAT: MODPLUG', MSG_NOTIFY);
+ e_WriteLog('MUSIC FORMAT: MODPLUG', TMsgType.Notify);
otherwise
- e_WriteLog('MUSIC FORMAT: UNKNOWN', MSG_NOTIFY);
+ e_WriteLog('MUSIC FORMAT: UNKNOWN', TMsgType.Notify);
end;
end;
end;
-function e_InitSoundSystem(): Boolean;
+function e_InitSoundSystem(NoOutput: Boolean = False): Boolean;
var
res, i: Integer;
rfreq: Integer;
Result := False;
SoundInitialized := False;
+ {$IFDEF HEADLESS}
+ // HACK: shit this into env and hope for the best
+ SetEnvVar('SDL_AUDIODRIVER', 'dummy');
+ {$ENDIF}
+
+ if NoOutput then begin Result := true; Exit end;
+
// wow, this is actually MIDI player!
// we need module player
res := Mix_Init(MIX_INIT_FLAC or MIX_INIT_MOD or MIX_INIT_MODPLUG or MIX_INIT_MP3 or MIX_INIT_OGG or MIX_INIT_FLUIDSYNTH);
- e_WriteLog(Format('SDL: res=0x%x', [res]), MSG_NOTIFY);
- if (res and MIX_INIT_FLAC) <> 0 then e_WriteLog('SDL: FLAC playback is active', MSG_NOTIFY);
- if (res and MIX_INIT_MOD) <> 0 then e_WriteLog('SDL: MOD playback is active', MSG_NOTIFY);
- if (res and MIX_INIT_MODPLUG) <> 0 then e_WriteLog('SDL: MODPLUG playback is active', MSG_NOTIFY);
- if (res and MIX_INIT_MP3) <> 0 then e_WriteLog('SDL: MP3 playback is active', MSG_NOTIFY);
- if (res and MIX_INIT_OGG) <> 0 then e_WriteLog('SDL: OGG playback is active', MSG_NOTIFY);
- if (res and MIX_INIT_FLUIDSYNTH) <> 0 then e_WriteLog('SDL: FLUIDSYNTH playback is active', MSG_NOTIFY);
-
- res := Mix_OpenAudio(44100, AUDIO_S16LSB, 2, 2048);
+ e_WriteLog(Format('SDL: res=0x%x', [res]), TMsgType.Notify);
+ if (res and MIX_INIT_FLAC) <> 0 then e_WriteLog('SDL: FLAC playback is active', TMsgType.Notify);
+ if (res and MIX_INIT_MOD) <> 0 then e_WriteLog('SDL: MOD playback is active', TMsgType.Notify);
+ if (res and MIX_INIT_MODPLUG) <> 0 then e_WriteLog('SDL: MODPLUG playback is active', TMsgType.Notify);
+ if (res and MIX_INIT_MP3) <> 0 then e_WriteLog('SDL: MP3 playback is active', TMsgType.Notify);
+ if (res and MIX_INIT_OGG) <> 0 then e_WriteLog('SDL: OGG playback is active', TMsgType.Notify);
+ if (res and MIX_INIT_FLUIDSYNTH) <> 0 then e_WriteLog('SDL: FLUIDSYNTH playback is active', TMsgType.Notify);
+
+ e_WriteLog(Format('SDL: initializing mixer at %d with buffer %d', [gsSDLSampleRate, gsSDLBufferSize]), TMsgType.Notify);
+ res := Mix_OpenAudio(gsSDLSampleRate, AUDIO_S16LSB, 2, gsSDLBufferSize);
if res = -1 then
begin
- e_WriteLog('Error initializing SDL mixer:', MSG_FATALERROR);
- e_WriteLog(Mix_GetError(), MSG_FATALERROR);
+ e_WriteLog('Error initializing SDL mixer:', TMsgType.Fatal);
+ e_WriteLog(Mix_GetError(), TMsgType.Fatal);
Exit;
end;
if Mix_QuerySpec(@rfreq, @rformat, @rchans) > 0 then
begin
- e_WriteLog(Format('SDL: frequency=%d; format=%u; channels=%d', [rfreq, rformat, rchans]), MSG_NOTIFY);
+ e_WriteLog(Format('SDL: frequency=%d; format=%u; channels=%d', [rfreq, rformat, rchans]), TMsgType.Notify);
end;
for i := 0 to Mix_GetNumChunkDecoders()-1 do
begin
- e_WriteLog(Format('SDL: chunk decoder %s is avalable', [Mix_GetChunkDecoder(i)]), MSG_NOTIFY);
+ e_WriteLog(Format('SDL: chunk decoder %s is avalable', [Mix_GetChunkDecoder(i)]), TMsgType.Notify);
+ end;
+ for i := 0 to Mix_GetNumMusicDecoders()-1 do
+ begin
+ e_WriteLog(Format('SDL: music decoder %s is avalable', [Mix_GetMusicDecoder(i)]), TMsgType.Notify);
end;
Mix_AllocateChannels(N_CHANNELS);
end;
end;
-function e_LoadSound(FileName: String; var ID: DWORD; isMusic: Boolean): Boolean;
+function e_LoadSound(FileName: String; var ID: DWORD; isMusic: Boolean; ForceNoLoop: Boolean = False): Boolean;
var
find_id: DWORD;
begin
Result := False;
if not SoundInitialized then Exit;
- if isMusic then e_WriteLog('Loading music '+FileName+'...', MSG_NOTIFY)
- else e_WriteLog('Loading sound '+FileName+'...', MSG_NOTIFY);
+ if isMusic then e_WriteLog('Loading music '+FileName+'...', TMsgType.Notify)
+ else e_WriteLog('Loading sound '+FileName+'...', TMsgType.Notify);
{
if isMusic then
begin
- e_WriteLog('IGNORING MUSIC FROM FILE', MSG_WARNING);
+ e_WriteLog('IGNORING MUSIC FROM FILE', TMsgType.Warning);
Exit;
end;
}
e_SoundsArray[find_id].Data := nil;
e_SoundsArray[find_id].isMusic := isMusic;
+ e_SoundsArray[find_id].Loops := isMusic and not ForceNoLoop;
e_SoundsArray[find_id].nRefs := 0;
if isMusic then
begin
- e_WriteLog(Format(' MUSIC SLOT: %u', [find_id]), MSG_NOTIFY);
+ e_WriteLog(Format(' MUSIC SLOT: %u', [find_id]), TMsgType.Notify);
e_SoundsArray[find_id].Music := Mix_LoadMUS(PAnsiChar(FileName));
if e_SoundsArray[find_id].Music = nil then
begin
- e_WriteLog(Format('ERROR LOADING MUSIC:', [find_id]), MSG_WARNING);
- e_WriteLog(Mix_GetError(), MSG_WARNING);
+ e_WriteLog(Format('ERROR LOADING MUSIC:', [find_id]), TMsgType.Warning);
+ e_WriteLog(Mix_GetError(), TMsgType.Warning);
Exit;
end;
dumpMusicType(e_SoundsArray[find_id].Music);
Result := True;
end;
-function e_LoadSoundMem(pData: Pointer; Length: Integer; var ID: DWORD; isMusic: Boolean): Boolean;
+function e_LoadSoundMem(pData: Pointer; Length: Integer; var ID: DWORD; isMusic: Boolean; ForceNoLoop: Boolean = False): Boolean;
var
find_id: DWORD;
rw: PSDL_RWops;
{
if isMusic then
begin
- e_WriteLog('IGNORING MUSIC FROM MEMORY', MSG_WARNING);
+ e_WriteLog('IGNORING MUSIC FROM MEMORY', TMsgType.Warning);
Exit;
end;
}
Inc(pc, $400);
pData := Pointer(pc);
Dec(Length, $400);
- e_WriteLog('MUSIC: MP3 ID3 WORKAROUND APPLIED!', MSG_WARNING);
+ e_WriteLog('MUSIC: MP3 ID3 WORKAROUND APPLIED!', TMsgType.Warning);
end;
}
e_SoundsArray[find_id].Data := pData;
if isid3 then e_SoundsArray[find_id].Data := nil;
e_SoundsArray[find_id].isMusic := isMusic;
+ e_SoundsArray[find_id].Loops := isMusic and not ForceNoLoop;
e_SoundsArray[find_id].nRefs := 0;
if isMusic then
begin
- e_WriteLog(Format(' MUSIC SLOT: %u', [find_id]), MSG_NOTIFY);
+ e_WriteLog(Format(' MUSIC SLOT: %u', [find_id]), TMsgType.Notify);
e_SoundsArray[find_id].Music := Mix_LoadMUS_RW(rw, 0);
if e_SoundsArray[find_id].Music = nil then
begin
- e_WriteLog(Format('ERROR LOADING MUSIC:', [find_id]), MSG_WARNING);
- e_WriteLog(Mix_GetError(), MSG_WARNING);
+ e_WriteLog(Format('ERROR LOADING MUSIC:', [find_id]), TMsgType.Warning);
+ e_WriteLog(Mix_GetError(), TMsgType.Warning);
end
else
begin
function e_PlaySound (ID: DWORD): Integer;
var
res: Integer = -1;
+ loops: Integer = 0;
begin
Result := -1;
if not SoundInitialized then Exit;
begin
if e_SoundsArray[ID].nRefs >= gMaxSimSounds then Exit;
Inc(e_SoundsArray[ID].nRefs);
- res := Mix_PlayChannel(-1, e_SoundsArray[ID].Sound, 0);
+ if e_SoundsArray[ID].Loops then loops := -1;
+ res := Mix_PlayChannel(-1, e_SoundsArray[ID].Sound, loops);
if res >= 0 then
begin
ChanSIds[res].id := ID;
begin
if not e_isMusic(ID) then Exit;
Mix_HaltMusic();
- res := Mix_PlayMusic(e_SoundsArray[ID].Music, -1);
+ if e_SoundsArray[ID].Loops then loops := -1;
+ res := Mix_PlayMusic(e_SoundsArray[ID].Music, loops);
if res >= 0 then res := N_MUSCHAN;
if SoundMuted then Mix_VolumeMusic(0) else Mix_VolumeMusic(MusVolume);
Result := res;
end;
if vol < 0 then vol := 0 else if vol > 1 then vol := 1;
ChanSIds[i].oldvol := trunc(vol*MIX_MAX_VOLUME);
- //if i = 0 then e_WriteLog(Format('modifying volumes: vol=%f; newvol=%d', [vol, ChanSIds[i].oldvol]), MSG_WARNING);
+ //if i = 0 then e_WriteLog(Format('modifying volumes: vol=%f; newvol=%d', [vol, ChanSIds[i].oldvol]), TMsgType.Warning);
if ChanSIds[i].muted then Mix_Volume(i, 0) else Mix_Volume(i, ChanSIds[i].oldvol);
end;
ovol := Mix_VolumeMusic(-1);
if ChanSIds[i].muted <> SoundMuted then
begin
ChanSIds[i].muted := SoundMuted;
- //e_WriteLog(Format('gmuting sound for channel %d', [i]), MSG_WARNING);
+ //e_WriteLog(Format('gmuting sound for channel %d', [i]), TMsgType.Warning);
if ChanSIds[i].muted then Mix_Volume(i, 0) else Mix_Volume(i, ChanSIds[i].oldvol);
end;
end;
- //if SoundMuted then e_WriteLog('muting music', MSG_NOTIFY) else e_WriteLog(Format('unmuting music (%d)', [MusVolume]), MSG_NOTIFY);
+ //if SoundMuted then e_WriteLog('muting music', TMsgType.Notify) else e_WriteLog(Format('unmuting music (%d)', [MusVolume]), TMsgType.Notify);
if SoundMuted then Mix_VolumeMusic(0) else Mix_VolumeMusic(MusVolume);
end;
if (FID = NO_SOUND_ID) or not SoundInitialized then Exit;
FChanNum := e_PlaySoundPanVolume(FID, Pan, Volume);
Result := (FChanNum >= 0);
- //if e_isMusic(FID) then e_WriteLog(Format('playing music (%u)', [FID]), MSG_NOTIFY);
+ //if e_isMusic(FID) then e_WriteLog(Format('playing music (%u)', [FID]), TMsgType.Notify);
//TODO: aPos
end;
Result := False;
if e_isSound(FID) then
begin
- //e_WriteLog(Format('IsPlaying: FID=%u; FChanNum=%d', [FID, FChanNum]), MSG_WARNING);
+ //e_WriteLog(Format('IsPlaying: FID=%u; FChanNum=%d', [FID, FChanNum]), TMsgType.Warning);
chan := Channel;
if chan < 0 then
begin
- //e_WriteLog(Format('IsPlaying: FID=%u; ONA', [FID]), MSG_WARNING);
+ //e_WriteLog(Format('IsPlaying: FID=%u; ONA', [FID]), TMsgType.Warning);
Exit;
end;
//Result := (Mix_Playing(chan) > 0)
- //e_WriteLog(Format('IsPlaying: FID=%u; TAN', [FID]), MSG_WARNING);
+ //e_WriteLog(Format('IsPlaying: FID=%u; TAN', [FID]), TMsgType.Warning);
Result := True;
end
else if e_isMusic(FID) then
begin
chan := Channel;
if chan < 0 then Exit;
- //e_WriteLog(Format('SetVolume: chan=%d; Volume=%f', [chan, Volume]), MSG_WARNING);
+ //e_WriteLog(Format('SetVolume: chan=%d; Volume=%f', [chan, Volume]), TMsgType.Warning);
e_chanSetVol(chan, Volume);
end
else if e_isMusic(FID) then
begin
- //e_WriteLog(Format('SetVolume: chan=MUSIC; Volume=%f', [Volume]), MSG_WARNING);
+ //e_WriteLog(Format('SetVolume: chan=MUSIC; Volume=%f', [Volume]), TMsgType.Warning);
e_chanSetVol(N_MUSCHAN, Volume);
end;
end;
if chan < 0 then Exit;
if ChanSIds[chan].muted <> Enable then
begin
- //e_WriteLog(Format('muting sound for channel %d', [cnan]), MSG_WARNING);
+ //e_WriteLog(Format('muting sound for channel %d', [cnan]), TMsgType.Warning);
ChanSIds[chan].muted := Enable;
if ChanSIds[chan].muted then Mix_Volume(chan, 0) else Mix_Volume(chan, ChanSIds[chan].oldvol);
end;