This makes it more obvious that the default destructor is what we're using, instead of making it look like maybe there was supposed to be a destructor here.
To derive the bit depth, we can determine the number of bytes per frame (kChannels * 2), divide by the number of channels to get bytes per sample (2), and finally convert to bits by multiplying by 8 (16 bits).
Adopt Google C++ style guide naming:
m_hWaveOut → wave_out_handle
m_hSoundEvent → sound_event_handle
m_aBuffers → buffers
m_iSampleRate → sample_rate
m_bShutdown → shutdown
m_iLastCursorPos → last_cursor_pos
b_InitSuccess → init_success
NUM_CHUNKS → num_blocks
BUFFERSIZE_FRAMES → num_frames_per_block
CHUNKSIZE → block_size
I've also fixed spacing in the constructor and reorganized the list of member variables in the header for easier reading, and added context to the comment in the header file, changed a static const int to constexpr int, etc
s
With WaveOut, typically one defines the following values before starting a WaveOut thread: sample rate, number of blocks, and size of each block in frames. Based on these values, a particular latency will be calculated. StepMania historically follows this approach.
However, it is possible to target a specific latency instead, and extrapolate the needed number of blocks if the sample rate and block size values are known.
This PR refactors the driver to calculate the ideal number of blocks based on a pre-determined optimal target latency and block size. This allows us to guarantee a nearly-imperceptible difference in WaveOut latency (0.29 ms) between 44.1 kHz and 48 kHz.
Nothing related to driver functionality is changed. We just change the way the buffer parameters are determined. This PR only changes code which runs before the WaveOut thread is launched.
When we consider how the WaveOut API works, we need to provide three of four values and the fourth is calculated. So, at 44100 Hz, with 15 blocks of 256 frames each, 15 * 256 gives us 3840 frames of latency (3840 / 44100 = ~87 ms). If we use this same configuration with 48000 Hz, we get a latency of 80ms which is a significant difference.
However, if we increase to 16 blocks at 48000 Hz, we get 4096 frames of latency (~85 ms), which is much closer to the 87 ms when using 15 blocks at 44100 Hz.
A target latency of 118 ms allows for the smallest possible delta when using a block size of 512 frames, and testing with sample rates of 44100 and 48000. At 44100 Hz / 512 frames / 118 ms target latency, we have a calculated latency of 127.7098 ms. At 48000 Hz / 512 frames/ 118 ms target latency, we have a calculated latency of 128 ms - a 0.29 ms difference.
I determined this by simulating the CalculteNumBufferChunks calculation for a range of 100 to 300.
This was actually already considered in the surrounding code. I just had to uncomment it. This recommendation has remained consistent in the Microsoft documentation since this code was written. It's safe to uncomment it to ensure our main buffer stays active, since shutdown of the mixer engine is unwanted.
- Moved end-of-line comments to preceding lines for better readability and to avoid potential line length issues across various files modified in previous commits.
- In the RageSoundReader_Chain constructor: Removed redundant initialization of m_iPreferredSampleRate. Replaced hardcoded 44100 with kFallbackSampleRate. Removed an unnecessary comment.
- Added braces consistently to single-statement if/else blocks across all recently modified sound system files. This enhances code clarity and maintainability by explicitly defining block scopes.
Replaces hardcoded 44100Hz values (used as fallbacks or for the "Default" sample rate preference) with a new constant `constexpr int kFallbackSampleRate = 44100;` defined in RageSound.h.
This constant is now used in:
- RageSoundReader_Silence
- RageSoundManager (for unloaded driver scenarios)
- All sound drivers' initialization logic for the "Default (0)" preference (DSound, WaveOut, AU, PulseAudio, OSS, WDMKS, Null)
- DSound primary buffer setup.
The English display name for the option has been updated to "Audio Sample Rate" for better clarity. Translations for this new option title have been added for Spanish, French, German, Japanese, Korean, Dutch, Polish, Slovak, and Traditional Chinese.
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.