1 (* Copyright (C) Doom 2D: Forever Developers
3 * This program is free software: you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation, either version 3 of the License, or
6 * (at your option) any later version.
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
16 {$INCLUDE ../shared/a_modes.inc}
17 unit e_soundfile_modplug
;
21 uses e_soundfile
, modplug
;
24 // a module loader that uses libmodplug
26 TModPlugLoader
= class (TSoundLoader
)
28 function Load(Data
: Pointer; Len
: LongWord; SStreaming
: Boolean): Boolean; override; overload
;
29 function Load(FName
: string; SStreaming
: Boolean): Boolean; override; overload
;
30 function SetPosition(Pos
: LongWord): Boolean; override;
31 function FillBuffer(Buf
: Pointer; Len
: LongWord): LongWord; override;
32 function GetAll(var OutPtr
: Pointer): LongWord; override;
33 procedure Free(); override;
38 TModPlugLoaderFactory
= class (TSoundLoaderFactory
)
40 function MatchHeader(Data
: Pointer; Len
: LongWord): Boolean; override;
41 function MatchExtension(FName
: string): Boolean; override;
42 function GetLoader(): TSoundLoader
; override;
47 uses sysutils
, utils
, e_sound
, e_log
, classes
;
50 Settings
: ModPlug_Settings
= (
51 mFlags
: MODPLUG_ENABLE_OVERSAMPLING
or MODPLUG_ENABLE_NOISE_REDUCTION
;
55 mResamplingMode
: MODPLUG_RESAMPLE_LINEAR
;
56 mStereoSeparation
: 128;
67 (* TModPlugLoaderFactory *)
69 function TModPlugLoaderFactory
.MatchHeader(Data
: Pointer; Len
: LongWord): Boolean;
73 // HACK: there's no "test" function in modplug, so just try to load that shit
76 Mpf
:= ModPlug_Load(Data
, Len
);
77 if Mpf
= nil then Exit
;
83 function TModPlugLoaderFactory
.MatchExtension(FName
: string): Boolean;
87 Ext
:= GetFilenameExt(FName
);
88 Result
:= (Ext
= '.it') or (Ext
= '.xm') or (Ext
= '.mod') or (Ext
= '.s3m');
91 function TModPlugLoaderFactory
.GetLoader(): TSoundLoader
;
93 // update interpolation setting
95 Settings
.mResamplingMode
:= MODPLUG_RESAMPLE_LINEAR
97 Settings
.mResamplingMode
:= MODPLUG_RESAMPLE_NEAREST
;
98 ModPlug_SetSettings(@Settings
);
99 Result
:= TModPlugLoader
.Create();
104 function TModPlugLoader
.Load(Data
: Pointer; Len
: LongWord; SStreaming
: Boolean): Boolean;
108 FFile
:= ModPlug_Load(Data
, Len
);
111 e_LogWriteln('ModPlug: ERROR: ModPlug_Load failed');
115 FFormat
.SampleRate
:= 44100;
116 FFormat
.SampleBits
:= 16;
117 FFormat
.Channels
:= 2;
118 FStreaming
:= True; // modules are always streaming
123 function TModPlugLoader
.Load(FName
: string; SStreaming
: Boolean): Boolean;
132 S
:= openDiskFileRO(FName
);
133 // ayy just read the entire file
134 Data
:= GetMem(S
.Size
);
136 raise Exception
.Create('out of memory');
137 Len
:= S
.Read(Data
^, S
.Size
);
139 raise Exception
.Create('what the fuck');
140 Result
:= Load(Data
, Len
, SStreaming
)
143 e_LogWritefln('ModPlug: ERROR: could not read file `%s`: %s', [FName
, E
.Message]);
146 if Data
<> nil then FreeMem(Data
);
147 if S
<> nil then S
.Free();
150 function TModPlugLoader
.SetPosition(Pos
: LongWord): Boolean;
153 if FFile
= nil then Exit
;
154 ModPlug_Seek(FFile
, Pos
);
158 function TModPlugLoader
.FillBuffer(Buf
: Pointer; Len
: LongWord): LongWord;
163 if FFile
= nil then Exit
;
165 Cnt
:= ModPlug_Read(FFile
, Buf
, Len
);
166 if Cnt
< 0 then Exit
;
168 if FLooping
and (Cnt
< Len
) then
170 // assume it just ended and restart, because modplug only loops if the
171 // module tells it to
172 ModPlug_Seek(FFile
, 0);
173 // this used to be Result := Cnt + Read(FFile, Buf + Cnt, Len - Cnt)
174 // but the difference appears to be negligible
175 Result
:= ModPlug_Read(FFile
, Buf
, Len
);
181 function TModPlugLoader
.GetAll(var OutPtr
: Pointer): LongWord;
183 Result
:= 0; // modules are always streaming, so this don't make sense
186 procedure TModPlugLoader
.Free();
190 ModPlug_Unload(FFile
);
196 e_AddSoundLoader(TModPlugLoaderFactory
.Create());