Skip to content

Commit e9afe0d

Browse files
committed
openal is now good
1 parent 1560e89 commit e9afe0d

3 files changed

Lines changed: 135 additions & 179 deletions

File tree

src/audio/openal/al_audio_system.c

Lines changed: 135 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@
88
#include "al_audio_system.h"
99
#include "data_win.h"
1010
#include "utils.h"
11-
#include "wave.h"
1211

1312
#include <stdio.h>
1413
#include <stdlib.h>
@@ -167,10 +166,25 @@ static void maInit(AudioSystem* audio, DataWin* dataWin, FileSystem* fileSystem)
167166
ma->fileSystem = fileSystem;
168167

169168
ma->alDevice = alcOpenDevice(nullptr);
169+
if (ma->alDevice == nullptr) {
170+
fprintf(stderr, "Audio: Failed to open OpenAL device (error %d)\n", alGetError());
171+
return;
172+
}
173+
170174
ma->alContext = alcCreateContext(ma->alDevice, nullptr);
171-
alcMakeContextCurrent(ma->alContext);
172-
if (ma->alDevice == nullptr || ma->alContext == nullptr) {
173-
fprintf(stderr, "Audio: Failed to initialize OpenAL engine (error %d)\n", alGetError());
175+
if (ma->alContext == nullptr) {
176+
fprintf(stderr, "Audio: Failed to create OpenAL context (error %d)\n", alGetError());
177+
alcCloseDevice(ma->alDevice);
178+
ma->alDevice = nullptr;
179+
return;
180+
}
181+
182+
if (!alcMakeContextCurrent(ma->alContext)) {
183+
fprintf(stderr, "Audio: Failed to make OpenAL context current (error %d)\n", alGetError());
184+
alcDestroyContext(ma->alContext);
185+
alcCloseDevice(ma->alDevice);
186+
ma->alContext = nullptr;
187+
ma->alDevice = nullptr;
174188
return;
175189
}
176190

@@ -278,6 +292,28 @@ static void maUpdate(AudioSystem* audio, float deltaTime) {
278292
}
279293
}
280294

295+
// Walk RIFF chunks in a WAV container to find the 'data' chunk payload offset and length.
296+
// Returns pointer to the first byte of audio data, or nullptr on failure.
297+
// audioDataLenOut receives the chunk's data length.
298+
static const uint8_t* findWavDataChunk(const uint8_t* data, uint32_t dataSize, uint32_t* audioDataLenOut) {
299+
if (data == nullptr || dataSize < 12) return nullptr;
300+
if (data[0] != 'R' || data[1] != 'I' || data[2] != 'F' || data[3] != 'F') return nullptr;
301+
uint32_t offset = 12;
302+
while (offset + 8 <= dataSize) {
303+
uint32_t chunkLen = data[offset+4] | (data[offset+5] << 8) | (data[offset+6] << 16) | (data[offset+7] << 24);
304+
uint32_t chunkDataOffset = offset + 8;
305+
uint32_t available = dataSize - chunkDataOffset;
306+
if (chunkLen > available) chunkLen = available;
307+
if (data[offset] == 'd' && data[offset+1] == 'a' && data[offset+2] == 't' && data[offset+3] == 'a') {
308+
*audioDataLenOut = chunkLen;
309+
return data + chunkDataOffset;
310+
}
311+
offset = chunkDataOffset + chunkLen;
312+
if (offset & 1) offset++;
313+
}
314+
return nullptr;
315+
}
316+
281317
static int32_t maPlaySound(AudioSystem* audio, int32_t soundIndex, int32_t priority, bool loop) {
282318
AlAudioSystem* ma = (AlAudioSystem*) audio;
283319

@@ -338,6 +374,15 @@ static int32_t maPlaySound(AudioSystem* audio, int32_t soundIndex, int32_t prior
338374

339375
alGenSources(1, &slot->alSource);
340376
alGenBuffers(AL_STREAM_BUFFER_COUNT, slot->streamBuffers);
377+
if (alGetError() != AL_NO_ERROR) {
378+
fprintf(stderr, "Audio: alGenSources/alGenBuffers failed for stream\n");
379+
stb_vorbis_close(v);
380+
free(slot->decodeScratch);
381+
slot->streaming = false;
382+
slot->vorbis = nullptr;
383+
slot->decodeScratch = nullptr;
384+
return -1;
385+
}
341386

342387
int primed = 0;
343388
for (int i = 0; AL_STREAM_BUFFER_COUNT > i; i++) {
@@ -360,6 +405,10 @@ static int32_t maPlaySound(AudioSystem* audio, int32_t soundIndex, int32_t prior
360405
} else {
361406
alGenSources(1, &slot->alSource);
362407
alGenBuffers(1, &slot->alBuffer);
408+
if (alGetError() != AL_NO_ERROR) {
409+
fprintf(stderr, "Audio: alGenSources/alGenBuffers failed for sound %d\n", soundIndex);
410+
return -1;
411+
}
363412
bool isRegular = (sound->flags & AUDIO_ENTRY_FLAG_REGULAR) == AUDIO_ENTRY_FLAG_REGULAR;
364413
bool isEmbedded = (sound->flags & AUDIO_ENTRY_FLAG_IS_EMBEDDED) != 0;
365414
bool isCompressed = (sound->flags & AUDIO_ENTRY_FLAG_IS_COMPRESSED) != 0;
@@ -373,31 +422,68 @@ static int32_t maPlaySound(AudioSystem* audio, int32_t soundIndex, int32_t prior
373422
}
374423

375424
AudioEntry* entry = &ma->base.audioGroups[sound->audioGroup]->audo.entries[sound->audioFile];
376-
WAVFile wav = WAV_ParseFileData(entry->data);
425+
426+
uint32_t channels = 0;
427+
uint32_t sampleRate = 0;
428+
uint32_t bitsPerSample = 0;
429+
const uint8_t* audioData = nullptr;
430+
uint32_t audioDataLen = 0;
431+
bool hasWavHeader = (entry->dataSize >= 12 &&
432+
entry->data[0] == 'R' && entry->data[1] == 'I' &&
433+
entry->data[2] == 'F' && entry->data[3] == 'F');
434+
435+
if (hasWavHeader) {
436+
channels = entry->data[22] | (entry->data[23] << 8);
437+
sampleRate = entry->data[24] | (entry->data[25] << 8) |
438+
(entry->data[26] << 16) | (entry->data[27] << 24);
439+
bitsPerSample = entry->data[34] | (entry->data[35] << 8);
440+
audioData = findWavDataChunk(entry->data, entry->dataSize, &audioDataLen);
441+
} else {
442+
channels = 2;
443+
sampleRate = 44100;
444+
bitsPerSample = 16;
445+
audioData = entry->data;
446+
audioDataLen = entry->dataSize;
447+
}
448+
449+
if (audioData == nullptr || audioDataLen == 0) {
450+
fprintf(stderr, "Audio: No audio data for '%s'\n", sound->name);
451+
return -1;
452+
}
453+
if (channels == 0 || sampleRate == 0 || bitsPerSample == 0) {
454+
fprintf(stderr, "Audio: Invalid audio params for '%s' ch=%u rate=%u bits=%u\n",
455+
sound->name, channels, sampleRate, bitsPerSample);
456+
return -1;
457+
}
377458

378459
uint32_t format;
379-
if (wav.header.number_of_channels == 1)
460+
if (channels == 1)
380461
{
381-
if (wav.header.bits_per_sample == 8)
462+
if (bitsPerSample == 8)
382463
format = AL_FORMAT_MONO8;
383464
else
384465
format = AL_FORMAT_MONO16;
385466
}
386467
else {
387-
if (wav.header.bits_per_sample == 8)
468+
if (bitsPerSample == 8)
388469
format = AL_FORMAT_STEREO8;
389470
else
390471
format = AL_FORMAT_STEREO16;
391472
}
392473
alBufferData(
393474
slot->alBuffer,
394475
format,
395-
wav.data,
396-
wav.data_length,
397-
wav.header.sample_rate
476+
audioData,
477+
audioDataLen,
478+
sampleRate
398479
);
480+
ALenum alErr = alGetError();
481+
if (alErr != AL_NO_ERROR) {
482+
fprintf(stderr, "Audio: alBufferData failed for '%s' format=0x%x len=%u rate=%u err=%d\n",
483+
sound->name, format, audioDataLen, sampleRate, alErr);
484+
return -1;
485+
}
399486
alSourcei(slot->alSource, AL_BUFFER, slot->alBuffer);
400-
if(wav.data != NULL) free(wav.data);
401487
} else {
402488
// External audio: load from file
403489
char* path = resolveExternalPath(ma, sound);
@@ -410,13 +496,24 @@ static int32_t maPlaySound(AudioSystem* audio, int32_t soundIndex, int32_t prior
410496
int sample_rate;
411497
short* data = NULL;
412498
int len = stb_vorbis_decode_filename(path, &channels, &sample_rate, &data);
499+
if (len <= 0 || data == nullptr) {
500+
fprintf(stderr, "Audio: stb_vorbis_decode failed for '%s' path='%s' len=%d\n", sound->name, path, len);
501+
free(path);
502+
return -1;
503+
}
413504
alBufferData(
414505
slot->alBuffer,
415506
(channels == 2) ? AL_FORMAT_STEREO16 : AL_FORMAT_MONO16,
416507
(void*)data,
417508
len*channels*sizeof(uint16_t),
418509
sample_rate
419510
);
511+
if (alGetError() != AL_NO_ERROR) {
512+
fprintf(stderr, "Audio: alBufferData failed for external '%s'\n", sound->name);
513+
free(data);
514+
free(path);
515+
return -1;
516+
}
420517
alSourcei(slot->alSource, AL_BUFFER, slot->alBuffer);
421518
if(data != NULL) free(data);
422519
free(path);
@@ -451,6 +548,9 @@ static int32_t maPlaySound(AudioSystem* audio, int32_t soundIndex, int32_t prior
451548
ma->nextInstanceCounter++;
452549

453550
alSourcePlay(slot->alSource);
551+
if (alGetError() != AL_NO_ERROR) {
552+
fprintf(stderr, "Audio: alSourcePlay failed for sound %d (stream=%d)\n", soundIndex, isStream);
553+
}
454554

455555
return slot->instanceId;
456556
}
@@ -774,11 +874,29 @@ static float maGetSoundLength(AudioSystem* audio, int32_t soundOrInstance) {
774874
if (inAudo) {
775875
if (0 > sound->audioFile || (uint32_t) sound->audioFile >= ma->base.audioGroups[sound->audioGroup]->audo.count) return 0.0f;
776876
AudioEntry* entry = &ma->base.audioGroups[sound->audioGroup]->audo.entries[sound->audioFile];
777-
WAVFile wav = WAV_ParseFileData(entry->data);
778-
float seconds = 0.0f;
779-
if (wav.header.byte_rate > 0) seconds = (float) wav.header.data_size / (float) wav.header.byte_rate;
780-
if (wav.data != nullptr) free(wav.data);
781-
return seconds;
877+
878+
bool hasWavHeader = (entry->dataSize >= 12 &&
879+
entry->data[0] == 'R' && entry->data[1] == 'I' &&
880+
entry->data[2] == 'F' && entry->data[3] == 'F');
881+
882+
if (hasWavHeader) {
883+
uint32_t channels = entry->data[22] | (entry->data[23] << 8);
884+
uint32_t sampleRate = entry->data[24] | (entry->data[25] << 8) |
885+
(entry->data[26] << 16) | (entry->data[27] << 24);
886+
uint32_t bitsPerSample = entry->data[34] | (entry->data[35] << 8);
887+
uint32_t audioDataLen = 0;
888+
findWavDataChunk(entry->data, entry->dataSize, &audioDataLen);
889+
if (channels > 0 && sampleRate > 0 && bitsPerSample > 0 && audioDataLen > 0) {
890+
uint32_t bytesPerSample = channels * (bitsPerSample / 8);
891+
if (bytesPerSample > 0)
892+
return (float) audioDataLen / (float)(sampleRate * bytesPerSample);
893+
}
894+
} else {
895+
// Raw PCM: assume stereo 16-bit 44100 Hz
896+
uint32_t audioDataLen = entry->dataSize;
897+
return (float) audioDataLen / (float)(44100 * 2 * 2);
898+
}
899+
return 0.0f;
782900
}
783901

784902
char* path = resolveExternalPath(ma, sound);

src/audio/openal/wave.c

Lines changed: 0 additions & 92 deletions
This file was deleted.

0 commit comments

Comments
 (0)