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) 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) 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 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) 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 #ifdef _WIN32
cellMic.error("Make sure microphone use is authorized under \"Microphone privacy settings\" in windows configuration"); cellMic.error("Make sure microphone use is authorized under \"Microphone privacy settings\" in windows configuration");
#endif #endif
return CELL_MICIN_ERROR_DEVICE_NOT_SUPPORT; return CELL_MICIN_ERROR_DEVICE_NOT_SUPPORT;
} }
input_devices.push_back(device); devices[0].device = device;
internal_bufs.emplace_back(); devices[0].buf.resize(inbuf_size, 0);
internal_bufs[0].resize(inbuf_size, 0);
temp_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 // 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) if (ALCenum err = alcGetError(device); err != ALC_NO_ERROR || !device)
{ {
// Ignore it and move on // 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 else
{ {
input_devices.push_back(device); devices[1].device = device;
internal_bufs.emplace_back(); devices[1].buf.resize(inbuf_size, 0);
internal_bufs[1].resize(inbuf_size, 0);
} }
} }
@ -455,16 +455,16 @@ error_code microphone_device::close_microphone()
stop_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(); micdevice.device = nullptr;
internal_bufs.clear(); micdevice.buf.clear();
}
mic_opened = false; mic_opened = false;
@ -473,12 +473,12 @@ error_code microphone_device::close_microphone()
error_code microphone_device::start_microphone() error_code microphone_device::start_microphone()
{ {
for (ALCdevice* micdevice : input_devices) for (const mic_device& micdevice : devices)
{ {
alcCaptureStart(micdevice); alcCaptureStart(micdevice.device);
if (ALCenum err = alcGetError(micdevice); err != ALC_NO_ERROR) 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(); stop_microphone();
return CELL_MICIN_ERROR_FATAL; return CELL_MICIN_ERROR_FATAL;
} }
@ -491,12 +491,12 @@ error_code microphone_device::start_microphone()
error_code microphone_device::stop_microphone() error_code microphone_device::stop_microphone()
{ {
for (ALCdevice* micdevice : input_devices) for (const mic_device& micdevice : devices)
{ {
alcCaptureStop(micdevice); alcCaptureStop(micdevice.device);
if (ALCenum err = alcGetError(micdevice); err != ALC_NO_ERROR) 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(); const u32 num_samples = capture_audio();
if (signal_types & CELLMIC_SIGTYPE_RAW) if (signal_types & CELLMIC_SIGTYPE_RAW)
{
get_raw(num_samples); get_raw(num_samples);
}
if (signal_types & CELLMIC_SIGTYPE_DSP) if (signal_types & CELLMIC_SIGTYPE_DSP)
{
get_dsp(num_samples); get_dsp(num_samples);
}
// TODO: aux? // TODO: aux?
} }
} }
@ -533,21 +539,26 @@ u32 microphone_device::capture_audio()
u32 num_samples = inbuf_size / sample_size; u32 num_samples = inbuf_size / sample_size;
for (ALCdevice* micdevice : input_devices) for (const mic_device& micdevice : devices)
{ {
ALCint samples_in = 0; ALCint samples_in = 0;
alcGetIntegerv(micdevice, ALC_CAPTURE_SAMPLES, 1, &samples_in); alcGetIntegerv(micdevice.device, ALC_CAPTURE_SAMPLES, 1, &samples_in);
if (ALCenum err = alcGetError(micdevice); err != ALC_NO_ERROR) 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; return CELL_MICIN_ERROR_FATAL;
} }
num_samples = std::min<u32>(num_samples, samples_in); 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; return num_samples;
@ -555,115 +566,116 @@ u32 microphone_device::capture_audio()
// Private functions // 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(); u8* tmp_ptr = temp_buf.data();
switch (device_type) switch (device_type)
{ {
case microphone_handler::real_singstar: 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 // 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; break;
}
case microphone_handler::standard: case microphone_handler::standard:
case microphone_handler::rocksmith: 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 // BE Translation
for (u32 index = 0; index < num_samples; index++) for (u32 index = 0; index < num_samples; index++)
{ {
const u32 sample_pos = index * sample_size;
for (u32 indchan = 0; indchan < num_channels; indchan++) for (u32 indchan = 0; indchan < num_channels; indchan++)
{ {
const u32 curindex = (index * sample_size) + indchan * (bit_resolution / 8); const u32 curindex = sample_pos + indchan * channel_size;
microphone_device::variable_byteswap(internal_bufs[0].data() + curindex, tmp_ptr + curindex, bit_resolution / 8); microphone_device::variable_byteswap(buf.data() + curindex, tmp_ptr + curindex, channel_size);
} }
} }
break; break;
}
case microphone_handler::singstar: case microphone_handler::singstar:
{
ensure(sample_size == 4); ensure(sample_size == 4);
// Mixing the 2 mics as if channels // Each device buffer contains 16 bit mono samples
if (input_devices.size() == 2) 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) for (u32 index = 0; index < (num_samples * 4); index += 4)
{ {
tmp_ptr[index] = internal_bufs[0][(index / 2)]; const u32 src_index = index / 2;
tmp_ptr[index + 1] = internal_bufs[0][(index / 2) + 1];
tmp_ptr[index + 2] = internal_bufs[1][(index / 2)]; tmp_ptr[index] = buf_0[src_index];
tmp_ptr[index + 3] = internal_bufs[1][(index / 2) + 1]; 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 else
{ {
for (u32 index = 0; index < (num_samples * 4); index += 4) for (u32 index = 0; index < (num_samples * 4); index += 4)
{ {
tmp_ptr[index] = internal_bufs[0][(index / 2)]; const u32 src_index = index / 2;
tmp_ptr[index + 1] = internal_bufs[0][(index / 2) + 1];
tmp_ptr[index] = buf_0[src_index];
tmp_ptr[index + 1] = buf_0[src_index + 1];
tmp_ptr[index + 2] = 0; tmp_ptr[index + 2] = 0;
tmp_ptr[index + 3] = 0; tmp_ptr[index + 3] = 0;
} }
} }
break; break;
}
case microphone_handler::null: case microphone_handler::null:
default: ensure(false); break; ensure(false);
break;
}
} }
rbuf_raw.write_bytes(tmp_ptr, num_samples * sample_size); void microphone_device::get_raw(const u32 num_samples)
}; {
if (num_samples == 0)
{
return;
}
get_data(num_samples);
rbuf_raw.write_bytes(temp_buf.data(), num_samples * sample_size);
}
void microphone_device::get_dsp(const u32 num_samples) void microphone_device::get_dsp(const u32 num_samples)
{ {
u8* tmp_ptr = temp_buf.data(); if (num_samples == 0)
switch (device_type)
{ {
case microphone_handler::real_singstar: return;
// 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; get_data(num_samples);
case microphone_handler::null:
default: ensure(false); break;
}
rbuf_dsp.write_bytes(tmp_ptr, num_samples * sample_size); rbuf_dsp.write_bytes(temp_buf.data(), num_samples * sample_size);
}; }
/// Initialization/Shutdown Functions /// Initialization/Shutdown Functions

View file

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