Subversion Repositories Games.Carmageddon

Rev

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
}