mirror of
https://github.com/RPCS3/rpcs3.git
synced 2025-03-14 10:21:21 +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/Cell/PPUModule.h"
|
||||
#include "Emu/IdManager.h"
|
||||
#include "Emu/RSX/rsx_utils.h"
|
||||
#include "Utilities/StrUtil.h"
|
||||
|
||||
#include "cellAudioIn.h"
|
||||
#include "cellAudioOut.h"
|
||||
@ -11,6 +12,115 @@
|
||||
|
||||
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)
|
||||
{
|
||||
cellAvconfExt.todo("cellAudioOutUnregisterDevice(deviceNumber=0x%x)", deviceNumber);
|
||||
@ -38,23 +148,21 @@ s32 cellVideoOutSetupDisplay()
|
||||
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);
|
||||
info->portType = CELL_AUDIO_IN_PORT_USB;
|
||||
info->availableModeCount = 1;
|
||||
info->state = CELL_AUDIO_IN_DEVICE_STATE_AVAILABLE;
|
||||
info->deviceNumber = 0;
|
||||
// Some games check if deviceId and type are the same.
|
||||
info->deviceId = 0xDEADBEEF;
|
||||
info->type = 0xBEEFDEAD;
|
||||
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");
|
||||
|
||||
auto av_manager = fxm::get_always<avconf_manager>();
|
||||
|
||||
if (deviceNumber >= av_manager->devices.size())
|
||||
return CELL_AUDIO_OUT_ERROR_DEVICE_NOT_FOUND;
|
||||
|
||||
av_manager->copy_device_info(deviceNumber, info);
|
||||
|
||||
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)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
@ -68,26 +176,30 @@ s32 cellVideoOutGetGamma(u32 videoOut, vm::ptr<f32> gamma)
|
||||
}
|
||||
|
||||
auto conf = fxm::get_always<rsx::avconf>();
|
||||
*gamma = conf->gamma;
|
||||
*gamma = conf->gamma;
|
||||
|
||||
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);
|
||||
info->portType = CELL_AUDIO_IN_PORT_USB;
|
||||
info->availableModeCount = 1;
|
||||
info->state = CELL_AUDIO_IN_DEVICE_STATE_AVAILABLE;
|
||||
info->deviceNumber = 0;
|
||||
// Some games check if deviceId and type are the same.
|
||||
info->deviceId = 0xDEADBEEF;
|
||||
info->type = 0xBEEFDEAD;
|
||||
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 1; // number of available devices
|
||||
cellAvconfExt.todo("cellAudioInGetAvailableDeviceInfo(count=0x%x, info=*0x%x)", count, device_info);
|
||||
|
||||
if (count > 16 || !device_info.addr())
|
||||
{
|
||||
return CELL_AUDIO_IN_ERROR_ILLEGAL_PARAMETER;
|
||||
}
|
||||
|
||||
auto av_manager = fxm::get_always<avconf_manager>();
|
||||
|
||||
u32 num_devices_returned = std::min(count, (u32)av_manager->devices.size());
|
||||
|
||||
for (u32 index = 0; index < num_devices_returned; index++)
|
||||
{
|
||||
av_manager->copy_device_info(index, device_info + index);
|
||||
}
|
||||
|
||||
return (s32)num_devices_returned;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
auto conf = fxm::get_always<rsx::avconf>();
|
||||
auto conf = fxm::get_always<rsx::avconf>();
|
||||
conf->gamma = gamma;
|
||||
|
||||
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)
|
||||
{
|
||||
cellAvconfExt.todo("cellAudioInRegisterDevice(deviceType=0x%llx, name=%s, option=*0x%x, config=*0x%x)", deviceType, name, option, config);
|
||||
|
||||
return 0; // device number
|
||||
}
|
||||
|
||||
@ -155,10 +268,10 @@ s32 cellVideoOutGetScreenSize(u32 videoOut, vm::ptr<f32> screenSize)
|
||||
return CELL_VIDEO_OUT_ERROR_UNSUPPORTED_VIDEO_OUT;
|
||||
}
|
||||
|
||||
//TODO: Use virtual screen size
|
||||
// TODO: Use virtual screen size
|
||||
#ifdef _WIN32
|
||||
//HDC screen = GetDC(NULL);
|
||||
//float diagonal = roundf(sqrtf((powf(float(GetDeviceCaps(screen, HORZSIZE)), 2) + powf(float(GetDeviceCaps(screen, VERTSIZE)), 2))) * 0.0393f);
|
||||
// HDC screen = GetDC(NULL);
|
||||
// float diagonal = roundf(sqrtf((powf(float(GetDeviceCaps(screen, HORZSIZE)), 2) + powf(float(GetDeviceCaps(screen, VERTSIZE)), 2))) * 0.0393f);
|
||||
#else
|
||||
// TODO: Linux implementation, without using wx
|
||||
// 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;
|
||||
}
|
||||
|
||||
|
||||
DECLARE(ppu_module_manager::cellAvconfExt)("cellSysutilAvconfExt", []()
|
||||
{
|
||||
DECLARE(ppu_module_manager::cellAvconfExt)
|
||||
("cellSysutilAvconfExt", []() {
|
||||
REG_FUNC(cellSysutilAvconfExt, cellAudioOutUnregisterDevice);
|
||||
REG_FUNC(cellSysutilAvconfExt, cellAudioOutGetDeviceInfo2);
|
||||
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/Thread.h"
|
||||
|
||||
#include "3rdparty/OpenAL/include/alext.h"
|
||||
|
||||
// Error Codes
|
||||
enum
|
||||
{
|
||||
CELL_MIC_ERROR_ALREADY_INIT = 0x80140101,
|
||||
CELL_MIC_ERROR_SYSTEM = 0x80140102,
|
||||
CELL_MIC_ERROR_NOT_INIT = 0x80140103,
|
||||
CELL_MIC_ERROR_PARAM = 0x80140104,
|
||||
CELL_MIC_ERROR_PORT_FULL = 0x80140105,
|
||||
CELL_MIC_ERROR_ALREADY_OPEN = 0x80140106,
|
||||
CELL_MIC_ERROR_NOT_OPEN = 0x80140107,
|
||||
CELL_MIC_ERROR_NOT_RUN = 0x80140108,
|
||||
CELL_MIC_ERROR_TRANS_EVENT = 0x80140109,
|
||||
CELL_MIC_ERROR_OPEN = 0x8014010a,
|
||||
CELL_MIC_ERROR_SHAREDMEMORY = 0x8014010b,
|
||||
CELL_MIC_ERROR_MUTEX = 0x8014010c,
|
||||
CELL_MIC_ERROR_EVENT_QUEUE = 0x8014010d,
|
||||
CELL_MIC_ERROR_DEVICE_NOT_FOUND = 0x8014010e,
|
||||
CELL_MIC_ERROR_SYSTEM_NOT_FOUND = 0x8014010e,
|
||||
CELL_MIC_ERROR_FATAL = 0x8014010f,
|
||||
CELL_MIC_ERROR_ALREADY_INIT = 0x80140101,
|
||||
CELL_MIC_ERROR_SYSTEM = 0x80140102,
|
||||
CELL_MIC_ERROR_NOT_INIT = 0x80140103,
|
||||
CELL_MIC_ERROR_PARAM = 0x80140104,
|
||||
CELL_MIC_ERROR_PORT_FULL = 0x80140105,
|
||||
CELL_MIC_ERROR_ALREADY_OPEN = 0x80140106,
|
||||
CELL_MIC_ERROR_NOT_OPEN = 0x80140107,
|
||||
CELL_MIC_ERROR_NOT_RUN = 0x80140108,
|
||||
CELL_MIC_ERROR_TRANS_EVENT = 0x80140109,
|
||||
CELL_MIC_ERROR_OPEN = 0x8014010a,
|
||||
CELL_MIC_ERROR_SHAREDMEMORY = 0x8014010b,
|
||||
CELL_MIC_ERROR_MUTEX = 0x8014010c,
|
||||
CELL_MIC_ERROR_EVENT_QUEUE = 0x8014010d,
|
||||
CELL_MIC_ERROR_DEVICE_NOT_FOUND = 0x8014010e,
|
||||
CELL_MIC_ERROR_SYSTEM_NOT_FOUND = 0x8014010e,
|
||||
CELL_MIC_ERROR_FATAL = 0x8014010f,
|
||||
CELL_MIC_ERROR_DEVICE_NOT_SUPPORT = 0x80140110,
|
||||
};
|
||||
|
||||
struct CellMicInputFormat
|
||||
{
|
||||
u8 channelNum;
|
||||
u8 subframeSize;
|
||||
u8 bitResolution;
|
||||
u8 dataType;
|
||||
be_t<u32> sampleRate;
|
||||
u8 channelNum;
|
||||
u8 subframeSize;
|
||||
u8 bitResolution;
|
||||
u8 dataType;
|
||||
be_t<u32> sampleRate;
|
||||
};
|
||||
|
||||
enum CellMicSignalState
|
||||
enum CellMicSignalState : u32
|
||||
{
|
||||
CELL_MIC_SIGSTATE_LOCTALK = 0,
|
||||
CELL_MIC_SIGSTATE_FARTALK = 1,
|
||||
@ -47,32 +49,220 @@ enum CellMicSignalState
|
||||
enum CellMicCommand
|
||||
{
|
||||
CELL_MIC_ATTACH = 2,
|
||||
CELL_MIC_DATA = 5,
|
||||
CELL_MIC_DATA = 5,
|
||||
};
|
||||
|
||||
// TODO: generate this from input from an actual microphone
|
||||
const u32 bufferSize = 1;
|
||||
enum CellMicDeviceAttr : u32
|
||||
{
|
||||
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
|
||||
{
|
||||
public:
|
||||
void operator()();
|
||||
void load_config_and_init();
|
||||
|
||||
// Default value of 48000 for no particular reason
|
||||
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;
|
||||
u64 event_queue_key = 0;
|
||||
|
||||
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
|
||||
std::unordered_map<u8, microphone_device> mic_list;
|
||||
|
||||
protected:
|
||||
const u64 start_time = get_system_time();
|
||||
u64 m_counter = 0;
|
||||
|
||||
// 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>;
|
||||
|
@ -119,6 +119,15 @@ enum class move_handler
|
||||
fake,
|
||||
};
|
||||
|
||||
enum class microphone_handler
|
||||
{
|
||||
null,
|
||||
standard,
|
||||
singstar,
|
||||
real_singstar,
|
||||
rocksmith,
|
||||
};
|
||||
|
||||
enum class video_resolution
|
||||
{
|
||||
_1080,
|
||||
@ -546,7 +555,8 @@ struct cfg_root : cfg::node
|
||||
cfg::_int<1, 1000> sampling_period_multiplier{this, "Sampling Period Multiplier", 100};
|
||||
cfg::_bool enable_time_stretching{this, "Enable Time Stretching", false};
|
||||
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};
|
||||
|
||||
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<fake_camera_type> camera_type{this, "Camera type", fake_camera_type::unknown};
|
||||
cfg::_enum<move_handler> move{this, "Move", move_handler::null};
|
||||
|
||||
} io{this};
|
||||
|
||||
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).",
|
||||
"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.",
|
||||
"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": {
|
||||
"PPU": {
|
||||
|
@ -9,6 +9,7 @@
|
||||
#include "Emu/System.h"
|
||||
#include "Utilities/Config.h"
|
||||
#include "Utilities/Thread.h"
|
||||
#include "Utilities/StrUtil.h"
|
||||
|
||||
#include <QMessageBox>
|
||||
|
||||
@ -24,6 +25,8 @@
|
||||
#include "Emu/RSX/VK/VKHelpers.h"
|
||||
#endif
|
||||
|
||||
#include "3rdparty/OpenAL/include/alext.h"
|
||||
|
||||
extern std::string g_cfg_defaults; //! Default settings grabbed from Utilities/Config.h
|
||||
|
||||
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 };
|
||||
}
|
||||
|
||||
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()
|
||||
{
|
||||
}
|
||||
|
@ -109,6 +109,8 @@ public:
|
||||
AudioBufferDuration,
|
||||
EnableTimeStretching,
|
||||
TimeStretchingThreshold,
|
||||
MicrophoneType,
|
||||
MicrophoneDevices,
|
||||
|
||||
// Input / Output
|
||||
PadHandler,
|
||||
@ -180,6 +182,17 @@ public:
|
||||
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
|
||||
|
||||
/** 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.*/
|
||||
Render_Creator m_render_creator;
|
||||
|
||||
/** Gets a list of all the microphones available.*/
|
||||
Microphone_Creator m_microphone_creator;
|
||||
|
||||
/** Loads the settings from path.*/
|
||||
void LoadSettings(const std::string& title_id = "");
|
||||
|
||||
@ -320,6 +336,8 @@ private:
|
||||
{ AudioBufferDuration, { "Audio", "Desired Audio Buffer Duration"}},
|
||||
{ EnableTimeStretching, { "Audio", "Enable Time Stretching"}},
|
||||
{ TimeStretchingThreshold, { "Audio", "Time Stretching Threshold"}},
|
||||
{ MicrophoneType, { "Audio", "Microphone Type" }},
|
||||
{ MicrophoneDevices, { "Audio", "Microphone Devices" }},
|
||||
|
||||
// Input / Output
|
||||
{ PadHandler, { "Input/Output", "Pad"}},
|
||||
|
@ -774,6 +774,7 @@ settings_dialog::settings_dialog(std::shared_ptr<gui_settings> guiSettings, std:
|
||||
ui->timeStretchingThresholdLabel->setEnabled(enabled);
|
||||
ui->timeStretchingThreshold->setEnabled(enabled);
|
||||
};
|
||||
|
||||
auto EnableBufferingOptions = [this, EnableTimeStretchingOptions](bool enabled)
|
||||
{
|
||||
ui->audioBufferDuration->setEnabled(enabled);
|
||||
@ -781,6 +782,7 @@ settings_dialog::settings_dialog(std::shared_ptr<gui_settings> guiSettings, std:
|
||||
ui->enableTimeStretching->setEnabled(enabled);
|
||||
EnableTimeStretchingOptions(enabled && ui->enableTimeStretching->isChecked());
|
||||
};
|
||||
|
||||
auto EnableBuffering = [this, EnableBufferingOptions](const QString& text)
|
||||
{
|
||||
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());
|
||||
};
|
||||
|
||||
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
|
||||
|
||||
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"));
|
||||
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
|
||||
|
||||
xemu_settings->EnhanceCheckBox(ui->audioDump, emu_settings::DumpToFile);
|
||||
|
@ -1,4 +1,4 @@
|
||||
#pragma once
|
||||
#pragma once
|
||||
|
||||
#include "gui_settings.h"
|
||||
#include "emu_settings.h"
|
||||
@ -36,13 +36,15 @@ private Q_SLOTS:
|
||||
private:
|
||||
void EnhanceSlider(emu_settings::SettingsType settings_type, QSlider* slider, QLabel* label, const QString& label_text);
|
||||
|
||||
//emulator tab
|
||||
// Emulator tab
|
||||
void AddConfigs();
|
||||
void AddStylesheets();
|
||||
QString m_currentStylesheet;
|
||||
QString m_currentConfig;
|
||||
//gpu tab
|
||||
// Gpu tab
|
||||
QString m_oldRender = "";
|
||||
// Audio tab
|
||||
QComboBox *mics_combo[4];
|
||||
|
||||
int m_tab_Index;
|
||||
Ui::settings_dialog *ui;
|
||||
@ -53,7 +55,7 @@ private:
|
||||
bool m_use_discord;
|
||||
QString m_discord_state;
|
||||
|
||||
// descriptions
|
||||
// Descriptions
|
||||
QList<QPair<QLabel*, QString>> m_description_labels;
|
||||
QHash<QObject*, QString> m_descriptions;
|
||||
void SubscribeDescription(QLabel* description);
|
||||
|
@ -780,7 +780,7 @@
|
||||
<attribute name="title">
|
||||
<string>Audio</string>
|
||||
</attribute>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_26" stretch="0,1,0">
|
||||
<layout class="QVBoxLayout" name="verticalLayout_26" stretch="0,0,1,0">
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_9" stretch="1,1,1">
|
||||
<item>
|
||||
@ -966,6 +966,157 @@
|
||||
</item>
|
||||
</layout>
|
||||
</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>
|
||||
<spacer name="verticalSpacer_19">
|
||||
<property name="orientation">
|
||||
|
Loading…
x
Reference in New Issue
Block a user