summary | shortlog | log | commit | commitdiff | tree
raw | patch | inline | side by side (parent: 425d755)
raw | patch | inline | side by side (parent: 425d755)
author | fgsfds <pvt.fgsfds@gmail.com> | |
Mon, 2 Sep 2019 16:16:17 +0000 (19:16 +0300) | ||
committer | fgsfds <pvt.fgsfds@gmail.com> | |
Mon, 2 Sep 2019 16:16:17 +0000 (19:16 +0300) |
src/engine/e_sound_al.inc | patch | blob | history | |
src/engine/e_soundfile_fluid.pas | [new file with mode: 0644] | patch | blob |
src/game/Doom2DF.lpr | patch | blob | history | |
src/lib/fluidsynth/fluidsynth.pas | [new file with mode: 0644] | patch | blob |
src/lib/modplug/modplug.pas | patch | blob | history | |
src/lib/mpg123/mpg123.pas | patch | blob | history | |
src/lib/openal/al.pas | patch | blob | history | |
src/lib/xmp/xmp.pas | patch | blob | history |
index f6ec993523682ae056ccc574115d1c0ad403cdb8..a5c83646ff18937ecf004e228250272b3af25b05 100644 (file)
exit;
end;
+ Loader.Looping := e_SoundsArray[find_id].Loops;
+
if not Loader.Load(FileName, e_SoundsArray[find_id].isMusic) then
begin
e_LogWritefln('Could not load sound `%s`', [FileName]);
end
else
begin
- Loader.Looping := e_SoundsArray[find_id].Loops;
e_SoundsArray[find_id].alBuffer := 0;
e_SoundsArray[find_id].Loader := Loader;
end;
exit;
end;
+ Loader.Looping := e_SoundsArray[find_id].Loops;
+
if not Loader.Load(pData, LongWord(Length), e_SoundsArray[find_id].isMusic) then
begin
e_LogWritefln('Could not load sound `%p`', [pData]);
end
else
begin
- Loader.Looping := e_SoundsArray[find_id].Loops;
e_SoundsArray[find_id].alBuffer := 0;
e_SoundsArray[find_id].Loader := Loader;
end;
diff --git a/src/engine/e_soundfile_fluid.pas b/src/engine/e_soundfile_fluid.pas
--- /dev/null
@@ -0,0 +1,248 @@
+(* 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/>.
+ *)
+{$INCLUDE ../shared/a_modes.inc}
+unit e_soundfile_fluid;
+
+interface
+
+uses e_soundfile, fluidsynth;
+
+type
+ // a midi loader that uses fluidsynth
+
+ TFluidLoader = class (TSoundLoader)
+ public
+ function Load(Data: Pointer; Len: LongWord; SStreaming: Boolean): Boolean; override; overload;
+ function Load(FName: string; SStreaming: Boolean): Boolean; override; overload;
+ function SetPosition(Pos: LongWord): Boolean; override;
+ function FillBuffer(Buf: Pointer; Len: LongWord): LongWord; override;
+ function GetAll(var OutPtr: Pointer): LongWord; override;
+ procedure Free(); override;
+
+ private
+ FSynth: pfluid_synth_t;
+ FPlayer: pfluid_player_t;
+ end;
+
+ TFluidLoaderFactory = class (TSoundLoaderFactory)
+ public
+ function MatchHeader(Data: Pointer; Len: LongWord): Boolean; override;
+ function MatchExtension(FName: string): Boolean; override;
+ function GetLoader(): TSoundLoader; override;
+ end;
+
+const
+ DEFAULT_SOUNDFONT = 'data/soundfont.sf2';
+
+var
+ e_Soundfont: string = '';
+
+implementation
+
+uses sysutils, utils, e_sound, e_log, ctypes{$IFDEF WINDOWS}, windirs{$ENDIF};
+
+var
+ FluidSettings: pfluid_settings_t = nil;
+
+function FindDefaultSoundfont(): string;
+{$IFDEF WINDOWS}
+var
+ SfNames: array [0..1] of string = (
+ // creative soundfonts
+ 'ct4mgm.sf2',
+ 'ct2mgm.sf2'
+ // gm.dls unsupported
+ );
+ I: Integer;
+ SysDir, S: string;
+begin
+ SysDir := GetWindowsSpecialDir(CSIDL_SYSTEM, False);
+ for I := Low(SfNames) to High(SfNames) do
+ begin
+ S := SysDir + SfNames[I];
+ if FileExists(S) then
+ begin
+ e_LogWriteln('FluidSynth: Found system soundfont ' + S);
+ Result := S;
+ exit;
+ end;
+ end;
+ Result := DEFAULT_SOUNDFONT;
+end;
+{$ELSE}
+begin
+ Result := DEFAULT_SOUNDFONT;
+end;
+{$ENDIF}
+
+(* TFluidLoaderFactory *)
+
+function TFluidLoaderFactory.MatchHeader(Data: Pointer; Len: LongWord): Boolean;
+var
+ P: PLongWord;
+const
+ MIDIHDR = $6468544D; // 'MThd'
+begin
+ Result := False;
+ if Len < 14 then Exit; // the header is at least 4+4+6 bytes
+ P := Data;
+ Result := ((P+0)^ = MIDIHDR) and ((P+1)^ <> 0); // header length is not 0
+end;
+
+function TFluidLoaderFactory.MatchExtension(FName: string): Boolean;
+var
+ Ext: string;
+begin
+ Ext := GetFilenameExt(FName);
+ Result := (Ext = '.mid') or (Ext = '.midi');
+end;
+
+function TFluidLoaderFactory.GetLoader(): TSoundLoader;
+begin
+ if e_Soundfont = '' then e_Soundfont := FindDefaultSoundfont();
+ Result := TFluidLoader.Create();
+end;
+
+(* TFluidLoader *)
+
+function TFluidLoader.Load(Data: Pointer; Len: LongWord; SStreaming: Boolean): Boolean;
+var
+ Ret: cint;
+begin
+ Result := False;
+
+ try
+ FSynth := new_fluid_synth(FluidSettings);
+ if FSynth = nil then
+ raise Exception.Create('new_fluid_synth failed');
+ Ret := fluid_synth_sfload(FSynth, PChar(e_Soundfont), 1);
+ if Ret = FLUID_FAILED then
+ raise Exception.Create('fluid_synth_sfload failed');
+ FPlayer := new_fluid_player(FSynth);
+ if FPlayer = nil then
+ raise Exception.Create('new_fluid_player failed');
+ Ret := fluid_player_add_mem(FPlayer, Data, Len);
+ if Ret = FLUID_FAILED then
+ raise Exception.Create('fluid_player_add failed');
+ fluid_player_play(FPlayer);
+ except
+ on E: Exception do
+ begin
+ e_LogWriteln('FluidSynth: Load(Data) failed: ' + E.Message);
+ if FPlayer <> nil then delete_fluid_player(FPlayer);
+ if FSynth <> nil then delete_fluid_synth(FSynth);
+ FPlayer := nil;
+ FSynth := nil;
+ Exit;
+ end;
+ end;
+
+ if FLooping then
+ fluid_player_set_loop(FPlayer, -1);
+ FFormat.SampleRate := 44100;
+ FFormat.SampleBits := 16;
+ FFormat.Channels := 2;
+ FStreaming := True;
+
+ Result := True;
+end;
+
+function TFluidLoader.Load(FName: string; SStreaming: Boolean): Boolean;
+var
+ Ret: cint;
+begin
+ Result := False;
+
+ try
+ FSynth := new_fluid_synth(FluidSettings);
+ if FSynth = nil then
+ raise Exception.Create('new_fluid_synth failed');
+ Ret := fluid_synth_sfload(FSynth, PChar(e_Soundfont), 1);
+ if Ret = FLUID_FAILED then
+ raise Exception.Create('fluid_synth_sfload failed');
+ FPlayer := new_fluid_player(FSynth);
+ if FPlayer = nil then
+ raise Exception.Create('new_fluid_player failed');
+ Ret := fluid_player_add(FPlayer, PChar(FName));
+ if Ret = FLUID_FAILED then
+ raise Exception.Create('fluid_player_add failed');
+ fluid_player_play(FPlayer);
+ except
+ on E: Exception do
+ begin
+ e_LogWriteln('FluidSynth: Load(Data) failed: ' + E.Message);
+ if FPlayer <> nil then delete_fluid_player(FPlayer);
+ if FSynth <> nil then delete_fluid_synth(FSynth);
+ FPlayer := nil;
+ FSynth := nil;
+ Exit;
+ end;
+ end;
+
+ if FLooping then
+ fluid_player_set_loop(FPlayer, -1);
+ FFormat.SampleRate := 44100;
+ FFormat.SampleBits := 16;
+ FFormat.Channels := 2;
+ FStreaming := True;
+
+ Result := True;
+end;
+
+function TFluidLoader.SetPosition(Pos: LongWord): Boolean;
+begin
+ Result := False; // unsupported?
+end;
+
+function TFluidLoader.FillBuffer(Buf: Pointer; Len: LongWord): LongWord;
+var
+ Ret: cint;
+begin
+ Result := 0;
+ if (FSynth = nil) or (FPlayer = nil) then Exit;
+ Ret := fluid_synth_write_s16(FSynth, Len div 4, Buf, 0, 2, Buf, 1, 2);
+ if Ret = FLUID_OK then Result := Len;
+end;
+
+function TFluidLoader.GetAll(var OutPtr: Pointer): LongWord;
+begin
+ Result := 0; // midis are always streaming, so this don't make sense
+end;
+
+procedure TFluidLoader.Free();
+begin
+ if FPlayer <> nil then delete_fluid_player(FPlayer);
+ if FSynth <> nil then delete_fluid_synth(FSynth);
+ FPlayer := nil;
+ FSynth := nil;
+end;
+
+initialization
+ FluidSettings := new_fluid_settings();
+ if FluidSettings <> nil then
+ begin
+ fluid_settings_setint(FluidSettings, PChar('synth.midi-channels'), 16);
+ fluid_settings_setint(FluidSettings, PChar('synth.cpu-cores'), 0);
+ fluid_settings_setnum(FluidSettings, PChar('synth.sample-rate'), 44100);
+ fluid_settings_setnum(FluidSettings, PChar('synth.gain'), 1);
+ fluid_settings_setstr(FluidSettings, PChar('player.timing-source'), PChar('sample'));
+ e_AddSoundLoader(TFluidLoaderFactory.Create());
+ end;
+finalization
+ if FluidSettings <> nil then
+ delete_fluid_settings(FluidSettings);
+end.
+
diff --git a/src/game/Doom2DF.lpr b/src/game/Doom2DF.lpr
index 75118f3f536d3156999a897737f528040f42c97c..9277239bbda6ce8dce35792842adea6f05382be7 100644 (file)
--- a/src/game/Doom2DF.lpr
+++ b/src/game/Doom2DF.lpr
AL in '../lib/openal/al.pas',
e_soundfile in '../engine/e_soundfile.pas',
e_soundfile_wav in '../engine/e_soundfile_wav.pas',
+ {$IFDEF USE_FLUIDSYNTH}
+ fluidsynth in '../lib/fluidsynth/fluidsynth.pas',
+ e_soundfile_fluid in '../engine/e_soundfile_fluid.pas',
+ {$ENDIF}
{$IFDEF USE_MODPLUG}
modplug in '../lib/modplug/modplug.pas',
e_soundfile_modplug in '../engine/e_soundfile_modplug.pas',
diff --git a/src/lib/fluidsynth/fluidsynth.pas b/src/lib/fluidsynth/fluidsynth.pas
--- /dev/null
@@ -0,0 +1,75 @@
+unit fluidsynth;
+
+{$MODE OBJFPC}{$H+}
+
+interface
+
+uses
+ ctypes;
+
+{$IFDEF FPC}
+{$PACKRECORDS C}
+{$ENDIF}
+
+{$IF 0}
+ {$IFNDEF LIBFLUIDSYNTH_WINDOZE_STATIC}
+ {$DEFINE FS_DYNAMIC}
+ {$ENDIF}
+{$ENDIF}
+
+{$IF DEFINED(FS_DYNAMIC)}
+const
+{$IF DEFINED(WINDOWS)}
+ fluidlib = 'libfluidsynth.dll';
+{$ELSEIF DEFINED(UNIX)}
+ fluidlib = 'libfluidsynth.so';
+{$ELSE}
+ {$MESSAGE ERROR 'FLUIDSYNTH_DYNAMIC not supported'}
+{$IFEND}
+{$ELSE}
+ {$LINKLIB libfluidsynth.a}
+{$ENDIF}
+
+const
+ FLUID_OK = 0;
+ FLUID_FAILED = -1;
+
+type
+ pfluid_settings_t = pointer;
+ pfluid_synth_t = pointer;
+ pfluid_player_t = pointer;
+ pfluid_sfont_t = pointer;
+ pfluid_sfloader_t = pointer;
+
+function fluid_version_str(): pchar; cdecl; external {$IFDEF FS_DYNAMIC}fluidlib{$ENDIF};
+procedure fluid_version(major, minor, patch: pcint); cdecl; external {$IFDEF FS_DYNAMIC}fluidlib{$ENDIF};
+
+function new_fluid_settings(): pfluid_settings_t; cdecl; external {$IFDEF FS_DYNAMIC}fluidlib{$ENDIF};
+procedure delete_fluid_settings(s: pfluid_settings_t); cdecl; external {$IFDEF FS_DYNAMIC}fluidlib{$ENDIF};
+
+function fluid_settings_setstr(s: pfluid_settings_t; key, val: pchar): cint; cdecl; external {$IFDEF FS_DYNAMIC}fluidlib{$ENDIF};
+function fluid_settings_getstr(s: pfluid_settings_t; key: pchar; var val: pchar): cint; cdecl; external {$IFDEF FS_DYNAMIC}fluidlib{$ENDIF};
+function fluid_settings_setnum(s: pfluid_settings_t; key: pchar; val: cdouble): cint; cdecl; external {$IFDEF FS_DYNAMIC}fluidlib{$ENDIF};
+function fluid_settings_getnum(s: pfluid_settings_t; key: pchar; var val: cdouble): cint; cdecl; external {$IFDEF FS_DYNAMIC}fluidlib{$ENDIF};
+function fluid_settings_setint(s: pfluid_settings_t; key: pchar; val: cint): cint; cdecl; external {$IFDEF FS_DYNAMIC}fluidlib{$ENDIF};
+function fluid_settings_getint(s: pfluid_settings_t; key: pchar; var val: cint): cint; cdecl; external {$IFDEF FS_DYNAMIC}fluidlib{$ENDIF};
+
+function new_fluid_synth(settings: pfluid_settings_t): pfluid_synth_t; cdecl; external {$IFDEF FS_DYNAMIC}fluidlib{$ENDIF};
+function delete_fluid_synth(synth: pfluid_synth_t): cint; cdecl; external {$IFDEF FS_DYNAMIC}fluidlib{$ENDIF};
+function fluid_synth_get_settings(synth: pfluid_synth_t): pfluid_settings_t; cdecl; external {$IFDEF FS_DYNAMIC}fluidlib{$ENDIF};
+function fluid_synth_sfload(synth: pfluid_synth_t; fname: pchar; reset: cint): cint; cdecl; external {$IFDEF FS_DYNAMIC}fluidlib{$ENDIF};
+
+function fluid_synth_write_s16(synth: pfluid_synth_t; len: cint; lout: pointer; loff, linc: cint; rout: pointer; roff, rinc: cint): cint; cdecl; external {$IFDEF FS_DYNAMIC}fluidlib{$ENDIF};
+
+function new_fluid_player(synth: pfluid_synth_t): pfluid_player_t; cdecl; external {$IFDEF FS_DYNAMIC}fluidlib{$ENDIF};
+function delete_fluid_player(player: pfluid_player_t): cint; cdecl; external {$IFDEF FS_DYNAMIC}fluidlib{$ENDIF};
+function fluid_player_add(player: pfluid_player_t; fname: pchar): cint; cdecl; external {$IFDEF FS_DYNAMIC}fluidlib{$ENDIF};
+function fluid_player_add_mem(player: pfluid_player_t; buf: pointer; len: csize_t): cint; cdecl; external {$IFDEF FS_DYNAMIC}fluidlib{$ENDIF};
+function fluid_player_play(player: pfluid_player_t): cint; cdecl; external {$IFDEF FS_DYNAMIC}fluidlib{$ENDIF};
+function fluid_player_stop(player: pfluid_player_t): cint; cdecl; external {$IFDEF FS_DYNAMIC}fluidlib{$ENDIF};
+function fluid_player_set_loop(player: pfluid_player_t; loop: cint): cint; cdecl; external {$IFDEF FS_DYNAMIC}fluidlib{$ENDIF};
+function fluid_player_get_status(player: pfluid_player_t): cint; cdecl; external {$IFDEF FS_DYNAMIC}fluidlib{$ENDIF};
+
+implementation
+
+end.
index 7b97bdb5b5a3fb9fb293934c6f60668900290bd9..bd49a1607b7312273566d84098023e586dc6da5c 100644 (file)
{$MESSAGE ERROR 'MP_DYNAMIC not supported'}
{$IFEND}
{$ELSE}
- {$LINKLIB stdc++} // is this necessary?
- {$LINKLIB modplug}
+ {$LINKLIB libstdc++.a} // is this necessary?
+ {$LINKLIB libmodplug.a}
{$ENDIF}
index dc160b4125ff5d7cd4ffc31ad5ee59de89c5b253..9ad2c91d5908b9cd3293045788ea2539c61e66a8 100644 (file)
{$MESSAGE ERROR 'MPG123_DYNAMIC not supported'}
{$IFEND}
{$ELSE}
- {$LINKLIB mpg123}
+ {$LINKLIB libmpg123.a}
{$ENDIF}
type
diff --git a/src/lib/openal/al.pas b/src/lib/openal/al.pas
index 2ca6fc12aac8f3ea24c050ab7a54338d809590a5..264f0e4049d80a9d6fae45114ece52ad7162d927 100644 (file)
--- a/src/lib/openal/al.pas
+++ b/src/lib/openal/al.pas
{$ELSEIF DEFINED(Darwin)}
{$LINKFRAMEWORK OpenAL}
{$ELSE}
- {$LINKLIB openal}
+ {$LINKLIB libopenal.a}
{$ENDIF}
{$include al.inc}
diff --git a/src/lib/xmp/xmp.pas b/src/lib/xmp/xmp.pas
index cd80954cff28152610ec753bfe59d54c4e47d0ee..4b41b901de6c89c1f66a44b1ae90f5907c566e3c 100644 (file)
--- a/src/lib/xmp/xmp.pas
+++ b/src/lib/xmp/xmp.pas
{$IFEND}
{$ELSE}
{$IF DEFINED(USE_XMP_FULL)}
- {$LINKLIB xmp}
+ {$LINKLIB libxmp.a}
{$ELSE}
- {$LINKLIB xmp-lite}
+ {$LINKLIB libxmp-lite.a}
{$ENDIF}
{$ENDIF}