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