mirror of
https://github.com/RPCS3/rpcs3.git
synced 2025-03-29 22:20:48 +00:00
Microphone implementation
This commit is contained in:
parent
2898309f68
commit
6c6b973342
@ -1,8 +1,9 @@
|
|||||||
#include "stdafx.h"
|
#include "stdafx.h"
|
||||||
#include "Emu/System.h"
|
#include "Emu/System.h"
|
||||||
#include "Emu/Cell/PPUModule.h"
|
#include "Emu/Cell/PPUModule.h"
|
||||||
#include "Emu/IdManager.h"
|
#include "Emu/IdManager.h"
|
||||||
#include "Emu/RSX/rsx_utils.h"
|
#include "Emu/RSX/rsx_utils.h"
|
||||||
|
#include "Utilities/StrUtil.h"
|
||||||
|
|
||||||
#include "cellAudioIn.h"
|
#include "cellAudioIn.h"
|
||||||
#include "cellAudioOut.h"
|
#include "cellAudioOut.h"
|
||||||
@ -11,6 +12,115 @@
|
|||||||
|
|
||||||
LOG_CHANNEL(cellAvconfExt);
|
LOG_CHANNEL(cellAvconfExt);
|
||||||
|
|
||||||
|
struct avconf_manager
|
||||||
|
{
|
||||||
|
std::vector<CellAudioInDeviceInfo> devices;
|
||||||
|
|
||||||
|
void copy_device_info(u32 num, vm::ptr<CellAudioInDeviceInfo> info);
|
||||||
|
avconf_manager();
|
||||||
|
};
|
||||||
|
|
||||||
|
avconf_manager::avconf_manager()
|
||||||
|
{
|
||||||
|
u32 curindex = 0;
|
||||||
|
|
||||||
|
auto mic_list = fmt::split(g_cfg.audio.microphone_devices, {"@@@"});
|
||||||
|
if (mic_list.size())
|
||||||
|
{
|
||||||
|
switch (g_cfg.audio.microphone_type)
|
||||||
|
{
|
||||||
|
case microphone_handler::standard:
|
||||||
|
for (u32 index = 0; index < mic_list.size(); index++)
|
||||||
|
{
|
||||||
|
devices.emplace_back();
|
||||||
|
|
||||||
|
devices[curindex].portType = CELL_AUDIO_IN_PORT_USB;
|
||||||
|
devices[curindex].availableModeCount = 1;
|
||||||
|
devices[curindex].state = CELL_AUDIO_IN_DEVICE_STATE_AVAILABLE;
|
||||||
|
devices[curindex].deviceId = 0xE11CC0DE + curindex;
|
||||||
|
devices[curindex].type = 0xC0DEE11C;
|
||||||
|
devices[curindex].availableModes[0].type = CELL_AUDIO_IN_CODING_TYPE_LPCM;
|
||||||
|
devices[curindex].availableModes[0].channel = CELL_AUDIO_IN_CHNUM_2;
|
||||||
|
devices[curindex].availableModes[0].fs = CELL_AUDIO_IN_FS_8KHZ | CELL_AUDIO_IN_FS_12KHZ | CELL_AUDIO_IN_FS_16KHZ | CELL_AUDIO_IN_FS_24KHZ | CELL_AUDIO_IN_FS_32KHZ | CELL_AUDIO_IN_FS_48KHZ;
|
||||||
|
devices[curindex].deviceNumber = curindex;
|
||||||
|
strcpy(devices[curindex].name, mic_list[index].c_str());
|
||||||
|
|
||||||
|
curindex++;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case microphone_handler::real_singstar:
|
||||||
|
case microphone_handler::singstar:
|
||||||
|
// Only one device for singstar device
|
||||||
|
devices.emplace_back();
|
||||||
|
|
||||||
|
devices[curindex].portType = CELL_AUDIO_IN_PORT_USB;
|
||||||
|
devices[curindex].availableModeCount = 1;
|
||||||
|
devices[curindex].state = CELL_AUDIO_IN_DEVICE_STATE_AVAILABLE;
|
||||||
|
devices[curindex].deviceId = 0x57A3C0DE;
|
||||||
|
devices[curindex].type = 0xC0DE57A3;
|
||||||
|
devices[curindex].availableModes[0].type = CELL_AUDIO_IN_CODING_TYPE_LPCM;
|
||||||
|
devices[curindex].availableModes[0].channel = CELL_AUDIO_IN_CHNUM_2;
|
||||||
|
devices[curindex].availableModes[0].fs = CELL_AUDIO_IN_FS_8KHZ | CELL_AUDIO_IN_FS_12KHZ | CELL_AUDIO_IN_FS_16KHZ | CELL_AUDIO_IN_FS_24KHZ | CELL_AUDIO_IN_FS_32KHZ | CELL_AUDIO_IN_FS_48KHZ;
|
||||||
|
devices[curindex].deviceNumber = curindex;
|
||||||
|
strcpy(devices[curindex].name, mic_list[0].c_str());
|
||||||
|
|
||||||
|
curindex++;
|
||||||
|
break;
|
||||||
|
case microphone_handler::rocksmith:
|
||||||
|
devices.emplace_back();
|
||||||
|
|
||||||
|
devices[curindex].portType = CELL_AUDIO_IN_PORT_USB;
|
||||||
|
devices[curindex].availableModeCount = 1;
|
||||||
|
devices[curindex].state = CELL_AUDIO_IN_DEVICE_STATE_AVAILABLE;
|
||||||
|
devices[curindex].deviceId = 0x12BA00FF; // Specific to rocksmith usb input
|
||||||
|
devices[curindex].type = 0xC0DE73C4;
|
||||||
|
devices[curindex].availableModes[0].type = CELL_AUDIO_IN_CODING_TYPE_LPCM;
|
||||||
|
devices[curindex].availableModes[0].channel = CELL_AUDIO_IN_CHNUM_1;
|
||||||
|
devices[curindex].availableModes[0].fs = CELL_AUDIO_IN_FS_8KHZ | CELL_AUDIO_IN_FS_12KHZ | CELL_AUDIO_IN_FS_16KHZ | CELL_AUDIO_IN_FS_24KHZ | CELL_AUDIO_IN_FS_32KHZ | CELL_AUDIO_IN_FS_48KHZ;
|
||||||
|
devices[curindex].deviceNumber = curindex;
|
||||||
|
strcpy(devices[curindex].name, mic_list[0].c_str());
|
||||||
|
|
||||||
|
curindex++;
|
||||||
|
break;
|
||||||
|
default: break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (g_cfg.io.camera != camera_handler::null)
|
||||||
|
{
|
||||||
|
devices.emplace_back();
|
||||||
|
|
||||||
|
devices[curindex].portType = CELL_AUDIO_IN_PORT_USB;
|
||||||
|
devices[curindex].availableModeCount = 1;
|
||||||
|
devices[curindex].state = CELL_AUDIO_IN_DEVICE_STATE_AVAILABLE;
|
||||||
|
devices[curindex].deviceId = 0xDEADBEEF;
|
||||||
|
devices[curindex].type = 0xBEEFDEAD;
|
||||||
|
devices[curindex].availableModes[0].type = CELL_AUDIO_IN_CODING_TYPE_LPCM;
|
||||||
|
devices[curindex].availableModes[0].channel = CELL_AUDIO_IN_CHNUM_NONE;
|
||||||
|
devices[curindex].availableModes[0].fs = CELL_AUDIO_IN_FS_8KHZ | CELL_AUDIO_IN_FS_12KHZ | CELL_AUDIO_IN_FS_16KHZ | CELL_AUDIO_IN_FS_24KHZ | CELL_AUDIO_IN_FS_32KHZ | CELL_AUDIO_IN_FS_48KHZ;
|
||||||
|
devices[curindex].deviceNumber = curindex;
|
||||||
|
strcpy(devices[curindex].name, "USB Camera");
|
||||||
|
|
||||||
|
curindex++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void avconf_manager::copy_device_info(u32 num, vm::ptr<CellAudioInDeviceInfo> info)
|
||||||
|
{
|
||||||
|
memset(info.get_ptr(), 0, sizeof(CellAudioInDeviceInfo));
|
||||||
|
|
||||||
|
info->portType = devices[num].portType;
|
||||||
|
info->availableModeCount = devices[num].availableModeCount;
|
||||||
|
info->state = devices[num].state;
|
||||||
|
info->deviceId = devices[num].deviceId;
|
||||||
|
info->type = devices[num].type;
|
||||||
|
info->availableModes[0].type = devices[num].availableModes[0].type;
|
||||||
|
info->availableModes[0].channel = devices[num].availableModes[0].channel;
|
||||||
|
info->availableModes[0].fs = devices[num].availableModes[0].fs;
|
||||||
|
info->deviceNumber = devices[num].deviceNumber;
|
||||||
|
strcpy(info->name, devices[num].name);
|
||||||
|
}
|
||||||
|
|
||||||
s32 cellAudioOutUnregisterDevice(u32 deviceNumber)
|
s32 cellAudioOutUnregisterDevice(u32 deviceNumber)
|
||||||
{
|
{
|
||||||
cellAvconfExt.todo("cellAudioOutUnregisterDevice(deviceNumber=0x%x)", deviceNumber);
|
cellAvconfExt.todo("cellAudioOutUnregisterDevice(deviceNumber=0x%x)", deviceNumber);
|
||||||
@ -38,23 +148,21 @@ s32 cellVideoOutSetupDisplay()
|
|||||||
s32 cellAudioInGetDeviceInfo(u32 deviceNumber, u32 deviceIndex, vm::ptr<CellAudioInDeviceInfo> info)
|
s32 cellAudioInGetDeviceInfo(u32 deviceNumber, u32 deviceIndex, vm::ptr<CellAudioInDeviceInfo> info)
|
||||||
{
|
{
|
||||||
cellAvconfExt.todo("cellAudioInGetDeviceInfo(deviceNumber=0x%x, deviceIndex=0x%x, info=*0x%x)", deviceNumber, deviceIndex, info);
|
cellAvconfExt.todo("cellAudioInGetDeviceInfo(deviceNumber=0x%x, deviceIndex=0x%x, info=*0x%x)", deviceNumber, deviceIndex, info);
|
||||||
info->portType = CELL_AUDIO_IN_PORT_USB;
|
|
||||||
info->availableModeCount = 1;
|
auto av_manager = fxm::get_always<avconf_manager>();
|
||||||
info->state = CELL_AUDIO_IN_DEVICE_STATE_AVAILABLE;
|
|
||||||
info->deviceNumber = 0;
|
if (deviceNumber >= av_manager->devices.size())
|
||||||
// Some games check if deviceId and type are the same.
|
return CELL_AUDIO_OUT_ERROR_DEVICE_NOT_FOUND;
|
||||||
info->deviceId = 0xDEADBEEF;
|
|
||||||
info->type = 0xBEEFDEAD;
|
av_manager->copy_device_info(deviceNumber, info);
|
||||||
info->availableModes[0].type = CELL_AUDIO_IN_CODING_TYPE_LPCM;
|
|
||||||
info->availableModes[0].channel = CELL_AUDIO_IN_CHNUM_NONE;
|
|
||||||
info->availableModes[0].fs = CELL_AUDIO_IN_FS_8KHZ | CELL_AUDIO_IN_FS_12KHZ | CELL_AUDIO_IN_FS_16KHZ | CELL_AUDIO_IN_FS_24KHZ | CELL_AUDIO_IN_FS_32KHZ | CELL_AUDIO_IN_FS_48KHZ;
|
|
||||||
strcpy(info->name, "USB Camera");
|
|
||||||
return CELL_OK;
|
return CELL_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
s32 cellVideoOutConvertCursorColor(u32 videoOut, s32 displaybuffer_format, f32 gamma, s32 source_buffer_format, vm::ptr<void> src_addr, vm::ptr<u32> dest_addr, s32 num)
|
s32 cellVideoOutConvertCursorColor(u32 videoOut, s32 displaybuffer_format, f32 gamma, s32 source_buffer_format, vm::ptr<void> src_addr, vm::ptr<u32> dest_addr, s32 num)
|
||||||
{
|
{
|
||||||
cellAvconfExt.todo("cellVideoOutConvertCursorColor(videoOut=%d, displaybuffer_format=0x%x, gamma=0x%x, source_buffer_format=0x%x, src_addr=*0x%x, dest_addr=*0x%x, num=0x%x)", videoOut, displaybuffer_format, gamma, source_buffer_format, src_addr, dest_addr, num);
|
cellAvconfExt.todo("cellVideoOutConvertCursorColor(videoOut=%d, displaybuffer_format=0x%x, gamma=0x%x, source_buffer_format=0x%x, src_addr=*0x%x, dest_addr=*0x%x, num=0x%x)", videoOut,
|
||||||
|
displaybuffer_format, gamma, source_buffer_format, src_addr, dest_addr, num);
|
||||||
return CELL_OK;
|
return CELL_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -68,26 +176,30 @@ s32 cellVideoOutGetGamma(u32 videoOut, vm::ptr<f32> gamma)
|
|||||||
}
|
}
|
||||||
|
|
||||||
auto conf = fxm::get_always<rsx::avconf>();
|
auto conf = fxm::get_always<rsx::avconf>();
|
||||||
*gamma = conf->gamma;
|
*gamma = conf->gamma;
|
||||||
|
|
||||||
return CELL_OK;
|
return CELL_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
s32 cellAudioInGetAvailableDeviceInfo(u32 count, vm::ptr<CellAudioInDeviceInfo> info)
|
s32 cellAudioInGetAvailableDeviceInfo(u32 count, vm::ptr<CellAudioInDeviceInfo> device_info)
|
||||||
{
|
{
|
||||||
cellAvconfExt.todo("cellAudioInGetAvailableDeviceInfo(count=0x%x, info=*0x%x)", count, info);
|
cellAvconfExt.todo("cellAudioInGetAvailableDeviceInfo(count=0x%x, info=*0x%x)", count, device_info);
|
||||||
info->portType = CELL_AUDIO_IN_PORT_USB;
|
|
||||||
info->availableModeCount = 1;
|
if (count > 16 || !device_info.addr())
|
||||||
info->state = CELL_AUDIO_IN_DEVICE_STATE_AVAILABLE;
|
{
|
||||||
info->deviceNumber = 0;
|
return CELL_AUDIO_IN_ERROR_ILLEGAL_PARAMETER;
|
||||||
// Some games check if deviceId and type are the same.
|
}
|
||||||
info->deviceId = 0xDEADBEEF;
|
|
||||||
info->type = 0xBEEFDEAD;
|
auto av_manager = fxm::get_always<avconf_manager>();
|
||||||
info->availableModes[0].type = CELL_AUDIO_IN_CODING_TYPE_LPCM;
|
|
||||||
info->availableModes[0].channel = CELL_AUDIO_IN_CHNUM_NONE;
|
u32 num_devices_returned = std::min(count, (u32)av_manager->devices.size());
|
||||||
info->availableModes[0].fs = CELL_AUDIO_IN_FS_8KHZ | CELL_AUDIO_IN_FS_12KHZ | CELL_AUDIO_IN_FS_16KHZ | CELL_AUDIO_IN_FS_24KHZ | CELL_AUDIO_IN_FS_32KHZ | CELL_AUDIO_IN_FS_48KHZ;
|
|
||||||
strcpy(info->name, "USB Camera");
|
for (u32 index = 0; index < num_devices_returned; index++)
|
||||||
return 1; // number of available devices
|
{
|
||||||
|
av_manager->copy_device_info(index, device_info + index);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (s32)num_devices_returned;
|
||||||
}
|
}
|
||||||
|
|
||||||
s32 cellAudioOutGetAvailableDeviceInfo(u32 count, vm::ptr<CellAudioOutDeviceInfo2> info)
|
s32 cellAudioOutGetAvailableDeviceInfo(u32 count, vm::ptr<CellAudioOutDeviceInfo2> info)
|
||||||
@ -110,7 +222,7 @@ s32 cellVideoOutSetGamma(u32 videoOut, f32 gamma)
|
|||||||
return CELL_VIDEO_OUT_ERROR_ILLEGAL_PARAMETER;
|
return CELL_VIDEO_OUT_ERROR_ILLEGAL_PARAMETER;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto conf = fxm::get_always<rsx::avconf>();
|
auto conf = fxm::get_always<rsx::avconf>();
|
||||||
conf->gamma = gamma;
|
conf->gamma = gamma;
|
||||||
|
|
||||||
return CELL_OK;
|
return CELL_OK;
|
||||||
@ -137,6 +249,7 @@ s32 cellAudioInSetDeviceMode(u32 deviceMode)
|
|||||||
s32 cellAudioInRegisterDevice(u64 deviceType, vm::cptr<char> name, vm::ptr<CellAudioInRegistrationOption> option, vm::ptr<CellAudioInDeviceConfiguration> config)
|
s32 cellAudioInRegisterDevice(u64 deviceType, vm::cptr<char> name, vm::ptr<CellAudioInRegistrationOption> option, vm::ptr<CellAudioInDeviceConfiguration> config)
|
||||||
{
|
{
|
||||||
cellAvconfExt.todo("cellAudioInRegisterDevice(deviceType=0x%llx, name=%s, option=*0x%x, config=*0x%x)", deviceType, name, option, config);
|
cellAvconfExt.todo("cellAudioInRegisterDevice(deviceType=0x%llx, name=%s, option=*0x%x, config=*0x%x)", deviceType, name, option, config);
|
||||||
|
|
||||||
return 0; // device number
|
return 0; // device number
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -155,10 +268,10 @@ s32 cellVideoOutGetScreenSize(u32 videoOut, vm::ptr<f32> screenSize)
|
|||||||
return CELL_VIDEO_OUT_ERROR_UNSUPPORTED_VIDEO_OUT;
|
return CELL_VIDEO_OUT_ERROR_UNSUPPORTED_VIDEO_OUT;
|
||||||
}
|
}
|
||||||
|
|
||||||
//TODO: Use virtual screen size
|
// TODO: Use virtual screen size
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
//HDC screen = GetDC(NULL);
|
// HDC screen = GetDC(NULL);
|
||||||
//float diagonal = roundf(sqrtf((powf(float(GetDeviceCaps(screen, HORZSIZE)), 2) + powf(float(GetDeviceCaps(screen, VERTSIZE)), 2))) * 0.0393f);
|
// float diagonal = roundf(sqrtf((powf(float(GetDeviceCaps(screen, HORZSIZE)), 2) + powf(float(GetDeviceCaps(screen, VERTSIZE)), 2))) * 0.0393f);
|
||||||
#else
|
#else
|
||||||
// TODO: Linux implementation, without using wx
|
// TODO: Linux implementation, without using wx
|
||||||
// float diagonal = roundf(sqrtf((powf(wxGetDisplaySizeMM().GetWidth(), 2) + powf(wxGetDisplaySizeMM().GetHeight(), 2))) * 0.0393f);
|
// float diagonal = roundf(sqrtf((powf(wxGetDisplaySizeMM().GetWidth(), 2) + powf(wxGetDisplaySizeMM().GetHeight(), 2))) * 0.0393f);
|
||||||
@ -173,9 +286,8 @@ s32 cellVideoOutSetCopyControl(u32 videoOut, u32 control)
|
|||||||
return CELL_OK;
|
return CELL_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DECLARE(ppu_module_manager::cellAvconfExt)
|
||||||
DECLARE(ppu_module_manager::cellAvconfExt)("cellSysutilAvconfExt", []()
|
("cellSysutilAvconfExt", []() {
|
||||||
{
|
|
||||||
REG_FUNC(cellSysutilAvconfExt, cellAudioOutUnregisterDevice);
|
REG_FUNC(cellSysutilAvconfExt, cellAudioOutUnregisterDevice);
|
||||||
REG_FUNC(cellSysutilAvconfExt, cellAudioOutGetDeviceInfo2);
|
REG_FUNC(cellSysutilAvconfExt, cellAudioOutGetDeviceInfo2);
|
||||||
REG_FUNC(cellSysutilAvconfExt, cellVideoOutSetXVColor);
|
REG_FUNC(cellSysutilAvconfExt, cellVideoOutSetXVColor);
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -1,40 +1,42 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "Utilities/BEType.h"
|
#include "Utilities/BEType.h"
|
||||||
#include "Utilities/Thread.h"
|
#include "Utilities/Thread.h"
|
||||||
|
|
||||||
|
#include "3rdparty/OpenAL/include/alext.h"
|
||||||
|
|
||||||
// Error Codes
|
// Error Codes
|
||||||
enum
|
enum
|
||||||
{
|
{
|
||||||
CELL_MIC_ERROR_ALREADY_INIT = 0x80140101,
|
CELL_MIC_ERROR_ALREADY_INIT = 0x80140101,
|
||||||
CELL_MIC_ERROR_SYSTEM = 0x80140102,
|
CELL_MIC_ERROR_SYSTEM = 0x80140102,
|
||||||
CELL_MIC_ERROR_NOT_INIT = 0x80140103,
|
CELL_MIC_ERROR_NOT_INIT = 0x80140103,
|
||||||
CELL_MIC_ERROR_PARAM = 0x80140104,
|
CELL_MIC_ERROR_PARAM = 0x80140104,
|
||||||
CELL_MIC_ERROR_PORT_FULL = 0x80140105,
|
CELL_MIC_ERROR_PORT_FULL = 0x80140105,
|
||||||
CELL_MIC_ERROR_ALREADY_OPEN = 0x80140106,
|
CELL_MIC_ERROR_ALREADY_OPEN = 0x80140106,
|
||||||
CELL_MIC_ERROR_NOT_OPEN = 0x80140107,
|
CELL_MIC_ERROR_NOT_OPEN = 0x80140107,
|
||||||
CELL_MIC_ERROR_NOT_RUN = 0x80140108,
|
CELL_MIC_ERROR_NOT_RUN = 0x80140108,
|
||||||
CELL_MIC_ERROR_TRANS_EVENT = 0x80140109,
|
CELL_MIC_ERROR_TRANS_EVENT = 0x80140109,
|
||||||
CELL_MIC_ERROR_OPEN = 0x8014010a,
|
CELL_MIC_ERROR_OPEN = 0x8014010a,
|
||||||
CELL_MIC_ERROR_SHAREDMEMORY = 0x8014010b,
|
CELL_MIC_ERROR_SHAREDMEMORY = 0x8014010b,
|
||||||
CELL_MIC_ERROR_MUTEX = 0x8014010c,
|
CELL_MIC_ERROR_MUTEX = 0x8014010c,
|
||||||
CELL_MIC_ERROR_EVENT_QUEUE = 0x8014010d,
|
CELL_MIC_ERROR_EVENT_QUEUE = 0x8014010d,
|
||||||
CELL_MIC_ERROR_DEVICE_NOT_FOUND = 0x8014010e,
|
CELL_MIC_ERROR_DEVICE_NOT_FOUND = 0x8014010e,
|
||||||
CELL_MIC_ERROR_SYSTEM_NOT_FOUND = 0x8014010e,
|
CELL_MIC_ERROR_SYSTEM_NOT_FOUND = 0x8014010e,
|
||||||
CELL_MIC_ERROR_FATAL = 0x8014010f,
|
CELL_MIC_ERROR_FATAL = 0x8014010f,
|
||||||
CELL_MIC_ERROR_DEVICE_NOT_SUPPORT = 0x80140110,
|
CELL_MIC_ERROR_DEVICE_NOT_SUPPORT = 0x80140110,
|
||||||
};
|
};
|
||||||
|
|
||||||
struct CellMicInputFormat
|
struct CellMicInputFormat
|
||||||
{
|
{
|
||||||
u8 channelNum;
|
u8 channelNum;
|
||||||
u8 subframeSize;
|
u8 subframeSize;
|
||||||
u8 bitResolution;
|
u8 bitResolution;
|
||||||
u8 dataType;
|
u8 dataType;
|
||||||
be_t<u32> sampleRate;
|
be_t<u32> sampleRate;
|
||||||
};
|
};
|
||||||
|
|
||||||
enum CellMicSignalState
|
enum CellMicSignalState : u32
|
||||||
{
|
{
|
||||||
CELL_MIC_SIGSTATE_LOCTALK = 0,
|
CELL_MIC_SIGSTATE_LOCTALK = 0,
|
||||||
CELL_MIC_SIGSTATE_FARTALK = 1,
|
CELL_MIC_SIGSTATE_FARTALK = 1,
|
||||||
@ -47,32 +49,220 @@ enum CellMicSignalState
|
|||||||
enum CellMicCommand
|
enum CellMicCommand
|
||||||
{
|
{
|
||||||
CELL_MIC_ATTACH = 2,
|
CELL_MIC_ATTACH = 2,
|
||||||
CELL_MIC_DATA = 5,
|
CELL_MIC_DATA = 5,
|
||||||
};
|
};
|
||||||
|
|
||||||
// TODO: generate this from input from an actual microphone
|
enum CellMicDeviceAttr : u32
|
||||||
const u32 bufferSize = 1;
|
{
|
||||||
|
CELLMIC_DEVATTR_LED = 9,
|
||||||
|
CELLMIC_DEVATTR_GAIN = 10,
|
||||||
|
CELLMIC_DEVATTR_VOLUME = 201,
|
||||||
|
CELLMIC_DEVATTR_AGC = 202,
|
||||||
|
CELLMIC_DEVATTR_CHANVOL = 301,
|
||||||
|
CELLMIC_DEVATTR_DSPTYPE = 302,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum CellMicSignalType : u8
|
||||||
|
{
|
||||||
|
CELLMIC_SIGTYPE_NULL = 0,
|
||||||
|
CELLMIC_SIGTYPE_DSP = 1,
|
||||||
|
CELLMIC_SIGTYPE_AUX = 2,
|
||||||
|
CELLMIC_SIGTYPE_RAW = 4,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum CellMicType : s32
|
||||||
|
{
|
||||||
|
CELLMIC_TYPE_UNDEF = -1,
|
||||||
|
CELLMIC_TYPE_UNKNOWN = 0,
|
||||||
|
CELLMIC_TYPE_EYETOY1 = 1,
|
||||||
|
CELLMIC_TYPE_EYETOY2 = 2,
|
||||||
|
CELLMIC_TYPE_USBAUDIO = 3,
|
||||||
|
CELLMIC_TYPE_BLUETOOTH = 4,
|
||||||
|
CELLMIC_TYPE_A2DP = 5,
|
||||||
|
} CellMicType;
|
||||||
|
|
||||||
|
template <std::size_t S>
|
||||||
|
class simple_ringbuf
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
simple_ringbuf()
|
||||||
|
{
|
||||||
|
m_container.resize(S);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool has_data() const
|
||||||
|
{
|
||||||
|
return m_used != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
u32 read_bytes(u8* buf, const u32 size)
|
||||||
|
{
|
||||||
|
u32 to_read = size > m_used ? m_used : size;
|
||||||
|
if (!to_read)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
u8* data = m_container.data();
|
||||||
|
u32 new_tail = m_tail + to_read;
|
||||||
|
|
||||||
|
if (new_tail >= S)
|
||||||
|
{
|
||||||
|
u32 first_chunk_size = S - m_tail;
|
||||||
|
std::memcpy(buf, data + m_tail, first_chunk_size);
|
||||||
|
std::memcpy(buf + first_chunk_size, data, to_read - first_chunk_size);
|
||||||
|
m_tail = (new_tail - S);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
std::memcpy(buf, data + m_tail, to_read);
|
||||||
|
m_tail = new_tail;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_used -= to_read;
|
||||||
|
|
||||||
|
return to_read;
|
||||||
|
}
|
||||||
|
|
||||||
|
void write_bytes(const u8* buf, const u32 size)
|
||||||
|
{
|
||||||
|
ASSERT(size <= S);
|
||||||
|
|
||||||
|
if (u32 over_size = m_used + size; over_size > S)
|
||||||
|
{
|
||||||
|
m_tail += (over_size - S);
|
||||||
|
if (m_tail > S)
|
||||||
|
m_tail -= S;
|
||||||
|
|
||||||
|
m_used = S;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_used = over_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
u8* data = m_container.data();
|
||||||
|
u32 new_head = m_head + size;
|
||||||
|
|
||||||
|
if (new_head >= S)
|
||||||
|
{
|
||||||
|
u32 first_chunk_size = S - m_head;
|
||||||
|
std::memcpy(data + m_head, buf, first_chunk_size);
|
||||||
|
std::memcpy(data, buf + first_chunk_size, size - first_chunk_size);
|
||||||
|
m_head = (new_head - S);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
std::memcpy(data + m_head, buf, size);
|
||||||
|
m_head = new_head;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
std::vector<u8> m_container;
|
||||||
|
u32 m_head = 0, m_tail = 0, m_used = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
class microphone_device
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
microphone_device(microphone_handler type);
|
||||||
|
|
||||||
|
void add_device(const std::string& name);
|
||||||
|
|
||||||
|
s32 open_microphone(const u8 type, const u32 dsp_r, const u32 raw_r, const u8 channels = 2);
|
||||||
|
s32 close_microphone();
|
||||||
|
|
||||||
|
s32 start_microphone();
|
||||||
|
s32 stop_microphone();
|
||||||
|
|
||||||
|
void update_audio();
|
||||||
|
bool has_data() const;
|
||||||
|
|
||||||
|
bool is_opened() const { return mic_opened; }
|
||||||
|
bool is_started() const { return mic_started; }
|
||||||
|
u8 get_signal_types() const { return signal_types; }
|
||||||
|
u8 get_bit_resolution() const { return bit_resolution; }
|
||||||
|
u32 get_raw_samplingrate() const { return raw_samplingrate; }
|
||||||
|
u8 get_num_channels() const { return num_channels; }
|
||||||
|
u8 get_datatype() const
|
||||||
|
{
|
||||||
|
switch(device_type)
|
||||||
|
{
|
||||||
|
case microphone_handler::real_singstar:
|
||||||
|
case microphone_handler::singstar:
|
||||||
|
return 0; // LE
|
||||||
|
default:
|
||||||
|
return 1; // BE
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
u32 read_raw(u8* buf, u32 size) { return rbuf_raw.read_bytes(buf, size); }
|
||||||
|
u32 read_dsp(u8* buf, u32 size) { return rbuf_dsp.read_bytes(buf, size); }
|
||||||
|
|
||||||
|
// Microphone attributes
|
||||||
|
u32 attr_gain = 3;
|
||||||
|
u32 attr_volume = 145;
|
||||||
|
u32 attr_agc = 0;
|
||||||
|
u32 attr_chanvol[2] = {145, 145};
|
||||||
|
u32 attr_led = 0;
|
||||||
|
u32 attr_dsptype = 0;
|
||||||
|
|
||||||
|
private:
|
||||||
|
static void variable_byteswap(const void* src, void* dst, const u32 bytesize);
|
||||||
|
|
||||||
|
u32 capture_audio();
|
||||||
|
|
||||||
|
void get_raw(const u32 num_samples);
|
||||||
|
void get_dsp(const u32 num_samples);
|
||||||
|
|
||||||
|
private:
|
||||||
|
microphone_handler device_type;
|
||||||
|
std::vector<std::string> device_name;
|
||||||
|
|
||||||
|
bool mic_opened = false;
|
||||||
|
bool mic_started = false;
|
||||||
|
|
||||||
|
std::vector<ALCdevice*> input_devices;
|
||||||
|
std::vector<std::vector<u8>> internal_bufs;
|
||||||
|
std::vector<u8> temp_buf;
|
||||||
|
|
||||||
|
// Sampling information provided at opening of mic
|
||||||
|
u32 raw_samplingrate = 48000;
|
||||||
|
u32 dsp_samplingrate = 48000;
|
||||||
|
u32 aux_samplingrate = 48000;
|
||||||
|
u8 bit_resolution = 16;
|
||||||
|
u8 num_channels = 2;
|
||||||
|
|
||||||
|
u8 signal_types = CELLMIC_SIGTYPE_NULL;
|
||||||
|
|
||||||
|
u32 sample_size; // Determined at opening for internal use
|
||||||
|
|
||||||
|
static constexpr std::size_t inbuf_size = 400000; // Default value unknown
|
||||||
|
|
||||||
|
simple_ringbuf<inbuf_size> rbuf_raw;
|
||||||
|
simple_ringbuf<inbuf_size> rbuf_dsp;
|
||||||
|
simple_ringbuf<inbuf_size> rbuf_aux;
|
||||||
|
};
|
||||||
|
|
||||||
class mic_context
|
class mic_context
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
void operator()();
|
void operator()();
|
||||||
|
void load_config_and_init();
|
||||||
|
|
||||||
// Default value of 48000 for no particular reason
|
u64 event_queue_key = 0;
|
||||||
u32 DspFrequency = 48000; // DSP is the default type
|
|
||||||
u32 rawFrequency = 48000;
|
|
||||||
u32 AuxFrequency = 48000;
|
|
||||||
u8 bitResolution = 32;
|
|
||||||
bool micOpened = false;
|
|
||||||
bool micStarted = false;
|
|
||||||
u64 eventQueueKey = 0;
|
|
||||||
|
|
||||||
u32 signalStateLocalTalk = 9; // value is in range 0-10. 10 indicates talking, 0 indicating none.
|
std::unordered_map<u8, microphone_device> mic_list;
|
||||||
u32 signalStateFarTalk = 0; // value is in range 0-10. 10 indicates talking from far away, 0 indicating none.
|
|
||||||
f32 signalStateNoiseSupression; // value is in decibels
|
protected:
|
||||||
f32 signalStateGainControl;
|
const u64 start_time = get_system_time();
|
||||||
f32 signalStateMicSignalLevel; // value is in decibels
|
u64 m_counter = 0;
|
||||||
f32 signalStateSpeakerSignalLevel; // value is in decibels
|
|
||||||
|
// u32 signalStateLocalTalk = 9; // value is in range 0-10. 10 indicates talking, 0 indicating none.
|
||||||
|
// u32 signalStateFarTalk = 0; // value is in range 0-10. 10 indicates talking from far away, 0 indicating none.
|
||||||
|
// f32 signalStateNoiseSupression; // value is in decibels
|
||||||
|
// f32 signalStateGainControl;
|
||||||
|
// f32 signalStateMicSignalLevel; // value is in decibels
|
||||||
|
// f32 signalStateSpeakerSignalLevel; // value is in decibels
|
||||||
};
|
};
|
||||||
|
|
||||||
using mic_thread = named_thread<mic_context>;
|
using mic_thread = named_thread<mic_context>;
|
||||||
|
@ -119,6 +119,15 @@ enum class move_handler
|
|||||||
fake,
|
fake,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum class microphone_handler
|
||||||
|
{
|
||||||
|
null,
|
||||||
|
standard,
|
||||||
|
singstar,
|
||||||
|
real_singstar,
|
||||||
|
rocksmith,
|
||||||
|
};
|
||||||
|
|
||||||
enum class video_resolution
|
enum class video_resolution
|
||||||
{
|
{
|
||||||
_1080,
|
_1080,
|
||||||
@ -546,7 +555,8 @@ struct cfg_root : cfg::node
|
|||||||
cfg::_int<1, 1000> sampling_period_multiplier{this, "Sampling Period Multiplier", 100};
|
cfg::_int<1, 1000> sampling_period_multiplier{this, "Sampling Period Multiplier", 100};
|
||||||
cfg::_bool enable_time_stretching{this, "Enable Time Stretching", false};
|
cfg::_bool enable_time_stretching{this, "Enable Time Stretching", false};
|
||||||
cfg::_int<0, 100> time_stretching_threshold{this, "Time Stretching Threshold", 75};
|
cfg::_int<0, 100> time_stretching_threshold{this, "Time Stretching Threshold", 75};
|
||||||
|
cfg::_enum<microphone_handler> microphone_type{ this, "Microphone Type", microphone_handler::null };
|
||||||
|
cfg::string microphone_devices{ this, "Microphone Devices", ";;;;" };
|
||||||
} audio{this};
|
} audio{this};
|
||||||
|
|
||||||
struct node_io : cfg::node
|
struct node_io : cfg::node
|
||||||
@ -559,7 +569,6 @@ struct cfg_root : cfg::node
|
|||||||
cfg::_enum<camera_handler> camera{this, "Camera", camera_handler::null};
|
cfg::_enum<camera_handler> camera{this, "Camera", camera_handler::null};
|
||||||
cfg::_enum<fake_camera_type> camera_type{this, "Camera type", fake_camera_type::unknown};
|
cfg::_enum<fake_camera_type> camera_type{this, "Camera type", fake_camera_type::unknown};
|
||||||
cfg::_enum<move_handler> move{this, "Move", move_handler::null};
|
cfg::_enum<move_handler> move{this, "Move", move_handler::null};
|
||||||
|
|
||||||
} io{this};
|
} io{this};
|
||||||
|
|
||||||
struct node_sys : cfg::node
|
struct node_sys : cfg::node
|
||||||
|
@ -9,7 +9,8 @@
|
|||||||
"enableBuffering": "Enables audio buffering, which reduces crackle/stutter but increases audio latency (requires XAudio2 or OpenAL).",
|
"enableBuffering": "Enables audio buffering, which reduces crackle/stutter but increases audio latency (requires XAudio2 or OpenAL).",
|
||||||
"audioBufferDuration": "Target buffer duration in milliseconds.\nHigher values make the buffering algorithm's job easier, but may introduce noticeable audio latency.",
|
"audioBufferDuration": "Target buffer duration in milliseconds.\nHigher values make the buffering algorithm's job easier, but may introduce noticeable audio latency.",
|
||||||
"enableTimeStretching": "Enables time stretching - requires buffering to be enabled.\nReduces crackle/stutter further, but may cause a very noticeable reduction in audio quality on slower CPUs.",
|
"enableTimeStretching": "Enables time stretching - requires buffering to be enabled.\nReduces crackle/stutter further, but may cause a very noticeable reduction in audio quality on slower CPUs.",
|
||||||
"timeStretchingThreshold": "Buffer fill level (in percentage) below which time stretching will start."
|
"timeStretchingThreshold": "Buffer fill level (in percentage) below which time stretching will start.",
|
||||||
|
"microphoneBox": "Standard should be used for most games.\nSingstar emulates a singstar device and should be used with Singstar games.\nReal Singstar should only be used with a REAL Singstar device with Singstar games.\nRocksmith should be used with a Rocksmith dongle."
|
||||||
},
|
},
|
||||||
"cpu": {
|
"cpu": {
|
||||||
"PPU": {
|
"PPU": {
|
||||||
|
@ -9,6 +9,7 @@
|
|||||||
#include "Emu/System.h"
|
#include "Emu/System.h"
|
||||||
#include "Utilities/Config.h"
|
#include "Utilities/Config.h"
|
||||||
#include "Utilities/Thread.h"
|
#include "Utilities/Thread.h"
|
||||||
|
#include "Utilities/StrUtil.h"
|
||||||
|
|
||||||
#include <QMessageBox>
|
#include <QMessageBox>
|
||||||
|
|
||||||
@ -24,6 +25,8 @@
|
|||||||
#include "Emu/RSX/VK/VKHelpers.h"
|
#include "Emu/RSX/VK/VKHelpers.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#include "3rdparty/OpenAL/include/alext.h"
|
||||||
|
|
||||||
extern std::string g_cfg_defaults; //! Default settings grabbed from Utilities/Config.h
|
extern std::string g_cfg_defaults; //! Default settings grabbed from Utilities/Config.h
|
||||||
|
|
||||||
inline std::string sstr(const QString& _in) { return _in.toStdString(); }
|
inline std::string sstr(const QString& _in) { return _in.toStdString(); }
|
||||||
@ -228,6 +231,58 @@ emu_settings::Render_Creator::Render_Creator()
|
|||||||
renderers = { &D3D12, &Vulkan, &OpenGL, &NullRender };
|
renderers = { &D3D12, &Vulkan, &OpenGL, &NullRender };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
emu_settings::Microphone_Creator::Microphone_Creator()
|
||||||
|
{
|
||||||
|
RefreshList();
|
||||||
|
}
|
||||||
|
|
||||||
|
void emu_settings::Microphone_Creator::RefreshList()
|
||||||
|
{
|
||||||
|
microphones_list.clear();
|
||||||
|
microphones_list.append(mic_none);
|
||||||
|
|
||||||
|
if (alcIsExtensionPresent(NULL, "ALC_ENUMERATION_EXT") == AL_TRUE)
|
||||||
|
{
|
||||||
|
const char *devices = alcGetString(NULL, ALC_CAPTURE_DEVICE_SPECIFIER);
|
||||||
|
|
||||||
|
while (*devices != 0)
|
||||||
|
{
|
||||||
|
microphones_list.append(qstr(devices));
|
||||||
|
devices += strlen(devices) + 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Without enumeration we can only use one device
|
||||||
|
microphones_list.append(qstr(alcGetString(NULL, ALC_DEFAULT_DEVICE_SPECIFIER)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string emu_settings::Microphone_Creator::SetDevice(u32 num, QString& text)
|
||||||
|
{
|
||||||
|
if (text == mic_none)
|
||||||
|
sel_list[num-1] = "";
|
||||||
|
else
|
||||||
|
sel_list[num-1] = text.toStdString();
|
||||||
|
|
||||||
|
const std::string final_list = sel_list[0] + "@@@" + sel_list[1] + "@@@" + sel_list[2] + "@@@" + sel_list[3] + "@@@";
|
||||||
|
return final_list;
|
||||||
|
}
|
||||||
|
|
||||||
|
void emu_settings::Microphone_Creator::ParseDevices(std::string list)
|
||||||
|
{
|
||||||
|
for (u32 index = 0; index < 4; index++)
|
||||||
|
{
|
||||||
|
sel_list[index] = "";
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto devices_list = fmt::split(list, { "@@@" });
|
||||||
|
for (u32 index = 0; index < std::min((u32)4, (u32)devices_list.size()); index++)
|
||||||
|
{
|
||||||
|
sel_list[index] = devices_list[index];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
emu_settings::emu_settings() : QObject()
|
emu_settings::emu_settings() : QObject()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
@ -109,6 +109,8 @@ public:
|
|||||||
AudioBufferDuration,
|
AudioBufferDuration,
|
||||||
EnableTimeStretching,
|
EnableTimeStretching,
|
||||||
TimeStretchingThreshold,
|
TimeStretchingThreshold,
|
||||||
|
MicrophoneType,
|
||||||
|
MicrophoneDevices,
|
||||||
|
|
||||||
// Input / Output
|
// Input / Output
|
||||||
PadHandler,
|
PadHandler,
|
||||||
@ -180,6 +182,17 @@ public:
|
|||||||
Render_Creator();
|
Render_Creator();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct Microphone_Creator
|
||||||
|
{
|
||||||
|
QStringList microphones_list;
|
||||||
|
QString mic_none = tr("None");
|
||||||
|
std::array<std::string, 4> sel_list;
|
||||||
|
std::string SetDevice(u32 num, QString& text);
|
||||||
|
void ParseDevices(std::string list);
|
||||||
|
void RefreshList();
|
||||||
|
Microphone_Creator();
|
||||||
|
};
|
||||||
|
|
||||||
std::set<SettingsType> m_broken_types; // list of broken settings
|
std::set<SettingsType> m_broken_types; // list of broken settings
|
||||||
|
|
||||||
/** Creates a settings object which reads in the config.yml file at rpcs3/bin/%path%/config.yml
|
/** Creates a settings object which reads in the config.yml file at rpcs3/bin/%path%/config.yml
|
||||||
@ -224,6 +237,9 @@ public:
|
|||||||
/** Gets all the renderer info for gpu settings.*/
|
/** Gets all the renderer info for gpu settings.*/
|
||||||
Render_Creator m_render_creator;
|
Render_Creator m_render_creator;
|
||||||
|
|
||||||
|
/** Gets a list of all the microphones available.*/
|
||||||
|
Microphone_Creator m_microphone_creator;
|
||||||
|
|
||||||
/** Loads the settings from path.*/
|
/** Loads the settings from path.*/
|
||||||
void LoadSettings(const std::string& title_id = "");
|
void LoadSettings(const std::string& title_id = "");
|
||||||
|
|
||||||
@ -320,6 +336,8 @@ private:
|
|||||||
{ AudioBufferDuration, { "Audio", "Desired Audio Buffer Duration"}},
|
{ AudioBufferDuration, { "Audio", "Desired Audio Buffer Duration"}},
|
||||||
{ EnableTimeStretching, { "Audio", "Enable Time Stretching"}},
|
{ EnableTimeStretching, { "Audio", "Enable Time Stretching"}},
|
||||||
{ TimeStretchingThreshold, { "Audio", "Time Stretching Threshold"}},
|
{ TimeStretchingThreshold, { "Audio", "Time Stretching Threshold"}},
|
||||||
|
{ MicrophoneType, { "Audio", "Microphone Type" }},
|
||||||
|
{ MicrophoneDevices, { "Audio", "Microphone Devices" }},
|
||||||
|
|
||||||
// Input / Output
|
// Input / Output
|
||||||
{ PadHandler, { "Input/Output", "Pad"}},
|
{ PadHandler, { "Input/Output", "Pad"}},
|
||||||
|
@ -774,6 +774,7 @@ settings_dialog::settings_dialog(std::shared_ptr<gui_settings> guiSettings, std:
|
|||||||
ui->timeStretchingThresholdLabel->setEnabled(enabled);
|
ui->timeStretchingThresholdLabel->setEnabled(enabled);
|
||||||
ui->timeStretchingThreshold->setEnabled(enabled);
|
ui->timeStretchingThreshold->setEnabled(enabled);
|
||||||
};
|
};
|
||||||
|
|
||||||
auto EnableBufferingOptions = [this, EnableTimeStretchingOptions](bool enabled)
|
auto EnableBufferingOptions = [this, EnableTimeStretchingOptions](bool enabled)
|
||||||
{
|
{
|
||||||
ui->audioBufferDuration->setEnabled(enabled);
|
ui->audioBufferDuration->setEnabled(enabled);
|
||||||
@ -781,6 +782,7 @@ settings_dialog::settings_dialog(std::shared_ptr<gui_settings> guiSettings, std:
|
|||||||
ui->enableTimeStretching->setEnabled(enabled);
|
ui->enableTimeStretching->setEnabled(enabled);
|
||||||
EnableTimeStretchingOptions(enabled && ui->enableTimeStretching->isChecked());
|
EnableTimeStretchingOptions(enabled && ui->enableTimeStretching->isChecked());
|
||||||
};
|
};
|
||||||
|
|
||||||
auto EnableBuffering = [this, EnableBufferingOptions](const QString& text)
|
auto EnableBuffering = [this, EnableBufferingOptions](const QString& text)
|
||||||
{
|
{
|
||||||
const bool enabled = text == "XAudio2" || text == "OpenAL";
|
const bool enabled = text == "XAudio2" || text == "OpenAL";
|
||||||
@ -788,6 +790,84 @@ settings_dialog::settings_dialog(std::shared_ptr<gui_settings> guiSettings, std:
|
|||||||
EnableBufferingOptions(enabled && ui->enableBuffering->isChecked());
|
EnableBufferingOptions(enabled && ui->enableBuffering->isChecked());
|
||||||
};
|
};
|
||||||
|
|
||||||
|
auto ChangeMicrophoneType = [=](QString text)
|
||||||
|
{
|
||||||
|
std::string s_standard, s_singstar, s_realsingstar, s_rocksmith;
|
||||||
|
|
||||||
|
auto enableMicsCombo = [=](u32 max)
|
||||||
|
{
|
||||||
|
ui->microphone1Box->setEnabled(true);
|
||||||
|
|
||||||
|
if (max == 1 || ui->microphone1Box->currentText() == xemu_settings->m_microphone_creator.mic_none)
|
||||||
|
return;
|
||||||
|
|
||||||
|
ui->microphone2Box->setEnabled(true);
|
||||||
|
|
||||||
|
if (max > 2 && ui->microphone2Box->currentText() != xemu_settings->m_microphone_creator.mic_none)
|
||||||
|
{
|
||||||
|
ui->microphone3Box->setEnabled(true);
|
||||||
|
if (ui->microphone3Box->currentText() != xemu_settings->m_microphone_creator.mic_none)
|
||||||
|
{
|
||||||
|
ui->microphone4Box->setEnabled(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
ui->microphone1Box->setEnabled(false);
|
||||||
|
ui->microphone2Box->setEnabled(false);
|
||||||
|
ui->microphone3Box->setEnabled(false);
|
||||||
|
ui->microphone4Box->setEnabled(false);
|
||||||
|
|
||||||
|
fmt_class_string<microphone_handler>::format(s_standard, static_cast<u64>(microphone_handler::standard));
|
||||||
|
fmt_class_string<microphone_handler>::format(s_singstar, static_cast<u64>(microphone_handler::singstar));
|
||||||
|
fmt_class_string<microphone_handler>::format(s_realsingstar, static_cast<u64>(microphone_handler::real_singstar));
|
||||||
|
fmt_class_string<microphone_handler>::format(s_rocksmith, static_cast<u64>(microphone_handler::rocksmith));
|
||||||
|
|
||||||
|
if (text == s_standard.c_str())
|
||||||
|
{
|
||||||
|
enableMicsCombo(4);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (text == s_singstar.c_str())
|
||||||
|
{
|
||||||
|
enableMicsCombo(2);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (text == s_realsingstar.c_str() || text == s_rocksmith.c_str())
|
||||||
|
{
|
||||||
|
enableMicsCombo(1);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
auto PropagateUsedDevices = [=]()
|
||||||
|
{
|
||||||
|
for (u32 index = 0; index < 4; index++)
|
||||||
|
{
|
||||||
|
const QString cur_item = mics_combo[index]->currentText();
|
||||||
|
QStringList cur_list = xemu_settings->m_microphone_creator.microphones_list;
|
||||||
|
for (u32 subindex = 0; subindex < 4; subindex++)
|
||||||
|
{
|
||||||
|
if (subindex != index && mics_combo[subindex]->currentText() != xemu_settings->m_microphone_creator.mic_none)
|
||||||
|
cur_list.removeOne(mics_combo[subindex]->currentText());
|
||||||
|
}
|
||||||
|
mics_combo[index]->blockSignals(true);
|
||||||
|
mics_combo[index]->clear();
|
||||||
|
mics_combo[index]->addItems(cur_list);
|
||||||
|
mics_combo[index]->setCurrentText(cur_item);
|
||||||
|
mics_combo[index]->blockSignals(false);
|
||||||
|
}
|
||||||
|
ChangeMicrophoneType(ui->microphoneBox->currentText());
|
||||||
|
};
|
||||||
|
|
||||||
|
auto ChangeMicrophoneDevice = [=](u32 next_index, QString text)
|
||||||
|
{
|
||||||
|
xemu_settings->SetSetting(emu_settings::MicrophoneDevices, xemu_settings->m_microphone_creator.SetDevice(next_index, text));
|
||||||
|
if (next_index < 4 && text == xemu_settings->m_microphone_creator.mic_none)
|
||||||
|
mics_combo[next_index]->setCurrentText(xemu_settings->m_microphone_creator.mic_none);
|
||||||
|
PropagateUsedDevices();
|
||||||
|
};
|
||||||
|
|
||||||
// Comboboxes
|
// Comboboxes
|
||||||
|
|
||||||
xemu_settings->EnhanceComboBox(ui->audioOutBox, emu_settings::AudioRenderer);
|
xemu_settings->EnhanceComboBox(ui->audioOutBox, emu_settings::AudioRenderer);
|
||||||
@ -800,6 +880,36 @@ settings_dialog::settings_dialog(std::shared_ptr<gui_settings> guiSettings, std:
|
|||||||
ui->audioOutBox->setItemText(ui->renderBox->findData("Null"), tr("Disable Audio Output"));
|
ui->audioOutBox->setItemText(ui->renderBox->findData("Null"), tr("Disable Audio Output"));
|
||||||
connect(ui->audioOutBox, &QComboBox::currentTextChanged, EnableBuffering);
|
connect(ui->audioOutBox, &QComboBox::currentTextChanged, EnableBuffering);
|
||||||
|
|
||||||
|
// Microphone Comboboxes
|
||||||
|
mics_combo[0] = ui->microphone1Box;
|
||||||
|
mics_combo[1] = ui->microphone2Box;
|
||||||
|
mics_combo[2] = ui->microphone3Box;
|
||||||
|
mics_combo[3] = ui->microphone4Box;
|
||||||
|
connect(mics_combo[0], &QComboBox::currentTextChanged, [=](const QString& text) { ChangeMicrophoneDevice(1, text); });
|
||||||
|
connect(mics_combo[1], &QComboBox::currentTextChanged, [=](const QString& text) { ChangeMicrophoneDevice(2, text); });
|
||||||
|
connect(mics_combo[2], &QComboBox::currentTextChanged, [=](const QString& text) { ChangeMicrophoneDevice(3, text); });
|
||||||
|
connect(mics_combo[3], &QComboBox::currentTextChanged, [=](const QString& text) { ChangeMicrophoneDevice(4, text); });
|
||||||
|
xemu_settings->m_microphone_creator.RefreshList();
|
||||||
|
PropagateUsedDevices(); // Fills comboboxes list
|
||||||
|
|
||||||
|
xemu_settings->m_microphone_creator.ParseDevices(xemu_settings->GetSetting(emu_settings::MicrophoneDevices));
|
||||||
|
|
||||||
|
for (s32 index = 3; index >= 0; index--)
|
||||||
|
{
|
||||||
|
if (xemu_settings->m_microphone_creator.sel_list[index] == "" || mics_combo[index]->findText(qstr(xemu_settings->m_microphone_creator.sel_list[index])) == -1)
|
||||||
|
{
|
||||||
|
mics_combo[index]->setCurrentText(xemu_settings->m_microphone_creator.mic_none);
|
||||||
|
ChangeMicrophoneDevice(index+1, xemu_settings->m_microphone_creator.mic_none); // Ensures the value is set in config
|
||||||
|
}
|
||||||
|
else
|
||||||
|
mics_combo[index]->setCurrentText(qstr(xemu_settings->m_microphone_creator.sel_list[index]));
|
||||||
|
}
|
||||||
|
|
||||||
|
xemu_settings->EnhanceComboBox(ui->microphoneBox, emu_settings::MicrophoneType);
|
||||||
|
SubscribeTooltip(ui->microphoneBox, json_audio["microphoneBox"].toString());
|
||||||
|
connect(ui->microphoneBox, &QComboBox::currentTextChanged, ChangeMicrophoneType);
|
||||||
|
PropagateUsedDevices(); // Enables/Disables comboboxes and checks values from config for sanity
|
||||||
|
|
||||||
// Checkboxes
|
// Checkboxes
|
||||||
|
|
||||||
xemu_settings->EnhanceCheckBox(ui->audioDump, emu_settings::DumpToFile);
|
xemu_settings->EnhanceCheckBox(ui->audioDump, emu_settings::DumpToFile);
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "gui_settings.h"
|
#include "gui_settings.h"
|
||||||
#include "emu_settings.h"
|
#include "emu_settings.h"
|
||||||
@ -36,13 +36,15 @@ private Q_SLOTS:
|
|||||||
private:
|
private:
|
||||||
void EnhanceSlider(emu_settings::SettingsType settings_type, QSlider* slider, QLabel* label, const QString& label_text);
|
void EnhanceSlider(emu_settings::SettingsType settings_type, QSlider* slider, QLabel* label, const QString& label_text);
|
||||||
|
|
||||||
//emulator tab
|
// Emulator tab
|
||||||
void AddConfigs();
|
void AddConfigs();
|
||||||
void AddStylesheets();
|
void AddStylesheets();
|
||||||
QString m_currentStylesheet;
|
QString m_currentStylesheet;
|
||||||
QString m_currentConfig;
|
QString m_currentConfig;
|
||||||
//gpu tab
|
// Gpu tab
|
||||||
QString m_oldRender = "";
|
QString m_oldRender = "";
|
||||||
|
// Audio tab
|
||||||
|
QComboBox *mics_combo[4];
|
||||||
|
|
||||||
int m_tab_Index;
|
int m_tab_Index;
|
||||||
Ui::settings_dialog *ui;
|
Ui::settings_dialog *ui;
|
||||||
@ -53,7 +55,7 @@ private:
|
|||||||
bool m_use_discord;
|
bool m_use_discord;
|
||||||
QString m_discord_state;
|
QString m_discord_state;
|
||||||
|
|
||||||
// descriptions
|
// Descriptions
|
||||||
QList<QPair<QLabel*, QString>> m_description_labels;
|
QList<QPair<QLabel*, QString>> m_description_labels;
|
||||||
QHash<QObject*, QString> m_descriptions;
|
QHash<QObject*, QString> m_descriptions;
|
||||||
void SubscribeDescription(QLabel* description);
|
void SubscribeDescription(QLabel* description);
|
||||||
|
@ -780,7 +780,7 @@
|
|||||||
<attribute name="title">
|
<attribute name="title">
|
||||||
<string>Audio</string>
|
<string>Audio</string>
|
||||||
</attribute>
|
</attribute>
|
||||||
<layout class="QVBoxLayout" name="verticalLayout_26" stretch="0,1,0">
|
<layout class="QVBoxLayout" name="verticalLayout_26" stretch="0,0,1,0">
|
||||||
<item>
|
<item>
|
||||||
<layout class="QHBoxLayout" name="horizontalLayout_9" stretch="1,1,1">
|
<layout class="QHBoxLayout" name="horizontalLayout_9" stretch="1,1,1">
|
||||||
<item>
|
<item>
|
||||||
@ -966,6 +966,157 @@
|
|||||||
</item>
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</item>
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QGroupBox" name="groupBox_9">
|
||||||
|
<property name="title">
|
||||||
|
<string>Microphone Settings</string>
|
||||||
|
</property>
|
||||||
|
<layout class="QVBoxLayout" name="verticalLayout_76">
|
||||||
|
<item>
|
||||||
|
<layout class="QHBoxLayout" name="horizontalLayout_7">
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="label_2">
|
||||||
|
<property name="text">
|
||||||
|
<string>Microphone Type:</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QComboBox" name="microphoneBox"/>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<spacer name="horizontalSpacer_2">
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Horizontal</enum>
|
||||||
|
</property>
|
||||||
|
<property name="sizeType">
|
||||||
|
<enum>QSizePolicy::MinimumExpanding</enum>
|
||||||
|
</property>
|
||||||
|
<property name="sizeHint" stdset="0">
|
||||||
|
<size>
|
||||||
|
<width>0</width>
|
||||||
|
<height>0</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
</spacer>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<layout class="QHBoxLayout" name="horizontalLayout_6">
|
||||||
|
<item>
|
||||||
|
<layout class="QVBoxLayout" name="verticalLayout_77">
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="label_3">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Minimum" vsizetype="Preferred">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Mic1:</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="label_5">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Minimum" vsizetype="Preferred">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Mic3:</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<layout class="QVBoxLayout" name="verticalLayout_78">
|
||||||
|
<item>
|
||||||
|
<widget class="QComboBox" name="microphone1Box">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QComboBox" name="microphone3Box">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<layout class="QVBoxLayout" name="verticalLayout_79">
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="label_4">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Minimum" vsizetype="Preferred">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Mic2:</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="label_6">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Minimum" vsizetype="Preferred">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Mic4:</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<layout class="QVBoxLayout" name="verticalLayout_80">
|
||||||
|
<item>
|
||||||
|
<widget class="QComboBox" name="microphone2Box">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QComboBox" name="microphone4Box">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<spacer name="verticalSpacer_19">
|
<spacer name="verticalSpacer_19">
|
||||||
<property name="orientation">
|
<property name="orientation">
|
||||||
|
Loading…
x
Reference in New Issue
Block a user