Audio: Avoid exposing fixed size queue in header.

This commit is contained in:
Unknown W. Brackets 2020-08-09 22:03:49 -07:00
parent 2da977bed2
commit 4c46867230
4 changed files with 38 additions and 32 deletions

View file

@ -52,6 +52,10 @@ StereoResampler resampler;
// atomic locks are used on the lock. TODO: make this lock-free
std::atomic_flag atomicLock_;
// We copy samples as they are written into this simple ring buffer.
// Might try something more efficient later.
FixedSizeQueue<s16, 32768 * 8> chanSampleQueues[PSP_AUDIO_CHANNEL_MAX + 1];
int eventAudioUpdate = -1;
int eventHostAudioUpdate = -1;
int mixFrequency = 44100;
@ -115,8 +119,10 @@ void __AudioInit() {
CoreTiming::ScheduleEvent(audioIntervalCycles, eventAudioUpdate, 0);
CoreTiming::ScheduleEvent(audioHostIntervalCycles, eventHostAudioUpdate, 0);
for (u32 i = 0; i < PSP_AUDIO_CHANNEL_MAX + 1; i++)
for (u32 i = 0; i < PSP_AUDIO_CHANNEL_MAX + 1; i++) {
chans[i].index = i;
chans[i].clear();
}
mixBuffer = new s32[hwBlockSize * 2];
clampedMixBuffer = new s16[hwBlockSize * 2];
@ -164,8 +170,10 @@ void __AudioDoState(PointerWrap &p) {
p.SetError(p.ERROR_FAILURE);
return;
}
for (int i = 0; i < chanCount; ++i)
for (int i = 0; i < chanCount; ++i) {
chans[i].index = i;
chans[i].DoState(p);
}
__AudioCPUMHzChange();
}
@ -175,8 +183,10 @@ void __AudioShutdown() {
delete [] clampedMixBuffer;
mixBuffer = 0;
for (u32 i = 0; i < PSP_AUDIO_CHANNEL_MAX + 1; i++)
for (u32 i = 0; i < PSP_AUDIO_CHANNEL_MAX + 1; i++) {
chans[i].index = i;
chans[i].clear();
}
#ifndef MOBILE_DEVICE
if (g_Config.bDumpAudio) {
@ -196,11 +206,11 @@ u32 __AudioEnqueue(AudioChannel &chan, int chanNum, bool blocking) {
}
// If there's anything on the queue at all, it should be busy, but we try to be a bit lax.
//if (chan.sampleQueue.size() > chan.sampleCount * 2 * chanQueueMaxSizeFactor || chan.sampleAddress == 0) {
if (chan.sampleQueue.size() > 0) {
//if (chanSampleQueues[chanNum].size() > chan.sampleCount * 2 * chanQueueMaxSizeFactor || chan.sampleAddress == 0) {
if (chanSampleQueues[chanNum].size() > 0) {
if (blocking) {
// TODO: Regular multichannel audio seems to block for 64 samples less? Or enqueue the first 64 sync?
int blockSamples = (int)chan.sampleQueue.size() / 2 / chanQueueMinSizeFactor;
int blockSamples = (int)chanSampleQueues[chanNum].size() / 2 / chanQueueMinSizeFactor;
if (__KernelIsDispatchEnabled()) {
AudioChannelWaitInfo waitInfo = {__KernelGetCurThread(), blockSamples};
@ -235,7 +245,7 @@ u32 __AudioEnqueue(AudioChannel &chan, int chanNum, bool blocking) {
const u32 totalSamples = chan.sampleCount * (chan.format == PSP_AUDIO_FORMAT_STEREO ? 2 : 1);
s16 *buf1 = 0, *buf2 = 0;
size_t sz1, sz2;
chan.sampleQueue.pushPointers(totalSamples, &buf1, &sz1, &buf2, &sz2);
chanSampleQueues[chanNum].pushPointers(totalSamples, &buf1, &sz1, &buf2, &sz2);
if (Memory::IsValidAddress(chan.sampleAddress + (totalSamples - 1) * sizeof(s16_le))) {
Memory::Memcpy(buf1, chan.sampleAddress, (u32)sz1 * sizeof(s16));
@ -257,7 +267,7 @@ u32 __AudioEnqueue(AudioChannel &chan, int chanNum, bool blocking) {
if (Memory::IsValidAddress(chan.sampleAddress + (totalSamples - 1) * sizeof(s16_le))) {
s16 *buf1 = 0, *buf2 = 0;
size_t sz1, sz2;
chan.sampleQueue.pushPointers(totalSamples, &buf1, &sz1, &buf2, &sz2);
chanSampleQueues[chanNum].pushPointers(totalSamples, &buf1, &sz1, &buf2, &sz2);
AdjustVolumeBlock(buf1, sampleData, sz1, leftVol, rightVol);
if (buf2) {
AdjustVolumeBlock(buf2, sampleData + sz1, sz2, leftVol, rightVol);
@ -267,8 +277,8 @@ u32 __AudioEnqueue(AudioChannel &chan, int chanNum, bool blocking) {
// Rare, so unoptimized. Expands to stereo.
for (u32 i = 0; i < chan.sampleCount; i++) {
s16 sample = (s16)Memory::Read_U16(chan.sampleAddress + 2 * i);
chan.sampleQueue.push(ApplySampleVolume(sample, leftVol));
chan.sampleQueue.push(ApplySampleVolume(sample, rightVol));
chanSampleQueues[chanNum].push(ApplySampleVolume(sample, leftVol));
chanSampleQueues[chanNum].push(ApplySampleVolume(sample, rightVol));
}
}
}
@ -335,20 +345,20 @@ void __AudioUpdate(bool resetRecording) {
__AudioWakeThreads(chans[i], 0, hwBlockSize);
if (!chans[i].sampleQueue.size()) {
if (!chanSampleQueues[i].size()) {
continue;
}
bool needsResample = i == PSP_AUDIO_CHANNEL_SRC && srcFrequency != 0 && srcFrequency != mixFrequency;
size_t sz = needsResample ? (hwBlockSize * 2 * srcFrequency) / mixFrequency : hwBlockSize * 2;
if (sz > chans[i].sampleQueue.size()) {
ERROR_LOG(SCEAUDIO, "Channel %i buffer underrun at %i of %i", i, (int)chans[i].sampleQueue.size() / 2, (int)sz / 2);
if (sz > chanSampleQueues[i].size()) {
ERROR_LOG(SCEAUDIO, "Channel %i buffer underrun at %i of %i", i, (int)chanSampleQueues[i].size() / 2, (int)sz / 2);
}
const s16 *buf1 = 0, *buf2 = 0;
size_t sz1, sz2;
chans[i].sampleQueue.popPointers(sz, &buf1, &sz1, &buf2, &sz2);
chanSampleQueues[i].popPointers(sz, &buf1, &sz1, &buf2, &sz2);
if (needsResample) {
auto read = [&](size_t i) {

View file

@ -17,6 +17,7 @@
#include "Common/ChunkFile.h"
#include "Common/ChunkFileDo.h"
#include "Common/FixedSizeQueue.h"
#include "Core/MIPS/MIPS.h"
#include "Core/Host.h"
#include "Core/CoreTiming.h"
@ -35,6 +36,8 @@ const int AUDIO_ROUTING_SPEAKER_ON = 1;
int defaultRoutingMode = AUDIO_ROUTING_SPEAKER_ON;
int defaultRoutingVolMode = AUDIO_ROUTING_SPEAKER_ON;
extern FixedSizeQueue<s16, 32768 * 8> chanSampleQueues[PSP_AUDIO_CHANNEL_MAX + 1];
void AudioChannel::DoState(PointerWrap &p)
{
auto s = p.Section("AudioChannel", 1, 2);
@ -52,7 +55,7 @@ void AudioChannel::DoState(PointerWrap &p)
Do(p, defaultRoutingMode);
Do(p, defaultRoutingVolMode);
}
sampleQueue.DoState(p);
chanSampleQueues[index].DoState(p);
}
void AudioChannel::reset()
@ -69,7 +72,7 @@ void AudioChannel::clear()
format = 0;
sampleAddress = 0;
sampleCount = 0;
sampleQueue.clear();
chanSampleQueues[index].clear();
waitingThreads.clear();
}
@ -183,7 +186,7 @@ static int sceAudioGetChannelRestLen(u32 chan) {
ERROR_LOG(SCEAUDIO, "sceAudioGetChannelRestLen(%08x) - bad channel", chan);
return SCE_ERROR_AUDIO_INVALID_CHANNEL;
}
int remainingSamples = (int)chans[chan].sampleQueue.size() / 2;
int remainingSamples = (int)chanSampleQueues[chan].size() / 2;
VERBOSE_LOG(SCEAUDIO, "%d=sceAudioGetChannelRestLen(%08x)", remainingSamples, chan);
return remainingSamples;
}
@ -193,7 +196,7 @@ static int sceAudioGetChannelRestLength(u32 chan) {
ERROR_LOG(SCEAUDIO, "sceAudioGetChannelRestLength(%08x) - bad channel", chan);
return SCE_ERROR_AUDIO_INVALID_CHANNEL;
}
int remainingSamples = (int)chans[chan].sampleQueue.size() / 2;
int remainingSamples = (int)chanSampleQueues[chan].size() / 2;
VERBOSE_LOG(SCEAUDIO, "%d=sceAudioGetChannelRestLength(%08x)", remainingSamples, chan);
return remainingSamples;
}
@ -371,7 +374,7 @@ static u32 sceAudioOutput2GetRestSample() {
if (!chan.reserved) {
return hleLogError(SCEAUDIO, SCE_ERROR_AUDIO_CHANNEL_NOT_RESERVED, "channel not reserved");
}
u32 size = (u32)chan.sampleQueue.size() / 2;
u32 size = (u32)chanSampleQueues[PSP_AUDIO_CHANNEL_OUTPUT2].size() / 2;
if (size > chan.sampleCount) {
// If ChangeLength reduces the size, it still gets output but this return is clamped.
size = chan.sampleCount;
@ -383,7 +386,7 @@ static u32 sceAudioOutput2Release() {
auto &chan = chans[PSP_AUDIO_CHANNEL_OUTPUT2];
if (!chan.reserved)
return hleLogError(SCEAUDIO, SCE_ERROR_AUDIO_CHANNEL_NOT_RESERVED, "channel not reserved");
if (!chan.sampleQueue.empty())
if (!chanSampleQueues[PSP_AUDIO_CHANNEL_OUTPUT2].empty())
return hleLogError(SCEAUDIO, SCE_ERROR_AUDIO_CHANNEL_ALREADY_RESERVED, "output busy");
chan.reset();
@ -444,7 +447,7 @@ static u32 sceAudioSRCChRelease() {
auto &chan = chans[PSP_AUDIO_CHANNEL_SRC];
if (!chan.reserved)
return hleLogError(SCEAUDIO, SCE_ERROR_AUDIO_CHANNEL_NOT_RESERVED, "channel not reserved");
if (!chan.sampleQueue.empty())
if (!chanSampleQueues[PSP_AUDIO_CHANNEL_SRC].empty())
return hleLogError(SCEAUDIO, SCE_ERROR_AUDIO_CHANNEL_ALREADY_RESERVED, "output busy");
chan.reset();

View file

@ -21,7 +21,6 @@
#include "CommonTypes.h"
#include "sceKernel.h"
#include "FixedSizeQueue.h"
class PointerWrap;
@ -60,9 +59,8 @@ struct AudioChannel
clear();
}
// PSP side
bool reserved;
int index = 0;
bool reserved = false;
// last sample address
u32 sampleAddress;
@ -73,12 +71,6 @@ struct AudioChannel
std::vector<AudioChannelWaitInfo> waitingThreads;
// PC side - should probably split out
// We copy samples as they are written into this simple ring buffer.
// Might try something more efficient later.
FixedSizeQueue<s16, 32768 * 8> sampleQueue;
void DoState(PointerWrap &p);
void reset();

View file

@ -7,10 +7,11 @@
#include "file/vfs.h"
#include "ui/root.h"
#include "Common/ChunkFileDo.h"
#include "Common/CommonTypes.h"
#include "Common/FixedSizeQueue.h"
#include "Core/HW/SimpleAudioDec.h"
#include "Core/HLE/__sceAudio.h"
#include "Common/FixedSizeQueue.h"
#include "GameInfoCache.h"
#include "Core/Config.h"
#include "UI/BackgroundAudio.h"