Skip to content

Commit

Permalink
Rework how generic info about sound formats is reported.
Browse files Browse the repository at this point in the history
- Determine interface-agnostic buffer sizes for the sound interfaces.
  • Loading branch information
DreamyCecil committed Jan 31, 2025
1 parent d96c3fc commit c6d1365
Show file tree
Hide file tree
Showing 6 changed files with 71 additions and 83 deletions.
32 changes: 28 additions & 4 deletions Sources/Engine/Sound/SoundAPI.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include <Engine/Sound/SoundAPI_SDL.h>
#include <Engine/Sound/SoundAPI_WaveOut.h>

extern FLOAT snd_tmMixAhead;

CAbstractSoundAPI::CAbstractSoundAPI() {
m_pslMixerBuffer = NULL;
m_slMixerBufferSize = 0;
Expand All @@ -36,22 +38,32 @@ CAbstractSoundAPI::~CAbstractSoundAPI() {
};

// Calculate mixer buffer size
SLONG CAbstractSoundAPI::CalculateMixerSize(const WAVEFORMATEX &wfe) {
extern FLOAT snd_tmMixAhead;
SLONG CAbstractSoundAPI::CalculateMixerSize(void) {
const WAVEFORMATEX &wfe = _pSound->sl_SwfeFormat;
return SLONG(ceil(snd_tmMixAhead * wfe.nSamplesPerSec) * wfe.wBitsPerSample / 8 * wfe.nChannels);
};

// Calculate decoder buffer size (only after mixer size)
SLONG CAbstractSoundAPI::CalculateDecoderSize(const WAVEFORMATEX &wfe) {
SLONG CAbstractSoundAPI::CalculateDecoderSize(void) {
// Decoder buffer always works at 44khz
const WAVEFORMATEX &wfe = _pSound->sl_SwfeFormat;
return m_slMixerBufferSize * ((44100 + wfe.nSamplesPerSec - 1) / wfe.nSamplesPerSec);
};

// Allocate new buffer memory
void CAbstractSoundAPI::AllocBuffers(void) {
void CAbstractSoundAPI::AllocBuffers(BOOL bAlignToBlockSize) {
ASSERT(m_pslMixerBuffer == NULL);
ASSERT(m_pswDecodeBuffer == NULL);

// Determine initial buffer sizes
m_slMixerBufferSize = CalculateMixerSize();
m_slDecodeBufferSize = CalculateDecoderSize();

// Align mixer size to be the next multiple of WAVEOUTBLOCKSIZE
if (bAlignToBlockSize) {
m_slMixerBufferSize += WAVEOUTBLOCKSIZE - (m_slMixerBufferSize % WAVEOUTBLOCKSIZE);
}

// Twice as much because of 32-bit buffer
m_pslMixerBuffer = (SLONG *)AllocMemory(m_slMixerBufferSize * 2);

Expand All @@ -70,6 +82,18 @@ void CAbstractSoundAPI::FreeBuffers(void) {
m_slDecodeBufferSize = 0;
};

// Report generic info about an interface
void CAbstractSoundAPI::ReportGenericInfo(void) {
const WAVEFORMATEX &wfe = _pSound->sl_SwfeFormat;
CPrintF(TRANS("Sound interface info:\n"));

CPrintF(TRANS(" %d Hz, %d bit, %d channels, mix-ahead: %gs\n"),
wfe.nSamplesPerSec, wfe.wBitsPerSample, wfe.nChannels, snd_tmMixAhead);

CPrintF(TRANS(" mixer buffer size: %d bytes\n"), m_slMixerBufferSize);
CPrintF(TRANS(" decode buffer size: %d bytes\n"), m_slDecodeBufferSize);
};

// Get API name from type
const CTString &CAbstractSoundAPI::GetApiName(CAbstractSoundAPI::ESoundAPI eAPI)
{
Expand Down
10 changes: 7 additions & 3 deletions Sources/Engine/Sound/SoundAPI.h
Original file line number Diff line number Diff line change
Expand Up @@ -66,17 +66,21 @@ class ENGINE_API CAbstractSoundAPI {
virtual ~CAbstractSoundAPI();

// Calculate mixer buffer size
SLONG CalculateMixerSize(const WAVEFORMATEX &wfe);
SLONG CalculateMixerSize(void);

// Calculate decoder buffer size (only after mixer size)
SLONG CalculateDecoderSize(const WAVEFORMATEX &wfe);
SLONG CalculateDecoderSize(void);

// Allocate new buffer memory
void AllocBuffers(void);
// Must always be called from interface's StartUp() method
void AllocBuffers(BOOL bAlignToBlockSize);

// Free buffer memory
void FreeBuffers(void);

// Report generic info about an interface
void ReportGenericInfo(void);

// Get API name from type
static const CTString &GetApiName(ESoundAPI eAPI);

Expand Down
37 changes: 12 additions & 25 deletions Sources/Engine/Sound/SoundAPI_DSound.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,6 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#define MINPAN (1.0f)
#define MAXPAN (9.0f)

extern FLOAT snd_tmMixAhead;
extern INDEX snd_iDevice;
extern INDEX snd_iInterface;
extern FLOAT snd_fEAXPanning;

Expand Down Expand Up @@ -202,8 +200,6 @@ BOOL CSoundAPI_DSound::StartUp(BOOL bReport) {
ASSERT(m_hDSoundLib == NULL && m_pDS == NULL);
ASSERT(m_pDSSecondary == NULL && m_pDSPrimary == NULL);

if (bReport) CPrintF(TRANS("Direct Sound initialization ...\n"));

m_hDSoundLib = OS::LoadLib("dsound.dll");

if (m_hDSoundLib == NULL) {
Expand Down Expand Up @@ -264,21 +260,22 @@ BOOL CSoundAPI_DSound::StartUp(BOOL bReport) {
if(hResult != DS_OK) return Fail(TRANS(" ! DirectSound error: Cannot create primary sound buffer.\n"));

// Set primary buffer format
WAVEFORMATEX &wfe = _pSound->sl_SwfeFormat;
const WAVEFORMATEX &wfe = _pSound->sl_SwfeFormat;

hResult = m_pDSPrimary->SetFormat(&wfe);
if (hResult != DS_OK) return Fail(TRANS(" ! DirectSound error: Cannot set primary sound buffer format.\n"));

// Start up secondary sound buffers
SLONG slBufferSize = CalculateMixerSize(wfe);
// Allocate mixer buffers
AllocBuffers(FALSE);

if (!InitSecondary(m_pDSSecondary, slBufferSize)) return FALSE;
// Start up secondary sound buffers
if (!InitSecondary(m_pDSSecondary, m_slMixerBufferSize)) return FALSE;

#if SE1_SND_EAX
// Set some additionals for EAX
if (snd_iInterface == E_SND_EAX) {
// 2nd secondary buffer
if (!InitSecondary(m_pDSSecondary2, slBufferSize)) return FALSE;
if (!InitSecondary(m_pDSSecondary2, m_slMixerBufferSize)) return FALSE;

// Set 3D for all buffers
HRESULT hr1, hr2, hr3, hr4;
Expand Down Expand Up @@ -334,27 +331,17 @@ BOOL CSoundAPI_DSound::StartUp(BOOL bReport) {
}

m_iWriteOffsetEAX = 0;

if (bReport) {
CPrintF(TRANS(" EAX: %s\n"), m_bUsingEAX ? TRANS("Enabled") : TRANS("Disabled"));
}
#endif // SE1_SND_EAX

// Mark that DirectSound is operative and set mixer buffer size (decoder buffer always works at 44khz)
// Mark that DirectSound is operative
m_iWriteOffset = 0;
m_slMixerBufferSize = slBufferSize;
m_slDecodeBufferSize = CalculateDecoderSize(wfe);

AllocBuffers();

// Report success
if (bReport) {
CTString strDevice = TRANS("default device");
if (snd_iDevice >= 0) strDevice.PrintF(TRANS("device %d"), snd_iDevice);

CPrintF(TRANS(" %dHz, %dbit, %s, mix-ahead: %gs\n"), wfe.nSamplesPerSec, wfe.wBitsPerSample, strDevice.ConstData(), snd_tmMixAhead);
CPrintF(TRANS(" mixer buffer size: %d KB\n"), m_slMixerBufferSize / 1024);
CPrintF(TRANS(" decode buffer size: %d KB\n"), m_slDecodeBufferSize / 1024);

#if SE1_SND_EAX
CPrintF(TRANS(" EAX: %s\n"), m_bUsingEAX ? TRANS("Enabled") : TRANS("Disabled"));
#endif
ReportGenericInfo();
}

return TRUE;
Expand Down
28 changes: 5 additions & 23 deletions Sources/Engine/Sound/SoundAPI_SDL.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,6 @@ with this program; if not, write to the Free Software Foundation, Inc.,

#if SE1_PREFER_SDL || SE1_SND_SDLAUDIO

extern INDEX snd_iDevice;
extern FLOAT snd_tmMixAhead;

static void AudioCallback(void *pUserData, Uint8 *pubStream, int iLength) {
CSoundAPI_SDL *pAPI = (CSoundAPI_SDL *)pUserData;

Expand Down Expand Up @@ -92,10 +89,6 @@ static void AudioCallback(void *pUserData, Uint8 *pubStream, int iLength) {
};

BOOL CSoundAPI_SDL::StartUp(BOOL bReport) {
snd_iDevice = 0;

if (bReport) CPrintF(TRANS("SDL audio initialization ...\n"));

SDL_AudioSpec desired, obtained;
SDL_zero(desired);
SDL_zero(obtained);
Expand Down Expand Up @@ -147,6 +140,9 @@ BOOL CSoundAPI_SDL::StartUp(BOOL bReport) {
return FALSE;
}

// Allocate mixer buffers
AllocBuffers(TRUE);

m_ubSilence = obtained.silence;
m_slBackBufferAlloc = (obtained.size * 4);
m_pBackBuffer = (Uint8 *)AllocMemory(m_slBackBufferAlloc);
Expand All @@ -156,25 +152,11 @@ BOOL CSoundAPI_SDL::StartUp(BOOL bReport) {
// Report success
if (bReport) {
CPrintF(TRANS(" opened device: %s\n"), strDeviceName);
CPrintF(TRANS(" %dHz, %dbit, %s\n"), wfe.nSamplesPerSec, wfe.wBitsPerSample, SDL_GetCurrentAudioDriver());
}

// Determine whole mixer buffer size
m_slMixerBufferSize = CalculateMixerSize(wfe);

// Align size to be next multiply of WAVEOUTBLOCKSIZE
m_slMixerBufferSize += WAVEOUTBLOCKSIZE - (m_slMixerBufferSize % WAVEOUTBLOCKSIZE);
m_slDecodeBufferSize = CalculateDecoderSize(wfe);

if (bReport) {
CPrintF(TRANS(" parameters: %d Hz, %d bit, stereo, mix-ahead: %gs\n"), wfe.nSamplesPerSec, wfe.wBitsPerSample, snd_tmMixAhead);
CPrintF(TRANS(" audio driver: %s\n"), SDL_GetCurrentAudioDriver());
CPrintF(TRANS(" output buffers: %d x %d bytes\n"), 2, obtained.size);
CPrintF(TRANS(" mpx decode: %d bytes\n"), m_slDecodeBufferSize);
ReportGenericInfo();
}

// Initialize mixing and decoding buffers
AllocBuffers();

// Audio callback can now safely fill the audio stream with silence until there is actual audio data to mix
SDL_PauseAudioDevice(m_iAudioDevice, 0);
return TRUE;
Expand Down
37 changes: 12 additions & 25 deletions Sources/Engine/Sound/SoundAPI_WaveOut.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@ with this program; if not, write to the Free Software Foundation, Inc.,

#if SE1_WIN && SE1_SND_WAVEOUT

extern FLOAT snd_tmMixAhead;
extern INDEX snd_iDevice;
extern INDEX snd_iMaxOpenRetries;
extern INDEX snd_iMaxExtraChannels;
Expand All @@ -31,9 +30,7 @@ BOOL CSoundAPI_WaveOut::StartUp(BOOL bReport) {
static INDEX _ctChannelsOpened;
_ctChannelsOpened = 0;

if (bReport) CPrintF(TRANS("WaveOut initialization ...\n"));

WAVEFORMATEX &wfe = _pSound->sl_SwfeFormat;
const WAVEFORMATEX &wfe = _pSound->sl_SwfeFormat;

// Set maximum total number of retries for device opening
INDEX ctMaxRetries = snd_iMaxOpenRetries;
Expand Down Expand Up @@ -72,7 +69,7 @@ BOOL CSoundAPI_WaveOut::StartUp(BOOL bReport) {
}

// Wait a bit (probably sound-scheme is playing)
_pTimer->Suspend(ULONG(snd_tmOpenFailDelay) * 1000);
_pTimer->Suspend(ULONG(snd_tmOpenFailDelay * 1000.0f));
}
}

Expand All @@ -95,36 +92,27 @@ BOOL CSoundAPI_WaveOut::StartUp(BOOL bReport) {
return FALSE;
}

// Allocate mixer buffers
AllocBuffers(TRUE);

// Get WaveOut capabilities
WAVEOUTCAPS woc;
memset(&woc, 0, sizeof(woc));

res = waveOutGetDevCaps((UINT_PTR)m_hwoWaveOut, &woc, sizeof(woc));

// Report success
if (bReport) {
CTString strDevice = TRANS("default device");
if (snd_iDevice >= 0) strDevice.PrintF(TRANS("device %d"), snd_iDevice);

CPrintF(TRANS(" opened device: %s\n"), woc.szPname);
CPrintF(TRANS(" %dHz, %dbit, %s\n"), wfe.nSamplesPerSec, wfe.wBitsPerSample, strDevice.ConstData());
}

// Determine whole mixer buffer size
m_slMixerBufferSize = CalculateMixerSize(wfe);

// Align size to be next multiply of WAVEOUTBLOCKSIZE
m_slMixerBufferSize += WAVEOUTBLOCKSIZE - (m_slMixerBufferSize % WAVEOUTBLOCKSIZE);
m_slDecodeBufferSize = CalculateDecoderSize(wfe);

// Determine number of WaveOut buffers
const INDEX ctWOBuffers = m_slMixerBufferSize / WAVEOUTBLOCKSIZE;

// Report success
if (bReport) {
CPrintF(TRANS(" parameters: %d Hz, %d bit, stereo, mix-ahead: %gs\n"), wfe.nSamplesPerSec, wfe.wBitsPerSample, snd_tmMixAhead);
CPrintF(TRANS(" output buffers: %d x %d bytes\n"), ctWOBuffers, WAVEOUTBLOCKSIZE),
CPrintF(TRANS(" mpx decode: %d bytes\n"), m_slDecodeBufferSize),
CTString strDevice = TRANS("default");
if (snd_iDevice >= 0) strDevice.PrintF("%d", snd_iDevice);

CPrintF(TRANS(" opened device (%s): %s\n"), strDevice.ConstData(), woc.szPname);
CPrintF(TRANS(" output buffers: %d x %d bytes\n"), ctWOBuffers, WAVEOUTBLOCKSIZE);
CPrintF(TRANS(" extra sound channels taken: %d\n"), _ctChannelsOpened-1);
ReportGenericInfo();
}

// Initialize WaveOut sound buffers
Expand All @@ -141,7 +129,6 @@ BOOL CSoundAPI_WaveOut::StartUp(BOOL bReport) {
wh.dwFlags = 0;
}

AllocBuffers();
return TRUE;
};

Expand Down
10 changes: 7 additions & 3 deletions Sources/Engine/Sound/SoundLibrary.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -238,12 +238,16 @@ void CSoundLibrary::SetFormat_internal(CSoundLibrary::SoundFormat EsfNew, BOOL b

// [Cecil] Try creating interfaces until one succeeds
for (INDEX iCheck = snd_iInterface; iCheck >= 0; iCheck--) {
CAbstractSoundAPI::ESoundAPI eAPI = (CAbstractSoundAPI::ESoundAPI)iCheck;

// Create a new interface
DestroyInterface();
sl_pInterface = CAbstractSoundAPI::CreateAPI((CAbstractSoundAPI::ESoundAPI)iCheck);
sl_pInterface = CAbstractSoundAPI::CreateAPI(eAPI);

// Set and start it up
snd_iInterface = iCheck;
snd_iInterface = eAPI;
if (bReport) CPrintF(TRANS("%s initialization...\n"), CAbstractSoundAPI::GetApiName(eAPI).ConstData());

bSoundOK = sl_pInterface->StartUp(bReport);

// Setting succeeded
Expand Down Expand Up @@ -322,7 +326,7 @@ void CSoundLibrary::Init(void)
sl_ctWaveDevices = (INDEX)SDL_GetNumAudioDevices(0);
CPrintF(TRANS(" Detected devices: %d\n"), sl_ctWaveDevices);

for (int iDevice = 0; iDevice < sl_ctWaveDevices; iDevice++) {
for (INDEX iDevice = 0; iDevice < sl_ctWaveDevices; iDevice++) {
CPrintF(TRANS(" device %d: %s\n"), iDevice, SDL_GetAudioDeviceName(iDevice, 0));
}

Expand Down

0 comments on commit c6d1365

Please sign in to comment.