6a736097eec60ca0ad5db6d588cb5bc7a2e4c115
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_opus
;
21 uses e_soundfile
, opus
, classes
;
26 TOpusLoader
= 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;
39 TOpusLoaderFactory
= class (TSoundLoaderFactory
)
41 function MatchHeader(Data
: Pointer; Len
: LongWord): Boolean; override;
42 function MatchExtension(FName
: string): Boolean; override;
43 function GetLoader(): TSoundLoader
; override;
48 uses sysutils
, utils
, e_log
, xstreams
, ogg
, ctypes
;
50 function TOpusLoaderFactory
.MatchHeader(Data
: Pointer; Len
: LongWord): Boolean;
52 OGG_HEADER
= $5367674F; // 'OggS'
54 F
: POggOpusFile
= nil;
58 if Len
< 27 then // header is at least 27 bytes
60 if PLongWord(Data
)^ <> OGG_HEADER
then
63 // now we gotta check that this is indeed an opus file and not a vorbis file
65 F
:= op_test_memory(Data
, Len
, nil);
67 if Result
then op_free(F
);
70 function TOpusLoaderFactory
.MatchExtension(FName
: string): Boolean;
72 Result
:= GetFilenameExt(FName
) = '.opus';
75 function TOpusLoaderFactory
.GetLoader(): TSoundLoader
;
77 Result
:= TOpusLoader
.Create();
82 function TOpusLoader
.Load(Data
: Pointer; Len
: LongWord; SStreaming
: Boolean): Boolean;
89 e_LogWriteln('Opus: Load(Data) failed: out of memory on copy');
92 Move(Data
^, FBuf
^, Len
);
94 FOpus
:= op_open_memory(FBuf
, Len
, nil);
98 e_LogWriteln('Opus: Load(Data) failed: op_open_memory failed');
102 FFormat
.Channels
:= 2; // we use ov_read_stereo
103 FFormat
.SampleBits
:= 16;
104 FFormat
.SampleRate
:= 48000; // is this even correct?
105 FStreaming
:= True; // opus is always streaming
110 function TOpusLoader
.Load(FName
: string; SStreaming
: Boolean): Boolean;
114 FOpus
:= op_open_file(PChar(FName
), nil);
117 e_LogWritefln('Opus: Load(%s) failed: op_open_file failed', [FName
]);
121 FFormat
.Channels
:= 2; // we use ov_read_stereo
122 FFormat
.SampleBits
:= 16;
123 FFormat
.SampleRate
:= 48000; // is this even correct?
124 FStreaming
:= True; // opus is always streaming
129 function TOpusLoader
.SetPosition(Pos
: LongWord): Boolean;
132 if (FOpus
= nil) or (op_seekable(FOpus
) = 0) then Exit
;
133 Result
:= op_pcm_seek(FOpus
, Pos
) = 0;
136 function TOpusLoader
.FillBuffer(Buf
: Pointer; Len
: LongWord): LongWord;
142 if FOpus
= nil then Exit
;
148 Ret
:= op_read_stereo(FOpus
, Buf
+ Rx
, (Len
- Rx
) div 2);
149 if Ret
= OP_HOLE
then continue
;
150 if Ret
< 0 then break
;
151 if FLooping
and (Ret
= 0) then op_pcm_seek(FOpus
, 0); // loop
158 function TOpusLoader
.GetAll(var OutPtr
: Pointer): LongWord;
160 Result
:= 0; // always streaming
163 procedure TOpusLoader
.Free();
175 e_AddSoundLoader(TOpusLoaderFactory
.Create());