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, version 3 of the License ONLY.
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
12 * You should have received a copy of the GNU General Public License
13 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 {$INCLUDE ../shared/a_modes.inc}
20 uses e_soundfile
, XMP
;
23 // a module loader that uses libxmp-lite
25 TXMPLoader
= class (TSoundLoader
)
27 function Load(Data
: Pointer; Len
: LongWord; Loop
: Boolean): Boolean; override; overload
;
28 function Load(FName
: string; Loop
: Boolean): Boolean; override; overload
;
29 function Finished(): Boolean; override;
30 function Restart(): Boolean; override;
31 function FillBuffer(Buf
: Pointer; Len
: LongWord): LongWord; override;
32 procedure Free(); override;
40 TXMPLoaderFactory
= class (TSoundLoaderFactory
)
42 function MatchHeader(Data
: Pointer; Len
: LongWord): Boolean; override;
43 function MatchExtension(FName
: string): Boolean; override;
44 function GetLoader(): TSoundLoader
; override;
49 uses sysutils
, utils
, math
, e_sound
, e_log
;
51 (* TXMPLoaderFactory *)
53 function TXMPLoaderFactory
.MatchHeader(Data
: Pointer; Len
: LongWord): Boolean;
58 // HACK: these fine gentlemen didn't provide us with a xmp_test_module_from_memory()
59 // so just load the module and unload it
63 Ctx
:= xmp_create_context();
64 Err
:= xmp_load_module_from_memory(Ctx
, Data
, Len
);
68 xmp_release_module(Ctx
);
72 xmp_free_context(Ctx
);
75 function TXMPLoaderFactory
.MatchExtension(FName
: string): Boolean;
79 Ext
:= GetFilenameExt(FName
);
80 Result
:= (Ext
= '.it') or (Ext
= '.xm') or (Ext
= '.mod') or (Ext
= '.s3m');
83 function TXMPLoaderFactory
.GetLoader(): TSoundLoader
;
85 Result
:= TXMPLoader
.Create();
90 function TXMPLoader
.Load(Data
: Pointer; Len
: LongWord; Loop
: Boolean): Boolean;
98 FXMP
:= xmp_create_context();
99 if FXMP
= nil then Exit
;
102 Err
:= xmp_load_module_from_memory(FXMP
, Data
, Len
);
104 raise Exception
.Create('xmp_load_module_from_memory failed');
106 if xmp_start_player(FXMP
, 48000, 0) <> 0 then
107 raise Exception
.Create('xmp_start_player failed');
109 if e_MusicLerp
then Interp
:= XMP_INTERP_LINEAR
110 else Interp
:= XMP_INTERP_NEAREST
;
111 xmp_set_player(FXMP
, XMP_PLAYER_INTERP
, Interp
);
113 FFormat
.SampleRate
:= 48000;
114 FFormat
.SampleBits
:= 16;
115 FFormat
.Channels
:= 2;
117 FStreaming
:= True; // modules are always streaming
125 e_LogWriteln('TXMPLoader.Load() error: ' + E
.Message);
126 if Err
= 0 then xmp_release_module(FXMP
);
127 xmp_free_context(FXMP
);
133 function TXMPLoader
.Load(FName
: string; Loop
: Boolean): Boolean;
141 FXMP
:= xmp_create_context();
142 if FXMP
= nil then Exit
;
145 Err
:= xmp_load_module(FXMP
, PChar(FName
));
147 raise Exception
.Create('xmp_load_module failed');
149 if xmp_start_player(FXMP
, 48000, 0) <> 0 then
150 raise Exception
.Create('xmp_start_player failed');
152 if e_MusicLerp
then Interp
:= XMP_INTERP_LINEAR
153 else Interp
:= XMP_INTERP_NEAREST
;
154 xmp_set_player(FXMP
, XMP_PLAYER_INTERP
, Interp
);
156 FFormat
.SampleRate
:= 48000;
157 FFormat
.SampleBits
:= 16;
158 FFormat
.Channels
:= 2;
160 FStreaming
:= True; // modules are always streaming
168 e_LogWritefln('TXMPLoader.Load(%s) error: %s', [FName
, E
.Message]);
169 if Err
= 0 then xmp_release_module(FXMP
);
170 xmp_free_context(FXMP
);
176 function TXMPLoader
.Finished(): Boolean;
181 function TXMPLoader
.Restart(): Boolean;
184 if FXMP
= nil then Exit
;
187 xmp_restart_module(FXMP
);
190 function TXMPLoader
.FillBuffer(Buf
: Pointer; Len
: LongWord): LongWord;
195 if FXMP
= nil then Exit
;
197 Ret
:= xmp_play_buffer(FXMP
, Buf
, Len
, IfThen(FLooping
, 0, 1));
201 else if (Ret
= -XMP_END
) and not FLooping
then
205 procedure TXMPLoader
.Free();
211 xmp_end_player(FXMP
);
212 xmp_release_module(FXMP
);
214 xmp_free_context(FXMP
);
223 e_AddSoundLoader(TXMPLoaderFactory
.Create());