DEADSOFTWARE

implement SDL1.2 system driver
[d2df-sdl.git] / src / engine / e_soundfile_wav.pas
1 (* Copyright (C) Doom 2D: Forever Developers
2 *
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.
6 *
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.
11 *
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/>.
14 *)
15 {$INCLUDE ../shared/a_modes.inc}
16 unit e_soundfile_wav;
18 interface
20 uses e_soundfile;
22 type
23 // a WAV loader that just uses SDL_LoadWAV
25 TWAVLoader = class (TSoundLoader)
26 public
27 function Load(Data: Pointer; Len: LongWord; SStreaming: Boolean): Boolean; override; overload;
28 function Load(FName: string; SStreaming: Boolean): Boolean; override; overload;
29 function SetPosition(Pos: LongWord): Boolean; override;
30 function FillBuffer(Buf: Pointer; Len: LongWord): LongWord; override;
31 function GetAll(var OutPtr: Pointer): LongWord; override;
32 procedure Free(); override;
33 private
34 FData: Pointer;
35 FDataLen: LongWord;
36 end;
38 TWAVLoaderFactory = class (TSoundLoaderFactory)
39 public
40 function MatchHeader(Data: Pointer; Len: LongWord): Boolean; override;
41 function MatchExtension(FName: string): Boolean; override;
42 function GetLoader(): TSoundLoader; override;
43 end;
45 implementation
47 uses
48 {$IFDEF USE_SDL}
49 SDL,
50 {$ELSE}
51 SDL2,
52 {$ENDIF}
53 utils, e_log;
55 (* TWAVLoaderFactory *)
57 function TWAVLoaderFactory.MatchHeader(Data: Pointer; Len: LongWord): Boolean;
58 var
59 P: PByte;
60 begin
61 if Len < 5 then
62 begin
63 Result := False;
64 exit;
65 end;
66 P := PByte(Data);
67 Result := ((P+0)^ = Ord('R')) and ((P+1)^ = Ord('I')) and ((P+2)^ = Ord('F')) and ((P+3)^ = Ord('F'));
68 end;
70 function TWAVLoaderFactory.MatchExtension(FName: string): Boolean;
71 begin
72 // TODO: ehhh
73 Result := GetFilenameExt(FName) = '.wav';
74 end;
76 function TWAVLoaderFactory.GetLoader(): TSoundLoader;
77 begin
78 Result := TWAVLoader.Create();
79 end;
81 (* TWAVLoader *)
82 function TWAVLoader.Load(Data: Pointer; Len: LongWord; SStreaming: Boolean): Boolean;
83 var
84 Spec: TSDL_AudioSpec;
85 RW: PSDL_RWops;
86 TmpLen: UInt32;
87 TmpBuf: PUInt8;
88 begin
89 Result := False;
91 RW := SDL_RWFromConstMem(Data, Len);
93 {$IFDEF USE_SDL2}
94 if SDL_LoadWAV_RW(RW, 0, @Spec, @TmpBuf, @TmpLen) = nil then
95 {$ELSE}
96 if SDL_LoadWAV_RW(RW, 0, @Spec, PUInt8(@TmpBuf), @TmpLen) = nil then
97 {$ENDIF}
98 begin
99 e_LogWriteln('Could not load WAV: ' + SDL_GetError());
100 end
101 else
102 begin
103 FFormat.SampleRate := Spec.freq;
104 {$IFDEF USE_SDL2}
105 FFormat.SampleBits := SDL_AUDIO_BITSIZE(Spec.format);
106 {$ELSE}
107 FFormat.SampleBits := Spec.format and $FF;
108 {$ENDIF}
109 FFormat.Channels := Spec.channels;
110 FStreaming := False; // never stream wavs
111 FDataLen := TmpLen;
112 FData := TmpBuf;
113 Result := True;
114 end;
116 SDL_RWclose(RW);
117 end;
119 function TWAVLoader.Load(FName: string; SStreaming: Boolean): Boolean;
120 var
121 Spec: TSDL_AudioSpec;
122 RW: PSDL_RWops;
123 TmpLen: UInt32;
124 TmpBuf: PUInt8;
125 begin
126 Result := False;
128 RW := SDL_RWFromFile(PChar(FName), 'rb');
130 if RW = nil then
131 begin
132 e_LogWritefln('Could not open WAV file `%s`: %s', [FName, SDL_GetError()]);
133 exit;
134 end;
136 {$IFDEF USE_SDL2}
137 if SDL_LoadWAV_RW(RW, 0, @Spec, @TmpBuf, @TmpLen) = nil then
138 {$ELSE}
139 if SDL_LoadWAV_RW(RW, 0, @Spec, PUInt8(@TmpBuf), @TmpLen) = nil then
140 {$ENDIF}
141 begin
142 e_LogWritefln('Could not load WAV file `%s`: %s', [FName, SDL_GetError()]);
143 end
144 else
145 begin
146 FFormat.SampleRate := Spec.freq;
147 {$IFDEF USE_SDL2}
148 FFormat.SampleBits := SDL_AUDIO_BITSIZE(Spec.format);
149 {$ELSE}
150 FFormat.SampleBits := Spec.format and $FF;
151 {$ENDIF}
152 FFormat.Channels := Spec.channels;
153 FStreaming := False; // never stream wavs
154 FDataLen := TmpLen;
155 FData := TmpBuf;
156 Result := True;
157 end;
159 SDL_RWclose(RW);
160 end;
162 function TWAVLoader.SetPosition(Pos: LongWord): Boolean;
163 begin
164 Result := False; // makes no sense when not streaming
165 end;
167 function TWAVLoader.FillBuffer(Buf: Pointer; Len: LongWord): LongWord;
168 begin
169 if FDataLen < Len then
170 Len := FDataLen;
171 if FData <> nil then
172 begin
173 Move(FData^, Buf^, Len);
174 Result := Len;
175 end
176 else
177 Result := 0;
178 end;
180 function TWAVLoader.GetAll(var OutPtr: Pointer): LongWord;
181 begin
182 OutPtr := FData;
183 Result := FDataLen;
184 end;
186 procedure TWAVLoader.Free();
187 begin
188 if FData <> nil then
189 SDL_FreeWAV(FData); // SDL allocates inside the DLL, so we need this
190 end;
192 initialization
193 e_AddSoundLoader(TWAVLoaderFactory.Create());
194 end.