Implement proper microphone support (#251)

This commit is contained in:
Adrian Graber 2022-11-03 00:24:34 +01:00 committed by GitHub
parent dfa7774c4c
commit d4e14d2b05
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
13 changed files with 682 additions and 36 deletions

View file

@ -1,5 +1,7 @@
#include "Cafe/OS/common/OSCommon.h"
#include "input/InputManager.h"
#include "audio/IAudioInputAPI.h"
#include "config/CemuConfig.h"
enum class MIC_RESULT
{
@ -13,6 +15,7 @@ enum class MIC_RESULT
#define MIC_SAMPLERATE 32000
const int MIC_SAMPLES_PER_3MS_32KHZ = (96); // 32000*3/1000
enum class MIC_STATUS_FLAGS : uint32
{
@ -22,8 +25,8 @@ enum class MIC_STATUS_FLAGS : uint32
};
DEFINE_ENUM_FLAG_OPERATORS(MIC_STATUS_FLAGS);
#define MIC_HANDLE_DRC0 100
#define MIC_HANDLE_DRC1 101
#define MIC_HANDLE_DRC0 0
#define MIC_HANDLE_DRC1 1
enum class MIC_STATEID
{
@ -139,6 +142,36 @@ void micExport_MICInit(PPCInterpreter_t* hCPU)
// return status
memory_writeU32(hCPU->gpr[6], 0); // no error
osLib_returnFromFunction(hCPU, (drcIndex==0)?MIC_HANDLE_DRC0:MIC_HANDLE_DRC1); // success
auto& config = GetConfig();
const auto audio_api = IAudioInputAPI::Cubeb; // change this if more input apis get implemented
std::unique_lock lock(g_audioInputMutex);
if (!g_inputAudio)
{
IAudioInputAPI::DeviceDescriptionPtr device_description;
if (IAudioInputAPI::IsAudioInputAPIAvailable(audio_api))
{
auto devices = IAudioInputAPI::GetDevices(audio_api);
const auto it = std::find_if(devices.begin(), devices.end(), [&config](const auto& d) {return d->GetIdentifier() == config.input_device; });
if (it != devices.end())
device_description = *it;
}
if (device_description)
{
try
{
g_inputAudio = IAudioInputAPI::CreateDevice(audio_api, device_description, MIC_SAMPLERATE, 1, MIC_SAMPLES_PER_3MS_32KHZ, 16);
g_inputAudio->SetVolume(config.input_volume);
}
catch (std::runtime_error& ex)
{
forceLog_printf("can't initialize audio input: %s", ex.what());
exit(0);
}
}
}
}
void micExport_MICOpen(PPCInterpreter_t* hCPU)
@ -172,6 +205,10 @@ void micExport_MICOpen(PPCInterpreter_t* hCPU)
// success
MICStatus.drc[drcIndex].isOpen = true;
osLib_returnFromFunction(hCPU, (uint32)MIC_RESULT::SUCCESS);
std::shared_lock lock(g_audioInputMutex);
if(g_inputAudio)
g_inputAudio->Play();
}
void micExport_MICClose(PPCInterpreter_t* hCPU)
@ -198,6 +235,10 @@ void micExport_MICClose(PPCInterpreter_t* hCPU)
// success
MICStatus.drc[drcIndex].isOpen = false;
osLib_returnFromFunction(hCPU, (uint32)MIC_RESULT::SUCCESS);
std::shared_lock lock(g_audioInputMutex);
if (g_inputAudio)
g_inputAudio->Stop();
}
void micExport_MICGetStatus(PPCInterpreter_t* hCPU)
@ -360,6 +401,17 @@ void micExport_MICSetDataConsumed(PPCInterpreter_t* hCPU)
return;
}
void mic_updateDevicePlayState(bool isPlaying)
{
if (g_inputAudio)
{
if (isPlaying)
g_inputAudio->Play();
else
g_inputAudio->Stop();
}
}
void mic_updateOnAXFrame()
{
sint32 drcIndex = 0;
@ -368,26 +420,39 @@ void mic_updateOnAXFrame()
drcIndex = 1;
if (mic_isActive(1) == false)
{
std::shared_lock lock(g_audioInputMutex);
mic_updateDevicePlayState(false);
return;
}
}
const sint32 micSampleCount = 32000/32;
sint16 micSampleData[micSampleCount];
auto controller = InputManager::instance().get_vpad_controller(drcIndex);
if( controller && controller->is_mic_active() )
std::shared_lock lock(g_audioInputMutex);
mic_updateDevicePlayState(true);
if (g_inputAudio)
{
for(sint32 i=0; i<micSampleCount; i++)
{
micSampleData[i] = (sint16)(sin((float)GetTickCount()*0.1f+sin((float)GetTickCount()*0.0001f)*100.0f)*30000.0f);
}
sint16 micSampleData[MIC_SAMPLES_PER_3MS_32KHZ];
g_inputAudio->ConsumeBlock(micSampleData);
mic_feedSamples(0, micSampleData, MIC_SAMPLES_PER_3MS_32KHZ);
}
else
{
memset(micSampleData, 0x00, sizeof(micSampleData));
const sint32 micSampleCount = 32000 / 32;
sint16 micSampleData[micSampleCount];
auto controller = InputManager::instance().get_vpad_controller(drcIndex);
if( controller && controller->is_mic_active() )
{
for(sint32 i=0; i<micSampleCount; i++)
{
micSampleData[i] = (sint16)(sin((float)GetTickCount()*0.1f+sin((float)GetTickCount()*0.0001f)*100.0f)*30000.0f);
}
}
else
{
memset(micSampleData, 0x00, sizeof(micSampleData));
}
mic_feedSamples(0, micSampleData, micSampleCount);
}
mic_feedSamples(0, micSampleData, micSampleCount);
}
namespace mic