From 4884cc5793b54e9e077e98b428ce98cf0d99cb12 Mon Sep 17 00:00:00 2001 From: Robert Beckebans Date: Sun, 6 Jan 2013 13:03:56 +0100 Subject: [PATCH] Fixed OpenAL bug when deleting the OpenAL buffers that caused the game to hang. --- neo/sound/OpenAL/AL_SoundHardware.cpp | 208 +++++++++++--------------- neo/sound/OpenAL/AL_SoundHardware.h | 13 +- neo/sound/OpenAL/AL_SoundSample.cpp | 21 +-- neo/sound/OpenAL/AL_SoundVoice.cpp | 17 ++- neo/sound/snd_local.h | 26 ++++ neo/sound/snd_system.cpp | 16 ++ neo/sound/sound.h | 4 + 7 files changed, 161 insertions(+), 144 deletions(-) diff --git a/neo/sound/OpenAL/AL_SoundHardware.cpp b/neo/sound/OpenAL/AL_SoundHardware.cpp index 47c503a3..3c28e34a 100644 --- a/neo/sound/OpenAL/AL_SoundHardware.cpp +++ b/neo/sound/OpenAL/AL_SoundHardware.cpp @@ -4,6 +4,7 @@ Doom 3 BFG Edition GPL Source Code Copyright (C) 1993-2012 id Software LLC, a ZeniMax Media company. Copyright (C) 2013 Robert Beckebans +Copyright (c) 2010 by Chris Robinson (OpenAL Info Utility) This file is part of the Doom 3 BFG Edition GPL Source Code ("Doom 3 BFG Edition Source Code"). @@ -61,135 +62,98 @@ idSoundHardware_OpenAL::idSoundHardware_OpenAL() lastResetTime = 0; } +void idSoundHardware_OpenAL::PrintDeviceList( const char* list ) +{ + if( !list || *list == '\0' ) + { + idLib::Printf( " !!! none !!!\n" ); + } + else + { + do + { + idLib::Printf( " %s\n", list ); + list += strlen( list ) + 1; + } + while( *list != '\0' ); + } +} + +void idSoundHardware_OpenAL::PrintALCInfo( ALCdevice* device ) +{ + ALCint major, minor; + + if( device ) + { + const ALCchar* devname = NULL; + idLib::Printf( "\n" ); + if( alcIsExtensionPresent( device, "ALC_ENUMERATE_ALL_EXT" ) != AL_FALSE ) + { + devname = alcGetString( device, ALC_ALL_DEVICES_SPECIFIER ); + } + + if( CheckALCErrors( device ) != ALC_NO_ERROR || !devname ) + { + devname = alcGetString( device, ALC_DEVICE_SPECIFIER ); + } + + idLib::Printf( "** Info for device \"%s\" **\n", devname ); + } + alcGetIntegerv( device, ALC_MAJOR_VERSION, 1, &major ); + alcGetIntegerv( device, ALC_MINOR_VERSION, 1, &minor ); + + if( CheckALCErrors( device ) == ALC_NO_ERROR ) + idLib::Printf( "ALC version: %d.%d\n", major, minor ); + + if( device ) + { + idLib::Printf( "OpenAL extensions: %s", alGetString( AL_EXTENSIONS ) ); + + //idLib::Printf("ALC extensions:"); + //printList(alcGetString(device, ALC_EXTENSIONS), ' '); + CheckALCErrors( device ); + } +} + +void idSoundHardware_OpenAL::PrintALInfo() +{ + idLib::Printf( "OpenAL vendor string: %s\n", alGetString( AL_VENDOR ) ); + idLib::Printf( "OpenAL renderer string: %s\n", alGetString( AL_RENDERER ) ); + idLib::Printf( "OpenAL version string: %s\n", alGetString( AL_VERSION ) ); + idLib::Printf( "OpenAL extensions: %s", alGetString( AL_EXTENSIONS ) ); + //PrintList(alGetString(AL_EXTENSIONS), ' '); + CheckALErrors(); +} + void listDevices_f( const idCmdArgs& args ) { -#if 1 - // TODO - - idLib::Warning( "No audio devices found" ); - return; -#else - UINT32 deviceCount = 0; - if( pXAudio2->GetDeviceCount( &deviceCount ) != S_OK || deviceCount == 0 ) + idLib::Printf( "Available playback devices:\n" ); + if( alcIsExtensionPresent( NULL, "ALC_ENUMERATE_ALL_EXT" ) != AL_FALSE ) { - idLib::Warning( "No audio devices found" ); - return; + idSoundHardware_OpenAL::PrintDeviceList( alcGetString( NULL, ALC_ALL_DEVICES_SPECIFIER ) ); + } + else + { + idSoundHardware_OpenAL::PrintDeviceList( alcGetString( NULL, ALC_DEVICE_SPECIFIER ) ); } - for( unsigned int i = 0; i < deviceCount; i++ ) + //idLib::Printf("Available capture devices:\n"); + //printDeviceList(alcGetString(NULL, ALC_CAPTURE_DEVICE_SPECIFIER)); + + if( alcIsExtensionPresent( NULL, "ALC_ENUMERATE_ALL_EXT" ) != AL_FALSE ) { - XAUDIO2_DEVICE_DETAILS deviceDetails; - if( pXAudio2->GetDeviceDetails( i, &deviceDetails ) != S_OK ) - { - continue; - } - idStaticList< const char*, 5 > roles; - if( deviceDetails.Role & DefaultConsoleDevice ) - { - roles.Append( "Console Device" ); - } - if( deviceDetails.Role & DefaultMultimediaDevice ) - { - roles.Append( "Multimedia Device" ); - } - if( deviceDetails.Role & DefaultCommunicationsDevice ) - { - roles.Append( "Communications Device" ); - } - if( deviceDetails.Role & DefaultGameDevice ) - { - roles.Append( "Game Device" ); - } - idStaticList< const char*, 11 > channelNames; - if( deviceDetails.OutputFormat.dwChannelMask & SPEAKER_FRONT_LEFT ) - { - channelNames.Append( "Front Left" ); - } - if( deviceDetails.OutputFormat.dwChannelMask & SPEAKER_FRONT_RIGHT ) - { - channelNames.Append( "Front Right" ); - } - if( deviceDetails.OutputFormat.dwChannelMask & SPEAKER_FRONT_CENTER ) - { - channelNames.Append( "Front Center" ); - } - if( deviceDetails.OutputFormat.dwChannelMask & SPEAKER_LOW_FREQUENCY ) - { - channelNames.Append( "Low Frequency" ); - } - if( deviceDetails.OutputFormat.dwChannelMask & SPEAKER_BACK_LEFT ) - { - channelNames.Append( "Back Left" ); - } - if( deviceDetails.OutputFormat.dwChannelMask & SPEAKER_BACK_RIGHT ) - { - channelNames.Append( "Back Right" ); - } - if( deviceDetails.OutputFormat.dwChannelMask & SPEAKER_FRONT_LEFT_OF_CENTER ) - { - channelNames.Append( "Front Left of Center" ); - } - if( deviceDetails.OutputFormat.dwChannelMask & SPEAKER_FRONT_RIGHT_OF_CENTER ) - { - channelNames.Append( "Front Right of Center" ); - } - if( deviceDetails.OutputFormat.dwChannelMask & SPEAKER_BACK_CENTER ) - { - channelNames.Append( "Back Center" ); - } - if( deviceDetails.OutputFormat.dwChannelMask & SPEAKER_SIDE_LEFT ) - { - channelNames.Append( "Side Left" ); - } - if( deviceDetails.OutputFormat.dwChannelMask & SPEAKER_SIDE_RIGHT ) - { - channelNames.Append( "Side Right" ); - } - char mbcsDisplayName[ 256 ]; - wcstombs( mbcsDisplayName, deviceDetails.DisplayName, sizeof( mbcsDisplayName ) ); - idLib::Printf( "%3d: %s\n", i, mbcsDisplayName ); - idLib::Printf( " %d channels, %d Hz\n", deviceDetails.OutputFormat.Format.nChannels, deviceDetails.OutputFormat.Format.nSamplesPerSec ); - if( channelNames.Num() != deviceDetails.OutputFormat.Format.nChannels ) - { - idLib::Printf( S_COLOR_YELLOW "WARNING: " S_COLOR_RED "Mismatch between # of channels and channel mask\n" ); - } - if( channelNames.Num() == 1 ) - { - idLib::Printf( " %s\n", channelNames[0] ); - } - else if( channelNames.Num() == 2 ) - { - idLib::Printf( " %s and %s\n", channelNames[0], channelNames[1] ); - } - else if( channelNames.Num() > 2 ) - { - idLib::Printf( " %s", channelNames[0] ); - for( int i = 1; i < channelNames.Num() - 1; i++ ) - { - idLib::Printf( ", %s", channelNames[i] ); - } - idLib::Printf( ", and %s\n", channelNames[channelNames.Num() - 1] ); - } - if( roles.Num() == 1 ) - { - idLib::Printf( " Default %s\n", roles[0] ); - } - else if( roles.Num() == 2 ) - { - idLib::Printf( " Default %s and %s\n", roles[0], roles[1] ); - } - else if( roles.Num() > 2 ) - { - idLib::Printf( " Default %s", roles[0] ); - for( int i = 1; i < roles.Num() - 1; i++ ) - { - idLib::Printf( ", %s", roles[i] ); - } - idLib::Printf( ", and %s\n", roles[roles.Num() - 1] ); - } + idLib::Printf( "Default playback device: %s\n", alcGetString( NULL, ALC_DEFAULT_ALL_DEVICES_SPECIFIER ) ); } -#endif -// RB end + else + { + idLib::Printf( "Default playback device: %s\n", alcGetString( NULL, ALC_DEFAULT_DEVICE_SPECIFIER ) ); + } + + //idLib::Printf("Default capture device: %s\n", alcGetString(NULL, ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER)); + + idSoundHardware_OpenAL::PrintALCInfo( NULL ); + + idSoundHardware_OpenAL::PrintALCInfo( ( ALCdevice* )soundSystem->GetOpenALDevice() ); } /* diff --git a/neo/sound/OpenAL/AL_SoundHardware.h b/neo/sound/OpenAL/AL_SoundHardware.h index e828e43f..49d389d3 100644 --- a/neo/sound/OpenAL/AL_SoundHardware.h +++ b/neo/sound/OpenAL/AL_SoundHardware.h @@ -77,13 +77,11 @@ public: idSoundVoice* AllocateVoice( const idSoundSample* leadinSample, const idSoundSample* loopingSample ); void FreeVoice( idSoundVoice* voice ); - // video playback needs this - /* - IXAudio2* GetIXAudio2() const + // listDevices needs this + ALCdevice* GetOpenALDevice() const { - return pXAudio2; + return openalDevice; }; - */ int GetNumZombieVoices() const { @@ -94,6 +92,11 @@ public: return freeVoices.Num(); } + // OpenAL info + static void PrintDeviceList( const char* list ); + static void PrintALCInfo( ALCdevice* device ); + static void PrintALInfo(); + protected: friend class idSoundSample_OpenAL; friend class idSoundVoice_OpenAL; diff --git a/neo/sound/OpenAL/AL_SoundSample.cpp b/neo/sound/OpenAL/AL_SoundSample.cpp index d9758c25..fb8d2e6f 100644 --- a/neo/sound/OpenAL/AL_SoundSample.cpp +++ b/neo/sound/OpenAL/AL_SoundSample.cpp @@ -280,17 +280,17 @@ void idSoundSample_OpenAL::LoadResource() void idSoundSample_OpenAL::CreateOpenALBuffer() { // build OpenAL buffer - alGetError(); + CheckALErrors(); alGenBuffers( 1, &openalBuffer ); - if( alGetError() != AL_NO_ERROR ) + if( CheckALErrors() != AL_NO_ERROR ) { common->Error( "idSoundSample_OpenAL::CreateOpenALBuffer: error generating OpenAL hardware buffer" ); } if( alIsBuffer( openalBuffer ) ) { - alGetError(); + CheckALErrors(); // RB: TODO decode idWaveFile::FORMAT_ADPCM to idWaveFile::FORMAT_PCM // and build one big OpenAL buffer using the alBufferSubData extension @@ -352,7 +352,7 @@ void idSoundSample_OpenAL::CreateOpenALBuffer() alBufferData( openalBuffer, GetOpenALBufferFormat(), buffer, bufferSize, format.basic.samplesPerSec ); } - if( alGetError() != AL_NO_ERROR ) + if( CheckALErrors() != AL_NO_ERROR ) { common->Error( "idSoundSample_OpenAL::CreateOpenALBuffer: error loading data into OpenAL hardware buffer" ); } @@ -579,19 +579,19 @@ void idSoundSample_OpenAL::MakeDefault() playLength = DEFAULT_NUM_SAMPLES; - alGetError(); + CheckALErrors(); alGenBuffers( 1, &openalBuffer ); - if( alGetError() != AL_NO_ERROR ) + if( CheckALErrors() != AL_NO_ERROR ) { common->Error( "idSoundSample_OpenAL::MakeDefault: error generating OpenAL hardware buffer" ); } if( alIsBuffer( openalBuffer ) ) { - alGetError(); + CheckALErrors(); alBufferData( openalBuffer, GetOpenALBufferFormat(), defaultBuffer, totalBufferSize, format.basic.samplesPerSec ); - if( alGetError() != AL_NO_ERROR ) + if( CheckALErrors() != AL_NO_ERROR ) { common->Error( "idSoundSample_OpenAL::MakeDefault: error loading data into OpenAL hardware buffer" ); } @@ -627,9 +627,10 @@ void idSoundSample_OpenAL::FreeData() if( alIsBuffer( openalBuffer ) ) { - alGetError(); + CheckALErrors(); + alDeleteBuffers( 1, &openalBuffer ); - if( alGetError() != AL_NO_ERROR ) + if( CheckALErrors() != AL_NO_ERROR ) { common->Error( "idSoundSample_OpenAL::FreeData: error unloading data from OpenAL hardware buffer" ); } diff --git a/neo/sound/OpenAL/AL_SoundVoice.cpp b/neo/sound/OpenAL/AL_SoundVoice.cpp index e734d7a7..8f403650 100644 --- a/neo/sound/OpenAL/AL_SoundVoice.cpp +++ b/neo/sound/OpenAL/AL_SoundVoice.cpp @@ -145,9 +145,10 @@ void idSoundVoice_OpenAL::Create( const idSoundSample* leadinSample_, const idSo //soundSystemLocal.hardware.pXAudio2->CreateSourceVoice( &pSourceVoice, ( const WAVEFORMATEX* )&leadinSample->format, XAUDIO2_VOICE_USEFILTER, 4.0f, &streamContext ); - alGetError(); + CheckALErrors(); + alGenSources( 1, &openalSource ); - if( alGetError() != AL_NO_ERROR ) + if( CheckALErrors() != 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) @@ -568,9 +569,10 @@ void idSoundVoice_OpenAL::FlushSourceBuffers() if( openalStreamingBuffer[0] && openalStreamingBuffer[1] && openalStreamingBuffer[2] ) { - alGetError(); + CheckALErrors(); + alDeleteBuffers( 3, &openalStreamingBuffer[0] ); - if( alGetError() == AL_NO_ERROR ) + if( CheckALErrors() == AL_NO_ERROR ) { openalStreamingBuffer[0] = openalStreamingBuffer[1] = openalStreamingBuffer[2] = 0; } @@ -578,9 +580,10 @@ void idSoundVoice_OpenAL::FlushSourceBuffers() if( lastopenalStreamingBuffer[0] && lastopenalStreamingBuffer[1] && lastopenalStreamingBuffer[2] ) { - alGetError(); + CheckALErrors(); + alDeleteBuffers( 3, &lastopenalStreamingBuffer[0] ); - if( alGetError() == AL_NO_ERROR ) + if( CheckALErrors() == AL_NO_ERROR ) { lastopenalStreamingBuffer[0] = lastopenalStreamingBuffer[1] = lastopenalStreamingBuffer[2] = 0; } @@ -654,7 +657,7 @@ void idSoundVoice_OpenAL::Stop() } alSourceStop( openalSource ); - //alSourcei( openalSource, AL_BUFFER, 0 ); + alSourcei( openalSource, AL_BUFFER, 0 ); //pSourceVoice->Stop( 0, OPERATION_SET ); paused = true; diff --git a/neo/sound/snd_local.h b/neo/sound/snd_local.h index 14f73405..ae18f52b 100644 --- a/neo/sound/snd_local.h +++ b/neo/sound/snd_local.h @@ -105,6 +105,28 @@ typedef enum #include "OpenAL/AL_SoundVoice.h" #include "OpenAL/AL_SoundHardware.h" +ID_INLINE_EXTERN ALenum CheckALErrors_( const char* filename, int line ) +{ + ALenum err = alGetError(); + if( err != AL_NO_ERROR ) + { + idLib::Printf( "OpenAL Error: %s (0x%x), @ %s %d\n", alGetString( err ), err, filename, line ); + } + return err; +} +#define CheckALErrors() CheckALErrors_(__FILE__, __LINE__) + +ID_INLINE_EXTERN ALCenum CheckALCErrors_( ALCdevice* device, const char* filename, int linenum ) +{ + ALCenum err = alcGetError( device ); + if( err != ALC_NO_ERROR ) + { + idLib::Printf( "ALC Error: %s (0x%x), @ %s %d\n", alcGetString( device, err ), err, filename, linenum ); + } + return err; +} +#define CheckALCErrors(x) CheckALCErrors_((x), __FILE__, __LINE__) + #elif defined(_MSC_VER) // DG: stub out xaudio for MinGW etc #define OPERATION_SET 1 @@ -460,6 +482,10 @@ public: virtual void* GetIXAudio2() const; // FIXME: stupid name; get rid of this? not sure if it's really needed.. + // RB begin + virtual void* GetOpenALDevice() const; + // RB end + // for the sound level meter window virtual cinData_t ImageForTime( const int milliseconds, const bool waveform ); diff --git a/neo/sound/snd_system.cpp b/neo/sound/snd_system.cpp index 68460e13..34821e04 100644 --- a/neo/sound/snd_system.cpp +++ b/neo/sound/snd_system.cpp @@ -399,6 +399,22 @@ void* idSoundSystemLocal::GetIXAudio2() const // RB end } +/* +======================== +idSoundSystemLocal::GetOpenALDevice +======================== +*/ +// RB begin +void* idSoundSystemLocal::GetOpenALDevice() const +{ +#if defined(USE_OPENAL) + return ( void* )hardware.GetOpenALDevice(); +#else + return ( void* )hardware.GetIXAudio2(); +#endif +} +// RB end + /* ======================== idSoundSystemLocal::SoundTime diff --git a/neo/sound/sound.h b/neo/sound/sound.h index b495a952..0b6abecb 100644 --- a/neo/sound/sound.h +++ b/neo/sound/sound.h @@ -321,6 +321,10 @@ public: // video playback needs to get this virtual void* GetIXAudio2() const = 0; // FIXME: stupid name if we have other backends +#if defined(USE_OPENAL) + virtual void* GetOpenALDevice() const = 0; +#endif + // for the sound level meter window virtual cinData_t ImageForTime( const int milliseconds, const bool waveform ) = 0;