mirror of
https://github.com/hrydgard/ppsspp.git
synced 2025-04-02 11:01:50 -04:00
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.
This commit is contained in:
parent
572a2e48f6
commit
aac4cbb1dc
4 changed files with 48 additions and 73 deletions
|
@ -32,6 +32,7 @@
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef HAVE_WIN32_MICROPHONE
|
#ifdef HAVE_WIN32_MICROPHONE
|
||||||
|
#define NOMINMAX
|
||||||
#include "Windows/CaptureDevice.h"
|
#include "Windows/CaptureDevice.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -71,8 +72,6 @@ static void __UsbMicAudioUpdate(u64 userdata, int cyclesLate) {
|
||||||
DEBUG_LOG(HLE, "sceUsbMic: Waking up thread(%d)", (int)waitingThread.threadID);
|
DEBUG_LOG(HLE, "sceUsbMic: Waking up thread(%d)", (int)waitingThread.threadID);
|
||||||
__KernelResumeThreadFromWait(threadID, ret);
|
__KernelResumeThreadFromWait(threadID, ret);
|
||||||
waitingThreads.erase(waitingThreads.begin() + count);
|
waitingThreads.erase(waitingThreads.begin() + count);
|
||||||
if (waitingThreads.size() == 0)
|
|
||||||
isNeedInput = false;
|
|
||||||
} else {
|
} else {
|
||||||
u64 waitTimeus = (waitingThread.needSize - Microphone::availableAudioBufSize()) * 1000000 / 2 / waitingThread.sampleRate;
|
u64 waitTimeus = (waitingThread.needSize - Microphone::availableAudioBufSize()) * 1000000 / 2 / waitingThread.sampleRate;
|
||||||
if(eventUsbMicAudioUpdate == -1)
|
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);
|
DEBUG_LOG(HLE, "sceUsbMic: Waking up thread(%d)", (int)waitingThread.threadID);
|
||||||
__KernelResumeThreadFromWait(threadID, ret);
|
__KernelResumeThreadFromWait(threadID, ret);
|
||||||
waitingThreads.erase(waitingThreads.begin() + count);
|
waitingThreads.erase(waitingThreads.begin() + count);
|
||||||
if (waitingThreads.size() == 0)
|
|
||||||
isNeedInput = false;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
++count;
|
++count;
|
||||||
|
@ -105,7 +102,7 @@ void __UsbMicInit() {
|
||||||
}
|
}
|
||||||
numNeedSamples = 0;
|
numNeedSamples = 0;
|
||||||
waitingThreads.clear();
|
waitingThreads.clear();
|
||||||
isNeedInput = false;
|
isNeedInput = true;
|
||||||
curSampleRate = 44100;
|
curSampleRate = 44100;
|
||||||
curChannels = 1;
|
curChannels = 1;
|
||||||
micState = 0;
|
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];
|
buf_ = new u8[size];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -167,7 +164,7 @@ QueueBuf::~QueueBuf() {
|
||||||
QueueBuf::QueueBuf(const QueueBuf &buf) {
|
QueueBuf::QueueBuf(const QueueBuf &buf) {
|
||||||
buf_ = new u8[buf.capacity];
|
buf_ = new u8[buf.capacity];
|
||||||
memcpy(buf_, buf.buf_, buf.capacity);
|
memcpy(buf_, buf.buf_, buf.capacity);
|
||||||
start = buf.start;
|
available = buf.available;
|
||||||
end = buf.end;
|
end = buf.end;
|
||||||
capacity = buf.capacity;
|
capacity = buf.capacity;
|
||||||
}
|
}
|
||||||
|
@ -178,27 +175,28 @@ QueueBuf& QueueBuf::operator=(const QueueBuf &buf) {
|
||||||
}
|
}
|
||||||
std::unique_lock<std::mutex> lock(mutex);
|
std::unique_lock<std::mutex> lock(mutex);
|
||||||
memcpy(buf_, buf.buf_, buf.capacity);
|
memcpy(buf_, buf.buf_, buf.capacity);
|
||||||
start = buf.start;
|
available = buf.available;
|
||||||
end = buf.end;
|
end = buf.end;
|
||||||
lock.unlock();
|
lock.unlock();
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
void QueueBuf::push(u8 *buf, u32 size) {
|
u32 QueueBuf::push(u8 *buf, u32 size) {
|
||||||
if (getRemainingSize() < size) {
|
u32 addedSize = 0;
|
||||||
resize((capacity + size - getRemainingSize()) * 3 / 2);
|
// This will overwrite the old data if the size prepare to add more than remaining size.
|
||||||
}
|
|
||||||
std::unique_lock<std::mutex> lock(mutex);
|
std::unique_lock<std::mutex> lock(mutex);
|
||||||
if (end + size <= capacity) {
|
while (end + size > capacity) {
|
||||||
memcpy(buf_ + end, buf, size);
|
memcpy(buf_ + end, buf + addedSize, capacity - end);
|
||||||
end += size;
|
addedSize += capacity - end;
|
||||||
} else {
|
|
||||||
memcpy(buf_ + end, buf, capacity - end);
|
|
||||||
size -= capacity - end;
|
size -= capacity - end;
|
||||||
memcpy(buf_, buf + capacity - end, size);
|
end = 0;
|
||||||
end = size;
|
|
||||||
}
|
}
|
||||||
|
memcpy(buf_ + end, buf + addedSize, size);
|
||||||
|
addedSize += size;
|
||||||
|
end = (end + size) % capacity;
|
||||||
|
available = std::min(capacity, available + addedSize);
|
||||||
lock.unlock();
|
lock.unlock();
|
||||||
|
return addedSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
u32 QueueBuf::pop(u8 *buf, u32 size) {
|
u32 QueueBuf::pop(u8 *buf, u32 size) {
|
||||||
|
@ -208,15 +206,13 @@ u32 QueueBuf::pop(u8 *buf, u32 size) {
|
||||||
ret = size;
|
ret = size;
|
||||||
|
|
||||||
std::unique_lock<std::mutex> lock(mutex);
|
std::unique_lock<std::mutex> lock(mutex);
|
||||||
if (start + size <= capacity) {
|
if (getStartPos() + size <= capacity) {
|
||||||
memcpy(buf, buf_ + start, size);
|
memcpy(buf, buf_ + getStartPos(), size);
|
||||||
start += size;
|
|
||||||
} else {
|
} else {
|
||||||
memcpy(buf, buf_ + start, capacity - start);
|
memcpy(buf, buf_ + getStartPos(), capacity - getStartPos());
|
||||||
size -= capacity - start;
|
memcpy(buf + capacity - getStartPos(), buf_, size - (capacity - getStartPos()));
|
||||||
memcpy(buf + capacity - start, buf_, size);
|
|
||||||
start = size;
|
|
||||||
}
|
}
|
||||||
|
available -= size;
|
||||||
lock.unlock();
|
lock.unlock();
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
@ -228,42 +224,33 @@ void QueueBuf::resize(u32 newSize) {
|
||||||
u32 availableSize = getAvailableSize();
|
u32 availableSize = getAvailableSize();
|
||||||
u8 *oldbuf = buf_;
|
u8 *oldbuf = buf_;
|
||||||
|
|
||||||
std::unique_lock<std::mutex> lock(mutex);
|
|
||||||
buf_ = new u8[newSize];
|
buf_ = new u8[newSize];
|
||||||
if (end >= start) {
|
pop(buf_, availableSize);
|
||||||
memcpy(buf_, oldbuf + start, availableSize);
|
available = availableSize;
|
||||||
} else {
|
|
||||||
memcpy(buf_, oldbuf + start, capacity - start);
|
|
||||||
memcpy(buf_ + capacity - start, oldbuf, availableSize - (capacity - start));
|
|
||||||
}
|
|
||||||
start = 0;
|
|
||||||
end = availableSize;
|
end = availableSize;
|
||||||
capacity = newSize;
|
capacity = newSize;
|
||||||
delete[] oldbuf;
|
delete[] oldbuf;
|
||||||
lock.unlock();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void QueueBuf::flush() {
|
void QueueBuf::flush() {
|
||||||
std::unique_lock<std::mutex> lock(mutex);
|
std::unique_lock<std::mutex> lock(mutex);
|
||||||
start = 0;
|
available = 0;
|
||||||
end = 0;
|
end = 0;
|
||||||
lock.unlock();
|
lock.unlock();
|
||||||
}
|
}
|
||||||
|
|
||||||
u32 QueueBuf::getAvailableSize() {
|
u32 QueueBuf::getAvailableSize() {
|
||||||
u32 availableSize = 0;
|
return available;
|
||||||
if (end >= start) {
|
|
||||||
availableSize = end - start;
|
|
||||||
} else {
|
|
||||||
availableSize = end + capacity - start;
|
|
||||||
}
|
|
||||||
return availableSize;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
u32 QueueBuf::getRemainingSize() {
|
u32 QueueBuf::getRemainingSize() {
|
||||||
return capacity - getAvailableSize();
|
return capacity - getAvailableSize();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
u32 QueueBuf::getStartPos() {
|
||||||
|
return end >= available ? end - available : capacity - available + end;
|
||||||
|
}
|
||||||
|
|
||||||
static int sceUsbMicPollInputEnd() {
|
static int sceUsbMicPollInputEnd() {
|
||||||
ERROR_LOG(HLE, "UNIMPL sceUsbMicPollInputEnd");
|
ERROR_LOG(HLE, "UNIMPL sceUsbMicPollInputEnd");
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -353,6 +340,7 @@ bool Microphone::isMicStarted() {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Deprecated.
|
||||||
bool Microphone::isNeedInput() {
|
bool Microphone::isNeedInput() {
|
||||||
return ::isNeedInput;
|
return ::isNeedInput;
|
||||||
}
|
}
|
||||||
|
@ -404,18 +392,15 @@ void Microphone::onMicDeviceChange() {
|
||||||
|
|
||||||
u32 __MicInputBlocking(u32 maxSamples, u32 sampleRate, u32 bufAddr) {
|
u32 __MicInputBlocking(u32 maxSamples, u32 sampleRate, u32 bufAddr) {
|
||||||
u32 size = maxSamples << 1;
|
u32 size = maxSamples << 1;
|
||||||
if (size > numNeedSamples << 1) {
|
if (!audioBuf) {
|
||||||
if (!audioBuf) {
|
audioBuf = new QueueBuf(size);
|
||||||
audioBuf = new QueueBuf(size);
|
} else {
|
||||||
} else {
|
audioBuf->resize(size);
|
||||||
audioBuf->resize(size);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if (!audioBuf)
|
if (!audioBuf)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
numNeedSamples = maxSamples;
|
numNeedSamples = maxSamples;
|
||||||
Microphone::flushAudioData();
|
|
||||||
if (!Microphone::isMicStarted()) {
|
if (!Microphone::isMicStarted()) {
|
||||||
std::vector<u32> *param = new std::vector<u32>({ sampleRate, 1 });
|
std::vector<u32> *param = new std::vector<u32>({ sampleRate, 1 });
|
||||||
Microphone::startMic(param);
|
Microphone::startMic(param);
|
||||||
|
@ -423,7 +408,6 @@ u32 __MicInputBlocking(u32 maxSamples, u32 sampleRate, u32 bufAddr) {
|
||||||
u64 waitTimeus = 0;
|
u64 waitTimeus = 0;
|
||||||
if (Microphone::availableAudioBufSize() < size) {
|
if (Microphone::availableAudioBufSize() < size) {
|
||||||
waitTimeus = (size - Microphone::availableAudioBufSize()) * 1000000 / 2 / sampleRate;
|
waitTimeus = (size - Microphone::availableAudioBufSize()) * 1000000 / 2 / sampleRate;
|
||||||
isNeedInput = true;
|
|
||||||
}
|
}
|
||||||
if(eventUsbMicAudioUpdate == -1)
|
if(eventUsbMicAudioUpdate == -1)
|
||||||
eventUsbMicAudioUpdate = CoreTiming::RegisterEvent("UsbMicAudioUpdate", &__UsbMicAudioUpdate);
|
eventUsbMicAudioUpdate = CoreTiming::RegisterEvent("UsbMicAudioUpdate", &__UsbMicAudioUpdate);
|
||||||
|
|
|
@ -41,15 +41,19 @@ public:
|
||||||
QueueBuf(const QueueBuf &buf);
|
QueueBuf(const QueueBuf &buf);
|
||||||
QueueBuf& operator=(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);
|
u32 pop(u8 *buf, u32 size);
|
||||||
void resize(u32 newSize);
|
void resize(u32 newSize);
|
||||||
void flush();
|
void flush();
|
||||||
u32 getAvailableSize();
|
u32 getAvailableSize();
|
||||||
u32 getRemainingSize();
|
u32 getRemainingSize();
|
||||||
|
u32 getStartPos();
|
||||||
|
u32 getCapacity() const {
|
||||||
|
return capacity;
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
u32 start;
|
u32 available;
|
||||||
u32 end;
|
u32 end;
|
||||||
u32 capacity;
|
u32 capacity;
|
||||||
u8 *buf_;
|
u8 *buf_;
|
||||||
|
@ -61,6 +65,7 @@ namespace Microphone {
|
||||||
int stopMic();
|
int stopMic();
|
||||||
bool isHaveDevice();
|
bool isHaveDevice();
|
||||||
bool isMicStarted();
|
bool isMicStarted();
|
||||||
|
// Deprecated.
|
||||||
bool isNeedInput();
|
bool isNeedInput();
|
||||||
u32 numNeedSamples();
|
u32 numNeedSamples();
|
||||||
u32 availableAudioBufSize();
|
u32 availableAudioBufSize();
|
||||||
|
|
|
@ -225,26 +225,14 @@ HRESULT ReaderCallback::OnReadSample(
|
||||||
DWORD length = 0;
|
DWORD length = 0;
|
||||||
u32 sizeAfterResample = 0;
|
u32 sizeAfterResample = 0;
|
||||||
// pSample can be null, in this case ReadSample still should be called to request next frame.
|
// 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);
|
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()) {
|
if (device->needResample()) {
|
||||||
sizeAfterResample = device->rawAudioBuf->getAvailableSize() * device->targetMediaParam.sampleRate / device->deviceParam.sampleRate / device->deviceParam.channels;
|
sizeAfterResample = doResample(
|
||||||
// Wait until have enough audio data.
|
&device->resampleBuf, device->targetMediaParam.sampleRate, device->targetMediaParam.channels, &device->resampleBufSize,
|
||||||
if (sizeAfterResample + Microphone::availableAudioBufSize() >= Microphone::numNeedSamples() * 2) {
|
sampleBuf, device->deviceParam.sampleRate, device->deviceParam.channels, device->deviceParam.audioFormat, length, device->deviceParam.bitsPerSample);
|
||||||
u32 rawAudioBufSize = device->rawAudioBuf->getAvailableSize();
|
if (device->resampleBuf)
|
||||||
u8 *tempbuf = new u8[rawAudioBufSize];
|
Microphone::addAudioData(device->resampleBuf, sizeAfterResample);
|
||||||
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);
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
Microphone::addAudioData(sampleBuf, length);
|
Microphone::addAudioData(sampleBuf, length);
|
||||||
}
|
}
|
||||||
|
@ -470,7 +458,6 @@ WindowsCaptureDevice::~WindowsCaptureDevice() {
|
||||||
break;
|
break;
|
||||||
case CAPTUREDEVIDE_TYPE::AUDIO:
|
case CAPTUREDEVIDE_TYPE::AUDIO:
|
||||||
av_freep(&resampleBuf);
|
av_freep(&resampleBuf);
|
||||||
delete rawAudioBuf;
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -249,7 +249,6 @@ protected:
|
||||||
//Microphone only
|
//Microphone only
|
||||||
u8 *resampleBuf = nullptr;
|
u8 *resampleBuf = nullptr;
|
||||||
u32 resampleBufSize = 0;
|
u32 resampleBufSize = 0;
|
||||||
QueueBuf *rawAudioBuf = nullptr;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
extern WindowsCaptureDevice *winCamera;
|
extern WindowsCaptureDevice *winCamera;
|
||||||
|
|
Loading…
Add table
Reference in a new issue