Improve Sound readability

This commit is contained in:
Alexander Batalov 2022-12-25 21:56:23 +03:00
parent e11f1af9ae
commit b8dea116ee
5 changed files with 292 additions and 274 deletions

View File

@ -1681,21 +1681,21 @@ void soundEffectCallback(void* userData, int a2)
// 0x451ADC
int _gsound_background_allocate(Sound** soundPtr, int a2, int a3)
{
int v5 = 10;
int v6 = 0;
int soundFlags = SOUND_FLAG_0x02 | SOUND_16BIT;
int type = 0;
if (a2 == 13) {
v6 |= 0x01;
type |= SOUND_TYPE_MEMORY;
} else if (a2 == 14) {
v6 |= 0x02;
type |= SOUND_TYPE_STREAMING;
}
if (a3 == 15) {
v6 |= 0x04;
type |= SOUND_TYPE_FIRE_AND_FORGET;
} else if (a3 == 16) {
v5 = 42;
soundFlags |= SOUND_LOOPING;
}
Sound* sound = soundAllocate(v6, v5);
Sound* sound = soundAllocate(type, soundFlags);
if (sound == NULL) {
return -1;
}
@ -2006,7 +2006,7 @@ Sound* _gsound_get_sound_ready_for_effect()
{
int rc;
Sound* sound = soundAllocate(5, 10);
Sound* sound = soundAllocate(SOUND_TYPE_MEMORY | SOUND_TYPE_FIRE_AND_FORGET, SOUND_FLAG_0x02 | SOUND_16BIT);
if (sound == NULL) {
if (gGameSoundDebugEnabled) {
debugPrint(" Can't allocate sound for effect. ");

View File

@ -1872,32 +1872,29 @@ static int intLibSoundDelete(int value)
// 0x466110
static int intLibSoundPlay(char* fileName, int mode)
{
int v3 = 1;
int v5 = 0;
int type = SOUND_TYPE_MEMORY;
int soundFlags = 0;
if (mode & 0x01) {
// looping
v5 |= 0x20;
soundFlags |= SOUND_LOOPING;
} else {
v3 = 5;
type |= SOUND_TYPE_FIRE_AND_FORGET;
}
if (mode & 0x02) {
v5 |= 0x08;
soundFlags |= SOUND_16BIT;
} else {
v5 |= 0x10;
soundFlags |= SOUND_8BIT;
}
if (mode & 0x0100) {
// memory
v3 &= ~0x03;
v3 |= 0x01;
type &= ~(SOUND_TYPE_MEMORY | SOUND_TYPE_STREAMING);
type |= SOUND_TYPE_MEMORY;
}
if (mode & 0x0200) {
// streamed
v3 &= ~0x03;
v3 |= 0x02;
type &= ~(SOUND_TYPE_MEMORY | SOUND_TYPE_STREAMING);
type |= SOUND_TYPE_STREAMING;
}
int index;
@ -1911,7 +1908,7 @@ static int intLibSoundPlay(char* fileName, int mode)
return -1;
}
Sound* sound = gIntLibSounds[index] = soundAllocate(v3, v5);
Sound* sound = gIntLibSounds[index] = soundAllocate(type, soundFlags);
if (sound == NULL) {
return -1;
}
@ -2009,7 +2006,7 @@ static int intLibSoundPause(int value)
}
int rc;
if (_soundType(sound, 0x01)) {
if (_soundType(sound, SOUND_TYPE_MEMORY)) {
rc = soundStop(sound);
} else {
rc = soundPause(sound);
@ -2061,7 +2058,7 @@ static int intLibSoundResume(int value)
}
int rc;
if (_soundType(sound, 0x01)) {
if (_soundType(sound, SOUND_TYPE_MEMORY)) {
rc = soundPlay(sound);
} else {
rc = soundResume(sound);

View File

@ -413,7 +413,7 @@ static int _lips_make_speech()
gLipsData.sound = NULL;
}
gLipsData.sound = soundAllocate(1, 8);
gLipsData.sound = soundAllocate(SOUND_TYPE_MEMORY, SOUND_16BIT);
if (gLipsData.sound == NULL) {
debugPrint("\nsoundAllocate falied in lips_make_speech!");
return -1;

View File

@ -22,10 +22,12 @@
namespace fallout {
#define SOUND_FLAG_SOUND_IS_DONE (0x01)
#define SOUND_FLAG_SOUND_IS_PLAYING (0x02)
#define SOUND_FLAG_SOUND_IS_FADING (0x04)
#define SOUND_FLAG_SOUND_IS_PAUSED (0x08)
typedef enum SoundStatusFlags {
SOUND_STATUS_DONE = 0x01,
SOUND_STATUS_IS_PLAYING = 0x02,
SOUND_STATUS_IS_FADING = 0x04,
SOUND_STATUS_IS_PAUSED = 0x08,
} SoundStatusFlags;
typedef char*(SoundFileNameMangler)(char*);
@ -35,7 +37,7 @@ typedef struct FadeSound {
int targetVolume;
int initialVolume;
int currentVolume;
int field_14;
int pause;
struct FadeSound* prev;
struct FadeSound* next;
} FadeSound;
@ -56,7 +58,7 @@ static Uint32 _doTimerEvent(Uint32 interval, void* param);
static void _removeTimedEvent(SDL_TimerID* timerId);
static void _removeFadeSound(FadeSound* fadeSound);
static void _fadeSounds();
static int _internalSoundFade(Sound* sound, int duration, int targetVolume, int a4);
static int _internalSoundFade(Sound* sound, int duration, int targetVolume, bool pause);
// 0x51D478
static FadeSound* _fadeHead = NULL;
@ -205,7 +207,7 @@ const char* soundGetErrorDescription(int err)
// 0x4AC7B0
void _refreshSoundBuffers(Sound* sound)
{
if (sound->field_3C & 0x80) {
if ((sound->soundFlags & SOUND_FLAG_0x80) != 0) {
return;
}
@ -216,50 +218,50 @@ void _refreshSoundBuffers(Sound* sound)
return;
}
if (readPos < sound->field_74) {
sound->field_64 += readPos + sound->field_78 * sound->field_7C - sound->field_74;
if (readPos < sound->lastPosition) {
sound->numBytesRead += readPos + sound->numBuffers * sound->dataSize - sound->lastPosition;
} else {
sound->field_64 += readPos - sound->field_74;
sound->numBytesRead += readPos - sound->lastPosition;
}
if (sound->field_3C & 0x0100) {
if (sound->field_44 & 0x20) {
if (sound->field_3C & 0x0200) {
sound->field_3C |= 0x80;
if ((sound->soundFlags & SOUND_FLAG_0x100) != 0) {
if ((sound->type & SOUND_TYPE_0x20) != 0) {
if ((sound->soundFlags & SOUND_FLAG_0x200) != 0) {
sound->soundFlags |= SOUND_FLAG_0x80;
}
} else {
if (sound->field_60 <= sound->field_64) {
sound->field_3C |= 0x0280;
if (sound->fileSize <= sound->numBytesRead) {
sound->soundFlags |= SOUND_FLAG_0x200 | SOUND_FLAG_0x80;
}
}
}
sound->field_74 = readPos;
sound->lastPosition = readPos;
if (sound->field_60 < sound->field_64) {
if (sound->fileSize < sound->numBytesRead) {
int v3;
do {
v3 = sound->field_64 - sound->field_60;
sound->field_64 = v3;
} while (v3 > sound->field_60);
v3 = sound->numBytesRead - sound->fileSize;
sound->numBytesRead = v3;
} while (v3 > sound->fileSize);
}
int v6 = readPos / sound->field_7C;
if (sound->field_70 == v6) {
int v6 = readPos / sound->dataSize;
if (sound->lastUpdate == v6) {
return;
}
int v53;
if (sound->field_70 > v6) {
v53 = v6 + sound->field_78 - sound->field_70;
if (sound->lastUpdate > v6) {
v53 = v6 + sound->numBuffers - sound->lastUpdate;
} else {
v53 = v6 - sound->field_70;
v53 = v6 - sound->lastUpdate;
}
if (sound->field_7C * v53 >= sound->readLimit) {
v53 = (sound->readLimit + sound->field_7C - 1) / sound->field_7C;
if (sound->dataSize * v53 >= sound->readLimit) {
v53 = (sound->readLimit + sound->dataSize - 1) / sound->dataSize;
}
if (v53 < sound->field_5C) {
if (v53 < sound->minReadBuffer) {
return;
}
@ -267,17 +269,17 @@ void _refreshSoundBuffers(Sound* sound)
void* audioPtr2;
unsigned int audioBytes1;
unsigned int audioBytes2;
hr = audioEngineSoundBufferLock(sound->soundBuffer, sound->field_7C * sound->field_70, sound->field_7C * v53, &audioPtr1, &audioBytes1, &audioPtr2, &audioBytes2, 0);
hr = audioEngineSoundBufferLock(sound->soundBuffer, sound->dataSize * sound->lastUpdate, sound->dataSize * v53, &audioPtr1, &audioBytes1, &audioPtr2, &audioBytes2, 0);
if (!hr) {
return;
}
if (audioBytes1 + audioBytes2 != sound->field_7C * v53) {
debugPrint("locked memory region not big enough, wanted %d (%d * %d), got %d (%d + %d)\n", sound->field_7C * v53, v53, sound->field_7C, audioBytes1 + audioBytes2, audioBytes1, audioBytes2);
debugPrint("Resetting readBuffers from %d to %d\n", v53, (audioBytes1 + audioBytes2) / sound->field_7C);
if (audioBytes1 + audioBytes2 != sound->dataSize * v53) {
debugPrint("locked memory region not big enough, wanted %d (%d * %d), got %d (%d + %d)\n", sound->dataSize * v53, v53, sound->dataSize, audioBytes1 + audioBytes2, audioBytes1, audioBytes2);
debugPrint("Resetting readBuffers from %d to %d\n", v53, (audioBytes1 + audioBytes2) / sound->dataSize);
v53 = (audioBytes1 + audioBytes2) / sound->field_7C;
if (v53 < sound->field_5C) {
v53 = (audioBytes1 + audioBytes2) / sound->dataSize;
if (v53 < sound->minReadBuffer) {
debugPrint("No longer above read buffer size, returning\n");
return;
}
@ -286,11 +288,11 @@ void _refreshSoundBuffers(Sound* sound)
int audioBytes = audioBytes1;
while (--v53 != -1) {
int bytesRead;
if (sound->field_3C & 0x0200) {
bytesRead = sound->field_7C;
memset(sound->field_20, 0, bytesRead);
if ((sound->soundFlags & SOUND_FLAG_0x200) != 0) {
bytesRead = sound->dataSize;
memset(sound->data, 0, bytesRead);
} else {
int bytesToRead = sound->field_7C;
int bytesToRead = sound->dataSize;
if (sound->field_58 != -1) {
int pos = sound->io.tell(sound->io.fd);
if (bytesToRead + pos > sound->field_58) {
@ -298,30 +300,30 @@ void _refreshSoundBuffers(Sound* sound)
}
}
bytesRead = sound->io.read(sound->io.fd, sound->field_20, bytesToRead);
if (bytesRead < sound->field_7C) {
if (!(sound->field_3C & 0x20) || (sound->field_3C & 0x0100)) {
memset(sound->field_20 + bytesRead, 0, sound->field_7C - bytesRead);
sound->field_3C |= 0x0200;
bytesRead = sound->field_7C;
bytesRead = sound->io.read(sound->io.fd, sound->data, bytesToRead);
if (bytesRead < sound->dataSize) {
if ((sound->soundFlags & SOUND_LOOPING) == 0 || (sound->soundFlags & SOUND_FLAG_0x100) != 0) {
memset(sound->data + bytesRead, 0, sound->dataSize - bytesRead);
sound->soundFlags |= SOUND_FLAG_0x200;
bytesRead = sound->dataSize;
} else {
while (bytesRead < sound->field_7C) {
if (sound->field_50 == -1) {
while (bytesRead < sound->dataSize) {
if (sound->loops == -1) {
sound->io.seek(sound->io.fd, sound->field_54, SEEK_SET);
if (sound->callback != NULL) {
sound->callback(sound->callbackUserData, 0x0400);
}
} else {
if (sound->field_50 <= 0) {
if (sound->loops <= 0) {
sound->field_58 = -1;
sound->field_54 = 0;
sound->field_50 = 0;
sound->field_3C &= ~0x20;
bytesRead += sound->io.read(sound->io.fd, sound->field_20 + bytesRead, sound->field_7C - bytesRead);
sound->loops = 0;
sound->soundFlags &= ~SOUND_LOOPING;
bytesRead += sound->io.read(sound->io.fd, sound->data + bytesRead, sound->dataSize - bytesRead);
break;
}
sound->field_50--;
sound->loops--;
sound->io.seek(sound->io.fd, sound->field_54, SEEK_SET);
if (sound->callback != NULL) {
@ -330,17 +332,17 @@ void _refreshSoundBuffers(Sound* sound)
}
if (sound->field_58 == -1) {
bytesToRead = sound->field_7C - bytesRead;
bytesToRead = sound->dataSize - bytesRead;
} else {
int pos = sound->io.tell(sound->io.fd);
if (sound->field_7C + bytesRead + pos <= sound->field_58) {
bytesToRead = sound->field_7C - bytesRead;
if (sound->dataSize + bytesRead + pos <= sound->field_58) {
bytesToRead = sound->dataSize - bytesRead;
} else {
bytesToRead = sound->field_58 - bytesRead - pos;
}
}
int v20 = sound->io.read(sound->io.fd, sound->field_20 + bytesRead, bytesToRead);
int v20 = sound->io.read(sound->io.fd, sound->data + bytesRead, bytesToRead);
bytesRead += v20;
if (v20 < bytesToRead) {
break;
@ -352,18 +354,18 @@ void _refreshSoundBuffers(Sound* sound)
if (bytesRead > audioBytes) {
if (audioBytes != 0) {
memcpy(audioPtr, sound->field_20, audioBytes);
memcpy(audioPtr, sound->data, audioBytes);
}
if (audioPtr2 != NULL) {
memcpy(audioPtr2, sound->field_20 + audioBytes, bytesRead - audioBytes);
memcpy(audioPtr2, sound->data + audioBytes, bytesRead - audioBytes);
audioPtr = (unsigned char*)audioPtr2 + bytesRead - audioBytes;
audioBytes = audioBytes2 - bytesRead;
} else {
debugPrint("Hm, no second write pointer, but buffer not big enough, this shouldn't happen\n");
}
} else {
memcpy(audioPtr, sound->field_20, bytesRead);
memcpy(audioPtr, sound->data, bytesRead);
audioPtr += bytesRead;
audioBytes -= bytesRead;
}
@ -371,11 +373,11 @@ void _refreshSoundBuffers(Sound* sound)
audioEngineSoundBufferUnlock(sound->soundBuffer, audioPtr1, audioBytes1, audioPtr2, audioBytes2);
sound->field_70 = v6;
sound->lastUpdate = v6;
}
// 0x4ACC58
int soundInit(int a1, int a2, int a3, int a4, int rate)
int soundInit(int a1, int numBuffers, int a3, int dataSize, int rate)
{
if (!audioEngineInit()) {
debugPrint("soundInit: Unable to init audio engine\n");
@ -385,8 +387,8 @@ int soundInit(int a1, int a2, int a3, int a4, int rate)
}
_sampleRate = rate;
_dataSize = a4;
_numBuffers = a2;
_dataSize = dataSize;
_numBuffers = numBuffers;
gSoundInitialized = true;
_deviceInit = 1;
@ -422,7 +424,7 @@ void soundExit()
}
// 0x4AD0FC
Sound* soundAllocate(int a1, int a2)
Sound* soundAllocate(int type, int soundFlags)
{
if (!gSoundInitialized) {
gSoundLastError = SOUND_NOT_INITIALIZED;
@ -434,30 +436,30 @@ Sound* soundAllocate(int a1, int a2)
memcpy(&(sound->io), &gSoundDefaultFileIO, sizeof(gSoundDefaultFileIO));
if (!(a2 & 0x02)) {
a2 |= 0x02;
if ((soundFlags & SOUND_FLAG_0x02) == 0) {
soundFlags |= SOUND_FLAG_0x02;
}
sound->bitsPerSample = (a2 & 0x08) != 0 ? 16 : 8;
sound->bitsPerSample = (soundFlags & SOUND_16BIT) != 0 ? 16 : 8;
sound->channels = 1;
sound->rate = _sampleRate;
sound->field_3C = a2;
sound->field_44 = a1;
sound->field_7C = _dataSize;
sound->field_64 = 0;
sound->soundFlags = soundFlags;
sound->type = type;
sound->dataSize = _dataSize;
sound->numBytesRead = 0;
sound->soundBuffer = -1;
sound->field_40 = 0;
sound->field_78 = _numBuffers;
sound->readLimit = sound->field_7C * _numBuffers;
sound->statusFlags = 0;
sound->numBuffers = _numBuffers;
sound->readLimit = sound->dataSize * _numBuffers;
if (a1 & 0x10) {
sound->field_50 = -1;
sound->field_3C |= 0x20;
if ((type & SOUND_TYPE_INFINITE) != 0) {
sound->loops = -1;
sound->soundFlags |= SOUND_LOOPING;
}
sound->field_58 = -1;
sound->field_5C = 1;
sound->minReadBuffer = 1;
sound->volume = VOLUME_MAX;
sound->prev = NULL;
sound->field_54 = 0;
@ -483,29 +485,29 @@ int _preloadBuffers(Sound* sound)
int size;
size = sound->io.filelength(sound->io.fd);
sound->field_60 = size;
sound->fileSize = size;
if (sound->field_44 & 0x02) {
if (!(sound->field_3C & 0x20)) {
sound->field_3C |= 0x0120;
if ((sound->type & SOUND_TYPE_STREAMING) != 0) {
if ((sound->soundFlags & SOUND_LOOPING) == 0) {
sound->soundFlags |= SOUND_FLAG_0x100 | SOUND_LOOPING;
}
if (sound->field_78 * sound->field_7C >= size) {
if (size / sound->field_7C * sound->field_7C != size) {
size = (size / sound->field_7C + 1) * sound->field_7C;
if (sound->numBuffers * sound->dataSize >= size) {
if (size / sound->dataSize * sound->dataSize != size) {
size = (size / sound->dataSize + 1) * sound->dataSize;
}
} else {
size = sound->field_78 * sound->field_7C;
size = sound->numBuffers * sound->dataSize;
}
} else {
sound->field_44 &= ~(0x03);
sound->field_44 |= 0x01;
sound->type &= ~(SOUND_TYPE_MEMORY | SOUND_TYPE_STREAMING);
sound->type |= SOUND_TYPE_MEMORY;
}
buf = (unsigned char*)gSoundMallocProc(size);
bytes_read = sound->io.read(sound->io.fd, buf, size);
if (bytes_read != size) {
if (!(sound->field_3C & 0x20) || (sound->field_3C & (0x01 << 8))) {
if ((sound->soundFlags & SOUND_LOOPING) == 0 || (sound->soundFlags & SOUND_FLAG_0x100) != 0) {
memset(buf + bytes_read, 0, size - bytes_read);
} else {
v14 = buf + bytes_read;
@ -525,12 +527,12 @@ int _preloadBuffers(Sound* sound)
result = _soundSetData(sound, buf, size);
gSoundFreeProc(buf);
if (sound->field_44 & 0x01) {
if ((sound->type & SOUND_TYPE_MEMORY) != 0) {
sound->io.close(sound->io.fd);
sound->io.fd = -1;
} else {
if (sound->field_20 == NULL) {
sound->field_20 = (unsigned char*)gSoundMallocProc(sound->field_7C);
if (sound->data == NULL) {
sound->data = (unsigned char*)gSoundMallocProc(sound->dataSize);
}
}
@ -574,12 +576,12 @@ int _soundRewind(Sound* sound)
return gSoundLastError;
}
if (sound->field_44 & 0x02) {
if ((sound->type & SOUND_TYPE_STREAMING) != 0) {
sound->io.seek(sound->io.fd, 0, SEEK_SET);
sound->field_70 = 0;
sound->field_74 = 0;
sound->field_64 = 0;
sound->field_3C &= 0xFD7F;
sound->lastUpdate = 0;
sound->lastPosition = 0;
sound->numBytesRead = 0;
sound->soundFlags &= ~(SOUND_FLAG_0x200 | SOUND_FLAG_0x80);
hr = audioEngineSoundBufferSetCurrentPosition(sound->soundBuffer, 0);
_preloadBuffers(sound);
} else {
@ -591,7 +593,7 @@ int _soundRewind(Sound* sound)
return gSoundLastError;
}
sound->field_40 &= ~SOUND_FLAG_SOUND_IS_DONE;
sound->statusFlags &= ~SOUND_STATUS_DONE;
gSoundLastError = SOUND_NO_ERROR;
return gSoundLastError;
@ -669,24 +671,23 @@ int soundPlay(Sound* sound)
return gSoundLastError;
}
// TODO: Check.
if (sound->field_40 & SOUND_FLAG_SOUND_IS_DONE) {
if ((sound->statusFlags & SOUND_STATUS_DONE) != 0) {
_soundRewind(sound);
}
soundSetVolume(sound, sound->volume);
hr = audioEngineSoundBufferPlay(sound->soundBuffer, sound->field_3C & 0x20 ? AUDIO_ENGINE_SOUND_BUFFER_PLAY_LOOPING : 0);
hr = audioEngineSoundBufferPlay(sound->soundBuffer, sound->soundFlags & SOUND_LOOPING ? AUDIO_ENGINE_SOUND_BUFFER_PLAY_LOOPING : 0);
audioEngineSoundBufferGetCurrentPosition(sound->soundBuffer, &readPos, &writePos);
sound->field_70 = readPos / sound->field_7C;
sound->lastUpdate = readPos / sound->dataSize;
if (!hr) {
gSoundLastError = SOUND_UNKNOWN_ERROR;
return gSoundLastError;
}
sound->field_40 |= SOUND_FLAG_SOUND_IS_PLAYING;
sound->statusFlags |= SOUND_STATUS_IS_PLAYING;
++_numSounds;
@ -709,7 +710,7 @@ int soundStop(Sound* sound)
return gSoundLastError;
}
if (!(sound->field_40 & SOUND_FLAG_SOUND_IS_PLAYING)) {
if ((sound->statusFlags & SOUND_STATUS_IS_PLAYING) == 0) {
gSoundLastError = SOUND_NOT_PLAYING;
return gSoundLastError;
}
@ -720,7 +721,7 @@ int soundStop(Sound* sound)
return gSoundLastError;
}
sound->field_40 &= ~SOUND_FLAG_SOUND_IS_PLAYING;
sound->statusFlags &= ~SOUND_STATUS_IS_PLAYING;
_numSounds--;
gSoundLastError = SOUND_NO_ERROR;
@ -772,12 +773,17 @@ int soundContinue(Sound* sound)
return gSoundLastError;
}
if (!(sound->field_40 & SOUND_FLAG_SOUND_IS_PLAYING) || (sound->field_40 & SOUND_FLAG_SOUND_IS_PAUSED)) {
if ((sound->statusFlags & SOUND_STATUS_IS_PLAYING) == 0) {
gSoundLastError = SOUND_NOT_PLAYING;
return gSoundLastError;
}
if (sound->field_40 & SOUND_FLAG_SOUND_IS_DONE) {
if ((sound->statusFlags & SOUND_STATUS_IS_PAUSED) != 0) {
gSoundLastError = SOUND_NOT_PLAYING;
return gSoundLastError;
}
if ((sound->statusFlags & SOUND_STATUS_DONE) != 0) {
gSoundLastError = SOUND_UNKNOWN_ERROR;
return gSoundLastError;
}
@ -790,29 +796,29 @@ int soundContinue(Sound* sound)
return gSoundLastError;
}
if (!(sound->field_3C & 0x80) && (status & (AUDIO_ENGINE_SOUND_BUFFER_STATUS_PLAYING | AUDIO_ENGINE_SOUND_BUFFER_STATUS_LOOPING))) {
if (!(sound->field_40 & SOUND_FLAG_SOUND_IS_PAUSED) && (sound->field_44 & 0x02)) {
if ((sound->soundFlags & SOUND_FLAG_0x80) == 0 && (status & (AUDIO_ENGINE_SOUND_BUFFER_STATUS_PLAYING | AUDIO_ENGINE_SOUND_BUFFER_STATUS_LOOPING)) != 0) {
if ((sound->statusFlags & SOUND_STATUS_IS_PAUSED) == 0 && (sound->type & SOUND_TYPE_STREAMING) != 0) {
_refreshSoundBuffers(sound);
}
} else if (!(sound->field_40 & SOUND_FLAG_SOUND_IS_PAUSED)) {
} else if ((sound->statusFlags & SOUND_STATUS_IS_PAUSED) == 0) {
if (sound->callback != NULL) {
sound->callback(sound->callbackUserData, 1);
sound->callback = NULL;
}
if (sound->field_44 & 0x04) {
if ((sound->type & SOUND_TYPE_FIRE_AND_FORGET) != 0) {
sound->callback = NULL;
soundDelete(sound);
} else {
sound->field_40 |= SOUND_FLAG_SOUND_IS_DONE;
sound->statusFlags |= SOUND_STATUS_DONE;
if (sound->field_40 & SOUND_FLAG_SOUND_IS_PLAYING) {
if ((sound->statusFlags & SOUND_STATUS_IS_PLAYING) != 0) {
--_numSounds;
}
soundStop(sound);
sound->field_40 &= ~(SOUND_FLAG_SOUND_IS_DONE | SOUND_FLAG_SOUND_IS_PLAYING);
sound->statusFlags &= ~(SOUND_STATUS_DONE | SOUND_STATUS_IS_PLAYING);
}
}
@ -833,7 +839,7 @@ bool soundIsPlaying(Sound* sound)
return false;
}
return (sound->field_40 & SOUND_FLAG_SOUND_IS_PLAYING) != 0;
return (sound->statusFlags & SOUND_STATUS_IS_PLAYING) != 0;
}
// 0x4ADAC4
@ -849,7 +855,7 @@ bool _soundDone(Sound* sound)
return false;
}
return sound->field_40 & 1;
return (sound->statusFlags & SOUND_STATUS_DONE) != 0;
}
// 0x4ADB44
@ -865,11 +871,11 @@ bool soundIsPaused(Sound* sound)
return false;
}
return (sound->field_40 & SOUND_FLAG_SOUND_IS_PAUSED) != 0;
return (sound->statusFlags & SOUND_STATUS_IS_PAUSED) != 0;
}
// 0x4ADBC4
int _soundType(Sound* sound, int a2)
int _soundType(Sound* sound, int type)
{
if (!gSoundInitialized) {
gSoundLastError = SOUND_NOT_INITIALIZED;
@ -881,7 +887,7 @@ int _soundType(Sound* sound, int a2)
return 0;
}
return sound->field_44 & a2;
return sound->type & type;
}
// 0x4ADC04
@ -898,7 +904,7 @@ int soundGetDuration(Sound* sound)
}
int bytesPerSec = sound->bitsPerSample / 8 * sound->rate;
int v3 = sound->field_60;
int v3 = sound->fileSize;
int v4 = v3 % bytesPerSec;
int result = v3 / bytesPerSec;
if (v4 != 0) {
@ -909,7 +915,7 @@ int soundGetDuration(Sound* sound)
}
// 0x4ADD00
int soundSetLooping(Sound* sound, int a2)
int soundSetLooping(Sound* sound, int loops)
{
if (!gSoundInitialized) {
gSoundLastError = SOUND_NOT_INITIALIZED;
@ -921,14 +927,14 @@ int soundSetLooping(Sound* sound, int a2)
return gSoundLastError;
}
if (a2) {
sound->field_3C |= 0x20;
sound->field_50 = a2;
if (loops != 0) {
sound->soundFlags |= SOUND_LOOPING;
sound->loops = loops;
} else {
sound->field_50 = 0;
sound->loops = 0;
sound->field_58 = -1;
sound->field_54 = 0;
sound->field_3C &= ~(0x20);
sound->soundFlags &= ~SOUND_LOOPING;
}
gSoundLastError = SOUND_NO_ERROR;
@ -1085,12 +1091,12 @@ int soundPause(Sound* sound)
return gSoundLastError;
}
if (!(sound->field_40 & SOUND_FLAG_SOUND_IS_PLAYING)) {
if ((sound->statusFlags & SOUND_STATUS_IS_PLAYING) == 0) {
gSoundLastError = SOUND_NOT_PLAYING;
return gSoundLastError;
}
if (sound->field_40 & SOUND_FLAG_SOUND_IS_PAUSED) {
if ((sound->statusFlags & SOUND_STATUS_IS_PAUSED) != 0) {
gSoundLastError = SOUND_ALREADY_PAUSED;
return gSoundLastError;
}
@ -1101,8 +1107,8 @@ int soundPause(Sound* sound)
return gSoundLastError;
}
sound->field_48 = readPos;
sound->field_40 |= SOUND_FLAG_SOUND_IS_PAUSED;
sound->pausePos = readPos;
sound->statusFlags |= SOUND_STATUS_IS_PAUSED;
return soundStop(sound);
}
@ -1124,24 +1130,24 @@ int soundResume(Sound* sound)
return gSoundLastError;
}
if ((sound->field_40 & SOUND_FLAG_SOUND_IS_PLAYING) != 0) {
if ((sound->statusFlags & SOUND_STATUS_IS_PLAYING) != 0) {
gSoundLastError = SOUND_NOT_PAUSED;
return gSoundLastError;
}
if (!(sound->field_40 & SOUND_FLAG_SOUND_IS_PAUSED)) {
if ((sound->statusFlags & SOUND_STATUS_IS_PAUSED) == 0) {
gSoundLastError = SOUND_NOT_PAUSED;
return gSoundLastError;
}
hr = audioEngineSoundBufferSetCurrentPosition(sound->soundBuffer, sound->field_48);
hr = audioEngineSoundBufferSetCurrentPosition(sound->soundBuffer, sound->pausePos);
if (!hr) {
gSoundLastError = SOUND_UNKNOWN_ERROR;
return gSoundLastError;
}
sound->field_40 &= ~SOUND_FLAG_SOUND_IS_PAUSED;
sound->field_48 = 0;
sound->statusFlags &= ~SOUND_STATUS_IS_PAUSED;
sound->pausePos = 0;
return soundPlay(sound);
}
@ -1194,22 +1200,21 @@ int soundSetFileIO(Sound* sound, SoundOpenProc* openProc, SoundCloseProc* closeP
// 0x4AE378
void soundDeleteInternal(Sound* sound)
{
FadeSound* curr;
Sound* v10;
Sound* v11;
Sound* next;
Sound* prev;
if (sound->field_40 & SOUND_FLAG_SOUND_IS_FADING) {
curr = _fadeHead;
if ((sound->statusFlags & SOUND_STATUS_IS_FADING) != 0) {
FadeSound* fadeSound = _fadeHead;
while (curr != NULL) {
if (sound == curr->sound) {
while (fadeSound != NULL) {
if (sound == fadeSound->sound) {
break;
}
curr = curr->next;
fadeSound = fadeSound->next;
}
_removeFadeSound(curr);
_removeFadeSound(fadeSound);
}
if (sound->soundBuffer != -1) {
@ -1226,23 +1231,23 @@ void soundDeleteInternal(Sound* sound)
sound->soundBuffer = -1;
}
if (sound->field_90 != NULL) {
sound->field_90(sound->field_8C);
if (sound->deleteCallback != NULL) {
sound->deleteCallback(sound->deleteUserData);
}
if (sound->field_20 != NULL) {
gSoundFreeProc(sound->field_20);
sound->field_20 = NULL;
if (sound->data != NULL) {
gSoundFreeProc(sound->data);
sound->data = NULL;
}
v10 = sound->next;
if (v10 != NULL) {
v10->prev = sound->prev;
next = sound->next;
if (next != NULL) {
next->prev = sound->prev;
}
v11 = sound->prev;
if (v11 != NULL) {
v11->next = sound->next;
prev = sound->prev;
if (prev != NULL) {
prev->next = sound->next;
} else {
gSoundListHead = sound->next;
}
@ -1305,23 +1310,23 @@ int _soundGetPosition(Sound* sound)
return gSoundLastError;
}
unsigned int playPos;
unsigned int readPos;
unsigned int writePos;
audioEngineSoundBufferGetCurrentPosition(sound->soundBuffer, &playPos, &writePos);
audioEngineSoundBufferGetCurrentPosition(sound->soundBuffer, &readPos, &writePos);
if ((sound->field_44 & 0x02) != 0) {
if (playPos < sound->field_74) {
playPos += sound->field_64 + sound->field_78 * sound->field_7C - sound->field_74;
if ((sound->type & SOUND_TYPE_STREAMING) != 0) {
if (readPos < sound->lastPosition) {
readPos += sound->numBytesRead + sound->numBuffers * sound->dataSize - sound->lastPosition;
} else {
playPos -= sound->field_74 + sound->field_64;
readPos -= sound->lastPosition + sound->numBytesRead;
}
}
return playPos;
return readPos;
}
// 0x4AE6CC
int _soundSetPosition(Sound* sound, int a2)
int _soundSetPosition(Sound* sound, int pos)
{
if (!gSoundInitialized) {
gSoundLastError = SOUND_NOT_INITIALIZED;
@ -1338,34 +1343,34 @@ int _soundSetPosition(Sound* sound, int a2)
return gSoundLastError;
}
if (sound->field_44 & 0x02) {
int v6 = a2 / sound->field_7C % sound->field_78;
if ((sound->type & SOUND_TYPE_STREAMING) != 0) {
int section = pos / sound->dataSize % sound->numBuffers;
audioEngineSoundBufferSetCurrentPosition(sound->soundBuffer, v6 * sound->field_7C + a2 % sound->field_7C);
audioEngineSoundBufferSetCurrentPosition(sound->soundBuffer, section * sound->dataSize + pos % sound->dataSize);
sound->io.seek(sound->io.fd, v6 * sound->field_7C, SEEK_SET);
int bytes_read = sound->io.read(sound->io.fd, sound->field_20, sound->field_7C);
if (bytes_read < sound->field_7C) {
if (sound->field_44 & 0x02) {
sound->io.seek(sound->io.fd, section * sound->dataSize, SEEK_SET);
int bytesRead = sound->io.read(sound->io.fd, sound->data, sound->dataSize);
if (bytesRead < sound->dataSize) {
if ((sound->type & SOUND_TYPE_STREAMING) != 0) {
sound->io.seek(sound->io.fd, 0, SEEK_SET);
sound->io.read(sound->io.fd, sound->field_20 + bytes_read, sound->field_7C - bytes_read);
sound->io.read(sound->io.fd, sound->data + bytesRead, sound->dataSize - bytesRead);
} else {
memset(sound->field_20 + bytes_read, 0, sound->field_7C - bytes_read);
memset(sound->data + bytesRead, 0, sound->dataSize - bytesRead);
}
}
int v17 = v6 + 1;
sound->field_64 = a2;
int nextSection = section + 1;
sound->numBytesRead = pos;
if (v17 < sound->field_78) {
sound->field_70 = v17;
if (nextSection < sound->numBuffers) {
sound->lastUpdate = nextSection;
} else {
sound->field_70 = 0;
sound->lastUpdate = 0;
}
soundContinue(sound);
} else {
audioEngineSoundBufferSetCurrentPosition(sound->soundBuffer, a2);
audioEngineSoundBufferSetCurrentPosition(sound->soundBuffer, pos);
}
gSoundLastError = SOUND_NO_ERROR;
@ -1387,7 +1392,7 @@ void _removeFadeSound(FadeSound* fadeSound)
return;
}
if (!(fadeSound->sound->field_40 & SOUND_FLAG_SOUND_IS_FADING)) {
if ((fadeSound->sound->statusFlags & SOUND_STATUS_IS_FADING) == 0) {
return;
}
@ -1403,7 +1408,7 @@ void _removeFadeSound(FadeSound* fadeSound)
next->prev = fadeSound->prev;
}
fadeSound->sound->field_40 &= ~SOUND_FLAG_SOUND_IS_FADING;
fadeSound->sound->statusFlags &= ~SOUND_STATUS_IS_FADING;
fadeSound->sound = NULL;
tmp = _fadeFreeList;
@ -1414,34 +1419,34 @@ void _removeFadeSound(FadeSound* fadeSound)
// 0x4AE8B0
void _fadeSounds()
{
FadeSound* ptr;
FadeSound* fadeSound;
ptr = _fadeHead;
while (ptr != NULL) {
if ((ptr->currentVolume > ptr->targetVolume || ptr->currentVolume + ptr->deltaVolume < ptr->targetVolume) && (ptr->currentVolume < ptr->targetVolume || ptr->currentVolume + ptr->deltaVolume > ptr->targetVolume)) {
ptr->currentVolume += ptr->deltaVolume;
soundSetVolume(ptr->sound, ptr->currentVolume);
fadeSound = _fadeHead;
while (fadeSound != NULL) {
if ((fadeSound->currentVolume > fadeSound->targetVolume || fadeSound->currentVolume + fadeSound->deltaVolume < fadeSound->targetVolume) && (fadeSound->currentVolume < fadeSound->targetVolume || fadeSound->currentVolume + fadeSound->deltaVolume > fadeSound->targetVolume)) {
fadeSound->currentVolume += fadeSound->deltaVolume;
soundSetVolume(fadeSound->sound, fadeSound->currentVolume);
} else {
if (ptr->targetVolume == 0) {
if (ptr->field_14) {
soundPause(ptr->sound);
soundSetVolume(ptr->sound, ptr->initialVolume);
if (fadeSound->targetVolume == 0) {
if (fadeSound->pause) {
soundPause(fadeSound->sound);
soundSetVolume(fadeSound->sound, fadeSound->initialVolume);
} else {
if (ptr->sound->field_44 & 0x04) {
soundDelete(ptr->sound);
if ((fadeSound->sound->type & SOUND_TYPE_FIRE_AND_FORGET) != 0) {
soundDelete(fadeSound->sound);
} else {
soundStop(ptr->sound);
soundStop(fadeSound->sound);
ptr->initialVolume = ptr->targetVolume;
ptr->currentVolume = ptr->targetVolume;
ptr->deltaVolume = 0;
fadeSound->initialVolume = fadeSound->targetVolume;
fadeSound->currentVolume = fadeSound->targetVolume;
fadeSound->deltaVolume = 0;
soundSetVolume(ptr->sound, ptr->targetVolume);
soundSetVolume(fadeSound->sound, fadeSound->targetVolume);
}
}
}
_removeFadeSound(ptr);
_removeFadeSound(fadeSound);
}
}
@ -1452,9 +1457,9 @@ void _fadeSounds()
}
// 0x4AE988
int _internalSoundFade(Sound* sound, int duration, int targetVolume, int a4)
int _internalSoundFade(Sound* sound, int duration, int targetVolume, bool pause)
{
FadeSound* ptr;
FadeSound* fadeSound;
if (!_deviceInit) {
gSoundLastError = SOUND_NOT_INITIALIZED;
@ -1466,56 +1471,56 @@ int _internalSoundFade(Sound* sound, int duration, int targetVolume, int a4)
return gSoundLastError;
}
ptr = NULL;
if (sound->field_40 & SOUND_FLAG_SOUND_IS_FADING) {
ptr = _fadeHead;
while (ptr != NULL) {
if (ptr->sound == sound) {
fadeSound = NULL;
if ((sound->statusFlags & SOUND_STATUS_IS_FADING) != 0) {
fadeSound = _fadeHead;
while (fadeSound != NULL) {
if (fadeSound->sound == sound) {
break;
}
ptr = ptr->next;
fadeSound = fadeSound->next;
}
}
if (ptr == NULL) {
if (fadeSound == NULL) {
if (_fadeFreeList != NULL) {
ptr = _fadeFreeList;
fadeSound = _fadeFreeList;
_fadeFreeList = _fadeFreeList->next;
} else {
ptr = (FadeSound*)gSoundMallocProc(sizeof(FadeSound));
fadeSound = (FadeSound*)gSoundMallocProc(sizeof(FadeSound));
}
if (ptr != NULL) {
if (fadeSound != NULL) {
if (_fadeHead != NULL) {
_fadeHead->prev = ptr;
_fadeHead->prev = fadeSound;
}
ptr->sound = sound;
ptr->prev = NULL;
ptr->next = _fadeHead;
_fadeHead = ptr;
fadeSound->sound = sound;
fadeSound->prev = NULL;
fadeSound->next = _fadeHead;
_fadeHead = fadeSound;
}
}
if (ptr == NULL) {
if (fadeSound == NULL) {
gSoundLastError = SOUND_NO_MEMORY_AVAILABLE;
return gSoundLastError;
}
ptr->targetVolume = targetVolume;
ptr->initialVolume = _soundGetVolume(sound);
ptr->currentVolume = ptr->initialVolume;
ptr->field_14 = a4;
fadeSound->targetVolume = targetVolume;
fadeSound->initialVolume = _soundGetVolume(sound);
fadeSound->currentVolume = fadeSound->initialVolume;
fadeSound->pause = pause;
// TODO: Check.
ptr->deltaVolume = 8 * (125 * (targetVolume - ptr->initialVolume)) / (40 * duration);
fadeSound->deltaVolume = 8 * (125 * (targetVolume - fadeSound->initialVolume)) / (40 * duration);
sound->field_40 |= SOUND_FLAG_SOUND_IS_FADING;
sound->statusFlags |= SOUND_STATUS_IS_FADING;
bool shouldPlay;
if (gSoundInitialized) {
if (sound->soundBuffer != -1) {
shouldPlay = (sound->field_40 & SOUND_FLAG_SOUND_IS_PLAYING) == 0;
shouldPlay = (sound->statusFlags & SOUND_STATUS_IS_PLAYING) == 0;
} else {
gSoundLastError = SOUND_NO_SOUND;
shouldPlay = true;
@ -1547,7 +1552,7 @@ int _internalSoundFade(Sound* sound, int duration, int targetVolume, int a4)
// 0x4AEB0C
int _soundFade(Sound* sound, int duration, int targetVolume)
{
return _internalSoundFade(sound, duration, targetVolume, 0);
return _internalSoundFade(sound, duration, targetVolume, false);
}
// 0x4AEB54

View File

@ -65,50 +65,66 @@ typedef struct SoundFileIO {
int fd;
} SoundFileIO;
typedef enum SoundType {
SOUND_TYPE_MEMORY = 0x01,
SOUND_TYPE_STREAMING = 0x02,
SOUND_TYPE_FIRE_AND_FORGET = 0x04,
SOUND_TYPE_INFINITE = 0x10,
SOUND_TYPE_0x20 = 0x20,
} SoundType;
typedef enum SoundFlags {
SOUND_FLAG_0x02 = 0x02,
SOUND_FLAG_0x04 = 0x04,
SOUND_16BIT = 0x08,
SOUND_8BIT = 0x10,
SOUND_LOOPING = 0x20,
SOUND_FLAG_0x80 = 0x80,
SOUND_FLAG_0x100 = 0x100,
SOUND_FLAG_0x200 = 0x200,
} SoundFlags;
typedef void SoundCallback(void* userData, int a2);
typedef void SoundDeleteCallback(void* userData);
typedef struct Sound {
SoundFileIO io;
unsigned char* field_20;
unsigned char* data;
int soundBuffer;
int bitsPerSample;
int channels;
int rate;
int field_3C;
// flags
int field_40;
int field_44;
// pause pos
int field_48;
int soundFlags;
int statusFlags;
int type;
int pausePos;
int volume;
int field_50;
int loops;
int field_54;
int field_58;
int field_5C;
// file size
int field_60;
int field_64;
int minReadBuffer;
int fileSize;
int numBytesRead;
int field_68;
int readLimit;
int field_70;
unsigned int field_74;
int field_78;
int field_7C;
int field_80;
// callback data
int lastUpdate;
unsigned int lastPosition;
int numBuffers;
int dataSize;
void* userData;
void* callbackUserData;
SoundCallback* callback;
int field_8C;
void (*field_90)(int);
void* deleteUserData;
SoundDeleteCallback* deleteCallback;
struct Sound* next;
struct Sound* prev;
} Sound;
void soundSetMemoryProcs(MallocProc* mallocProc, ReallocProc* reallocProc, FreeProc* freeProc);
const char* soundGetErrorDescription(int err);
int soundInit(int a1, int a2, int a3, int a4, int rate);
int soundInit(int a1, int numBuffers, int a3, int dataSize, int rate);
void soundExit();
Sound* soundAllocate(int a1, int a2);
Sound* soundAllocate(int type, int soundFlags);
int soundLoad(Sound* sound, char* filePath);
int soundPlay(Sound* sound);
int soundStop(Sound* sound);
@ -116,9 +132,9 @@ int soundDelete(Sound* sound);
bool soundIsPlaying(Sound* sound);
bool _soundDone(Sound* sound);
bool soundIsPaused(Sound* sound);
int _soundType(Sound* sound, int a2);
int _soundType(Sound* sound, int type);
int soundGetDuration(Sound* sound);
int soundSetLooping(Sound* sound, int a2);
int soundSetLooping(Sound* sound, int loops);
int _soundVolumeHMItoDirectSound(int a1);
int soundSetVolume(Sound* sound, int volume);
int soundSetCallback(Sound* sound, SoundCallback* callback, void* userData);
@ -129,7 +145,7 @@ int soundResume(Sound* sound);
int soundSetFileIO(Sound* sound, SoundOpenProc* openProc, SoundCloseProc* closeProc, SoundReadProc* readProc, SoundWriteProc* writeProc, SoundSeekProc* seekProc, SoundTellProc* tellProc, SoundFileLengthProc* fileLengthProc);
int _soundSetMasterVolume(int value);
int _soundGetPosition(Sound* sound);
int _soundSetPosition(Sound* sound, int a2);
int _soundSetPosition(Sound* sound, int pos);
int _soundFade(Sound* sound, int duration, int targetVolume);
void soundDeleteAll();
void soundContinueAll();