Rev 18 | Go to most recent revision | Details | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
1 | pmbaty | 1 | #include "audio.h" |
2 | #include "resource.h" |
||
3 | |||
4 | #include "3d.h" |
||
5 | #include "backends/backend.h" |
||
6 | #include "harness/config.h" |
||
7 | #include "harness/os.h" |
||
8 | #include "harness/trace.h" |
||
9 | #include "s3/s3.h" |
||
10 | #include "s3cda.h" |
||
11 | #include "s3music.h" |
||
12 | #include "s3sound.h" |
||
13 | #include <ctype.h> |
||
14 | #include <errno.h> |
||
15 | #include <stddef.h> |
||
16 | #include <stdio.h> |
||
17 | #include <stdlib.h> |
||
18 | #include <string.h> |
||
19 | |||
20 | extern int PDGetTotalTime(void); |
||
21 | |||
22 | int gS3_enabled; |
||
23 | int gS3_noutlets; |
||
24 | int gS3_nsound_sources; |
||
25 | int gS3_next_outlet_id; |
||
26 | tS3_outlet* gS3_outlets; |
||
27 | tS3_sound_source* gS3_sound_sources; |
||
28 | tS3_descriptor* gS3_descriptors; |
||
29 | tS3_descriptor* gS3_root_descriptor; |
||
30 | int gS3_opened_output_devices; |
||
31 | int gS3_last_service_time; |
||
32 | int gS3_service_time_delta; |
||
33 | tS3_channel* gS3_unbound_channels; |
||
34 | tS3_channel* gS3_last_unbound_channel; |
||
35 | int gS3_last_error; |
||
36 | int gS3_default_pitch; |
||
37 | tS3_hardware_info gS3_hardware_info; |
||
38 | char* gS3_soundbank_buffer; |
||
39 | int gS3_soundbank_buffer_len; |
||
40 | int gS3_inside_cockpit; |
||
41 | |||
42 | tS3_channel gS3_channel_template; |
||
43 | int gS3_tag_seed; |
||
44 | |||
45 | char gS3_directory_separator[4]; |
||
46 | char gS3_directory_name[8]; |
||
47 | int gS3_have_current_dir; |
||
48 | char gS3_current_dir[260]; |
||
49 | |||
50 | int dword_5216C0; |
||
51 | |||
52 | int S3Init(char* pPath, int pLow_memory_mode) { |
||
53 | tS3_descriptor* root_descriptor; |
||
54 | |||
55 | gS3_noutlets = 0; |
||
56 | gS3_nsound_sources = 0; |
||
57 | gS3_next_outlet_id = 0; |
||
58 | gS3_outlets = NULL; |
||
59 | gS3_sound_sources = NULL; |
||
60 | gS3_descriptors = NULL; |
||
61 | gS3_root_descriptor = NULL; |
||
62 | |||
63 | S3Disable(); |
||
64 | S3DisableMIDI(); |
||
65 | S3DisableCDA(); |
||
66 | gS3_sample_filter_funcs_registered = 0; |
||
67 | gS3_sample_filter_func = NULL; |
||
68 | gS3_sample_filter_disable_func = NULL; |
||
69 | if (S3OpenOutputDevices() == 0) { |
||
70 | return 1; |
||
71 | } |
||
72 | gS3_opened_output_devices = 1; |
||
73 | root_descriptor = S3MemAllocate(sizeof(tS3_descriptor), kMem_S3_sentinel); |
||
74 | if (!root_descriptor) { |
||
75 | return 3; |
||
76 | } |
||
77 | memset(root_descriptor, 0, sizeof(tS3_descriptor)); |
||
78 | root_descriptor->id = 2495081; |
||
79 | gS3_root_descriptor = root_descriptor; |
||
80 | gS3_descriptors = root_descriptor; |
||
81 | if (S3LoadSoundbank(pPath, pLow_memory_mode)) { |
||
82 | return 5; |
||
83 | } |
||
84 | gS3_last_service_time = PDGetTotalTime(); |
||
85 | gS3_unbound_channels = 0; |
||
86 | gS3_last_unbound_channel = 0; |
||
87 | return 0; |
||
88 | } |
||
89 | |||
90 | void S3Shutdown(void) { |
||
91 | tS3_outlet* outlet; // [esp+10h] [ebp-10h] |
||
92 | tS3_outlet* next_outlet; // [esp+14h] [ebp-Ch] |
||
93 | tS3_descriptor* next_descriptor; // [esp+18h] [ebp-8h] |
||
94 | tS3_descriptor* descriptor; // [esp+1Ch] [ebp-4h] |
||
95 | |||
96 | S3StopAllOutletSounds(); |
||
97 | S3DisableMIDI(); |
||
98 | S3DisableCDA(); |
||
99 | if (gS3_enabled) { |
||
100 | S3Disable(); |
||
101 | for (descriptor = gS3_descriptors; descriptor != NULL; descriptor = next_descriptor) { |
||
102 | next_descriptor = descriptor->next; |
||
103 | S3ReleaseSound(descriptor->id); |
||
104 | S3MemFree(descriptor); |
||
105 | } |
||
106 | for (outlet = gS3_outlets; outlet != NULL; outlet = next_outlet) { |
||
107 | next_outlet = outlet->next; |
||
108 | S3ReleaseOutlet(outlet); |
||
109 | } |
||
110 | S3ReleaseUnboundChannels(); |
||
111 | } |
||
112 | if (gS3_opened_output_devices) { |
||
113 | S3CloseDevices(); |
||
114 | } |
||
115 | } |
||
116 | |||
117 | void S3Enable(void) { |
||
118 | gS3_enabled = 1; |
||
119 | } |
||
120 | |||
121 | void S3Disable(void) { |
||
122 | S3StopAllOutletSounds(); |
||
123 | gS3_enabled = 0; |
||
124 | } |
||
125 | |||
126 | int S3OpenOutputDevices(void) { |
||
127 | |||
128 | // strcpy(gS3_directory_separator, "\\"); |
||
129 | strcpy(gS3_directory_separator, "/"); |
||
130 | strcpy(gS3_directory_name, "SOUND"); |
||
131 | memset(&gS3_hardware_info, 0, sizeof(gS3_hardware_info)); |
||
132 | if (S3OpenSampleDevice() == 0) { |
||
133 | return 0; |
||
134 | } |
||
135 | S3OpenCDADevice(); |
||
136 | gS3_hardware_info.timer_installed = 0; |
||
137 | gS3_hardware_info.device_installed = 1; |
||
138 | gS3_hardware_info.independent_pitch = 0; |
||
139 | return 1; |
||
140 | } |
||
141 | |||
142 | int S3OpenSampleDevice(void) { |
||
143 | |||
144 | // if (DirectSoundCreate(0, &gS3_direct_sound_ptr, 0)) { |
||
145 | // return 0; |
||
146 | // } |
||
147 | // if (gS3_direct_sound_ptr->lpVtbl->SetCooperativeLevel(gS3_direct_sound_ptr, gWin32_hwnd, 3)) { |
||
148 | // return 0; |
||
149 | // } |
||
150 | |||
151 | if (AudioBackend_Init() != eAB_success) { |
||
152 | return 0; |
||
153 | } |
||
154 | S3Enable(); |
||
155 | return 1; |
||
156 | } |
||
157 | |||
158 | // returns 0 on failure, 1 on success |
||
159 | int S3OpenCDADevice(void) { |
||
160 | // gS3_cda_device.lpstrDeviceType = (LPCSTR)516; |
||
161 | // if (mciSendCommandA(0, 0x803u, 0x3000u, (DWORD_PTR)&gS3_cda_device) |
||
162 | // && mciSendCommandA(0, 0x803u, 0x3100u, (DWORD_PTR)&gS3_cda_device)) { |
||
163 | // return 0; |
||
164 | // } |
||
165 | // stru_550560.dwTimeFormat = 10; // MCI_FORMAT_TMSF |
||
166 | // mciSendCommandA(gS3_cda_device.wDeviceID, 0x80Du, 0x400u, (DWORD_PTR)&stru_550560); |
||
167 | |||
168 | if (AudioBackend_InitCDA() != eAB_success) { |
||
169 | return 0; |
||
170 | } |
||
171 | |||
172 | S3EnableCDA(); |
||
173 | return 1; |
||
174 | } |
||
175 | |||
176 | void S3CloseDevices(void) { |
||
177 | if (gS3_hardware_info.device_installed) { |
||
178 | // gS3_direct_sound_ptr->lpVtbl->Release(gS3_direct_sound_ptr); |
||
179 | // gS3_direct_sound_ptr = NULL; |
||
180 | |||
181 | AudioBackend_UnInit(); |
||
182 | } |
||
183 | // if (gS3_cda_device.wDeviceID) { |
||
184 | // mciSendCommandA(gS3_cda_device.wDeviceID, 0x804u, 0, 0); // MCI_CLOSE |
||
185 | // } |
||
186 | |||
187 | AudioBackend_UnInitCDA(); |
||
188 | } |
||
189 | |||
190 | int S3ReleaseSound(tS3_sound_id id) { |
||
191 | tS3_channel* c; // [esp+Ch] [ebp-10h] |
||
192 | tS3_outlet* o; // [esp+10h] [ebp-Ch] |
||
193 | tS3_descriptor* desc; // [esp+14h] [ebp-8h] |
||
194 | tS3_sample* sample_ptr; |
||
195 | |||
196 | if (!gS3_enabled) { |
||
197 | return 0; |
||
198 | } |
||
199 | |||
200 | desc = S3GetDescriptorByID(id); |
||
201 | if (desc == NULL) { |
||
202 | return eS3_error_bad_id; |
||
203 | } |
||
204 | if (desc->type == eS3_ST_midi) { |
||
205 | for (o = gS3_outlets; o; o = o->next) { |
||
206 | for (c = o->channel_list; c; c = c->next) { |
||
207 | if (c->descriptor && c->descriptor->id == id) { |
||
208 | S3ReleaseMIDI(c->tag); |
||
209 | } |
||
210 | } |
||
211 | } |
||
212 | } else if (desc->type == eS3_ST_sample) { |
||
213 | sample_ptr = (tS3_sample*)desc->sound_data; |
||
214 | if (sample_ptr == NULL) { |
||
215 | return 0; |
||
216 | } |
||
217 | S3MemFree(sample_ptr->freeptr); |
||
218 | S3MemFree(sample_ptr); |
||
219 | desc->sound_data = NULL; |
||
220 | } |
||
221 | return 0; |
||
222 | } |
||
223 | |||
224 | int S3LoadSoundbank(const char* pSoundbank_filename, int pLow_memory_mode) { |
||
225 | char soundbank_filename[256]; // [esp+Ch] [ebp-218h] BYREF |
||
226 | void* buffer; // [esp+10Ch] [ebp-118h] |
||
227 | tS3_soundbank_read_ctx read_ctx; // [esp+110h] [ebp-114h] BYREF |
||
228 | char* cur_dir; // [esp+120h] [ebp-104h] |
||
229 | char dir_name[256]; // [esp+124h] [ebp-100h] BYREF |
||
230 | |||
231 | if (gS3_enabled) { |
||
232 | dir_name[0] = 0; |
||
233 | soundbank_filename[0] = 0; |
||
234 | cur_dir = S3GetCurrentDir(); |
||
235 | strcpy(dir_name, cur_dir); |
||
236 | strcat(dir_name, gS3_directory_separator); |
||
237 | strcat(dir_name, "DATA"); |
||
238 | strcat(dir_name, gS3_directory_separator); |
||
239 | strcat(dir_name, gS3_directory_name); |
||
240 | strcat(dir_name, gS3_directory_separator); |
||
241 | strcpy(soundbank_filename, pSoundbank_filename); |
||
242 | buffer = S3LoadSoundBankFile(soundbank_filename); |
||
243 | if (!buffer) { |
||
244 | return gS3_last_error; |
||
245 | } |
||
246 | read_ctx.data = (char*)buffer; |
||
247 | read_ctx.data_len = gS3_soundbank_buffer_len; |
||
248 | read_ctx.nlines = 0; |
||
249 | S3SoundBankReaderSkipWhitespace(&read_ctx); |
||
250 | while (S3SoundBankReadEntry(&read_ctx, dir_name, pLow_memory_mode)) { |
||
251 | ; |
||
252 | } |
||
253 | S3MemFree(buffer); |
||
254 | } |
||
255 | return 0; |
||
256 | } |
||
257 | |||
258 | char* S3LoadSoundBankFile(char* pThe_path) { |
||
259 | size_t bytes_read; |
||
260 | // int fd; // [esp+Ch] [ebp-2Ch] |
||
261 | char* buffer; |
||
262 | // struct _stat stat_result; |
||
263 | |||
264 | FILE* fd; |
||
265 | size_t file_size; |
||
266 | |||
267 | // fd = _open(pThe_path, 0x8000); |
||
268 | fd = OS_fopen(pThe_path, "rb"); |
||
269 | if (!fd) { |
||
270 | gS3_last_error = eS3_error_readfile; |
||
271 | return 0; |
||
272 | } |
||
273 | |||
274 | // if (_fstat(fd, &stat_result)) { |
||
275 | // gS3_last_error = eS3_error_readfile; |
||
276 | // return 0; |
||
277 | // } |
||
278 | |||
279 | if (fseek(fd, 0, SEEK_END) != 0) { |
||
280 | gS3_last_error = eS3_error_readfile; |
||
281 | return 0; |
||
282 | } |
||
283 | file_size = ftell(fd); |
||
284 | fseek(fd, 0, SEEK_SET); |
||
285 | |||
286 | buffer = S3MemAllocate(file_size + 1, kMem_S3_sample); |
||
287 | if (buffer == NULL) { |
||
288 | fclose(fd); |
||
289 | gS3_last_error = eS3_error_memory; |
||
290 | return 0; |
||
291 | } |
||
292 | buffer[file_size] = 0; |
||
293 | bytes_read = fread(buffer, 1, file_size, fd); |
||
294 | if (bytes_read == file_size) { |
||
295 | gS3_soundbank_buffer = buffer; |
||
296 | gS3_soundbank_buffer_len = file_size; |
||
297 | fclose(fd); |
||
298 | return buffer; |
||
299 | } |
||
300 | gS3_last_error = eS3_error_readfile; |
||
301 | return 0; |
||
302 | } |
||
303 | |||
304 | void S3SoundBankReaderNextLine(tS3_soundbank_read_ctx* ctx) { |
||
305 | S3SoundBankReaderSkipToNewline(ctx); |
||
306 | S3SoundBankReaderSkipWhitespace(ctx); |
||
307 | } |
||
308 | |||
309 | void S3SoundBankReaderSkipWhitespace(tS3_soundbank_read_ctx* ctx) { |
||
310 | while (ctx->data_len) { |
||
311 | if (isalnum(*ctx->data) || *ctx->data == '-') { |
||
312 | break; |
||
313 | } |
||
314 | S3SoundBankReaderSkipToNewline(ctx); |
||
315 | } |
||
316 | } |
||
317 | |||
318 | void S3SoundBankReaderSkipToNewline(tS3_soundbank_read_ctx* ctx) { |
||
319 | char* newline_ptr; // [esp+Ch] [ebp-4h] |
||
320 | |||
321 | newline_ptr = memchr(ctx->data, '\n', ctx->data_len); |
||
322 | if (newline_ptr) { |
||
323 | S3SoundBankReaderAdvance(ctx, newline_ptr + 1 - ctx->data); |
||
324 | ctx->nlines++; |
||
325 | } else { |
||
326 | ctx->data_len = 0; |
||
327 | } |
||
328 | } |
||
329 | |||
330 | void S3SoundBankReaderAdvance(tS3_soundbank_read_ctx* buffer, int bytes_read) { |
||
331 | buffer->data += bytes_read; |
||
332 | buffer->data_len -= bytes_read; |
||
333 | } |
||
334 | |||
335 | int S3SoundBankReadEntry(tS3_soundbank_read_ctx* ctx, char* dir_name, int low_memory_mode) { |
||
336 | int nmemory_proxies; // [esp+Ch] [ebp-24h] BYREF |
||
337 | int i; // [esp+10h] [ebp-20h] |
||
338 | int proxy_id; // [esp+14h] [ebp-1Ch] BYREF |
||
339 | tS3_descriptor* desc; // [esp+18h] [ebp-18h] |
||
340 | double tmp1; // [esp+1Ch] [ebp-14h] BYREF |
||
341 | double tmp2; // [esp+24h] [ebp-Ch] BYREF |
||
342 | int char_count; // [esp+2Ch] [ebp-4h] BYREF |
||
343 | char cda_dir_name[4]; |
||
344 | |||
345 | desc = S3CreateDescriptor(); |
||
346 | if (!desc) { |
||
347 | return gS3_last_error; |
||
348 | } |
||
349 | if (sscanf(ctx->data, "%i%n", &desc->id, &char_count) != 1) { |
||
350 | return 0; |
||
351 | } |
||
352 | S3SoundBankReaderAdvance(ctx, char_count); |
||
353 | S3SoundBankReaderNextLine(ctx); |
||
354 | if (sscanf(ctx->data, "%i,%i%n", &desc->type, &desc->flags, &char_count) != 2) { |
||
355 | return 0; |
||
356 | } |
||
357 | S3SoundBankReaderAdvance(ctx, char_count); |
||
358 | S3SoundBankReaderNextLine(ctx); |
||
359 | if (desc->type == eS3_ST_cda) { |
||
360 | dir_name = cda_dir_name; |
||
361 | cda_dir_name[0] = '\0'; |
||
362 | } |
||
363 | if (!S3SoundBankReaderReadFilename(&desc->filename, ctx, dir_name)) { |
||
364 | return 0; |
||
365 | } |
||
366 | S3SoundBankReaderNextLine(ctx); |
||
367 | if (sscanf(ctx->data, "%i%n", (int*)&desc->priority, &char_count) != 1) { |
||
368 | return 0; |
||
369 | } |
||
370 | S3SoundBankReaderAdvance(ctx, char_count); |
||
371 | S3SoundBankReaderNextLine(ctx); |
||
372 | if (sscanf(ctx->data, "%i%n", &desc->repeats, &char_count) != 1) { |
||
373 | return 0; |
||
374 | } |
||
375 | S3SoundBankReaderAdvance(ctx, char_count); |
||
376 | S3SoundBankReaderNextLine(ctx); |
||
377 | if (sscanf(ctx->data, "%i,%i%n", &desc->min_volume, &desc->max_volume, &char_count) != 2) { |
||
378 | return 0; |
||
379 | } |
||
380 | S3SoundBankReaderAdvance(ctx, char_count); |
||
381 | S3SoundBankReaderNextLine(ctx); |
||
382 | if (sscanf(ctx->data, "%lf,%lf%n", &tmp1, &tmp2, &char_count) != 2) { |
||
383 | return 0; |
||
384 | } |
||
385 | S3SoundBankReaderAdvance(ctx, char_count); |
||
386 | S3SoundBankReaderNextLine(ctx); |
||
387 | if (tmp1 == 0.0f) { |
||
388 | tmp1 = 1.0f; |
||
389 | } |
||
390 | if (tmp2 == 0.0f) { |
||
391 | tmp2 = 1.0f; |
||
392 | } |
||
393 | desc->min_pitch = ldexpf(tmp1, 16); |
||
394 | desc->max_pitch = ldexpf(tmp2, 16); |
||
395 | if (sscanf(ctx->data, "%lf,%lf%n", &tmp1, &tmp2, &char_count) != 2) { |
||
396 | return 0; |
||
397 | } |
||
398 | S3SoundBankReaderAdvance(ctx, char_count); |
||
399 | S3SoundBankReaderNextLine(ctx); |
||
400 | if (tmp1 == 0.0) { |
||
401 | tmp1 = 1.0; |
||
402 | } |
||
403 | if (tmp2 == 0.0) { |
||
404 | tmp2 = 1.0; |
||
405 | } |
||
406 | desc->min_speed = ldexpf(tmp1, 16); |
||
407 | desc->max_speed = ldexpf(tmp2, 16); |
||
408 | if (sscanf(ctx->data, "%i%n", &desc->special_fx, &char_count) != 1) { |
||
409 | return 0; |
||
410 | } |
||
411 | S3SoundBankReaderAdvance(ctx, char_count); |
||
412 | S3SoundBankReaderNextLine(ctx); |
||
413 | if (sscanf(ctx->data, "%d%n", &nmemory_proxies, &char_count) != 1) { |
||
414 | return 0; |
||
415 | } |
||
416 | S3SoundBankReaderAdvance(ctx, char_count); |
||
417 | S3SoundBankReaderNextLine(ctx); |
||
418 | desc->memory_proxy = -1; |
||
419 | for (i = 0; i < nmemory_proxies; i++) { |
||
420 | if (sscanf(ctx->data, "%d%n", &proxy_id, &char_count) != 1) { |
||
421 | return 0; |
||
422 | } |
||
423 | if (low_memory_mode == i + 1) { |
||
424 | desc->memory_proxy = proxy_id; |
||
425 | } |
||
426 | S3SoundBankReaderAdvance(ctx, char_count); |
||
427 | S3SoundBankReaderNextLine(ctx); |
||
428 | } |
||
429 | if ((desc->flags & 1) != 0 && desc->memory_proxy == -1) { |
||
430 | if (desc->type == eS3_ST_midi) { |
||
431 | desc->sound_data = NULL; |
||
432 | } else if (S3LoadSample(desc->id) != 0) { |
||
433 | printf("\nSound bank file: couldn't load '%s'\n", desc->filename); |
||
434 | ctx->data_len = 1; |
||
435 | return 0; |
||
436 | } |
||
437 | } |
||
438 | return 1; |
||
439 | } |
||
440 | |||
441 | tS3_descriptor* S3CreateDescriptor(void) { |
||
442 | tS3_descriptor* root; |
||
443 | tS3_descriptor* d; |
||
444 | |||
445 | d = S3MemAllocate(sizeof(tS3_descriptor), kMem_S3_descriptor); |
||
446 | if (!d) { |
||
447 | gS3_last_error = eS3_error_memory; |
||
448 | return NULL; |
||
449 | } |
||
450 | memset(d, 0, sizeof(tS3_descriptor)); |
||
451 | root = gS3_root_descriptor; |
||
452 | gS3_root_descriptor->next = d; |
||
453 | d->prev = root; |
||
454 | gS3_root_descriptor = d; |
||
455 | return d; |
||
456 | } |
||
457 | |||
458 | int S3SoundBankReaderReadFilename(char** filename, tS3_soundbank_read_ctx* ctx, const char* dir_name) { |
||
459 | char* data_start; // [esp+10h] [ebp-Ch] |
||
460 | unsigned int bytes_read; // [esp+14h] [ebp-8h] |
||
461 | unsigned int dir_name_len; // [esp+18h] [ebp-4h] |
||
462 | |||
463 | data_start = ctx->data; |
||
464 | dir_name_len = strlen(dir_name); |
||
465 | while (ctx->data_len) { |
||
466 | if (isspace(*ctx->data)) { |
||
467 | break; |
||
468 | } |
||
469 | S3SoundBankReaderAdvance(ctx, 1); |
||
470 | } |
||
471 | bytes_read = ctx->data - data_start; |
||
472 | if (!bytes_read) { |
||
473 | return 0; |
||
474 | } |
||
475 | *filename = S3MemAllocate(bytes_read + dir_name_len + 1, kMem_S3_scan_name); |
||
476 | if (!*filename) { |
||
477 | return 0; |
||
478 | } |
||
479 | strcpy(*filename, dir_name); |
||
480 | memcpy(&(*filename)[dir_name_len], data_start, bytes_read); |
||
481 | (*filename)[bytes_read + dir_name_len] = '\0'; |
||
482 | return 1; |
||
483 | } |
||
484 | |||
485 | tS3_outlet* S3CreateOutlet(int unk1, int pChannel_count) { |
||
486 | tS3_outlet* o; |
||
487 | int nchannels; |
||
488 | tS3_outlet* outlet; |
||
489 | int channels_remaining; |
||
490 | |||
491 | // nchannels = (int)operator new(unk1, (void*)pChannel_count); |
||
492 | nchannels = pChannel_count; |
||
493 | |||
494 | if (nchannels == 0) { |
||
495 | gS3_last_error = eS3_error_channel_alloc; |
||
496 | return NULL; |
||
497 | } |
||
498 | outlet = S3MemAllocate(sizeof(tS3_outlet), kMem_S3_outlet); |
||
499 | if (outlet == NULL) { |
||
500 | gS3_last_error = eS3_error_memory; |
||
501 | return 0; |
||
502 | } |
||
503 | memset(outlet, 0, sizeof(tS3_outlet)); |
||
504 | channels_remaining = S3CreateOutletChannels(outlet, nchannels); |
||
505 | if (channels_remaining == nchannels) { |
||
506 | S3MemFree(outlet); |
||
507 | return NULL; |
||
508 | } |
||
509 | o = gS3_outlets; |
||
510 | if (gS3_outlets) { |
||
511 | while (o->next) { |
||
512 | o = o->next; |
||
513 | } |
||
514 | o->next = outlet; |
||
515 | outlet->prev = o; |
||
516 | } else { |
||
517 | gS3_outlets = outlet; |
||
518 | } |
||
519 | outlet->max_channels = nchannels - channels_remaining; |
||
520 | outlet->id = gS3_next_outlet_id; |
||
521 | gS3_next_outlet_id++; |
||
522 | outlet->independent_pitch = gS3_hardware_info.independent_pitch; |
||
523 | gS3_noutlets++; |
||
524 | return outlet; |
||
525 | } |
||
526 | |||
527 | int S3CreateOutletChannels(tS3_outlet* outlet, int pChannel_count) { |
||
528 | tS3_channel* chan; // [esp+Ch] [ebp-8h] |
||
529 | tS3_channel* last_chan; // [esp+10h] [ebp-4h] |
||
530 | |||
531 | last_chan = NULL; |
||
532 | while (pChannel_count) { |
||
533 | chan = (tS3_channel*)S3MemAllocate(sizeof(tS3_channel), kMem_S3_channel); |
||
534 | if (!chan) { |
||
535 | return pChannel_count; |
||
536 | } |
||
537 | memset(chan, 0, sizeof(tS3_channel)); |
||
538 | chan->owner_outlet = outlet; |
||
539 | |||
540 | if (S3CreateTypeStructs(chan) == 0) { |
||
541 | S3MemFree(chan); |
||
542 | return pChannel_count; |
||
543 | } |
||
544 | chan->volume_multiplier = 1.0f; |
||
545 | if (last_chan) { |
||
546 | last_chan->next = chan; |
||
547 | } else { |
||
548 | outlet->channel_list = chan; |
||
549 | } |
||
550 | last_chan = chan; |
||
551 | pChannel_count--; |
||
552 | } |
||
553 | return 0; |
||
554 | } |
||
555 | |||
556 | void S3ReleaseOutlet(tS3_outlet* outlet) { |
||
557 | tS3_outlet* next; |
||
558 | tS3_outlet* prev; |
||
559 | |||
560 | if (outlet) { |
||
561 | S3UnbindChannels(outlet); |
||
562 | prev = outlet->prev; |
||
563 | next = outlet->next; |
||
564 | if (prev != NULL) { |
||
565 | prev->next = next; |
||
566 | } else { |
||
567 | gS3_outlets = outlet->next; |
||
568 | } |
||
569 | if (next != NULL) { |
||
570 | next->prev = prev; |
||
571 | } |
||
572 | if (gS3_noutlets) { |
||
573 | gS3_noutlets--; |
||
574 | if (gS3_noutlets == 0) { |
||
575 | gS3_outlets = NULL; |
||
576 | } |
||
577 | } |
||
578 | S3MemFree(outlet); |
||
579 | } |
||
580 | } |
||
581 | |||
582 | int S3UnbindChannels(tS3_outlet* outlet) { |
||
583 | tS3_channel* chan; |
||
584 | tS3_channel* next; |
||
585 | |||
586 | for (chan = outlet->channel_list; chan; chan = next) { |
||
587 | next = chan->next; |
||
588 | S3ReleaseTypeStructs(chan); |
||
589 | if (gS3_unbound_channels) { |
||
590 | gS3_last_unbound_channel->next = chan; |
||
591 | } else { |
||
592 | gS3_unbound_channels = chan; |
||
593 | } |
||
594 | gS3_last_unbound_channel = chan; |
||
595 | memset(chan, 0, sizeof(tS3_channel)); |
||
596 | } |
||
597 | outlet->channel_list = NULL; |
||
598 | return 1; |
||
599 | } |
||
600 | |||
601 | void S3ReleaseUnboundChannels(void) { |
||
602 | tS3_channel* channel; // [esp+Ch] [ebp-8h] |
||
603 | tS3_channel* next_channel; // [esp+10h] [ebp-4h] |
||
604 | |||
605 | for (channel = gS3_unbound_channels; channel != NULL; channel = next_channel) { |
||
606 | next_channel = channel->next; |
||
607 | S3MemFree(channel); |
||
608 | } |
||
609 | } |
||
610 | |||
611 | tS3_channel* S3AllocateChannel(tS3_outlet* outlet, int priority) { |
||
612 | tS3_channel* c; // [esp+Ch] [ebp-10h] |
||
613 | int lowest_priority; // [esp+10h] [ebp-Ch] MAPDST |
||
614 | int this_priority; // [esp+14h] [ebp-8h] |
||
615 | tS3_channel* lowest_priority_chan; // [esp+18h] [ebp-4h] |
||
616 | |||
617 | lowest_priority_chan = outlet->channel_list; |
||
618 | c = outlet->channel_list; |
||
619 | if (lowest_priority_chan == NULL) { |
||
620 | return NULL; |
||
621 | } |
||
622 | while (c) { |
||
623 | if (!c->active || c->needs_service) { |
||
624 | if (!c->needs_service) { |
||
625 | c->active = 1; |
||
626 | return c; |
||
627 | } |
||
628 | } else { |
||
629 | if (lowest_priority_chan->descriptor) { |
||
630 | lowest_priority = lowest_priority_chan->descriptor->priority |
||
631 | * (lowest_priority_chan->right_volume + lowest_priority_chan->left_volume + 1); |
||
632 | } else { |
||
633 | lowest_priority = 0; |
||
634 | } |
||
635 | if (c->descriptor) { |
||
636 | this_priority = c->descriptor->priority * (c->left_volume + c->right_volume + 1); |
||
637 | } else { |
||
638 | this_priority = 0; |
||
639 | } |
||
640 | if (this_priority <= lowest_priority) { |
||
641 | lowest_priority_chan = c; |
||
642 | } |
||
643 | } |
||
644 | c = c->next; |
||
645 | } |
||
646 | if (!lowest_priority_chan->descriptor || lowest_priority_chan->needs_service) { |
||
647 | lowest_priority = 0; |
||
648 | } else { |
||
649 | lowest_priority = lowest_priority_chan->descriptor->priority * (lowest_priority_chan->right_volume + lowest_priority_chan->left_volume + 1); |
||
650 | } |
||
651 | if (priority > lowest_priority && !lowest_priority_chan->needs_service) { |
||
652 | lowest_priority_chan->termination_reason = 2; |
||
653 | S3StopChannel(lowest_priority_chan); |
||
654 | lowest_priority_chan->active = 1; |
||
655 | } |
||
656 | |||
657 | return NULL; |
||
658 | } |
||
659 | |||
660 | int S3StopChannel(tS3_channel* chan) { |
||
661 | if (!chan->tag) { |
||
662 | return eS3_error_bad_stag; |
||
663 | } |
||
664 | chan->termination_reason = eS3_tr_stopped; |
||
665 | if (chan->active) { |
||
666 | chan->needs_service = 1; |
||
667 | } |
||
668 | if (chan->type == eS3_ST_sample) { |
||
669 | if (chan->sound_source_ptr) { |
||
670 | chan->sound_source_ptr->tag = 0; |
||
671 | chan->sound_source_ptr->channel = 0; |
||
672 | chan->sound_source_ptr->volume = 0; |
||
673 | } |
||
674 | if (S3StopSample(chan) == 0) { |
||
675 | return eS3_error_function_failed; |
||
676 | } |
||
677 | } else if (chan->type == eS3_ST_midi) { |
||
678 | if (S3StopMIDI(chan) != 0) { |
||
679 | return eS3_error_function_failed; |
||
680 | } |
||
681 | } else if (chan->type == eS3_ST_cda) { |
||
682 | if (S3StopCDA(chan) != 0) { |
||
683 | return eS3_error_function_failed; |
||
684 | } |
||
685 | } |
||
686 | |||
687 | if ((chan->descriptor->flags & 2) != 0) { |
||
688 | S3ReleaseSound(chan->descriptor->id); |
||
689 | } |
||
690 | chan->repetitions = 1; |
||
691 | return 0; |
||
692 | } |
||
693 | |||
694 | tS3_sound_source* S3CreateSoundSourceBR(br_vector3* pPosition, br_vector3* pVelocity, tS3_outlet* pBound_outlet) { |
||
695 | tS3_sound_source* source; // [esp+Ch] [ebp-4h] |
||
696 | |||
697 | if (!gS3_enabled) { |
||
698 | return 0; |
||
699 | } |
||
700 | source = S3CreateSoundSource(pPosition, pVelocity, pBound_outlet); |
||
701 | if (source != NULL) { |
||
702 | source->brender_vector = 1; |
||
703 | } |
||
704 | return source; |
||
705 | } |
||
706 | |||
707 | tS3_sound_source* S3CreateSoundSource(void* pPosition, void* pVelocity, tS3_outlet* pBound_outlet) { |
||
708 | tS3_sound_source* src; // [esp+Ch] [ebp-8h] |
||
709 | tS3_sound_source* s; // [esp+10h] [ebp-4h] |
||
710 | |||
711 | src = S3MemAllocate(sizeof(tS3_sound_source), kMem_S3_source); |
||
712 | if (src == NULL) { |
||
713 | gS3_last_error = eS3_error_memory; |
||
714 | return 0; |
||
715 | } |
||
716 | memset(src, 0, sizeof(tS3_sound_source)); |
||
717 | src->bound_outlet = pBound_outlet; |
||
718 | src->position_ptr = pPosition; |
||
719 | src->velocity_ptr = pVelocity; |
||
720 | s = gS3_sound_sources; |
||
721 | if (gS3_sound_sources) { |
||
722 | while (s->next) { |
||
723 | s = s->next; |
||
724 | } |
||
725 | s->next = src; |
||
726 | src->prev = s; |
||
727 | } else { |
||
728 | gS3_sound_sources = src; |
||
729 | } |
||
730 | gS3_nsound_sources++; |
||
731 | return src; |
||
732 | } |
||
733 | |||
734 | int S3ReleaseSoundSource(tS3_sound_source* src) { |
||
735 | tS3_sound_source* prev; // [esp+Ch] [ebp-8h] |
||
736 | tS3_sound_source* next; // [esp+10h] [ebp-4h] |
||
737 | |||
738 | if (!gS3_enabled) { |
||
739 | return 0; |
||
740 | } |
||
741 | |||
742 | if (src) { |
||
743 | prev = src->prev; |
||
744 | next = src->next; |
||
745 | if (prev) { |
||
746 | prev->next = next; |
||
747 | } else { |
||
748 | gS3_sound_sources = src->next; |
||
749 | } |
||
750 | if (next) { |
||
751 | next->prev = prev; |
||
752 | } |
||
753 | if (gS3_nsound_sources) { |
||
754 | gS3_nsound_sources--; |
||
755 | if (gS3_nsound_sources == 0) { |
||
756 | gS3_sound_sources = NULL; |
||
757 | } |
||
758 | } |
||
759 | S3StopSoundSource(src); |
||
760 | S3MemFree(src); |
||
761 | } |
||
762 | return 0; |
||
763 | } |
||
764 | |||
765 | void S3Service(int inside_cockpit, int unk1) { |
||
766 | |||
767 | int now; // [esp+Ch] [ebp-10h] |
||
768 | tS3_channel* c; // [esp+10h] [ebp-Ch] |
||
769 | tS3_outlet* o; // [esp+14h] [ebp-8h] |
||
770 | int v5; // [esp+18h] [ebp-4h] |
||
771 | |||
772 | v5 = 0; |
||
773 | gS3_inside_cockpit = inside_cockpit; |
||
774 | if (!gS3_enabled) { |
||
775 | return; |
||
776 | } |
||
777 | now = PDGetTotalTime(); |
||
778 | gS3_service_time_delta = now - gS3_last_service_time; |
||
779 | gS3_last_service_time = now; |
||
780 | S3ServiceOutlets(); |
||
781 | if (unk1 == 1) { |
||
782 | S3UpdateListenerVectors(); |
||
783 | S3ServiceAmbientSoundSources(); |
||
784 | } |
||
785 | for (o = gS3_outlets; o; o = o->next) { |
||
786 | for (c = o->channel_list; c; c = c->next) { |
||
787 | if (c->needs_service) { |
||
788 | c->needs_service = 0; |
||
789 | if (c->descriptor && c->descriptor->flags == 2) { |
||
790 | S3ReleaseSound(c->descriptor->id); |
||
791 | } |
||
792 | c->active = 0; |
||
793 | if (c->type != eS3_ST_midi) { |
||
794 | c->tag = 0; |
||
795 | } |
||
796 | } else if (c->spatial_sound && c->active) { |
||
797 | if (S3UpdateSpatialSound(c)) { |
||
798 | if (c->sound_source_ptr && c->sound_source_ptr->ambient && !S3SoundStillPlaying(c->tag)) { |
||
799 | S3UpdateSoundSource(NULL, -1, c->sound_source_ptr, -1.0f, -1, -1, 0, -1, -1); |
||
800 | } |
||
801 | } else if (c->sound_source_ptr) { |
||
802 | if (c->sound_source_ptr->ambient) { |
||
803 | S3UpdateSoundSource(NULL, -1, c->sound_source_ptr, -1.0f, -1, -1, 0, -1, -1); |
||
804 | } |
||
805 | } else { |
||
806 | S3StopChannel(c); |
||
807 | } |
||
808 | } else if (c->type == eS3_ST_midi && c->active) { |
||
809 | // sub_4124BE(c); |
||
810 | } |
||
811 | if (unk1 < 2 && gS3_last_service_time > dword_5216C0) { |
||
812 | v5 = 1; |
||
813 | if (!c->active && c->spatial_sound == 2) { |
||
814 | // null_unknown_libname_8(); /* no-op */ |
||
815 | } |
||
816 | } |
||
817 | } |
||
818 | } |
||
819 | if (v5) { |
||
820 | dword_5216C0 = gS3_last_service_time; |
||
821 | } |
||
822 | } |
||
823 | |||
824 | void S3ServiceOutlets(void) { |
||
825 | tS3_channel* c; // [esp+Ch] [ebp-8h] |
||
826 | tS3_outlet* o; // [esp+10h] [ebp-4h] |
||
827 | |||
828 | for (o = gS3_outlets; o; o = o->next) { |
||
829 | for (c = o->channel_list; c; c = c->next) { |
||
830 | S3ServiceChannel(c); |
||
831 | } |
||
832 | } |
||
833 | } |
||
834 | |||
835 | int S3ServiceChannel(tS3_channel* chan) { |
||
836 | if (chan->type == eS3_ST_sample) { |
||
837 | if (AudioBackend_SoundIsPlaying(chan)) { |
||
838 | return 1; |
||
839 | } |
||
840 | S3StopSample(chan); |
||
841 | return 0; |
||
842 | } else if (chan->type == eS3_ST_midi) { |
||
843 | return !S3IsMIDIStopped(chan); |
||
844 | } else if (chan->type == eS3_ST_cda) { |
||
845 | return S3IsCDAPlaying(); |
||
846 | } else { |
||
847 | return 0; |
||
848 | } |
||
849 | } |
||
850 | |||
851 | void S3StopAllOutletSounds(void) { |
||
852 | tS3_outlet* o; // [esp+Ch] [ebp-4h] |
||
853 | |||
854 | if (!gS3_enabled) { |
||
855 | return; |
||
856 | } |
||
857 | |||
858 | for (o = gS3_outlets; o; o = o->next) { |
||
859 | S3StopOutletSound(o); |
||
860 | } |
||
861 | } |
||
862 | |||
863 | tS3_sound_tag S3StartSound(tS3_outlet* pOutlet, tS3_sound_id pSound) { |
||
864 | int repetitions; // eax |
||
865 | tS3_channel* chan; // [esp+14h] [ebp-Ch] |
||
866 | tS3_descriptor* desc; // [esp+1Ch] [ebp-4h] |
||
867 | |||
868 | if (!gS3_enabled) { |
||
869 | return 0; |
||
870 | } |
||
871 | if (!pOutlet) { |
||
872 | gS3_last_error = eS3_error_bad_id; |
||
873 | return 0; |
||
874 | } |
||
875 | desc = S3GetDescriptorByID(pSound); |
||
876 | if (!desc) { |
||
877 | gS3_last_error = eS3_error_bad_id; |
||
878 | return 0; |
||
879 | } |
||
880 | memset(&gS3_channel_template, 0, sizeof(gS3_channel_template)); |
||
881 | S3CalculateRandomizedFields(&gS3_channel_template, desc); |
||
882 | chan = S3AllocateChannel(pOutlet, desc->priority * (gS3_channel_template.right_volume + gS3_channel_template.left_volume + 1)); |
||
883 | if (!chan) { |
||
884 | gS3_last_error = eS3_error_channel_alloc; |
||
885 | return 0; |
||
886 | } |
||
887 | chan->left_volume = gS3_channel_template.left_volume * chan->volume_multiplier; |
||
888 | chan->right_volume = gS3_channel_template.right_volume * chan->volume_multiplier; |
||
889 | chan->rate = gS3_channel_template.rate; |
||
890 | if (desc->type == eS3_ST_sample && (!desc->sound_data || desc->flags == 2)) { |
||
891 | if (!S3LoadSample(pSound)) { |
||
892 | chan->needs_service = 1; |
||
893 | gS3_last_error = eS3_error_load_sound; |
||
894 | return 0; |
||
895 | } |
||
896 | } |
||
897 | if (chan->descriptor && chan->descriptor->type == 1 && chan->descriptor->id != pSound) { |
||
898 | S3ReleaseMIDI(chan->tag); |
||
899 | } |
||
900 | chan->spatial_sound = 0; |
||
901 | chan->sound_source_ptr = 0; |
||
902 | chan->descriptor = desc; |
||
903 | chan->type = desc->type; |
||
904 | repetitions = desc->repeats; |
||
905 | if (repetitions <= 0) { |
||
906 | repetitions = 0; |
||
907 | } |
||
908 | chan->repetitions = repetitions; |
||
909 | chan->needs_service = 0; |
||
910 | chan->termination_reason = eS3_tr_natural; |
||
911 | chan->tag = S3GenerateTag(pOutlet); |
||
912 | if (desc->type == eS3_ST_midi && !desc->sound_data) { |
||
913 | if (S3MIDILoadSong(chan)) { |
||
914 | chan->needs_service = 1; |
||
915 | return 0; |
||
916 | } |
||
917 | } |
||
918 | if (chan->type == eS3_ST_sample) { |
||
919 | S3ExecuteSampleFilterFuncs(chan); |
||
920 | if (S3PlaySample(chan) == 0) { |
||
921 | gS3_last_error = eS3_error_start_sound; |
||
922 | chan->needs_service = 1; |
||
923 | return 0; |
||
924 | } |
||
925 | } else if (chan->type == eS3_ST_midi) { |
||
926 | if (S3PlayMIDI(chan)) { |
||
927 | chan->needs_service = 1; |
||
928 | gS3_last_error = eS3_error_start_song; |
||
929 | return 0; |
||
930 | } |
||
931 | S3SetMIDIVolume(chan); |
||
932 | } else if (chan->type == eS3_ST_cda) { |
||
933 | if (S3PlayCDA(chan)) { |
||
934 | chan->needs_service = 1; |
||
935 | gS3_last_error = eS3_error_start_cda; |
||
936 | return 0; |
||
937 | } |
||
938 | } |
||
939 | |||
940 | return chan->tag; |
||
941 | } |
||
942 | |||
943 | tS3_sound_tag S3StartSound2(tS3_outlet* pOutlet, tS3_sound_id pSound, tS3_repeats pRepeats, tS3_volume pLVolume, tS3_volume pRVolume, tS3_pitch pPitch, tS3_speed pSpeed) { |
||
944 | tS3_channel* chan; // [esp+30h] [ebp-Ch] |
||
945 | tS3_descriptor* desc; // [esp+38h] [ebp-4h] |
||
946 | |||
947 | if (!gS3_enabled) { |
||
948 | return 0; |
||
949 | } |
||
950 | desc = S3GetDescriptorByID(pSound); |
||
951 | if (!desc) { |
||
952 | gS3_last_error = eS3_error_bad_id; |
||
953 | return 0; |
||
954 | } |
||
955 | if (pLVolume < 0) { |
||
956 | pLVolume = 128; |
||
957 | } |
||
958 | if (pRVolume < 0) { |
||
959 | pRVolume = 128; |
||
960 | } |
||
961 | if (pLVolume > 255) { |
||
962 | pLVolume = 255; |
||
963 | } |
||
964 | if (pRVolume > 255) { |
||
965 | pRVolume = 255; |
||
966 | } |
||
967 | chan = S3AllocateChannel(pOutlet, desc->priority * (pLVolume + pRVolume + 1)); |
||
968 | if (chan == NULL) { |
||
969 | gS3_last_error = eS3_error_channel_alloc; |
||
970 | return 0; |
||
971 | } |
||
972 | if (desc->type == eS3_ST_sample) { |
||
973 | if (desc->sound_data == NULL && (!S3LoadSample(pSound) || (desc->flags & 2) != 0)) { |
||
974 | chan->needs_service = 1; |
||
975 | gS3_last_error = eS3_error_load_sound; |
||
976 | return 0; |
||
977 | } |
||
978 | } |
||
979 | |||
980 | if (chan->descriptor && chan->descriptor->type == eS3_ST_midi) { |
||
981 | if (chan->descriptor->id != pSound) { |
||
982 | S3ReleaseMIDI(chan->tag); |
||
983 | } |
||
984 | } |
||
985 | chan->spatial_sound = 0; |
||
986 | chan->descriptor = desc; |
||
987 | chan->needs_service = 0; |
||
988 | chan->termination_reason = eS3_tr_natural; |
||
989 | chan->type = desc->type; |
||
990 | chan->sound_source_ptr = NULL; |
||
991 | chan->repetitions = MAX(pRepeats, 0); |
||
992 | S3CalculateRandomizedFields(chan, desc); |
||
993 | chan->left_volume = pLVolume * chan->volume_multiplier; |
||
994 | chan->right_volume = pRVolume * chan->volume_multiplier; |
||
995 | chan->tag = S3GenerateTag(pOutlet); |
||
996 | if (pPitch == -1) { |
||
997 | pPitch = 0x10000; |
||
998 | } |
||
999 | if (pSpeed == -1) { |
||
1000 | pSpeed = 0x10000; |
||
1001 | } |
||
1002 | chan->rate = ldexpf(pPitch, -16) * chan->rate; |
||
1003 | if (!pOutlet->independent_pitch) { |
||
1004 | chan->rate = ldexpf(pSpeed, -16) * chan->rate; |
||
1005 | } |
||
1006 | if (desc->type == eS3_ST_midi && desc->sound_data == NULL && S3MIDILoadSong(chan)) { |
||
1007 | chan->needs_service = 1; |
||
1008 | return 0; |
||
1009 | } |
||
1010 | |||
1011 | switch (chan->type) { |
||
1012 | case eS3_ST_sample: |
||
1013 | S3ExecuteSampleFilterFuncs(chan); |
||
1014 | if (!S3PlaySample(chan)) { |
||
1015 | chan->needs_service = 1; |
||
1016 | gS3_last_error = eS3_error_start_sound; |
||
1017 | return 0; |
||
1018 | } |
||
1019 | break; |
||
1020 | |||
1021 | case eS3_ST_midi: |
||
1022 | if (S3PlayMIDI(chan)) { |
||
1023 | chan->needs_service = 1; |
||
1024 | gS3_last_error = eS3_error_start_song; |
||
1025 | return 0; |
||
1026 | } |
||
1027 | S3SetMIDIVolume(chan); |
||
1028 | break; |
||
1029 | |||
1030 | case eS3_ST_cda: |
||
1031 | if (S3PlayCDA(chan)) { |
||
1032 | chan->needs_service = 1; |
||
1033 | gS3_last_error = eS3_error_start_cda; |
||
1034 | return 0; |
||
1035 | } |
||
1036 | break; |
||
1037 | } |
||
1038 | |||
1039 | return chan->tag; |
||
1040 | } |
||
1041 | |||
1042 | void S3CalculateRandomizedFields(tS3_channel* chan, tS3_descriptor* desc) { |
||
1043 | int vol; // eax |
||
1044 | |||
1045 | vol = S3IRandomBetween(desc->min_volume, desc->max_volume, 128); |
||
1046 | chan->left_volume = vol; |
||
1047 | chan->right_volume = vol; |
||
1048 | if (desc->type == eS3_ST_sample) { |
||
1049 | #if defined(DETHRACE_FIX_BUGS) |
||
1050 | /* Avoid a possible NULL pointer dereference. */ |
||
1051 | if (desc->sound_data == NULL) { |
||
1052 | chan->rate = desc->min_pitch; |
||
1053 | return; |
||
1054 | } |
||
1055 | #endif |
||
1056 | chan->rate = S3IRandomBetweenLog(desc->min_pitch, desc->max_pitch, ((tS3_sample*)desc->sound_data)->rate); |
||
1057 | } |
||
1058 | } |
||
1059 | |||
1060 | // duplicate of S3IRandomBetween2 |
||
1061 | int S3IRandomBetween(int pMin, int pMax, int pDefault) { |
||
1062 | if (pMin == -1) { |
||
1063 | return pDefault; |
||
1064 | } |
||
1065 | if (pMax <= pMin) { |
||
1066 | return pMin; |
||
1067 | } |
||
1068 | return rand() % (pMax - pMin) + pMin; |
||
1069 | } |
||
1070 | |||
1071 | // duplicate of S3IRandomBetweenLog2 |
||
1072 | int S3IRandomBetweenLog(int pMin, int pMax, int pDefault) { |
||
1073 | float v4; // st7 |
||
1074 | |||
1075 | if (pMin == -1 || pMin >= pMax) { |
||
1076 | return pDefault; |
||
1077 | } |
||
1078 | v4 = S3FRandomBetween(log(pMin), log(pMax)); |
||
1079 | return ldexp(exp(v4), -16) * pDefault; |
||
1080 | } |
||
1081 | |||
1082 | // duplicate of S3FRandomBetween2 |
||
1083 | double S3FRandomBetween(double pMin, double pMax) { |
||
1084 | return (double)rand() * (pMax - pMin) / (double)RAND_MAX + pMin; |
||
1085 | } |
||
1086 | |||
1087 | int S3GenerateTag(tS3_outlet* outlet) { |
||
1088 | gS3_tag_seed += 256; |
||
1089 | return gS3_tag_seed | outlet->id; |
||
1090 | } |
||
1091 | |||
1092 | int S3SoundStillPlaying(tS3_sound_tag pTag) { |
||
1093 | tS3_channel* chan; |
||
1094 | |||
1095 | if (!gS3_enabled) { |
||
1096 | return 0; |
||
1097 | } |
||
1098 | if (!pTag) { |
||
1099 | return 0; |
||
1100 | } |
||
1101 | chan = S3GetChannelForTag(pTag); |
||
1102 | if (!chan) { |
||
1103 | return 0; |
||
1104 | } |
||
1105 | return S3ServiceChannel(chan) != 0; |
||
1106 | } |
||
1107 | |||
1108 | int S3ChangePitchSpeed(tS3_sound_tag pTag, tS3_pitch pNew_pitch) { |
||
1109 | tS3_channel* chan; |
||
1110 | |||
1111 | if (!gS3_enabled) { |
||
1112 | return 0; |
||
1113 | } |
||
1114 | if (pNew_pitch == -1) { |
||
1115 | pNew_pitch = 0x10000; |
||
1116 | } |
||
1117 | chan = S3GetChannelForTag(pTag); |
||
1118 | if (chan == NULL) { |
||
1119 | return eS3_error_bad_stag; |
||
1120 | } |
||
1121 | if (chan->type != eS3_ST_sample) { |
||
1122 | return 0; |
||
1123 | } |
||
1124 | chan->rate = ldexp(pNew_pitch, -16) * ((tS3_sample*)chan->descriptor->sound_data)->rate; |
||
1125 | if (S3SyncSampleRate(chan)) { |
||
1126 | return 0; |
||
1127 | } else { |
||
1128 | return eS3_error_function_failed; |
||
1129 | } |
||
1130 | } |
||
1131 | |||
1132 | int S3StopSound(tS3_sound_tag pTag) { |
||
1133 | tS3_channel* chan; // [esp+Ch] [ebp-4h] |
||
1134 | |||
1135 | if (!gS3_enabled) { |
||
1136 | return 0; |
||
1137 | } |
||
1138 | if (!pTag) { |
||
1139 | return eS3_error_bad_stag; |
||
1140 | } |
||
1141 | chan = S3GetChannelForTag(pTag); |
||
1142 | if (!chan) { |
||
1143 | return eS3_error_bad_stag; |
||
1144 | } |
||
1145 | chan->termination_reason = eS3_tr_stopped; |
||
1146 | chan->initial_volume = 0; |
||
1147 | if (chan->active) { |
||
1148 | chan->needs_service = 1; |
||
1149 | } |
||
1150 | if (chan->type == eS3_ST_sample) { |
||
1151 | if (chan->sound_source_ptr) { |
||
1152 | chan->sound_source_ptr->tag = 0; |
||
1153 | chan->sound_source_ptr->channel = NULL; |
||
1154 | chan->sound_source_ptr->volume = 0; |
||
1155 | } |
||
1156 | if (!S3StopSample(chan)) { |
||
1157 | return eS3_error_function_failed; |
||
1158 | } |
||
1159 | } else if (chan->type == eS3_ST_midi) { |
||
1160 | if (S3StopMIDI(chan)) { |
||
1161 | return eS3_error_function_failed; |
||
1162 | } |
||
1163 | } else if (chan->type == eS3_ST_cda) { |
||
1164 | if (S3StopCDA(chan)) { |
||
1165 | return eS3_error_function_failed; |
||
1166 | } |
||
1167 | } |
||
1168 | |||
1169 | if ((chan->descriptor->flags & 2) != 0) { |
||
1170 | S3ReleaseSound(chan->descriptor->id); |
||
1171 | } |
||
1172 | chan->repetitions = 1; |
||
1173 | return 0; |
||
1174 | } |
||
1175 | |||
1176 | int S3StopOutletSound(tS3_outlet* pOutlet) { |
||
1177 | tS3_channel* c; // [esp+Ch] [ebp-4h] |
||
1178 | |||
1179 | if (!gS3_enabled) { |
||
1180 | return 0; |
||
1181 | } |
||
1182 | for (c = pOutlet->channel_list; c; c = c->next) { |
||
1183 | // null_unknown_libname_8(); |
||
1184 | if (c->active) { |
||
1185 | c->spatial_sound = 0; |
||
1186 | S3StopChannel(c); |
||
1187 | c->needs_service = 1; |
||
1188 | } |
||
1189 | } |
||
1190 | return 0; |
||
1191 | } |
||
1192 | |||
1193 | char* S3GetCurrentDir(void) { |
||
1194 | if (!gS3_have_current_dir) { |
||
1195 | if (getcwd(gS3_current_dir, 260) == NULL) { |
||
1196 | LOG_PANIC("failed to call getcwd"); // added by dethrace |
||
1197 | }; |
||
1198 | gS3_have_current_dir = 1; |
||
1199 | } |
||
1200 | return gS3_current_dir; |
||
1201 | } |
||
1202 | |||
1203 | tS3_descriptor* S3GetDescriptorByID(tS3_sound_tag id) { |
||
1204 | tS3_descriptor* d; // [esp+Ch] [ebp-4h] |
||
1205 | |||
1206 | for (d = gS3_descriptors;; d = d->next) { |
||
1207 | if (!d) { |
||
1208 | return 0; |
||
1209 | } |
||
1210 | if (d->id == id) { |
||
1211 | break; |
||
1212 | } |
||
1213 | } |
||
1214 | if (d->memory_proxy < 0) { |
||
1215 | return d; |
||
1216 | } else { |
||
1217 | return S3GetDescriptorByID(d->memory_proxy); |
||
1218 | } |
||
1219 | } |
||
1220 | |||
1221 | int S3SetOutletVolume(tS3_outlet* pOutlet, tS3_volume pVolume) { |
||
1222 | tS3_channel* c; // [esp+10h] [ebp-4h] |
||
1223 | |||
1224 | if (!gS3_enabled) { |
||
1225 | return 0; |
||
1226 | } |
||
1227 | if (pVolume > 255) { |
||
1228 | pVolume = 255; |
||
1229 | } |
||
1230 | if (pVolume < 10) { |
||
1231 | pVolume = 10; |
||
1232 | } |
||
1233 | if (!pOutlet) { |
||
1234 | return 0; |
||
1235 | } |
||
1236 | for (c = pOutlet->channel_list; c; c = c->next) { |
||
1237 | c->volume_multiplier = pVolume / 150.0f; |
||
1238 | if (c->active) { |
||
1239 | S3ChangeVolume(c->tag, pVolume); |
||
1240 | } |
||
1241 | } |
||
1242 | return 0; |
||
1243 | } |
||
1244 | |||
1245 | tS3_channel* S3GetChannelForTag(tS3_sound_tag tag) { |
||
1246 | tS3_channel* c; // [esp+Ch] [ebp-Ch] |
||
1247 | tS3_outlet* o; // [esp+14h] [ebp-4h] |
||
1248 | |||
1249 | if (!tag) { |
||
1250 | return 0; |
||
1251 | } |
||
1252 | for (o = gS3_outlets; o && o->id != (uint8_t)tag; o = o->next) { |
||
1253 | ; |
||
1254 | } |
||
1255 | if (!o) { |
||
1256 | return 0; |
||
1257 | } |
||
1258 | for (c = o->channel_list; c; c = c->next) { |
||
1259 | if (c->tag == tag) { |
||
1260 | return c; |
||
1261 | } |
||
1262 | } |
||
1263 | return 0; |
||
1264 | } |
||
1265 | |||
1266 | int S3ChangeVolume(tS3_sound_tag pTag, tS3_volume pVolume) { |
||
1267 | tS3_channel* chan; // [esp+14h] [ebp-4h] |
||
1268 | |||
1269 | if (!gS3_enabled) { |
||
1270 | return 0; |
||
1271 | } |
||
1272 | chan = S3GetChannelForTag(pTag); |
||
1273 | if (!chan) { |
||
1274 | return eS3_error_bad_stag; |
||
1275 | } |
||
1276 | if (pVolume < 0) { |
||
1277 | pVolume = 128; |
||
1278 | } |
||
1279 | if (pVolume > 255) { |
||
1280 | pVolume = 255; |
||
1281 | } |
||
1282 | if (chan->type == eS3_ST_sample) { |
||
1283 | chan->left_volume = pVolume * chan->volume_multiplier; |
||
1284 | chan->right_volume = pVolume * chan->volume_multiplier; |
||
1285 | if (!S3SyncSampleVolumeAndPan(chan)) { |
||
1286 | return eS3_error_function_failed; |
||
1287 | } |
||
1288 | } else if (chan->type == eS3_ST_midi) { |
||
1289 | S3SetMIDIVolume(chan); |
||
1290 | } else if (chan->type == eS3_ST_cda) { |
||
1291 | S3SetCDAVolume(chan, pVolume); |
||
1292 | } |
||
1293 | |||
1294 | return 0; |
||
1295 | } |