diff --git a/Source/HLEAudio/HLEMain.cpp b/Source/HLEAudio/HLEMain.cpp index 0348c849..550e2d0a 100644 --- a/Source/HLEAudio/HLEMain.cpp +++ b/Source/HLEAudio/HLEMain.cpp @@ -113,33 +113,70 @@ inline void Audio_Ucode_Detect(OSTask *pTask) { //***************************************************************************** // //***************************************************************************** +#include +#include +#include + +// Atomic flag to signal which queue is active +std::atomic activeQueueIndex{0}; // 0 or 1 to switch between the two queues + +// Two separate task queues for each CPU +std::queue queue1; +std::queue queue2; + +// Function to enqueue tasks into one of the two queues +void EnqueueTask() { + + OSTask *pTask = (OSTask *)(g_pu8SpMemBase + 0x0FC0); + // Determine which queue to enqueue the task into based on the active queue + if (activeQueueIndex.load() == 0) { + queue1.push(pTask); + } else { + queue2.push(pTask); + } +} + void Audio_Ucode() { #ifdef DAEDALUS_PROFILE - DAEDALUS_PROFILE("HLEMain::Audio_Ucode"); + DAEDALUS_PROFILE("HLEMain::Audio_Ucode"); #endif - OSTask *pTask = (OSTask *)(g_pu8SpMemBase + 0x0FC0); - - // Only detect ABI once per game - if (!bAudioChanged) { - bAudioChanged = true; - Audio_Ucode_Detect(pTask); - } - - gAudioHLEState.LoopVal = 0; - memset( gAudioHLEState.Segments, 0, sizeof( gAudioHLEState.Segments ) ); - - u32 *p_alist = (u32 *)(g_pu8RamBase + (uintptr_t)pTask->t.data_ptr); - u32 ucode_size = (pTask->t.data_size >> 3); // ABI5 can return 0 here!!! - while (ucode_size) { - AudioHLECommand command; - command.cmd0 = *p_alist++; - command.cmd1 = *p_alist++; - - ABI[command.cmd](command); - - --ucode_size; - - // printf("%08X %08X\n",command.cmd0,command.cmd1); - } -} + // Process tasks from the current active queue + std::queue& processingQueue = (activeQueueIndex.load() == 0) ? queue1 : queue2; + + while (!processingQueue.empty()) { + OSTask* pTask = processingQueue.front(); + processingQueue.pop(); + + // Only detect ABI once per game + if (!bAudioChanged) { + bAudioChanged = true; + Audio_Ucode_Detect(pTask); + } + + gAudioHLEState.LoopVal = 0; + + u32* p_alist = (u32*)(g_pu8RamBase + (uintptr_t)pTask->t.data_ptr); + u32 ucode_size = (pTask->t.data_size >> 3); // ABI5 can return 0 here! + + // Process the commands in the task + while (ucode_size) { + AudioHLECommand command; + command.cmd0 = *p_alist++; + command.cmd1 = *p_alist++; + + // Execute the command using the ABI + ABI[command.cmd](command); + + --ucode_size; + } + for(int i = 0; i < 8192; i += 64) + { + __builtin_allegrex_cache(0x14, i); + __builtin_allegrex_cache(0x14, i); + } + } + + // Swap the active queue after processing + activeQueueIndex.store(!activeQueueIndex.load()); +} \ No newline at end of file diff --git a/Source/HLEAudio/Plugin/PSP/AudioPluginPSP.cpp b/Source/HLEAudio/Plugin/PSP/AudioPluginPSP.cpp index 39d8df46..e4a03a2a 100644 --- a/Source/HLEAudio/Plugin/PSP/AudioPluginPSP.cpp +++ b/Source/HLEAudio/Plugin/PSP/AudioPluginPSP.cpp @@ -140,11 +140,67 @@ class AudioPluginPSP : public CAudioPlugin static AudioPluginPSP * ac; +#include +#include +#include + +// Atomic flag to signal which queue is active +std::atomic activeQueueIndexplayback{0}; // 0 or 1 to switch between the two queues + +// Two separate task queues for each CPU +std::queue Samplequeue1; +std::queue Samplequeue2; +std::queue num_Samplequeue1; +std::queue num_Samplequeue2; + +// Function to enqueue tasks into one of the two queues +void EnqueueTaskplayback(Sample * buffer, u32 num_samples) { + + // Determine which queue to enqueue the task into based on the active queue + if (activeQueueIndexplayback.load() == 0) { + Samplequeue1.push(buffer); + num_Samplequeue1.push(num_samples); + } else { + Samplequeue2.push(buffer); + num_Samplequeue2.push(num_samples); + } +} + +void processthequeues(CAudioBuffer * bubble){ + + std::queue& processingQueue1 = (activeQueueIndexplayback.load() == 0) ? Samplequeue1 : Samplequeue2; + std::queue& processingQueue2 = (activeQueueIndexplayback.load() == 0) ? num_Samplequeue1 : num_Samplequeue2; + + while (!processingQueue1.empty()) { + + Sample* buffer = processingQueue1.front(); + processingQueue1.pop(); + u32 numberofsamples = processingQueue2.front(); + processingQueue2.pop(); + + + bubble->Drain( buffer, numberofsamples ); + + for(int i = 0; i < 8192; i += 64) + { + __builtin_allegrex_cache(0x14, i); + __builtin_allegrex_cache(0x14, i); + } + + } +} + + + + void AudioPluginPSP::FillBuffer(Sample * buffer, u32 num_samples) { sceKernelWaitSema( mSemaphore, 1, nullptr ); - mAudioBufferUncached->Drain( buffer, num_samples ); + EnqueueTaskplayback(buffer, num_samples); + sceKernelDcacheWritebackInvalidateAll(); + BeginME( mei, (int)&processthequeues, (int)mAudioBuffer, -1, NULL, -1, NULL); + sceKernelSignalSema( mSemaphore, 1 ); } @@ -228,6 +284,7 @@ void AudioPluginPSP::LenChanged() } } +extern void EnqueueTask(); EProcessResult AudioPluginPSP::ProcessAList() { @@ -242,23 +299,19 @@ EProcessResult AudioPluginPSP::ProcessAList() break; case APM_ENABLED_ASYNC: { -#ifdef DAEDALUS_PSP_USE_ME + EnqueueTask(); sceKernelDcacheWritebackInvalidateAll(); if(BeginME( mei, (int)&Audio_Ucode, (int)NULL, -1, NULL, -1, NULL) < 0){ - Audio_Ucode(); result = PR_COMPLETED; break; } -#else - DAEDALUS_ERROR("Async audio is unimplemented"); - Audio_Ucode(); result = PR_COMPLETED; break; -#endif } result = PR_COMPLETED; break; case APM_ENABLED_SYNC: + EnqueueTask(); Audio_Ucode(); result = PR_COMPLETED; break; @@ -267,7 +320,6 @@ EProcessResult AudioPluginPSP::ProcessAList() return result; } - void audioCallback( void * buf, unsigned int length, void * userdata ) { AudioPluginPSP * ac( reinterpret_cast< AudioPluginPSP * >( userdata ) ); @@ -276,6 +328,7 @@ void audioCallback( void * buf, unsigned int length, void * userdata ) } + void AudioPluginPSP::StartAudio() { if (mKeepRunning)