From 5f532c25600e0ed4d36632d06093ed07fb80fea6 Mon Sep 17 00:00:00 2001 From: James Rowe Date: Wed, 6 Mar 2019 11:16:43 -0700 Subject: [PATCH] Address review comments --- src/audio_core/cubeb_input.cpp | 13 +-- src/audio_core/cubeb_input.h | 2 +- src/citra/config.cpp | 4 + src/citra_qt/configuration/config.cpp | 7 +- .../configuration/configure_audio.cpp | 13 +-- src/core/frontend/mic.cpp | 70 +++++--------- src/core/frontend/mic.h | 36 +++---- src/core/hle/service/mic_u.cpp | 93 ++++++++++--------- src/core/hle/service/mic_u.h | 2 - src/core/settings.cpp | 6 +- src/core/settings.h | 8 +- 11 files changed, 119 insertions(+), 135 deletions(-) diff --git a/src/audio_core/cubeb_input.cpp b/src/audio_core/cubeb_input.cpp index 6c7f3e740..5666b09bb 100644 --- a/src/audio_core/cubeb_input.cpp +++ b/src/audio_core/cubeb_input.cpp @@ -9,11 +9,13 @@ namespace AudioCore { +using SampleQueue = Common::SPSCQueue; + struct CubebInput::Impl { cubeb* ctx = nullptr; cubeb_stream* stream = nullptr; - std::unique_ptr sample_queue{}; + std::unique_ptr sample_queue{}; u8 sample_size_in_bytes = 0; static long DataCallback(cubeb_stream* stream, void* user_data, const void* input_buffer, @@ -26,7 +28,7 @@ CubebInput::CubebInput() : impl(std::make_unique()) { LOG_ERROR(Audio, "cubeb_init failed! Mic will not work properly"); return; } - impl->sample_queue = std::make_unique(); + impl->sample_queue = std::make_unique(); } CubebInput::~CubebInput() { @@ -40,7 +42,7 @@ CubebInput::~CubebInput() { cubeb_destroy(impl->ctx); } -void CubebInput::StartSampling(Frontend::Mic::Parameters params) { +void CubebInput::StartSampling(const Frontend::Mic::Parameters& params) { // Cubeb apparently only supports signed 16 bit PCM (and float32 which the 3ds doesn't support) // TODO resample the input stream if (params.sign == Frontend::Mic::Signedness::Unsigned) { @@ -103,12 +105,11 @@ Frontend::Mic::Samples CubebInput::Read() { long CubebInput::Impl::DataCallback(cubeb_stream* stream, void* user_data, const void* input_buffer, void* output_buffer, long num_frames) { Impl* impl = static_cast(user_data); - u8 const* data = reinterpret_cast(input_buffer); - if (!impl) { return 0; } + u8 const* data = reinterpret_cast(input_buffer); impl->sample_queue->Push(std::vector(data, data + num_frames * impl->sample_size_in_bytes)); // returning less than num_frames here signals cubeb to stop sampling @@ -130,7 +131,7 @@ std::vector ListCubebInputDevices() { if (cubeb_enumerate_devices(ctx, CUBEB_DEVICE_TYPE_INPUT, &collection) != CUBEB_OK) { LOG_WARNING(Audio_Sink, "Audio input device enumeration not supported"); } else { - for (size_t i = 0; i < collection.count; i++) { + for (std::size_t i = 0; i < collection.count; i++) { const cubeb_device_info& device = collection.device[i]; if (device.state == CUBEB_DEVICE_STATE_ENABLED && device.friendly_name) { device_list.emplace_back(device.friendly_name); diff --git a/src/audio_core/cubeb_input.h b/src/audio_core/cubeb_input.h index 20f9c4cea..a38737849 100644 --- a/src/audio_core/cubeb_input.h +++ b/src/audio_core/cubeb_input.h @@ -15,7 +15,7 @@ public: CubebInput(); ~CubebInput() override; - void StartSampling(Frontend::Mic::Parameters params) override; + void StartSampling(const Frontend::Mic::Parameters& params) override; void StopSampling() override; diff --git a/src/citra/config.cpp b/src/citra/config.cpp index e6eea37cc..70f05b7b5 100644 --- a/src/citra/config.cpp +++ b/src/citra/config.cpp @@ -166,6 +166,10 @@ void Config::ReadValues() { sdl2_config->GetBoolean("Audio", "enable_audio_stretching", true); Settings::values.audio_device_id = sdl2_config->GetString("Audio", "output_device", "auto"); Settings::values.volume = sdl2_config->GetReal("Audio", "volume", 1); + Settings::values.mic_input_device = + sdl2_config->GetString("Audio", "mic_input_device", "Default"); + Settings::values.mic_input_type = + static_cast(sdl2_config->GetInteger("Audio", "mic_input_type", 0)); // Data Storage Settings::values.use_virtual_sd = diff --git a/src/citra_qt/configuration/config.cpp b/src/citra_qt/configuration/config.cpp index 29f61fae3..2f55a4e92 100644 --- a/src/citra_qt/configuration/config.cpp +++ b/src/citra_qt/configuration/config.cpp @@ -198,7 +198,8 @@ void Config::ReadValues() { Settings::values.audio_device_id = ReadSetting("output_device", "auto").toString().toStdString(); Settings::values.volume = ReadSetting("volume", 1).toFloat(); - Settings::values.mic_input_type = ReadSetting("mic_input_type", 0).toInt(); + Settings::values.mic_input_type = + static_cast(ReadSetting("mic_input_type", 0).toInt()); Settings::values.mic_input_device = ReadSetting("mic_input_device", "Default").toString().toStdString(); qt_config->endGroup(); @@ -483,8 +484,8 @@ void Config::SaveValues() { WriteSetting("enable_audio_stretching", Settings::values.enable_audio_stretching, true); WriteSetting("output_device", QString::fromStdString(Settings::values.audio_device_id), "auto"); WriteSetting("volume", Settings::values.volume, 1.0f); - WriteSetting("mic_input_device", QString::fromStdString(Settings::values.mic_input_device), 0); - WriteSetting("mic_input_type", Settings::values.mic_input_type, "Default"); + WriteSetting("mic_input_device", QString::fromStdString(Settings::values.mic_input_device), "Default"); + WriteSetting("mic_input_type", static_cast(Settings::values.mic_input_type), 0); qt_config->endGroup(); using namespace Service::CAM; diff --git a/src/citra_qt/configuration/configure_audio.cpp b/src/citra_qt/configuration/configure_audio.cpp index 1d9731cd3..e84c2f14d 100644 --- a/src/citra_qt/configuration/configure_audio.cpp +++ b/src/citra_qt/configuration/configure_audio.cpp @@ -3,7 +3,6 @@ // Refer to the license.txt file included. #include -#include #include #include "audio_core/cubeb_input.h" #include "audio_core/sink.h" @@ -37,14 +36,14 @@ ConfigureAudio::ConfigureAudio(QWidget* parent) ui->input_device_combo_box->addItem(QString::fromStdString(device)); } - connect(ui->input_type_combo_box, QOverload::of(&QComboBox::currentIndexChanged), this, + connect(ui->input_type_combo_box, qOverload(&QComboBox::currentIndexChanged), this, &ConfigureAudio::updateAudioInputDevices); ui->input_type_combo_box->setEnabled(!Core::System::GetInstance().IsPoweredOn()); ui->input_device_combo_box->setEnabled(!Core::System::GetInstance().IsPoweredOn()); this->setConfiguration(); - connect(ui->output_sink_combo_box, QOverload::of(&QComboBox::currentIndexChanged), this, + connect(ui->output_sink_combo_box, qOverload(&QComboBox::currentIndexChanged), this, &ConfigureAudio::updateAudioOutputDevices); } @@ -74,10 +73,11 @@ void ConfigureAudio::setConfiguration() { } ui->emulation_combo_box->setCurrentIndex(selection); - ui->input_type_combo_box->setCurrentIndex(Settings::values.mic_input_type); + int index = static_cast(Settings::values.mic_input_type); + ui->input_type_combo_box->setCurrentIndex(index); ui->input_device_combo_box->setCurrentText( QString::fromStdString(Settings::values.mic_input_device)); - updateAudioInputDevices(Settings::values.mic_input_type); + updateAudioInputDevices(index); } void ConfigureAudio::setOutputSinkFromSinkID() { @@ -124,7 +124,8 @@ void ConfigureAudio::applyConfiguration() { static_cast(ui->volume_slider->sliderPosition()) / ui->volume_slider->maximum(); Settings::values.enable_dsp_lle = ui->emulation_combo_box->currentIndex() != 0; Settings::values.enable_dsp_lle_multithread = ui->emulation_combo_box->currentIndex() == 2; - Settings::values.mic_input_type = ui->input_type_combo_box->currentIndex(); + Settings::values.mic_input_type = + static_cast(ui->input_type_combo_box->currentIndex()); Settings::values.mic_input_device = ui->input_device_combo_box->currentText().toStdString(); } diff --git a/src/core/frontend/mic.cpp b/src/core/frontend/mic.cpp index 5d880fcf7..84f090cb2 100644 --- a/src/core/frontend/mic.cpp +++ b/src/core/frontend/mic.cpp @@ -1,4 +1,4 @@ -// Copyright 2018 Citra Emulator Project +// Copyright 2019 Citra Emulator Project // Licensed under GPLv2 or any later version // Refer to the license.txt file included. @@ -12,39 +12,28 @@ constexpr std::array NOISE_SAMPLE_8_BIT = { 0xFC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF5, 0xFF, 0xFF, 0xFF, 0xFF, 0x8E, 0xFF, 0xF4, 0xE1, 0xBF, 0x9A, 0x71, 0x58, 0x5B, 0x5F, 0x62, 0xC2, 0x25, 0x05, 0x01, 0x01, 0x01, 0x01}; -constexpr std::array NOISE_SAMPLE_16_BIT = { +constexpr std::array NOISE_SAMPLE_16_BIT = { 0x64, 0x61, 0x74, 0x61, 0x56, 0xD7, 0x00, 0x00, 0x48, 0xF7, 0x86, 0x05, 0x77, 0x1A, 0xF4, 0x1F, - 0x28, 0x0F, 0x6B, 0xEB, 0x1C, 0xC0, 0xCB, 0x9D, 0x46, 0x90, 0xDF, 0x98, 0xEA, 0xAE, 0xB5, 0xC4, - 0x9D, 0xCE, 0xB6, 0xC9, 0xDF, 0xBD, 0x82, 0xBA, 0x83, 0xCD, 0x57, 0xF9, 0x96, 0x30, 0x2C, 0x5B, - 0x29, 0x64, 0xD3, 0x46, 0x0D, 0x12, 0x3E, 0xDE, 0x00, 0xBD, 0x74, 0xAE, 0xF0, 0xA4, 0x91, 0x93, - 0x02, 0x80, 0x00, 0x80, 0x03, 0x80, 0x6F, 0xAA, 0x8E, 0xE8, 0xEE, 0x1A, 0x2B, 0x2C, 0xC6, 0x18, - 0xF8, 0xED, 0xC2, 0xBE, 0x00, 0x99, 0xC1, 0x82, 0x00, 0x80, 0xA6, 0x8A, 0x37, 0xA8, 0x6B, 0xCE, - 0x20, 0xEF, 0xD0, 0xFD, 0x68, 0xF9, 0x50, 0xEF, 0x89, 0xF2, 0xDE, 0x0C, 0x24, 0x36, 0xDB, 0x58, - 0xB2, 0x61, 0xD5, 0x4C, 0x0B, 0x27, 0x6D, 0x02, 0xDC, 0xE8, 0x13, 0xD8, 0x2F, 0xC9, 0x07, 0xBC, - 0xAB, 0xBA, 0x70, 0xD1, 0xDE, 0x01, 0xF2, 0x3C, 0x64, 0x6A, 0xFF, 0x78, 0x47, 0x6B, 0x26, 0x56, - 0x9B, 0x51, 0xF3, 0x65, 0xFF, 0x7F, 0xFF, 0x7F, 0x88, 0x6B, 0x46, 0x24, 0xBF, 0xD8, 0x8C, 0xB4, - 0xD9, 0xCF, 0x77, 0x1C, 0x43, 0x6B, 0xFE, 0x7F, 0x15, 0x64, 0xA6, 0x13, 0x03, 0xCE, 0x51, 0xBF, - 0xC7, 0xEB, 0xCB, 0x2E, 0x6C, 0x58, 0xA7, 0x51, 0x40, 0x2A, 0x24, 0x06, 0x45, 0xFB, 0xD3, 0xFE, - 0x51, 0xF2, 0x1E, 0xC5, 0x79, 0x8A, 0x00, 0x80, 0x94, 0x8E, 0x7A, 0xDE, 0x83, 0x29, 0x8E, 0x3C, - 0x4B, 0x0F, 0xD8, 0xCB, 0x41, 0xAB, 0xC1, 0xC5, 0xC6, 0xFE, 0x0F, 0x1F, 0x92, 0x05, 0x4B, 0xC4, - 0xDC, 0x8F, 0xE1, 0x90, 0xE3, 0xC0, 0xDB, 0xF1, 0xCC, 0xF8, 0xC8, 0xD4, 0x2A, 0xAF, 0xB7, 0xB5, - 0x7F, 0xF0, 0xB2, 0x39, 0xD4, 0x5C, 0xD6, 0x41, 0x69, 0xFD, 0xEA, 0xBB, 0x57, 0x9B, 0x59, 0x98, - 0x8E, 0x9B, 0x8A, 0x97, 0x54, 0x98, 0xE6, 0xB5, 0x25, 0xF8, 0x77, 0x48, 0xFF, 0x7F, 0xFF, 0x7F, - 0x49, 0x6B, 0xB4, 0x4B, 0xE9, 0x45, 0xE3, 0x57, 0x60, 0x64, 0x8C, 0x4D, 0x69, 0x10, 0x10, 0xCA, - 0x13, 0xA4, 0xC5, 0xB7, 0xE4, 0xFD, 0x7C, 0x54, 0xFF, 0x7F, 0xFF, 0x7F, 0xFF, 0x7F, 0xE0, 0x52, - 0x5E, 0x22, 0x31, 0x0B, 0xB5, 0x12, 0xB1, 0x2E, 0xA7, 0x4D, 0x17, 0x61, 0x46, 0x65, 0xA5, 0x5F, - 0x5C, 0x57, 0xB6, 0x4C, 0x3B, 0x38, 0xFD, 0x11, 0x70, 0xDC, 0x2A, 0xA8, 0xB9, 0x8C, 0xEA, 0x98, - 0x07, 0xC6, 0xDF, 0xF7, 0x2D, 0x0C, 0xEC, 0xF0, 0xA8, 0xB2, 0x02, 0x80, 0x00, 0x80, 0xBA, 0x8A, - 0x0E, 0xCB, 0x54, 0xF7, 0x2B, 0xEE, 0x4C, 0xB9, 0x48, 0x89, 0x8F, 0x90, 0x0E, 0xD8, 0x83, 0x32, - 0xC5, 0x5C, 0x54, 0x34, 0x86, 0xD6, 0x78, 0x8C, 0x88, 0x90, 0x87, 0xDE, 0x75, 0x37, 0x55, 0x56, - 0xF1, 0x28, 0xF0, 0xDA, 0xE2, 0xAB, 0xE6, 0xB6, 0xD6, 0xDF, 0x4D, 0xF4, 0xCF, 0xDE, 0x3E, 0xBA, - 0xC6, 0xB3, 0x81, 0xDA, 0xFE, 0x0D, 0xE9, 0x1D, 0xCE, 0xFB, 0x59, 0xCD, 0x57, 0xCA, 0x77, 0x06, - 0x63, 0x5A, 0xFE, 0x7F, 0x49, 0x63, 0x7F, 0x14, 0x0E, 0xDB, 0x2A, 0xE5, 0x3B, 0x27, 0xFF, 0x69, - 0x0A, 0x7C, 0xC5, 0x56, 0x65, 0x19, 0xEC, 0xE5, 0x0E, 0xC6, 0xA6, 0xB0, 0x09, 0xA2, 0x06, 0xA8, - 0xC7, 0xD1, 0xE9, 0x15, 0xD5, 0x4E, 0xBB, 0x56, 0x85, 0x2A, 0x25, 0xF0, 0x78, 0xD6, 0x70, 0xEB, - 0xF2, 0x0F, 0xE1, 0x15, 0x66, 0xEC, 0xC7, 0xB0, 0xE7, 0x93, 0x9D, 0xAD, 0xD1, 0xE6, 0xD3, 0x0D, - 0xAC, 0x00, 0xB2, 0xC7, 0x5D, 0x8B, 0x00, 0x80, 0xA1, 0x88, 0x14, 0xBE, 0xDF, 0xFB, 0xCF, 0x32, - 0xD8, 0x5B, 0x0F, 0x6F, 0x6C, 0x62, 0xD9, 0x33, 0x76, 0xF3, 0xD6, 0xBF, 0x41, 0xB3, 0x5C, 0xD1}; + 0x28, 0x0F, 0x6B, 0xEB, 0x1C, 0xC0, 0xCB, 0x9D, 0x46, 0x90, 0xDF, 0x98, 0xEA, 0xAE, 0xB5, 0xC4}; + +Interface::~Interface() = default; + +void NullMic::StartSampling(const Parameters& params) { + parameters = params; + is_sampling = true; +} + +void NullMic::StopSampling() { + is_sampling = false; +} + +void NullMic::AdjustSampleRate(u32 sample_rate) { + parameters.sample_rate = sample_rate; +} + +Samples NullMic::Read() { + return {}; +} StaticMic::StaticMic() : CACHE_8_BIT{NOISE_SAMPLE_8_BIT.begin(), NOISE_SAMPLE_8_BIT.end()}, @@ -52,7 +41,7 @@ StaticMic::StaticMic() StaticMic::~StaticMic() = default; -void StaticMic::StartSampling(Parameters params) { +void StaticMic::StartSampling(const Parameters& params) { sample_rate = params.sample_rate; sample_size = params.sample_size; @@ -70,17 +59,4 @@ Samples StaticMic::Read() { return (sample_size == 8) ? CACHE_8_BIT : CACHE_16_BIT; } -static std::shared_ptr current_mic; - -void RegisterMic(std::shared_ptr mic) { - current_mic = mic; -} - -std::shared_ptr GetCurrentMic() { - if (!current_mic) { - current_mic = std::make_shared(); - } - return current_mic; -} - } // namespace Frontend::Mic diff --git a/src/core/frontend/mic.h b/src/core/frontend/mic.h index 13f79e4fa..296e434f6 100644 --- a/src/core/frontend/mic.h +++ b/src/core/frontend/mic.h @@ -1,4 +1,4 @@ -// Copyright 2018 Citra Emulator Project +// Copyright 2019 Citra Emulator Project // Licensed under GPLv2 or any later version // Refer to the license.txt file included. @@ -17,7 +17,6 @@ enum class Signedness : u8 { }; using Samples = std::vector; -using SampleQueue = Common::SPSCQueue; struct Parameters { Signedness sign; @@ -32,17 +31,19 @@ class Interface { public: Interface() = default; - virtual ~Interface() = default; + virtual ~Interface(); /// Starts the microphone. Called by Core - virtual void StartSampling(Parameters params) = 0; + virtual void StartSampling(const Parameters& params) = 0; /// Stops the microphone. Called by Core virtual void StopSampling() = 0; - /// Called from the actual event timing read back. The frontend impl is responsible for wrapping - /// up any data and returning them to the core so the core can write them to the sharedmem. If - /// theres nothing to return just return an empty vector + /** + * Called from the actual event timing at a constant period under a given sample rate. + * When sampling is enabled this function is expected to return a buffer of 16 samples in ideal + * conditions, but can be lax if the data is coming in from another source like a real mic. + */ virtual Samples Read() = 0; /// Adjusts the Parameters. Implementations should update the parameters field in addition to @@ -70,7 +71,7 @@ public: return is_sampling; } - Parameters GetParameters() const { + const Parameters& GetParameters() const { return parameters; } @@ -83,22 +84,13 @@ protected: class NullMic final : public Interface { public: - void StartSampling(Parameters params) override { - parameters = params; - is_sampling = true; - } + void StartSampling(const Parameters& params) override; - void StopSampling() override { - is_sampling = false; - } + void StopSampling() override; - void AdjustSampleRate(u32 sample_rate) override { - parameters.sample_rate = sample_rate; - } + void AdjustSampleRate(u32 sample_rate) override; - Samples Read() override { - return {}; - } + Samples Read() override; }; class StaticMic final : public Interface { @@ -106,7 +98,7 @@ public: StaticMic(); ~StaticMic() override; - void StartSampling(Parameters params) override; + void StartSampling(const Parameters& params) override; void StopSampling() override; void AdjustSampleRate(u32 sample_rate) override; diff --git a/src/core/hle/service/mic_u.cpp b/src/core/hle/service/mic_u.cpp index 577d7740f..0ac6a1340 100644 --- a/src/core/hle/service/mic_u.cpp +++ b/src/core/hle/service/mic_u.cpp @@ -23,7 +23,8 @@ enum class Encoding : u8 { PCM16Signed = 3, ///< Signed 16-bit PCM. }; -/// Microphone audio sampling rates. +/// Microphone audio sampling rates. The actual accurate sampling rate can be calculated using +/// (16756991 / 512) / (SampleRate + 1) where SampleRate is one of the above values. enum class SampleRate : u8 { Rate32730 = 0, ///< 32728.498 Hz Rate16360 = 1, ///< 16364.479 Hz @@ -34,13 +35,13 @@ enum class SampleRate : u8 { constexpr u32 GetSampleRateInHz(SampleRate sample_rate) { switch (sample_rate) { case SampleRate::Rate8180: - return 8180; + return 8182; case SampleRate::Rate10910: - return 10910; + return 10909; case SampleRate::Rate16360: - return 16360; + return 16364; case SampleRate::Rate32730: - return 32730; + return 32728; default: UNREACHABLE(); } @@ -54,45 +55,28 @@ constexpr u64 BufferUpdateRate16360 = BASE_CLOCK_RATE_ARM11 / 1022; constexpr u64 BufferUpdateRate32730 = BASE_CLOCK_RATE_ARM11 / 2045; constexpr u64 GetBufferUpdateRate(SampleRate sample_rate) { - switch (sample_rate) { - case SampleRate::Rate8180: - return BufferUpdateRate8180; - case SampleRate::Rate10910: - return BufferUpdateRate10910; - case SampleRate::Rate16360: - return BufferUpdateRate16360; - case SampleRate::Rate32730: - return BufferUpdateRate32730; - default: - UNREACHABLE(); - } + return GetSampleRateInHz(sample_rate) / 16; } // Variables holding the current mic buffer writing state struct State { u8* sharedmem_buffer = nullptr; u32 sharedmem_size = 0; - size_t size = 0; + std::size_t size = 0; u32 offset = 0; u32 initial_offset = 0; bool looped_buffer = false; u8 sample_size = 0; SampleRate sample_rate = SampleRate::Rate16360; - void UpdateOffset() { - // The last 4 bytes of the shared memory contains the latest offset - // so update that as well https://www.3dbrew.org/wiki/MIC_Shared_Memory - std::memcpy(sharedmem_buffer + (sharedmem_size - sizeof(u32)), - reinterpret_cast(&offset), sizeof(u32)); - } - void WriteSamples(const std::vector& samples) { u32 bytes_total_written = 0; - const size_t remaining_space = size - offset; - size_t bytes_to_write = std::min(samples.size(), remaining_space); + const std::size_t remaining_space = size - offset; + std::size_t bytes_to_write = std::min(samples.size(), remaining_space); // Write as many samples as we can to the buffer. - // TODO if the sample size is 16bit, this could theoretically cut a sample + // TODO if the sample size is 16bit, this could theoretically cut a sample in the case where + // the application configures an odd size std::memcpy(sharedmem_buffer + offset, samples.data(), bytes_to_write); offset += static_cast(bytes_to_write); bytes_total_written += static_cast(bytes_to_write); @@ -105,6 +89,12 @@ struct State { bytes_to_write); offset += static_cast(bytes_to_write); } + + // The last 4 bytes of the shared memory contains the latest offset + // so update that as well https://www.3dbrew.org/wiki/MIC_Shared_Memory + u32_le off = offset; + std::memcpy(sharedmem_buffer + (sharedmem_size - sizeof(u32)), reinterpret_cast(&off), + sizeof(u32)); } }; @@ -112,9 +102,10 @@ struct MIC_U::Impl { explicit Impl(Core::System& system) : timing(system.CoreTiming()) { buffer_full_event = system.Kernel().CreateEvent(Kernel::ResetType::OneShot, "MIC_U::buffer_full_event"); - buffer_write_event = timing.RegisterEvent( - "MIC_U::UpdateBuffer", std::bind(&Impl::UpdateSharedMemBuffer, this, - std::placeholders::_1, std::placeholders::_2)); + buffer_write_event = + timing.RegisterEvent("MIC_U::UpdateBuffer", [this](u64 userdata, s64 cycles_late) { + UpdateSharedMemBuffer(userdata, cycles_late); + }); } void MapSharedMem(Kernel::HLERequestContext& ctx) { @@ -131,7 +122,7 @@ struct MIC_U::Impl { IPC::RequestBuilder rb = rp.MakeBuilder(1, 0); rb.Push(RESULT_SUCCESS); - LOG_TRACE(Service_MIC, "MIC:U MapSharedMem called, size=0x{:X}", size); + LOG_TRACE(Service_MIC, "MapSharedMem called, size=0x{:X}", size); } void UnmapSharedMem(Kernel::HLERequestContext& ctx) { @@ -139,7 +130,7 @@ struct MIC_U::Impl { IPC::RequestBuilder rb = rp.MakeBuilder(1, 0); shared_memory = nullptr; rb.Push(RESULT_SUCCESS); - LOG_TRACE(Service_MIC, "MIC:U UnmapSharedMem called"); + LOG_TRACE(Service_MIC, "UnmapSharedMem called"); } void UpdateSharedMemBuffer(u64 userdata, s64 cycles_late) { @@ -152,8 +143,6 @@ struct MIC_U::Impl { if (!samples.empty()) { // write the samples to sharedmem page state.WriteSamples(samples); - // write the new offset to the last 4 bytes of the buffer - state.UpdateOffset(); } // schedule next run @@ -194,7 +183,7 @@ struct MIC_U::Impl { IPC::RequestBuilder rb = rp.MakeBuilder(1, 0); rb.Push(RESULT_SUCCESS); LOG_TRACE(Service_MIC, - "MIC:U StartSampling called, encoding={}, sample_rate={}, " + "StartSampling called, encoding={}, sample_rate={}, " "audio_buffer_offset={}, audio_buffer_size={}, audio_buffer_loop={}", static_cast(encoding), static_cast(sample_rate), audio_buffer_offset, audio_buffer_size, audio_buffer_loop); @@ -207,8 +196,7 @@ struct MIC_U::Impl { IPC::RequestBuilder rb = rp.MakeBuilder(1, 0); rb.Push(RESULT_SUCCESS); - LOG_TRACE(Service_MIC, "MIC:U AdjustSampling sample_rate={}", - static_cast(sample_rate)); + LOG_TRACE(Service_MIC, "AdjustSampling sample_rate={}", static_cast(sample_rate)); } void StopSampling(Kernel::HLERequestContext& ctx) { @@ -217,7 +205,8 @@ struct MIC_U::Impl { IPC::RequestBuilder rb = rp.MakeBuilder(1, 0); rb.Push(RESULT_SUCCESS); mic->StopSampling(); - LOG_TRACE(Service_MIC, "MIC:U StopSampling called"); + timing.RemoveEvent(buffer_write_event); + LOG_TRACE(Service_MIC, "StopSampling called"); } void IsSampling(Kernel::HLERequestContext& ctx) { @@ -227,7 +216,7 @@ struct MIC_U::Impl { rb.Push(RESULT_SUCCESS); bool is_sampling = mic->IsSampling(); rb.Push(is_sampling); - LOG_TRACE(Service_MIC, "MIC:U IsSampling: {}", is_sampling); + LOG_TRACE(Service_MIC, "IsSampling: {}", is_sampling); } void GetBufferFullEvent(Kernel::HLERequestContext& ctx) { @@ -246,7 +235,7 @@ struct MIC_U::Impl { IPC::RequestBuilder rb = rp.MakeBuilder(1, 0); rb.Push(RESULT_SUCCESS); - LOG_TRACE(Service_MIC, "MIC:U SetGain gain={}", gain); + LOG_TRACE(Service_MIC, "SetGain gain={}", gain); } void GetGain(Kernel::HLERequestContext& ctx) { @@ -256,7 +245,7 @@ struct MIC_U::Impl { rb.Push(RESULT_SUCCESS); u8 gain = mic->GetGain(); rb.Push(gain); - LOG_TRACE(Service_MIC, "MIC:U GetGain gain={}", gain); + LOG_TRACE(Service_MIC, "GetGain gain={}", gain); } void SetPower(Kernel::HLERequestContext& ctx) { @@ -266,7 +255,7 @@ struct MIC_U::Impl { IPC::RequestBuilder rb = rp.MakeBuilder(1, 0); rb.Push(RESULT_SUCCESS); - LOG_TRACE(Service_MIC, "MIC:U SetPower mic_power={}", power); + LOG_TRACE(Service_MIC, "SetPower mic_power={}", power); } void GetPower(Kernel::HLERequestContext& ctx) { @@ -276,7 +265,7 @@ struct MIC_U::Impl { rb.Push(RESULT_SUCCESS); bool mic_power = mic->GetPower(); rb.Push(mic_power); - LOG_TRACE(Service_MIC, "MIC:U GetPower called"); + LOG_TRACE(Service_MIC, "GetPower called"); } void SetIirFilterMic(Kernel::HLERequestContext& ctx) { @@ -437,3 +426,19 @@ void InstallInterfaces(Core::System& system) { } } // namespace Service::MIC + +namespace Frontend::Mic { +static std::shared_ptr current_mic; + +void RegisterMic(std::shared_ptr mic) { + current_mic = mic; +} + +std::shared_ptr GetCurrentMic() { + if (!current_mic) { + current_mic = std::make_shared(); + } + return current_mic; +} + +} // namespace Frontend::Mic diff --git a/src/core/hle/service/mic_u.h b/src/core/hle/service/mic_u.h index bdd94fdd9..bc4933229 100644 --- a/src/core/hle/service/mic_u.h +++ b/src/core/hle/service/mic_u.h @@ -192,6 +192,4 @@ private: void InstallInterfaces(Core::System& system); -void ChangeMicImpl(); - } // namespace Service::MIC diff --git a/src/core/settings.cpp b/src/core/settings.cpp index cd810f2db..39a56e567 100644 --- a/src/core/settings.cpp +++ b/src/core/settings.cpp @@ -62,13 +62,13 @@ void Apply() { } // TODO support mic hotswapping by creating the new impl, and copying any parameters to it. switch (Settings::values.mic_input_type) { - case 0: + case Settings::MicInputType::None: Frontend::Mic::RegisterMic(std::make_shared()); break; - case 1: + case Settings::MicInputType::Real: Frontend::Mic::RegisterMic(std::make_shared()); break; - case 2: + case Settings::MicInputType::Static: Frontend::Mic::RegisterMic(std::make_shared()); break; } diff --git a/src/core/settings.h b/src/core/settings.h index 702dd4d21..ef5e48410 100644 --- a/src/core/settings.h +++ b/src/core/settings.h @@ -26,6 +26,12 @@ enum class LayoutOption { SideScreen, }; +enum class MicInputType { + None, + Real, + Static, +}; + namespace NativeButton { enum Values { A, @@ -167,7 +173,7 @@ struct Values { bool enable_audio_stretching; std::string audio_device_id; float volume; - u8 mic_input_type; + MicInputType mic_input_type; std::string mic_input_device; // Camera