mirror of
https://github.com/cemu-project/Cemu.git
synced 2025-07-05 14:31:17 +12:00
Implement proper microphone support (#251)
This commit is contained in:
parent
dfa7774c4c
commit
d4e14d2b05
13 changed files with 682 additions and 36 deletions
|
@ -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
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue