cellMic: remove duplicate code and add size checks

This commit is contained in:
Megamouse 2024-08-05 23:50:56 +02:00
parent f09d22a00d
commit 667db0f2de
2 changed files with 126 additions and 103 deletions

View file

@ -260,7 +260,9 @@ microphone_device::microphone_device(microphone_handler type)
void microphone_device::add_device(const std::string& name)
{
device_name.push_back(name);
devices.push_back(mic_device{
.name = name
});
}
error_code microphone_device::open_microphone(const u8 type, const u32 dsp_r, const u32 raw_r, const u8 channels)
@ -406,39 +408,37 @@ error_code microphone_device::open_microphone(const u8 type, const u32 dsp_r, co
aux_samplingrate = dsp_samplingrate = raw_samplingrate; // Same rate for now
ensure(!device_name.empty());
ensure(!devices.empty());
ALCdevice* device = alcCaptureOpenDevice(device_name[0].c_str(), raw_samplingrate, num_al_channels, inbuf_size);
ALCdevice* device = alcCaptureOpenDevice(devices[0].name.c_str(), raw_samplingrate, num_al_channels, inbuf_size);
if (ALCenum err = alcGetError(device); err != ALC_NO_ERROR || !device)
{
cellMic.error("Error opening capture device %s (error=0x%x, device=*0x%x)", device_name[0], err, device);
cellMic.error("Error opening capture device %s (error=0x%x, device=*0x%x)", devices[0].name, err, device);
#ifdef _WIN32
cellMic.error("Make sure microphone use is authorized under \"Microphone privacy settings\" in windows configuration");
#endif
return CELL_MICIN_ERROR_DEVICE_NOT_SUPPORT;
}
input_devices.push_back(device);
internal_bufs.emplace_back();
internal_bufs[0].resize(inbuf_size, 0);
devices[0].device = device;
devices[0].buf.resize(inbuf_size, 0);
temp_buf.resize(inbuf_size, 0);
if (device_type == microphone_handler::singstar && device_name.size() >= 2)
if (device_type == microphone_handler::singstar && devices.size() >= 2)
{
// Open a 2nd microphone into the same device
device = alcCaptureOpenDevice(device_name[1].c_str(), raw_samplingrate, AL_FORMAT_MONO16, inbuf_size);
device = alcCaptureOpenDevice(devices[1].name.c_str(), raw_samplingrate, AL_FORMAT_MONO16, inbuf_size);
if (ALCenum err = alcGetError(device); err != ALC_NO_ERROR || !device)
{
// Ignore it and move on
cellMic.error("Error opening 2nd SingStar capture device %s (error=0x%x, device=*0x%x)", device_name[1], err, device);
cellMic.error("Error opening 2nd SingStar capture device %s (error=0x%x, device=*0x%x)", devices[1].name, err, device);
}
else
{
input_devices.push_back(device);
internal_bufs.emplace_back();
internal_bufs[1].resize(inbuf_size, 0);
devices[1].device = device;
devices[1].buf.resize(inbuf_size, 0);
}
}
@ -455,16 +455,16 @@ error_code microphone_device::close_microphone()
stop_microphone();
}
for (const auto& micdevice : input_devices)
for (mic_device& micdevice : devices)
{
if (alcCaptureCloseDevice(micdevice) != ALC_TRUE)
if (alcCaptureCloseDevice(micdevice.device) != ALC_TRUE)
{
cellMic.error("Error closing capture device");
cellMic.error("Error closing capture device %s", micdevice.name);
}
}
input_devices.clear();
internal_bufs.clear();
micdevice.device = nullptr;
micdevice.buf.clear();
}
mic_opened = false;
@ -473,12 +473,12 @@ error_code microphone_device::close_microphone()
error_code microphone_device::start_microphone()
{
for (ALCdevice* micdevice : input_devices)
for (const mic_device& micdevice : devices)
{
alcCaptureStart(micdevice);
if (ALCenum err = alcGetError(micdevice); err != ALC_NO_ERROR)
alcCaptureStart(micdevice.device);
if (ALCenum err = alcGetError(micdevice.device); err != ALC_NO_ERROR)
{
cellMic.error("Error starting capture (error=0x%x)", err);
cellMic.error("Error starting capture of device %s (error=0x%x)", micdevice.name, err);
stop_microphone();
return CELL_MICIN_ERROR_FATAL;
}
@ -491,12 +491,12 @@ error_code microphone_device::start_microphone()
error_code microphone_device::stop_microphone()
{
for (ALCdevice* micdevice : input_devices)
for (const mic_device& micdevice : devices)
{
alcCaptureStop(micdevice);
if (ALCenum err = alcGetError(micdevice); err != ALC_NO_ERROR)
alcCaptureStop(micdevice.device);
if (ALCenum err = alcGetError(micdevice.device); err != ALC_NO_ERROR)
{
cellMic.error("Error stopping capture (error=0x%x)", err);
cellMic.error("Error stopping capture of device %s (error=0x%x)", micdevice.name, err);
}
}
@ -515,9 +515,15 @@ void microphone_device::update_audio()
const u32 num_samples = capture_audio();
if (signal_types & CELLMIC_SIGTYPE_RAW)
{
get_raw(num_samples);
}
if (signal_types & CELLMIC_SIGTYPE_DSP)
{
get_dsp(num_samples);
}
// TODO: aux?
}
}
@ -533,21 +539,26 @@ u32 microphone_device::capture_audio()
u32 num_samples = inbuf_size / sample_size;
for (ALCdevice* micdevice : input_devices)
for (const mic_device& micdevice : devices)
{
ALCint samples_in = 0;
alcGetIntegerv(micdevice, ALC_CAPTURE_SAMPLES, 1, &samples_in);
if (ALCenum err = alcGetError(micdevice); err != ALC_NO_ERROR)
alcGetIntegerv(micdevice.device, ALC_CAPTURE_SAMPLES, 1, &samples_in);
if (ALCenum err = alcGetError(micdevice.device); err != ALC_NO_ERROR)
{
cellMic.error("Error getting number of captured samples (error=0x%x)", err);
cellMic.error("Error getting number of captured samples of device %s (error=0x%x)", micdevice.name, err);
return CELL_MICIN_ERROR_FATAL;
}
num_samples = std::min<u32>(num_samples, samples_in);
}
for (u32 index = 0; index < input_devices.size(); index++)
for (mic_device& micdevice : devices)
{
alcCaptureSamples(input_devices[index], internal_bufs[index].data(), num_samples);
alcCaptureSamples(micdevice.device, micdevice.buf.data(), num_samples);
if (ALCenum err = alcGetError(micdevice.device); err != ALC_NO_ERROR)
{
cellMic.error("Error capturing samples of device %s (error=0x%x)", micdevice.name, err);
}
}
return num_samples;
@ -555,115 +566,116 @@ u32 microphone_device::capture_audio()
// Private functions
void microphone_device::get_raw(const u32 num_samples)
void microphone_device::get_data(const u32 num_samples)
{
ensure(num_samples > 0);
u8* tmp_ptr = temp_buf.data();
switch (device_type)
{
case microphone_handler::real_singstar:
{
const usz bufsize = num_samples * sample_size;
const mic_device& device = ::at32(devices, 0);
ensure(bufsize <= device.buf.size());
ensure(bufsize <= temp_buf.size());
// Straight copy from device
memcpy(tmp_ptr, internal_bufs[0].data(), num_samples * (bit_resolution / 8) * num_channels);
std::memcpy(tmp_ptr, device.buf.data(), bufsize);
break;
}
case microphone_handler::standard:
case microphone_handler::rocksmith:
{
const u8 channel_size = bit_resolution / 8;
const usz bufsize = num_samples * sample_size;
const std::vector<u8>& buf = ::at32(devices, 0).buf;
ensure(bufsize <= buf.size());
ensure(bufsize <= temp_buf.size());
// BE Translation
for (u32 index = 0; index < num_samples; index++)
{
const u32 sample_pos = index * sample_size;
for (u32 indchan = 0; indchan < num_channels; indchan++)
{
const u32 curindex = (index * sample_size) + indchan * (bit_resolution / 8);
microphone_device::variable_byteswap(internal_bufs[0].data() + curindex, tmp_ptr + curindex, bit_resolution / 8);
const u32 curindex = sample_pos + indchan * channel_size;
microphone_device::variable_byteswap(buf.data() + curindex, tmp_ptr + curindex, channel_size);
}
}
break;
}
case microphone_handler::singstar:
{
ensure(sample_size == 4);
// Mixing the 2 mics as if channels
if (input_devices.size() == 2)
// Each device buffer contains 16 bit mono samples
const usz bufsize = num_samples * sizeof(u16);
const std::vector<u8>& buf_0 = ::at32(devices, 0).buf;
ensure(bufsize <= buf_0.size());
// Mixing the 2 mics into the 2 destination channels
if (devices.size() == 2)
{
const std::vector<u8>& buf_1 = ::at32(devices, 1).buf;
ensure(bufsize <= buf_1.size());
for (u32 index = 0; index < (num_samples * 4); index += 4)
{
tmp_ptr[index] = internal_bufs[0][(index / 2)];
tmp_ptr[index + 1] = internal_bufs[0][(index / 2) + 1];
tmp_ptr[index + 2] = internal_bufs[1][(index / 2)];
tmp_ptr[index + 3] = internal_bufs[1][(index / 2) + 1];
const u32 src_index = index / 2;
tmp_ptr[index] = buf_0[src_index];
tmp_ptr[index + 1] = buf_0[src_index + 1];
tmp_ptr[index + 2] = buf_1[src_index];
tmp_ptr[index + 3] = buf_1[src_index + 1];
}
}
else
{
for (u32 index = 0; index < (num_samples * 4); index += 4)
{
tmp_ptr[index] = internal_bufs[0][(index / 2)];
tmp_ptr[index + 1] = internal_bufs[0][(index / 2) + 1];
const u32 src_index = index / 2;
tmp_ptr[index] = buf_0[src_index];
tmp_ptr[index + 1] = buf_0[src_index + 1];
tmp_ptr[index + 2] = 0;
tmp_ptr[index + 3] = 0;
}
}
break;
}
case microphone_handler::null:
default: ensure(false); break;
ensure(false);
break;
}
}
void microphone_device::get_raw(const u32 num_samples)
{
if (num_samples == 0)
{
return;
}
rbuf_raw.write_bytes(tmp_ptr, num_samples * sample_size);
};
get_data(num_samples);
rbuf_raw.write_bytes(temp_buf.data(), num_samples * sample_size);
}
void microphone_device::get_dsp(const u32 num_samples)
{
u8* tmp_ptr = temp_buf.data();
switch (device_type)
if (num_samples == 0)
{
case microphone_handler::real_singstar:
// Straight copy from device
memcpy(tmp_ptr, internal_bufs[0].data(), num_samples * (bit_resolution / 8) * num_channels);
break;
case microphone_handler::standard:
case microphone_handler::rocksmith:
// BE Translation
for (u32 index = 0; index < num_samples; index++)
{
for (u32 indchan = 0; indchan < num_channels; indchan++)
{
const u32 curindex = (index * sample_size) + indchan * (bit_resolution / 8);
microphone_device::variable_byteswap(internal_bufs[0].data() + curindex, tmp_ptr + curindex, bit_resolution / 8);
}
}
break;
case microphone_handler::singstar:
ensure(sample_size == 4);
// Mixing the 2 mics as if channels
if (input_devices.size() == 2)
{
for (u32 index = 0; index < (num_samples * 4); index += 4)
{
tmp_ptr[index] = internal_bufs[0][(index / 2)];
tmp_ptr[index + 1] = internal_bufs[0][(index / 2) + 1];
tmp_ptr[index + 2] = internal_bufs[1][(index / 2)];
tmp_ptr[index + 3] = internal_bufs[1][(index / 2) + 1];
}
}
else
{
for (u32 index = 0; index < (num_samples * 4); index += 4)
{
tmp_ptr[index] = internal_bufs[0][(index / 2)];
tmp_ptr[index + 1] = internal_bufs[0][(index / 2) + 1];
tmp_ptr[index + 2] = 0;
tmp_ptr[index + 3] = 0;
}
}
break;
case microphone_handler::null:
default: ensure(false); break;
return;
}
rbuf_dsp.write_bytes(tmp_ptr, num_samples * sample_size);
};
get_data(num_samples);
rbuf_dsp.write_bytes(temp_buf.data(), num_samples * sample_size);
}
/// Initialization/Shutdown Functions

View file

@ -197,12 +197,12 @@ public:
u32 read_bytes(u8* buf, const u32 size)
{
ensure(buf);
const u32 to_read = size > m_used ? m_used : size;
if (!to_read)
return 0;
ensure(buf);
u8* data = m_container.data();
const u32 new_tail = m_tail + to_read;
@ -226,6 +226,11 @@ public:
void write_bytes(const u8* buf, const u32 size)
{
if (size == 0)
{
return;
}
ensure(size <= Size);
const u32 over_size = m_used + size;
@ -280,7 +285,7 @@ public:
error_code start_microphone();
error_code stop_microphone();
std::string get_device_name() const { return device_name.empty() ? "" : device_name.front(); }
std::string get_device_name() const { return devices.empty() ? "" : devices.front().name; }
void update_audio();
bool has_data() const;
@ -320,18 +325,24 @@ private:
u32 capture_audio();
void get_data(const u32 num_samples);
void get_raw(const u32 num_samples);
void get_dsp(const u32 num_samples);
microphone_handler device_type = microphone_handler::null;
std::vector<std::string> device_name;
bool mic_registered = false;
bool mic_opened = false;
bool mic_started = false;
std::vector<ALCdevice*> input_devices;
std::vector<std::vector<u8>> internal_bufs;
struct mic_device
{
std::string name;
ALCdevice* device = nullptr;
std::vector<u8> buf;
};
std::vector<mic_device> devices;
std::vector<u8> temp_buf;
// Sampling information provided at opening of mic