From c2ea8c4eabbd63282ae12be94a26add9bb1ba609 Mon Sep 17 00:00:00 2001 From: Florin9doi Date: Fri, 16 Aug 2024 23:09:00 +0300 Subject: [PATCH] USB: Audio support for EyeToy --- pcsx2/USB/usb-eyetoy/usb-eyetoy-webcam.cpp | 66 +++++++++++++++++----- pcsx2/USB/usb-mic/usb-mic.cpp | 44 +++++++-------- pcsx2/USB/usb-mic/usb-mic.h | 2 +- pcsx2/USB/usb-pad/usb-seamic.cpp | 2 +- 4 files changed, 74 insertions(+), 40 deletions(-) diff --git a/pcsx2/USB/usb-eyetoy/usb-eyetoy-webcam.cpp b/pcsx2/USB/usb-eyetoy/usb-eyetoy-webcam.cpp index 75054b01dc..61c03c1744 100644 --- a/pcsx2/USB/usb-eyetoy/usb-eyetoy-webcam.cpp +++ b/pcsx2/USB/usb-eyetoy/usb-eyetoy-webcam.cpp @@ -6,6 +6,8 @@ #include "usb-eyetoy-webcam.h" #include "ov519.h" #include "USB/qemu-usb/desc.h" +#include "USB/usb-mic/audio.h" +#include "USB/usb-mic/usb-mic.h" #include "USB/USB.h" #include "StateWrapper.h" @@ -23,7 +25,7 @@ namespace usb_eyetoy u32 subtype; std::unique_ptr videodev; - // struct freeze { + USBDevice* mic; uint8_t regs[0xFF]; //OV519 uint8_t i2c_regs[0xFF]; //OV764x @@ -32,7 +34,6 @@ namespace usb_eyetoy std::unique_ptr mpeg_frame_data; unsigned int mpeg_frame_size; unsigned int mpeg_frame_offset; - // } f; } EYETOYState; static const USBDescStrings desc_strings = { @@ -103,8 +104,11 @@ namespace usb_eyetoy static void eyetoy_handle_reset(USBDevice* dev) { - reset_controller(USB_CONTAINER_OF(dev, EYETOYState, dev)); - reset_sensor(USB_CONTAINER_OF(dev, EYETOYState, dev)); + EYETOYState* s = USB_CONTAINER_OF(dev, EYETOYState, dev); + reset_controller(s); + reset_sensor(s); + if (s->mic) + s->mic->klass.handle_reset(s->mic); } static void webcam_handle_control_eyetoy(USBDevice* dev, USBPacket* p, int request, int value, int index, int length, uint8_t* data) @@ -328,10 +332,8 @@ namespace usb_eyetoy } else if (devep == 2) { - // get audio - //Console.Warning("get audio %d\n", len); - memset(data, 0, std::min(p->buffer_size, max_ep_size)); - usb_packet_copy(p, data, std::min(p->buffer_size, max_ep_size)); + if (s->mic) + s->mic->klass.handle_data(s->mic, p); } break; case USB_TOKEN_OUT: @@ -408,11 +410,18 @@ namespace usb_eyetoy { EYETOYState* s = USB_CONTAINER_OF(dev, EYETOYState, dev); close_camera(s); + if (s->mic) + s->mic->klass.unrealize(s->mic); delete s; } USBDevice* EyeToyWebCamDevice::CreateDevice(SettingsInterface& si, u32 port, u32 subtype) const { + const usb_mic::MicrophoneDevice* mic_proxy = + static_cast(RegisterDevice::instance().Device(DEVTYPE_MICROPHONE)); + if (!mic_proxy) + return nullptr; + std::unique_ptr videodev(VideoDevice::CreateInstance()); if (!videodev) { @@ -435,6 +444,8 @@ namespace usb_eyetoy goto fail; s->dev.klass.handle_control = webcam_handle_control_eyetoy; s->dev.klass.handle_data = webcam_handle_data_eyetoy; + + s->mic = mic_proxy->CreateDevice(si, port, 0, false, 16000, TypeName()); } else if (subtype == TYPE_OV511P) { @@ -503,17 +514,42 @@ namespace usb_eyetoy std::span EyeToyWebCamDevice::SubTypes() const { static const char* subtypes[] = { - TRANSLATE_NOOP("USB", "Sony EyeToy"), TRANSLATE_NOOP("USB", "Konami Capture Eye")}; + TRANSLATE_NOOP("USB", "Sony EyeToy"), + TRANSLATE_NOOP("USB", "Konami Capture Eye") + }; return subtypes; } std::span EyeToyWebCamDevice::Settings(u32 subtype) const { - static constexpr const SettingInfo info[] = { - {SettingInfo::Type::StringList, "device_name", TRANSLATE_NOOP("USB", "Device Name"), - TRANSLATE_NOOP("USB", "Selects the device to capture images from."), "", nullptr, nullptr, nullptr, - nullptr, nullptr, &VideoDevice::GetDeviceList}, - }; - return info; + switch (subtype) + { + case TYPE_EYETOY: + { + static constexpr const SettingInfo info[] = { + {SettingInfo::Type::StringList, "device_name", TRANSLATE_NOOP("USB", "Video Device"), + TRANSLATE_NOOP("USB", "Selects the device to capture images from."), "", nullptr, nullptr, nullptr, + nullptr, nullptr, &VideoDevice::GetDeviceList}, + {SettingInfo::Type::StringList, "input_device_name", TRANSLATE_NOOP("USB", "Audio Device"), + TRANSLATE_NOOP("USB", "Selects the device to read audio from."), "", nullptr, nullptr, nullptr, nullptr, + nullptr, &AudioDevice::GetInputDeviceList}, + {SettingInfo::Type::Integer, "input_latency", TRANSLATE_NOOP("USB", "Audio Latency"), + TRANSLATE_NOOP("USB", "Specifies the latency to the host input device."), + AudioDevice::DEFAULT_LATENCY_STR, "1", "1000", "1", TRANSLATE_NOOP("USB", "%dms"), nullptr, nullptr, 1.0f}, + }; + return info; + } + case TYPE_OV511P: + { + static constexpr const SettingInfo info[] = { + {SettingInfo::Type::StringList, "device_name", TRANSLATE_NOOP("USB", "Video Device"), + TRANSLATE_NOOP("USB", "Selects the device to capture images from."), "", nullptr, nullptr, nullptr, + nullptr, nullptr, &VideoDevice::GetDeviceList}, + }; + return info; + } + default: + return {}; + } } } // namespace usb_eyetoy diff --git a/pcsx2/USB/usb-mic/usb-mic.cpp b/pcsx2/USB/usb-mic/usb-mic.cpp index fbdf1ddffc..b4dafe630d 100644 --- a/pcsx2/USB/usb-mic/usb-mic.cpp +++ b/pcsx2/USB/usb-mic/usb-mic.cpp @@ -55,13 +55,13 @@ namespace usb_mic { /* - * A USB audio device supports an arbitrary number of alternate - * interface settings for each interface. Each corresponds to a block - * diagram of parameterized blocks. This can thus refer to things like - * number of channels, data rates, or in fact completely different - * block diagrams. Alternative setting 0 is always the null block diagram, - * which is used by a disabled device. - */ + * A USB audio device supports an arbitrary number of alternate + * interface settings for each interface. Each corresponds to a block + * diagram of parameterized blocks. This can thus refer to things like + * number of channels, data rates, or in fact completely different + * block diagrams. Alternative setting 0 is always the null block diagram, + * which is used by a disabled device. + */ enum usb_audio_altset : int8_t { ALTSET_OFF = 0x00, /* No endpoint */ @@ -200,7 +200,7 @@ namespace usb_mic AUDIO_PROTOCOL_UNDEFINED, /* bInterfaceProtocol */ 0x00, /* iInterface */ - /* Interface 1, Alternate Setting 1, Audio Streaming - Operational */ + /* Interface 1, Alternate Setting 1, Audio Streaming - 1 channel */ USB_INTERFACE_DESC_SIZE, /* bLength */ USB_INTERFACE_DESCRIPTOR_TYPE, /* bDescriptorType */ 0x01, /* bInterfaceNumber */ @@ -252,7 +252,7 @@ namespace usb_mic 0x00, /* bLockDelayUnits */ WBVAL(0x0000), /* wLockDelay */ - /* Interface 1, Alternate Setting 2, Audio Streaming - ? */ + /* Interface 1, Alternate Setting 2, Audio Streaming - 2 channels */ USB_INTERFACE_DESC_SIZE, /* bLength */ USB_INTERFACE_DESCRIPTOR_TYPE, /* bDescriptorType */ 0x01, /* bInterfaceNumber */ @@ -402,7 +402,7 @@ namespace usb_mic AUDIO_PROTOCOL_UNDEFINED, /* bInterfaceProtocol */ 0x00, /* iInterface */ - /* Interface 1, Alternate Setting 1, Audio Streaming - Operational */ + /* Interface 1, Alternate Setting 1, Audio Streaming - 1 channel */ USB_INTERFACE_DESC_SIZE, /* bLength */ USB_INTERFACE_DESCRIPTOR_TYPE, /* bDescriptorType */ 0x01, /* bInterfaceNumber */ @@ -454,7 +454,7 @@ namespace usb_mic 0x00, /* bLockDelayUnits */ WBVAL(0x0000), /* wLockDelay */ - /* Interface 1, Alternate Setting 2, Audio Streaming - ? */ + /* Interface 1, Alternate Setting 2, Audio Streaming - 2 channels */ USB_INTERFACE_DESC_SIZE, /* bLength */ USB_INTERFACE_DESCRIPTOR_TYPE, /* bDescriptorType */ 0x01, /* bInterfaceNumber */ @@ -627,7 +627,7 @@ namespace usb_mic Console.Warning("singstar: ep control cs %x, cn %X, %X %X data:", cs, cn, attrib, ep); /*for(int i=0; iep->nr; switch (p->pid) { case USB_TOKEN_IN: //Console.Warning("token in ep: %d len: %zd\n", devep, p->iov.size); - if (devep == 1) { - //TODO - int outChns = s->f.intf == 1 ? 1 : 2; + int outChns = s->f.intf == 2 ? 2 : 1; uint32_t frames, out_frames[2] = {0}, chn; int16_t *src1, *src2; int16_t* dst = (int16_t*)p->buffer_ptr; size_t len = p->buffer_size; // send only 1ms (bInterval) of samples - if (s->f.srate[0] == 48000 || s->f.srate[0] == 8000) + if (s->f.srate[0] == 48000 || s->f.srate[0] == 8000 || s->f.srate[0] == 16000) len = std::min(p->buffer_size, outChns * sizeof(int16_t) * s->f.srate[0] / 1000); //Divide 'len' bytes between 2 channels of 16 bits @@ -912,10 +909,10 @@ namespace usb_mic return nullptr; static const bool dual_mic = subtype == MIC_SINGSTAR; - return CreateDevice(si, port, subtype, dual_mic, MicrophoneDevice::TypeName()); + return CreateDevice(si, port, subtype, dual_mic, 48000, MicrophoneDevice::TypeName()); } - USBDevice* MicrophoneDevice::CreateDevice(SettingsInterface& si, u32 port, u32 subtype, bool dual_mic, const char* devtype) const + USBDevice* MicrophoneDevice::CreateDevice(SettingsInterface& si, u32 port, u32 subtype, bool dual_mic, const int samplerate, const char* devtype) const { if (subtype >= MIC_COUNT) return nullptr; @@ -985,6 +982,7 @@ namespace usb_mic Host::OSD_ERROR_DURATION); goto fail; } + s->audsrc[i]->SetResampling(samplerate); } } @@ -1020,8 +1018,8 @@ namespace usb_mic // set defaults s->f.vol[0] = 240; /* 0 dB */ s->f.vol[1] = 240; /* 0 dB */ - s->f.srate[0] = 48000; - s->f.srate[1] = 48000; + s->f.srate[0] = samplerate; + s->f.srate[1] = samplerate; usb_desc_init(&s->dev); usb_ep_init(&s->dev); diff --git a/pcsx2/USB/usb-mic/usb-mic.h b/pcsx2/USB/usb-mic/usb-mic.h index b1e86302af..89cc9fd68b 100644 --- a/pcsx2/USB/usb-mic/usb-mic.h +++ b/pcsx2/USB/usb-mic/usb-mic.h @@ -17,7 +17,7 @@ namespace usb_mic class MicrophoneDevice : public DeviceProxy { public: - USBDevice* CreateDevice(SettingsInterface& si, u32 port, u32 subtype, bool dual_mic, const char* devtype) const; + USBDevice* CreateDevice(SettingsInterface& si, u32 port, u32 subtype, bool dual_mic, const int samplerate, const char* devtype) const; USBDevice* CreateDevice(SettingsInterface& si, u32 port, u32 subtype) const override; const char* Name() const override; const char* TypeName() const override; diff --git a/pcsx2/USB/usb-pad/usb-seamic.cpp b/pcsx2/USB/usb-pad/usb-seamic.cpp index c864918d2f..b8c1d3270c 100644 --- a/pcsx2/USB/usb-pad/usb-seamic.cpp +++ b/pcsx2/USB/usb-pad/usb-seamic.cpp @@ -393,7 +393,7 @@ namespace usb_pad if (!mic_proxy) return nullptr; - USBDevice* mic = mic_proxy->CreateDevice(si, port, 0, false, TypeName()); + USBDevice* mic = mic_proxy->CreateDevice(si, port, 0, false, 48000, TypeName()); if (!mic) return nullptr;