1 // Copyright (c) 2019- PPSSPP Project.
2
3 // This program is free software: you can redistribute it and/or modify
4 // it under the terms of the GNU General Public License as published by
5 // the Free Software Foundation, version 2.0 or later versions.
6
7 // This program is distributed in the hope that it will be useful,
8 // but WITHOUT ANY WARRANTY; without even the implied warranty of
9 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 // GNU General Public License 2.0 for more details.
11
12 // A copy of the GPL 2.0 should have been included with the program.
13 // If not, see http://www.gnu.org/licenses/
14
15 // Official git repository and contact information can be found at
16 // https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/.
17
18 #include "ppsspp_config.h"
19 #include <algorithm>
20 #include <mutex>
21
22 #include "Common/Serialize/Serializer.h"
23 #include "Common/Serialize/SerializeFuncs.h"
24 #include "Common/System/System.h"
25 #include "Core/HLE/HLE.h"
26 #include "Core/HLE/FunctionWrappers.h"
27 #include "Core/HLE/sceKernelThread.h"
28 #include "Core/HLE/sceUsbMic.h"
29 #include "Core/CoreTiming.h"
30 #include "Core/MemMapHelpers.h"
31
32 #if defined(_WIN32) && !PPSSPP_PLATFORM(UWP) && !defined(__LIBRETRO__)
33 #define HAVE_WIN32_MICROPHONE
34 #endif
35
36 #ifdef HAVE_WIN32_MICROPHONE
37 #include "Common/CommonWindows.h"
38 #include "Windows/CaptureDevice.h"
39 #endif
40
41 enum {
42 SCE_USBMIC_ERROR_INVALID_MAX_SAMPLES = 0x80243806,
43 SCE_USBMIC_ERROR_INVALID_SAMPLERATE = 0x8024380A,
44 };
45
46 int eventMicBlockingResume = -1;
47
48 static QueueBuf *audioBuf = nullptr;
49 static u32 numNeedSamples;
50 static std::vector<MicWaitInfo> waitingThreads;
51 static bool isNeedInput;
52 static u32 curSampleRate;
53 static u32 curChannels;
54 static u32 readMicDataLength;
55 static u32 curTargetAddr;
56 static int micState; // 0 means stopped, 1 means started, for save state.
57
__MicBlockingResume(u64 userdata,int cyclesLate)58 static void __MicBlockingResume(u64 userdata, int cyclesLate) {
59 SceUID threadID = (SceUID)userdata;
60 u32 error;
61 int count = 0;
62 for (auto waitingThread : waitingThreads) {
63 if (waitingThread.threadID == threadID) {
64 SceUID waitID = __KernelGetWaitID(threadID, WAITTYPE_MICINPUT, error);
65 if (waitID == 0)
66 continue;
67 if (Microphone::isHaveDevice()) {
68 if (Microphone::getReadMicDataLength() >= waitingThread.needSize) {
69 u32 ret = __KernelGetWaitValue(threadID, error);
70 DEBUG_LOG(HLE, "sceUsbMic: Waking up thread(%d)", (int)waitingThread.threadID);
71 __KernelResumeThreadFromWait(threadID, ret);
72 waitingThreads.erase(waitingThreads.begin() + count);
73 } else {
74 u64 waitTimeus = (waitingThread.needSize - Microphone::getReadMicDataLength()) * 1000000 / 2 / waitingThread.sampleRate;
75 CoreTiming::ScheduleEvent(usToCycles(waitTimeus), eventMicBlockingResume, userdata);
76 }
77 } else {
78 for (u32 i = 0; i < waitingThread.needSize; i++) {
79 if (Memory::IsValidAddress(waitingThread.addr + i)) {
80 Memory::Write_U8(i & 0xFF, waitingThread.addr + i);
81 }
82 }
83 u32 ret = __KernelGetWaitValue(threadID, error);
84 DEBUG_LOG(HLE, "sceUsbMic: Waking up thread(%d)", (int)waitingThread.threadID);
85 __KernelResumeThreadFromWait(threadID, ret);
86 waitingThreads.erase(waitingThreads.begin() + count);
87 readMicDataLength += waitingThread.needSize;
88 }
89 }
90 ++count;
91 }
92 }
93
__UsbMicInit()94 void __UsbMicInit() {
95 if (audioBuf) {
96 delete audioBuf;
97 audioBuf = nullptr;
98 }
99 numNeedSamples = 0;
100 waitingThreads.clear();
101 isNeedInput = true;
102 curSampleRate = 44100;
103 curChannels = 1;
104 curTargetAddr = 0;
105 readMicDataLength = 0;
106 micState = 0;
107 eventMicBlockingResume = CoreTiming::RegisterEvent("MicBlockingResume", &__MicBlockingResume);
108 }
109
__UsbMicShutdown()110 void __UsbMicShutdown() {
111 if (audioBuf) {
112 delete audioBuf;
113 audioBuf = nullptr;
114 }
115 Microphone::stopMic();
116 }
117
__UsbMicDoState(PointerWrap & p)118 void __UsbMicDoState(PointerWrap &p) {
119 auto s = p.Section("sceUsbMic", 0, 3);
120 if (!s) {
121 // Still need to restore the event.
122 eventMicBlockingResume = -1;
123 CoreTiming::RestoreRegisterEvent(eventMicBlockingResume, "MicBlockingResume", &__MicBlockingResume);
124 waitingThreads.clear();
125 return;
126 }
127 bool isMicStartedNow = Microphone::isMicStarted();
128 Do(p, numNeedSamples);
129 Do(p, waitingThreads);
130 Do(p, isNeedInput);
131 Do(p, curSampleRate);
132 Do(p, curChannels);
133 Do(p, micState);
134 if (s > 1) {
135 Do(p, eventMicBlockingResume);
136 } else {
137 eventMicBlockingResume = -1;
138 }
139 CoreTiming::RestoreRegisterEvent(eventMicBlockingResume, "MicBlockingResume", &__MicBlockingResume);
140
141 if (s > 2) {
142 Do(p, curTargetAddr);
143 Do(p, readMicDataLength);
144 }
145 if (!audioBuf && numNeedSamples > 0) {
146 audioBuf = new QueueBuf(numNeedSamples << 1);
147 }
148
149 if (micState == 0) {
150 if (isMicStartedNow)
151 Microphone::stopMic();
152 } else if (micState == 1) {
153 if (isMicStartedNow) {
154 // Ok, started.
155 } else {
156 Microphone::startMic(new std::vector<u32>({ curSampleRate, curChannels }));
157 }
158 }
159 }
160
QueueBuf(u32 size)161 QueueBuf::QueueBuf(u32 size) : available(0), end(0), capacity(size) {
162 buf_ = new u8[size];
163 }
164
~QueueBuf()165 QueueBuf::~QueueBuf() {
166 delete[] buf_;
167 }
168
QueueBuf(const QueueBuf & buf)169 QueueBuf::QueueBuf(const QueueBuf &buf) {
170 buf_ = new u8[buf.capacity];
171 memcpy(buf_, buf.buf_, buf.capacity);
172 available = buf.available;
173 end = buf.end;
174 capacity = buf.capacity;
175 }
176
operator =(const QueueBuf & buf)177 QueueBuf& QueueBuf::operator=(const QueueBuf &buf) {
178 if (capacity < buf.capacity) {
179 resize(buf.capacity);
180 }
181 std::unique_lock<std::mutex> lock(mutex);
182 memcpy(buf_, buf.buf_, buf.capacity);
183 available = buf.available;
184 end = buf.end;
185 lock.unlock();
186 return *this;
187 }
188
push(u8 * buf,u32 size)189 u32 QueueBuf::push(u8 *buf, u32 size) {
190 u32 addedSize = 0;
191 if (size > capacity)
192 resize(size);
193 // This will overwrite the old data if the size prepare to add more than remaining size.
194 std::unique_lock<std::mutex> lock(mutex);
195 while (end + size > capacity) {
196 memcpy(buf_ + end, buf + addedSize, capacity - end);
197 addedSize += capacity - end;
198 size -= capacity - end;
199 end = 0;
200 }
201 memcpy(buf_ + end, buf + addedSize, size);
202 addedSize += size;
203 end = (end + size) % capacity;
204 available = std::min(capacity, available + addedSize);
205 lock.unlock();
206 return addedSize;
207 }
208
pop(u8 * buf,u32 size)209 u32 QueueBuf::pop(u8 *buf, u32 size) {
210 u32 ret = 0;
211 if (getAvailableSize() < size)
212 size = getAvailableSize();
213 ret = size;
214
215 std::unique_lock<std::mutex> lock(mutex);
216 if (getStartPos() + size <= capacity) {
217 memcpy(buf, buf_ + getStartPos(), size);
218 } else {
219 memcpy(buf, buf_ + getStartPos(), capacity - getStartPos());
220 memcpy(buf + capacity - getStartPos(), buf_, size - (capacity - getStartPos()));
221 }
222 available -= size;
223 lock.unlock();
224 return ret;
225 }
226
resize(u32 newSize)227 void QueueBuf::resize(u32 newSize) {
228 if (capacity >= newSize) {
229 return;
230 }
231 u32 availableSize = getAvailableSize();
232 u8 *oldbuf = buf_;
233
234 buf_ = new u8[newSize];
235 pop(buf_, availableSize);
236 available = availableSize;
237 end = availableSize;
238 capacity = newSize;
239 delete[] oldbuf;
240 }
241
flush()242 void QueueBuf::flush() {
243 std::unique_lock<std::mutex> lock(mutex);
244 available = 0;
245 end = 0;
246 lock.unlock();
247 }
248
getAvailableSize()249 u32 QueueBuf::getAvailableSize() {
250 return available;
251 }
252
getRemainingSize()253 u32 QueueBuf::getRemainingSize() {
254 return capacity - getAvailableSize();
255 }
256
getStartPos()257 u32 QueueBuf::getStartPos() {
258 return end >= available ? end - available : capacity - available + end;
259 }
260
sceUsbMicPollInputEnd()261 static int sceUsbMicPollInputEnd() {
262 ERROR_LOG(HLE, "UNIMPL sceUsbMicPollInputEnd");
263 return 0;
264 }
265
sceUsbMicInputBlocking(u32 maxSamples,u32 sampleRate,u32 bufAddr)266 static int sceUsbMicInputBlocking(u32 maxSamples, u32 sampleRate, u32 bufAddr) {
267 if (!Memory::IsValidAddress(bufAddr)) {
268 ERROR_LOG(HLE, "sceUsbMicInputBlocking(%d, %d, %08x): invalid addresses", maxSamples, sampleRate, bufAddr);
269 return -1;
270 }
271
272 INFO_LOG(HLE, "sceUsbMicInputBlocking: maxSamples: %d, samplerate: %d, bufAddr: %08x", maxSamples, sampleRate, bufAddr);
273 if (maxSamples <= 0 || (maxSamples & 0x3F) != 0) {
274 return SCE_USBMIC_ERROR_INVALID_MAX_SAMPLES;
275 }
276
277 if (sampleRate != 44100 && sampleRate != 22050 && sampleRate != 11025) {
278 return SCE_USBMIC_ERROR_INVALID_SAMPLERATE;
279 }
280
281 return __MicInput(maxSamples, sampleRate, bufAddr, USBMIC);
282 }
283
sceUsbMicInputInitEx(u32 paramAddr)284 static int sceUsbMicInputInitEx(u32 paramAddr) {
285 ERROR_LOG(HLE, "UNIMPL sceUsbMicInputInitEx: %08x", paramAddr);
286 return 0;
287 }
288
sceUsbMicInput(u32 maxSamples,u32 sampleRate,u32 bufAddr)289 static int sceUsbMicInput(u32 maxSamples, u32 sampleRate, u32 bufAddr) {
290 if (!Memory::IsValidAddress(bufAddr)) {
291 ERROR_LOG(HLE, "sceUsbMicInput(%d, %d, %08x): invalid addresses", maxSamples, sampleRate, bufAddr);
292 return -1;
293 }
294
295 ERROR_LOG(HLE, "UNTEST sceUsbMicInput: maxSamples: %d, samplerate: %d, bufAddr: %08x", maxSamples, sampleRate, bufAddr);
296 if (maxSamples <= 0 || (maxSamples & 0x3F) != 0) {
297 return SCE_USBMIC_ERROR_INVALID_MAX_SAMPLES;
298 }
299
300 if (sampleRate != 44100 && sampleRate != 22050 && sampleRate != 11025) {
301 return SCE_USBMIC_ERROR_INVALID_SAMPLERATE;
302 }
303
304 return __MicInput(maxSamples, sampleRate, bufAddr, USBMIC, false);
305 }
sceUsbMicGetInputLength()306 static int sceUsbMicGetInputLength() {
307 int ret = Microphone::getReadMicDataLength() / 2;
308 ERROR_LOG(HLE, "UNTEST sceUsbMicGetInputLength(ret: %d)", ret);
309 return ret;
310 }
311
sceUsbMicInputInit(int unknown1,int inputVolume,int unknown2)312 static int sceUsbMicInputInit(int unknown1, int inputVolume, int unknown2) {
313 ERROR_LOG(HLE, "UNIMPL sceUsbMicInputInit(unknown1: %d, inputVolume: %d, unknown2: %d)", unknown1, inputVolume, unknown2);
314 return 0;
315 }
316
sceUsbMicWaitInputEnd()317 static int sceUsbMicWaitInputEnd() {
318 ERROR_LOG(HLE, "UNIMPL sceUsbMicWaitInputEnd");
319 return 0;
320 }
321
startMic(void * param)322 int Microphone::startMic(void *param) {
323 #ifdef HAVE_WIN32_MICROPHONE
324 if (winMic)
325 winMic->sendMessage({ CAPTUREDEVIDE_COMMAND::START, param });
326 #elif PPSSPP_PLATFORM(ANDROID)
327 std::vector<u32> *micParam = static_cast<std::vector<u32>*>(param);
328 int sampleRate = micParam->at(0);
329 int channels = micParam->at(1);
330 INFO_LOG(HLE, "microphone_command : sr = %d", sampleRate);
331 System_SendMessage("microphone_command", ("startRecording:" + std::to_string(sampleRate)).c_str());
332 #endif
333 micState = 1;
334 return 0;
335 }
336
stopMic()337 int Microphone::stopMic() {
338 #ifdef HAVE_WIN32_MICROPHONE
339 if (winMic)
340 winMic->sendMessage({ CAPTUREDEVIDE_COMMAND::STOP, nullptr });
341 #elif PPSSPP_PLATFORM(ANDROID)
342 System_SendMessage("microphone_command", "stopRecording");
343 #endif
344 micState = 0;
345 return 0;
346 }
347
isHaveDevice()348 bool Microphone::isHaveDevice() {
349 #ifdef HAVE_WIN32_MICROPHONE
350 return winMic->getDeviceCounts() >= 1;
351 #elif PPSSPP_PLATFORM(ANDROID)
352 return audioRecording_Available();
353 #endif
354 return false;
355 }
356
isMicStarted()357 bool Microphone::isMicStarted() {
358 return micState == 1;
359 }
360
361 // Deprecated.
isNeedInput()362 bool Microphone::isNeedInput() {
363 return ::isNeedInput;
364 }
365
numNeedSamples()366 u32 Microphone::numNeedSamples() {
367 return ::numNeedSamples;
368 }
369
availableAudioBufSize()370 u32 Microphone::availableAudioBufSize() {
371 return audioBuf->getAvailableSize();
372 }
373
getReadMicDataLength()374 u32 Microphone::getReadMicDataLength() {
375 return ::readMicDataLength;
376 }
377
addAudioData(u8 * buf,u32 size)378 int Microphone::addAudioData(u8 *buf, u32 size) {
379 if (audioBuf)
380 audioBuf->push(buf, size);
381 else
382 return 0;
383 if (Memory::IsValidAddress(curTargetAddr)) {
384 u32 addSize = std::min(audioBuf->getAvailableSize(), numNeedSamples() * 2 - getReadMicDataLength());
385 u8 *tempbuf8 = new u8[addSize];
386 getAudioData(tempbuf8, addSize);
387 Memory::Memcpy(curTargetAddr + readMicDataLength, tempbuf8, addSize);
388 delete[] tempbuf8;
389 readMicDataLength += addSize;
390 }
391
392 return size;
393 }
394
getAudioData(u8 * buf,u32 size)395 u32 Microphone::getAudioData(u8 *buf, u32 size) {
396 if(audioBuf)
397 return audioBuf->pop(buf, size);
398
399 return 0;
400 }
401
flushAudioData()402 void Microphone::flushAudioData() {
403 audioBuf->flush();
404 }
405
getDeviceList()406 std::vector<std::string> Microphone::getDeviceList() {
407 #ifdef HAVE_WIN32_MICROPHONE
408 if (winMic) {
409 return winMic->getDeviceList();
410 }
411 #endif
412 return std::vector<std::string>();
413 }
414
onMicDeviceChange()415 void Microphone::onMicDeviceChange() {
416 if (Microphone::isMicStarted()) {
417 Microphone::stopMic();
418 // Just use the last param.
419 Microphone::startMic(nullptr);
420 }
421 }
422
__MicInput(u32 maxSamples,u32 sampleRate,u32 bufAddr,MICTYPE type,bool block)423 u32 __MicInput(u32 maxSamples, u32 sampleRate, u32 bufAddr, MICTYPE type, bool block) {
424 curSampleRate = sampleRate;
425 curChannels = 1;
426 curTargetAddr = bufAddr;
427 u32 size = maxSamples << 1;
428 if (!audioBuf) {
429 audioBuf = new QueueBuf(size);
430 } else {
431 audioBuf->resize(size);
432 }
433 if (!audioBuf)
434 return 0;
435
436 numNeedSamples = maxSamples;
437 readMicDataLength = 0;
438 if (!Microphone::isMicStarted()) {
439 std::vector<u32> *param = new std::vector<u32>({ sampleRate, 1 });
440 Microphone::startMic(param);
441 }
442
443 if (Microphone::availableAudioBufSize() > 0) {
444 u32 addSize = std::min(Microphone::availableAudioBufSize(), size);
445 u8 *tempbuf8 = new u8[addSize];
446 Microphone::getAudioData(tempbuf8, addSize);
447 Memory::Memcpy(curTargetAddr, tempbuf8, addSize);
448 delete[] tempbuf8;
449 readMicDataLength += addSize;
450 }
451
452 if (!block) {
453 return type == CAMERAMIC ? size : maxSamples;
454 }
455
456 u64 waitTimeus = (size - Microphone::availableAudioBufSize()) * 1000000 / 2 / sampleRate;
457 CoreTiming::ScheduleEvent(usToCycles(waitTimeus), eventMicBlockingResume, __KernelGetCurThread());
458 MicWaitInfo waitInfo = { __KernelGetCurThread(), bufAddr, size, sampleRate };
459 waitingThreads.push_back(waitInfo);
460 DEBUG_LOG(HLE, "MicInputBlocking: blocking thread(%d)", (int)__KernelGetCurThread());
461 __KernelWaitCurThread(WAITTYPE_MICINPUT, 1, size, 0, false, "blocking microphone");
462
463 return type == CAMERAMIC ? size : maxSamples;
464 }
465
466 const HLEFunction sceUsbMic[] =
467 {
468 {0x06128E42, &WrapI_V<sceUsbMicPollInputEnd>, "sceUsbMicPollInputEnd", 'i', "" },
469 {0x2E6DCDCD, &WrapI_UUU<sceUsbMicInputBlocking>, "sceUsbMicInputBlocking", 'i', "xxx" },
470 {0x45310F07, &WrapI_U<sceUsbMicInputInitEx>, "sceUsbMicInputInitEx", 'i', "x" },
471 {0x5F7F368D, &WrapI_UUU<sceUsbMicInput>, "sceUsbMicInput", 'i', "xxx" },
472 {0x63400E20, &WrapI_V<sceUsbMicGetInputLength>, "sceUsbMicGetInputLength", 'i', "" },
473 {0xB8E536EB, &WrapI_III<sceUsbMicInputInit>, "sceUsbMicInputInit", 'i', "iii" },
474 {0xF899001C, &WrapI_V<sceUsbMicWaitInputEnd>, "sceUsbMicWaitInputEnd", 'i', "" },
475 };
476
Register_sceUsbMic()477 void Register_sceUsbMic()
478 {
479 RegisterModule("sceUsbMic", ARRAY_SIZE(sceUsbMic), sceUsbMic);
480 }
481