Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
rubberduckycooly
GitHub Repository: rubberduckycooly/Sonic-1-2-2013-Decompilation
Path: blob/main/RSDKv4/Audio.cpp
817 views
1
#include "RetroEngine.hpp"
2
#include <cmath>
3
4
int globalSFXCount = 0;
5
int stageSFXCount = 0;
6
7
int masterVolume = MAX_VOLUME;
8
int trackID = -1;
9
int sfxVolume = MAX_VOLUME;
10
int bgmVolume = MAX_VOLUME;
11
bool audioEnabled = false;
12
13
bool musicEnabled = 0;
14
int musicStatus = MUSIC_STOPPED;
15
int musicStartPos = 0;
16
int musicPosition = 0;
17
int musicRatio = 0;
18
TrackInfo musicTracks[TRACK_COUNT];
19
SFXInfo sfxList[SFX_COUNT];
20
char sfxNames[SFX_COUNT][0x40];
21
22
int currentStreamIndex = 0;
23
StreamFile streamFile[STREAMFILE_COUNT];
24
StreamInfo streamInfo[STREAMFILE_COUNT];
25
StreamFile *streamFilePtr = NULL;
26
StreamInfo *streamInfoPtr = NULL;
27
28
ChannelInfo sfxChannels[CHANNEL_COUNT];
29
30
int currentMusicTrack = -1;
31
32
#if RETRO_USING_SDL1 || RETRO_USING_SDL2
33
34
#if RETRO_USING_SDL2
35
SDL_AudioDeviceID audioDevice;
36
#endif
37
SDL_AudioSpec audioDeviceFormat;
38
39
#define AUDIO_FREQUENCY (44100)
40
#define AUDIO_FORMAT (AUDIO_S16SYS) /**< Signed 16-bit samples */
41
#define AUDIO_SAMPLES (0x800)
42
#define AUDIO_CHANNELS (2)
43
44
#define ADJUST_VOLUME(s, v) (s = (s * v) / MAX_VOLUME)
45
#endif
46
47
int InitAudioPlayback()
48
{
49
StopAllSfx(); //"init"
50
51
#if !RETRO_USE_ORIGINAL_CODE
52
#if RETRO_USING_SDL1 || RETRO_USING_SDL2
53
SDL_AudioSpec want;
54
want.freq = AUDIO_FREQUENCY;
55
want.format = AUDIO_FORMAT;
56
want.samples = AUDIO_SAMPLES;
57
want.channels = AUDIO_CHANNELS;
58
want.callback = ProcessAudioPlayback;
59
60
#if RETRO_USING_SDL2
61
if ((audioDevice = SDL_OpenAudioDevice(nullptr, 0, &want, &audioDeviceFormat, SDL_AUDIO_ALLOW_FREQUENCY_CHANGE)) > 0) {
62
audioEnabled = true;
63
SDL_PauseAudioDevice(audioDevice, 0);
64
}
65
else {
66
PrintLog("Unable to open audio device: %s", SDL_GetError());
67
audioEnabled = false;
68
return true; // no audio but game wont crash now
69
}
70
#elif RETRO_USING_SDL1
71
if (SDL_OpenAudio(&want, &audioDeviceFormat) == 0) {
72
audioEnabled = true;
73
SDL_PauseAudio(0);
74
}
75
else {
76
PrintLog("Unable to open audio device: %s", SDL_GetError());
77
audioEnabled = false;
78
return true; // no audio but game wont crash now
79
}
80
#endif // !RETRO_USING_SDL1
81
#endif
82
#endif
83
84
LoadGlobalSfx();
85
86
return true;
87
}
88
89
void LoadGlobalSfx()
90
{
91
FileInfo info;
92
FileInfo infoStore;
93
char strBuffer[0x100];
94
byte fileBuffer = 0;
95
int fileBuffer2 = 0;
96
97
globalSFXCount = 0;
98
99
if (LoadFile("Data/Game/GameConfig.bin", &info)) {
100
infoStore = info;
101
102
FileRead(&fileBuffer, 1);
103
FileRead(strBuffer, fileBuffer);
104
105
FileRead(&fileBuffer, 1);
106
FileRead(strBuffer, fileBuffer);
107
108
byte buf[3];
109
for (int c = 0; c < 0x60; ++c) FileRead(buf, 3);
110
111
// Read Obect Names
112
byte objectCount = 0;
113
FileRead(&objectCount, 1);
114
for (byte o = 0; o < objectCount; ++o) {
115
FileRead(&fileBuffer, 1);
116
FileRead(&strBuffer, fileBuffer);
117
}
118
119
// Read Script Paths
120
for (byte s = 0; s < objectCount; ++s) {
121
FileRead(&fileBuffer, 1);
122
FileRead(&strBuffer, fileBuffer);
123
}
124
125
byte varCount = 0;
126
FileRead(&varCount, 1);
127
for (byte v = 0; v < varCount; ++v) {
128
// Read Variable Name
129
FileRead(&fileBuffer, 1);
130
FileRead(&strBuffer, fileBuffer);
131
132
// Read Variable Value
133
FileRead(&fileBuffer2, 4);
134
}
135
136
// Read SFX
137
FileRead(&fileBuffer, 1);
138
globalSFXCount = fileBuffer;
139
for (byte s = 0; s < globalSFXCount; ++s) { // SFX Names
140
FileRead(&fileBuffer, 1);
141
FileRead(&strBuffer, fileBuffer);
142
strBuffer[fileBuffer] = 0;
143
144
SetSfxName(strBuffer, s);
145
}
146
for (byte s = 0; s < globalSFXCount; ++s) { // SFX Paths
147
FileRead(&fileBuffer, 1);
148
FileRead(&strBuffer, fileBuffer);
149
strBuffer[fileBuffer] = 0;
150
151
GetFileInfo(&infoStore);
152
CloseFile();
153
LoadSfx(strBuffer, s);
154
SetFileInfo(&infoStore);
155
}
156
157
CloseFile();
158
159
#if RETRO_USE_MOD_LOADER
160
Engine.LoadXMLSoundFX();
161
#endif
162
}
163
164
for (int i = 0; i < CHANNEL_COUNT; ++i) sfxChannels[i].sfxID = -1;
165
}
166
167
size_t readVorbis(void *mem, size_t size, size_t nmemb, void *ptr)
168
{
169
StreamFile *file = (StreamFile *)ptr;
170
171
int n = size * nmemb;
172
if (size * nmemb > file->fileSize - file->filePos)
173
n = file->fileSize - file->filePos;
174
175
if (n) {
176
memcpy(mem, &file->buffer[file->filePos], n);
177
file->filePos += n;
178
}
179
return n;
180
}
181
int seekVorbis(void *ptr, ogg_int64_t offset, int whence)
182
{
183
StreamFile *file = (StreamFile *)ptr;
184
185
switch (whence) {
186
case SEEK_SET: whence = 0; break;
187
case SEEK_CUR: whence = file->filePos; break;
188
case SEEK_END: whence = file->fileSize; break;
189
default: break;
190
}
191
file->filePos = whence + offset;
192
return 0;
193
}
194
long tellVorbis(void *ptr)
195
{
196
StreamFile *file = (StreamFile *)ptr;
197
return file->filePos;
198
}
199
int closeVorbis(void *ptr) { return 1; }
200
201
#if !RETRO_USE_ORIGINAL_CODE
202
void ProcessMusicStream(Sint32 *stream, size_t bytes_wanted)
203
{
204
if (!streamFilePtr || !streamInfoPtr)
205
return;
206
if (!streamFilePtr->fileSize)
207
return;
208
switch (musicStatus) {
209
case MUSIC_READY:
210
case MUSIC_PLAYING: {
211
#if RETRO_USING_SDL2
212
while (musicStatus == MUSIC_PLAYING && streamInfoPtr->stream && SDL_AudioStreamAvailable(streamInfoPtr->stream) < bytes_wanted) {
213
// We need more samples: get some
214
long bytes_read = ov_read(&streamInfoPtr->vorbisFile, (char *)streamInfoPtr->buffer, sizeof(streamInfoPtr->buffer), 0, 2, 1,
215
&streamInfoPtr->vorbBitstream);
216
217
if (bytes_read == 0) {
218
// We've reached the end of the file
219
if (streamInfoPtr->trackLoop) {
220
ov_pcm_seek(&streamInfoPtr->vorbisFile, streamInfoPtr->loopPoint);
221
continue;
222
}
223
else {
224
musicStatus = MUSIC_STOPPED;
225
break;
226
}
227
}
228
229
if (musicStatus != MUSIC_PLAYING
230
|| (streamInfoPtr->stream && SDL_AudioStreamPut(streamInfoPtr->stream, streamInfoPtr->buffer, (int)bytes_read) == -1))
231
return;
232
}
233
234
// Now that we know there are enough samples, read them and mix them
235
int bytes_done = SDL_AudioStreamGet(streamInfoPtr->stream, streamInfoPtr->buffer, (int)bytes_wanted);
236
if (bytes_done == -1) {
237
return;
238
}
239
if (bytes_done != 0)
240
ProcessAudioMixing(stream, streamInfoPtr->buffer, bytes_done / sizeof(Sint16), (bgmVolume * masterVolume) / MAX_VOLUME, 0);
241
#endif
242
243
#if RETRO_USING_SDL1
244
size_t bytes_gotten = 0;
245
byte *buffer = (byte *)malloc(bytes_wanted);
246
memset(buffer, 0, bytes_wanted);
247
while (bytes_gotten < bytes_wanted) {
248
// We need more samples: get some
249
long bytes_read =
250
ov_read(&oggFilePtr->vorbisFile, (char *)oggFilePtr->buffer,
251
sizeof(oggFilePtr->buffer) > (bytes_wanted - bytes_gotten) ? (bytes_wanted - bytes_gotten) : sizeof(oggFilePtr->buffer),
252
0, 2, 1, &oggFilePtr->vorbBitstream);
253
254
if (bytes_read == 0) {
255
// We've reached the end of the file
256
if (oggFilePtr->trackLoop) {
257
ov_pcm_seek(&oggFilePtr->vorbisFile, oggFilePtr->loopPoint);
258
continue;
259
}
260
else {
261
musicStatus = MUSIC_STOPPED;
262
break;
263
}
264
}
265
266
if (bytes_read > 0) {
267
memcpy(buffer + bytes_gotten, oggFilePtr->buffer, bytes_read);
268
bytes_gotten += bytes_read;
269
}
270
else {
271
PrintLog("Music read error: vorbis error: %d", bytes_read);
272
}
273
}
274
275
if (bytes_gotten > 0) {
276
SDL_AudioCVT convert;
277
MEM_ZERO(convert);
278
int cvtResult = SDL_BuildAudioCVT(&convert, oggFilePtr->spec.format, oggFilePtr->spec.channels, oggFilePtr->spec.freq,
279
audioDeviceFormat.format, audioDeviceFormat.channels, audioDeviceFormat.freq);
280
if (cvtResult == 0) {
281
if (convert.len_mult > 0) {
282
convert.buf = (byte *)malloc(bytes_gotten * convert.len_mult);
283
convert.len = bytes_gotten;
284
memcpy(convert.buf, buffer, bytes_gotten);
285
SDL_ConvertAudio(&convert);
286
}
287
}
288
289
// Now that we know there are enough samples, read them and mix them
290
// int bytes_done = SDL_AudioStreamGet(oggFilePtr->stream, oggFilePtr->buffer, bytes_wanted);
291
// if (bytes_done == -1) {
292
// return;
293
//}
294
295
if (cvtResult == 0)
296
ProcessAudioMixing(stream, (const Sint16 *)convert.buf, bytes_gotten / sizeof(Sint16), (bgmVolume * masterVolume) / MAX_VOLUME,
297
0);
298
299
if (convert.len > 0 && convert.buf)
300
free(convert.buf);
301
}
302
if (bytes_wanted > 0)
303
free(buffer);
304
#endif
305
306
musicPosition = ov_pcm_tell(&streamInfoPtr->vorbisFile);
307
break;
308
}
309
case MUSIC_STOPPED:
310
case MUSIC_PAUSED:
311
case MUSIC_LOADING:
312
// dont play
313
break;
314
}
315
}
316
317
void ProcessAudioPlayback(void *userdata, Uint8 *stream, int len)
318
{
319
(void)userdata; // Unused
320
321
if (!audioEnabled)
322
return;
323
324
Sint16 *output_buffer = (Sint16 *)stream;
325
326
size_t samples_remaining = (size_t)len / sizeof(Sint16);
327
while (samples_remaining != 0) {
328
Sint32 mix_buffer[MIX_BUFFER_SAMPLES];
329
memset(mix_buffer, 0, sizeof(mix_buffer));
330
331
const size_t samples_to_do = (samples_remaining < MIX_BUFFER_SAMPLES) ? samples_remaining : MIX_BUFFER_SAMPLES;
332
333
// Mix music
334
ProcessMusicStream(mix_buffer, samples_to_do * sizeof(Sint16));
335
336
// Mix SFX
337
for (byte i = 0; i < CHANNEL_COUNT; ++i) {
338
ChannelInfo *sfx = &sfxChannels[i];
339
if (sfx == NULL)
340
continue;
341
342
if (sfx->sfxID < 0)
343
continue;
344
345
if (sfx->samplePtr) {
346
Sint16 buffer[MIX_BUFFER_SAMPLES];
347
348
size_t samples_done = 0;
349
while (samples_done != samples_to_do) {
350
size_t sampleLen = (sfx->sampleLength < samples_to_do - samples_done) ? sfx->sampleLength : samples_to_do - samples_done;
351
memcpy(&buffer[samples_done], sfx->samplePtr, sampleLen * sizeof(Sint16));
352
353
samples_done += sampleLen;
354
sfx->samplePtr += sampleLen;
355
sfx->sampleLength -= sampleLen;
356
357
if (sfx->sampleLength == 0) {
358
if (sfx->loopSFX) {
359
sfx->samplePtr = sfxList[sfx->sfxID].buffer;
360
sfx->sampleLength = sfxList[sfx->sfxID].length;
361
}
362
else {
363
MEM_ZEROP(sfx);
364
sfx->sfxID = -1;
365
break;
366
}
367
}
368
}
369
370
#if RETRO_USING_SDL1 || RETRO_USING_SDL2
371
ProcessAudioMixing(mix_buffer, buffer, (int)samples_done, sfxVolume, sfx->pan);
372
#endif
373
}
374
}
375
376
// Clamp mixed samples back to 16-bit and write them to the output buffer
377
for (size_t i = 0; i < sizeof(mix_buffer) / sizeof(*mix_buffer); ++i) {
378
const Sint16 max_audioval = ((1 << (16 - 1)) - 1);
379
const Sint16 min_audioval = -(1 << (16 - 1));
380
381
const Sint32 sample = mix_buffer[i];
382
383
if (sample > max_audioval)
384
*output_buffer++ = max_audioval;
385
else if (sample < min_audioval)
386
*output_buffer++ = min_audioval;
387
else
388
*output_buffer++ = sample;
389
}
390
391
samples_remaining -= samples_to_do;
392
}
393
}
394
395
#if RETRO_USING_SDL1 || RETRO_USING_SDL2
396
void ProcessAudioMixing(Sint32 *dst, const Sint16 *src, int len, int volume, sbyte pan)
397
{
398
if (volume == 0)
399
return;
400
401
if (volume > MAX_VOLUME)
402
volume = MAX_VOLUME;
403
404
float panL = 0.0;
405
float panR = 0.0;
406
int i = 0;
407
408
if (pan < 0) {
409
panR = 1.0f - abs(pan / 100.0f);
410
panL = 1.0f;
411
}
412
else if (pan > 0) {
413
panL = 1.0f - abs(pan / 100.0f);
414
panR = 1.0f;
415
}
416
417
while (len--) {
418
Sint32 sample = *src++;
419
ADJUST_VOLUME(sample, volume);
420
421
if (pan != 0) {
422
if ((i % 2) != 0) {
423
sample *= panR;
424
}
425
else {
426
sample *= panL;
427
}
428
}
429
430
*dst++ += sample;
431
432
i++;
433
}
434
}
435
#endif
436
#endif
437
438
void LoadMusic(void *userdata)
439
{
440
int oldStreamID = currentStreamIndex;
441
currentStreamIndex++;
442
currentStreamIndex %= STREAMFILE_COUNT;
443
444
LockAudioDevice();
445
446
if (streamFile[currentStreamIndex].fileSize > 0)
447
StopMusic(false);
448
449
FileInfo info;
450
if (LoadFile(musicTracks[currentMusicTrack].fileName, &info)) {
451
StreamInfo *strmInfo = &streamInfo[currentStreamIndex];
452
453
StreamFile *musFile = &streamFile[currentStreamIndex];
454
musFile->filePos = 0;
455
musFile->fileSize = info.vfileSize;
456
if (info.vfileSize > MUSBUFFER_SIZE)
457
musFile->fileSize = MUSBUFFER_SIZE;
458
459
FileRead(streamFile[currentStreamIndex].buffer, musFile->fileSize);
460
CloseFile();
461
462
unsigned long long samples = 0;
463
ov_callbacks callbacks;
464
465
callbacks.read_func = readVorbis;
466
callbacks.seek_func = seekVorbis;
467
callbacks.tell_func = tellVorbis;
468
callbacks.close_func = closeVorbis;
469
470
int error = ov_open_callbacks(musFile, &strmInfo->vorbisFile, NULL, 0, callbacks);
471
if (error == 0) {
472
strmInfo->vorbBitstream = -1;
473
strmInfo->vorbisFile.vi = ov_info(&strmInfo->vorbisFile, -1);
474
475
samples = (unsigned long long)ov_pcm_total(&strmInfo->vorbisFile, -1);
476
477
#if RETRO_USING_SDL2
478
strmInfo->stream = SDL_NewAudioStream(AUDIO_S16, strmInfo->vorbisFile.vi->channels, (int)strmInfo->vorbisFile.vi->rate,
479
audioDeviceFormat.format, audioDeviceFormat.channels, audioDeviceFormat.freq);
480
if (!strmInfo->stream)
481
PrintLog("Failed to create stream: %s", SDL_GetError());
482
#endif
483
484
#if RETRO_USING_SDL1
485
playbackInfo->spec.format = AUDIO_S16;
486
playbackInfo->spec.channels = playbackInfo->vorbisFile.vi->channels;
487
playbackInfo->spec.freq = (int)playbackInfo->vorbisFile.vi->rate;
488
#endif
489
490
if (musicStartPos) {
491
uint oldPos = (uint)ov_pcm_tell(&streamInfo[oldStreamID].vorbisFile);
492
493
float newPos = oldPos * ((float)musicRatio * 0.0001); // 8,000 == 0.8, 10,000 == 1.0 (ratio / 10,000)
494
musicStartPos = fmod(newPos, samples);
495
496
ov_pcm_seek(&strmInfo->vorbisFile, musicStartPos);
497
}
498
musicStartPos = 0;
499
500
musicStatus = MUSIC_PLAYING;
501
masterVolume = MAX_VOLUME;
502
trackID = currentMusicTrack;
503
strmInfo->trackLoop = musicTracks[currentMusicTrack].trackLoop;
504
strmInfo->loopPoint = musicTracks[currentMusicTrack].loopPoint;
505
strmInfo->loaded = true;
506
streamFilePtr = &streamFile[currentStreamIndex];
507
streamInfoPtr = &streamInfo[currentStreamIndex];
508
currentMusicTrack = -1;
509
musicPosition = 0;
510
}
511
else {
512
musicStatus = MUSIC_STOPPED;
513
PrintLog("Failed to load vorbis! error: %d", error);
514
switch (error) {
515
default: PrintLog("Vorbis open error: Unknown (%d)", error); break;
516
case OV_EREAD: PrintLog("Vorbis open error: A read from media returned an error"); break;
517
case OV_ENOTVORBIS: PrintLog("Vorbis open error: Bitstream does not contain any Vorbis data"); break;
518
case OV_EVERSION: PrintLog("Vorbis open error: Vorbis version mismatch"); break;
519
case OV_EBADHEADER: PrintLog("Vorbis open error: Invalid Vorbis bitstream header"); break;
520
case OV_EFAULT: PrintLog("Vorbis open error: Internal logic fault; indicates a bug or heap / stack corruption"); break;
521
}
522
}
523
}
524
else {
525
musicStatus = MUSIC_STOPPED;
526
}
527
UnlockAudioDevice();
528
}
529
530
void SetMusicTrack(const char *filePath, byte trackID, bool loop, uint loopPoint)
531
{
532
LockAudioDevice();
533
TrackInfo *track = &musicTracks[trackID];
534
StrCopy(track->fileName, "Data/Music/");
535
StrAdd(track->fileName, filePath);
536
track->trackLoop = loop;
537
track->loopPoint = loopPoint;
538
UnlockAudioDevice();
539
}
540
541
void SwapMusicTrack(const char *filePath, byte trackID, uint loopPoint, uint ratio)
542
{
543
if (StrLength(filePath) <= 0) {
544
StopMusic(true);
545
}
546
else {
547
LockAudioDevice();
548
TrackInfo *track = &musicTracks[trackID];
549
StrCopy(track->fileName, "Data/Music/");
550
StrAdd(track->fileName, filePath);
551
track->trackLoop = true;
552
track->loopPoint = loopPoint;
553
musicRatio = ratio;
554
UnlockAudioDevice();
555
PlayMusic(trackID, 1);
556
}
557
}
558
559
bool PlayMusic(int track, int musStartPos)
560
{
561
if (!audioEnabled)
562
return false;
563
564
if (musicTracks[track].fileName[0]) {
565
if (musicStatus != MUSIC_LOADING) {
566
LockAudioDevice();
567
if (track < 0 || track >= TRACK_COUNT) {
568
StopMusic(true);
569
currentMusicTrack = -1;
570
return false;
571
}
572
musicStartPos = musStartPos;
573
currentMusicTrack = track;
574
musicStatus = MUSIC_LOADING;
575
LoadMusic(NULL);
576
UnlockAudioDevice();
577
return true;
578
}
579
else {
580
PrintLog("WARNING music tried to play while music was loading!");
581
}
582
}
583
else {
584
StopMusic(true);
585
}
586
587
return false;
588
}
589
590
void SetSfxName(const char *sfxName, int sfxID)
591
{
592
int sfxNameID = 0;
593
int soundNameID = 0;
594
while (sfxName[sfxNameID]) {
595
if (sfxName[sfxNameID] != ' ')
596
sfxNames[sfxID][soundNameID++] = sfxName[sfxNameID];
597
++sfxNameID;
598
}
599
sfxNames[sfxID][soundNameID] = 0;
600
PrintLog("Set SFX (%d) name to: %s", sfxID, sfxName);
601
}
602
603
void LoadSfx(char *filePath, byte sfxID)
604
{
605
if (!audioEnabled)
606
return;
607
608
FileInfo info;
609
char fullPath[0x80];
610
611
StrCopy(fullPath, "Data/SoundFX/");
612
StrAdd(fullPath, filePath);
613
614
if (LoadFile(fullPath, &info)) {
615
#if !RETRO_USE_ORIGINAL_CODE
616
byte type = fullPath[StrLength(fullPath) - 3];
617
if (type == 'w') {
618
byte *sfx = new byte[info.vfileSize];
619
FileRead(sfx, info.vfileSize);
620
CloseFile();
621
622
SDL_RWops *src = SDL_RWFromMem(sfx, info.vfileSize);
623
if (src == NULL) {
624
PrintLog("Unable to open sfx: %s", info.fileName);
625
}
626
else {
627
SDL_AudioSpec wav_spec;
628
uint wav_length;
629
byte *wav_buffer;
630
SDL_AudioSpec *wav = SDL_LoadWAV_RW(src, 0, &wav_spec, &wav_buffer, &wav_length);
631
632
SDL_RWclose(src);
633
delete[] sfx;
634
if (wav == NULL) {
635
PrintLog("Unable to read sfx: %s", info.fileName);
636
}
637
else {
638
SDL_AudioCVT convert;
639
if (SDL_BuildAudioCVT(&convert, wav->format, wav->channels, wav->freq, audioDeviceFormat.format, audioDeviceFormat.channels,
640
audioDeviceFormat.freq)
641
> 0) {
642
convert.buf = (byte *)malloc(wav_length * convert.len_mult);
643
convert.len = wav_length;
644
memcpy(convert.buf, wav_buffer, wav_length);
645
SDL_ConvertAudio(&convert);
646
647
LockAudioDevice();
648
StrCopy(sfxList[sfxID].name, filePath);
649
sfxList[sfxID].buffer = (Sint16 *)convert.buf;
650
sfxList[sfxID].length = convert.len_cvt / sizeof(Sint16);
651
sfxList[sfxID].loaded = true;
652
UnlockAudioDevice();
653
SDL_FreeWAV(wav_buffer);
654
}
655
else { // this causes errors, actually
656
PrintLog("Unable to read sfx: %s (error: %s)", info.fileName, SDL_GetError());
657
sfxList[sfxID].loaded = false;
658
SDL_FreeWAV(wav_buffer);
659
// LockAudioDevice()
660
// StrCopy(sfxList[sfxID].name, filePath);
661
// sfxList[sfxID].buffer = (Sint16 *)wav_buffer;
662
// sfxList[sfxID].length = wav_length / sizeof(Sint16);
663
// sfxList[sfxID].loaded = false;
664
// UnlockAudioDevice()
665
}
666
}
667
}
668
}
669
else if (type == 'o') {
670
// ogg sfx :(
671
OggVorbis_File vf;
672
ov_callbacks callbacks = OV_CALLBACKS_NOCLOSE;
673
vorbis_info *vinfo;
674
byte *buf;
675
SDL_AudioSpec spec;
676
int bitstream = -1;
677
long samplesize;
678
long samples;
679
int read, toRead;
680
681
currentStreamIndex++;
682
currentStreamIndex %= STREAMFILE_COUNT;
683
684
StreamFile *sfxFile = &streamFile[currentStreamIndex];
685
sfxFile->filePos = 0;
686
sfxFile->fileSize = info.vfileSize;
687
if (info.vfileSize > MUSBUFFER_SIZE)
688
sfxFile->fileSize = MUSBUFFER_SIZE;
689
690
FileRead(streamFile[currentStreamIndex].buffer, sfxFile->fileSize);
691
CloseFile();
692
693
callbacks.read_func = readVorbis;
694
callbacks.seek_func = seekVorbis;
695
callbacks.tell_func = tellVorbis;
696
callbacks.close_func = closeVorbis;
697
698
// GetFileInfo(&info);
699
int error = ov_open_callbacks(sfxFile, &vf, NULL, 0, callbacks);
700
if (error != 0) {
701
ov_clear(&vf);
702
PrintLog("failed to load ogg sfx!");
703
return;
704
}
705
706
vinfo = ov_info(&vf, -1);
707
708
byte *audioBuf = NULL;
709
uint audioLen = 0;
710
memset(&spec, 0, sizeof(SDL_AudioSpec));
711
712
spec.format = AUDIO_S16;
713
spec.channels = vinfo->channels;
714
spec.freq = (int)vinfo->rate;
715
spec.samples = 4096; /* buffer size */
716
717
samples = (long)ov_pcm_total(&vf, -1);
718
719
audioLen = spec.size = (Uint32)(samples * spec.channels * 2);
720
audioBuf = (byte *)malloc(audioLen);
721
buf = audioBuf;
722
toRead = audioLen;
723
724
for (read = (int)ov_read(&vf, (char *)buf, toRead, 0, 2, 1, &bitstream); read > 0;
725
read = (int)ov_read(&vf, (char *)buf, toRead, 0, 2, 1, &bitstream)) {
726
if (read < 0) {
727
free(audioBuf);
728
ov_clear(&vf);
729
PrintLog("failed to read ogg sfx!");
730
return;
731
}
732
toRead -= read;
733
buf += read;
734
}
735
736
ov_clear(&vf); // clears & closes vorbis file
737
738
/* Don't return a buffer that isn't a multiple of samplesize */
739
samplesize = ((spec.format & 0xFF) / 8) * spec.channels;
740
audioLen &= ~(samplesize - 1);
741
742
SDL_AudioCVT convert;
743
if (SDL_BuildAudioCVT(&convert, spec.format, spec.channels, spec.freq, audioDeviceFormat.format, audioDeviceFormat.channels,
744
audioDeviceFormat.freq)
745
> 0) {
746
convert.buf = (byte *)malloc(audioLen * convert.len_mult);
747
convert.len = audioLen;
748
memcpy(convert.buf, audioBuf, audioLen);
749
SDL_ConvertAudio(&convert);
750
751
LockAudioDevice();
752
StrCopy(sfxList[sfxID].name, filePath);
753
sfxList[sfxID].buffer = (Sint16 *)convert.buf;
754
sfxList[sfxID].length = convert.len_cvt / sizeof(Sint16);
755
sfxList[sfxID].loaded = true;
756
UnlockAudioDevice();
757
free(audioBuf);
758
}
759
else {
760
LockAudioDevice();
761
StrCopy(sfxList[sfxID].name, filePath);
762
sfxList[sfxID].buffer = (Sint16 *)audioBuf;
763
sfxList[sfxID].length = audioLen / sizeof(Sint16);
764
sfxList[sfxID].loaded = true;
765
UnlockAudioDevice();
766
}
767
}
768
else {
769
// wtf lol
770
CloseFile();
771
PrintLog("Sfx format not supported!");
772
}
773
#endif
774
}
775
}
776
void PlaySfx(int sfx, bool loop)
777
{
778
LockAudioDevice();
779
int sfxChannelID = -1;
780
for (int c = 0; c < CHANNEL_COUNT; ++c) {
781
if (sfxChannels[c].sfxID == sfx || sfxChannels[c].sfxID == -1) {
782
sfxChannelID = c;
783
break;
784
}
785
}
786
787
ChannelInfo *sfxInfo = &sfxChannels[sfxChannelID];
788
sfxInfo->sfxID = sfx;
789
sfxInfo->samplePtr = sfxList[sfx].buffer;
790
sfxInfo->sampleLength = sfxList[sfx].length;
791
sfxInfo->loopSFX = loop;
792
sfxInfo->pan = 0;
793
UnlockAudioDevice();
794
}
795
void SetSfxAttributes(int sfx, int loopCount, sbyte pan)
796
{
797
LockAudioDevice();
798
int sfxChannel = -1;
799
for (int i = 0; i < CHANNEL_COUNT; ++i) {
800
if (sfxChannels[i].sfxID == sfx) {
801
sfxChannel = i;
802
break;
803
}
804
}
805
if (sfxChannel == -1) {
806
UnlockAudioDevice();
807
return; // wasn't found
808
}
809
810
ChannelInfo *sfxInfo = &sfxChannels[sfxChannel];
811
sfxInfo->loopSFX = loopCount == -1 ? sfxInfo->loopSFX : loopCount;
812
sfxInfo->pan = pan;
813
sfxInfo->sfxID = sfx;
814
UnlockAudioDevice();
815
}
816
817