Skip to content

Commit

Permalink
Microphone queuebuf: Switch to int instead of u32 to simplify length …
Browse files Browse the repository at this point in the history
…checks. No more crashes, but it hangs

see issue #19528
  • Loading branch information
hrydgard committed Oct 15, 2024
1 parent e52c1e3 commit 65a0885
Show file tree
Hide file tree
Showing 2 changed files with 54 additions and 75 deletions.
85 changes: 31 additions & 54 deletions Core/HLE/sceUsbMic.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ static void __MicBlockingResume(u64 userdata, int cyclesLate) {
CoreTiming::ScheduleEvent(usToCycles(waitTimeus), eventMicBlockingResume, userdata);
}
} else {
for (u32 i = 0; i < waitingThread.needSize; i++) {
for (int i = 0; i < waitingThread.needSize; i++) {
if (Memory::IsValidAddress(waitingThread.addr + i)) {
Memory::Write_U8(i & 0xFF, waitingThread.addr + i);
}
Expand Down Expand Up @@ -159,40 +159,20 @@ void __UsbMicDoState(PointerWrap &p) {
}
}

QueueBuf::QueueBuf(u32 size) : available(0), end(0), capacity(size) {
QueueBuf::QueueBuf(int size) : available(0), end(0), capacity(size) {
buf_ = new u8[size];
}

QueueBuf::~QueueBuf() {
delete[] buf_;
}

QueueBuf::QueueBuf(const QueueBuf &buf) {
buf_ = new u8[buf.capacity];
memcpy(buf_, buf.buf_, buf.capacity);
available = buf.available;
end = buf.end;
capacity = buf.capacity;
}

QueueBuf& QueueBuf::operator=(const QueueBuf &buf) {
if (capacity < buf.capacity) {
resize(buf.capacity);
}
std::unique_lock<std::mutex> lock(mutex);
memcpy(buf_, buf.buf_, buf.capacity);
available = buf.available;
end = buf.end;
lock.unlock();
return *this;
}

u32 QueueBuf::push(u8 *buf, u32 size) {
u32 addedSize = 0;
int QueueBuf::push(const u8 *buf, int size) {
int addedSize = 0;
// This will overwrite the old data if the size prepare to add more than remaining size.
std::unique_lock<std::recursive_mutex> lock(mutex);
if (size > capacity)
resize(size);
// This will overwrite the old data if the size prepare to add more than remaining size.
std::unique_lock<std::mutex> lock(mutex);
while (end + size > capacity) {
memcpy(buf_ + end, buf + addedSize, capacity - end);
addedSize += capacity - end;
Expand All @@ -207,29 +187,33 @@ u32 QueueBuf::push(u8 *buf, u32 size) {
return addedSize;
}

u32 QueueBuf::pop(u8 *buf, u32 size) {
u32 ret = 0;
int QueueBuf::pop(u8 *buf, int size) {
if (size == 0) {
return 0;
}
int ret = 0;
std::unique_lock<std::recursive_mutex> lock(mutex);
if (getAvailableSize() < size)
size = getAvailableSize();
ret = size;

std::unique_lock<std::mutex> lock(mutex);
if (getStartPos() + size <= capacity) {
memcpy(buf, buf_ + getStartPos(), size);
int startPos = getStartPos();
if (startPos + size <= capacity) {
memcpy(buf, buf_ + startPos, size);
} else {
memcpy(buf, buf_ + getStartPos(), capacity - getStartPos());
memcpy(buf + capacity - getStartPos(), buf_, size - (capacity - getStartPos()));
memcpy(buf, buf_ + startPos, capacity - startPos);
memcpy(buf + capacity - startPos, buf_, size - (capacity - startPos));
}
available -= size;
lock.unlock();
return ret;
}

void QueueBuf::resize(u32 newSize) {
void QueueBuf::resize(int newSize) {
if (capacity >= newSize) {
return;
}
u32 availableSize = getAvailableSize();
int availableSize = getAvailableSize();
u8 *oldbuf = buf_;

buf_ = new u8[newSize];
Expand All @@ -241,21 +225,17 @@ void QueueBuf::resize(u32 newSize) {
}

void QueueBuf::flush() {
std::unique_lock<std::mutex> lock(mutex);
std::unique_lock<std::recursive_mutex> lock(mutex);
available = 0;
end = 0;
lock.unlock();
}

u32 QueueBuf::getAvailableSize() {
return available;
}

u32 QueueBuf::getRemainingSize() {
int QueueBuf::getRemainingSize() const {
return capacity - getAvailableSize();
}

u32 QueueBuf::getStartPos() {
int QueueBuf::getStartPos() const {
return end >= available ? end - available : capacity - available + end;
}

Expand Down Expand Up @@ -364,24 +344,24 @@ bool Microphone::isNeedInput() {
return ::isNeedInput;
}

u32 Microphone::numNeedSamples() {
int Microphone::numNeedSamples() {
return ::numNeedSamples;
}

u32 Microphone::availableAudioBufSize() {
int Microphone::availableAudioBufSize() {
return audioBuf->getAvailableSize();
}

u32 Microphone::getReadMicDataLength() {
int Microphone::getReadMicDataLength() {
return ::readMicDataLength;
}

int Microphone::addAudioData(u8 *buf, u32 size) {
int Microphone::addAudioData(u8 *buf, int size) {
if (!audioBuf)
return 0;
audioBuf->push(buf, size);

u32 addSize = std::min(audioBuf->getAvailableSize(), numNeedSamples() * 2 - getReadMicDataLength());
int addSize = std::min(audioBuf->getAvailableSize(), numNeedSamples() * 2 - getReadMicDataLength());
if (Memory::IsValidRange(curTargetAddr + readMicDataLength, addSize)) {
getAudioData(Memory::GetPointerWriteUnchecked(curTargetAddr + readMicDataLength), addSize);
NotifyMemInfo(MemBlockFlags::WRITE, curTargetAddr + readMicDataLength, addSize, "MicAddAudioData");
Expand All @@ -391,10 +371,9 @@ int Microphone::addAudioData(u8 *buf, u32 size) {
return size;
}

u32 Microphone::getAudioData(u8 *buf, u32 size) {
int Microphone::getAudioData(u8 *buf, int size) {
if(audioBuf)
return audioBuf->pop(buf, size);

return 0;
}

Expand Down Expand Up @@ -423,7 +402,7 @@ u32 __MicInput(u32 maxSamples, u32 sampleRate, u32 bufAddr, MICTYPE type, bool b
curSampleRate = sampleRate;
curChannels = 1;
curTargetAddr = bufAddr;
u32 size = maxSamples << 1;
int size = maxSamples << 1;
if (!audioBuf) {
audioBuf = new QueueBuf(size);
} else {
Expand Down Expand Up @@ -460,8 +439,7 @@ u32 __MicInput(u32 maxSamples, u32 sampleRate, u32 bufAddr, MICTYPE type, bool b
return type == CAMERAMIC ? size : maxSamples;
}

const HLEFunction sceUsbMic[] =
{
const HLEFunction sceUsbMic[] = {
{0x06128E42, &WrapI_V<sceUsbMicPollInputEnd>, "sceUsbMicPollInputEnd", 'i', "" },
{0x2E6DCDCD, &WrapI_UUU<sceUsbMicInputBlocking>, "sceUsbMicInputBlocking", 'i', "xxx" },
{0x45310F07, &WrapI_U<sceUsbMicInputInitEx>, "sceUsbMicInputInitEx", 'i', "x" },
Expand All @@ -471,7 +449,6 @@ const HLEFunction sceUsbMic[] =
{0xF899001C, &WrapI_V<sceUsbMicWaitInputEnd>, "sceUsbMicWaitInputEnd", 'i', "" },
};

void Register_sceUsbMic()
{
void Register_sceUsbMic() {
RegisterModule("sceUsbMic", ARRAY_SIZE(sceUsbMic), sceUsbMic);
}
44 changes: 23 additions & 21 deletions Core/HLE/sceUsbMic.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,49 +35,51 @@ enum MICTYPE {
struct MicWaitInfo {
SceUID threadID;
u32 addr;
u32 needSize;
int needSize;
u32 sampleRate;
};

class QueueBuf {
public:
QueueBuf(u32 size);
QueueBuf(int size);
~QueueBuf();

QueueBuf(const QueueBuf &buf);
QueueBuf& operator=(const QueueBuf &buf);
QueueBuf(const QueueBuf &buf) = delete;
QueueBuf& operator=(const QueueBuf &buf) = delete;

u32 push(u8 *buf, u32 size);
u32 pop(u8 *buf, u32 size);
void resize(u32 newSize);
int push(const u8 *buf, int size);
int pop(u8 *buf, int size);
void resize(int newSize);
void flush();
u32 getAvailableSize();
u32 getRemainingSize();
u32 getStartPos();
u32 getCapacity() const {
int getAvailableSize() const {
return available;
}
int getRemainingSize() const;
int getStartPos() const;
int getCapacity() const {
return capacity;
}

private:
u32 available;
u32 end;
u32 capacity;
int available = 0;
int end = 0;
int capacity; // set in constructor
u8 *buf_;
std::mutex mutex;
// TODO: Turn back to a regular mutex, will take some refactoring.
std::recursive_mutex mutex;
};

namespace Microphone {
int startMic(void *param);
int stopMic();
bool isHaveDevice();
bool isMicStarted();
u32 numNeedSamples();
u32 availableAudioBufSize();
u32 getReadMicDataLength();

int numNeedSamples();
int availableAudioBufSize();
int getReadMicDataLength();

int addAudioData(u8 *buf, u32 size);
u32 getAudioData(u8 *buf, u32 size);
int addAudioData(u8 *buf, int size);
int getAudioData(u8 *buf, int size);
void flushAudioData();

std::vector<std::string> getDeviceList();
Expand Down

0 comments on commit 65a0885

Please sign in to comment.