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}
16 unit e_soundfile_opus
;
20 uses e_soundfile
, opus
, classes
;
25 TOpusLoader
= 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 TOpusLoaderFactory
= 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
, e_log
, xstreams
, ogg
, ctypes
;
51 function TOpusLoaderFactory
.MatchHeader(Data
: Pointer; Len
: LongWord): Boolean;
53 OGG_HEADER
= $5367674F; // 'OggS'
55 F
: POggOpusFile
= nil;
59 if Len
< 27 then // header is at least 27 bytes
61 if PLongWord(Data
)^ <> OGG_HEADER
then
64 // now we gotta check that this is indeed an opus file and not a vorbis file
66 F
:= op_test_memory(Data
, Len
, nil);
68 if Result
then op_free(F
);
71 function TOpusLoaderFactory
.MatchExtension(FName
: string): Boolean;
73 Result
:= GetFilenameExt(FName
) = '.opus';
76 function TOpusLoaderFactory
.GetLoader(): TSoundLoader
;
78 Result
:= TOpusLoader
.Create();
83 function TOpusLoader
.Load(Data
: Pointer; Len
: LongWord; Loop
: Boolean): Boolean;
90 e_LogWriteln('Opus: Load(Data) failed: out of memory on copy');
93 Move(Data
^, FBuf
^, Len
);
95 FOpus
:= op_open_memory(FBuf
, Len
, nil);
99 e_LogWriteln('Opus: Load(Data) failed: op_open_memory failed');
103 FFormat
.Channels
:= 2; // we use ov_read_stereo
104 FFormat
.SampleBits
:= 16;
105 FFormat
.SampleRate
:= 48000; // is this even correct?
106 FStreaming
:= True; // opus is always streaming
113 function TOpusLoader
.Load(FName
: string; Loop
: Boolean): Boolean;
117 FOpus
:= op_open_file(PChar(FName
), nil);
120 e_LogWritefln('Opus: Load(%s) failed: op_open_file failed', [FName
]);
124 FFormat
.Channels
:= 2; // we use ov_read_stereo
125 FFormat
.SampleBits
:= 16;
126 FFormat
.SampleRate
:= 48000; // is this even correct?
127 FStreaming
:= True; // opus is always streaming
134 function TOpusLoader
.Finished(): Boolean;
139 function TOpusLoader
.Restart(): Boolean;
142 if (FOpus
= nil) or (op_seekable(FOpus
) = 0) then Exit
;
143 Result
:= op_pcm_seek(FOpus
, 0) = 0;
147 function TOpusLoader
.FillBuffer(Buf
: Pointer; Len
: LongWord): LongWord;
153 if FOpus
= nil then Exit
;
159 Ret
:= op_read_stereo(FOpus
, Buf
+ Rx
, (Len
- Rx
) div 2);
160 if Ret
= OP_HOLE
then continue
;
161 if Ret
< 0 then break
;
165 op_pcm_seek(FOpus
, 0)
178 procedure TOpusLoader
.Free();
192 e_AddSoundLoader(TOpusLoaderFactory
.Create());