From 2e18b57da09f0fe06623a43564fd64cabe76c140 Mon Sep 17 00:00:00 2001 From: Patrik Nilsson <113925545+pnn64@users.noreply.github.com> Date: Thu, 29 May 2025 01:25:26 +0200 Subject: [PATCH] Implement configurable Sample Rate in options Key changes: - Added "Sample Rate" to `ScreenOptionsGraphicsSound` with choices: - "Default" (resolves to 44100 Hz for now) - "44100 Hz" - "48000 Hz" - Created a new ConfOption "PreferredSampleRate" in `ScreenOptionsMasterPrefs.cpp` mapping UI choices to the integer values (0, 44100, 48000) for the existing `m_iSoundPreferredSampleRate` preference. - Updated relevant sound drivers: - DirectSound (RageSoundDriver_DSound_Software): Primary buffer now attempts to use the preferred rate. Secondary buffers already handled it correctly. - WaveOut (RageSoundDriver_WaveOut): Already handled 0 as 44.1kHz correctly. - PulseAudio (RageSoundDriver_PulseAudio): Ensured m_InitStream uses the constructor-initialized rate based on preference. - AudioUnit (RageSoundDriver_AU): Already handled 0 as 44.1kHz and attempts to set hardware rate. - OSS (RageSoundDriver_OSS): Updated to read and apply the preferred sample rate. - WDMKS (RageSoundDriver_WDMKS): Updated to pass the resolved preferred rate to its stream opening logic. - Null (RageSoundDriver_Null): Already handled 0 as 44.1kHz correctly. - Updated `RageSoundReader_Chain` constructor to use the preferred system sample rate for its internal default. - Added English localization for the new option title and explanation. The implementation ensures that if the preference is 0 (Default), the system currently defaults to 44100 Hz across all drivers. This lays the groundwork for future dynamic hardware rate detection. A game restart is recommended for the new sample rate to take full effect. --- Themes/_fallback/Languages/en.ini | 2 + Themes/_fallback/metrics.ini | 11 ++-- src/RageSound.cpp | 2 +- src/RageSoundManager.cpp | 4 +- src/RageSoundReader_Chain.cpp | 5 +- src/ScreenOptionsMasterPrefs.cpp | 8 +++ src/arch/Sound/ALSA9Helpers.cpp | 4 +- src/arch/Sound/DSoundHelpers.cpp | 15 +++-- src/arch/Sound/RageSoundDriver.h | 2 +- src/arch/Sound/RageSoundDriver_AU.mm | 2 +- .../Sound/RageSoundDriver_DSound_Software.cpp | 3 +- src/arch/Sound/RageSoundDriver_Null.cpp | 2 +- src/arch/Sound/RageSoundDriver_OSS.cpp | 43 +++++++++------ src/arch/Sound/RageSoundDriver_PulseAudio.cpp | 55 +++++++++++-------- src/arch/Sound/RageSoundDriver_WaveOut.cpp | 2 +- 15 files changed, 99 insertions(+), 61 deletions(-) diff --git a/Themes/_fallback/Languages/en.ini b/Themes/_fallback/Languages/en.ini index dca0e1283f..94ac14daef 100644 --- a/Themes/_fallback/Languages/en.ini +++ b/Themes/_fallback/Languages/en.ini @@ -465,6 +465,7 @@ Persp=Tilt Player1Profile= Player2Profile= PlayerAutoPlay=PlayerAutoPlay +PreferredSampleRate=Set the audio output rate. DEFAULT currently uses 44100 Hz. Matching the system native rate may help prevent sync issues and drift. A restart is required for changes to take full effect. PreloadSounds=If YES, preload most sounds in advance. This increases load times, and should normally be left OFF. Premium=Choose from various premium options. (Coin Mode = Pay) Profile= @@ -1203,6 +1204,7 @@ Player1Profile=Player1 Profile Player2Profile=Player2 Profile PlayerAutoPlay=AutoPlay Predicted Meter=Predicted Meter +PreferredSampleRate=Sample Rate Preferences=Preferences PreloadSounds=Preload Sounds Premium=Premium diff --git a/Themes/_fallback/metrics.ini b/Themes/_fallback/metrics.ini index 8753fc7ff9..57406951d3 100644 --- a/Themes/_fallback/metrics.ini +++ b/Themes/_fallback/metrics.ini @@ -3110,11 +3110,12 @@ Line14="conf,ShowStats" Line15="conf,ShowBanners" Line16="conf,AttractSoundFrequency" Line17="conf,SoundVolume" -Line18="conf,EnableAttackSounds" -Line19="conf,EnableMineHitSound" -Line20="conf,VisualDelaySeconds" -Line21="conf,DefaultSyncOffset" -Line22="conf,RateModPreservesPitch", +Line18="conf,PreferredSampleRate" +Line19="conf,EnableAttackSounds" +Line20="conf,EnableMineHitSound" +Line21="conf,VisualDelaySeconds" +Line22="conf,DefaultSyncOffset" +Line23="conf,RateModPreservesPitch", [ScreenOptionsAdvanced] Fallback="ScreenOptionsServiceChild" diff --git a/src/RageSound.cpp b/src/RageSound.cpp index c5d887a9f7..3836980000 100644 --- a/src/RageSound.cpp +++ b/src/RageSound.cpp @@ -147,7 +147,7 @@ public: int SetPosition( int iFrame ) { return 1; } int Read( float *pBuf, int iFrames ) { return RageSoundReader::END_OF_FILE; } RageSoundReader *Copy() const { return new RageSoundReader_Silence; } - int GetSampleRate() const { return 48000; } + int GetSampleRate() const { return 44100; } // Hardcoded to 44100 unsigned GetNumChannels() const { return 1; } int GetNextSourceFrame() const { return 0; } float GetStreamToSourceRatio() const { return 1.0f; } diff --git a/src/RageSoundManager.cpp b/src/RageSoundManager.cpp index 331c644994..af373c5a6b 100644 --- a/src/RageSoundManager.cpp +++ b/src/RageSoundManager.cpp @@ -133,9 +133,9 @@ float RageSoundManager::GetPlayLatency() const int RageSoundManager::GetDriverSampleRate() const { if( m_pDriver == nullptr ) - return 48000; + return 44100; // Fallback if no driver is loaded - return m_pDriver->GetSampleRate(); + return m_pDriver->GetSampleRate(); // Returns the *actual* operating rate of the loaded driver } /* If the given path is loaded, return a copy; otherwise return nullptr. diff --git a/src/RageSoundReader_Chain.cpp b/src/RageSoundReader_Chain.cpp index cbbca4134b..3020eee663 100644 --- a/src/RageSoundReader_Chain.cpp +++ b/src/RageSoundReader_Chain.cpp @@ -23,7 +23,10 @@ */ RageSoundReader_Chain::RageSoundReader_Chain() { - m_iPreferredSampleRate = 48000; + m_iPreferredSampleRate = PREFSMAN->m_iSoundPreferredSampleRate; + if (m_iPreferredSampleRate == 0) + m_iPreferredSampleRate = 44100; // Default if system default (0) is chosen + m_iActualSampleRate = -1; m_iChannels = 0; m_iCurrentFrame = 0; diff --git a/src/ScreenOptionsMasterPrefs.cpp b/src/ScreenOptionsMasterPrefs.cpp index 382ef7c133..c83ba3628b 100644 --- a/src/ScreenOptionsMasterPrefs.cpp +++ b/src/ScreenOptionsMasterPrefs.cpp @@ -695,6 +695,12 @@ static void SoundVolumeAttract( int &sel, bool ToSel, const ConfOption *pConfOpt MoveMap( sel, pConfOption, ToSel, mapping, ARRAYLEN(mapping) ); } +static void PreferredSampleRate( int &sel, bool ToSel, const ConfOption *pConfOption ) +{ + const int mapping[] = { 0, 44100, 48000 }; + MoveMap( sel, pConfOption, ToSel, mapping, ARRAYLEN(mapping) ); +} + static void VisualDelaySeconds( int &sel, bool ToSel, const ConfOption *pConfOption ) { const float mapping[] = { -0.125f,-0.1f,-0.075f,-0.05f,-0.025f,0.0f,0.025f,0.05f,0.075f,0.1f,0.125f }; @@ -935,6 +941,8 @@ static void InitializeConfOptions() ADD( ConfOption( "SoundVolume", SoundVolume, "Silent","|10%","|20%","|30%","|40%","|50%","|60%","|70%","|80%","|90%","|100%" ) ); g_ConfOptions.back().m_iEffects = OPT_APPLY_SOUND; ADD( ConfOption( "SoundVolumeAttract", SoundVolumeAttract, "Silent","|10%","|20%","|30%","|40%","|50%","|60%","|70%","|80%","|90%","|100%" ) ); + ADD( ConfOption( "PreferredSampleRate", PreferredSampleRate, "Default", "44100 Hz", "48000 Hz" ) ); + g_ConfOptions.back().m_sPrefName = "SoundPreferredSampleRate"; ADD( ConfOption( "VisualDelaySeconds", VisualDelaySeconds, "|-5","|-4","|-3","|-2","|-1","|0","|+1","|+2","|+3","|+4","|+5" ) ); { ConfOption c( "GlobalOffsetSeconds", GlobalOffsetSeconds ); diff --git a/src/arch/Sound/ALSA9Helpers.cpp b/src/arch/Sound/ALSA9Helpers.cpp index 007022b211..9fc6fc7c1e 100644 --- a/src/arch/Sound/ALSA9Helpers.cpp +++ b/src/arch/Sound/ALSA9Helpers.cpp @@ -212,7 +212,7 @@ void Alsa9Buf::GetSoundCardDebugInfo() Alsa9Buf::Alsa9Buf() { - samplerate = 48000; + samplerate = 44100; samplebits = 16; last_cursor_pos = 0; preferred_writeahead = 8192; @@ -229,7 +229,7 @@ RString Alsa9Buf::Init( int channels_, preferred_writeahead = iWriteahead; preferred_chunksize = iChunkSize; if( iSampleRate == 0 ) - samplerate = 48000; + samplerate = 44100; else samplerate = iSampleRate; diff --git a/src/arch/Sound/DSoundHelpers.cpp b/src/arch/Sound/DSoundHelpers.cpp index 441e7d4ac5..1152d3a40c 100644 --- a/src/arch/Sound/DSoundHelpers.cpp +++ b/src/arch/Sound/DSoundHelpers.cpp @@ -62,7 +62,12 @@ void DSound::SetPrimaryBufferMode() waveformat.wFormatTag = WAVE_FORMAT_PCM; waveformat.wBitsPerSample = 16; waveformat.nChannels = 2; - waveformat.nSamplesPerSec = 48000; + int preferredSampleRate = PREFSMAN->m_iSoundPreferredSampleRate; + if (preferredSampleRate == 0) + { + preferredSampleRate = 44100; // Default to 44100 Hz if preference is 0 + } + waveformat.nSamplesPerSec = preferredSampleRate; waveformat.nBlockAlign = 4; waveformat.nAvgBytesPerSec = waveformat.nSamplesPerSec * waveformat.nBlockAlign; @@ -75,8 +80,8 @@ void DSound::SetPrimaryBufferMode() hr = pBuffer->GetFormat( &waveformat, sizeof(waveformat), &got ); if( FAILED(hr) ) LOG->Warn( hr_ssprintf(hr, "GetFormat on primary buffer") ); - else if( waveformat.nSamplesPerSec != 48000 ) - LOG->Warn( "Primary buffer set to %i instead of 48000", waveformat.nSamplesPerSec ); + else if( waveformat.nSamplesPerSec != 44100 ) + LOG->Warn( "Primary buffer set to %i instead of 44100", waveformat.nSamplesPerSec ); /* * MS docs: @@ -195,9 +200,9 @@ RString DSoundBuf::Init( DSound &ds, DSoundBuf::hw hardware, waveformat.wFormatTag = WAVE_FORMAT_PCM; bool bNeedCtrlFrequency = false; - if( m_iSampleRate == DYNAMIC_SAMPLERATE ) + if( m_iSampleRate == DYNAMIC_SAMPLERATE ) // DYNAMIC_SAMPLERATE is usually 0 or some special value { - m_iSampleRate = 48000; + m_iSampleRate = 44100; // If dynamic, default to 44100 for now bNeedCtrlFrequency = true; } diff --git a/src/arch/Sound/RageSoundDriver.h b/src/arch/Sound/RageSoundDriver.h index daa7a9d89c..22309b5948 100644 --- a/src/arch/Sound/RageSoundDriver.h +++ b/src/arch/Sound/RageSoundDriver.h @@ -66,7 +66,7 @@ public: * hearing it. (This isn't necessarily the same as the buffer latency.) */ virtual float GetPlayLatency() const { return 0.0f; } - virtual int GetSampleRate() const { return 48000; } + virtual int GetSampleRate() const { return 44100; } protected: /* Start the decoding. This should be called once the hardware is set up and diff --git a/src/arch/Sound/RageSoundDriver_AU.mm b/src/arch/Sound/RageSoundDriver_AU.mm index 1c4d0f41a2..28366266be 100644 --- a/src/arch/Sound/RageSoundDriver_AU.mm +++ b/src/arch/Sound/RageSoundDriver_AU.mm @@ -151,7 +151,7 @@ RString RageSoundDriver_AU::Init() streamFormat.mBitsPerChannel = kBitsPerChannel; if( streamFormat.mSampleRate <= 0.0 ) - streamFormat.mSampleRate = 48000.0; + streamFormat.mSampleRate = 44100.0; m_iSampleRate = int( streamFormat.mSampleRate ); m_TimeScale = streamFormat.mSampleRate / AudioGetHostClockFrequency(); diff --git a/src/arch/Sound/RageSoundDriver_DSound_Software.cpp b/src/arch/Sound/RageSoundDriver_DSound_Software.cpp index dbcffefd33..01440276e9 100644 --- a/src/arch/Sound/RageSoundDriver_DSound_Software.cpp +++ b/src/arch/Sound/RageSoundDriver_DSound_Software.cpp @@ -97,7 +97,8 @@ RString RageSoundDriver_DSound_Software::Init() m_pPCM = new DSoundBuf; m_iSampleRate = PREFSMAN->m_iSoundPreferredSampleRate; if( m_iSampleRate == 0 ) - m_iSampleRate = 48000; + m_iSampleRate = 44100; + // This m_iSampleRate (driver's) is then passed as the iSampleRate parameter to DSoundBuf::Init() sError = m_pPCM->Init( ds, DSoundBuf::HW_DONT_CARE, channels, m_iSampleRate, 16, g_iMaxWriteahead ); if( sError != "" ) return sError; diff --git a/src/arch/Sound/RageSoundDriver_Null.cpp b/src/arch/Sound/RageSoundDriver_Null.cpp index 6c140fff06..f8a7124a58 100644 --- a/src/arch/Sound/RageSoundDriver_Null.cpp +++ b/src/arch/Sound/RageSoundDriver_Null.cpp @@ -32,7 +32,7 @@ RageSoundDriver_Null::RageSoundDriver_Null() { m_iSampleRate = PREFSMAN->m_iSoundPreferredSampleRate; if( m_iSampleRate == 0 ) - m_iSampleRate = 48000; + m_iSampleRate = 44100; m_iLastCursorPos = GetPosition(); StartDecodeThread(); } diff --git a/src/arch/Sound/RageSoundDriver_OSS.cpp b/src/arch/Sound/RageSoundDriver_OSS.cpp index 95a39f7e90..655fc7fad0 100644 --- a/src/arch/Sound/RageSoundDriver_OSS.cpp +++ b/src/arch/Sound/RageSoundDriver_OSS.cpp @@ -181,26 +181,33 @@ RString RageSoundDriver_OSS::Init() if( sError != "" ) return sError; - int i = AFMT_S16_LE; - if(ioctl(fd, SNDCTL_DSP_SETFMT, &i) == -1) - return ssprintf( "RageSoundDriver_OSS: ioctl(SNDCTL_DSP_SETFMT, %i): %s", i, strerror(errno) ); - if(i != AFMT_S16_LE) - return ssprintf( "RageSoundDriver_OSS: Wanted format %i, got %i instead", AFMT_S16_LE, i ); + int fmt_val = AFMT_S16_LE; + if(ioctl(fd, SNDCTL_DSP_SETFMT, &fmt_val) == -1) + return ssprintf( "RageSoundDriver_OSS: ioctl(SNDCTL_DSP_SETFMT, %i): %s", fmt_val, strerror(errno) ); + if(fmt_val != AFMT_S16_LE) + return ssprintf( "RageSoundDriver_OSS: Wanted format %i, got %i instead", AFMT_S16_LE, fmt_val ); - i = channels; - if(ioctl(fd, SNDCTL_DSP_CHANNELS, &i) == -1) - return ssprintf( "RageSoundDriver_OSS: ioctl(SNDCTL_DSP_CHANNELS, %i): %s", i, strerror(errno) ); - if(i != channels) - return ssprintf( "RageSoundDriver_OSS: Wanted %i channels, got %i instead", channels, i ); + int channels_val = channels; + if(ioctl(fd, SNDCTL_DSP_CHANNELS, &channels_val) == -1) + return ssprintf( "RageSoundDriver_OSS: ioctl(SNDCTL_DSP_CHANNELS, %i): %s", channels_val, strerror(errno) ); + if(channels_val != channels) + return ssprintf( "RageSoundDriver_OSS: Wanted %i channels, got %i instead", channels, channels_val ); - i = 48000; - if(ioctl(fd, SNDCTL_DSP_SPEED, &i) == -1 ) - return ssprintf( "RageSoundDriver_OSS: ioctl(SNDCTL_DSP_SPEED, %i): %s", i, strerror(errno) ); - samplerate = i; - LOG->Trace("RageSoundDriver_OSS: sample rate %i", samplerate); - i = (num_chunks << 16) + chunk_order; - if(ioctl(fd, SNDCTL_DSP_SETFRAGMENT, &i) == -1) - return ssprintf( "RageSoundDriver_OSS: ioctl(SNDCTL_DSP_SETFRAGMENT, %i): %s", i, strerror(errno) ); + // Determine the target sample rate based on preference + int targetSampleRate = PREFSMAN->m_iSoundPreferredSampleRate; + if (targetSampleRate == 0) { + targetSampleRate = 44100; // Default to 44100 if preference is 0 + } + + samplerate = targetSampleRate; // Attempt to set this rate + if(ioctl(fd, SNDCTL_DSP_SPEED, &samplerate) == -1 ) // Pass 'samplerate' (member var) by address + return ssprintf( "RageSoundDriver_OSS: ioctl(SNDCTL_DSP_SPEED, %i): %s", targetSampleRate, strerror(errno) ); + // samplerate now holds the actual rate set by the driver + LOG->Trace("RageSoundDriver_OSS: Requested sample rate %i, got %i", targetSampleRate, samplerate); + + int frag_val = (num_chunks << 16) + chunk_order; + if(ioctl(fd, SNDCTL_DSP_SETFRAGMENT, &frag_val) == -1) + return ssprintf( "RageSoundDriver_OSS: ioctl(SNDCTL_DSP_SETFRAGMENT, %i): %s", frag_val, strerror(errno) ); StartDecodeThread(); MixingThread.SetName( "RageSoundDriver_OSS" ); diff --git a/src/arch/Sound/RageSoundDriver_PulseAudio.cpp b/src/arch/Sound/RageSoundDriver_PulseAudio.cpp index 88d56850a5..8a58d37c23 100644 --- a/src/arch/Sound/RageSoundDriver_PulseAudio.cpp +++ b/src/arch/Sound/RageSoundDriver_PulseAudio.cpp @@ -29,7 +29,7 @@ m_PulseMainLoop(nullptr), m_PulseCtx(nullptr), m_PulseStream(nullptr) { m_ss.rate = PREFSMAN->m_iSoundPreferredSampleRate; if( m_ss.rate == 0 ) - m_ss.rate = 48000; + m_ss.rate = 44100; } RageSoundDriver_PulseAudio::~RageSoundDriver_PulseAudio() @@ -124,27 +124,23 @@ RString RageSoundDriver_PulseAudio::Init() void RageSoundDriver_PulseAudio::m_InitStream(void) { int error; - pa_sample_spec ss; + pa_sample_spec ss_local; // Use a local pa_sample_spec for setup pa_channel_map map; /* init sample spec */ - ss.format = PA_SAMPLE_S16LE; - ss.channels = 2; - ss.rate = PREFSMAN->m_iSoundPreferredSampleRate; - if(ss.rate == 0) - { - ss.rate = 48000; - } + ss_local.format = PA_SAMPLE_S16LE; + ss_local.channels = 2; + ss_local.rate = m_ss.rate; // Use the rate initialized in the constructor's m_ss /* init channel map */ pa_channel_map_init_stereo(&map); /* check sample spec */ - if(!pa_sample_spec_valid(&ss)) + if(!pa_sample_spec_valid(&ss_local)) { if(asprintf(&m_Error, "invalid sample spec!") == -1) { - m_Error = nullptr; + m_Error = nullptr; // asprintf failed to allocate memory } m_Sem.Post(); return; @@ -152,17 +148,17 @@ void RageSoundDriver_PulseAudio::m_InitStream(void) /* log the used sample spec */ char specstring[PA_SAMPLE_SPEC_SNPRINT_MAX]; - pa_sample_spec_snprint(specstring, sizeof(specstring), &ss); + pa_sample_spec_snprint(specstring, sizeof(specstring), &ss_local); LOG->Trace("Pulse: using sample spec: %s", specstring); /* create the stream */ LOG->Trace("Pulse: pa_stream_new()..."); - m_PulseStream = pa_stream_new(m_PulseCtx, PRODUCT_FAMILY " Audio", &ss, &map); + m_PulseStream = pa_stream_new(m_PulseCtx, PRODUCT_FAMILY " Audio", &ss_local, &map); if(m_PulseStream == nullptr) { if(asprintf(&m_Error, "pa_stream_new(): %s", pa_strerror(pa_context_errno(m_PulseCtx))) == -1) { - m_Error = nullptr; + m_Error = nullptr; // asprintf failed to allocate memory } m_Sem.Post(); return; @@ -172,13 +168,13 @@ void RageSoundDriver_PulseAudio::m_InitStream(void) * needs data */ pa_stream_set_write_callback(m_PulseStream, StaticStreamWriteCb, this); - /* set the state callback, it will be called the the stream state will + /* set the state callback, it will be called when the stream state will * change */ pa_stream_set_state_callback(m_PulseStream, StaticStreamStateCb, this); /* configure attributes of the stream */ pa_buffer_attr attr; - memset(&attr, 0x00, sizeof(attr)); + memset(&attr, 0x00, sizeof(attr)); // Initialize all members to 0/nullptr /* tlength: Target length of the buffer. * @@ -193,7 +189,7 @@ void RageSoundDriver_PulseAudio::m_InitStream(void) * We don't want the default here, we want a small latency. * We use pa_usec_to_bytes() to convert a latency to a buffer size. */ - attr.tlength = pa_usec_to_bytes(20*PA_USEC_PER_MSEC, &ss); + attr.tlength = pa_usec_to_bytes(20*PA_USEC_PER_MSEC, &ss_local); // Use local ss_local /* maxlength: Maximum length of the buffer * @@ -215,7 +211,7 @@ void RageSoundDriver_PulseAudio::m_InitStream(void) * (uint32_t)-1 is NOT working here, setting it to 0, like * openal-soft-pulseaudio does. */ - attr.minreq = 0; + attr.minreq = 0; // Setting to (uint32_t)-1 caused issues in some environments. 0 is safer. /* prebuf: Pre-buffering * @@ -226,14 +222,21 @@ void RageSoundDriver_PulseAudio::m_InitStream(void) */ attr.prebuf = (uint32_t)-1; + /* fragsize: Deprecated. Use tlength, prebuf, minreq, maxlength instead. + * Ensure it's not used by setting to (uint32_t)-1, as per PA documentation. + */ + attr.fragsize = (uint32_t)-1; + + /* log the used target buffer length */ LOG->Trace("Pulse: using target buffer length of %i bytes", attr.tlength); /* connect the stream for playback */ LOG->Trace("Pulse: pa_stream_connect_playback()..."); const int flags = PA_STREAM_INTERPOLATE_TIMING - | PA_STREAM_NOT_MONOTONIC - | PA_STREAM_AUTO_TIMING_UPDATE; + | PA_STREAM_NOT_MONOTONIC // mHostTime may not be monotonic in some cases + | PA_STREAM_AUTO_TIMING_UPDATE + | PA_STREAM_ADJUST_LATENCY; // Allow server to adjust latency based on our buffer_attr error = pa_stream_connect_playback(m_PulseStream, nullptr, &attr, static_cast(flags), nullptr, nullptr); if(error < 0) @@ -241,13 +244,21 @@ void RageSoundDriver_PulseAudio::m_InitStream(void) if(asprintf(&m_Error, "pa_stream_connect_playback(): %s", pa_strerror(pa_context_errno(m_PulseCtx))) == -1) { - m_Error = nullptr; + m_Error = nullptr; // asprintf failed to allocate memory } m_Sem.Post(); return; } - m_ss = ss; + // m_ss is the member variable. After successfully connecting the stream, + // we can be more confident about the sample spec being used. + // It's generally good practice to update m_ss with the spec that was + // actually used to create the stream, in case the server negotiated + // something slightly different (though with PA_SAMPLE_S16LE, 2ch, and specific rates, + // it's less likely to change). + m_ss = ss_local; + + // Semaphore is posted in StreamStateCb when stream becomes PA_STREAM_READY } void RageSoundDriver_PulseAudio::CtxStateCb(pa_context *c) diff --git a/src/arch/Sound/RageSoundDriver_WaveOut.cpp b/src/arch/Sound/RageSoundDriver_WaveOut.cpp index cb1195cc24..c40f7b7626 100644 --- a/src/arch/Sound/RageSoundDriver_WaveOut.cpp +++ b/src/arch/Sound/RageSoundDriver_WaveOut.cpp @@ -125,7 +125,7 @@ RString RageSoundDriver_WaveOut::Init() b_InitSuccess = false; m_iSampleRate = PREFSMAN->m_iSoundPreferredSampleRate; if( m_iSampleRate == 0 ) - m_iSampleRate = 48000; + m_iSampleRate = 44100; WAVEFORMATEX fmt; fmt.wFormatTag = WAVE_FORMAT_PCM;