Properly handle Partner CTR audio

This commit is contained in:
Lorenzooone 2026-01-12 12:54:51 +01:00
parent 2197dbb9ca
commit 3dc7b032a8
7 changed files with 53 additions and 4 deletions

View File

@ -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<std::chrono::high_resolution_clock> clock_time_start;
std::chrono::time_point<std::chrono::high_resolution_clock> inside_clock_time_start;
AudioSampleRate current_sample_rate = SAMPLE_RATE_INVALID;
bool onGetData(sf::SoundStream::Chunk &data) override;
void onSeek(sf::Time timeOffset) override;

View File

@ -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;

View File

@ -5,6 +5,7 @@
#include "hw_defs.hpp"
#include <mutex>
#include <string>
#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 {

View File

@ -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

View File

@ -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;
}

View File

@ -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();

View File

@ -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) {