From 3dc7b032a861e998b5c37a6cc30790ba038e737c Mon Sep 17 00:00:00 2001 From: Lorenzooone Date: Mon, 12 Jan 2026 12:54:51 +0100 Subject: [PATCH] Properly handle Partner CTR audio --- include/audio.hpp | 3 ++ include/audio_data.hpp | 1 + include/capture_structs.hpp | 2 + include/hw_defs.hpp | 6 ++- .../cypress_partner_ctr_acquisition.cpp | 1 + source/audio.cpp | 38 ++++++++++++++++++- source/cc3dsfs.cpp | 6 +++ 7 files changed, 53 insertions(+), 4 deletions(-) diff --git a/include/audio.hpp b/include/audio.hpp index 7a7a3c9..999e55b 100755 --- a/include/audio.hpp +++ b/include/audio.hpp @@ -25,6 +25,8 @@ public: void update_volume(); void start_audio(); void stop_audio(); + AudioSampleRate get_current_sample_rate(); + void change_sample_rate(AudioSampleRate target); bool hasTooMuchTimeElapsed(); private: @@ -36,6 +38,7 @@ private: std::int16_t *buffer; std::chrono::time_point clock_time_start; std::chrono::time_point inside_clock_time_start; + AudioSampleRate current_sample_rate = SAMPLE_RATE_INVALID; bool onGetData(sf::SoundStream::Chunk &data) override; void onSeek(sf::Time timeOffset) override; diff --git a/include/audio_data.hpp b/include/audio_data.hpp index 2ada0b2..5e0eb68 100755 --- a/include/audio_data.hpp +++ b/include/audio_data.hpp @@ -7,6 +7,7 @@ enum AudioOutputType {AUDIO_OUTPUT_STEREO, AUDIO_OUTPUT_MONO, AUDIO_OUTPUT_END}; enum AudioMode {AUDIO_MODE_LOW_LATENCY, AUDIO_MODE_STABLE, AUDIO_MODE_END}; +enum AudioSampleRate { SAMPLE_RATE_DS, SAMPLE_RATE_48K, SAMPLE_RATE_44_1K, SAMPLE_RATE_32K, SAMPLE_RATE_32768, SAMPLE_RATE_INVALID }; struct audio_output_device_data { bool preference_requested = false; diff --git a/include/capture_structs.hpp b/include/capture_structs.hpp index 70718f6..e07d840 100755 --- a/include/capture_structs.hpp +++ b/include/capture_structs.hpp @@ -5,6 +5,7 @@ #include "hw_defs.hpp" #include #include +#include "audio_data.hpp" // It may happen that a frame is lost. // This value prevents showing a black frame for that. @@ -350,6 +351,7 @@ struct CaptureDevice { bool is_horizontally_flipped = false; bool is_vertically_flipped = false; bool continuous_3d_screens = true; + AudioSampleRate sample_rate = SAMPLE_RATE_DS; }; struct CaptureStatus { diff --git a/include/hw_defs.hpp b/include/hw_defs.hpp index 19ba4be..a6e8575 100755 --- a/include/hw_defs.hpp +++ b/include/hw_defs.hpp @@ -2,8 +2,10 @@ #define __HW_DEFS_HPP #define AUDIO_CHANNELS 2 -#define SAMPLE_RATE_BASE 67027964 -#define SAMPLE_RATE_DIVISOR 2048 +#define SAMPLE_RATE_DS_BASE 67027964 +#define SAMPLE_RATE_DS_DIVISOR 2048 + +#define SAMPLE_RATE_COMMON_48K 48000 #define TOP_WIDTH_3DS 400 #define BOT_WIDTH_3DS 320 diff --git a/source/CaptureDeviceSpecific/Partner_CTR/cypress_partner_ctr_acquisition.cpp b/source/CaptureDeviceSpecific/Partner_CTR/cypress_partner_ctr_acquisition.cpp index 079da2b..bd8e459 100644 --- a/source/CaptureDeviceSpecific/Partner_CTR/cypress_partner_ctr_acquisition.cpp +++ b/source/CaptureDeviceSpecific/Partner_CTR/cypress_partner_ctr_acquisition.cpp @@ -92,6 +92,7 @@ static CaptureDevice _cypress_partner_ctr_create_device(const cypart_device_usb_ CaptureDevice out_device = CaptureDevice(serial, usb_device_desc->name, usb_device_desc->long_name, CAPTURE_CONN_PARTNER_CTR, (void*)usb_device_desc, true, true, true, TOP_WIDTH_3DS, HEIGHT_3DS * 2, TOP_WIDTH_3DS, HEIGHT_3DS * 3, N3DSXL_SAMPLES_IN, 180, 0, HEIGHT_3DS, 0, 2 * HEIGHT_3DS, 0, 0, false, usb_device_desc->video_data_type, 0x200, path); out_device.is_horizontally_flipped = true; out_device.continuous_3d_screens = false; + out_device.sample_rate = SAMPLE_RATE_48K; return out_device; } diff --git a/source/audio.cpp b/source/audio.cpp index 42cbb15..71bea2f 100755 --- a/source/audio.cpp +++ b/source/audio.cpp @@ -24,9 +24,8 @@ Audio::Audio(AudioData *audio_data) { this->audio_data = audio_data; // Consume old events this->buffer = new std::int16_t[MAX_SAMPLES_IN * (MAX_MAX_AUDIO_LATENCY + 1)]; + this->change_sample_rate(SAMPLE_RATE_DS); this->audio_data->check_audio_restart_request(); - sf::SoundStream::initialize(AUDIO_CHANNELS, SAMPLE_RATE_BASE, {sf::SoundChannel::FrontLeft, sf::SoundChannel::FrontRight}); - this->setPitch(1.0 / SAMPLE_RATE_DIVISOR); start_audio(); setVolume(0); this->final_volume = 0; @@ -35,6 +34,41 @@ Audio::Audio(AudioData *audio_data) { Audio::~Audio() { delete []this->buffer; } + +AudioSampleRate Audio::get_current_sample_rate() { + return this->current_sample_rate; +} + +void Audio::change_sample_rate(AudioSampleRate target) { + if(target == this->current_sample_rate) + return; + + switch(target) { + case SAMPLE_RATE_DS: + sf::SoundStream::initialize(AUDIO_CHANNELS, SAMPLE_RATE_DS_BASE, {sf::SoundChannel::FrontLeft, sf::SoundChannel::FrontRight}); + this->setPitch(1.0 / SAMPLE_RATE_DS_DIVISOR); + break; + case SAMPLE_RATE_48K: + sf::SoundStream::initialize(AUDIO_CHANNELS, 48000, {sf::SoundChannel::FrontLeft, sf::SoundChannel::FrontRight}); + this->setPitch(1.0); + break; + case SAMPLE_RATE_44_1K: + sf::SoundStream::initialize(AUDIO_CHANNELS, 44100, {sf::SoundChannel::FrontLeft, sf::SoundChannel::FrontRight}); + this->setPitch(1.0); + break; + case SAMPLE_RATE_32K: + sf::SoundStream::initialize(AUDIO_CHANNELS, 32000, {sf::SoundChannel::FrontLeft, sf::SoundChannel::FrontRight}); + this->setPitch(1.0); + break; + case SAMPLE_RATE_32768: + sf::SoundStream::initialize(AUDIO_CHANNELS, 32768, {sf::SoundChannel::FrontLeft, sf::SoundChannel::FrontRight}); + this->setPitch(1.0); + break; + default: + break; + } + this->current_sample_rate = target; +} void Audio::update_volume() { int new_final_volume = this->audio_data->get_final_volume(); diff --git a/source/cc3dsfs.cpp b/source/cc3dsfs.cpp index f59bc46..7df320a 100755 --- a/source/cc3dsfs.cpp +++ b/source/cc3dsfs.cpp @@ -455,6 +455,12 @@ static void soundCall(AudioData *audio_data, CaptureData* capture_data, volatile while(capture_data->status.running) { if(capture_data->status.connected && capture_data->status.device.has_audio && (*can_do_output)) { + if(audio.get_current_sample_rate() != capture_data->status.device.sample_rate) { + audio.stop_audio(); + audio.stop(); + audio.change_sample_rate(capture_data->status.device.sample_rate); + } + bool timed_out = !capture_data->status.audio_wait.timed_lock(); if(!capture_data->status.cooldown_curr_in) {