From aac4cbb1dcef20b5be114f61bdfe6529e66a13e4 Mon Sep 17 00:00:00 2001 From: shenweip <1037567878@qq.com> Date: Sun, 22 Nov 2020 01:17:25 +0800 Subject: [PATCH 1/8] Changes the way of reading microphone data. Feeds the microphone buffer continuously(Windows) and overwrites old data with new data when the buffer has no remaining space. --- Core/HLE/sceUsbMic.cpp | 86 ++++++++++++++++----------------------- Core/HLE/sceUsbMic.h | 9 +++- Windows/CaptureDevice.cpp | 25 +++--------- Windows/CaptureDevice.h | 1 - 4 files changed, 48 insertions(+), 73 deletions(-) diff --git a/Core/HLE/sceUsbMic.cpp b/Core/HLE/sceUsbMic.cpp index 246d8921e1..d3f2075dd9 100644 --- a/Core/HLE/sceUsbMic.cpp +++ b/Core/HLE/sceUsbMic.cpp @@ -32,6 +32,7 @@ #endif #ifdef HAVE_WIN32_MICROPHONE +#define NOMINMAX #include "Windows/CaptureDevice.h" #endif @@ -71,8 +72,6 @@ static void __UsbMicAudioUpdate(u64 userdata, int cyclesLate) { DEBUG_LOG(HLE, "sceUsbMic: Waking up thread(%d)", (int)waitingThread.threadID); __KernelResumeThreadFromWait(threadID, ret); waitingThreads.erase(waitingThreads.begin() + count); - if (waitingThreads.size() == 0) - isNeedInput = false; } else { u64 waitTimeus = (waitingThread.needSize - Microphone::availableAudioBufSize()) * 1000000 / 2 / waitingThread.sampleRate; if(eventUsbMicAudioUpdate == -1) @@ -89,8 +88,6 @@ static void __UsbMicAudioUpdate(u64 userdata, int cyclesLate) { DEBUG_LOG(HLE, "sceUsbMic: Waking up thread(%d)", (int)waitingThread.threadID); __KernelResumeThreadFromWait(threadID, ret); waitingThreads.erase(waitingThreads.begin() + count); - if (waitingThreads.size() == 0) - isNeedInput = false; } } ++count; @@ -105,7 +102,7 @@ void __UsbMicInit() { } numNeedSamples = 0; waitingThreads.clear(); - isNeedInput = false; + isNeedInput = true; curSampleRate = 44100; curChannels = 1; micState = 0; @@ -156,7 +153,7 @@ void __UsbMicDoState(PointerWrap &p) { } } -QueueBuf::QueueBuf(u32 size) : start(0), end(0), capacity(size) { +QueueBuf::QueueBuf(u32 size) : available(0), end(0), capacity(size) { buf_ = new u8[size]; } @@ -167,7 +164,7 @@ QueueBuf::~QueueBuf() { QueueBuf::QueueBuf(const QueueBuf &buf) { buf_ = new u8[buf.capacity]; memcpy(buf_, buf.buf_, buf.capacity); - start = buf.start; + available = buf.available; end = buf.end; capacity = buf.capacity; } @@ -178,27 +175,28 @@ QueueBuf& QueueBuf::operator=(const QueueBuf &buf) { } std::unique_lock lock(mutex); memcpy(buf_, buf.buf_, buf.capacity); - start = buf.start; + available = buf.available; end = buf.end; lock.unlock(); return *this; } -void QueueBuf::push(u8 *buf, u32 size) { - if (getRemainingSize() < size) { - resize((capacity + size - getRemainingSize()) * 3 / 2); - } +u32 QueueBuf::push(u8 *buf, u32 size) { + u32 addedSize = 0; + // This will overwrite the old data if the size prepare to add more than remaining size. std::unique_lock lock(mutex); - if (end + size <= capacity) { - memcpy(buf_ + end, buf, size); - end += size; - } else { - memcpy(buf_ + end, buf, capacity - end); + while (end + size > capacity) { + memcpy(buf_ + end, buf + addedSize, capacity - end); + addedSize += capacity - end; size -= capacity - end; - memcpy(buf_, buf + capacity - end, size); - end = size; + end = 0; } + memcpy(buf_ + end, buf + addedSize, size); + addedSize += size; + end = (end + size) % capacity; + available = std::min(capacity, available + addedSize); lock.unlock(); + return addedSize; } u32 QueueBuf::pop(u8 *buf, u32 size) { @@ -208,15 +206,13 @@ u32 QueueBuf::pop(u8 *buf, u32 size) { ret = size; std::unique_lock lock(mutex); - if (start + size <= capacity) { - memcpy(buf, buf_ + start, size); - start += size; + if (getStartPos() + size <= capacity) { + memcpy(buf, buf_ + getStartPos(), size); } else { - memcpy(buf, buf_ + start, capacity - start); - size -= capacity - start; - memcpy(buf + capacity - start, buf_, size); - start = size; + memcpy(buf, buf_ + getStartPos(), capacity - getStartPos()); + memcpy(buf + capacity - getStartPos(), buf_, size - (capacity - getStartPos())); } + available -= size; lock.unlock(); return ret; } @@ -228,42 +224,33 @@ void QueueBuf::resize(u32 newSize) { u32 availableSize = getAvailableSize(); u8 *oldbuf = buf_; - std::unique_lock lock(mutex); buf_ = new u8[newSize]; - if (end >= start) { - memcpy(buf_, oldbuf + start, availableSize); - } else { - memcpy(buf_, oldbuf + start, capacity - start); - memcpy(buf_ + capacity - start, oldbuf, availableSize - (capacity - start)); - } - start = 0; + pop(buf_, availableSize); + available = availableSize; end = availableSize; capacity = newSize; delete[] oldbuf; - lock.unlock(); } void QueueBuf::flush() { std::unique_lock lock(mutex); - start = 0; + available = 0; end = 0; lock.unlock(); } u32 QueueBuf::getAvailableSize() { - u32 availableSize = 0; - if (end >= start) { - availableSize = end - start; - } else { - availableSize = end + capacity - start; - } - return availableSize; + return available; } u32 QueueBuf::getRemainingSize() { return capacity - getAvailableSize(); } +u32 QueueBuf::getStartPos() { + return end >= available ? end - available : capacity - available + end; +} + static int sceUsbMicPollInputEnd() { ERROR_LOG(HLE, "UNIMPL sceUsbMicPollInputEnd"); return 0; @@ -353,6 +340,7 @@ bool Microphone::isMicStarted() { return false; } +// Deprecated. bool Microphone::isNeedInput() { return ::isNeedInput; } @@ -404,18 +392,15 @@ void Microphone::onMicDeviceChange() { u32 __MicInputBlocking(u32 maxSamples, u32 sampleRate, u32 bufAddr) { u32 size = maxSamples << 1; - if (size > numNeedSamples << 1) { - if (!audioBuf) { - audioBuf = new QueueBuf(size); - } else { - audioBuf->resize(size); - } + if (!audioBuf) { + audioBuf = new QueueBuf(size); + } else { + audioBuf->resize(size); } if (!audioBuf) return 0; numNeedSamples = maxSamples; - Microphone::flushAudioData(); if (!Microphone::isMicStarted()) { std::vector *param = new std::vector({ sampleRate, 1 }); Microphone::startMic(param); @@ -423,7 +408,6 @@ u32 __MicInputBlocking(u32 maxSamples, u32 sampleRate, u32 bufAddr) { u64 waitTimeus = 0; if (Microphone::availableAudioBufSize() < size) { waitTimeus = (size - Microphone::availableAudioBufSize()) * 1000000 / 2 / sampleRate; - isNeedInput = true; } if(eventUsbMicAudioUpdate == -1) eventUsbMicAudioUpdate = CoreTiming::RegisterEvent("UsbMicAudioUpdate", &__UsbMicAudioUpdate); diff --git a/Core/HLE/sceUsbMic.h b/Core/HLE/sceUsbMic.h index c073d4cf56..cd71c0d1c2 100644 --- a/Core/HLE/sceUsbMic.h +++ b/Core/HLE/sceUsbMic.h @@ -41,15 +41,19 @@ public: QueueBuf(const QueueBuf &buf); QueueBuf& operator=(const QueueBuf &buf); - void push(u8 *buf, u32 size); + u32 push(u8 *buf, u32 size); u32 pop(u8 *buf, u32 size); void resize(u32 newSize); void flush(); u32 getAvailableSize(); u32 getRemainingSize(); + u32 getStartPos(); + u32 getCapacity() const { + return capacity; + } private: - u32 start; + u32 available; u32 end; u32 capacity; u8 *buf_; @@ -61,6 +65,7 @@ namespace Microphone { int stopMic(); bool isHaveDevice(); bool isMicStarted(); + // Deprecated. bool isNeedInput(); u32 numNeedSamples(); u32 availableAudioBufSize(); diff --git a/Windows/CaptureDevice.cpp b/Windows/CaptureDevice.cpp index f697670992..45cbc33fb2 100644 --- a/Windows/CaptureDevice.cpp +++ b/Windows/CaptureDevice.cpp @@ -225,26 +225,14 @@ HRESULT ReaderCallback::OnReadSample( DWORD length = 0; u32 sizeAfterResample = 0; // pSample can be null, in this case ReadSample still should be called to request next frame. - if (pSample && Microphone::isNeedInput()) { + if (pSample) { pBuffer->Lock(&sampleBuf, nullptr, &length); - if (!device->rawAudioBuf) { - device->rawAudioBuf = new QueueBuf(length * 2); // Alloc enough space. - } - device->rawAudioBuf->push(sampleBuf, length); if (device->needResample()) { - sizeAfterResample = device->rawAudioBuf->getAvailableSize() * device->targetMediaParam.sampleRate / device->deviceParam.sampleRate / device->deviceParam.channels; - // Wait until have enough audio data. - if (sizeAfterResample + Microphone::availableAudioBufSize() >= Microphone::numNeedSamples() * 2) { - u32 rawAudioBufSize = device->rawAudioBuf->getAvailableSize(); - u8 *tempbuf = new u8[rawAudioBufSize]; - device->rawAudioBuf->pop(tempbuf, rawAudioBufSize); - sizeAfterResample = doResample( - &device->resampleBuf, device->targetMediaParam.sampleRate, device->targetMediaParam.channels, &device->resampleBufSize, - tempbuf, device->deviceParam.sampleRate, device->deviceParam.channels, device->deviceParam.audioFormat, rawAudioBufSize, device->deviceParam.bitsPerSample); - delete[] tempbuf; - if (device->resampleBuf) - Microphone::addAudioData(device->resampleBuf, sizeAfterResample); - } + sizeAfterResample = doResample( + &device->resampleBuf, device->targetMediaParam.sampleRate, device->targetMediaParam.channels, &device->resampleBufSize, + sampleBuf, device->deviceParam.sampleRate, device->deviceParam.channels, device->deviceParam.audioFormat, length, device->deviceParam.bitsPerSample); + if (device->resampleBuf) + Microphone::addAudioData(device->resampleBuf, sizeAfterResample); } else { Microphone::addAudioData(sampleBuf, length); } @@ -470,7 +458,6 @@ WindowsCaptureDevice::~WindowsCaptureDevice() { break; case CAPTUREDEVIDE_TYPE::AUDIO: av_freep(&resampleBuf); - delete rawAudioBuf; break; } } diff --git a/Windows/CaptureDevice.h b/Windows/CaptureDevice.h index 0829bdb2bc..5c5224f9c8 100644 --- a/Windows/CaptureDevice.h +++ b/Windows/CaptureDevice.h @@ -249,7 +249,6 @@ protected: //Microphone only u8 *resampleBuf = nullptr; u32 resampleBufSize = 0; - QueueBuf *rawAudioBuf = nullptr; }; extern WindowsCaptureDevice *winCamera; From c70c8cad6e54b67114125d402c9f1347eb0cdab8 Mon Sep 17 00:00:00 2001 From: shenweip <1037567878@qq.com> Date: Sun, 22 Nov 2020 02:06:15 +0800 Subject: [PATCH 2/8] Makes a distinction between blocking and non blocking modes. --- Core/HLE/sceAudio.cpp | 2 +- Core/HLE/sceUsbCam.cpp | 4 ++-- Core/HLE/sceUsbMic.cpp | 16 +++++++++++++--- Core/HLE/sceUsbMic.h | 2 +- 4 files changed, 17 insertions(+), 7 deletions(-) diff --git a/Core/HLE/sceAudio.cpp b/Core/HLE/sceAudio.cpp index aa247385d4..0ef9583e1a 100644 --- a/Core/HLE/sceAudio.cpp +++ b/Core/HLE/sceAudio.cpp @@ -474,7 +474,7 @@ static u32 sceAudioSRCOutputBlocking(u32 vol, u32 buf) { static int sceAudioInputBlocking(u32 maxSamples, u32 sampleRate, u32 bufAddr) { ERROR_LOG(HLE, "UNIMPL sceAudioInputBlocking: maxSamples: %d, samplerate: %d, bufAddr: %08x", maxSamples, sampleRate, bufAddr); - return __MicInputBlocking(maxSamples, sampleRate, bufAddr); + return __MicInput(maxSamples, sampleRate, bufAddr); } static u32 sceAudioRoutingSetMode(u32 mode) { diff --git a/Core/HLE/sceUsbCam.cpp b/Core/HLE/sceUsbCam.cpp index c6dccd6796..e391f52457 100644 --- a/Core/HLE/sceUsbCam.cpp +++ b/Core/HLE/sceUsbCam.cpp @@ -134,12 +134,12 @@ static int sceUsbCamStopMic() { static int sceUsbCamReadMicBlocking(u32 bufAddr, u32 size) { INFO_LOG(HLE, "UNIMPL sceUsbCamReadMicBlocking: size: %d", size); - return __MicInputBlocking(size >> 1, config->micParam.frequency, bufAddr); + return __MicInput(size >> 1, config->micParam.frequency, bufAddr); } static int sceUsbCamReadMic(u32 bufAddr, u32 size) { INFO_LOG(HLE, "UNIMPL sceUsbCamReadMic: size: %d", size); - return __MicInputBlocking(size >> 1, config->micParam.frequency, bufAddr); + return __MicInput(size >> 1, config->micParam.frequency, bufAddr, false); } static int sceUsbCamSetupVideo(u32 paramAddr, u32 workareaAddr, int wasize) { diff --git a/Core/HLE/sceUsbMic.cpp b/Core/HLE/sceUsbMic.cpp index d3f2075dd9..3248a70225 100644 --- a/Core/HLE/sceUsbMic.cpp +++ b/Core/HLE/sceUsbMic.cpp @@ -267,7 +267,7 @@ static int sceUsbMicInputBlocking(u32 maxSamples, u32 sampleRate, u32 bufAddr) { } curSampleRate = sampleRate; curChannels = 1; - return __MicInputBlocking(maxSamples, sampleRate, bufAddr); + return __MicInput(maxSamples, sampleRate, bufAddr); } static int sceUsbMicInputInitEx(u32 paramAddr) { @@ -390,7 +390,7 @@ void Microphone::onMicDeviceChange() { } } -u32 __MicInputBlocking(u32 maxSamples, u32 sampleRate, u32 bufAddr) { +u32 __MicInput(u32 maxSamples, u32 sampleRate, u32 bufAddr, bool block) { u32 size = maxSamples << 1; if (!audioBuf) { audioBuf = new QueueBuf(size); @@ -405,6 +405,16 @@ u32 __MicInputBlocking(u32 maxSamples, u32 sampleRate, u32 bufAddr) { std::vector *param = new std::vector({ sampleRate, 1 }); Microphone::startMic(param); } + if (!block) { + size = Microphone::availableAudioBufSize(); + if (size > 0) { + u8 *tempbuf8 = new u8[size]; + Microphone::getAudioData(tempbuf8, Microphone::availableAudioBufSize()); + Memory::Memcpy(bufAddr, tempbuf8, size); + delete[] tempbuf8; + } + return size; + } u64 waitTimeus = 0; if (Microphone::availableAudioBufSize() < size) { waitTimeus = (size - Microphone::availableAudioBufSize()) * 1000000 / 2 / sampleRate; @@ -419,7 +429,7 @@ u32 __MicInputBlocking(u32 maxSamples, u32 sampleRate, u32 bufAddr) { DEBUG_LOG(HLE, "MicInputBlocking: blocking thread(%d)", (int)__KernelGetCurThread()); __KernelWaitCurThread(WAITTYPE_MICINPUT, 1, size, 0, false, "blocking microphone"); - return maxSamples; + return size; } const HLEFunction sceUsbMic[] = diff --git a/Core/HLE/sceUsbMic.h b/Core/HLE/sceUsbMic.h index cd71c0d1c2..42d4d6ec53 100644 --- a/Core/HLE/sceUsbMic.h +++ b/Core/HLE/sceUsbMic.h @@ -78,4 +78,4 @@ namespace Microphone { void onMicDeviceChange(); } -u32 __MicInputBlocking(u32 maxSamples, u32 sampleRate, u32 bufAddr); +u32 __MicInput(u32 maxSamples, u32 sampleRate, u32 bufAddr, bool block = true); From f2bd0b9f6f3f9ad2a843cd562b74acba750cb630 Mon Sep 17 00:00:00 2001 From: shenweip <1037567878@qq.com> Date: Mon, 23 Nov 2020 14:07:11 +0800 Subject: [PATCH 3/8] Implements sceUsbCamGetMicDataLength. --- Core/HLE/sceUsbCam.cpp | 6 +++++- Core/HLE/sceUsbMic.cpp | 26 +++++++++++++++++--------- Core/HLE/sceUsbMic.h | 7 +++++-- 3 files changed, 27 insertions(+), 12 deletions(-) diff --git a/Core/HLE/sceUsbCam.cpp b/Core/HLE/sceUsbCam.cpp index e391f52457..d24b6ed2eb 100644 --- a/Core/HLE/sceUsbCam.cpp +++ b/Core/HLE/sceUsbCam.cpp @@ -142,6 +142,10 @@ static int sceUsbCamReadMic(u32 bufAddr, u32 size) { return __MicInput(size >> 1, config->micParam.frequency, bufAddr, false); } +static int sceUsbCamGetMicDataLength() { + return Microphone::getReadMicDataLength(); +} + static int sceUsbCamSetupVideo(u32 paramAddr, u32 workareaAddr, int wasize) { if (Memory::IsValidRange(paramAddr, sizeof(PspUsbCamSetupVideoParam))) { Memory::ReadStruct(paramAddr, &config->videoParam); @@ -251,7 +255,7 @@ const HLEFunction sceUsbCam[] = { 0X3DC0088E, &WrapI_UU, "sceUsbCamReadMic", 'i', "xx" }, { 0XB048A67D, nullptr, "sceUsbCamWaitReadMicEnd", '?', "" }, { 0XF8847F60, nullptr, "sceUsbCamPollReadMicEnd", '?', "" }, - { 0X5778B452, nullptr, "sceUsbCamGetMicDataLength", '?', "" }, + { 0X5778B452, &WrapI_V, "sceUsbCamGetMicDataLength", 'i', "" }, { 0X08AEE98A, nullptr, "sceUsbCamSetMicGain", '?', "" }, { 0X17F7B2FB, &WrapI_UUI, "sceUsbCamSetupVideo", 'i', "xxi" }, diff --git a/Core/HLE/sceUsbMic.cpp b/Core/HLE/sceUsbMic.cpp index 3248a70225..131edfe40a 100644 --- a/Core/HLE/sceUsbMic.cpp +++ b/Core/HLE/sceUsbMic.cpp @@ -50,6 +50,7 @@ std::mutex wtMutex; bool isNeedInput; u32 curSampleRate; u32 curChannels; +u32 readMicDataLength; int micState; // 0 means stopped, 1 means started, for save state. static void __UsbMicAudioUpdate(u64 userdata, int cyclesLate) { @@ -72,6 +73,7 @@ static void __UsbMicAudioUpdate(u64 userdata, int cyclesLate) { DEBUG_LOG(HLE, "sceUsbMic: Waking up thread(%d)", (int)waitingThread.threadID); __KernelResumeThreadFromWait(threadID, ret); waitingThreads.erase(waitingThreads.begin() + count); + readMicDataLength += waitingThread.needSize; } else { u64 waitTimeus = (waitingThread.needSize - Microphone::availableAudioBufSize()) * 1000000 / 2 / waitingThread.sampleRate; if(eventUsbMicAudioUpdate == -1) @@ -88,6 +90,7 @@ static void __UsbMicAudioUpdate(u64 userdata, int cyclesLate) { DEBUG_LOG(HLE, "sceUsbMic: Waking up thread(%d)", (int)waitingThread.threadID); __KernelResumeThreadFromWait(threadID, ret); waitingThreads.erase(waitingThreads.begin() + count); + readMicDataLength += waitingThread.needSize; } } ++count; @@ -183,6 +186,8 @@ QueueBuf& QueueBuf::operator=(const QueueBuf &buf) { u32 QueueBuf::push(u8 *buf, u32 size) { u32 addedSize = 0; + if (size > capacity) + resize(size); // This will overwrite the old data if the size prepare to add more than remaining size. std::unique_lock lock(mutex); while (end + size > capacity) { @@ -331,13 +336,7 @@ bool Microphone::isHaveDevice() { } bool Microphone::isMicStarted() { -#ifdef HAVE_WIN32_MICROPHONE - if(winMic) - return winMic->isStarted(); -#elif PPSSPP_PLATFORM(ANDROID) - return audioRecording_State(); -#endif - return false; + return micState == 1; } // Deprecated. @@ -353,6 +352,10 @@ u32 Microphone::availableAudioBufSize() { return audioBuf->getAvailableSize(); } +u32 Microphone::getReadMicDataLength() { + return ::readMicDataLength; +} + int Microphone::addAudioData(u8 *buf, u32 size) { if (audioBuf) audioBuf->push(buf, size); @@ -400,21 +403,26 @@ u32 __MicInput(u32 maxSamples, u32 sampleRate, u32 bufAddr, bool block) { if (!audioBuf) return 0; + readMicDataLength = 0; numNeedSamples = maxSamples; + if (!Microphone::isMicStarted()) { std::vector *param = new std::vector({ sampleRate, 1 }); Microphone::startMic(param); } + if (!block) { - size = Microphone::availableAudioBufSize(); if (size > 0) { u8 *tempbuf8 = new u8[size]; - Microphone::getAudioData(tempbuf8, Microphone::availableAudioBufSize()); + memset(tempbuf8, 0, size); + Microphone::getAudioData(tempbuf8, size); Memory::Memcpy(bufAddr, tempbuf8, size); delete[] tempbuf8; } + readMicDataLength += size; return size; } + u64 waitTimeus = 0; if (Microphone::availableAudioBufSize() < size) { waitTimeus = (size - Microphone::availableAudioBufSize()) * 1000000 / 2 / sampleRate; diff --git a/Core/HLE/sceUsbMic.h b/Core/HLE/sceUsbMic.h index 42d4d6ec53..b17087caa3 100644 --- a/Core/HLE/sceUsbMic.h +++ b/Core/HLE/sceUsbMic.h @@ -65,10 +65,10 @@ namespace Microphone { int stopMic(); bool isHaveDevice(); bool isMicStarted(); - // Deprecated. - bool isNeedInput(); u32 numNeedSamples(); u32 availableAudioBufSize(); + u32 getReadMicDataLength(); + int addAudioData(u8 *buf, u32 size); u32 getAudioData(u8 *buf, u32 size); @@ -76,6 +76,9 @@ namespace Microphone { std::vector getDeviceList(); void onMicDeviceChange(); + + // Deprecated. + bool isNeedInput(); } u32 __MicInput(u32 maxSamples, u32 sampleRate, u32 bufAddr, bool block = true); From 730d9f8fd9736758549c95e3bb2f0dcbf6ed684a Mon Sep 17 00:00:00 2001 From: shenweip <1037567878@qq.com> Date: Mon, 23 Nov 2020 15:49:14 +0800 Subject: [PATCH 4/8] Clean up. --- Core/HLE/sceAudio.cpp | 2 +- Core/HLE/sceUsbCam.cpp | 4 ++-- Core/HLE/sceUsbMic.cpp | 25 +++++++++++-------------- 3 files changed, 14 insertions(+), 17 deletions(-) diff --git a/Core/HLE/sceAudio.cpp b/Core/HLE/sceAudio.cpp index 0ef9583e1a..37f7eaa3e9 100644 --- a/Core/HLE/sceAudio.cpp +++ b/Core/HLE/sceAudio.cpp @@ -473,7 +473,7 @@ static u32 sceAudioSRCOutputBlocking(u32 vol, u32 buf) { } static int sceAudioInputBlocking(u32 maxSamples, u32 sampleRate, u32 bufAddr) { - ERROR_LOG(HLE, "UNIMPL sceAudioInputBlocking: maxSamples: %d, samplerate: %d, bufAddr: %08x", maxSamples, sampleRate, bufAddr); + INFO_LOG(HLE, "sceAudioInputBlocking: maxSamples: %d, samplerate: %d, bufAddr: %08x", maxSamples, sampleRate, bufAddr); return __MicInput(maxSamples, sampleRate, bufAddr); } diff --git a/Core/HLE/sceUsbCam.cpp b/Core/HLE/sceUsbCam.cpp index d24b6ed2eb..89d73f009f 100644 --- a/Core/HLE/sceUsbCam.cpp +++ b/Core/HLE/sceUsbCam.cpp @@ -133,12 +133,12 @@ static int sceUsbCamStopMic() { } static int sceUsbCamReadMicBlocking(u32 bufAddr, u32 size) { - INFO_LOG(HLE, "UNIMPL sceUsbCamReadMicBlocking: size: %d", size); + INFO_LOG(HLE, "sceUsbCamReadMicBlocking: size: %d", size); return __MicInput(size >> 1, config->micParam.frequency, bufAddr); } static int sceUsbCamReadMic(u32 bufAddr, u32 size) { - INFO_LOG(HLE, "UNIMPL sceUsbCamReadMic: size: %d", size); + INFO_LOG(HLE, "sceUsbCamReadMic: size: %d", size); return __MicInput(size >> 1, config->micParam.frequency, bufAddr, false); } diff --git a/Core/HLE/sceUsbMic.cpp b/Core/HLE/sceUsbMic.cpp index 131edfe40a..f28d524b40 100644 --- a/Core/HLE/sceUsbMic.cpp +++ b/Core/HLE/sceUsbMic.cpp @@ -43,21 +43,19 @@ enum { int eventUsbMicAudioUpdate = -1; -QueueBuf *audioBuf = nullptr; -u32 numNeedSamples; +static QueueBuf *audioBuf = nullptr; +static u32 numNeedSamples; static std::vector waitingThreads; -std::mutex wtMutex; -bool isNeedInput; -u32 curSampleRate; -u32 curChannels; -u32 readMicDataLength; -int micState; // 0 means stopped, 1 means started, for save state. +static bool isNeedInput; +static u32 curSampleRate; +static u32 curChannels; +static u32 readMicDataLength; +static int micState; // 0 means stopped, 1 means started, for save state. static void __UsbMicAudioUpdate(u64 userdata, int cyclesLate) { SceUID threadID = (SceUID)userdata; u32 error; int count = 0; - std::unique_lock lock(wtMutex); for (auto waitingThread : waitingThreads) { if (waitingThread.threadID == threadID) { SceUID waitID = __KernelGetWaitID(threadID, WAITTYPE_MICINPUT, error); @@ -95,7 +93,6 @@ static void __UsbMicAudioUpdate(u64 userdata, int cyclesLate) { } ++count; } - lock.unlock(); } void __UsbMicInit() { @@ -121,7 +118,7 @@ void __UsbMicShutdown() { } void __UsbMicDoState(PointerWrap &p) { - auto s = p.Section("sceUsbMic", 0, 2); + auto s = p.Section("sceUsbMic", 0, 3); if (!s) { return; } @@ -139,7 +136,9 @@ void __UsbMicDoState(PointerWrap &p) { } else { eventUsbMicAudioUpdate = -1; } - + if (s > 2) { + Do(p, readMicDataLength); + } if (!audioBuf && numNeedSamples > 0) { audioBuf = new QueueBuf(numNeedSamples << 1); } @@ -431,9 +430,7 @@ u32 __MicInput(u32 maxSamples, u32 sampleRate, u32 bufAddr, bool block) { eventUsbMicAudioUpdate = CoreTiming::RegisterEvent("UsbMicAudioUpdate", &__UsbMicAudioUpdate); CoreTiming::ScheduleEvent(usToCycles(waitTimeus), eventUsbMicAudioUpdate, __KernelGetCurThread()); MicWaitInfo waitInfo = { __KernelGetCurThread(), bufAddr, size, sampleRate }; - std::unique_lock lock(wtMutex); waitingThreads.push_back(waitInfo); - lock.unlock(); DEBUG_LOG(HLE, "MicInputBlocking: blocking thread(%d)", (int)__KernelGetCurThread()); __KernelWaitCurThread(WAITTYPE_MICINPUT, 1, size, 0, false, "blocking microphone"); From 235919f905b9e38d8c4d7b1b4780e4531607c326 Mon Sep 17 00:00:00 2001 From: shenweip <1037567878@qq.com> Date: Mon, 23 Nov 2020 17:13:55 +0800 Subject: [PATCH 5/8] Try to implement some related funcs. Marked as UNTEST. --- Core/HLE/sceAudio.cpp | 27 ++++++++++++++++++++++--- Core/HLE/sceUsbCam.cpp | 10 +++++++++ Core/HLE/sceUsbMic.cpp | 46 +++++++++++++++++++++++++++++------------- 3 files changed, 66 insertions(+), 17 deletions(-) diff --git a/Core/HLE/sceAudio.cpp b/Core/HLE/sceAudio.cpp index 37f7eaa3e9..ab69ba035b 100644 --- a/Core/HLE/sceAudio.cpp +++ b/Core/HLE/sceAudio.cpp @@ -473,10 +473,31 @@ static u32 sceAudioSRCOutputBlocking(u32 vol, u32 buf) { } static int sceAudioInputBlocking(u32 maxSamples, u32 sampleRate, u32 bufAddr) { + if (!Memory::IsValidAddress(bufAddr)) { + ERROR_LOG(HLE, "sceAudioInputBlocking(%d, %d, %08x): invalid addresses", maxSamples, sampleRate, bufAddr); + return -1; + } + INFO_LOG(HLE, "sceAudioInputBlocking: maxSamples: %d, samplerate: %d, bufAddr: %08x", maxSamples, sampleRate, bufAddr); return __MicInput(maxSamples, sampleRate, bufAddr); } +static int sceAudioInput(u32 maxSamples, u32 sampleRate, u32 bufAddr) { + if (!Memory::IsValidAddress(bufAddr)) { + ERROR_LOG(HLE, "sceAudioInput(%d, %d, %08x): invalid addresses", maxSamples, sampleRate, bufAddr); + return -1; + } + + ERROR_LOG(HLE, "UNTEST sceAudioInput: maxSamples: %d, samplerate: %d, bufAddr: %08x", maxSamples, sampleRate, bufAddr); + return __MicInput(maxSamples, sampleRate, bufAddr, false); +} + +static int sceAudioGetInputLength() { + int ret = Microphone::availableAudioBufSize() / 2; + ERROR_LOG(HLE, "UNTEST sceAudioGetInputLength(ret: %d)", ret); + return ret; +} + static u32 sceAudioRoutingSetMode(u32 mode) { ERROR_LOG_REPORT(SCEAUDIO, "sceAudioRoutingSetMode(%08x)", mode); int previousMode = defaultRoutingMode; @@ -540,9 +561,9 @@ const HLEFunction sceAudio[] = // Microphone interface {0X7DE61688, nullptr, "sceAudioInputInit", '?', "" }, {0XE926D3FB, nullptr, "sceAudioInputInitEx", '?', "" }, - {0X6D4BEC68, nullptr, "sceAudioInput", '?', "" }, - {0X086E5895, &WrapI_UUU, "sceAudioInputBlocking", 'i', "xxx" }, - {0XA708C6A6, nullptr, "sceAudioGetInputLength", '?', "" }, + {0X6D4BEC68, &WrapI_UUU, "sceAudioInput", 'i', "xxx" }, + {0X086E5895, &WrapI_UUU, "sceAudioInputBlocking", 'i', "xxx" }, + {0XA708C6A6, &WrapI_V, "sceAudioGetInputLength", 'i', "" }, {0XA633048E, nullptr, "sceAudioPollInputEnd", '?', "" }, {0X87B2E651, nullptr, "sceAudioWaitInputEnd", '?', "" }, diff --git a/Core/HLE/sceUsbCam.cpp b/Core/HLE/sceUsbCam.cpp index 89d73f009f..a9446a7ece 100644 --- a/Core/HLE/sceUsbCam.cpp +++ b/Core/HLE/sceUsbCam.cpp @@ -133,11 +133,21 @@ static int sceUsbCamStopMic() { } static int sceUsbCamReadMicBlocking(u32 bufAddr, u32 size) { + if (!Memory::IsValidAddress(bufAddr)) { + ERROR_LOG(HLE,"sceUsbCamReadMicBlocking(%08x, %d): invalid addresses", bufAddr, size); + return -1; + } + INFO_LOG(HLE, "sceUsbCamReadMicBlocking: size: %d", size); return __MicInput(size >> 1, config->micParam.frequency, bufAddr); } static int sceUsbCamReadMic(u32 bufAddr, u32 size) { + if (!Memory::IsValidAddress(bufAddr)) { + ERROR_LOG(HLE, "sceUsbCamReadMic(%08x, %d): invalid addresses", bufAddr, size); + return -1; + } + INFO_LOG(HLE, "sceUsbCamReadMic: size: %d", size); return __MicInput(size >> 1, config->micParam.frequency, bufAddr, false); } diff --git a/Core/HLE/sceUsbMic.cpp b/Core/HLE/sceUsbMic.cpp index f28d524b40..b544d29c53 100644 --- a/Core/HLE/sceUsbMic.cpp +++ b/Core/HLE/sceUsbMic.cpp @@ -71,7 +71,7 @@ static void __UsbMicAudioUpdate(u64 userdata, int cyclesLate) { DEBUG_LOG(HLE, "sceUsbMic: Waking up thread(%d)", (int)waitingThread.threadID); __KernelResumeThreadFromWait(threadID, ret); waitingThreads.erase(waitingThreads.begin() + count); - readMicDataLength += waitingThread.needSize; + readMicDataLength = waitingThread.needSize; } else { u64 waitTimeus = (waitingThread.needSize - Microphone::availableAudioBufSize()) * 1000000 / 2 / waitingThread.sampleRate; if(eventUsbMicAudioUpdate == -1) @@ -88,7 +88,7 @@ static void __UsbMicAudioUpdate(u64 userdata, int cyclesLate) { DEBUG_LOG(HLE, "sceUsbMic: Waking up thread(%d)", (int)waitingThread.threadID); __KernelResumeThreadFromWait(threadID, ret); waitingThreads.erase(waitingThreads.begin() + count); - readMicDataLength += waitingThread.needSize; + readMicDataLength = waitingThread.needSize; } } ++count; @@ -261,6 +261,11 @@ static int sceUsbMicPollInputEnd() { } static int sceUsbMicInputBlocking(u32 maxSamples, u32 sampleRate, u32 bufAddr) { + if (!Memory::IsValidAddress(bufAddr)) { + ERROR_LOG(HLE, "sceUsbMicInputBlocking(%d, %d, %08x): invalid addresses", maxSamples, sampleRate, bufAddr); + return -1; + } + INFO_LOG(HLE, "sceUsbMicInputBlocking: maxSamples: %d, samplerate: %d, bufAddr: %08x", maxSamples, sampleRate, bufAddr); if (maxSamples <= 0 || (maxSamples & 0x3F) != 0) { return SCE_USBMIC_ERROR_INVALID_MAX_SAMPLES; @@ -269,8 +274,7 @@ static int sceUsbMicInputBlocking(u32 maxSamples, u32 sampleRate, u32 bufAddr) { if (sampleRate != 44100 && sampleRate != 22050 && sampleRate != 11025) { return SCE_USBMIC_ERROR_INVALID_SAMPLERATE; } - curSampleRate = sampleRate; - curChannels = 1; + return __MicInput(maxSamples, sampleRate, bufAddr); } @@ -279,9 +283,22 @@ static int sceUsbMicInputInitEx(u32 paramAddr) { return 0; } -static int sceUsbMicInput() { - ERROR_LOG(HLE, "UNIMPL sceUsbMicInput"); - return 0; +static int sceUsbMicInput(u32 maxSamples, u32 sampleRate, u32 bufAddr) { + if (!Memory::IsValidAddress(bufAddr)) { + ERROR_LOG(HLE, "sceUsbMicInput(%d, %d, %08x): invalid addresses", maxSamples, sampleRate, bufAddr); + return -1; + } + + ERROR_LOG(HLE, "UNTEST sceUsbMicInput: maxSamples: %d, samplerate: %d, bufAddr: %08x", maxSamples, sampleRate, bufAddr); + if (maxSamples <= 0 || (maxSamples & 0x3F) != 0) { + return SCE_USBMIC_ERROR_INVALID_MAX_SAMPLES; + } + + if (sampleRate != 44100 && sampleRate != 22050 && sampleRate != 11025) { + return SCE_USBMIC_ERROR_INVALID_SAMPLERATE; + } + + return __MicInput(maxSamples, sampleRate, bufAddr, false); } static int sceUsbMicGetInputLength() { int ret = Microphone::availableAudioBufSize() / 2; @@ -393,6 +410,8 @@ void Microphone::onMicDeviceChange() { } u32 __MicInput(u32 maxSamples, u32 sampleRate, u32 bufAddr, bool block) { + curSampleRate = sampleRate; + curChannels = 1; u32 size = maxSamples << 1; if (!audioBuf) { audioBuf = new QueueBuf(size); @@ -402,7 +421,6 @@ u32 __MicInput(u32 maxSamples, u32 sampleRate, u32 bufAddr, bool block) { if (!audioBuf) return 0; - readMicDataLength = 0; numNeedSamples = maxSamples; if (!Microphone::isMicStarted()) { @@ -418,7 +436,7 @@ u32 __MicInput(u32 maxSamples, u32 sampleRate, u32 bufAddr, bool block) { Memory::Memcpy(bufAddr, tempbuf8, size); delete[] tempbuf8; } - readMicDataLength += size; + readMicDataLength = size; return size; } @@ -439,13 +457,13 @@ u32 __MicInput(u32 maxSamples, u32 sampleRate, u32 bufAddr, bool block) { const HLEFunction sceUsbMic[] = { - {0x06128E42, &WrapI_V, "sceUsbMicPollInputEnd", 'i', "" }, + {0x06128E42, &WrapI_V, "sceUsbMicPollInputEnd", 'i', "" }, {0x2E6DCDCD, &WrapI_UUU, "sceUsbMicInputBlocking", 'i', "xxx" }, - {0x45310F07, &WrapI_U, "sceUsbMicInputInitEx", 'i', "x" }, - {0x5F7F368D, &WrapI_V, "sceUsbMicInput", 'i', "" }, - {0x63400E20, &WrapI_V, "sceUsbMicGetInputLength", 'i', "" }, + {0x45310F07, &WrapI_U, "sceUsbMicInputInitEx", 'i', "x" }, + {0x5F7F368D, &WrapI_UUU, "sceUsbMicInput", 'i', "xxx" }, + {0x63400E20, &WrapI_V, "sceUsbMicGetInputLength", 'i', "" }, {0xB8E536EB, &WrapI_III, "sceUsbMicInputInit", 'i', "iii" }, - {0xF899001C, &WrapI_V, "sceUsbMicWaitInputEnd", 'i', "" }, + {0xF899001C, &WrapI_V, "sceUsbMicWaitInputEnd", 'i', "" }, }; void Register_sceUsbMic() From 9a85ab2c438f966f18aa231529328c3122720e9f Mon Sep 17 00:00:00 2001 From: shenweip <1037567878@qq.com> Date: Tue, 24 Nov 2020 17:15:26 +0800 Subject: [PATCH 6/8] Writes target buffer address in multiple times. Would be better to calculate read data length. --- Core/HLE/sceAudio.cpp | 6 +-- Core/HLE/sceUsbCam.cpp | 4 +- Core/HLE/sceUsbMic.cpp | 86 ++++++++++++++++++++++-------------------- Core/HLE/sceUsbMic.h | 8 +++- 4 files changed, 58 insertions(+), 46 deletions(-) diff --git a/Core/HLE/sceAudio.cpp b/Core/HLE/sceAudio.cpp index ab69ba035b..06996a8205 100644 --- a/Core/HLE/sceAudio.cpp +++ b/Core/HLE/sceAudio.cpp @@ -479,7 +479,7 @@ static int sceAudioInputBlocking(u32 maxSamples, u32 sampleRate, u32 bufAddr) { } INFO_LOG(HLE, "sceAudioInputBlocking: maxSamples: %d, samplerate: %d, bufAddr: %08x", maxSamples, sampleRate, bufAddr); - return __MicInput(maxSamples, sampleRate, bufAddr); + return __MicInput(maxSamples, sampleRate, bufAddr, AUDIOINPUT); } static int sceAudioInput(u32 maxSamples, u32 sampleRate, u32 bufAddr) { @@ -489,11 +489,11 @@ static int sceAudioInput(u32 maxSamples, u32 sampleRate, u32 bufAddr) { } ERROR_LOG(HLE, "UNTEST sceAudioInput: maxSamples: %d, samplerate: %d, bufAddr: %08x", maxSamples, sampleRate, bufAddr); - return __MicInput(maxSamples, sampleRate, bufAddr, false); + return __MicInput(maxSamples, sampleRate, bufAddr, AUDIOINPUT, false); } static int sceAudioGetInputLength() { - int ret = Microphone::availableAudioBufSize() / 2; + int ret = Microphone::getReadMicDataLength() / 2; ERROR_LOG(HLE, "UNTEST sceAudioGetInputLength(ret: %d)", ret); return ret; } diff --git a/Core/HLE/sceUsbCam.cpp b/Core/HLE/sceUsbCam.cpp index a9446a7ece..3882e140fb 100644 --- a/Core/HLE/sceUsbCam.cpp +++ b/Core/HLE/sceUsbCam.cpp @@ -139,7 +139,7 @@ static int sceUsbCamReadMicBlocking(u32 bufAddr, u32 size) { } INFO_LOG(HLE, "sceUsbCamReadMicBlocking: size: %d", size); - return __MicInput(size >> 1, config->micParam.frequency, bufAddr); + return __MicInput(size >> 1, config->micParam.frequency, bufAddr, CAMERAMIC); } static int sceUsbCamReadMic(u32 bufAddr, u32 size) { @@ -149,7 +149,7 @@ static int sceUsbCamReadMic(u32 bufAddr, u32 size) { } INFO_LOG(HLE, "sceUsbCamReadMic: size: %d", size); - return __MicInput(size >> 1, config->micParam.frequency, bufAddr, false); + return __MicInput(size >> 1, config->micParam.frequency, bufAddr, CAMERAMIC, false); } static int sceUsbCamGetMicDataLength() { diff --git a/Core/HLE/sceUsbMic.cpp b/Core/HLE/sceUsbMic.cpp index b544d29c53..52f96c9609 100644 --- a/Core/HLE/sceUsbMic.cpp +++ b/Core/HLE/sceUsbMic.cpp @@ -41,7 +41,7 @@ enum { SCE_USBMIC_ERROR_INVALID_SAMPLERATE = 0x8024380A, }; -int eventUsbMicAudioUpdate = -1; +int eventMicBlockingResume = -1; static QueueBuf *audioBuf = nullptr; static u32 numNeedSamples; @@ -50,9 +50,10 @@ static bool isNeedInput; static u32 curSampleRate; static u32 curChannels; static u32 readMicDataLength; +static u32 curTargetAddr; static int micState; // 0 means stopped, 1 means started, for save state. -static void __UsbMicAudioUpdate(u64 userdata, int cyclesLate) { +static void __MicBlockingResume(u64 userdata, int cyclesLate) { SceUID threadID = (SceUID)userdata; u32 error; int count = 0; @@ -62,21 +63,16 @@ static void __UsbMicAudioUpdate(u64 userdata, int cyclesLate) { if (waitID == 0) continue; if (Microphone::isHaveDevice()) { - if (Microphone::availableAudioBufSize() >= waitingThread.needSize) { - u8 *tempbuf8 = new u8[waitingThread.needSize]; - Microphone::getAudioData(tempbuf8, waitingThread.needSize); - Memory::Memcpy(waitingThread.addr, tempbuf8, waitingThread.needSize); - delete[] tempbuf8; + if (Microphone::getReadMicDataLength() >= waitingThread.needSize) { u32 ret = __KernelGetWaitValue(threadID, error); DEBUG_LOG(HLE, "sceUsbMic: Waking up thread(%d)", (int)waitingThread.threadID); __KernelResumeThreadFromWait(threadID, ret); waitingThreads.erase(waitingThreads.begin() + count); - readMicDataLength = waitingThread.needSize; } else { - u64 waitTimeus = (waitingThread.needSize - Microphone::availableAudioBufSize()) * 1000000 / 2 / waitingThread.sampleRate; - if(eventUsbMicAudioUpdate == -1) - eventUsbMicAudioUpdate = CoreTiming::RegisterEvent("UsbMicAudioUpdate", &__UsbMicAudioUpdate); - CoreTiming::ScheduleEvent(usToCycles(waitTimeus), eventUsbMicAudioUpdate, userdata); + u64 waitTimeus = (waitingThread.needSize - Microphone::getReadMicDataLength()) * 1000000 / 2 / waitingThread.sampleRate; + if(eventMicBlockingResume == -1) + eventMicBlockingResume = CoreTiming::RegisterEvent("MicBlockingResume", &__MicBlockingResume); + CoreTiming::ScheduleEvent(usToCycles(waitTimeus), eventMicBlockingResume, userdata); } } else { for (u32 i = 0; i < waitingThread.needSize; i++) { @@ -88,7 +84,7 @@ static void __UsbMicAudioUpdate(u64 userdata, int cyclesLate) { DEBUG_LOG(HLE, "sceUsbMic: Waking up thread(%d)", (int)waitingThread.threadID); __KernelResumeThreadFromWait(threadID, ret); waitingThreads.erase(waitingThreads.begin() + count); - readMicDataLength = waitingThread.needSize; + readMicDataLength += waitingThread.needSize; } } ++count; @@ -105,8 +101,10 @@ void __UsbMicInit() { isNeedInput = true; curSampleRate = 44100; curChannels = 1; + curTargetAddr = 0; + readMicDataLength = 0; micState = 0; - eventUsbMicAudioUpdate = CoreTiming::RegisterEvent("UsbMicAudioUpdate", &__UsbMicAudioUpdate); + eventMicBlockingResume = CoreTiming::RegisterEvent("MicBlockingResume", &__MicBlockingResume); } void __UsbMicShutdown() { @@ -129,14 +127,15 @@ void __UsbMicDoState(PointerWrap &p) { Do(p, curChannels); Do(p, micState); if (s > 1) { - Do(p, eventUsbMicAudioUpdate); - if (eventUsbMicAudioUpdate != -1) { - CoreTiming::RestoreRegisterEvent(eventUsbMicAudioUpdate, "UsbMicAudioUpdate", &__UsbMicAudioUpdate); + Do(p, eventMicBlockingResume); + if (eventMicBlockingResume != -1) { + CoreTiming::RestoreRegisterEvent(eventMicBlockingResume, "MicBlockingResume", &__MicBlockingResume); } } else { - eventUsbMicAudioUpdate = -1; + eventMicBlockingResume = -1; } if (s > 2) { + Do(p, curTargetAddr); Do(p, readMicDataLength); } if (!audioBuf && numNeedSamples > 0) { @@ -275,7 +274,7 @@ static int sceUsbMicInputBlocking(u32 maxSamples, u32 sampleRate, u32 bufAddr) { return SCE_USBMIC_ERROR_INVALID_SAMPLERATE; } - return __MicInput(maxSamples, sampleRate, bufAddr); + return __MicInput(maxSamples, sampleRate, bufAddr, USBMIC); } static int sceUsbMicInputInitEx(u32 paramAddr) { @@ -298,10 +297,10 @@ static int sceUsbMicInput(u32 maxSamples, u32 sampleRate, u32 bufAddr) { return SCE_USBMIC_ERROR_INVALID_SAMPLERATE; } - return __MicInput(maxSamples, sampleRate, bufAddr, false); + return __MicInput(maxSamples, sampleRate, bufAddr, USBMIC, false); } static int sceUsbMicGetInputLength() { - int ret = Microphone::availableAudioBufSize() / 2; + int ret = Microphone::getReadMicDataLength() / 2; ERROR_LOG(HLE, "UNTEST sceUsbMicGetInputLength(ret: %d)", ret); return ret; } @@ -377,6 +376,14 @@ int Microphone::addAudioData(u8 *buf, u32 size) { audioBuf->push(buf, size); else return 0; + if (Memory::IsValidAddress(curTargetAddr)) { + u32 addSize = std::min(audioBuf->getAvailableSize(), numNeedSamples() * 2 - getReadMicDataLength()); + u8 *tempbuf8 = new u8[addSize]; + getAudioData(tempbuf8, addSize); + Memory::Memcpy(curTargetAddr + readMicDataLength, tempbuf8, addSize); + delete[] tempbuf8; + readMicDataLength += addSize; + } return size; } @@ -409,9 +416,10 @@ void Microphone::onMicDeviceChange() { } } -u32 __MicInput(u32 maxSamples, u32 sampleRate, u32 bufAddr, bool block) { +u32 __MicInput(u32 maxSamples, u32 sampleRate, u32 bufAddr, MICTYPE type, bool block) { curSampleRate = sampleRate; curChannels = 1; + curTargetAddr = bufAddr; u32 size = maxSamples << 1; if (!audioBuf) { audioBuf = new QueueBuf(size); @@ -422,37 +430,35 @@ u32 __MicInput(u32 maxSamples, u32 sampleRate, u32 bufAddr, bool block) { return 0; numNeedSamples = maxSamples; - + readMicDataLength = 0; if (!Microphone::isMicStarted()) { std::vector *param = new std::vector({ sampleRate, 1 }); Microphone::startMic(param); } - if (!block) { - if (size > 0) { - u8 *tempbuf8 = new u8[size]; - memset(tempbuf8, 0, size); - Microphone::getAudioData(tempbuf8, size); - Memory::Memcpy(bufAddr, tempbuf8, size); - delete[] tempbuf8; - } - readMicDataLength = size; - return size; + if (Microphone::availableAudioBufSize() > 0) { + u32 addSize = std::min(Microphone::availableAudioBufSize(), size); + u8 *tempbuf8 = new u8[addSize]; + Microphone::getAudioData(tempbuf8, addSize); + Memory::Memcpy(curTargetAddr, tempbuf8, addSize); + delete[] tempbuf8; + readMicDataLength += addSize; } - u64 waitTimeus = 0; - if (Microphone::availableAudioBufSize() < size) { - waitTimeus = (size - Microphone::availableAudioBufSize()) * 1000000 / 2 / sampleRate; + if (!block) { + return type == CAMERAMIC ? size : maxSamples; } - if(eventUsbMicAudioUpdate == -1) - eventUsbMicAudioUpdate = CoreTiming::RegisterEvent("UsbMicAudioUpdate", &__UsbMicAudioUpdate); - CoreTiming::ScheduleEvent(usToCycles(waitTimeus), eventUsbMicAudioUpdate, __KernelGetCurThread()); + + u64 waitTimeus = (size - Microphone::availableAudioBufSize()) * 1000000 / 2 / sampleRate; + if (eventMicBlockingResume == -1) + eventMicBlockingResume = CoreTiming::RegisterEvent("MicBlockingResume", &__MicBlockingResume); + CoreTiming::ScheduleEvent(usToCycles(waitTimeus), eventMicBlockingResume, __KernelGetCurThread()); MicWaitInfo waitInfo = { __KernelGetCurThread(), bufAddr, size, sampleRate }; waitingThreads.push_back(waitInfo); DEBUG_LOG(HLE, "MicInputBlocking: blocking thread(%d)", (int)__KernelGetCurThread()); __KernelWaitCurThread(WAITTYPE_MICINPUT, 1, size, 0, false, "blocking microphone"); - return size; + return type == CAMERAMIC ? size : maxSamples; } const HLEFunction sceUsbMic[] = diff --git a/Core/HLE/sceUsbMic.h b/Core/HLE/sceUsbMic.h index b17087caa3..a05d142709 100644 --- a/Core/HLE/sceUsbMic.h +++ b/Core/HLE/sceUsbMic.h @@ -26,6 +26,12 @@ void __UsbMicInit(); void __UsbMicShutdown(); void __UsbMicDoState(PointerWrap &p); +enum MICTYPE { + AUDIOINPUT, + USBMIC, + CAMERAMIC +}; + struct MicWaitInfo { SceUID threadID; u32 addr; @@ -81,4 +87,4 @@ namespace Microphone { bool isNeedInput(); } -u32 __MicInput(u32 maxSamples, u32 sampleRate, u32 bufAddr, bool block = true); +u32 __MicInput(u32 maxSamples, u32 sampleRate, u32 bufAddr, MICTYPE type, bool block = true); From be0449d16de5c4b717c82b1bd5ba256151a44a3b Mon Sep 17 00:00:00 2001 From: shenweip <1037567878@qq.com> Date: Tue, 24 Nov 2020 17:28:31 +0800 Subject: [PATCH 7/8] Fixes state. --- Core/HLE/sceUsbMic.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/Core/HLE/sceUsbMic.cpp b/Core/HLE/sceUsbMic.cpp index 52f96c9609..ed7fe29e9b 100644 --- a/Core/HLE/sceUsbMic.cpp +++ b/Core/HLE/sceUsbMic.cpp @@ -120,6 +120,7 @@ void __UsbMicDoState(PointerWrap &p) { if (!s) { return; } + bool isMicStartedNow = Microphone::isMicStarted(); Do(p, numNeedSamples); Do(p, waitingThreads); Do(p, isNeedInput); @@ -143,10 +144,10 @@ void __UsbMicDoState(PointerWrap &p) { } if (micState == 0) { - if (Microphone::isMicStarted()) + if (isMicStartedNow) Microphone::stopMic(); } else if (micState == 1) { - if (Microphone::isMicStarted()) { + if (isMicStartedNow) { // Ok, started. } else { Microphone::startMic(new std::vector({ curSampleRate, curChannels })); From 6afeed877c9b9573477cb78e028d534112ae1bcd Mon Sep 17 00:00:00 2001 From: shenweip <1037567878@qq.com> Date: Tue, 24 Nov 2020 21:36:17 +0800 Subject: [PATCH 8/8] Build fixes --- Core/HLE/sceUsbMic.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/Core/HLE/sceUsbMic.cpp b/Core/HLE/sceUsbMic.cpp index ed7fe29e9b..086b968f45 100644 --- a/Core/HLE/sceUsbMic.cpp +++ b/Core/HLE/sceUsbMic.cpp @@ -15,6 +15,7 @@ // Official git repository and contact information can be found at // https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/. +#include #include #include "Common/Serialize/Serializer.h"