// Mix samples from the various audio channels into a single sample queue. // This single sample queue is where __AudioMix should read from. If the sample queue is full, we should // just sleep the main emulator thread a little. void __AudioUpdate() { // Audio throttle doesn't really work on the PSP since the mixing intervals are so closely tied // to the CPU. Much better to throttle the frame rate on frame display and just throw away audio // if the buffer somehow gets full. s32 mixBuffer[hwBlockSize * 2]; memset(mixBuffer, 0, sizeof(mixBuffer)); for (int i = 0; i < PSP_AUDIO_CHANNEL_MAX; i++) { if (!chans[i].reserved) continue; if (!chans[i].sampleQueue.size()) { // ERROR_LOG(HLE, "No queued samples, skipping channel %i", i); continue; } for (int s = 0; s < hwBlockSize; s++) { if (chans[i].sampleQueue.size() >= 2) { s16 sampleL = chans[i].sampleQueue.pop_front(); s16 sampleR = chans[i].sampleQueue.pop_front(); mixBuffer[s * 2 + 0] += sampleL; mixBuffer[s * 2 + 1] += sampleR; } else { ERROR_LOG(HLE, "Channel %i buffer underrun at %i of %i", i, s, hwBlockSize); break; } } if (chans[i].sampleQueue.size() < chans[i].sampleCount * 2 * chanQueueMinSizeFactor) { // Ask the thread to send more samples until next time, queue is being drained. if (chans[i].waitingThread) { SceUID waitingThread = chans[i].waitingThread; chans[i].waitingThread = 0; // DEBUG_LOG(HLE, "Woke thread %i for some buffer filling", waitingThread); __KernelResumeThreadFromWait(waitingThread, chans[i].sampleCount); } } } if (g_Config.bEnableSound) { section.lock(); if (outAudioQueue.room() >= hwBlockSize * 2) { // Push the mixed samples onto the output audio queue. for (int i = 0; i < hwBlockSize; i++) { s32 sampleL = mixBuffer[i * 2 + 0] >> 2; // TODO - what factor? s32 sampleR = mixBuffer[i * 2 + 1] >> 2; outAudioQueue.push((s16)sampleL); outAudioQueue.push((s16)sampleR); } } else {
// Mix samples from the various audio channels into a single sample queue. // This single sample queue is where __AudioMix should read from. If the sample queue is full, we should // just sleep the main emulator thread a little. void __AudioUpdate() { // Audio throttle doesn't really work on the PSP since the mixing intervals are so closely tied // to the CPU. Much better to throttle the frame rate on frame display and just throw away audio // if the buffer somehow gets full. s32 mixBuffer[hwBlockSize * 2]; memset(mixBuffer, 0, sizeof(mixBuffer)); for (u32 i = 0; i < PSP_AUDIO_CHANNEL_MAX + 1; i++) { if (!chans[i].reserved) continue; __AudioWakeThreads(chans[i], hwBlockSize); if (!chans[i].sampleQueue.size()) { // ERROR_LOG(HLE, "No queued samples, skipping channel %i", i); continue; } for (int s = 0; s < hwBlockSize; s++) { if (chans[i].sampleQueue.size() >= 2) { s16 sampleL = chans[i].sampleQueue.pop_front(); s16 sampleR = chans[i].sampleQueue.pop_front(); mixBuffer[s * 2 + 0] += sampleL; mixBuffer[s * 2 + 1] += sampleR; } else { ERROR_LOG(HLE, "Channel %i buffer underrun at %i of %i", i, s, hwBlockSize); break; } } } if (g_Config.bEnableSound) { section.lock(); if (outAudioQueue.room() >= hwBlockSize * 2) { // Push the mixed samples onto the output audio queue. for (int i = 0; i < hwBlockSize; i++) { s16 sampleL = clamp_s16(mixBuffer[i * 2 + 0]); s16 sampleR = clamp_s16(mixBuffer[i * 2 + 1]); outAudioQueue.push((s16)sampleL); outAudioQueue.push((s16)sampleR); } } else { // This happens quite a lot. There's still something slightly off // about the amount of audio we produce. DEBUG_LOG(HLE, "Audio outbuffer overrun! room = %i / %i", outAudioQueue.room(), (u32)outAudioQueue.capacity()); } section.unlock(); } }