Skip to content

Commit

Permalink
Audio: Avoid exposing fixed size queue in header.
Browse files Browse the repository at this point in the history
  • Loading branch information
unknownbrackets committed Aug 10, 2020
1 parent 2da977b commit 4c46867
Show file tree
Hide file tree
Showing 4 changed files with 38 additions and 32 deletions.
38 changes: 24 additions & 14 deletions Core/HLE/__sceAudio.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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];
Expand Down Expand Up @@ -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();
}
Expand All @@ -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) {
Expand All @@ -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};
Expand Down Expand Up @@ -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));
Expand All @@ -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);
Expand All @@ -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));
}
}
}
Expand Down Expand Up @@ -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) {
Expand Down
17 changes: 10 additions & 7 deletions Core/HLE/sceAudio.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand All @@ -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);
Expand All @@ -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()
Expand All @@ -69,7 +72,7 @@ void AudioChannel::clear()
format = 0;
sampleAddress = 0;
sampleCount = 0;
sampleQueue.clear();
chanSampleQueues[index].clear();
waitingThreads.clear();
}

Expand Down Expand Up @@ -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;
}
Expand All @@ -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;
}
Expand Down Expand Up @@ -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;
Expand All @@ -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();
Expand Down Expand Up @@ -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();
Expand Down
12 changes: 2 additions & 10 deletions Core/HLE/sceAudio.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@

#include "CommonTypes.h"
#include "sceKernel.h"
#include "FixedSizeQueue.h"

class PointerWrap;

Expand Down Expand Up @@ -60,9 +59,8 @@ struct AudioChannel
clear();
}

// PSP side

bool reserved;
int index = 0;
bool reserved = false;

// last sample address
u32 sampleAddress;
Expand All @@ -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();
Expand Down
3 changes: 2 additions & 1 deletion UI/BackgroundAudio.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down

0 comments on commit 4c46867

Please sign in to comment.