Rev 11 | Go to most recent revision | Details | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
1 | pmbaty | 1 | #include "s3sound.h" |
2 | #include "audio.h" |
||
3 | #include "backends/backend.h" |
||
4 | #include "harness/trace.h" |
||
5 | #include "resource.h" |
||
6 | #include <stdio.h> |
||
7 | #include <stdlib.h> |
||
8 | #include <string.h> |
||
9 | |||
10 | #define MAX_PATH_LENGTH 1024 |
||
11 | extern void dr_dprintf(char* fmt_string, ...); |
||
12 | |||
13 | int gS3_sample_filter_funcs_registered; |
||
14 | long gS3_last_file_length; |
||
15 | tS3_sample_filter* gS3_sample_filter_func; |
||
16 | tS3_sample_filter* gS3_sample_filter_disable_func; |
||
17 | |||
18 | int S3LoadSample(tS3_sound_id id) { |
||
19 | // changed by dethrace for compatibility |
||
20 | // char filename[80]; // [esp+10h] [ebp-5Ch] BYREF |
||
21 | char filename[MAX_PATH_LENGTH]; |
||
22 | tS3_descriptor* descriptor; |
||
23 | tS3_sample* sample; |
||
24 | char* buf; |
||
25 | // LPDIRECTSOUNDBUFFER dsound_buffer; // win95 only |
||
26 | |||
27 | if (!gS3_enabled) { |
||
28 | return 0; |
||
29 | } |
||
30 | descriptor = S3GetDescriptorByID(id); |
||
31 | if (!descriptor) { |
||
32 | return eS3_error_bad_id; |
||
33 | } |
||
34 | if (descriptor->type != eS3_ST_sample) { |
||
35 | return 0; |
||
36 | } |
||
37 | if (descriptor->sound_data) { |
||
38 | return 0; |
||
39 | } |
||
40 | filename[0] = 0; |
||
41 | strcpy(filename, descriptor->filename); |
||
42 | sample = S3MemAllocate(sizeof(tS3_sample), kMem_S3_sound_header); |
||
43 | if (!sample) { |
||
44 | return eS3_error_memory; |
||
45 | } |
||
46 | |||
47 | memset(sample, 0, sizeof(tS3_sample)); |
||
48 | buf = S3LoadWavFile_DOS(filename); |
||
49 | if (buf == NULL) { |
||
50 | S3MemFree(sample); |
||
51 | return gS3_last_error; |
||
52 | } |
||
53 | sample->freeptr = buf; |
||
54 | if (memcmp(buf, "RIFF", 4) == 0) { |
||
55 | wav_header* hdr = (wav_header*)buf; |
||
56 | sample->dataptr = &buf[sizeof(wav_header)]; |
||
57 | sample->size = hdr->data_bytes; |
||
58 | sample->rate = hdr->sample_rate; |
||
59 | sample->resolution = hdr->bit_depth; |
||
60 | sample->channels = hdr->num_channels; |
||
61 | } else { |
||
62 | sample->rate = 16000; |
||
63 | sample->resolution = 8; |
||
64 | sample->channels = 1; |
||
65 | sample->dataptr = buf; |
||
66 | sample->size = gS3_last_file_length; |
||
67 | } |
||
68 | |||
69 | // win95 |
||
70 | // descriptor->sound_buffer = S3LoadWavFile(filename, sample); |
||
71 | // if (!descriptor->sound_buffer) { |
||
72 | // S3MemFree(sample); |
||
73 | // return gS3_last_error; |
||
74 | // } |
||
75 | descriptor->special_fx = 0; |
||
76 | descriptor->sound_data = (char*)sample; |
||
77 | return eS3_error_none; |
||
78 | } |
||
79 | |||
80 | int S3ReadWavHeader_Win95(char* buf, tWAVEFORMATEX_** pWav_format, char** data_ptr, int* pData_size) { |
||
81 | int riff_len; |
||
82 | char* file_eof; // [esp+10h] [ebp-14h] |
||
83 | unsigned int chunk_len; // [esp+18h] [ebp-Ch] |
||
84 | char* chunk_data; // [esp+1Ch] [ebp-8h] |
||
85 | // char* chunk_name; // [esp+20h] [ebp-4h] |
||
86 | char* chunk_ptr; |
||
87 | |||
88 | if (pWav_format) { |
||
89 | *pWav_format = 0; |
||
90 | } |
||
91 | if (data_ptr) { |
||
92 | *data_ptr = 0; |
||
93 | } |
||
94 | if (pData_size) { |
||
95 | *pData_size = 0; |
||
96 | } |
||
97 | chunk_ptr = buf + 12; |
||
98 | if (buf[0] != 'R' || buf[1] != 'I' || buf[2] != 'F' || buf[3] != 'F') { |
||
99 | return 0; |
||
100 | } |
||
101 | if (buf[8] != 'W' || buf[9] != 'A' || buf[10] != 'V' || buf[11] != 'E') { |
||
102 | return 0; |
||
103 | } |
||
104 | memcpy(&riff_len, &buf[4], sizeof(riff_len)); // (int32_t)buf[4]; |
||
105 | #if BR_ENDIAN_BIG |
||
106 | riff_len = BrSwap32(riff_len); |
||
107 | #endif |
||
108 | file_eof = &chunk_ptr[riff_len - 4]; |
||
109 | while (file_eof > chunk_ptr) { |
||
110 | memcpy(&chunk_len, chunk_ptr + 4, sizeof(chunk_len)); |
||
111 | #if BR_ENDIAN_BIG |
||
112 | chunk_len = BrSwap32(chunk_len); |
||
113 | #endif |
||
114 | chunk_data = chunk_ptr + 8; |
||
115 | if (strncmp(chunk_ptr, "fmt ", 4) == 0) { |
||
116 | if (pWav_format && *pWav_format == NULL) { |
||
117 | if (chunk_len < 14) { |
||
118 | return 0; |
||
119 | } |
||
120 | *pWav_format = (tWAVEFORMATEX_*)chunk_data; |
||
121 | if ((!data_ptr || *data_ptr) && (!pData_size || *pData_size)) { |
||
122 | return 1; |
||
123 | } |
||
124 | } |
||
125 | } else if (strncmp(chunk_ptr, "data", 4) == 0 && ((data_ptr && !*data_ptr) || (pData_size && !*pData_size))) { |
||
126 | if (data_ptr) { |
||
127 | *data_ptr = chunk_data; |
||
128 | } |
||
129 | if (pData_size) { |
||
130 | *pData_size = chunk_len; |
||
131 | } |
||
132 | if (!pWav_format || *pWav_format) { |
||
133 | return 1; |
||
134 | } |
||
135 | } |
||
136 | chunk_ptr = &chunk_data[(chunk_len + 1) & 0xFFFFFFFE]; |
||
137 | } |
||
138 | return 0; |
||
139 | } |
||
140 | |||
141 | void* S3LoadWavFile_DOS(char* pFile_name) { |
||
142 | FILE* f; |
||
143 | long file_len; |
||
144 | size_t bytes_read; |
||
145 | char* buf; |
||
146 | |||
147 | f = fopen(pFile_name, "rb"); |
||
148 | if (f == NULL) { |
||
149 | gS3_last_error = eS3_error_readfile; |
||
150 | return 0; |
||
151 | } |
||
152 | fseek(f, 0, SEEK_END); |
||
153 | file_len = ftell(f); |
||
154 | fseek(f, 0, SEEK_SET); |
||
155 | |||
156 | buf = S3MemAllocate(file_len + 1, kMem_S3_sample); |
||
157 | |||
158 | if (buf) { |
||
159 | bytes_read = fread(buf, 1, file_len, f); |
||
160 | if (bytes_read == file_len) { |
||
161 | gS3_last_file_length = file_len; |
||
162 | fclose(f); |
||
163 | return buf; |
||
164 | } else { |
||
165 | gS3_last_error = 4; |
||
166 | } |
||
167 | } else { |
||
168 | fclose(f); |
||
169 | gS3_last_error = eS3_error_memory; |
||
170 | } |
||
171 | return 0; |
||
172 | } |
||
173 | |||
174 | void* S3LoadWavFile_Win95(char* pFile_name, tS3_sample* pSample) { |
||
175 | FILE* f; // [esp+Ch] [ebp-C8h] |
||
176 | size_t bytes_read; // [esp+14h] [ebp-C0h] BYREF |
||
177 | // unsigned int locked_buffer_data_len; // [esp+18h] [ebp-BCh] BYREF |
||
178 | // struct _OFSTRUCT ReOpenBuff; // [esp+1Ch] [ebp-B8h] BYREF |
||
179 | char* buf; // [esp+A4h] [ebp-30h] |
||
180 | // LPDIRECTSOUNDBUFFER ds_buffer; // [esp+A8h] [ebp-2Ch] BYREF |
||
181 | // DSBUFFERDESC buffer_desc; // [esp+ACh] [ebp-28h] BYREF |
||
182 | int data_size; // [esp+C0h] [ebp-14h] BYREF |
||
183 | tWAVEFORMATEX_* wav_format; // [esp+C4h] [ebp-10h] BYREF |
||
184 | char* data_ptr; // [esp+C8h] [ebp-Ch] BYREF |
||
185 | // char* locked_buffer_data; // [esp+CCh] [ebp-8h] BYREF |
||
186 | size_t file_len; // [esp+D0h] [ebp-4h] |
||
187 | |||
188 | f = fopen(pFile_name, "rb"); |
||
189 | if (f == NULL) { |
||
190 | gS3_last_error = eS3_error_readfile; |
||
191 | return 0; |
||
192 | } |
||
193 | fseek(f, 0, SEEK_END); |
||
194 | file_len = (size_t)ftell(f); |
||
195 | fseek(f, 0, SEEK_SET); |
||
196 | |||
197 | buf = S3MemAllocate(file_len, kMem_S3_Windows_95_load_WAV_file); |
||
198 | if (buf == NULL) { |
||
199 | fclose(f); |
||
200 | gS3_last_error = eS3_error_memory; |
||
201 | return 0; |
||
202 | } |
||
203 | bytes_read = fread(buf, file_len, 1, f); |
||
204 | fclose(f); |
||
205 | |||
206 | data_size = 0; |
||
207 | wav_format = 0; |
||
208 | data_ptr = 0; |
||
209 | if (S3ReadWavHeader_Win95(buf, &wav_format, &data_ptr, &data_size) == 0) { |
||
210 | gS3_last_error = eS3_error_readfile; |
||
211 | dr_dprintf("ERROR: .WAV file '%s' is crap", pFile_name); |
||
212 | return 0; |
||
213 | } |
||
214 | pSample->freeptr = 0; |
||
215 | pSample->dataptr = 0; |
||
216 | pSample->size = data_size; |
||
217 | pSample->rate = wav_format->nSamplesPerSec; |
||
218 | pSample->resolution = wav_format->nAvgBytesPerSec; |
||
219 | pSample->channels = wav_format->nChannels; |
||
220 | #if BR_ENDIAN_BIG |
||
221 | pSample->rate = BrSwap32(pSample->rate); |
||
222 | pSample->resolution = BrSwap32(pSample->resolution); |
||
223 | pSample->channels = BrSwap32(pSample->channels); |
||
224 | #endif |
||
225 | |||
226 | // buffer_desc.dwReserved = 0; |
||
227 | // buffer_desc.dwSize = 20; |
||
228 | // buffer_desc.dwFlags = 226; |
||
229 | // buffer_desc.dwBufferBytes = data_size; |
||
230 | // buffer_desc.lpwfxFormat = wav_format; |
||
231 | // if (gS3_direct_sound_ptr->lpVtbl->CreateSoundBuffer(gS3_direct_sound_ptr, &buffer_desc, &ds_buffer, 0)) { |
||
232 | // return 0; |
||
233 | // } else if (ds_buffer->lpVtbl->Lock( |
||
234 | // ds_buffer, |
||
235 | // 0, |
||
236 | // data_size, |
||
237 | // (LPVOID*)&locked_buffer_data, |
||
238 | // &locked_buffer_data_len, |
||
239 | // 0, |
||
240 | // 0, |
||
241 | // 0)) { |
||
242 | // return 0; |
||
243 | // } else { |
||
244 | // qmemcpy(locked_buffer_data, data_ptr, locked_buffer_data_len); |
||
245 | // S3MemFree(buf); |
||
246 | // ds_buffer->lpVtbl->Unlock(ds_buffer, locked_buffer_data, locked_buffer_data_len, 0, 0); |
||
247 | // return ds_buffer; |
||
248 | // } |
||
249 | return NULL; |
||
250 | } |
||
251 | |||
252 | int S3StopSample(tS3_channel* chan) { |
||
253 | if (chan->tag == 0) { |
||
254 | return 1; |
||
255 | } |
||
256 | |||
257 | if (chan->type_struct_sample == NULL) { |
||
258 | return 0; |
||
259 | } |
||
260 | |||
261 | AudioBackend_StopSample(chan); |
||
262 | |||
263 | if (chan->active) { |
||
264 | chan->needs_service = 1; |
||
265 | } |
||
266 | |||
267 | return 1; |
||
268 | } |
||
269 | |||
270 | int S3ExecuteSampleFilterFuncs(tS3_channel* chan) { |
||
271 | if (((chan->descriptor->special_fx == 0) & gS3_sample_filter_funcs_registered) != 0) { |
||
272 | gS3_sample_filter_func(1, chan->tag); |
||
273 | chan->descriptor->special_fx = 1; |
||
274 | } else if (((gS3_sample_filter_funcs_registered == 0) & chan->descriptor->special_fx) != 0) { |
||
275 | gS3_sample_filter_disable_func(1, chan->tag); |
||
276 | chan->descriptor->special_fx = 0; |
||
277 | } |
||
278 | return 0; |
||
279 | } |
||
280 | |||
281 | int S3PlaySample(tS3_channel* chan) { |
||
282 | |||
283 | if (chan->type_struct_sample == NULL) { |
||
284 | return 0; |
||
285 | } |
||
286 | |||
287 | S3SyncSampleVolumeAndPan(chan); |
||
288 | S3SyncSampleRate(chan); |
||
289 | |||
290 | if (AudioBackend_PlaySample(chan) != eAB_success) { |
||
291 | return 0; |
||
292 | } |
||
293 | // if (chan->descriptor && chan->descriptor->type == chan->type) { |
||
294 | // dsound_buffer = chan->descriptor->dsound_buffer; |
||
295 | // if (dsound_buffer) { |
||
296 | // dsound_buffer->lpVtbl->SetCurrentPosition(dsound_buffer, 0); |
||
297 | // play_flags = chan->repetitions == 0; // 1 = DSBPLAY_LOOPING |
||
298 | // dsound_buffer->lpVtbl->Play(dsound_buffer, 0, 0, play_flags); |
||
299 | // if (!dsound_buffer->lpVtbl->GetStatus(dsound_buffer, (LPDWORD)&status)) { |
||
300 | // if ((status & 1) != 0) // DSBSTATUS_PLAYING |
||
301 | // { |
||
302 | // dsound_buffer->lpVtbl->SetCurrentPosition(dsound_buffer, 0); |
||
303 | // } else { |
||
304 | // dsound_buffer->lpVtbl->Play(dsound_buffer, 0, 0, play_flags); |
||
305 | // } |
||
306 | // } |
||
307 | // } |
||
308 | // } |
||
309 | |||
310 | return 1; |
||
311 | } |
||
312 | |||
313 | // this function was only called in DOS build |
||
314 | int S3CreateTypeStructs(tS3_channel* chan) { |
||
315 | void* result; |
||
316 | |||
317 | result = AudioBackend_AllocateSampleTypeStruct(); |
||
318 | if (result == NULL) { |
||
319 | return 0; |
||
320 | } |
||
321 | chan->type_struct_midi = NULL; |
||
322 | chan->type_struct_cda = NULL; |
||
323 | chan->type_struct_sample = (char*)result; |
||
324 | return 1; |
||
325 | } |
||
326 | |||
327 | int S3ReleaseTypeStructs(tS3_channel* chan) { |
||
328 | if (chan->type_struct_sample) { |
||
329 | S3MemFree(chan->type_struct_sample); |
||
330 | chan->type_struct_sample = NULL; |
||
331 | } |
||
332 | if (chan->type_struct_cda) { |
||
333 | S3MemFree(chan->type_struct_cda); |
||
334 | chan->type_struct_cda = NULL; |
||
335 | } |
||
336 | return 1; |
||
337 | } |
||
338 | |||
339 | int S3SyncSampleVolumeAndPan(tS3_channel* chan) { |
||
340 | |||
341 | float pan_ratio; // [esp+38h] [ebp-8h] |
||
342 | float total_vol; // [esp+3Ch] [ebp-4h] |
||
343 | |||
344 | int volume_db; |
||
345 | int pan; |
||
346 | //float linear_volume; // Pierre-Marie Baty -- unused variable |
||
347 | |||
348 | if (chan->type != eS3_ST_sample) { |
||
349 | return 1; |
||
350 | } |
||
351 | total_vol = (float) (chan->left_volume + chan->right_volume); // Pierre-Marie Baty -- added type cast |
||
352 | if (total_vol == 0.0f) { |
||
353 | total_vol = 1.0f; |
||
354 | } |
||
355 | if (chan->descriptor && chan->descriptor->type == chan->type) { |
||
356 | volume_db = (int) (510.0f / total_vol * -5.0f - 350.0f); // Pierre-Marie Baty -- added type cast |
||
357 | if (volume_db >= 0) { |
||
358 | volume_db = 0; |
||
359 | } |
||
360 | |||
361 | if (AudioBackend_SetVolume(chan, volume_db) == eAB_success && chan->spatial_sound) { |
||
362 | |||
363 | if (chan->left_volume != 0 && chan->right_volume > chan->left_volume) { |
||
364 | pan_ratio = chan->right_volume / (float)chan->left_volume; |
||
365 | } else if (chan->right_volume != 0) { |
||
366 | pan_ratio = chan->left_volume / (float)chan->right_volume; |
||
367 | } |
||
368 | if (chan->left_volume != 0 && chan->right_volume != 0) { |
||
369 | pan = (int) ((chan->right_volume - chan->left_volume) * pan_ratio); // Pierre-Marie Baty -- added type cast |
||
370 | pan = MAX(pan, -10000); |
||
371 | pan = MIN(pan, 10000); |
||
372 | } else if (chan->left_volume != 0) { |
||
373 | pan = -10000; |
||
374 | } else { |
||
375 | pan = 10000; |
||
376 | } |
||
377 | AudioBackend_SetPan(chan, pan); |
||
378 | } |
||
379 | } |
||
380 | return 1; |
||
381 | } |
||
382 | |||
383 | int S3SyncSampleRate(tS3_channel* chan) { |
||
384 | if (chan->type != eS3_ST_sample) { |
||
385 | return 1; |
||
386 | } |
||
387 | |||
388 | int rate = chan->rate; |
||
389 | if (rate >= 100000) { |
||
390 | rate = 100000; |
||
391 | } |
||
392 | |||
393 | // sound_buffer->lpVtbl->SetFrequency(sound_buffer, rate); |
||
394 | AudioBackend_SetFrequency(chan, rate); |
||
395 | |||
396 | return 1; |
||
397 | } |
||
398 | |||
399 | int S3SetEffects(tS3_sample_filter* filter1, tS3_sample_filter* filter2) { |
||
400 | STUB_ONCE(); |
||
401 | return 0; |
||
402 | } |