Replaced most XAudio2 calls with OpenAL

This commit is contained in:
Robert Beckebans 2013-01-03 16:56:25 +01:00
parent 9a40f246b6
commit 038037e524
9 changed files with 200 additions and 230 deletions

View file

@ -1048,6 +1048,9 @@ if(MSVC)
list(APPEND RBDOOM3_INCLUDES ${OPENAL_INCLUDES}) list(APPEND RBDOOM3_INCLUDES ${OPENAL_INCLUDES})
list(APPEND RBDOOM3_SOURCES ${OPENAL_SOURCES}) list(APPEND RBDOOM3_SOURCES ${OPENAL_SOURCES})
set(OpenAL_LIBRARIES
OpenAL32)
else() else()
add_definitions(-DUSE_DOOMCLASSIC) add_definitions(-DUSE_DOOMCLASSIC)
@ -1152,6 +1155,7 @@ if(MSVC)
iphlpapi iphlpapi
winmm winmm
wsock32.lib wsock32.lib
${OpenAL_LIBRARIES}
) )
#CMAKE_BINARY_DIR #CMAKE_BINARY_DIR

View file

@ -3,7 +3,7 @@
Doom 3 BFG Edition GPL Source Code Doom 3 BFG Edition GPL Source Code
Copyright (C) 1993-2012 id Software LLC, a ZeniMax Media company. Copyright (C) 1993-2012 id Software LLC, a ZeniMax Media company.
Copyright (C) 2012 Robert Beckebans Copyright (C) 2013 Robert Beckebans
This file is part of the Doom 3 BFG Edition GPL Source Code ("Doom 3 BFG Edition Source Code"). This file is part of the Doom 3 BFG Edition GPL Source Code ("Doom 3 BFG Edition Source Code").
@ -45,15 +45,14 @@ idSoundHardware_OpenAL::idSoundHardware_OpenAL
*/ */
idSoundHardware_OpenAL::idSoundHardware_OpenAL() idSoundHardware_OpenAL::idSoundHardware_OpenAL()
{ {
pXAudio2 = NULL; openalDevice = NULL;
pMasterVoice = NULL; openalContext = NULL;
pSubmixVoice = NULL;
vuMeterRMS = NULL; //vuMeterRMS = NULL;
vuMeterPeak = NULL; //vuMeterPeak = NULL;
outputChannels = 0; //outputChannels = 0;
channelMask = 0; //channelMask = 0;
voices.SetNum( 0 ); voices.SetNum( 0 );
zombieVoices.SetNum( 0 ); zombieVoices.SetNum( 0 );
@ -64,19 +63,8 @@ idSoundHardware_OpenAL::idSoundHardware_OpenAL()
void listDevices_f( const idCmdArgs& args ) void listDevices_f( const idCmdArgs& args )
{ {
#if 1
IXAudio2* pXAudio2 = soundSystemLocal.hardware.GetIXAudio2(); // TODO
if( pXAudio2 == NULL )
{
idLib::Warning( "No xaudio object" );
return;
}
// RB: not available on Windows 8 SDK
#if (_WIN32_WINNT >= 0x0602 /*_WIN32_WINNT_WIN8*/)
// FIXME
idLib::Warning( "No audio devices found" ); idLib::Warning( "No audio devices found" );
return; return;
@ -211,139 +199,46 @@ idSoundHardware_OpenAL::Init
*/ */
void idSoundHardware_OpenAL::Init() void idSoundHardware_OpenAL::Init()
{ {
cmdSystem->AddCommand( "listDevices", listDevices_f, 0, "Lists the connected sound devices", NULL ); cmdSystem->AddCommand( "listDevices", listDevices_f, 0, "Lists the connected sound devices", NULL );
DWORD xAudioCreateFlags = 0; common->Printf( "Setup OpenAL device and context... " );
// RB: not available on Windows 8 SDK openalDevice = alcOpenDevice( NULL );
#if (_WIN32_WINNT < 0x0602 /*_WIN32_WINNT_WIN8*/) && defined(_DEBUG) if( openalDevice == NULL )
xAudioCreateFlags |= XAUDIO2_DEBUG_ENGINE;
#endif
// RB end
XAUDIO2_PROCESSOR xAudioProcessor = XAUDIO2_DEFAULT_PROCESSOR;
// RB: not available on Windows 8 SDK
if( FAILED( XAudio2Create( &pXAudio2, xAudioCreateFlags, xAudioProcessor ) ) )
{ {
#if (_WIN32_WINNT < 0x0602 /*_WIN32_WINNT_WIN8*/) && defined(_DEBUG) common->FatalError( "idSoundHardware_OpenAL::Init: alcOpenDevice() failed\n" );
if( xAudioCreateFlags & XAUDIO2_DEBUG_ENGINE )
{
// in case the debug engine isn't installed
xAudioCreateFlags &= ~XAUDIO2_DEBUG_ENGINE;
if( FAILED( XAudio2Create( &pXAudio2, xAudioCreateFlags, xAudioProcessor ) ) )
{
idLib::FatalError( "Failed to create XAudio2 engine. Try installing the latest DirectX." );
return;
}
}
else
#endif
// RB end
{
idLib::FatalError( "Failed to create XAudio2 engine. Try installing the latest DirectX." );
return;
}
}
#ifdef _DEBUG
XAUDIO2_DEBUG_CONFIGURATION debugConfiguration = { 0 };
debugConfiguration.TraceMask = XAUDIO2_LOG_WARNINGS;
debugConfiguration.BreakMask = XAUDIO2_LOG_ERRORS;
pXAudio2->SetDebugConfiguration( &debugConfiguration );
#endif
// Register the sound engine callback
pXAudio2->RegisterForCallbacks( &soundEngineCallback );
soundEngineCallback.hardware = this;
// RB: not available on Windows 8 SDK
#if (_WIN32_WINNT >= 0x0602 /*_WIN32_WINNT_WIN8*/)
// FIXME
idLib::Warning( "No audio devices found" );
pXAudio2->Release();
pXAudio2 = NULL;
return;
#else
UINT32 deviceCount = 0;
if( pXAudio2->GetDeviceCount( &deviceCount ) != S_OK || deviceCount == 0 )
{
idLib::Warning( "No audio devices found" );
pXAudio2->Release();
pXAudio2 = NULL;
return; return;
} }
idCmdArgs args; openalContext = alcCreateContext( openalDevice, NULL );
listDevices_f( args ); if( alcMakeContextCurrent( openalContext ) == 0 )
int preferredDevice = s_device.GetInteger();
if( preferredDevice < 0 || preferredDevice >= ( int )deviceCount )
{ {
int preferredChannels = 0; common->FatalError( "idSoundHardware_OpenAL::Init: alcMakeContextCurrent( %p) failed\n", openalContext );
for( unsigned int i = 0; i < deviceCount; i++ )
{
XAUDIO2_DEVICE_DETAILS deviceDetails;
if( pXAudio2->GetDeviceDetails( i, &deviceDetails ) != S_OK )
{
continue;
}
if( deviceDetails.Role & DefaultGameDevice )
{
// if we find a device the user marked as their preferred 'game' device, then always use that
preferredDevice = i;
preferredChannels = deviceDetails.OutputFormat.Format.nChannels;
break;
}
if( deviceDetails.OutputFormat.Format.nChannels > preferredChannels )
{
preferredDevice = i;
preferredChannels = deviceDetails.OutputFormat.Format.nChannels;
}
}
}
idLib::Printf( "Using device %d\n", preferredDevice );
XAUDIO2_DEVICE_DETAILS deviceDetails;
if( pXAudio2->GetDeviceDetails( preferredDevice, &deviceDetails ) != S_OK )
{
// One way this could happen is if a device is removed between the loop and this line of code
// Highly unlikely but possible
idLib::Warning( "Failed to get device details" );
pXAudio2->Release();
pXAudio2 = NULL;
return; return;
} }
DWORD outputSampleRate = 44100; // Max( (DWORD)XAUDIO2FX_REVERB_MIN_FRAMERATE, Min( (DWORD)XAUDIO2FX_REVERB_MAX_FRAMERATE, deviceDetails.OutputFormat.Format.nSamplesPerSec ) ); common->Printf( "Done.\n" );
if( FAILED( pXAudio2->CreateMasteringVoice( &pMasterVoice, XAUDIO2_DEFAULT_CHANNELS, outputSampleRate, 0, preferredDevice, NULL ) ) ) common->Printf( "OpenAL vendor: %s\n", alGetString( AL_VENDOR ) );
{ common->Printf( "OpenAL renderer: %s\n", alGetString( AL_RENDERER ) );
idLib::Warning( "Failed to create master voice" ); common->Printf( "OpenAL version: %s\n", alGetString( AL_VERSION ) );
pXAudio2->Release();
pXAudio2 = NULL;
return;
}
pMasterVoice->SetVolume( DBtoLinear( s_volume_dB.GetFloat() ) );
outputChannels = deviceDetails.OutputFormat.Format.nChannels; //pMasterVoice->SetVolume( DBtoLinear( s_volume_dB.GetFloat() ) );
channelMask = deviceDetails.OutputFormat.dwChannelMask;
idSoundVoice::InitSurround( outputChannels, channelMask ); //outputChannels = deviceDetails.OutputFormat.Format.nChannels;
//channelMask = deviceDetails.OutputFormat.dwChannelMask;
//idSoundVoice::InitSurround( outputChannels, channelMask );
// --------------------- // ---------------------
// Initialize the Doom classic sound system. // Initialize the Doom classic sound system.
// --------------------- // ---------------------
I_InitSoundHardware( outputChannels, channelMask ); //I_InitSoundHardware( outputChannels, channelMask );
// --------------------- // ---------------------
// Create VU Meter Effect // Create VU Meter Effect
// --------------------- // ---------------------
/*
IUnknown* vuMeter = NULL; IUnknown* vuMeter = NULL;
XAudio2CreateVolumeMeter( &vuMeter, 0 ); XAudio2CreateVolumeMeter( &vuMeter, 0 );
@ -359,11 +254,13 @@ void idSoundHardware_OpenAL::Init()
pMasterVoice->SetEffectChain( &chain ); pMasterVoice->SetEffectChain( &chain );
vuMeter->Release(); vuMeter->Release();
*/
// --------------------- // ---------------------
// Create VU Meter Graph // Create VU Meter Graph
// --------------------- // ---------------------
/*
vuMeterRMS = console->CreateGraph( outputChannels ); vuMeterRMS = console->CreateGraph( outputChannels );
vuMeterPeak = console->CreateGraph( outputChannels ); vuMeterPeak = console->CreateGraph( outputChannels );
vuMeterRMS->Enable( false ); vuMeterRMS->Enable( false );
@ -388,16 +285,9 @@ void idSoundHardware_OpenAL::Init()
vuMeterRMS->SetLabel( i, channelNames[ ci ] ); vuMeterRMS->SetLabel( i, channelNames[ ci ] );
i++; i++;
} }
*/
// --------------------- // OpenAL doesn't really impose a maximum number of sources
// Create submix buffer
// ---------------------
if( FAILED( pXAudio2->CreateSubmixVoice( &pSubmixVoice, 1, outputSampleRate, 0, 0, NULL, NULL ) ) )
{
idLib::FatalError( "Failed to create submix voice" );
}
// XAudio doesn't really impose a maximum number of voices
voices.SetNum( voices.Max() ); voices.SetNum( voices.Max() );
freeVoices.SetNum( voices.Max() ); freeVoices.SetNum( voices.Max() );
zombieVoices.SetNum( 0 ); zombieVoices.SetNum( 0 );
@ -405,8 +295,6 @@ void idSoundHardware_OpenAL::Init()
{ {
freeVoices[i] = &voices[i]; freeVoices[i] = &voices[i];
} }
#endif // #if (_WIN32_WINNT < 0x0602 /*_WIN32_WINNT_WIN8*/)
// RB end
} }
/* /*
@ -424,37 +312,21 @@ void idSoundHardware_OpenAL::Shutdown()
freeVoices.Clear(); freeVoices.Clear();
zombieVoices.Clear(); zombieVoices.Clear();
alcMakeContextCurrent( NULL );
alcDestroyContext( openalContext );
openalContext = NULL;
alcCloseDevice( openalDevice );
openalDevice = NULL;
// --------------------- // ---------------------
// Shutdown the Doom classic sound system. // Shutdown the Doom classic sound system.
// --------------------- // ---------------------
//I_ShutdownSoundHardware(); //I_ShutdownSoundHardware();
if( pXAudio2 != NULL ) /*
{
// Unregister the sound engine callback
pXAudio2->UnregisterForCallbacks( &soundEngineCallback );
}
if( pSubmixVoice != NULL )
{
pSubmixVoice->DestroyVoice();
pSubmixVoice = NULL;
}
if( pMasterVoice != NULL )
{
// release the vu meter effect
pMasterVoice->SetEffectChain( NULL );
pMasterVoice->DestroyVoice();
pMasterVoice = NULL;
}
if( pXAudio2 != NULL )
{
XAUDIO2_PERFORMANCE_DATA perfData;
pXAudio2->GetPerformanceData( &perfData );
idLib::Printf( "Final pXAudio2 performanceData: Voices: %d/%d CPU: %.2f%% Mem: %dkb\n", perfData.ActiveSourceVoiceCount, perfData.TotalSourceVoiceCount, perfData.AudioCyclesSinceLastQuery / ( float )perfData.TotalCyclesSinceLastQuery, perfData.MemoryUsageInBytes / 1024 );
pXAudio2->Release();
pXAudio2 = NULL;
}
if( vuMeterRMS != NULL ) if( vuMeterRMS != NULL )
{ {
console->DestroyGraph( vuMeterRMS ); console->DestroyGraph( vuMeterRMS );
@ -465,6 +337,7 @@ void idSoundHardware_OpenAL::Shutdown()
console->DestroyGraph( vuMeterPeak ); console->DestroyGraph( vuMeterPeak );
vuMeterPeak = NULL; vuMeterPeak = NULL;
} }
*/
} }
/* /*
@ -533,7 +406,7 @@ idSoundHardware_OpenAL::Update
*/ */
void idSoundHardware_OpenAL::Update() void idSoundHardware_OpenAL::Update()
{ {
if( pXAudio2 == NULL ) if( openalDevice == NULL )
{ {
int nowTime = Sys_Milliseconds(); int nowTime = Sys_Milliseconds();
if( lastResetTime + 1000 < nowTime ) if( lastResetTime + 1000 < nowTime )
@ -543,17 +416,16 @@ void idSoundHardware_OpenAL::Update()
} }
return; return;
} }
if( soundSystem->IsMuted() ) if( soundSystem->IsMuted() )
{ {
pMasterVoice->SetVolume( 0.0f, OPERATION_SET ); alListenerf( AL_GAIN, 0.0f );
} }
else else
{ {
pMasterVoice->SetVolume( DBtoLinear( s_volume_dB.GetFloat() ), OPERATION_SET ); alListenerf( AL_GAIN, DBtoLinear( s_volume_dB.GetFloat() ) );
} }
pXAudio2->CommitChanges( XAUDIO2_COMMIT_ALL );
// IXAudio2SourceVoice::Stop() has been called for every sound on the // IXAudio2SourceVoice::Stop() has been called for every sound on the
// zombie list, but it is documented as asyncronous, so we have to wait // zombie list, but it is documented as asyncronous, so we have to wait
// until it actually reports that it is no longer playing. // until it actually reports that it is no longer playing.
@ -573,13 +445,16 @@ void idSoundHardware_OpenAL::Update()
} }
} }
/*
if( s_showPerfData.GetBool() ) if( s_showPerfData.GetBool() )
{ {
XAUDIO2_PERFORMANCE_DATA perfData; XAUDIO2_PERFORMANCE_DATA perfData;
pXAudio2->GetPerformanceData( &perfData ); pXAudio2->GetPerformanceData( &perfData );
idLib::Printf( "Voices: %d/%d CPU: %.2f%% Mem: %dkb\n", perfData.ActiveSourceVoiceCount, perfData.TotalSourceVoiceCount, perfData.AudioCyclesSinceLastQuery / ( float )perfData.TotalCyclesSinceLastQuery, perfData.MemoryUsageInBytes / 1024 ); idLib::Printf( "Voices: %d/%d CPU: %.2f%% Mem: %dkb\n", perfData.ActiveSourceVoiceCount, perfData.TotalSourceVoiceCount, perfData.AudioCyclesSinceLastQuery / ( float )perfData.TotalCyclesSinceLastQuery, perfData.MemoryUsageInBytes / 1024 );
} }
*/
/*
if( vuMeterRMS == NULL ) if( vuMeterRMS == NULL )
{ {
// Init probably hasn't been called yet // Init probably hasn't been called yet
@ -642,6 +517,7 @@ void idSoundHardware_OpenAL::Update()
vuMeterPeakTimes[i] = currentTime + s_meterTopTime.GetInteger(); vuMeterPeakTimes[i] = currentTime + s_meterTopTime.GetInteger();
} }
} }
*/
} }
@ -656,7 +532,9 @@ idSoundEngineCallback
idSoundEngineCallback::OnCriticalError idSoundEngineCallback::OnCriticalError
======================== ========================
*/ */
/*
void idSoundEngineCallback::OnCriticalError( HRESULT Error ) void idSoundEngineCallback::OnCriticalError( HRESULT Error )
{ {
soundSystemLocal.SetNeedsRestart(); soundSystemLocal.SetNeedsRestart();
} }
*/

View file

@ -3,7 +3,7 @@
Doom 3 BFG Edition GPL Source Code Doom 3 BFG Edition GPL Source Code
Copyright (C) 1993-2012 id Software LLC, a ZeniMax Media company. Copyright (C) 1993-2012 id Software LLC, a ZeniMax Media company.
Copyright (C) 2012 Robert Beckebans Copyright (C) 2013 Robert Beckebans
This file is part of the Doom 3 BFG Edition GPL Source Code ("Doom 3 BFG Edition Source Code"). This file is part of the Doom 3 BFG Edition GPL Source Code ("Doom 3 BFG Edition Source Code").
@ -39,22 +39,24 @@ class idSoundHardware_OpenAL;
idSoundEngineCallback idSoundEngineCallback
================================================ ================================================
*/ */
/*
class idSoundEngineCallback : public IXAudio2EngineCallback class idSoundEngineCallback : public IXAudio2EngineCallback
{ {
public: public:
idSoundHardware_OpenAL* hardware; idSoundHardware_OpenAL* hardware;
private: private:
// Called by XAudio2 just before an audio processing pass begins. // Called by XAudio2 just before an audio processing pass begins.
STDMETHOD_( void, OnProcessingPassStart )( THIS ) {} STDMETHOD_( void, OnProcessingPassStart )( THIS ) {}
// Called just after an audio processing pass ends. // Called just after an audio processing pass ends.
STDMETHOD_( void, OnProcessingPassEnd )( THIS ) {} STDMETHOD_( void, OnProcessingPassEnd )( THIS ) {}
// Called in the event of a critical system error which requires XAudio2 // Called in the event of a critical system error which requires XAudio2
// to be closed down and restarted. The error code is given in Error. // to be closed down and restarted. The error code is given in Error.
STDMETHOD_( void, OnCriticalError )( THIS_ HRESULT Error ); STDMETHOD_( void, OnCriticalError )( THIS_ HRESULT Error );
}; };
*/
/* /*
================================================ ================================================
@ -76,10 +78,12 @@ public:
void FreeVoice( idSoundVoice* voice ); void FreeVoice( idSoundVoice* voice );
// video playback needs this // video playback needs this
/*
IXAudio2* GetIXAudio2() const IXAudio2* GetIXAudio2() const
{ {
return pXAudio2; return pXAudio2;
}; };
*/
int GetNumZombieVoices() const int GetNumZombieVoices() const
{ {
@ -95,19 +99,25 @@ protected:
friend class idSoundVoice_OpenAL; friend class idSoundVoice_OpenAL;
private: private:
/*
IXAudio2* pXAudio2; IXAudio2* pXAudio2;
IXAudio2MasteringVoice* pMasterVoice; IXAudio2MasteringVoice* pMasterVoice;
IXAudio2SubmixVoice* pSubmixVoice; IXAudio2SubmixVoice* pSubmixVoice;
idSoundEngineCallback soundEngineCallback; idSoundEngineCallback soundEngineCallback;
*/
ALCdevice* openalDevice;
ALCcontext* openalContext;
int lastResetTime; int lastResetTime;
int outputChannels; //int outputChannels;
int channelMask; //int channelMask;
idDebugGraph* vuMeterRMS; //idDebugGraph* vuMeterRMS;
idDebugGraph* vuMeterPeak; //idDebugGraph* vuMeterPeak;
int vuMeterPeakTimes[ 8 ]; //int vuMeterPeakTimes[ 8 ];
// Can't stop and start a voice on the same frame, so we have to double this to handle the worst case scenario of stopping all voices and starting a full new set // Can't stop and start a voice on the same frame, so we have to double this to handle the worst case scenario of stopping all voices and starting a full new set
idStaticList<idSoundVoice_OpenAL, MAX_HARDWARE_VOICES* 2 > voices; idStaticList<idSoundVoice_OpenAL, MAX_HARDWARE_VOICES* 2 > voices;

View file

@ -3,6 +3,7 @@
Doom 3 BFG Edition GPL Source Code Doom 3 BFG Edition GPL Source Code
Copyright (C) 1993-2012 id Software LLC, a ZeniMax Media company. Copyright (C) 1993-2012 id Software LLC, a ZeniMax Media company.
Copyright (C) 2013 Robert Beckebans
This file is part of the Doom 3 BFG Edition GPL Source Code ("Doom 3 BFG Edition Source Code"). This file is part of the Doom 3 BFG Edition GPL Source Code ("Doom 3 BFG Edition Source Code").
@ -455,7 +456,7 @@ void idSoundSample_OpenAL::MakeDefault()
format.basic.formatTag = idWaveFile::FORMAT_PCM; format.basic.formatTag = idWaveFile::FORMAT_PCM;
format.basic.numChannels = 1; format.basic.numChannels = 1;
format.basic.bitsPerSample = 16; format.basic.bitsPerSample = 16;
format.basic.samplesPerSec = XAUDIO2_MIN_SAMPLE_RATE; format.basic.samplesPerSec = 1000; //XAUDIO2_MIN_SAMPLE_RATE;
format.basic.blockSize = format.basic.numChannels * format.basic.bitsPerSample / 8; format.basic.blockSize = format.basic.numChannels * format.basic.bitsPerSample / 8;
format.basic.avgBytesPerSec = format.basic.samplesPerSec * format.basic.blockSize; format.basic.avgBytesPerSec = format.basic.samplesPerSec * format.basic.blockSize;

View file

@ -3,6 +3,7 @@
Doom 3 BFG Edition GPL Source Code Doom 3 BFG Edition GPL Source Code
Copyright (C) 1993-2012 id Software LLC, a ZeniMax Media company. Copyright (C) 1993-2012 id Software LLC, a ZeniMax Media company.
Copyright (C) 2013 Robert Beckebans
This file is part of the Doom 3 BFG Edition GPL Source Code ("Doom 3 BFG Edition Source Code"). This file is part of the Doom 3 BFG Edition GPL Source Code ("Doom 3 BFG Edition Source Code").

View file

@ -3,6 +3,7 @@
Doom 3 BFG Edition GPL Source Code Doom 3 BFG Edition GPL Source Code
Copyright (C) 1993-2012 id Software LLC, a ZeniMax Media company. Copyright (C) 1993-2012 id Software LLC, a ZeniMax Media company.
Copyright (C) 2013 Robert Beckebans
This file is part of the Doom 3 BFG Edition GPL Source Code ("Doom 3 BFG Edition Source Code"). This file is part of the Doom 3 BFG Edition GPL Source Code ("Doom 3 BFG Edition Source Code").
@ -30,7 +31,7 @@ If you have questions concerning this license or the applicable additional terms
#include "../snd_local.h" #include "../snd_local.h"
idCVar s_skipHardwareSets( "s_skipHardwareSets", "0", CVAR_BOOL, "Do all calculation, but skip XA2 calls" ); idCVar s_skipHardwareSets( "s_skipHardwareSets", "0", CVAR_BOOL, "Do all calculation, but skip XA2 calls" );
idCVar s_debugHardware( "s_debugHardware", "0", CVAR_BOOL, "Print a message any time a hardware voice changes" ); idCVar s_debugHardware( "s_debugHardware", "1", CVAR_BOOL, "Print a message any time a hardware voice changes" );
// The whole system runs at this sample rate // The whole system runs at this sample rate
static int SYSTEM_SAMPLE_RATE = 44100; static int SYSTEM_SAMPLE_RATE = 44100;
@ -41,6 +42,7 @@ static float ONE_OVER_SYSTEM_SAMPLE_RATE = 1.0f / SYSTEM_SAMPLE_RATE;
idStreamingVoiceContext idStreamingVoiceContext
======================== ========================
*/ */
/*
class idStreamingVoiceContext : public IXAudio2VoiceCallback class idStreamingVoiceContext : public IXAudio2VoiceCallback
{ {
public: public:
@ -63,6 +65,7 @@ public:
soundSystemLocal.ReleaseStreamBufferContext( bufferContext ); soundSystemLocal.ReleaseStreamBufferContext( bufferContext );
} }
} streamContext; } streamContext;
*/
/* /*
======================== ========================
@ -70,7 +73,7 @@ idSoundVoice_OpenAL::idSoundVoice_OpenAL
======================== ========================
*/ */
idSoundVoice_OpenAL::idSoundVoice_OpenAL() idSoundVoice_OpenAL::idSoundVoice_OpenAL()
: pSourceVoice( NULL ), : openalSource( 0 ),
leadinSample( NULL ), leadinSample( NULL ),
loopingSample( NULL ), loopingSample( NULL ),
formatTag( 0 ), formatTag( 0 ),
@ -99,11 +102,12 @@ idSoundVoice_OpenAL::CompatibleFormat
*/ */
bool idSoundVoice_OpenAL::CompatibleFormat( idSoundSample_OpenAL* s ) bool idSoundVoice_OpenAL::CompatibleFormat( idSoundSample_OpenAL* s )
{ {
if( pSourceVoice == NULL ) if( alIsSource( openalSource ) )
{ {
// If this voice has never been allocated, then it's compatible with everything // If this voice has never been allocated, then it's compatible with everything
return true; return true;
} }
return false; return false;
} }
@ -120,10 +124,11 @@ void idSoundVoice_OpenAL::Create( const idSoundSample* leadinSample_, const idSo
Stop(); Stop();
return; return;
} }
leadinSample = ( idSoundSample_OpenAL* )leadinSample_; leadinSample = ( idSoundSample_OpenAL* )leadinSample_;
loopingSample = ( idSoundSample_OpenAL* )loopingSample_; loopingSample = ( idSoundSample_OpenAL* )loopingSample_;
if( pSourceVoice != NULL && CompatibleFormat( leadinSample ) ) if( alIsSource( openalSource ) && CompatibleFormat( leadinSample ) )
{ {
sampleRate = leadinSample->format.basic.samplesPerSec; sampleRate = leadinSample->format.basic.samplesPerSec;
} }
@ -134,27 +139,41 @@ void idSoundVoice_OpenAL::Create( const idSoundSample* leadinSample_, const idSo
numChannels = leadinSample->format.basic.numChannels; numChannels = leadinSample->format.basic.numChannels;
sampleRate = leadinSample->format.basic.samplesPerSec; sampleRate = leadinSample->format.basic.samplesPerSec;
soundSystemLocal.hardware.pXAudio2->CreateSourceVoice( &pSourceVoice, ( const WAVEFORMATEX* )&leadinSample->format, XAUDIO2_VOICE_USEFILTER, 4.0f, &streamContext ); //soundSystemLocal.hardware.pXAudio2->CreateSourceVoice( &pSourceVoice, ( const WAVEFORMATEX* )&leadinSample->format, XAUDIO2_VOICE_USEFILTER, 4.0f, &streamContext );
if( pSourceVoice == NULL )
alGetError();
alGenSources( 1, &openalSource );
if( alGetError() != AL_NO_ERROR )
//if( pSourceVoice == NULL )
{ {
// If this hits, then we are most likely passing an invalid sample format, which should have been caught by the loader (and the sample defaulted) // If this hits, then we are most likely passing an invalid sample format, which should have been caught by the loader (and the sample defaulted)
return; return;
} }
alSourcef( openalSource, AL_ROLLOFF_FACTOR, 0.0f );
if( s_debugHardware.GetBool() ) if( s_debugHardware.GetBool() )
{ {
if( loopingSample == NULL || loopingSample == leadinSample ) if( loopingSample == NULL || loopingSample == leadinSample )
{ {
idLib::Printf( "%dms: %p created for %s\n", Sys_Milliseconds(), pSourceVoice, leadinSample ? leadinSample->GetName() : "<null>" ); idLib::Printf( "%dms: %i created for %s\n", Sys_Milliseconds(), openalSource, leadinSample ? leadinSample->GetName() : "<null>" );
} }
else else
{ {
idLib::Printf( "%dms: %p created for %s and %s\n", Sys_Milliseconds(), pSourceVoice, leadinSample ? leadinSample->GetName() : "<null>", loopingSample ? loopingSample->GetName() : "<null>" ); idLib::Printf( "%dms: %i created for %s and %s\n", Sys_Milliseconds(), openalSource, leadinSample ? leadinSample->GetName() : "<null>", loopingSample ? loopingSample->GetName() : "<null>" );
} }
} }
} }
sourceVoiceRate = sampleRate; sourceVoiceRate = sampleRate;
pSourceVoice->SetSourceSampleRate( sampleRate ); //pSourceVoice->SetSourceSampleRate( sampleRate );
pSourceVoice->SetVolume( 0.0f ); //pSourceVoice->SetVolume( 0.0f );
alSourcei( openalSource, AL_SOURCE_RELATIVE, AL_TRUE );
alSource3f( openalSource, AL_POSITION, 0.0f, 0.0f, 0.0f );
// RB: FIXME 0.0f ?
alSourcef( openalSource, AL_GAIN, 1.0f );
} }
/* /*
@ -164,14 +183,16 @@ idSoundVoice_OpenAL::DestroyInternal
*/ */
void idSoundVoice_OpenAL::DestroyInternal() void idSoundVoice_OpenAL::DestroyInternal()
{ {
if( pSourceVoice != NULL ) if( alIsSource( openalSource ) )
{ {
if( s_debugHardware.GetBool() ) if( s_debugHardware.GetBool() )
{ {
idLib::Printf( "%dms: %p destroyed\n", Sys_Milliseconds(), pSourceVoice ); idLib::Printf( "%dms: %i destroyed\n", Sys_Milliseconds(), openalSource );
} }
pSourceVoice->DestroyVoice();
pSourceVoice = NULL; alDeleteSources( 1, &openalSource );
openalSource = 0;
hasVUMeter = false; hasVUMeter = false;
} }
} }
@ -183,17 +204,17 @@ idSoundVoice_OpenAL::Start
*/ */
void idSoundVoice_OpenAL::Start( int offsetMS, int ssFlags ) void idSoundVoice_OpenAL::Start( int offsetMS, int ssFlags )
{ {
if( s_debugHardware.GetBool() ) if( s_debugHardware.GetBool() )
{ {
idLib::Printf( "%dms: %p starting %s @ %dms\n", Sys_Milliseconds(), pSourceVoice, leadinSample ? leadinSample->GetName() : "<null>", offsetMS ); idLib::Printf( "%dms: %i starting %s @ %dms\n", Sys_Milliseconds(), openalSource, leadinSample ? leadinSample->GetName() : "<null>", offsetMS );
} }
if( !leadinSample ) if( !leadinSample )
{ {
return; return;
} }
if( !pSourceVoice )
if( !alIsSource( openalSource ) )
{ {
return; return;
} }
@ -209,23 +230,25 @@ void idSoundVoice_OpenAL::Start( int offsetMS, int ssFlags )
{ {
hasVUMeter = flicker; hasVUMeter = flicker;
/*
if( flicker ) if( flicker )
{ {
IUnknown* vuMeter = NULL; IUnknown* vuMeter = NULL;
if( XAudio2CreateVolumeMeter( &vuMeter, 0 ) == S_OK ) if( XAudio2CreateVolumeMeter( &vuMeter, 0 ) == S_OK )
{ {
XAUDIO2_EFFECT_DESCRIPTOR descriptor; XAUDIO2_EFFECT_DESCRIPTOR descriptor;
descriptor.InitialState = true; descriptor.InitialState = true;
descriptor.OutputChannels = leadinSample->NumChannels(); descriptor.OutputChannels = leadinSample->NumChannels();
descriptor.pEffect = vuMeter; descriptor.pEffect = vuMeter;
XAUDIO2_EFFECT_CHAIN chain; XAUDIO2_EFFECT_CHAIN chain;
chain.EffectCount = 1; chain.EffectCount = 1;
chain.pEffectDescriptors = &descriptor; chain.pEffectDescriptors = &descriptor;
pSourceVoice->SetEffectChain( &chain ); pSourceVoice->SetEffectChain( &chain );
vuMeter->Release(); vuMeter->Release();
} }
} }
@ -233,6 +256,7 @@ void idSoundVoice_OpenAL::Start( int offsetMS, int ssFlags )
{ {
pSourceVoice->SetEffectChain( NULL ); pSourceVoice->SetEffectChain( NULL );
} }
*/
} }
assert( offsetMS >= 0 ); assert( offsetMS >= 0 );
@ -290,11 +314,11 @@ idSoundVoice_OpenAL::SubmitBuffer
*/ */
int idSoundVoice_OpenAL::SubmitBuffer( idSoundSample_OpenAL* sample, int bufferNumber, int offset ) int idSoundVoice_OpenAL::SubmitBuffer( idSoundSample_OpenAL* sample, int bufferNumber, int offset )
{ {
if( sample == NULL || ( bufferNumber < 0 ) || ( bufferNumber >= sample->buffers.Num() ) ) if( sample == NULL || ( bufferNumber < 0 ) || ( bufferNumber >= sample->buffers.Num() ) )
{ {
return 0; return 0;
} }
idSoundSystemLocal::bufferContext_t* bufferContext = soundSystemLocal.ObtainStreamBufferContext(); idSoundSystemLocal::bufferContext_t* bufferContext = soundSystemLocal.ObtainStreamBufferContext();
if( bufferContext == NULL ) if( bufferContext == NULL )
{ {
@ -306,6 +330,11 @@ int idSoundVoice_OpenAL::SubmitBuffer( idSoundSample_OpenAL* sample, int bufferN
bufferContext->sample = sample; bufferContext->sample = sample;
bufferContext->bufferNumber = bufferNumber; bufferContext->bufferNumber = bufferNumber;
// TODO openal stream
return 0;
/*
XAUDIO2_BUFFER buffer = { 0 }; XAUDIO2_BUFFER buffer = { 0 };
if( offset > 0 ) if( offset > 0 )
{ {
@ -327,6 +356,8 @@ int idSoundVoice_OpenAL::SubmitBuffer( idSoundSample_OpenAL* sample, int bufferN
pSourceVoice->SubmitSourceBuffer( &buffer ); pSourceVoice->SubmitSourceBuffer( &buffer );
return buffer.AudioBytes; return buffer.AudioBytes;
*/
} }
/* /*
@ -336,6 +367,7 @@ idSoundVoice_OpenAL::Update
*/ */
bool idSoundVoice_OpenAL::Update() bool idSoundVoice_OpenAL::Update()
{ {
/*
if( pSourceVoice == NULL || leadinSample == NULL ) if( pSourceVoice == NULL || leadinSample == NULL )
{ {
return false; return false;
@ -363,6 +395,7 @@ bool idSoundVoice_OpenAL::Update()
// we don't do this any longer because we pause and unpause explicitly when the soundworld is paused or unpaused // we don't do this any longer because we pause and unpause explicitly when the soundworld is paused or unpaused
// UnPause(); // UnPause();
*/
return true; return true;
} }
@ -373,13 +406,21 @@ idSoundVoice_OpenAL::IsPlaying
*/ */
bool idSoundVoice_OpenAL::IsPlaying() bool idSoundVoice_OpenAL::IsPlaying()
{ {
if( pSourceVoice == NULL ) if( !alIsSource( openalSource ) )
{ {
return false; return false;
} }
XAUDIO2_VOICE_STATE state;
pSourceVoice->GetState( &state ); ALint state = AL_INITIAL;
return ( state.BuffersQueued != 0 );
alGetSourcei( openalSource, AL_SOURCE_STATE, &state );
return ( state == AL_PLAYING );
//XAUDIO2_VOICE_STATE state;
//pSourceVoice->GetState( &state );
//return ( state.BuffersQueued != 0 );
} }
/* /*
@ -389,9 +430,9 @@ idSoundVoice_OpenAL::FlushSourceBuffers
*/ */
void idSoundVoice_OpenAL::FlushSourceBuffers() void idSoundVoice_OpenAL::FlushSourceBuffers()
{ {
if( pSourceVoice != NULL ) if( alIsSource( openalSource ) )
{ {
pSourceVoice->FlushSourceBuffers(); //pSourceVoice->FlushSourceBuffers();
} }
} }
@ -402,15 +443,18 @@ idSoundVoice_OpenAL::Pause
*/ */
void idSoundVoice_OpenAL::Pause() void idSoundVoice_OpenAL::Pause()
{ {
if( !pSourceVoice || paused ) if( !alIsSource( openalSource ) || paused )
{ {
return; return;
} }
if( s_debugHardware.GetBool() ) if( s_debugHardware.GetBool() )
{ {
idLib::Printf( "%dms: %p pausing %s\n", Sys_Milliseconds(), pSourceVoice, leadinSample ? leadinSample->GetName() : "<null>" ); idLib::Printf( "%dms: %i pausing %s\n", Sys_Milliseconds(), openalSource, leadinSample ? leadinSample->GetName() : "<null>" );
} }
pSourceVoice->Stop( 0, OPERATION_SET );
alSourcePause( openalSource );
//pSourceVoice->Stop( 0, OPERATION_SET );
paused = true; paused = true;
} }
@ -421,15 +465,18 @@ idSoundVoice_OpenAL::UnPause
*/ */
void idSoundVoice_OpenAL::UnPause() void idSoundVoice_OpenAL::UnPause()
{ {
if( !pSourceVoice || !paused ) if( !alIsSource( openalSource ) || !paused )
{ {
return; return;
} }
if( s_debugHardware.GetBool() ) if( s_debugHardware.GetBool() )
{ {
idLib::Printf( "%dms: %p unpausing %s\n", Sys_Milliseconds(), pSourceVoice, leadinSample ? leadinSample->GetName() : "<null>" ); idLib::Printf( "%dms: %i unpausing %s\n", Sys_Milliseconds(), openalSource, leadinSample ? leadinSample->GetName() : "<null>" );
} }
pSourceVoice->Start( 0, OPERATION_SET );
alSourcePlay( openalSource );
//pSourceVoice->Start( 0, OPERATION_SET );
paused = false; paused = false;
} }
@ -440,17 +487,22 @@ idSoundVoice_OpenAL::Stop
*/ */
void idSoundVoice_OpenAL::Stop() void idSoundVoice_OpenAL::Stop()
{ {
if( !pSourceVoice ) if( !alIsSource( openalSource ) )
{ {
return; return;
} }
if( !paused ) if( !paused )
{ {
if( s_debugHardware.GetBool() ) if( s_debugHardware.GetBool() )
{ {
idLib::Printf( "%dms: %p stopping %s\n", Sys_Milliseconds(), pSourceVoice, leadinSample ? leadinSample->GetName() : "<null>" ); idLib::Printf( "%dms: %i stopping %s\n", Sys_Milliseconds(), openalSource, leadinSample ? leadinSample->GetName() : "<null>" );
} }
pSourceVoice->Stop( 0, OPERATION_SET );
alSourceStop( openalSource );
alSourcei( openalSource, AL_BUFFER, 0 );
//pSourceVoice->Stop( 0, OPERATION_SET );
paused = true; paused = true;
} }
} }
@ -462,6 +514,10 @@ idSoundVoice_OpenAL::GetAmplitude
*/ */
float idSoundVoice_OpenAL::GetAmplitude() float idSoundVoice_OpenAL::GetAmplitude()
{ {
// TODO
return 1.0f;
/*
if( !hasVUMeter ) if( !hasVUMeter )
{ {
return 1.0f; return 1.0f;
@ -497,6 +553,7 @@ float idSoundVoice_OpenAL::GetAmplitude()
} }
return rms / ( float )levels.ChannelCount; return rms / ( float )levels.ChannelCount;
*/
} }
/* /*
@ -506,6 +563,7 @@ idSoundVoice_OpenAL::ResetSampleRate
*/ */
void idSoundVoice_OpenAL::SetSampleRate( uint32 newSampleRate, uint32 operationSet ) void idSoundVoice_OpenAL::SetSampleRate( uint32 newSampleRate, uint32 operationSet )
{ {
/*
if( pSourceVoice == NULL || leadinSample == NULL ) if( pSourceVoice == NULL || leadinSample == NULL )
{ {
return; return;
@ -543,7 +601,9 @@ void idSoundVoice_OpenAL::SetSampleRate( uint32 newSampleRate, uint32 operationS
{ {
assert( freqRatio * ( float )SYSTEM_SAMPLE_RATE <= XAUDIO2_MAX_RATIO_TIMES_RATE_XMA_MULTICHANNEL ); assert( freqRatio * ( float )SYSTEM_SAMPLE_RATE <= XAUDIO2_MAX_RATIO_TIMES_RATE_XMA_MULTICHANNEL );
} }
pSourceVoice->SetFrequencyRatio( freqRatio, operationSet ); pSourceVoice->SetFrequencyRatio( freqRatio, operationSet );
*/
} }
/* /*
@ -553,7 +613,7 @@ idSoundVoice_OpenAL::OnBufferStart
*/ */
void idSoundVoice_OpenAL::OnBufferStart( idSoundSample_OpenAL* sample, int bufferNumber ) void idSoundVoice_OpenAL::OnBufferStart( idSoundSample_OpenAL* sample, int bufferNumber )
{ {
SetSampleRate( sample->SampleRate(), XAUDIO2_COMMIT_NOW ); //SetSampleRate( sample->SampleRate(), XAUDIO2_COMMIT_NOW );
idSoundSample_OpenAL* nextSample = sample; idSoundSample_OpenAL* nextSample = sample;
int nextBuffer = bufferNumber + 1; int nextBuffer = bufferNumber + 1;

View file

@ -3,6 +3,7 @@
Doom 3 BFG Edition GPL Source Code Doom 3 BFG Edition GPL Source Code
Copyright (C) 1993-2012 id Software LLC, a ZeniMax Media company. Copyright (C) 1993-2012 id Software LLC, a ZeniMax Media company.
Copyright (C) 2013 Robert Beckebans
This file is part of the Doom 3 BFG Edition GPL Source Code ("Doom 3 BFG Edition Source Code"). This file is part of the Doom 3 BFG Edition GPL Source Code ("Doom 3 BFG Edition Source Code").
@ -51,6 +52,7 @@ public:
// Stop consuming buffers // Stop consuming buffers
void Pause(); void Pause();
// Start consuming buffers again // Start consuming buffers again
void UnPause(); void UnPause();
@ -92,9 +94,11 @@ private:
// Adjust the voice frequency based on the new sample rate for the buffer // Adjust the voice frequency based on the new sample rate for the buffer
void SetSampleRate( uint32 newSampleRate, uint32 operationSet ); void SetSampleRate( uint32 newSampleRate, uint32 operationSet );
IXAudio2SourceVoice* pSourceVoice; //IXAudio2SourceVoice* pSourceVoice;
idSoundSample_OpenAL* leadinSample; ALuint openalSource;
idSoundSample_OpenAL* loopingSample;
idSoundSample_OpenAL* leadinSample;
idSoundSample_OpenAL* loopingSample;
// These are the fields from the sample format that matter to us for voice reuse // These are the fields from the sample format that matter to us for voice reuse
uint16 formatTag; uint16 formatTag;

View file

@ -97,6 +97,16 @@ typedef enum
#define OPERATION_SET 1 #define OPERATION_SET 1
#if defined(USE_OPENAL)
#include <AL/al.h>
#include <AL/alc.h>
#include "OpenAL/AL_SoundSample.h"
#include "OpenAL/AL_SoundVoice.h"
#include "OpenAL/AL_SoundHardware.h"
#else
// RB: not available on Windows 8 SDK // RB: not available on Windows 8 SDK
#if (_WIN32_WINNT < 0x0602 /*_WIN32_WINNT_WIN8*/) #if (_WIN32_WINNT < 0x0602 /*_WIN32_WINNT_WIN8*/)
#include <dxsdkver.h> #include <dxsdkver.h>
@ -112,11 +122,6 @@ typedef enum
#include <xma2defs.h> #include <xma2defs.h>
#endif #endif
#if defined(USE_OPENAL)
#include "OpenAL/AL_SoundSample.h"
#include "OpenAL/AL_SoundVoice.h"
#include "OpenAL/AL_SoundHardware.h"
#else
#include "XAudio2/XA2_SoundSample.h" #include "XAudio2/XA2_SoundSample.h"
#include "XAudio2/XA2_SoundVoice.h" #include "XAudio2/XA2_SoundVoice.h"
#include "XAudio2/XA2_SoundHardware.h" #include "XAudio2/XA2_SoundHardware.h"

View file

@ -3,6 +3,7 @@
Doom 3 BFG Edition GPL Source Code Doom 3 BFG Edition GPL Source Code
Copyright (C) 1993-2012 id Software LLC, a ZeniMax Media company. Copyright (C) 1993-2012 id Software LLC, a ZeniMax Media company.
Copyright (C) 2013 Robert Beckebans
This file is part of the Doom 3 BFG Edition GPL Source Code ("Doom 3 BFG Edition Source Code"). This file is part of the Doom 3 BFG Edition GPL Source Code ("Doom 3 BFG Edition Source Code").
@ -389,7 +390,13 @@ idSoundSystemLocal::GetIXAudio2
*/ */
void* idSoundSystemLocal::GetIXAudio2() const void* idSoundSystemLocal::GetIXAudio2() const
{ {
// RB begin
#if defined(USE_OPENAL)
return NULL;
#else
return ( void* )hardware.GetIXAudio2(); return ( void* )hardware.GetIXAudio2();
#endif
// RB end
} }
/* /*