DEADSOFTWARE

Added SFS support (resource wads only) (#4)
[d2df-editor.git] / src / editor / f_addresource_sound.pas
1 unit f_addresource_sound;
3 {$INCLUDE ../shared/a_modes.inc}
5 interface
7 uses
8 LCLIntf, LCLType, LMessages, SysUtils, Variants, Classes,
9 Graphics, Controls, Forms, Dialogs, f_addresource,
10 ExtCtrls, StdCtrls, spectrum, Buttons, ComCtrls, utils;
12 type
13 TAddSoundForm = class (TAddResourceForm)
14 pSpectrum: TPanel;
15 bbPlay: TBitBtn;
16 bbStop: TBitBtn;
17 Timer: TTimer;
18 bEmpty: TButton;
20 procedure FormCreate(Sender: TObject);
21 procedure bbPlayClick(Sender: TObject);
22 procedure TimerTimer(Sender: TObject);
23 procedure FormDestroy(Sender: TObject);
24 procedure FormClose(Sender: TObject; var Action: TCloseAction);
25 procedure bbStopClick(Sender: TObject);
26 procedure FormActivate(Sender: TObject);
27 procedure bOKClick(Sender: TObject);
28 procedure bEmptyClick(Sender: TObject);
30 private
31 FSpectrum: TMiniSpectrum;
32 FSetResource: String;
34 procedure ShowSpectrum();
36 public
37 property SetResource: String read FSetResource write FSetResource;
38 end;
40 var
41 AddSoundForm: TAddSoundForm;
43 implementation
45 uses
46 BinEditor, WADEDITOR, e_log, f_main, g_language, g_resources
47 {$IFNDEF NOSOUND}, fmod, fmodtypes, fmoderrors;{$ELSE};{$ENDIF}
49 {$R *.lfm}
51 {$IFDEF NOSOUND}
52 // fuck my life
53 const
54 FMOD_OK = 0;
56 type
57 FMOD_SYSTEM = Pointer;
58 FMOD_CHANNEL = Pointer;
59 FMOD_SOUND = Pointer;
60 FMOD_CREATESOUNDEXINFO = Pointer;
61 FMOD_RESULT = Integer;
62 {$ENDIF}
64 var
65 F_System: FMOD_SYSTEM;
66 SoundData: Pointer = nil;
67 Sound: FMOD_SOUND = nil;
68 Channel: FMOD_CHANNEL = nil;
69 Playing: Boolean = False;
71 procedure TAddSoundForm.FormCreate(Sender: TObject);
72 var
73 res: FMOD_RESULT;
74 ver: Cardinal;
76 begin
77 Inherited;
79 res := FMOD_OK;
81 {$IFNDEF NOSOUND}
82 try
83 res := FMOD_System_Create(F_System);
84 if res <> FMOD_OK then
85 raise Exception.Create('FMOD_System_Create failed!');
87 res := FMOD_System_GetVersion(F_System, ver);
88 if res <> FMOD_OK then
89 raise Exception.Create('FMOD_System_GetVersion failed!');
91 if ver < FMOD_VERSION then
92 raise Exception.Create('FMOD version is too old! Need '+IntToStr(FMOD_VERSION));
94 res := FMOD_System_SetOutput(F_System, FMOD_OUTPUTTYPE_WINMM);
95 if res <> FMOD_OK then
96 raise Exception.Create('FMOD_System_SetOutput failed!');
98 res := FMOD_System_SetSoftwareFormat(F_System, 48000,
99 FMOD_SOUND_FORMAT_PCM16, 0, 0, FMOD_DSP_RESAMPLER_LINEAR);
100 if res <> FMOD_OK then
101 raise Exception.Create('FMOD_System_SetSoftwareFormat failed!');
103 res := FMOD_System_Init(F_System, 64, FMOD_INIT_NORMAL, nil);
104 if res <> FMOD_OK then
105 raise Exception.Create('FMOD_System_Init failed!');
107 except
108 Application.MessageBox(FMOD_ErrorString(res), 'Initialization', MB_OK or MB_ICONHAND);
109 raise;
110 end;
111 {$ENDIF}
113 FSpectrum := TMiniSpectrum.Create(pSpectrum);
114 FSpectrum.Align := alClient;
115 FSpectrum.Enabled := True;
116 FSpectrum.Style := ssBlock;
117 end;
119 function CreateSoundWAD(Resource: String): Boolean;
120 var
121 FileName, SectionName, ResourceName: String;
122 ResLength: Integer;
123 sz: LongWord;
124 soundExInfo: FMOD_CREATESOUNDEXINFO;
125 res: FMOD_RESULT;
127 begin
128 Result := False;
129 SoundData := nil;
130 Sound := nil;
131 Channel := nil;
132 {$IFNDEF NOSOUND}
133 g_ProcessResourceStr(Resource, FileName, SectionName, ResourceName);
134 g_ReadResource(FileName, SectionName, ResourceName, SoundData, ResLength);
136 if SoundData <> nil then
137 begin
138 sz := SizeOf(FMOD_CREATESOUNDEXINFO);
139 FillMemory(@soundExInfo, sz, 0);
140 soundExInfo.cbsize := sz;
141 soundExInfo.length := LongWord(ResLength);
143 res := FMOD_System_CreateStream(F_System, SoundData,
144 FMOD_LOOP_OFF or FMOD_2D or FMOD_OPENMEMORY,
145 @soundExInfo, Sound);
147 if res <> FMOD_OK then
148 begin
149 e_WriteLog(Format('Error creating sound %s', [Resource]), MSG_WARNING);
150 e_WriteLog(FMOD_ErrorString(res), MSG_WARNING);
151 Exit;
152 end;
153 end
154 else
155 begin
156 e_WriteLog(Format('Error loading sound %s', [Resource]), MSG_WARNING);
157 //e_WriteLog(Format('WAD Reader error: %s', [WAD.GetLastErrorStr]), MSG_WARNING);
158 Exit;
159 end;
161 Result := True;
162 {$ENDIF}
163 end;
165 procedure TAddSoundForm.bbPlayClick(Sender: TObject);
166 var
167 res: FMOD_RESULT;
169 begin
170 Inherited;
172 if FResourceSelected then
173 begin
174 if Playing then
175 bbStop.Click();
177 if not CreateSoundWAD(FFullResourceName) then
178 Exit;
179 {$IFNDEF NOSOUND}
180 res := FMOD_System_PlaySound(F_System, FMOD_CHANNEL_FREE,
181 Sound, False, Channel);
182 if res <> FMOD_OK then
183 begin
184 Application.MessageBox(FMOD_ErrorString(res),
185 PChar(_lc[I_MSG_SOUND_ERROR]),
186 MB_OK or MB_ICONHAND);
187 Exit;
188 end;
190 Playing := True;
192 FMOD_Channel_SetVolume(Channel, 1.0);
194 FSpectrum.SetChannel(Channel);
195 {$ENDIF}
196 end;
197 end;
199 procedure TAddSoundForm.ShowSpectrum;
200 begin
201 if FSpectrum.Enabled then
202 FSpectrum.Draw();
203 end;
205 procedure TAddSoundForm.TimerTimer(Sender: TObject);
206 var
207 res: FMOD_RESULT;
208 b: LongBool;
210 begin
211 Inherited;
212 {$IFNDEF NOSOUND}
213 FMOD_System_Update(F_System);
215 ShowSpectrum();
217 res := FMOD_Channel_IsPlaying(Channel, b);
218 if (res <> FMOD_OK) or (not b) then
219 bbStop.Click();
220 {$ENDIF}
221 end;
223 procedure TAddSoundForm.FormDestroy(Sender: TObject);
224 var
225 res: FMOD_RESULT;
227 begin
228 Inherited;
230 FSpectrum.Free;
231 {$IFNDEF NOSOUND}
232 res := FMOD_System_Close(F_System);
233 if res <> FMOD_OK then
234 begin
235 e_WriteLog('Error closing FMOD system!', MSG_FATALERROR);
236 e_WriteLog(FMOD_ErrorString(res), MSG_FATALERROR);
237 Exit;
238 end;
240 res := FMOD_System_Release(F_System);
241 if res <> FMOD_OK then
242 begin
243 e_WriteLog('Error releasing FMOD system!', MSG_FATALERROR);
244 e_WriteLog(FMOD_ErrorString(res), MSG_FATALERROR);
245 end;
246 {$ENDIF}
247 end;
249 procedure Sound_StopRelease();
250 begin
251 Playing := False;
252 {$IFNDEF NOSOUND}
253 if Channel <> nil then
254 FMOD_Channel_Stop(Channel);
256 if Sound <> nil then
257 FMOD_Sound_Release(Sound);
258 {$ENDIF}
259 if SoundData <> nil then
260 FreeMem(SoundData);
262 SoundData := nil;
263 Sound := nil;
264 Channel := nil;
265 end;
267 procedure TAddSoundForm.FormClose(Sender: TObject;
268 var Action: TCloseAction);
269 begin
270 Inherited;
272 Timer.Enabled := False;
274 FSpectrum.SetChannel(nil);
275 Sound_StopRelease();
276 end;
278 procedure TAddSoundForm.bbStopClick(Sender: TObject);
279 begin
280 Inherited;
282 FSpectrum.SetChannel(nil);
283 Sound_StopRelease();
284 end;
286 procedure TAddSoundForm.FormActivate(Sender: TObject);
287 var
288 FileName, SectionName, ResourceName: String;
289 a: Integer;
291 begin
292 Inherited;
294 Timer.Enabled := True;
296 // Уже есть выбранный ресурс:
297 if FSetResource <> '' then
298 begin
299 g_ProcessResourceStr(FSetResource, FileName, SectionName, ResourceName);
301 if FileName = '' then
302 FileName := _lc[I_WAD_SPECIAL_MAP];
304 if SectionName = '' then
305 SectionName := '..';
307 // WAD файл:
308 a := cbWADList.Items.IndexOf(FileName);
309 if a <> -1 then
310 begin
311 cbWADList.ItemIndex := a;
312 cbWADList.OnChange(nil);
313 end;
315 // Секция:
316 a := cbSectionsList.Items.IndexOf(SectionName);
317 if a <> -1 then
318 begin
319 cbSectionsList.ItemIndex := a;
320 cbSectionsList.OnChange(nil);
321 end;
323 // Ресурс:
324 a := lbResourcesList.Items.IndexOf(ResourceName);
325 if a <> -1 then
326 begin
327 lbResourcesList.ItemIndex := a;
328 lbResourcesList.OnClick(nil);
329 end;
330 end;
331 end;
333 procedure TAddSoundForm.bOKClick(Sender: TObject);
334 begin
335 inherited;
337 ModalResult := mrOk;
338 end;
340 procedure TAddSoundForm.bEmptyClick(Sender: TObject);
341 begin
342 FResourceName := '';
343 ModalResult := mrOk;
344 end;
346 end.