mirror of
https://github.com/HarbourMasters/Starship.git
synced 2025-01-23 05:25:01 +03:00
Another attempt at this thing
This commit is contained in:
parent
adc561891a
commit
2354ee76a3
8
assets/yaml/us/rev1/ast_audio.yaml
Normal file
8
assets/yaml/us/rev1/ast_audio.yaml
Normal file
@ -0,0 +1,8 @@
|
||||
audio_seq:
|
||||
{ type: BLOB, offset: 0xDEA20, size: 0x3ACF0, symbol: gAudioSeq }
|
||||
|
||||
audio_bank:
|
||||
{ type: BLOB, offset: 0x119710, size: 0x1E020, symbol: gAudioBank }
|
||||
|
||||
audio_table:
|
||||
{ type: BLOB, offset: 0x137730, size: 0x73C580, symbol: gAudioTable }
|
@ -788,7 +788,7 @@ typedef struct {
|
||||
/* 0x01 */ s8 delay;
|
||||
/* 0x02 */ s8 medium;
|
||||
/* 0x04 */ u8* ramAddr;
|
||||
/* 0x08 */ u32 curDevAddr;
|
||||
/* 0x08 */ uintptr_t curDevAddr;
|
||||
/* 0x0C */ u8* curRamAddr;
|
||||
/* 0x10 */ u32 bytesRemaining;
|
||||
/* 0x14 */ u32 chunkSize;
|
||||
@ -803,7 +803,7 @@ typedef struct {
|
||||
/* 0x00 */ u8 medium;
|
||||
/* 0x01 */ u8 seqOrFontId;
|
||||
/* 0x02 */ u8 instId;
|
||||
/* 0x04 */ u32 curDevAddr;
|
||||
/* 0x04 */ uintptr_t curDevAddr;
|
||||
/* 0x08 */ u8* curRamAddr;
|
||||
/* 0x0C */ u8* ramAddr;
|
||||
/* 0x10 */ s32 state;
|
||||
@ -844,7 +844,7 @@ typedef struct {
|
||||
|
||||
typedef struct SampleDma {
|
||||
/* 0x00 */ u8* ramAddr;
|
||||
/* 0x04 */ u32 devAddr;
|
||||
/* 0x04 */ uintptr_t devAddr;
|
||||
/* 0x08 */ u16 sizeUnused;
|
||||
/* 0x0A */ u16 size;
|
||||
/* 0x0C */ u8 unused;
|
||||
@ -885,8 +885,8 @@ typedef struct {
|
||||
typedef struct {
|
||||
/* 0x00 */ s32 sampleBankId1;
|
||||
/* 0x04 */ s32 sampleBankId2;
|
||||
/* 0x08 */ s32 baseAddr1;
|
||||
/* 0x0C */ s32 baseAddr2;
|
||||
/* 0x08 */ uintptr_t baseAddr1;
|
||||
/* 0x0C */ uintptr_t baseAddr2;
|
||||
/* 0x10 */ u32 medium1;
|
||||
/* 0x14 */ u32 medium2;
|
||||
} SampleBankRelocInfo; // size = 0x18
|
||||
@ -1047,7 +1047,7 @@ void* AudioHeap_AllocPersistentSampleCache(s32 size, s32 fontId, uintptr_t sampl
|
||||
void AudioLoad_DecreaseSampleDmaTtls(void);
|
||||
void AudioLoad_ProcessLoads(s32 resetStatus);
|
||||
void AudioLoad_SyncInitSeqPlayer(s32 playerIdx, s32 seqId, s32 arg2);
|
||||
void* AudioLoad_DmaSampleData(u32 devAddr, u32 size, u32 arg2, u8* dmaIndexRef, s32 medium);
|
||||
void* AudioLoad_DmaSampleData(uintptr_t devAddr, u32 size, u32 arg2, u8* dmaIndexRef, s32 medium);
|
||||
void AudioLoad_InitSampleDmaBuffers(s32 numNotes);
|
||||
void AudioLoad_SyncLoadSeqParts(s32 seqId, s32 flags);
|
||||
s32 AudioLoad_SyncLoadInstrument(s32 fontId, s32 instId, s32 drumId);
|
||||
|
@ -1 +1 @@
|
||||
Subproject commit e15b3ab12a696a5fe400185966752f0927200b5a
|
||||
Subproject commit 00c6bcc88286173ce22b8a6656373d3aa5830c62
|
@ -1595,7 +1595,7 @@ void Audio_PlayActiveSfx(u8 bankId) {
|
||||
|
||||
void Audio_KillSfxByBank(u8 bankId) {
|
||||
// LAudioTODO: Stub for now
|
||||
return;
|
||||
// return;
|
||||
|
||||
SfxBankEntry* entry;
|
||||
u8 next = sSfxBanks[bankId][0].next;
|
||||
@ -1618,7 +1618,8 @@ void Audio_KillSfxByBank(u8 bankId) {
|
||||
|
||||
void Audio_StopSfxByBankAndSource(u8 bankId, f32* sfxSource) {
|
||||
// LAudioTODO: Stub for now
|
||||
return;
|
||||
// return;
|
||||
|
||||
SfxBankEntry* entry;
|
||||
u8 curIndex = 0;
|
||||
u8 nextIndex = sSfxBanks[bankId][0].next;
|
||||
@ -1641,7 +1642,8 @@ void Audio_StopSfxByBankAndSource(u8 bankId, f32* sfxSource) {
|
||||
|
||||
void Audio_KillSfxByBankAndSource(u8 bankId, f32* sfxSource) {
|
||||
// LAudioTODO: Stub for now
|
||||
return;
|
||||
// return;
|
||||
|
||||
SfxBankEntry cmp;
|
||||
|
||||
Audio_StopSfxByBankAndSource(bankId, sfxSource);
|
||||
@ -1652,7 +1654,8 @@ void Audio_KillSfxByBankAndSource(u8 bankId, f32* sfxSource) {
|
||||
|
||||
void Audio_KillSfxBySource(f32* sfxSource) {
|
||||
// LAudioTODO: Stub for now
|
||||
return;
|
||||
// return;
|
||||
|
||||
u8 i;
|
||||
SfxBankEntry cmp;
|
||||
|
||||
@ -1665,7 +1668,7 @@ void Audio_KillSfxBySource(f32* sfxSource) {
|
||||
|
||||
void Audio_KillSfxBySourceAndId(f32* sfxSource, u32 sfxId) {
|
||||
// LAudioTODO: Stub for now
|
||||
return;
|
||||
// return;
|
||||
|
||||
u32 bankId = SFX_BANK(sfxId);
|
||||
u8 next = sSfxBanks[bankId][0].next;
|
||||
@ -1695,7 +1698,8 @@ void Audio_KillSfxBySourceAndId(f32* sfxSource, u32 sfxId) {
|
||||
|
||||
void Audio_KillSfxByTokenAndId(u8 token, u32 sfxId) {
|
||||
// LAudioTODO: Stub for now
|
||||
return;
|
||||
// return;
|
||||
|
||||
u32 bankId = SFX_BANK(sfxId);
|
||||
u8 next = sSfxBanks[bankId][0].next;
|
||||
u8 current = 0;
|
||||
@ -1723,7 +1727,8 @@ void Audio_KillSfxByTokenAndId(u8 token, u32 sfxId) {
|
||||
|
||||
void Audio_KillSfxById(u32 sfxId) {
|
||||
// LAudioTODO: Stub for now
|
||||
return;
|
||||
// return;
|
||||
|
||||
u32 bankId = SFX_BANK(sfxId);
|
||||
u8 next = sSfxBanks[bankId][0].next;
|
||||
u8 current = 0;
|
||||
@ -1864,7 +1869,8 @@ void Audio_ClearVoice(void) {
|
||||
|
||||
s32 Audio_GetCurrentVoice(void) {
|
||||
// LAudioTODO: Stub for now
|
||||
return 0;
|
||||
// return 0;
|
||||
|
||||
if (!IS_SEQUENCE_CHANNEL_VALID(gSeqPlayers[SEQ_PLAYER_VOICE].channels[15])) {
|
||||
return 0;
|
||||
}
|
||||
@ -1880,7 +1886,8 @@ s32 Audio_GetCurrentVoice(void) {
|
||||
|
||||
s32 Audio_GetCurrentVoiceStatus(void) {
|
||||
// LAudioTODO: Stub for now
|
||||
return 1;
|
||||
// return 1;
|
||||
|
||||
SequenceChannel* channel = gSeqPlayers[SEQ_PLAYER_VOICE].channels[15];
|
||||
SequenceLayer* layer = channel->layers[0];
|
||||
|
||||
|
@ -147,8 +147,8 @@ void* AudioHeap_Alloc(AudioAllocPool* pool, u32 size) {
|
||||
}
|
||||
|
||||
void AudioHeap_InitPool(AudioAllocPool* pool, void* ramAddr, u32 size) {
|
||||
pool->curRamAddr = pool->startRamAddr = (u8*) ALIGN16((u32) ramAddr);
|
||||
pool->size = size - ((u32) ramAddr & 0xF);
|
||||
pool->curRamAddr = pool->startRamAddr = (u8*) ramAddr;
|
||||
pool->size = size - ((uintptr_t) ramAddr & 0xF);
|
||||
pool->numEntries = 0;
|
||||
}
|
||||
|
||||
|
@ -1,6 +1,8 @@
|
||||
#include "sys.h"
|
||||
#include "sf64dma.h"
|
||||
#include "sf64audio_provisional.h"
|
||||
#include "assets/ast_audio.h"
|
||||
#include "port/Engine.h"
|
||||
|
||||
s32 D_80146D80;
|
||||
s32 PAD_80146D88[2];
|
||||
@ -14,23 +16,23 @@ void* AudioLoad_SyncLoad(u32 tableType, u32 id, s32* didAllocate);
|
||||
s32 AudioLoad_GetLoadTableIndex(s32 tableType, u32 entryId);
|
||||
void* AudioLoad_SearchCaches(s32 tableType, s32 id);
|
||||
AudioTable* AudioLoad_GetLoadTable(s32 tableType);
|
||||
void AudioLoad_SyncDma(u32 devAddr, u8* ramAddr, u32 size, s32 medium);
|
||||
void AudioLoad_SyncDmaUnkMedium(u32 devAddr, u8* ramAddr, u32 size, s32 unkMediumParam);
|
||||
s32 AudioLoad_Dma(OSIoMesg* mesg, u32 priority, s32 direction, u32 devAddr, void* ramAddr, u32 size,
|
||||
void AudioLoad_SyncDma(uintptr_t devAddr, u8* ramAddr, u32 size, s32 medium);
|
||||
void AudioLoad_SyncDmaUnkMedium(uintptr_t devAddr, u8* ramAddr, u32 size, s32 unkMediumParam);
|
||||
s32 AudioLoad_Dma(OSIoMesg* mesg, u32 priority, s32 direction, uintptr_t devAddr, void* ramAddr, u32 size,
|
||||
OSMesgQueue* retQueue, s32 medium, const char* dmaType);
|
||||
s32 func_8000FC7C(u32 unkMediumParam, u32* addrPtr);
|
||||
void func_8000FC8C(s32 unkParam2, u32 addr, u8* ramAddr, u32 size);
|
||||
void func_8000FC8C(s32 unkParam2, uintptr_t addr, u8* ramAddr, u32 size);
|
||||
void* AudioLoad_AsyncLoadInner(s32 tableType, s32 id, s32 nChunks, s32 retData, OSMesgQueue* retQueue);
|
||||
Sample* AudioLoad_GetFontSample(s32 fontId, s32 instId);
|
||||
void AudioLoad_ProcessSlowLoads(s32 resetStatus);
|
||||
void AudioLoad_DmaSlowCopy(AudioSlowLoad* slowLoad, s32 size);
|
||||
void AudioLoad_DmaSlowCopyUnkMedium(u32 devAddr, u8* ramAddr, u32 size, s32 unkMediumParam);
|
||||
AudioAsyncLoad* AudioLoad_StartAsyncLoad(u32 devAddr, u8* ramAddr, u32 size, s32 medium, s32 nChunks,
|
||||
void AudioLoad_DmaSlowCopyUnkMedium(uintptr_t devAddr, u8* ramAddr, u32 size, s32 unkMediumParam);
|
||||
AudioAsyncLoad* AudioLoad_StartAsyncLoad(uintptr_t devAddr, u8* ramAddr, u32 size, s32 medium, s32 nChunks,
|
||||
OSMesgQueue* retQueue, u32 retMesg);
|
||||
void AudioLoad_ProcessAsyncLoads(s32 resetStatus);
|
||||
void AudioLoad_ProcessAsyncLoad(AudioAsyncLoad* asyncLoad, s32 resetStatus);
|
||||
void AudioLoad_AsyncDma(AudioAsyncLoad* asyncLoad, u32 size);
|
||||
void AudioLoad_AsyncDmaUnkMedium(u32 devAddr, u8* ramAddr, u32 size, s32 unkMediumParam);
|
||||
void AudioLoad_AsyncDmaUnkMedium(uintptr_t devAddr, u8* ramAddr, u32 size, s32 unkMediumParam);
|
||||
void AudioLoad_RelocateSample(TunedSample* tSample, u32 fontDataAddr, SampleBankRelocInfo* relocInfo);
|
||||
s32 AudioLoad_RelocateFontAndPreloadSamples(s32 fontId, u32 fontDataAddr, SampleBankRelocInfo* relocData, s32 isAsync);
|
||||
s32 AudioLoad_ProcessSamplePreloads(s32 resetStatus);
|
||||
@ -67,12 +69,12 @@ void AudioLoad_DecreaseSampleDmaTtls(void) {
|
||||
|
||||
static const char devstr00[] = "CAUTION:WAVE CACHE FULL %d";
|
||||
|
||||
void* AudioLoad_DmaSampleData(u32 devAddr, u32 size, u32 arg2, u8* dmaIndexRef, s32 medium) {
|
||||
void* AudioLoad_DmaSampleData(uintptr_t devAddr, u32 size, u32 arg2, u8* dmaIndexRef, s32 medium) {
|
||||
u32 i;
|
||||
SampleDma* dma;
|
||||
bool hasDma = false;
|
||||
s32 bufferPos;
|
||||
u32 dmaDevAddr;
|
||||
uintptr_t dmaDevAddr;
|
||||
s32 sp38;
|
||||
|
||||
if ((arg2 != 0) || (*dmaIndexRef >= gSampleDmaListSize1)) {
|
||||
@ -676,7 +678,7 @@ void AudioLoad_RelocateFont(s32 fontId, u32 fontBaseAddr, void* relocData) {
|
||||
gSoundFontList[fontId].instruments = (u32) &fontDataPtrs[1];
|
||||
}
|
||||
|
||||
void AudioLoad_SyncDma(u32 devAddr, u8* ramAddr, u32 size, s32 medium) {
|
||||
void AudioLoad_SyncDma(uintptr_t devAddr, u8* ramAddr, u32 size, s32 medium) {
|
||||
size = ALIGN16(size);
|
||||
|
||||
osInvalDCache(ramAddr, size);
|
||||
@ -698,8 +700,8 @@ void AudioLoad_SyncDma(u32 devAddr, u8* ramAddr, u32 size, s32 medium) {
|
||||
}
|
||||
}
|
||||
|
||||
void AudioLoad_SyncDmaUnkMedium(u32 devAddr, u8* ramAddr, u32 size, s32 unkMediumParam) {
|
||||
s32 addr = devAddr;
|
||||
void AudioLoad_SyncDmaUnkMedium(uintptr_t devAddr, u8* ramAddr, u32 size, s32 unkMediumParam) {
|
||||
uintptr_t addr = devAddr;
|
||||
|
||||
osInvalDCache(ramAddr, size);
|
||||
func_8000FC8C(func_8000FC7C(unkMediumParam, &addr), addr, ramAddr, size);
|
||||
@ -711,20 +713,20 @@ static const char devstr24[] = "Load Bank BG, Type %d , ID %d\n";
|
||||
static const char devstr25[] = "get auto\n";
|
||||
static const char devstr26[] = "get s-auto %x\n";
|
||||
|
||||
s32 AudioLoad_Dma(OSIoMesg* mesg, u32 priority, s32 direction, u32 devAddr, void* ramAddr, u32 size,
|
||||
s32 AudioLoad_Dma(OSIoMesg* mesg, u32 priority, s32 direction, uintptr_t devAddr, void* ramAddr, u32 size,
|
||||
OSMesgQueue* retQueue, s32 medium, const char* dmaType) {
|
||||
OSPiHandle* handle;
|
||||
|
||||
switch (medium) {
|
||||
case MEDIUM_CART:
|
||||
handle = osCartRomInit();
|
||||
break;
|
||||
case MEDIUM_DISK_DRIVE:
|
||||
// handle = osDriveRomInit();
|
||||
break;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
// switch (medium) {
|
||||
// case MEDIUM_CART:
|
||||
// handle = osCartRomInit();
|
||||
// break;
|
||||
// case MEDIUM_DISK_DRIVE:
|
||||
// // handle = osDriveRomInit();
|
||||
// break;
|
||||
// default:
|
||||
// return 0;
|
||||
// }
|
||||
|
||||
if (size % 16) {
|
||||
size = ALIGN16(size);
|
||||
@ -737,7 +739,8 @@ s32 AudioLoad_Dma(OSIoMesg* mesg, u32 priority, s32 direction, u32 devAddr, void
|
||||
mesg->size = size;
|
||||
|
||||
handle->transferInfo.cmdType = 2;
|
||||
osEPiStartDma(handle, mesg, direction);
|
||||
// osEPiStartDma(handle, mesg, direction);
|
||||
memcpy(ramAddr, (void*) devAddr, size);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -746,7 +749,7 @@ s32 func_8000FC7C(u32 unkMediumParam, u32* addrPtr) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
void func_8000FC8C(s32 unkParam2, u32 addr, u8* ramAddr, u32 size) {
|
||||
void func_8000FC8C(s32 unkParam2, uintptr_t addr, u8* ramAddr, u32 size) {
|
||||
}
|
||||
|
||||
void AudioLoad_SyncLoadSimple(u32 tableType, u32 id) {
|
||||
@ -890,7 +893,7 @@ void AudioLoad_Init(void) {
|
||||
}
|
||||
|
||||
clearContext = gAudioContextStart;
|
||||
dwordsLeft = ((u32) gAudioContextEnd - (u32) gAudioContextStart) / 8;
|
||||
dwordsLeft = ((uintptr_t) gAudioContextEnd - (uintptr_t) gAudioContextStart) / 8;
|
||||
for (; dwordsLeft >= 0; dwordsLeft--) {
|
||||
*clearContext++ = 0;
|
||||
}
|
||||
@ -938,9 +941,9 @@ void AudioLoad_Init(void) {
|
||||
gSeqFontTable = gSeqFontTableInit;
|
||||
gNumSequences = gSequenceTable->base.numEntries;
|
||||
|
||||
AudioLoad_InitTable(gSequenceTable, SEGMENT_ROM_START(audio_seq), gSequenceMedium);
|
||||
AudioLoad_InitTable(gSoundFontTable, SEGMENT_ROM_START(audio_bank), gSoundFontMedium);
|
||||
AudioLoad_InitTable(gSampleBankTable, SEGMENT_ROM_START(audio_table), gSampleBankMedium);
|
||||
AudioLoad_InitTable(gSequenceTable, LOAD_ASSET(gAudioSeq), gSequenceMedium);
|
||||
AudioLoad_InitTable(gSoundFontTable, LOAD_ASSET(gAudioBank), gSoundFontMedium);
|
||||
AudioLoad_InitTable(gSampleBankTable, LOAD_ASSET(gAudioTable), gSampleBankMedium);
|
||||
|
||||
numFonts = gSoundFontTable->base.numEntries;
|
||||
|
||||
@ -1104,14 +1107,14 @@ static const char devstr45[] = "===Block BG end\n";
|
||||
static const char devstr46[] = "Retcode %x\n";
|
||||
static const char devstr47[] = "Other Type: Not Write ID.\n";
|
||||
|
||||
void AudioLoad_DmaSlowCopyUnkMedium(u32 devAddr, u8* ramAddr, u32 size, s32 unkMediumParam) {
|
||||
s32 addr = devAddr;
|
||||
void AudioLoad_DmaSlowCopyUnkMedium(uintptr_t devAddr, u8* ramAddr, u32 size, s32 unkMediumParam) {
|
||||
uintptr_t addr = devAddr;
|
||||
|
||||
osInvalDCache(ramAddr, size);
|
||||
func_8000FC8C(func_8000FC7C(unkMediumParam, &addr), addr, ramAddr, size);
|
||||
}
|
||||
|
||||
AudioAsyncLoad* AudioLoad_StartAsyncLoad(u32 devAddr, u8* ramAddr, u32 size, s32 medium, s32 nChunks,
|
||||
AudioAsyncLoad* AudioLoad_StartAsyncLoad(uintptr_t devAddr, u8* ramAddr, u32 size, s32 medium, s32 nChunks,
|
||||
OSMesgQueue* retQueue, u32 retMesg) {
|
||||
AudioAsyncLoad* asyncLoad;
|
||||
s32 i;
|
||||
@ -1264,8 +1267,8 @@ void AudioLoad_AsyncDma(AudioAsyncLoad* asyncLoad, u32 size) {
|
||||
asyncLoad->medium, "BGCOPY");
|
||||
}
|
||||
|
||||
void AudioLoad_AsyncDmaUnkMedium(u32 devAddr, u8* ramAddr, u32 size, s32 unkMediumParam) {
|
||||
s32 addr = devAddr;
|
||||
void AudioLoad_AsyncDmaUnkMedium(uintptr_t devAddr, u8* ramAddr, u32 size, s32 unkMediumParam) {
|
||||
uintptr_t addr = devAddr;
|
||||
|
||||
osInvalDCache(ramAddr, size);
|
||||
func_8000FC8C(func_8000FC7C(unkMediumParam, &addr), addr, ramAddr, size);
|
||||
|
@ -1,5 +1,6 @@
|
||||
#include "sys.h"
|
||||
#include "sf64audio_provisional.h"
|
||||
#include "audio/mixer.h"
|
||||
|
||||
s32 D_80145D40; // unused
|
||||
|
||||
|
@ -39,7 +39,74 @@ static const char devstr12[] = "Undefined Port Command %d\n";
|
||||
static const char devstr13[] = "specchg conjunction error (Msg:%d Cur:%d)\n";
|
||||
static const char devstr14[] = "Error : Queue is not empty ( %x ) \n";
|
||||
|
||||
SPTask* AudioThread_CreateTask(void) {
|
||||
void AudioThread_CreateNextAudioBuffer(s16 *samples, u32 num_samples) {
|
||||
static s32 gMaxAbiCmdCnt = 128;
|
||||
static SPTask* gWaitingAudioTask = NULL;
|
||||
u32 sp54;
|
||||
s32 sp50;
|
||||
s32 sp4C;
|
||||
s32 pad48;
|
||||
OSTask_t* task;
|
||||
u16* sp40;
|
||||
s32 pad3C;
|
||||
OSMesg sp38;
|
||||
OSMesg sp34;
|
||||
s32 pad30;
|
||||
gAudioTaskCountQ++;
|
||||
if ((gAudioTaskCountQ % gAudioBufferParams.count) != 0) {
|
||||
return;
|
||||
}
|
||||
osSendMesg(gAudioTaskStartQueue, OS_MESG_32(gAudioTaskCountQ), 0);
|
||||
gAudioTaskIndexQ ^= 1;
|
||||
gCurAiBuffIndex++;
|
||||
gCurAiBuffIndex %= 3;
|
||||
sp4C = (gCurAiBuffIndex + 1) % 3;
|
||||
sp54 = osAiGetLength() >> 2;
|
||||
if ((gAudioResetTimer < 16) && (gAiBuffLengths[sp4C] != 0)) {
|
||||
osAiSetNextBuffer(gAiBuffers[sp4C], gAiBuffLengths[sp4C] * 4);
|
||||
}
|
||||
if (gCurAudioFrameDmaCount && gCurAudioFrameDmaCount) {}
|
||||
gCurAudioFrameDmaCount = 0;
|
||||
AudioLoad_DecreaseSampleDmaTtls();
|
||||
AudioLoad_ProcessLoads(gAudioResetStep);
|
||||
if (osRecvMesg(&gAudioTaskMesgQueue, &sp38, 0) != -1) {
|
||||
if (gAudioResetStep == 0) {
|
||||
gAudioResetStep = 5;
|
||||
}
|
||||
gAudioSpecId = sp38.data32;
|
||||
}
|
||||
if ((gAudioResetStep != 0) && (AudioHeap_ResetStep() == 0)) {
|
||||
if (gAudioResetStep == 0) {
|
||||
osSendMesg(gAudioResetQueue, OS_MESG_32((s32) gAudioSpecId), 0);
|
||||
}
|
||||
gWaitingAudioTask = NULL;
|
||||
return;
|
||||
}
|
||||
if (gAudioResetTimer > 16) {
|
||||
return;
|
||||
}
|
||||
if (gAudioResetTimer != 0) {
|
||||
gAudioResetTimer++;
|
||||
}
|
||||
gAudioCurTask = &gAudioRspTasks[gAudioTaskIndexQ];
|
||||
gCurAbiCmdBuffer = gAbiCmdBuffs[gAudioTaskIndexQ];
|
||||
sp4C = gCurAiBuffIndex;
|
||||
sp40 = gAiBuffers[sp4C];
|
||||
gAiBuffLengths[sp4C] = num_samples;
|
||||
if (gAiBuffLengths[sp4C] < gAudioBufferParams.minAiBufferLength) {
|
||||
gAiBuffLengths[sp4C] = gAudioBufferParams.minAiBufferLength;
|
||||
}
|
||||
if (gAiBuffLengths[sp4C] > gAudioBufferParams.maxAiBufferLength) {
|
||||
gAiBuffLengths[sp4C] = gAudioBufferParams.maxAiBufferLength;
|
||||
}
|
||||
while (osRecvMesg(gThreadCmdProcQueue, &sp34, 0) != -1) {
|
||||
AudioThread_ProcessCmds(sp34.data32);
|
||||
}
|
||||
gCurAbiCmdBuffer = func_80009B64(gCurAbiCmdBuffer, &sp50, samples, num_samples);
|
||||
gAudioRandom = osGetCount() * (gAudioRandom + gAudioTaskCountQ);
|
||||
}
|
||||
|
||||
SPTask* AudioThread_CreateTask() {
|
||||
static s32 gMaxAbiCmdCnt = 128;
|
||||
static SPTask* gWaitingAudioTask = NULL;
|
||||
u32 aiSamplesLeft;
|
||||
|
527
src/audio/mixer.c
Normal file
527
src/audio/mixer.c
Normal file
@ -0,0 +1,527 @@
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "mixer.h"
|
||||
|
||||
#ifndef __clang__
|
||||
#pragma GCC optimize ("unroll-loops")
|
||||
#endif
|
||||
|
||||
#define ROUND_UP_64(v) (((v) + 63) & ~63)
|
||||
#define ROUND_UP_32(v) (((v) + 31) & ~31)
|
||||
#define ROUND_UP_16(v) (((v) + 15) & ~15)
|
||||
#define ROUND_UP_8(v) (((v) + 7) & ~7)
|
||||
#define ROUND_DOWN_16(v) ((v) & ~0xf)
|
||||
|
||||
#define DMEM_BUF_SIZE (0x1000 - 0x3C0 - 0x40)
|
||||
#define BUF_U8(a) (rspa.buf.as_u8 + ((a) - 0x3C0))
|
||||
#define BUF_S16(a) (rspa.buf.as_s16 + ((a) - 0x3C0) / sizeof(int16_t))
|
||||
|
||||
static struct {
|
||||
uint16_t in;
|
||||
uint16_t out;
|
||||
uint16_t nbytes;
|
||||
|
||||
uint16_t vol[2];
|
||||
uint16_t rate[2];
|
||||
uint16_t vol_wet;
|
||||
uint16_t rate_wet;
|
||||
|
||||
ADPCM_STATE *adpcm_loop_state;
|
||||
|
||||
int16_t adpcm_table[8][2][8];
|
||||
|
||||
uint16_t filter_count;
|
||||
int16_t filter[8];
|
||||
|
||||
union {
|
||||
int16_t as_s16[DMEM_BUF_SIZE / sizeof(int16_t)];
|
||||
uint8_t as_u8[DMEM_BUF_SIZE];
|
||||
} buf;
|
||||
} rspa;
|
||||
|
||||
static int16_t resample_table[64][4] = {
|
||||
{0x0c39, 0x66ad, 0x0d46, 0xffdf}, {0x0b39, 0x6696, 0x0e5f, 0xffd8},
|
||||
{0x0a44, 0x6669, 0x0f83, 0xffd0}, {0x095a, 0x6626, 0x10b4, 0xffc8},
|
||||
{0x087d, 0x65cd, 0x11f0, 0xffbf}, {0x07ab, 0x655e, 0x1338, 0xffb6},
|
||||
{0x06e4, 0x64d9, 0x148c, 0xffac}, {0x0628, 0x643f, 0x15eb, 0xffa1},
|
||||
{0x0577, 0x638f, 0x1756, 0xff96}, {0x04d1, 0x62cb, 0x18cb, 0xff8a},
|
||||
{0x0435, 0x61f3, 0x1a4c, 0xff7e}, {0x03a4, 0x6106, 0x1bd7, 0xff71},
|
||||
{0x031c, 0x6007, 0x1d6c, 0xff64}, {0x029f, 0x5ef5, 0x1f0b, 0xff56},
|
||||
{0x022a, 0x5dd0, 0x20b3, 0xff48}, {0x01be, 0x5c9a, 0x2264, 0xff3a},
|
||||
{0x015b, 0x5b53, 0x241e, 0xff2c}, {0x0101, 0x59fc, 0x25e0, 0xff1e},
|
||||
{0x00ae, 0x5896, 0x27a9, 0xff10}, {0x0063, 0x5720, 0x297a, 0xff02},
|
||||
{0x001f, 0x559d, 0x2b50, 0xfef4}, {0xffe2, 0x540d, 0x2d2c, 0xfee8},
|
||||
{0xffac, 0x5270, 0x2f0d, 0xfedb}, {0xff7c, 0x50c7, 0x30f3, 0xfed0},
|
||||
{0xff53, 0x4f14, 0x32dc, 0xfec6}, {0xff2e, 0x4d57, 0x34c8, 0xfebd},
|
||||
{0xff0f, 0x4b91, 0x36b6, 0xfeb6}, {0xfef5, 0x49c2, 0x38a5, 0xfeb0},
|
||||
{0xfedf, 0x47ed, 0x3a95, 0xfeac}, {0xfece, 0x4611, 0x3c85, 0xfeab},
|
||||
{0xfec0, 0x4430, 0x3e74, 0xfeac}, {0xfeb6, 0x424a, 0x4060, 0xfeaf},
|
||||
{0xfeaf, 0x4060, 0x424a, 0xfeb6}, {0xfeac, 0x3e74, 0x4430, 0xfec0},
|
||||
{0xfeab, 0x3c85, 0x4611, 0xfece}, {0xfeac, 0x3a95, 0x47ed, 0xfedf},
|
||||
{0xfeb0, 0x38a5, 0x49c2, 0xfef5}, {0xfeb6, 0x36b6, 0x4b91, 0xff0f},
|
||||
{0xfebd, 0x34c8, 0x4d57, 0xff2e}, {0xfec6, 0x32dc, 0x4f14, 0xff53},
|
||||
{0xfed0, 0x30f3, 0x50c7, 0xff7c}, {0xfedb, 0x2f0d, 0x5270, 0xffac},
|
||||
{0xfee8, 0x2d2c, 0x540d, 0xffe2}, {0xfef4, 0x2b50, 0x559d, 0x001f},
|
||||
{0xff02, 0x297a, 0x5720, 0x0063}, {0xff10, 0x27a9, 0x5896, 0x00ae},
|
||||
{0xff1e, 0x25e0, 0x59fc, 0x0101}, {0xff2c, 0x241e, 0x5b53, 0x015b},
|
||||
{0xff3a, 0x2264, 0x5c9a, 0x01be}, {0xff48, 0x20b3, 0x5dd0, 0x022a},
|
||||
{0xff56, 0x1f0b, 0x5ef5, 0x029f}, {0xff64, 0x1d6c, 0x6007, 0x031c},
|
||||
{0xff71, 0x1bd7, 0x6106, 0x03a4}, {0xff7e, 0x1a4c, 0x61f3, 0x0435},
|
||||
{0xff8a, 0x18cb, 0x62cb, 0x04d1}, {0xff96, 0x1756, 0x638f, 0x0577},
|
||||
{0xffa1, 0x15eb, 0x643f, 0x0628}, {0xffac, 0x148c, 0x64d9, 0x06e4},
|
||||
{0xffb6, 0x1338, 0x655e, 0x07ab}, {0xffbf, 0x11f0, 0x65cd, 0x087d},
|
||||
{0xffc8, 0x10b4, 0x6626, 0x095a}, {0xffd0, 0x0f83, 0x6669, 0x0a44},
|
||||
{0xffd8, 0x0e5f, 0x6696, 0x0b39}, {0xffdf, 0x0d46, 0x66ad, 0x0c39}
|
||||
};
|
||||
|
||||
static inline int16_t clamp16(int32_t v) {
|
||||
if (v < -0x8000) {
|
||||
return -0x8000;
|
||||
} else if (v > 0x7fff) {
|
||||
return 0x7fff;
|
||||
}
|
||||
return (int16_t)v;
|
||||
}
|
||||
|
||||
static inline int32_t clamp32(int64_t v) {
|
||||
if (v < -0x7fffffff - 1) {
|
||||
return -0x7fffffff - 1;
|
||||
} else if (v > 0x7fffffff) {
|
||||
return 0x7fffffff;
|
||||
}
|
||||
return (int32_t)v;
|
||||
}
|
||||
|
||||
void aClearBufferImpl(uint16_t addr, int nbytes) {
|
||||
nbytes = ROUND_UP_16(nbytes);
|
||||
memset(BUF_U8(addr), 0, nbytes);
|
||||
}
|
||||
|
||||
void aLoadBufferImpl(const void *source_addr, uint16_t dest_addr, uint16_t nbytes) {
|
||||
memcpy(BUF_U8(dest_addr), source_addr, ROUND_DOWN_16(nbytes));
|
||||
}
|
||||
|
||||
void aSaveBufferImpl(uint16_t source_addr, int16_t *dest_addr, uint16_t nbytes) {
|
||||
memcpy(dest_addr, BUF_S16(source_addr), ROUND_DOWN_16(nbytes));
|
||||
}
|
||||
|
||||
void aLoadADPCMImpl(int num_entries_times_16, const int16_t *book_source_addr) {
|
||||
memcpy(rspa.adpcm_table, book_source_addr, num_entries_times_16);
|
||||
}
|
||||
|
||||
void aSetBufferImpl(uint8_t flags, uint16_t in, uint16_t out, uint16_t nbytes) {
|
||||
rspa.in = in;
|
||||
rspa.out = out;
|
||||
rspa.nbytes = nbytes;
|
||||
}
|
||||
|
||||
void aInterleaveImpl(uint16_t dest, uint16_t left, uint16_t right, uint16_t c) {
|
||||
int count = ROUND_UP_8(c) / sizeof(int16_t) / 4;
|
||||
int16_t *l = BUF_S16(left);
|
||||
int16_t *r = BUF_S16(right);
|
||||
int16_t *d = BUF_S16(dest);
|
||||
while (count > 0) {
|
||||
int16_t l0 = *l++;
|
||||
int16_t l1 = *l++;
|
||||
int16_t l2 = *l++;
|
||||
int16_t l3 = *l++;
|
||||
int16_t r0 = *r++;
|
||||
int16_t r1 = *r++;
|
||||
int16_t r2 = *r++;
|
||||
int16_t r3 = *r++;
|
||||
*d++ = l0;
|
||||
*d++ = r0;
|
||||
*d++ = l1;
|
||||
*d++ = r1;
|
||||
*d++ = l2;
|
||||
*d++ = r2;
|
||||
*d++ = l3;
|
||||
*d++ = r3;
|
||||
--count;
|
||||
}
|
||||
}
|
||||
|
||||
void aDMEMMoveImpl(uint16_t in_addr, uint16_t out_addr, int nbytes) {
|
||||
nbytes = ROUND_UP_16(nbytes);
|
||||
memmove(BUF_U8(out_addr), BUF_U8(in_addr), nbytes);
|
||||
}
|
||||
|
||||
void aSetLoopImpl(ADPCM_STATE *adpcm_loop_state) {
|
||||
rspa.adpcm_loop_state = adpcm_loop_state;
|
||||
}
|
||||
|
||||
void aADPCMdecImpl(uint8_t flags, ADPCM_STATE state) {
|
||||
uint8_t *in = BUF_U8(rspa.in);
|
||||
int16_t *out = BUF_S16(rspa.out);
|
||||
int nbytes = ROUND_UP_32(rspa.nbytes);
|
||||
if (flags & A_INIT) {
|
||||
memset(out, 0, 16 * sizeof(int16_t));
|
||||
} else if (flags & A_LOOP) {
|
||||
memcpy(out, rspa.adpcm_loop_state, 16 * sizeof(int16_t));
|
||||
} else {
|
||||
memcpy(out, state, 16 * sizeof(int16_t));
|
||||
}
|
||||
out += 16;
|
||||
|
||||
while (nbytes > 0) {
|
||||
int shift = *in >> 4; // should be in 0..12 or 0..14
|
||||
int table_index = *in++ & 0xf; // should be in 0..7
|
||||
int16_t (*tbl)[8] = rspa.adpcm_table[table_index];
|
||||
int i;
|
||||
|
||||
for (i = 0; i < 2; i++) {
|
||||
int16_t ins[8];
|
||||
int16_t prev1 = out[-1];
|
||||
int16_t prev2 = out[-2];
|
||||
int j, k;
|
||||
if (flags & 4) {
|
||||
for (j = 0; j < 2; j++) {
|
||||
ins[j * 4] = (((*in >> 6) << 30) >> 30) << shift;
|
||||
ins[j * 4 + 1] = ((((*in >> 4) & 0x3) << 30) >> 30) << shift;
|
||||
ins[j * 4 + 2] = ((((*in >> 2) & 0x3) << 30) >> 30) << shift;
|
||||
ins[j * 4 + 3] = (((*in++ & 0x3) << 30) >> 30) << shift;
|
||||
}
|
||||
} else {
|
||||
for (j = 0; j < 4; j++) {
|
||||
ins[j * 2] = (((*in >> 4) << 28) >> 28) << shift;
|
||||
ins[j * 2 + 1] = (((*in++ & 0xf) << 28) >> 28) << shift;
|
||||
}
|
||||
}
|
||||
for (j = 0; j < 8; j++) {
|
||||
int32_t acc = tbl[0][j] * prev2 + tbl[1][j] * prev1 + (ins[j] << 11);
|
||||
for (k = 0; k < j; k++) {
|
||||
acc += tbl[1][((j - k) - 1)] * ins[k];
|
||||
}
|
||||
acc >>= 11;
|
||||
*out++ = clamp16(acc);
|
||||
}
|
||||
}
|
||||
nbytes -= 16 * sizeof(int16_t);
|
||||
}
|
||||
memcpy(state, out - 16, 16 * sizeof(int16_t));
|
||||
}
|
||||
|
||||
void aResampleImpl(uint8_t flags, uint16_t pitch, RESAMPLE_STATE state) {
|
||||
int16_t tmp[16];
|
||||
int16_t *in_initial = BUF_S16(rspa.in);
|
||||
int16_t *in = in_initial;
|
||||
int16_t *out = BUF_S16(rspa.out);
|
||||
int nbytes = ROUND_UP_16(rspa.nbytes);
|
||||
uint32_t pitch_accumulator;
|
||||
int i;
|
||||
int16_t *tbl;
|
||||
int32_t sample;
|
||||
|
||||
if (flags & A_INIT) {
|
||||
memset(tmp, 0, 5 * sizeof(int16_t));
|
||||
} else {
|
||||
memcpy(tmp, state, 16 * sizeof(int16_t));
|
||||
}
|
||||
if (flags & 2) {
|
||||
memcpy(in - 8, tmp + 8, 8 * sizeof(int16_t));
|
||||
in -= tmp[5] / sizeof(int16_t);
|
||||
}
|
||||
in -= 4;
|
||||
pitch_accumulator = (uint16_t)tmp[4];
|
||||
memcpy(in, tmp, 4 * sizeof(int16_t));
|
||||
|
||||
do {
|
||||
for (i = 0; i < 8; i++) {
|
||||
tbl = resample_table[pitch_accumulator * 64 >> 16];
|
||||
sample = ((in[0] * tbl[0] + 0x4000) >> 15) +
|
||||
((in[1] * tbl[1] + 0x4000) >> 15) +
|
||||
((in[2] * tbl[2] + 0x4000) >> 15) +
|
||||
((in[3] * tbl[3] + 0x4000) >> 15);
|
||||
*out++ = clamp16(sample);
|
||||
|
||||
pitch_accumulator += (pitch << 1);
|
||||
in += pitch_accumulator >> 16;
|
||||
pitch_accumulator %= 0x10000;
|
||||
}
|
||||
nbytes -= 8 * sizeof(int16_t);
|
||||
} while (nbytes > 0);
|
||||
|
||||
state[4] = (int16_t)pitch_accumulator;
|
||||
memcpy(state, in, 4 * sizeof(int16_t));
|
||||
i = (in - in_initial + 4) & 7;
|
||||
in -= i;
|
||||
if (i != 0) {
|
||||
i = -8 - i;
|
||||
}
|
||||
state[5] = i;
|
||||
memcpy(state + 8, in, 8 * sizeof(int16_t));
|
||||
}
|
||||
|
||||
void aEnvSetup1Impl(uint8_t initial_vol_wet, uint16_t rate_wet, uint16_t rate_left, uint16_t rate_right) {
|
||||
rspa.vol_wet = (uint16_t)(initial_vol_wet << 8);
|
||||
rspa.rate_wet = rate_wet;
|
||||
rspa.rate[0] = rate_left;
|
||||
rspa.rate[1] = rate_right;
|
||||
}
|
||||
|
||||
void aEnvSetup2Impl(uint16_t initial_vol_left, uint16_t initial_vol_right) {
|
||||
rspa.vol[0] = initial_vol_left;
|
||||
rspa.vol[1] = initial_vol_right;
|
||||
}
|
||||
|
||||
void aEnvMixerImpl(uint16_t in_addr, uint16_t n_samples, bool swap_reverb,
|
||||
bool neg_3, bool neg_2,
|
||||
bool neg_left, bool neg_right,
|
||||
int32_t wet_dry_addr, u32 unk)
|
||||
{
|
||||
int16_t *in = BUF_S16(in_addr);
|
||||
int16_t *dry[2] = {BUF_S16(((wet_dry_addr >> 24) & 0xFF) << 4), BUF_S16(((wet_dry_addr >> 16) & 0xFF) << 4)};
|
||||
int16_t *wet[2] = {BUF_S16(((wet_dry_addr >> 8) & 0xFF) << 4), BUF_S16(((wet_dry_addr) & 0xFF) << 4)};
|
||||
int16_t negs[4] = {neg_left ? -1 : 0, neg_right ? -1 : 0, neg_3 ? -4 : 0, neg_2 ? -2 : 0};
|
||||
int swapped[2] = {swap_reverb ? 1 : 0, swap_reverb ? 0 : 1};
|
||||
int n = ROUND_UP_16(n_samples);
|
||||
|
||||
uint16_t vols[2] = {rspa.vol[0], rspa.vol[1]};
|
||||
uint16_t rates[2] = {rspa.rate[0], rspa.rate[1]};
|
||||
uint16_t vol_wet = rspa.vol_wet;
|
||||
uint16_t rate_wet = rspa.rate_wet;
|
||||
|
||||
do {
|
||||
for (int i = 0; i < 8; i++) {
|
||||
int16_t samples[2] = {*in, *in}; in++;
|
||||
for (int j = 0; j < 2; j++) {
|
||||
samples[j] = (samples[j] * vols[j] >> 16) ^ negs[j];
|
||||
}
|
||||
for (int j = 0; j < 2; j++) {
|
||||
*dry[j] = clamp16(*dry[j] + samples[j]); dry[j]++;
|
||||
*wet[j] = clamp16(*wet[j] + ((samples[swapped[j]] * vol_wet >> 16) ^ negs[2 + j])); wet[j]++;
|
||||
}
|
||||
}
|
||||
vols[0] += rates[0];
|
||||
vols[1] += rates[1];
|
||||
vol_wet += rate_wet;
|
||||
|
||||
n -= 8;
|
||||
} while (n > 0);
|
||||
}
|
||||
|
||||
void aMixImpl(uint16_t count, int16_t gain, uint16_t in_addr, uint16_t out_addr) {
|
||||
int nbytes = ROUND_UP_32(ROUND_DOWN_16(count << 4));
|
||||
int16_t *in = BUF_S16(in_addr);
|
||||
int16_t *out = BUF_S16(out_addr);
|
||||
int i;
|
||||
int32_t sample;
|
||||
|
||||
if (gain == -0x8000) {
|
||||
while (nbytes > 0) {
|
||||
for (i = 0; i < 16; i++) {
|
||||
sample = *out - *in++;
|
||||
*out++ = clamp16(sample);
|
||||
}
|
||||
nbytes -= 16 * sizeof(int16_t);
|
||||
}
|
||||
}
|
||||
|
||||
while (nbytes > 0) {
|
||||
for (i = 0; i < 16; i++) {
|
||||
sample = ((*out * 0x7fff + *in++ * gain) + 0x4000) >> 15;
|
||||
*out++ = clamp16(sample);
|
||||
}
|
||||
|
||||
nbytes -= 16 * sizeof(int16_t);
|
||||
}
|
||||
}
|
||||
|
||||
void aS8DecImpl(uint8_t flags, ADPCM_STATE state) {
|
||||
uint8_t *in = BUF_U8(rspa.in);
|
||||
int16_t *out = BUF_S16(rspa.out);
|
||||
int nbytes = ROUND_UP_32(rspa.nbytes);
|
||||
if (flags & A_INIT) {
|
||||
memset(out, 0, 16 * sizeof(int16_t));
|
||||
} else if (flags & A_LOOP) {
|
||||
memcpy(out, rspa.adpcm_loop_state, 16 * sizeof(int16_t));
|
||||
} else {
|
||||
memcpy(out, state, 16 * sizeof(int16_t));
|
||||
}
|
||||
out += 16;
|
||||
|
||||
while (nbytes > 0) {
|
||||
*out++ = (int16_t)(*in++ << 8);
|
||||
*out++ = (int16_t)(*in++ << 8);
|
||||
*out++ = (int16_t)(*in++ << 8);
|
||||
*out++ = (int16_t)(*in++ << 8);
|
||||
*out++ = (int16_t)(*in++ << 8);
|
||||
*out++ = (int16_t)(*in++ << 8);
|
||||
*out++ = (int16_t)(*in++ << 8);
|
||||
*out++ = (int16_t)(*in++ << 8);
|
||||
*out++ = (int16_t)(*in++ << 8);
|
||||
*out++ = (int16_t)(*in++ << 8);
|
||||
*out++ = (int16_t)(*in++ << 8);
|
||||
*out++ = (int16_t)(*in++ << 8);
|
||||
*out++ = (int16_t)(*in++ << 8);
|
||||
*out++ = (int16_t)(*in++ << 8);
|
||||
*out++ = (int16_t)(*in++ << 8);
|
||||
*out++ = (int16_t)(*in++ << 8);
|
||||
|
||||
nbytes -= 16 * sizeof(int16_t);
|
||||
}
|
||||
|
||||
memcpy(state, out - 16, 16 * sizeof(int16_t));
|
||||
}
|
||||
|
||||
void aAddMixerImpl(uint16_t count, uint16_t in_addr, uint16_t out_addr) {
|
||||
int16_t *in = BUF_S16(in_addr);
|
||||
int16_t *out = BUF_S16(out_addr);
|
||||
int nbytes = ROUND_UP_64(ROUND_DOWN_16(count));
|
||||
|
||||
do {
|
||||
*out = clamp16(*out + *in++); out++;
|
||||
*out = clamp16(*out + *in++); out++;
|
||||
*out = clamp16(*out + *in++); out++;
|
||||
*out = clamp16(*out + *in++); out++;
|
||||
*out = clamp16(*out + *in++); out++;
|
||||
*out = clamp16(*out + *in++); out++;
|
||||
*out = clamp16(*out + *in++); out++;
|
||||
*out = clamp16(*out + *in++); out++;
|
||||
*out = clamp16(*out + *in++); out++;
|
||||
*out = clamp16(*out + *in++); out++;
|
||||
*out = clamp16(*out + *in++); out++;
|
||||
*out = clamp16(*out + *in++); out++;
|
||||
*out = clamp16(*out + *in++); out++;
|
||||
*out = clamp16(*out + *in++); out++;
|
||||
*out = clamp16(*out + *in++); out++;
|
||||
*out = clamp16(*out + *in++); out++;
|
||||
|
||||
nbytes -= 16 * sizeof(int16_t);
|
||||
} while (nbytes > 0);
|
||||
}
|
||||
|
||||
void aDuplicateImpl(uint16_t count, uint16_t in_addr, uint16_t out_addr) {
|
||||
uint8_t* in = BUF_U8(in_addr);
|
||||
uint8_t *out = BUF_U8(out_addr);
|
||||
|
||||
uint8_t tmp[128];
|
||||
memcpy(tmp, in, 128);
|
||||
do {
|
||||
memcpy(out, tmp, 128);
|
||||
out += 128;
|
||||
} while (count-- > 0);
|
||||
}
|
||||
|
||||
void aResampleZohImpl(uint16_t pitch, uint16_t start_fract) {
|
||||
int16_t *in = BUF_S16(rspa.in);
|
||||
int16_t *out = BUF_S16(rspa.out);
|
||||
int nbytes = ROUND_UP_8(rspa.nbytes);
|
||||
uint32_t pos = start_fract;
|
||||
uint32_t pitch_add = pitch << 2;
|
||||
|
||||
do {
|
||||
*out++ = in[pos >> 17]; pos += pitch_add;
|
||||
*out++ = in[pos >> 17]; pos += pitch_add;
|
||||
*out++ = in[pos >> 17]; pos += pitch_add;
|
||||
*out++ = in[pos >> 17]; pos += pitch_add;
|
||||
|
||||
nbytes -= 4 * sizeof(int16_t);
|
||||
} while (nbytes > 0);
|
||||
}
|
||||
|
||||
void aInterlImpl(uint16_t in_addr, uint16_t out_addr, uint16_t n_samples) {
|
||||
int16_t *in = BUF_S16(in_addr);
|
||||
int16_t *out = BUF_S16(out_addr);
|
||||
int n = ROUND_UP_8(n_samples);
|
||||
|
||||
do {
|
||||
*out++ = *in++; in++;
|
||||
*out++ = *in++; in++;
|
||||
*out++ = *in++; in++;
|
||||
*out++ = *in++; in++;
|
||||
*out++ = *in++; in++;
|
||||
*out++ = *in++; in++;
|
||||
*out++ = *in++; in++;
|
||||
*out++ = *in++; in++;
|
||||
|
||||
n -= 8;
|
||||
} while (n > 0);
|
||||
}
|
||||
|
||||
void aFilterImpl(uint8_t flags, uint16_t count_or_buf, int16_t *state_or_filter) {
|
||||
if (flags > A_INIT) {
|
||||
rspa.filter_count = ROUND_UP_16(count_or_buf);
|
||||
memcpy(rspa.filter, state_or_filter, sizeof(rspa.filter));
|
||||
} else {
|
||||
int16_t tmp[16], tmp2[8];
|
||||
int count = rspa.filter_count;
|
||||
int16_t *buf = BUF_S16(count_or_buf);
|
||||
|
||||
if (flags == A_INIT) {
|
||||
#ifndef __clang__
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wmemset-elt-size"
|
||||
#endif
|
||||
memset(tmp, 0, 8 * sizeof(int16_t));
|
||||
#ifndef __clang__
|
||||
#pragma GCC diagnostic pop
|
||||
#endif
|
||||
memset(tmp2, 0, 8 * sizeof(int16_t));
|
||||
} else {
|
||||
memcpy(tmp, state_or_filter, 8 * sizeof(int16_t));
|
||||
memcpy(tmp2, state_or_filter + 8, 8 * sizeof(int16_t));
|
||||
}
|
||||
|
||||
for (int i = 0; i < 8; i++) {
|
||||
rspa.filter[i] = (tmp2[i] + rspa.filter[i]) / 2;
|
||||
}
|
||||
|
||||
do {
|
||||
memcpy(tmp + 8, buf, 8 * sizeof(int16_t));
|
||||
for (int i = 0; i < 8; i++) {
|
||||
int64_t sample = 0x4000; // round term
|
||||
for (int j = 0; j < 8; j++) {
|
||||
sample += tmp[i + j] * rspa.filter[7 - j];
|
||||
}
|
||||
buf[i] = clamp16((int32_t)(sample >> 15));
|
||||
}
|
||||
memcpy(tmp, tmp + 8, 8 * sizeof(int16_t));
|
||||
|
||||
buf += 8;
|
||||
count -= 8 * sizeof(int16_t);
|
||||
} while (count > 0);
|
||||
|
||||
memcpy(state_or_filter, tmp, 8 * sizeof(int16_t));
|
||||
memcpy(state_or_filter + 8, rspa.filter, 8 * sizeof(int16_t));
|
||||
}
|
||||
}
|
||||
|
||||
void aHiLoGainImpl(uint8_t g, uint16_t count, uint16_t addr) {
|
||||
int16_t *samples = BUF_S16(addr);
|
||||
int nbytes = ROUND_UP_32(count);
|
||||
|
||||
do {
|
||||
*samples = clamp16((*samples * g) >> 4); samples++;
|
||||
*samples = clamp16((*samples * g) >> 4); samples++;
|
||||
*samples = clamp16((*samples * g) >> 4); samples++;
|
||||
*samples = clamp16((*samples * g) >> 4); samples++;
|
||||
*samples = clamp16((*samples * g) >> 4); samples++;
|
||||
*samples = clamp16((*samples * g) >> 4); samples++;
|
||||
*samples = clamp16((*samples * g) >> 4); samples++;
|
||||
*samples = clamp16((*samples * g) >> 4); samples++;
|
||||
|
||||
nbytes -= 8;
|
||||
} while (nbytes > 0);
|
||||
}
|
||||
|
||||
void aUnkCmd3Impl(uint16_t a, uint16_t b, uint16_t c) {
|
||||
}
|
||||
|
||||
void aUnkCmd19Impl(uint8_t f, uint16_t count, uint16_t out_addr, uint16_t in_addr) {
|
||||
int nbytes = ROUND_UP_64(count);
|
||||
int16_t *in = BUF_S16(in_addr + f);
|
||||
int16_t *out = BUF_S16(out_addr);
|
||||
int16_t tbl[32];
|
||||
|
||||
memcpy(tbl, in, 32 * sizeof(int16_t));
|
||||
do {
|
||||
for (int i = 0; i < 32; i++) {
|
||||
out[i] = clamp16(out[i] * tbl[i]);
|
||||
}
|
||||
out += 32;
|
||||
nbytes -= 32 * sizeof(int16_t);
|
||||
} while (nbytes > 0);
|
||||
}
|
88
src/audio/mixer.h
Normal file
88
src/audio/mixer.h
Normal file
@ -0,0 +1,88 @@
|
||||
#pragma once
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include "libultraship/libultra/abi.h"
|
||||
|
||||
#undef aSegment
|
||||
#undef aClearBuffer
|
||||
#undef aSetBuffer
|
||||
#undef aLoadBuffer
|
||||
#undef aSaveBuffer
|
||||
#undef aDMEMMove
|
||||
#undef aMix
|
||||
#undef aEnvMixer
|
||||
#undef aResample
|
||||
#undef aInterleave
|
||||
#undef aSetVolume
|
||||
#undef aSetVolume32
|
||||
#undef aSetLoop
|
||||
#undef aLoadADPCM
|
||||
#undef aADPCMdec
|
||||
#undef aS8Dec
|
||||
#undef aAddMixer
|
||||
#undef aDuplicate
|
||||
#undef aDMEMMove2
|
||||
#undef aResampleZoh
|
||||
#undef aEnvSetup1
|
||||
#undef aEnvSetup2
|
||||
#undef aFilter
|
||||
#undef aHiLoGain
|
||||
#undef aInterl
|
||||
#undef aUnkCmd3
|
||||
#undef aUnkCmd19
|
||||
|
||||
void aClearBufferImpl(uint16_t addr, int nbytes);
|
||||
void aLoadBufferImpl(const void* source_addr, uint16_t dest_addr, uint16_t nbytes);
|
||||
void aSaveBufferImpl(uint16_t source_addr, int16_t* dest_addr, uint16_t nbytes);
|
||||
void aLoadADPCMImpl(int num_entries_times_16, const int16_t* book_source_addr);
|
||||
void aSetBufferImpl(uint8_t flags, uint16_t in, uint16_t out, uint16_t nbytes);
|
||||
void aInterleaveImpl(uint16_t dest, uint16_t left, uint16_t right, uint16_t c);
|
||||
void aDMEMMoveImpl(uint16_t in_addr, uint16_t out_addr, int nbytes);
|
||||
void aSetLoopImpl(ADPCM_STATE* adpcm_loop_state);
|
||||
void aADPCMdecImpl(uint8_t flags, ADPCM_STATE state);
|
||||
void aResampleImpl(uint8_t flags, uint16_t pitch, RESAMPLE_STATE state);
|
||||
void aEnvSetup1Impl(uint8_t initial_vol_wet, uint16_t rate_wet, uint16_t rate_left, uint16_t rate_right);
|
||||
void aEnvSetup2Impl(uint16_t initial_vol_left, uint16_t initial_vol_right);
|
||||
void aEnvMixerImpl(uint16_t in_addr, uint16_t n_samples, bool swap_reverb, bool neg_3, bool neg_2, bool neg_left,
|
||||
bool neg_right, int32_t wet_dry_addr, u32 unk);
|
||||
void aMixImpl(uint16_t count, int16_t gain, uint16_t in_addr, uint16_t out_addr);
|
||||
void aS8DecImpl(uint8_t flags, ADPCM_STATE state);
|
||||
void aAddMixerImpl(uint16_t count, uint16_t in_addr, uint16_t out_addr);
|
||||
void aDuplicateImpl(uint16_t count, uint16_t in_addr, uint16_t out_addr);
|
||||
void aResampleZohImpl(uint16_t pitch, uint16_t start_fract);
|
||||
void aInterlImpl(uint16_t in_addr, uint16_t out_addr, uint16_t n_samples);
|
||||
void aFilterImpl(uint8_t flags, uint16_t count_or_buf, int16_t* state_or_filter);
|
||||
void aHiLoGainImpl(uint8_t g, uint16_t count, uint16_t addr);
|
||||
void aUnkCmd3Impl(uint16_t a, uint16_t b, uint16_t c);
|
||||
void aUnkCmd19Impl(uint8_t f, uint16_t count, uint16_t out_addr, uint16_t in_addr);
|
||||
|
||||
#define aSegment(pkt, s, b) \
|
||||
do { \
|
||||
} while (0)
|
||||
#define aClearBuffer(pkt, d, c) aClearBufferImpl(d, c)
|
||||
#define aLoadBuffer(pkt, s, d, c) aLoadBufferImpl(s, d, c)
|
||||
#define aSaveBuffer(pkt, s, d, c) aSaveBufferImpl(s, d, c)
|
||||
#define aLoadADPCM(pkt, c, d) aLoadADPCMImpl(c, d)
|
||||
#define aSetBuffer(pkt, f, i, o, c) aSetBufferImpl(f, i, o, c)
|
||||
#define aInterleave(pkt, o, l, r, c) aInterleaveImpl(o, l, r, c)
|
||||
#define aDMEMMove(pkt, i, o, c) aDMEMMoveImpl(i, o, c)
|
||||
#define aSetLoop(pkt, a) aSetLoopImpl(a)
|
||||
#define aADPCMdec(pkt, f, s) aADPCMdecImpl(f, s)
|
||||
#define aResample(pkt, f, p, s) aResampleImpl(f, p, s)
|
||||
#define aEnvSetup1(pkt, initialVolReverb, rampReverb, rampLeft, rampRight) \
|
||||
aEnvSetup1Impl(initialVolReverb, rampReverb, rampLeft, rampRight)
|
||||
#define aEnvSetup2(pkt, initialVolLeft, initialVolRight) aEnvSetup2Impl(initialVolLeft, initialVolRight)
|
||||
#define aEnvMixer(pkt, inBuf, nSamples, swapReverb, negLeft, negRight, dryLeft, dryRight, wetLeft, wetRight) \
|
||||
aEnvMixerImpl(inBuf, nSamples, swapReverb, negLeft, negRight, dryLeft, dryRight, wetLeft, wetRight)
|
||||
#define aMix(pkt, c, g, i, o) aMixImpl(c, g, i, o)
|
||||
#define aS8Dec(pkt, f, s) aS8DecImpl(f, s)
|
||||
#define aAddMixer(pkt, s, d, c, x) aAddMixerImpl(s, d, c)
|
||||
#define aDuplicate(pkt, s, d, c) aDuplicateImpl(s, d, c)
|
||||
#define aDMEMMove2(pkt, t, i, o, c) aDMEMMove2Impl(t, i, o, c)
|
||||
#define aResampleZoh(pkt, pitch, startFract) aResampleZohImpl(pitch, startFract)
|
||||
#define aInterl(pkt, dmemi, dmemo, count) aInterlImpl(dmemi, dmemo, count)
|
||||
#define aFilter(pkt, f, countOrBuf, addr) aFilterImpl(f, countOrBuf, addr)
|
||||
#define aHiLoGain(pkt, g, buflen, i, a4) aHiLoGainImpl(g, buflen, i)
|
||||
#define aUnkCmd3(pkt, a1, a2, a3) aUnkCmd3Impl(a1, a2, a3)
|
||||
#define aUnkCmd19(pkt, a1, a2, a3, a4) aUnkCmd19Impl(a1, a2, a3, a4)
|
@ -3,7 +3,7 @@
|
||||
u8 gOSYieldData[OS_YIELD_DATA_SIZE];
|
||||
FrameBuffer gZBuffer; // z buffer
|
||||
u8 gTaskOutputBuffer[0x30000];
|
||||
u8 gAudioHeap[0xB0000];
|
||||
u8 gAudioHeap[0xB0000 * 2];
|
||||
u16 gTextureRenderBuffer[0x3C40];
|
||||
u16 gFillBuffer[3 * SCREEN_WIDTH];
|
||||
FrameBuffer gFrameBuffers[3];
|
||||
|
@ -3,6 +3,7 @@
|
||||
s32 osViClock2 = 0x02E6D354;
|
||||
|
||||
s32 osAiSetFrequency(u32 freq) {
|
||||
return 32000;
|
||||
register u32 a1;
|
||||
register s32 a2;
|
||||
register float ftmp;
|
||||
|
@ -13,6 +13,7 @@
|
||||
#include "assets/ast_option.h"
|
||||
#include "assets/ast_vs_menu.h"
|
||||
#include "assets/ast_map.h"
|
||||
#include "port/interpolation/FrameInterpolation.h"
|
||||
|
||||
extern s32 gRankingTeamAlive[][3];
|
||||
extern Gfx gMapVenomCloudDL[];
|
||||
|
@ -10,6 +10,7 @@
|
||||
#include "fox_title.h"
|
||||
#include "assets/ast_title.h"
|
||||
#include "assets/ast_text.h"
|
||||
#include "port/interpolation/FrameInterpolation.h"
|
||||
|
||||
f32 D_menu_801B7BB0;
|
||||
f32 D_menu_801B7BB4;
|
||||
|
@ -24,6 +24,7 @@
|
||||
#include <MatrixFactory.h>
|
||||
#include <BlobFactory.h>
|
||||
#include <VertexFactory.h>
|
||||
#include "audio/GameAudio.h"
|
||||
|
||||
#include <Fast3D/gfx_pc.h>
|
||||
#include <Fast3D/gfx_rendering_api.h>
|
||||
@ -36,6 +37,7 @@ extern uint16_t gFPS;
|
||||
float gInterpolationStep = 0.0f;
|
||||
#include <sf64thread.h>
|
||||
#include <macros.h>
|
||||
void AudioThread_CreateNextAudioBuffer(int16_t *samples, uint32_t num_samples);
|
||||
}
|
||||
|
||||
GameEngine* GameEngine::Instance;
|
||||
@ -85,6 +87,7 @@ GameEngine::GameEngine() {
|
||||
|
||||
void GameEngine::Create(){
|
||||
const auto instance = Instance = new GameEngine();
|
||||
instance->AudioInit();
|
||||
GameUI::SetupGuiElements();
|
||||
#if defined(__SWITCH__) || defined(__WIIU__)
|
||||
CVarRegisterInteger("gControlNav", 1); // always enable controller nav on switch/wii u
|
||||
@ -114,6 +117,64 @@ void GameEngine::StartFrame() const{
|
||||
this->context->GetWindow()->StartFrame();
|
||||
}
|
||||
|
||||
void GameEngine::HandleAudioThread(){
|
||||
while (audio.running) {
|
||||
{
|
||||
std::unique_lock<std::mutex> Lock(audio.mutex);
|
||||
while (!audio.processing && audio.running) {
|
||||
audio.cv_to_thread.wait(Lock);
|
||||
}
|
||||
if (!audio.running) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
std::unique_lock<std::mutex> Lock(audio.mutex);
|
||||
int samples_left = AudioPlayerBuffered();
|
||||
u32 num_audio_samples = samples_left < AudioPlayerGetDesiredBuffered() ? SAMPLES_HIGH : SAMPLES_LOW;
|
||||
s16 audio_buffer[SAMPLES_PER_FRAME];
|
||||
for (int i = 0; i < NUM_AUDIO_CHANNELS; i++) {
|
||||
AudioThread_CreateNextAudioBuffer(audio_buffer + i * (num_audio_samples * 2), num_audio_samples);
|
||||
}
|
||||
AudioPlayerPlayFrame((u8 *) audio_buffer, 2 * num_audio_samples * 4);
|
||||
audio.processing = false;
|
||||
audio.cv_from_thread.notify_one();
|
||||
}
|
||||
}
|
||||
|
||||
void GameEngine::StartAudioFrame(){
|
||||
{
|
||||
std::unique_lock<std::mutex> Lock(audio.mutex);
|
||||
audio.processing = true;
|
||||
}
|
||||
audio.cv_to_thread.notify_one();
|
||||
}
|
||||
|
||||
void GameEngine::EndAudioFrame(){
|
||||
{
|
||||
std::unique_lock<std::mutex> Lock(audio.mutex);
|
||||
while (audio.processing) {
|
||||
audio.cv_from_thread.wait(Lock);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void GameEngine::AudioInit() {
|
||||
if (!audio.running) {
|
||||
audio.running = true;
|
||||
audio.thread = std::thread(HandleAudioThread);
|
||||
}
|
||||
}
|
||||
|
||||
void GameEngine::AudioExit() {
|
||||
{
|
||||
std::unique_lock lock(audio.mutex);
|
||||
audio.running = false;
|
||||
}
|
||||
audio.cv_to_thread.notify_all();
|
||||
// Wait until the audio thread quit
|
||||
audio.thread.join();
|
||||
}
|
||||
|
||||
void GameEngine::RunCommands(Gfx* Commands, const std::vector<std::unordered_map<Mtx*, MtxF>>& mtx_replacements) {
|
||||
for (const auto& m : mtx_replacements) {
|
||||
gfx_run(Commands, m);
|
||||
|
@ -23,6 +23,11 @@ class GameEngine {
|
||||
GameEngine();
|
||||
static void Create();
|
||||
void StartFrame() const;
|
||||
static void HandleAudioThread();
|
||||
static void StartAudioFrame();
|
||||
static void EndAudioFrame();
|
||||
static void AudioInit();
|
||||
static void AudioExit();
|
||||
static void RunCommands(Gfx* Commands, const std::vector<std::unordered_map<Mtx*, MtxF>>& mtx_replacements);
|
||||
void ProcessFrame(void (*run_one_game_iter)()) const;
|
||||
static void Destroy();
|
||||
|
@ -10,6 +10,7 @@ extern "C" {
|
||||
void Main_ThreadEntry(void* arg);
|
||||
void Lib_FillScreen(u8 setFill);
|
||||
void Graphics_ThreadUpdate();
|
||||
void AudioThread_CreateTask();
|
||||
}
|
||||
|
||||
extern "C"
|
||||
@ -20,12 +21,12 @@ void Graphics_PushFrame(Gfx* data) {
|
||||
extern "C" void Timer_Update();
|
||||
|
||||
void push_frame() {
|
||||
// GameEngine::StartAudioFrame();
|
||||
GameEngine::StartAudioFrame();
|
||||
GameEngine::Instance->StartFrame();
|
||||
Graphics_ThreadUpdate();
|
||||
Timer_Update();
|
||||
// thread5_iteration();
|
||||
// GameEngine::EndAudioFrame();
|
||||
GameEngine::EndAudioFrame();
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
|
10
src/port/audio/GameAudio.h
Normal file
10
src/port/audio/GameAudio.h
Normal file
@ -0,0 +1,10 @@
|
||||
#pragma once
|
||||
#include <thread>
|
||||
#include <condition_variable>
|
||||
static struct {
|
||||
std::thread thread;
|
||||
std::condition_variable cv_to_thread, cv_from_thread;
|
||||
std::mutex mutex;
|
||||
bool running;
|
||||
bool processing;
|
||||
} audio;
|
@ -105,8 +105,9 @@ void Main_Initialize(void) {
|
||||
void Audio_ThreadEntry(void* arg0) {
|
||||
// SPTask* task;
|
||||
|
||||
// AudioLoad_Init();
|
||||
// Audio_InitSounds();
|
||||
AudioLoad_Init();
|
||||
Audio_InitSounds();
|
||||
|
||||
// task = AudioThread_CreateTask();
|
||||
// if (task != NULL) {
|
||||
// task->msgQueue = &gAudioTaskMsgQueue;
|
||||
@ -383,7 +384,7 @@ void Main_ThreadEntry(void* arg0) {
|
||||
u32 mesg;
|
||||
|
||||
// LTODO: Implement audio
|
||||
// Audio_ThreadEntry(NULL);
|
||||
Audio_ThreadEntry(NULL);
|
||||
Graphics_ThreadEntry(NULL);
|
||||
Controller_Init();
|
||||
|
||||
|
@ -1 +1 @@
|
||||
Subproject commit 298578677e28ef1fe0d3a425f2856930c6cc4ef1
|
||||
Subproject commit ff8c2d13c71069f3117faf42ed25f0816229a872
|
Loading…
Reference in New Issue
Block a user