Skip to content

Commit

Permalink
Implement proper microphone support (cemu-project#251)
Browse files Browse the repository at this point in the history
  • Loading branch information
AGraber committed Nov 2, 2022
1 parent dfa7774 commit d4e14d2
Show file tree
Hide file tree
Showing 13 changed files with 682 additions and 36 deletions.
2 changes: 2 additions & 0 deletions src/Cafe/CafeSystem.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
#include "Cafe/HW/Espresso/Interpreter/PPCInterpreterInternal.h"
#include "Cafe/HW/Espresso/Recompiler/PPCRecompiler.h"
#include "audio/IAudioAPI.h"
#include "audio/IAudioInputAPI.h"
#include "Cafe/HW/Espresso/Debugger/Debugger.h"

#include "config/ActiveSettings.h"
Expand Down Expand Up @@ -402,6 +403,7 @@ void cemu_initForGame()
GraphicPack2::ActivateForCurrentTitle();
// print audio log
IAudioAPI::PrintLogging();
IAudioInputAPI::PrintLogging();
// everything initialized
forceLog_printf("------- Run title -------");
// wait till GPU thread is initialized
Expand Down
91 changes: 78 additions & 13 deletions src/Cafe/OS/libs/mic/mic.cpp
Original file line number Diff line number Diff line change
@@ -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
{
Expand All @@ -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
{
Expand All @@ -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
{
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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)
Expand All @@ -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)
Expand Down Expand Up @@ -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;
Expand All @@ -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
Expand Down
4 changes: 4 additions & 0 deletions src/audio/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
add_library(CemuAudio
IAudioAPI.cpp
IAudioAPI.h
IAudioInputAPI.cpp
IAudioInputAPI.h
)

set_property(TARGET CemuAudio PROPERTY MSVC_RUNTIME_LIBRARY "MultiThreaded$<$<CONFIG:Debug>:Debug>")
Expand All @@ -26,6 +28,8 @@ if(ENABLE_CUBEB)
target_sources(CemuAudio PRIVATE
CubebAPI.cpp
CubebAPI.h
CubebInputAPI.cpp
CubebInputAPI.h
)
#add_compile_definitions(HAS_CUBEB)
endif()
Expand Down
2 changes: 1 addition & 1 deletion src/audio/CubebAPI.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
#endif


void state_cb(cubeb_stream* stream, void* user, cubeb_state state)
static void state_cb(cubeb_stream* stream, void* user, cubeb_state state)
{
if (!stream)
return;
Expand Down
Loading

0 comments on commit d4e14d2

Please sign in to comment.