diff --git a/neo/CMakeLists.txt b/neo/CMakeLists.txt index f87876be..679a34b7 100644 --- a/neo/CMakeLists.txt +++ b/neo/CMakeLists.txt @@ -21,10 +21,6 @@ cmake_minimum_required(VERSION 2.6) # ID_NOLANADDRESS -DID_NOLANADDRESS # ID_MCHECK -DID_MCHECK -# don't add these as options at all -# ALSA remove all sound backends except openal -# OPENAL will always be enabled - set(CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/sys/cmake") set(CMAKE_SKIP_RPATH ON CACHE BOOL "Skip RPATH" FORCE) @@ -109,8 +105,6 @@ else() add_definitions(-DID_ENABLE_CURL=0) endif() -add_definitions(-DNO_ALSA) - # compiler specific flags if (CMAKE_COMPILER_IS_GNUCC OR CMAKE_C_COMPILER_ID STREQUAL "Clang") add_definitions(-pipe) @@ -197,7 +191,7 @@ if (CMAKE_COMPILER_IS_GNUCC OR CMAKE_C_COMPILER_ID STREQUAL "Clang") message(FATAL_ERROR "Unsupported CPU architecture for OSX") endif() - set(sys_libs ${sys_libs} "-framework Carbon -framework Cocoa -framework OpenGL -framework OpenAL -framework CoreAudio -framework IOKit") + set(sys_libs ${sys_libs} "-framework Carbon -framework Cocoa -framework OpenGL -framework OpenAL -framework IOKit") else() if (cpu STREQUAL "x86" AND X86) add_definitions(-m32) @@ -223,7 +217,6 @@ if (WIN32) set(sys_libs ${sys_libs} dinput8 - dsound ksuser dxguid dxerr8 @@ -655,7 +648,6 @@ if (APPLE) sys/osx/PickMonitor.cpp sys/osx/PreferencesDialog.cpp sys/osx/macosx_guids.cpp - sys/osx/macosx_sound.cpp sys/osx/DOOMController.mm sys/osx/macosx_event.mm sys/osx/macosx_glimp.mm @@ -674,7 +666,6 @@ elseif (WIN32) sys/win32/win_net.cpp sys/win32/win_qgl.cpp sys/win32/win_shared.cpp - sys/win32/win_snd.cpp sys/win32/win_syscon.cpp sys/win32/win_taskkeyhook.cpp sys/win32/win_wndproc.cpp @@ -690,7 +681,6 @@ else() sys/posix/posix_signal.cpp sys/posix/posix_threads.cpp sys/posix/posix_main.cpp - sys/linux/sound.cpp sys/linux/main.cpp ) diff --git a/neo/SConstruct b/neo/SConstruct index 40d2c36c..cb2c2bab 100644 --- a/neo/SConstruct +++ b/neo/SConstruct @@ -13,7 +13,7 @@ conf_filename='site.conf' # choose configuration variables which should be saved between runs # ( we handle all those as strings ) serialized=['CC', 'CXX', 'X86', 'BUILD', 'IDNET_HOST', 'DEDICATED', - 'DEBUG_MEMORY', 'LIBC_MALLOC', 'ID_NOLANADDRESS', 'ID_MCHECK', 'OPENAL', 'ALSA', + 'DEBUG_MEMORY', 'LIBC_MALLOC', 'ID_NOLANADDRESS', 'ID_MCHECK', 'TARGET_CORE', 'TARGET_GAME', 'TARGET_D3XP', 'TARGET_MONO', 'TARGET_DEMO', 'NOCURL', 'BUILD_ROOT', 'BUILD_GAMEPAK', 'BASEFLAGS' ] @@ -109,12 +109,6 @@ ID_MCHECK (default 2) note that Doom has it's own block allocator/checking this should not be considered a replacement, but an additional tool -OPENAL (default 1) - enable OpenAL sound backend support - -ALSA (default 1) - enable ALSA sound backend support - SETUP (default 0, not saved) build a setup. implies release build @@ -179,8 +173,6 @@ LIBC_MALLOC = '1' ID_NOLANADDRESS = '0' ID_MCHECK = '2' BUILD_ROOT = 'build' -OPENAL = '1' -ALSA = '1' SETUP = '0' SDK = '0' NOCONF = '0' @@ -382,7 +374,7 @@ local_idlibpic = 0 # switch between base game build and d3xp game build local_d3xp = 0 -GLOBALS = 'g_env g_env_noopt g_game_env g_os g_cpu g_build ID_MCHECK OPENAL ALSA idlib_objects game_objects local_dedicated local_gamedll local_demo local_idlibpic local_curl local_d3xp OPTCPPFLAGS' +GLOBALS = 'g_env g_env_noopt g_game_env g_os g_cpu g_build ID_MCHECK idlib_objects game_objects local_dedicated local_gamedll local_demo local_idlibpic local_curl local_d3xp OPTCPPFLAGS' # end general configuration ---------------------- diff --git a/neo/idlib/precompiled.h b/neo/idlib/precompiled.h index 5984be1a..644f5e6b 100644 --- a/neo/idlib/precompiled.h +++ b/neo/idlib/precompiled.h @@ -47,9 +47,6 @@ If you have questions concerning this license or the applicable additional terms #include #define DIRECTINPUT_VERSION 0x0800 // was 0x0700 with the old mssdk -#define DIRECTSOUND_VERSION 0x0800 - -#include #include #pragma warning(disable : 4100) // unreferenced formal parameter diff --git a/neo/sound/snd_local.h b/neo/sound/snd_local.h index 552de9e4..b567b49c 100644 --- a/neo/sound/snd_local.h +++ b/neo/sound/snd_local.h @@ -68,7 +68,6 @@ const float SND_EPSILON = 1.0f / 32768.0f; // if volume is below this, it wil const int ROOM_SLICES_IN_BUFFER = 10; -class idAudioHardware; class idAudioBuffer; class idWaveFile; class idSoundCache; @@ -222,38 +221,6 @@ private: }; -/* -=================================================================================== - -idAudioHardware - -=================================================================================== -*/ - -class idAudioHardware { -public: - static idAudioHardware *Alloc(); - - virtual ~idAudioHardware(); - - virtual bool Initialize( ) = 0; - - virtual bool Lock( void **pDSLockedBuffer, ulong *dwDSLockedBufferSize ) = 0; - virtual bool Unlock( void *pDSLockedBuffer, dword dwDSLockedBufferSize ) = 0; - virtual bool GetCurrentPosition( ulong *pdwCurrentWriteCursor ) = 0; - - // try to write as many sound samples to the device as possible without blocking and prepare for a possible new mixing call - // returns wether there is *some* space for writing available - virtual bool Flush( void ) = 0; - - virtual void Write( bool flushing ) = 0; - - virtual int GetNumberOfSpeakers( void )= 0; - virtual int GetMixBufferSize( void ) = 0; - virtual short* GetMixBuffer( void ) = 0; -}; - - /* =================================================================================== diff --git a/neo/sys/linux/sound.cpp b/neo/sys/linux/sound.cpp deleted file mode 100644 index 71d68c99..00000000 --- a/neo/sys/linux/sound.cpp +++ /dev/null @@ -1,391 +0,0 @@ -/* -=========================================================================== - -Doom 3 GPL Source Code -Copyright (C) 1999-2011 id Software LLC, a ZeniMax Media company. - -This file is part of the Doom 3 GPL Source Code ("Doom 3 Source Code"). - -Doom 3 Source Code is free software: you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation, either version 3 of the License, or -(at your option) any later version. - -Doom 3 Source Code is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with Doom 3 Source Code. If not, see . - -In addition, the Doom 3 Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 Source Code. If not, please request a copy in writing from id Software at the address below. - -If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA. - -=========================================================================== -*/ -#include -#include -#include -#include -#include -#include -#include -// OSS sound interface -// http://www.opensound.com/ -#include - -#include "../../idlib/precompiled.h" -#include "../../sound/snd_local.h" -#include "../posix/posix_public.h" -#include "sound.h" - -const char *s_driverArgs[] = { "best", "oss", "alsa", NULL }; - -#ifndef NO_ALSA -static idCVar s_driver( "s_driver", s_driverArgs[0], CVAR_SYSTEM | CVAR_ARCHIVE, "sound driver. 'best' will attempt to use alsa and fallback to OSS if not available", s_driverArgs, idCmdSystem::ArgCompletion_String ); -#else -static idCVar s_driver( "s_driver", "oss", CVAR_SYSTEM | CVAR_ARCHIVE | CVAR_ROM, "sound driver. only OSS is supported in this build" ); -#endif - -idAudioHardware *idAudioHardware::Alloc() { -#ifndef NO_ALSA - if ( !strcmp( s_driver.GetString(), "best" ) ) { - idAudioHardwareALSA *test = new idAudioHardwareALSA; - if ( test->DLOpen() ) { - common->Printf( "Alsa is available\n" ); - return test; - } - common->Printf( "Alsa is not available\n" ); - delete test; - return new idAudioHardwareOSS; - } - if ( !strcmp( s_driver.GetString(), "alsa" ) ) { - return new idAudioHardwareALSA; - } -#endif - return new idAudioHardwareOSS; -} - -// OSS sound ---------------------------------------------------- - -/* -=============== -idAudioHardware::~idAudioHardware -=============== -*/ -idAudioHardware::~idAudioHardware() { } - -/* -================= -idAudioHardwareOSS::~idAudioHardwareOSS -================= -*/ -idAudioHardwareOSS::~idAudioHardwareOSS() { - Release(); -} - -/* -================= -idAudioHardwareOSS::Release -================= -*/ -void idAudioHardwareOSS::Release( bool bSilent ) { - if (m_audio_fd) { - if (!bSilent) { - common->Printf("------ OSS Sound Shutdown ------\n"); - } - if (m_buffer) { - free( m_buffer ); - m_buffer = NULL; - m_buffer_size = 0; - } - common->Printf("close sound device\n"); - if (close(m_audio_fd) == -1) { - common->Warning( "failed to close sound device: %s", strerror(errno) ); - } - m_audio_fd = 0; - if (!bSilent) { - common->Printf("--------------------------------\n"); - } - } -} - -/* -================= -idAudioHardwareOSS::InitFailed -================= -*/ -void idAudioHardwareOSS::InitFailed() { - Release( true ); - cvarSystem->SetCVarBool( "s_noSound", true ); - common->Warning( "sound subsystem disabled" ); - common->Printf( "--------------------------------------\n" ); -} - -/* -================= -idAudioHardwareOSS::ExtractOSSVersion -================= -*/ -void idAudioHardwareOSS::ExtractOSSVersion( int version, idStr &str ) const { - sprintf( str, "%d.%d.%d", ( version & 0xFF0000 ) >> 16, ( version & 0xFF00 ) >> 8, version & 0xFF ); -} - -/* -================= -idAudioHardwareOSS::Initialize - -http://www.4front-tech.com/pguide/index.html -though OSS API docs (1.1) advertise AFMT_S32_LE, AFMT_S16_LE is the only output format I've found in kernel emu10k1 headers - -BSD NOTE: With the GNU library, you can use free to free the blocks that memalign, posix_memalign, and valloc return. -That does not work in BSD, however--BSD does not provide any way to free such blocks. -================= -*/ -idCVar s_device( "s_dsp", "/dev/dsp", CVAR_SYSTEM | CVAR_ARCHIVE, "" ); - -bool idAudioHardwareOSS::Initialize( ) { - common->Printf("------ OSS Sound Initialization ------\n"); - - int requested_sample_format, caps, oss_version; - idStr s_compiled_oss_version, s_oss_version; - struct audio_buf_info info; - - memset( &info, 0, sizeof( info ) ); - - if (m_audio_fd) { - Release(); - } - - // open device ------------------------------------------------ - if ((m_audio_fd = open( s_device.GetString(), O_WRONLY | O_NONBLOCK, 0)) == -1) { - m_audio_fd = 0; - common->Warning( "failed to open sound device '%s': %s", s_device.GetString(), strerror(errno) ); - InitFailed(); - return false; - } - // make it blocking - so write overruns don't fail with 'Resource temporarily unavailable' - int flags; - if ( ( flags = fcntl( m_audio_fd, F_GETFL ) ) == -1 ) { - common->Warning( "failed fcntl F_GETFL on sound device '%s': %s", s_device.GetString(), strerror( errno ) ); - InitFailed(); - return false; - } - flags &= ~O_NONBLOCK; - if ( fcntl( m_audio_fd, F_SETFL, flags ) == -1 ) { - common->Warning( "failed to clear O_NONBLOCK on sound device '%s': %s", s_device.GetString(), strerror( errno ) ); - InitFailed(); - return false; - } - - common->Printf("opened sound device '%s'\n", s_device.GetString()); - - // verify capabilities ----------------------------------------- - -#if SOUND_VERSION >= 0x040000 - // may only be available starting with OSS API v4.0 - // http://www.fi.opensound.com/developer/SNDCTL_SYSINFO.html - // NOTE: at OSS API 4.0 headers, replace OSS_SYSINFO with SNDCTL_SYSINFO - oss_sysinfo si; - if ( ioctl( m_audio_fd, OSS_SYSINFO, &si ) == -1 ) { - common->Printf( "ioctl SNDCTL_SYSINFO failed: %s\nthis ioctl is only available in OSS/Linux implementation. If you run OSS/Free, don't bother.", strerror( errno ) ); - } else { - common->Printf( "%s: %s %s\n", s_device.GetString(), si.product, si.version ); - } -#endif - - if ( ioctl( m_audio_fd, SNDCTL_DSP_GETCAPS, &caps ) == -1 ) { - common->Warning( "ioctl SNDCTL_DSP_GETCAPS failed - driver too old?" ); - InitFailed(); - return false; - } - common->DPrintf("driver rev %d - capabilities %d\n", caps & DSP_CAP_REVISION, caps); - if (ioctl( m_audio_fd, OSS_GETVERSION, &oss_version ) == -1) { - common->Warning( "ioctl OSS_GETVERSION failed" ); - InitFailed(); - return false; - } - ExtractOSSVersion( oss_version, s_oss_version ); - ExtractOSSVersion( SOUND_VERSION, s_compiled_oss_version ); - common->DPrintf( "OSS interface version %s - compile time %s\n", s_oss_version.c_str(), s_compiled_oss_version.c_str() ); - if (!(caps & DSP_CAP_MMAP)) { - common->Warning( "driver doesn't have DSP_CAP_MMAP capability" ); - InitFailed(); - return false; - } - if (!(caps & DSP_CAP_TRIGGER)) { - common->Warning( "driver doesn't have DSP_CAP_TRIGGER capability" ); - InitFailed(); - return false; - } - - // sample format ----------------------------------------------- - requested_sample_format = AFMT_S16_LE; - m_sample_format = requested_sample_format; - if (ioctl(m_audio_fd, SNDCTL_DSP_SETFMT, &m_sample_format) == -1) { - common->Warning( "ioctl SNDCTL_DSP_SETFMT %d failed: %s", requested_sample_format, strerror(errno) ); - InitFailed(); - return false; - } - if ( m_sample_format != requested_sample_format ) { - common->Warning( "ioctl SNDCTL_DSP_SETFMT failed to get the requested sample format %d, got %d", requested_sample_format, m_sample_format ); - InitFailed(); - return false; - } - - // channels ---------------------------------------------------- - - // sanity over number of speakers - if ( idSoundSystemLocal::s_numberOfSpeakers.GetInteger() != 6 && idSoundSystemLocal::s_numberOfSpeakers.GetInteger() != 2 ) { - common->Warning( "invalid value for s_numberOfSpeakers. Use either 2 or 6" ); - idSoundSystemLocal::s_numberOfSpeakers.SetInteger( 2 ); - } - - m_channels = idSoundSystemLocal::s_numberOfSpeakers.GetInteger(); - if ( ioctl( m_audio_fd, SNDCTL_DSP_CHANNELS, &m_channels ) == -1 ) { - common->Warning( "ioctl SNDCTL_DSP_CHANNELS %d failed: %s", idSoundSystemLocal::s_numberOfSpeakers.GetInteger(), strerror(errno) ); - InitFailed(); - return false; - } - if ( m_channels != (unsigned int)idSoundSystemLocal::s_numberOfSpeakers.GetInteger() ) { - common->Warning( "ioctl SNDCTL_DSP_CHANNELS failed to get the %d requested channels, got %d", idSoundSystemLocal::s_numberOfSpeakers.GetInteger(), m_channels ); - if ( m_channels != 2 && idSoundSystemLocal::s_numberOfSpeakers.GetInteger() != 2 ) { - // we didn't request 2 channels, some drivers reply 1 channel on error but may still let us still get 2 if properly asked - m_channels = 2; - if ( ioctl( m_audio_fd, SNDCTL_DSP_CHANNELS, &m_channels ) == -1 ) { - common->Warning( "ioctl SNDCTL_DSP_CHANNELS fallback to 2 failed: %s", strerror(errno) ); - InitFailed(); - return false; - } - } - if ( m_channels == 2 ) { - // tell the system to mix 2 channels - common->Warning( "falling back to stereo" ); - idSoundSystemLocal::s_numberOfSpeakers.SetInteger( 2 ); - } else { - // disable sound - InitFailed(); - return false; - } - } - assert( (int)m_channels == idSoundSystemLocal::s_numberOfSpeakers.GetInteger() ); - - // sampling rate ------------------------------------------------ - m_speed = PRIMARYFREQ; - if ( ioctl( m_audio_fd, SNDCTL_DSP_SPEED, &m_speed ) == -1 ) { - common->Warning( "ioctl SNDCTL_DSP_SPEED %d failed: %s", PRIMARYFREQ, strerror(errno) ); - InitFailed(); - return false; - } - // instead of an exact match, do a very close to - // there is some horrible Ensonic ES1371 which replies 44101 for a 44100 request - if ( abs( m_speed - PRIMARYFREQ ) > 5 ) { - common->Warning( "ioctl SNDCTL_DSP_SPEED failed to get the requested frequency %d, got %d", PRIMARYFREQ, m_speed ); - InitFailed(); - return false; - } - common->Printf("%s - bit rate: %d, channels: %d, frequency: %d\n", s_device.GetString(), m_sample_format, m_channels, m_speed); - - // output buffer ------------------------------------------------ - // allocate a final buffer target, the sound engine locks, writes, and we write back to the device - // we want m_buffer_size ( will have to rename those ) - // ROOM_SLICES_IN_BUFFER is fixed ( system default, 10 ) - // MIXBUFFER_SAMPLES is the number of samples found in a slice - // each sample is m_channels * sizeof( float ) bytes - // in AsyncUpdate we only write one block at a time, so we'd only need to have a final mix buffer sized of a single block - m_buffer_size = MIXBUFFER_SAMPLES * m_channels * 2; - m_buffer = malloc( m_buffer_size ); - common->Printf( "allocated a mix buffer of %d bytes\n", m_buffer_size ); - - // toggle sound ------------------------------------------------- - - // toggle off before toggling on. that's what OSS source code samples recommends - int flag = 0; - if (ioctl(m_audio_fd, SNDCTL_DSP_SETTRIGGER, &flag) == -1) { - common->Warning( "ioctl SNDCTL_DSP_SETTRIGGER 0 failed: %s", strerror(errno) ); - } - flag = PCM_ENABLE_OUTPUT; - if (ioctl(m_audio_fd, SNDCTL_DSP_SETTRIGGER, &flag) == -1) { - common->Warning( "ioctl SNDCTL_DSP_SETTRIGGER PCM_ENABLE_OUTPUT failed: %s", strerror(errno) ); - } - - common->Printf("--------------------------------------\n"); - return true; -} - -/* -=============== -idAudioHardwareOSS::Flush -=============== -*/ -bool idAudioHardwareOSS::Flush( void ) { - audio_buf_info ospace; - if ( ioctl( m_audio_fd, SNDCTL_DSP_GETOSPACE, &ospace ) == -1 ) { - Sys_Printf( "ioctl SNDCTL_DSP_GETOSPACE failed: %s\n", strerror( errno ) ); - return false; - } - // how many chunks can we write to the audio device right now - m_freeWriteChunks = ( ospace.bytes * MIXBUFFER_CHUNKS ) / ( MIXBUFFER_SAMPLES * m_channels * 2 ); - if ( m_writeChunks ) { - // flush out any remaining chunks we could now - Write( true ); - } - return ( m_freeWriteChunks > 0 ); -} - -/* -================= -idAudioHardwareOSS::GetMixBufferSize -================= -*/ -int idAudioHardwareOSS::GetMixBufferSize() { - // return MIXBUFFER_SAMPLES * 2 * m_channels; - return m_buffer_size; -} - -/* -================= -idAudioHardwareOSS::GetMixBuffer -================= -*/ -short* idAudioHardwareOSS::GetMixBuffer() { - return (short *)m_buffer; -} - -/* -=============== -idAudioHardwareOSS::Write -rely on m_freeWriteChunks which has been set in Flush() before engine did the mixing for this MIXBUFFER_SAMPLE -=============== -*/ -void idAudioHardwareOSS::Write( bool flushing ) { - assert( m_audio_fd ); - int ret; - if ( !flushing && m_writeChunks ) { - // if we write after a new mixing loop, we should have m_writeChunk == 0 - // otherwise that last remaining chunk that was never flushed out to the audio device has just been overwritten - Sys_Printf( "idAudioHardwareOSS::Write: %d samples were overflowed and dropped\n", m_writeChunks * MIXBUFFER_SAMPLES / MIXBUFFER_CHUNKS ); - } - if ( !flushing ) { - // if running after the mix loop, then we have a full buffer to write out - m_writeChunks = MIXBUFFER_CHUNKS; - } - if ( m_freeWriteChunks == 0 ) { - return; - } - // what to write and how much - uintptr_t pos = (uintptr_t)m_buffer + ( MIXBUFFER_CHUNKS - m_writeChunks ) * m_channels * 2 * MIXBUFFER_SAMPLES / MIXBUFFER_CHUNKS; - int len = Min( m_writeChunks, m_freeWriteChunks ) * m_channels * 2 * MIXBUFFER_SAMPLES / MIXBUFFER_CHUNKS; - assert( len > 0 ); - if ( ( ret = write( m_audio_fd, (void*)pos, len ) ) == -1 ) { - Sys_Printf( "write to audio fd failed: %s\n", strerror( errno ) ); - return; - } - if ( len != ret ) { - Sys_Printf( "short write to audio fd: wrote %d out of %d\n", ret, m_buffer_size ); - return; - } - m_writeChunks -= Min( m_writeChunks, m_freeWriteChunks ); -} diff --git a/neo/sys/linux/sound.h b/neo/sys/linux/sound.h deleted file mode 100644 index 68804eae..00000000 --- a/neo/sys/linux/sound.h +++ /dev/null @@ -1,185 +0,0 @@ -/* -=========================================================================== - -Doom 3 GPL Source Code -Copyright (C) 1999-2011 id Software LLC, a ZeniMax Media company. - -This file is part of the Doom 3 GPL Source Code ("Doom 3 Source Code"). - -Doom 3 Source Code is free software: you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation, either version 3 of the License, or -(at your option) any later version. - -Doom 3 Source Code is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with Doom 3 Source Code. If not, see . - -In addition, the Doom 3 Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 Source Code. If not, please request a copy in writing from id Software at the address below. - -If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA. - -=========================================================================== -*/ -#ifndef ID_SND_BACKENDS -#define ID_SND_BACKENDS - -class idAudioHardwareOSS : public idAudioHardware { - // if you can't write MIXBUFFER_SAMPLES all at once to the audio device, split in MIXBUFFER_CHUNKS - static const int MIXBUFFER_CHUNKS = 4; - - int m_audio_fd; - int m_sample_format; - unsigned int m_channels; - unsigned int m_speed; - void *m_buffer; - int m_buffer_size; - - // counting the loops through the dma buffer - int m_loops; - - // how many chunks we have left to write in cases where we need to split - int m_writeChunks; - // how many chunks we can write to the audio device without blocking - int m_freeWriteChunks; - -public: - idAudioHardwareOSS() { - m_audio_fd = 0; - m_sample_format = 0; - m_channels = 0; - m_speed = 0; - m_buffer = NULL; - m_buffer_size = 0; - m_loops = 0; - m_writeChunks = 0; - m_freeWriteChunks = 0; - } - virtual ~idAudioHardwareOSS(); - - bool Initialize( void ); - - // Linux driver doesn't support memory map API - bool Lock( void **pDSLockedBuffer, ulong *dwDSLockedBufferSize ) { return false; } - bool Unlock( void *pDSLockedBuffer, dword dwDSLockedBufferSize ) { return false; } - bool GetCurrentPosition( ulong *pdwCurrentWriteCursor ) { return false; } - - bool Flush(); - void Write( bool flushing ); - - int GetNumberOfSpeakers() { return m_channels; } - int GetMixBufferSize(); - short* GetMixBuffer(); - -private: - void Release( bool bSilent = false ); - void InitFailed(); - void ExtractOSSVersion( int version, idStr &str ) const; -}; - -#ifndef NO_ALSA - -// libasound2-dev -// the new/old API may be a problem if we are going to dynamically load the asound lib? -#define ALSA_PCM_NEW_HW_PARAMS_API -#define ALSA_PCM_NEW_SW_PARAMS_API -#include - -typedef const char * ( *pfn_snd_asoundlib_version )( void ); -typedef snd_pcm_sframes_t ( *pfn_snd_pcm_avail_update )( snd_pcm_t *pcm ); -typedef int ( *pfn_snd_pcm_close )( snd_pcm_t *pcm ); -typedef const char * ( *pfn_snd_strerror )( int errnum ); -typedef int ( *pfn_snd_pcm_hw_params )( snd_pcm_t *pcm, snd_pcm_hw_params_t *params ); -typedef int ( *pfn_snd_pcm_hw_params_any )( snd_pcm_t *pcm, snd_pcm_hw_params_t *params ); -typedef int ( *pfn_snd_pcm_hw_params_get_buffer_size )( const snd_pcm_hw_params_t *params, snd_pcm_uframes_t *val ); -typedef int ( *pfn_snd_pcm_hw_params_set_access )( snd_pcm_t *pcm, snd_pcm_hw_params_t *params, snd_pcm_access_t access ); -typedef int ( *pfn_snd_pcm_hw_params_set_buffer_size_min )( snd_pcm_t *pcm, snd_pcm_hw_params_t *params, snd_pcm_uframes_t *val ); -typedef int ( *pfn_snd_pcm_hw_params_set_channels )( snd_pcm_t *pcm, snd_pcm_hw_params_t *params, unsigned int val ); -typedef int ( *pfn_snd_pcm_hw_params_set_format )( snd_pcm_t *pcm, snd_pcm_hw_params_t *params, snd_pcm_format_t format ); -typedef int ( *pfn_snd_pcm_hw_params_set_rate )( snd_pcm_t *pcm, snd_pcm_hw_params_t *params, unsigned int val, int dir ); -typedef size_t ( *pfn_snd_pcm_hw_params_sizeof )( void ); -typedef int ( *pfn_snd_pcm_open )( snd_pcm_t **pcmp, const char *name, snd_pcm_stream_t stream, int mode ); -typedef int ( *pfn_snd_pcm_prepare )( snd_pcm_t *pcm ); -typedef snd_pcm_state_t ( *pfn_snd_pcm_state )( snd_pcm_t *pcm ); -typedef snd_pcm_sframes_t ( *pfn_snd_pcm_writei )( snd_pcm_t *pcm, const void *buffer, snd_pcm_uframes_t size ); - -#define ALSA_DLSYM(SYM) id_##SYM = ( pfn_##SYM )dlvsym( m_handle, #SYM, "ALSA_0.9" ); if ( !id_##SYM ) { common->Printf( "dlsym "#SYM" failed: %s\n", dlerror() ); Release(); return false; } - -class idAudioHardwareALSA : public idAudioHardware { -private: - // if you can't write MIXBUFFER_SAMPLES all at once to the audio device, split in MIXBUFFER_CHUNKS - static const int MIXBUFFER_CHUNKS = 4; - - snd_pcm_t *m_pcm_handle; - unsigned int m_channels; - void *m_buffer; - int m_buffer_size; - - // how many frames remaining to be written to the device - int m_remainingFrames; - - void *m_handle; - -public: - idAudioHardwareALSA() { - m_pcm_handle = NULL; - m_channels = 0; - m_buffer = NULL; - m_buffer_size = 0; - m_remainingFrames = 0; - m_handle = NULL; - } - virtual ~idAudioHardwareALSA(); - - // dlopen the lib ( check minimum version ) - bool DLOpen(); - - bool Initialize( void ); - - - // Linux driver doesn't support memory map API - bool Lock( void **pDSLockedBuffer, ulong *dwDSLockedBufferSize ) { return false; } - bool Unlock( void *pDSLockedBuffer, dword dwDSLockedBufferSize ) { return false; } - bool GetCurrentPosition( ulong *pdwCurrentWriteCursor ) { return false; } - - bool Flush(); - void Write( bool flushing ); - - int GetNumberOfSpeakers( void ) { return m_channels; } - int GetMixBufferSize( void ); - short* GetMixBuffer( void ); - -private: - void Release(); - void InitFailed(); - void PlayTestPattern(); - - // may be NULL, outdated alsa versions are missing it and we just ignore - pfn_snd_asoundlib_version id_snd_asoundlib_version; - - pfn_snd_pcm_avail_update id_snd_pcm_avail_update; - pfn_snd_pcm_close id_snd_pcm_close; - pfn_snd_strerror id_snd_strerror; - pfn_snd_pcm_hw_params id_snd_pcm_hw_params; - pfn_snd_pcm_hw_params_any id_snd_pcm_hw_params_any; - pfn_snd_pcm_hw_params_get_buffer_size id_snd_pcm_hw_params_get_buffer_size; - pfn_snd_pcm_hw_params_set_access id_snd_pcm_hw_params_set_access; - pfn_snd_pcm_hw_params_set_buffer_size_min id_snd_pcm_hw_params_set_buffer_size_min; - pfn_snd_pcm_hw_params_set_channels id_snd_pcm_hw_params_set_channels; - pfn_snd_pcm_hw_params_set_format id_snd_pcm_hw_params_set_format; - pfn_snd_pcm_hw_params_set_rate id_snd_pcm_hw_params_set_rate; - pfn_snd_pcm_hw_params_sizeof id_snd_pcm_hw_params_sizeof; - pfn_snd_pcm_open id_snd_pcm_open; - pfn_snd_pcm_prepare id_snd_pcm_prepare; - pfn_snd_pcm_state id_snd_pcm_state; - pfn_snd_pcm_writei id_snd_pcm_writei; - -}; - -#endif // NO_ALSA - -#endif diff --git a/neo/sys/linux/sound_alsa.cpp b/neo/sys/linux/sound_alsa.cpp deleted file mode 100644 index 5513f6ff..00000000 --- a/neo/sys/linux/sound_alsa.cpp +++ /dev/null @@ -1,317 +0,0 @@ -/* -=========================================================================== - -Doom 3 GPL Source Code -Copyright (C) 1999-2011 id Software LLC, a ZeniMax Media company. - -This file is part of the Doom 3 GPL Source Code ("Doom 3 Source Code"). - -Doom 3 Source Code is free software: you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation, either version 3 of the License, or -(at your option) any later version. - -Doom 3 Source Code is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with Doom 3 Source Code. If not, see . - -In addition, the Doom 3 Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 Source Code. If not, please request a copy in writing from id Software at the address below. - -If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA. - -=========================================================================== -*/ -#include "../../idlib/precompiled.h" -#include "../../sound/snd_local.h" -#include "../posix/posix_public.h" -#include "sound.h" - -#include - -static idCVar s_alsa_pcm( "s_alsa_pcm", "default", CVAR_SYSTEM | CVAR_ARCHIVE, "which alsa pcm device to use. default, hwplug, hw.. see alsa docs" ); -static idCVar s_alsa_lib( "s_alsa_lib", "libasound.so.2", CVAR_SYSTEM | CVAR_ARCHIVE, "alsa client sound library" ); - -/* -=============== -idAudioHardwareALSA::DLOpen -=============== -*/ -bool idAudioHardwareALSA::DLOpen( void ) { - const char *version; - - if ( m_handle ) { - return true; - } - common->Printf( "dlopen(%s)\n", s_alsa_lib.GetString() ); - if ( !( m_handle = dlopen( s_alsa_lib.GetString(), RTLD_NOW | RTLD_GLOBAL ) ) ) { - common->Printf( "dlopen(%s) failed: %s\n", s_alsa_lib.GetString(), dlerror() ); - return false; - } - // print the version if available - id_snd_asoundlib_version = ( pfn_snd_asoundlib_version )dlsym( m_handle, "snd_asoundlib_version" ); - if ( !id_snd_asoundlib_version ) { - common->Printf( "dlsym(\"snd_asoundlib_version\") failed: %s\n", dlerror() ); - common->Warning( "please consider upgrading alsa to a more recent version." ); - } else { - version = id_snd_asoundlib_version(); - common->Printf( "asoundlib version: %s\n", version ); - } - // dlsym the symbols - ALSA_DLSYM(snd_pcm_avail_update); - ALSA_DLSYM(snd_pcm_close); - ALSA_DLSYM(snd_pcm_hw_params); - ALSA_DLSYM(snd_pcm_hw_params_any); - ALSA_DLSYM(snd_pcm_hw_params_get_buffer_size); - ALSA_DLSYM(snd_pcm_hw_params_set_access); - ALSA_DLSYM(snd_pcm_hw_params_set_buffer_size_min); - ALSA_DLSYM(snd_pcm_hw_params_set_channels); - ALSA_DLSYM(snd_pcm_hw_params_set_format); - ALSA_DLSYM(snd_pcm_hw_params_set_rate); - ALSA_DLSYM(snd_pcm_hw_params_sizeof); - ALSA_DLSYM(snd_pcm_open); - ALSA_DLSYM(snd_pcm_prepare); - ALSA_DLSYM(snd_pcm_state); - ALSA_DLSYM(snd_pcm_writei); - ALSA_DLSYM(snd_strerror); - return true; -} - -/* -=============== -idAudioHardwareALSA::Release -=============== -*/ -void idAudioHardwareALSA::Release() { - if ( m_pcm_handle ) { - common->Printf( "close pcm\n" ); - id_snd_pcm_close( m_pcm_handle ); - m_pcm_handle = NULL; - } - if ( m_buffer ) { - free( m_buffer ); - m_buffer = NULL; - } - if ( m_handle ) { - common->Printf( "dlclose\n" ); - dlclose( m_handle ); - m_handle = NULL; - } -} - -/* -================= -idAudioHardwareALSA::InitFailed -================= -*/ -void idAudioHardwareALSA::InitFailed() { - Release(); - cvarSystem->SetCVarBool( "s_noSound", true ); - common->Warning( "sound subsystem disabled\n" ); - common->Printf( "--------------------------------------\n" ); -} - -/* -===================== -idAudioHardwareALSA::Initialize -===================== -*/ -bool idAudioHardwareALSA::Initialize( void ) { - int err; - - common->Printf( "------ Alsa Sound Initialization -----\n" ); - if ( !DLOpen() ) { - InitFailed(); - return false; - } - if ( ( err = id_snd_pcm_open( &m_pcm_handle, s_alsa_pcm.GetString(), SND_PCM_STREAM_PLAYBACK, SND_PCM_NONBLOCK ) ) < 0 ) { - common->Printf( "snd_pcm_open SND_PCM_STREAM_PLAYBACK '%s' failed: %s\n", s_alsa_pcm.GetString(), id_snd_strerror( err ) ); - InitFailed(); - return false; - } - common->Printf( "opened Alsa PCM device %s for playback\n", s_alsa_pcm.GetString() ); - - // set hardware parameters ---------------------------------------------------------------------- - - // init hwparams with the full configuration space - snd_pcm_hw_params_t *hwparams = (snd_pcm_hw_params_t *) alloca(id_snd_pcm_hw_params_sizeof()); - memset(hwparams, 0, id_snd_pcm_hw_params_sizeof()); - - if ( ( err = id_snd_pcm_hw_params_any( m_pcm_handle, hwparams ) ) < 0 ) { - common->Printf( "cannot configure the PCM device: %s\n", id_snd_strerror( err ) ); - InitFailed(); - return false; - } - - if ( ( err = id_snd_pcm_hw_params_set_access( m_pcm_handle, hwparams, SND_PCM_ACCESS_RW_INTERLEAVED ) ) < 0 ) { - common->Printf( "SND_PCM_ACCESS_RW_INTERLEAVED failed: %s\n", id_snd_strerror( err ) ); - InitFailed(); - return false; - } - - if ( ( err = id_snd_pcm_hw_params_set_format( m_pcm_handle, hwparams, SND_PCM_FORMAT_S16_LE ) ) < 0 ) { - common->Printf( "SND_PCM_FORMAT_S16_LE failed: %s\n", id_snd_strerror( err ) ); - InitFailed(); - return false; - } - - // channels - - // sanity over number of speakers - if ( idSoundSystemLocal::s_numberOfSpeakers.GetInteger() != 6 && idSoundSystemLocal::s_numberOfSpeakers.GetInteger() != 2 ) { - common->Warning( "invalid value for s_numberOfSpeakers. Use either 2 or 6" ); - idSoundSystemLocal::s_numberOfSpeakers.SetInteger( 2 ); - } - - m_channels = idSoundSystemLocal::s_numberOfSpeakers.GetInteger(); - if ( ( err = id_snd_pcm_hw_params_set_channels( m_pcm_handle, hwparams, m_channels ) ) < 0 ) { - common->Printf( "error setting %d channels: %s\n", m_channels, id_snd_strerror( err ) ); - if ( idSoundSystemLocal::s_numberOfSpeakers.GetInteger() != 2 ) { - // fallback to stereo if that works - m_channels = 2; - if ( ( err = id_snd_pcm_hw_params_set_channels( m_pcm_handle, hwparams, m_channels ) ) < 0 ) { - common->Printf( "fallback to stereo failed: %s\n", id_snd_strerror( err ) ); - InitFailed(); - return false; - } else { - common->Printf( "fallback to stereo\n" ); - idSoundSystemLocal::s_numberOfSpeakers.SetInteger( 2 ); - } - } else { - InitFailed(); - return false; - } - } - - // set sample rate (frequency) - if ( ( err = id_snd_pcm_hw_params_set_rate( m_pcm_handle, hwparams, PRIMARYFREQ, 0 ) ) < 0 ) { - common->Printf( "failed to set 44.1KHz rate: %s - try ( +set s_alsa_pcm plughw:0 ? )\n", id_snd_strerror( err ) ); - InitFailed(); - return false; - } - - // have enough space in the input buffer for our MIXBUFFER_SAMPLE feedings and async ticks - snd_pcm_uframes_t frames; - frames = MIXBUFFER_SAMPLES + MIXBUFFER_SAMPLES / 3; - if ( ( err = id_snd_pcm_hw_params_set_buffer_size_min( m_pcm_handle, hwparams, &frames ) ) < 0 ) { - common->Printf( "buffer size select failed: %s\n", id_snd_strerror( err ) ); - InitFailed(); - return false; - } - - // apply parameters - if ( ( err = id_snd_pcm_hw_params( m_pcm_handle, hwparams ) ) < 0 ) { - common->Printf( "snd_pcm_hw_params failed: %s\n", id_snd_strerror( err ) ); - InitFailed(); - return false; - } - - // check the buffer size - if ( ( err = id_snd_pcm_hw_params_get_buffer_size( hwparams, &frames ) ) < 0 ) { - common->Printf( "snd_pcm_hw_params_get_buffer_size failed: %s\n", id_snd_strerror( err ) ); - } else { - common->Printf( "device buffer size: %lu frames ( %lu bytes )\n", ( long unsigned int )frames, frames * m_channels * 2 ); - } - - // TODO: can use swparams to setup the device so it doesn't underrun but rather loops over - // snd_pcm_sw_params_set_stop_threshold - // To get alsa to just loop on underruns. set the swparam stop_threshold to equal buffer size. The sound buffer will just loop and never throw an xrun. - - // allocate the final mix buffer - m_buffer_size = MIXBUFFER_SAMPLES * m_channels * 2; - m_buffer = malloc( m_buffer_size ); - common->Printf( "allocated a mix buffer of %d bytes\n", m_buffer_size ); - -#ifdef _DEBUG - // verbose the state - snd_pcm_state_t curstate = id_snd_pcm_state( m_pcm_handle ); - assert( curstate == SND_PCM_STATE_PREPARED ); -#endif - - common->Printf( "--------------------------------------\n" ); - return true; -} - -/* -=============== -idAudioHardwareALSA::~idAudioHardwareALSA -=============== -*/ -idAudioHardwareALSA::~idAudioHardwareALSA() { - common->Printf( "----------- Alsa Shutdown ------------\n" ); - Release(); - common->Printf( "--------------------------------------\n" ); -} - -/* -================= -idAudioHardwareALSA::GetMixBufferSize -================= -*/ -int idAudioHardwareALSA::GetMixBufferSize() { - return m_buffer_size; -} - -/* -================= -idAudioHardwareALSA::GetMixBuffer -================= -*/ -short* idAudioHardwareALSA::GetMixBuffer() { - return (short *)m_buffer; -} - -/* -=============== -idAudioHardwareALSA::Flush -=============== -*/ -bool idAudioHardwareALSA::Flush( void ) { - int ret; - snd_pcm_state_t state; - state = id_snd_pcm_state( m_pcm_handle ); - if ( state != SND_PCM_STATE_RUNNING && state != SND_PCM_STATE_PREPARED ) { - if ( ( ret = id_snd_pcm_prepare( m_pcm_handle ) ) < 0 ) { - Sys_Printf( "failed to recover from SND_PCM_STATE_XRUN: %s\n", id_snd_strerror( ret ) ); - cvarSystem->SetCVarBool( "s_noSound", true ); - return false; - } - Sys_Printf( "preparing audio device for output\n" ); - } - Write( true ); - return true; -} - -/* -=============== -idAudioHardwareALSA::Write -rely on m_freeWriteChunks which has been set in Flush() before engine did the mixing for this MIXBUFFER_SAMPLE -=============== -*/ -void idAudioHardwareALSA::Write( bool flushing ) { - if ( !flushing && m_remainingFrames ) { - // if we write after a new mixing loop, we should have m_writeChunk == 0 - // otherwise that last remaining chunk that was never flushed out to the audio device has just been overwritten - Sys_Printf( "idAudioHardwareALSA::Write: %d frames overflowed and dropped\n", m_remainingFrames ); - } - if ( !flushing ) { - // if running after the mix loop, then we have a full buffer to write out - m_remainingFrames = MIXBUFFER_SAMPLES; - } - if ( m_remainingFrames == 0 ) { - return; - } - // write the max frames you can in one shot - we need to write it all out in Flush() calls before the next Write() happens - uintptr_t pos = (uintptr_t)m_buffer + ( MIXBUFFER_SAMPLES - m_remainingFrames ) * m_channels * 2; - snd_pcm_sframes_t frames = id_snd_pcm_writei( m_pcm_handle, (void*)pos, m_remainingFrames ); - if ( frames < 0 ) { - if ( frames != -EAGAIN ) { - Sys_Printf( "snd_pcm_writei %d frames failed: %s\n", m_remainingFrames, id_snd_strerror( frames ) ); - } - return; - } - m_remainingFrames -= frames; -} diff --git a/neo/sys/osx/macosx_sound.cpp b/neo/sys/osx/macosx_sound.cpp deleted file mode 100644 index 391e46ff..00000000 --- a/neo/sys/osx/macosx_sound.cpp +++ /dev/null @@ -1,433 +0,0 @@ -/* -=========================================================================== - -Doom 3 GPL Source Code -Copyright (C) 1999-2011 id Software LLC, a ZeniMax Media company. - -This file is part of the Doom 3 GPL Source Code ("Doom 3 Source Code"). - -Doom 3 Source Code is free software: you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation, either version 3 of the License, or -(at your option) any later version. - -Doom 3 Source Code is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with Doom 3 Source Code. If not, see . - -In addition, the Doom 3 Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 Source Code. If not, please request a copy in writing from id Software at the address below. - -If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA. - -=========================================================================== -*/ - -#include "../../idlib/precompiled.h" -#include "../../sound/snd_local.h" - -#include -#include - -idCVar s_device( "s_device", "-1", CVAR_SYSTEM | CVAR_ARCHIVE | CVAR_INTEGER, "Sound device to use. -1 for default device" ); - -class idAudioHardwareOSX : public idAudioHardware { -public: - idAudioHardwareOSX(); - ~idAudioHardwareOSX(); - - bool Initialize( ); - - // OSX driver doesn't support memory map API - bool Lock( void **pDSLockedBuffer, ulong *dwDSLockedBufferSize ) { return false; } - bool Unlock( void *pDSLockedBuffer, dword dwDSLockedBufferSize ) { return false; } - bool GetCurrentPosition( ulong *pdwCurrentWriteCursor ) { return false; } - int GetMixBufferSize( void ) { return 0; } - - int GetNumberOfSpeakers( void ); - - // OSX driver doesn't support write API - bool Flush( void ) { return false; } - void Write( bool ) { } - short* GetMixBuffer( void ) { return NULL; } - -private: - AudioDeviceID selectedDevice; - bool activeIOProc; - - void Reset( void ); - void InitFailed( void ); - const char* ExtractStatus( OSStatus status ); - void GetAvailableNominalSampleRates( void ); - - // AudioDevicePropertyListenerProc - static OSStatus DeviceListener( AudioDeviceID inDevice, - UInt32 inChannel, - Boolean isInput, - AudioDevicePropertyID inPropertyID, - void* inClientData ); - - // AudioDeviceIOProc - static OSStatus DeviceIOProc( AudioDeviceID inDevice, - const AudioTimeStamp* inNow, - const AudioBufferList* inInputData, - const AudioTimeStamp* inInputTime, - AudioBufferList* outOutputData, - const AudioTimeStamp* inOutputTime, - void* inClientData ); -}; - -/* -========== -iAudioHardware::Alloc -========== -*/ -idAudioHardware *idAudioHardware::Alloc() { return new idAudioHardwareOSX; } - -/* -========== -idAudioHardware::~idAudioHardware -========== -*/ -idAudioHardware::~idAudioHardware() { } - -/* -========== -idAudioHardwareOSX::idAudioHardwareOSX -========== -*/ -idAudioHardwareOSX::idAudioHardwareOSX() { - selectedDevice = kAudioDeviceUnknown; - activeIOProc = false; -} - -/* -========== -idAudioHardwareOSX::~idAudioHardwareOSX -========== -*/ -idAudioHardwareOSX::~idAudioHardwareOSX() { - Reset(); -} - -/* -========== -idAudioHardwareOSX::Reset -========== -*/ -void idAudioHardwareOSX::Reset() { - OSStatus status; - - if ( activeIOProc ) { - status = AudioDeviceStop( selectedDevice, DeviceIOProc ); - if ( status != kAudioHardwareNoError ) { - common->Warning( "idAudioHardwareOSX::Reset: AudioDeviceStop failed. status: %s", ExtractStatus( status ) ); - } - status = AudioDeviceRemoveIOProc( selectedDevice, DeviceIOProc ); - if ( status != kAudioHardwareNoError ) { - common->Warning( "idAudioHardwareOSX::Reset: AudioDeviceRemoveIOProc failed. status %s\n", ExtractStatus( status ) ); - } - activeIOProc = false; - } - selectedDevice = kAudioDeviceUnknown; - AudioHardwareUnload(); -} - -/* -================= -idAudioHardwareOSX::InitFailed -================= -*/ -void idAudioHardwareOSX::InitFailed() { - Reset(); - cvarSystem->SetCVarBool( "s_noSound", true ); - common->Warning( "sound subsystem disabled" ); - common->Printf( "------------------------------------------------\n" ); -} - -/* -========== -idAudioHardwareOSX::DeviceListener -========== -*/ -OSStatus idAudioHardwareOSX::DeviceListener( AudioDeviceID inDevice, - UInt32 inChannel, - Boolean isInput, - AudioDevicePropertyID inPropertyID, - void* inClientData) { - common->Printf( "DeviceListener\n" ); - return kAudioHardwareNoError; -} - -/* -========== -idAudioHardwareOSX::DeviceIOProc -========== -*/ -OSStatus idAudioHardwareOSX::DeviceIOProc( AudioDeviceID inDevice, - const AudioTimeStamp* inNow, - const AudioBufferList* inInputData, - const AudioTimeStamp* inInputTime, - AudioBufferList* outOutputData, - const AudioTimeStamp* inOutputTime, - void* inClientData ) { - - // setup similar to async thread - Sys_EnterCriticalSection(); - soundSystem->AsyncMix( (int)inOutputTime->mSampleTime, (float*)outOutputData->mBuffers[ 0 ].mData ); - Sys_LeaveCriticalSection(); - - // doom mixes sound to -32768.0f 32768.0f range, scale down to -1.0f 1.0f - SIMDProcessor->Mul( (Float32*)outOutputData->mBuffers[ 0 ].mData, 1.0f / 32768.0f, (Float32*)outOutputData->mBuffers[ 0 ].mData, MIXBUFFER_SAMPLES * 2 ); - - return kAudioHardwareNoError; -} - -/* -========== -idAudioHardwareOSX::ExtractStatus -========== -*/ -const char* idAudioHardwareOSX::ExtractStatus( OSStatus status ) { - static char buf[ sizeof( OSStatus ) + 1 ]; - strncpy( buf, (const char *)&status, sizeof( OSStatus ) ); - buf[ sizeof( OSStatus ) ] = '\0'; - return buf; -} - -/* -========== -idAudioHardwareOSX::Initialize -========== -*/ -bool idAudioHardwareOSX::Initialize( ) { - - UInt32 size; - OSStatus status; - int i, deviceCount; - AudioDeviceID *deviceList; - char buf[ 1024 ]; - - status = AudioHardwareGetPropertyInfo( kAudioHardwarePropertyDevices, &size, NULL ); - if ( status != kAudioHardwareNoError ) { - common->Warning( "AudioHardwareGetPropertyInfo kAudioHardwarePropertyDevices failed. status: %s", ExtractStatus( status ) ); - InitFailed(); - return false; - } - - deviceCount = size / sizeof( AudioDeviceID ); - if ( !deviceCount ) { - common->Printf( "No sound device found\n" ); - InitFailed(); - return false; - } - - deviceList = (AudioDeviceID*)malloc( size ); - status = AudioHardwareGetProperty( kAudioHardwarePropertyDevices, &size, deviceList ); - if ( status != kAudioHardwareNoError ) { - common->Warning( "AudioHardwareGetProperty kAudioHardwarePropertyDevices failed. status: %s", ExtractStatus( status ) ); - free( deviceList ); - InitFailed(); - return false; - } - - common->Printf( "%d sound device(s)\n", deviceCount ); - for( i = 0; i < deviceCount; i++ ) { - size = 1024; - status = AudioDeviceGetProperty( deviceList[ i ], 0, false, kAudioDevicePropertyDeviceName, &size, buf ); - if ( status != kAudioHardwareNoError ) { - common->Warning( "AudioDeviceGetProperty kAudioDevicePropertyDeviceName %d failed. status: %s", i, ExtractStatus( status ) ); - free( deviceList ); - InitFailed(); - return false; - } - common->Printf( " %d: ID %d, %s - ", i, deviceList[ i ], buf ); - size = 1024; - status = AudioDeviceGetProperty( deviceList[ i ], 0, false, kAudioDevicePropertyDeviceManufacturer, &size, buf ); - if ( status != kAudioHardwareNoError ) { - common->Warning( "AudioDeviceGetProperty kAudioDevicePropertyDeviceManufacturer %d failed. status: %s", i, ExtractStatus( status ) ); - free( deviceList ); - InitFailed(); - return false; - } - common->Printf( "%s\n", buf ); - } - - if ( s_device.GetInteger() != -1 && s_device.GetInteger() < deviceCount ) { - selectedDevice = deviceList[ s_device.GetInteger() ]; - common->Printf( "s_device: device ID %d\n", selectedDevice ); - } else { - size = sizeof( selectedDevice ); - status = AudioHardwareGetProperty( kAudioHardwarePropertyDefaultOutputDevice, &size, &selectedDevice ); - if ( status != kAudioHardwareNoError ) { - common->Warning( "AudioHardwareGetProperty kAudioHardwarePropertyDefaultOutputDevice failed. status: %s", ExtractStatus( status ) ); - - free( deviceList ); - InitFailed(); - return false; - } - common->Printf( "select default device, ID %d\n", selectedDevice ); - } - - free( deviceList ); - deviceList = NULL; - - /* - // setup a listener to watch for changes to properties - status = AudioDeviceAddPropertyListener( selectedDevice, 0, false, kAudioDeviceProcessorOverload, DeviceListener, this ); - if ( status != kAudioHardwareNoError ) { - common->Warning( "AudioDeviceAddPropertyListener kAudioDeviceProcessorOverload failed. status: %s", ExtractStatus( status ) ); - InitFailed(); - return; - } - */ - - Float64 sampleRate; - size = sizeof( sampleRate ); - status = AudioDeviceGetProperty( selectedDevice, 0, false, kAudioDevicePropertyNominalSampleRate, &size, &sampleRate ); - if ( status != kAudioHardwareNoError ) { - common->Warning( "AudioDeviceGetProperty %d kAudioDevicePropertyNominalSampleRate failed. status: %s", selectedDevice, ExtractStatus( status ) ); - InitFailed(); - return false; - } - common->Printf( "current nominal rate: %g\n", sampleRate ); - - if ( sampleRate != PRIMARYFREQ ) { - - GetAvailableNominalSampleRates(); - - sampleRate = PRIMARYFREQ; - common->Printf( "setting rate to: %g\n", sampleRate ); - status = AudioDeviceSetProperty( selectedDevice, NULL, 0, false, kAudioDevicePropertyNominalSampleRate, size, &sampleRate ); - if ( status != kAudioHardwareNoError ) { - common->Warning( "AudioDeviceSetProperty %d kAudioDevicePropertyNominalSampleRate %g failed. status: %s", selectedDevice, sampleRate, ExtractStatus( status ) ); - InitFailed(); - return false; - } - } - - UInt32 frameSize; - size = sizeof( UInt32 ); - status = AudioDeviceGetProperty( selectedDevice, 0, false, kAudioDevicePropertyBufferFrameSize, &size, &frameSize ); - if ( status != kAudioHardwareNoError ) { - common->Warning( "AudioDeviceGetProperty %d kAudioDevicePropertyBufferFrameSize failed.status: %s", selectedDevice, ExtractStatus( status ) ); - InitFailed(); - return false; - } - common->Printf( "current frame size: %d\n", frameSize ); - - // get the allowed frame size range - AudioValueRange frameSizeRange; - size = sizeof( AudioValueRange ); - status = AudioDeviceGetProperty( selectedDevice, 0, false, kAudioDevicePropertyBufferFrameSizeRange, &size, &frameSizeRange ); - if ( status != kAudioHardwareNoError ) { - common->Warning( "AudioDeviceGetProperty %d kAudioDevicePropertyBufferFrameSizeRange failed. status: %s", selectedDevice, ExtractStatus( status ) ); - InitFailed(); - return false; - } - common->Printf( "frame size allowed range: %g %g\n", frameSizeRange.mMinimum, frameSizeRange.mMaximum ); - - if ( frameSizeRange.mMaximum < MIXBUFFER_SAMPLES ) { - common->Warning( "can't obtain the required frame size of %d bits", MIXBUFFER_SAMPLES ); - InitFailed(); - return false; - } - - if ( frameSize != (unsigned int)MIXBUFFER_SAMPLES ) { - frameSize = MIXBUFFER_SAMPLES; - common->Printf( "setting frame size to: %d\n", frameSize ); - size = sizeof( frameSize ); - status = AudioDeviceSetProperty( selectedDevice, NULL, 0, false, kAudioDevicePropertyBufferFrameSize, size, &frameSize ); - if ( status != kAudioHardwareNoError ) { - common->Warning( "AudioDeviceSetProperty %d kAudioDevicePropertyBufferFrameSize failed. status: %s", selectedDevice, ExtractStatus( status ) ); - InitFailed(); - return false; - } - } - - if ( idSoundSystemLocal::s_numberOfSpeakers.GetInteger() != 2 ) { - common->Warning( "only stereo sound currently supported" ); - idSoundSystemLocal::s_numberOfSpeakers.SetInteger( 2 ); - } - UInt32 channels[ 2 ]; - size = 2 * sizeof( UInt32 ); - status = AudioDeviceGetProperty( selectedDevice, 0, false, kAudioDevicePropertyPreferredChannelsForStereo, &size, &channels ); - if ( status != kAudioHardwareNoError ) { - common->Warning( "AudioDeviceGetProperty %d kAudioDevicePropertyPreferredChannelsForStereo failed. status: %s", selectedDevice, ExtractStatus( status ) ); - InitFailed(); - return false; - } - common->Printf( "using stereo channel IDs %d %d\n", channels[ 0 ], channels[ 1 ] ); - - status = AudioDeviceAddIOProc( selectedDevice, DeviceIOProc, NULL ); - if ( status != kAudioHardwareNoError ) { - common->Warning( "AudioDeviceAddIOProc failed. status: %s", ExtractStatus( status ) ); - InitFailed(); - return false; - } - activeIOProc = true; - - status = AudioDeviceStart( selectedDevice, DeviceIOProc ); - if ( status != kAudioHardwareNoError ) { - common->Warning( "AudioDeviceStart failed. status: %s", ExtractStatus( status ) ); - InitFailed(); - return false; - } - - /* - // allocate the mix buffer - // it has the space for ROOM_SLICES_IN_BUFFER DeviceIOProc loops - mixBufferSize = dwSpeakers * dwSampleSize * dwPrimaryBitRate * ROOM_SLICES_IN_BUFFER / 8; - mixBuffer = malloc( mixBufferSize ); - memset( mixBuffer, 0, mixBufferSize ); - */ - - return true; -} - -/* -========== -idAudioHardwareOSX::GetAvailableNominalSampleRates -========== -*/ -void idAudioHardwareOSX::GetAvailableNominalSampleRates( void ) { - UInt32 size; - OSStatus status; - int i, rangeCount; - AudioValueRange *rangeArray; - - status = AudioDeviceGetPropertyInfo( selectedDevice, 0, false, kAudioDevicePropertyAvailableNominalSampleRates, &size, NULL ); - if ( status != kAudioHardwareNoError ) { - common->Warning( "AudioDeviceGetPropertyInfo %d kAudioDevicePropertyAvailableNominalSampleRates failed. status: %s", selectedDevice, ExtractStatus( status ) ); - return; - } - rangeCount = size / sizeof( AudioValueRange ); - rangeArray = (AudioValueRange *)malloc( size ); - - common->Printf( "%d possible rate(s)\n", rangeCount ); - - status = AudioDeviceGetProperty( selectedDevice, 0, false, kAudioDevicePropertyAvailableNominalSampleRates, &size, rangeArray ); - if ( status != kAudioHardwareNoError ) { - common->Warning( "AudioDeviceGetProperty %d kAudioDevicePropertyAvailableNominalSampleRates failed. status: %s", selectedDevice, ExtractStatus( status ) ); - free( rangeArray ); - return; - } - - for( i = 0; i < rangeCount; i++ ) { - common->Printf( " %d: min %g max %g\n", i, rangeArray[ i ].mMinimum, rangeArray[ i ].mMaximum ); - } - - free( rangeArray ); -} - -/* -========== -idAudioHardwareOSX::GetNumberOfSpeakers -========== -*/ -int idAudioHardwareOSX::GetNumberOfSpeakers() { - return idSoundSystemLocal::s_numberOfSpeakers.GetInteger(); -} diff --git a/neo/sys/scons/SConscript.core b/neo/sys/scons/SConscript.core index 4ac1de7d..2a215268 100644 --- a/neo/sys/scons/SConscript.core +++ b/neo/sys/scons/SConscript.core @@ -211,6 +211,7 @@ if ( local_dedicated == 0 ): else: sys_string += ' \ stub/stub_gl.cpp \ + stub/openal_stub.cpp \ linux/dedicated.cpp' sys_list = scons_utils.BuildList( 'sys', sys_string ) @@ -231,9 +232,6 @@ local_env = g_env.Clone() if ( local_dedicated == 1 ): local_env.Append( CPPDEFINES = [ 'ID_DEDICATED' ] ) - # don't enable openal or alsa for a dedicated server binary - OPENAL = '0' - ALSA = '0' if ( local_gamedll == 1 ): local_env.Append( CPPDEFINES = [ '__DOOM_DLL__' ] ) @@ -244,18 +242,6 @@ if ( local_demo == 1 ): if ( local_curl == 0 ): local_env.Append( CPPDEFINES = [ 'ID_ENABLE_CURL=0' ] ) -sound_env = local_env.Clone() -sound_list = [ '../linux/sound.cpp' ] -if ( OPENAL != '1' ): - sound_env.Append( CPPDEFINES = 'ID_OPENAL=0' ) - sound_list.append( '../../sys/stub/openal_stub.cpp' ) - -if ( g_os == "Linux" and ALSA != '0' ): - sound_list.append( '../../sys/linux/sound_alsa.cpp' ) -else: - sound_env.Append( CPPDEFINES = 'NO_ALSA' ) -sound_lib = sound_env.StaticLibrary( 'sound', sound_list ) - local_env.Append( LIBS = [ 'pthread', 'jpeg', 'vorbisfile' ] ) if ( local_dedicated == 0 ): @@ -269,13 +255,10 @@ if ( local_curl == 1 ): if ( local_dedicated == 0 ): local_env.Append( LIBS = [ 'X11', 'Xext', 'Xxf86vm' ] ) # 'Xxf86dga', local_env.Append( LIBPATH = [ '/usr/X11R6/lib' ] ) - -if ( OPENAL == '1' ): local_env.Append( LIBS = [ 'openal' ] ) source_list = core_list source_list += idlib_objects -source_list += sound_lib if ( local_gamedll == 0 ): source_list += game_objects diff --git a/neo/sys/win32/win_snd.cpp b/neo/sys/win32/win_snd.cpp deleted file mode 100644 index dc4954ae..00000000 --- a/neo/sys/win32/win_snd.cpp +++ /dev/null @@ -1,801 +0,0 @@ -/* -=========================================================================== - -Doom 3 GPL Source Code -Copyright (C) 1999-2011 id Software LLC, a ZeniMax Media company. - -This file is part of the Doom 3 GPL Source Code ("Doom 3 Source Code"). - -Doom 3 Source Code is free software: you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation, either version 3 of the License, or -(at your option) any later version. - -Doom 3 Source Code is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with Doom 3 Source Code. If not, see . - -In addition, the Doom 3 Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 Source Code. If not, please request a copy in writing from id Software at the address below. - -If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA. - -=========================================================================== -*/ -#include "../../idlib/precompiled.h" -#pragma hdrstop - -// DirectX SDK -#include - -#include -#include -#include "../../sound/snd_local.h" -#include "win_local.h" - -#define SAFE_DELETE(p) { if(p) { delete (p); (p)=NULL; } } -#define SAFE_DELETE_ARRAY(p) { if(p) { delete[] (p); (p)=NULL; } } -#define SAFE_RELEASE(p) { if(p) { (p)->Release(); (p)=NULL; } } - -class idAudioBufferWIN32 : public idAudioBuffer { -public: - idAudioBufferWIN32( LPDIRECTSOUNDBUFFER apDSBuffer, dword dwDSBufferSize, idWaveFile* pWaveFile=NULL ); - ~idAudioBufferWIN32(); - - int FillBufferWithSound( LPDIRECTSOUNDBUFFER pDSB, bool bRepeatWavIfBufferLarger ); - - bool Lock( void **pDSLockedBuffer, ulong *dwDSLockedBufferSize ); - bool Unlock(void *pDSLockedBuffer, dword dwDSLockedBufferSize ); - bool GetCurrentPosition( ulong *pdwCurrentWriteCursor ); - - int Play( dword dwPriority=0, dword dwFlags=0 ); - int Stop( void ); - int Reset( void ); - bool IsSoundPlaying( void ); - void SetVolume( float x); - - idWaveFile* m_pWaveFile; -private: - LPDIRECTSOUNDBUFFER m_apDSBuffer; - dword m_dwDSBufferSize; - - int RestoreBuffer( LPDIRECTSOUNDBUFFER pDSB, bool* pbWasRestored ); -}; - -class idAudioHardwareWIN32 : public idAudioHardware { - -public: - idAudioHardwareWIN32(); - ~idAudioHardwareWIN32(); - - bool Initialize( ); - bool InitializeSpeakers( byte *buffer, int bufferSize, dword dwPrimaryFreq, dword dwPrimaryBitRate, dword dwSpeakers ); - - void SetPrimaryBufferFormat( dword dwPrimaryFreq, dword dwPrimaryBitRate, dword dwSpeakers ); - - int Create( idWaveFile* pWaveFile, idAudioBuffer** ppiab ); - int Create( idAudioBuffer** ppSound, const char* strWaveFileName, dword dwCreationFlags = 0 ); - int CreateFromMemory( idAudioBufferWIN32** ppSound, byte* pbData, ulong ulDataSize, waveformatextensible_t *pwfx, dword dwCreationFlags = 0 ); - - bool Lock( void **pDSLockedBuffer, ulong *dwDSLockedBufferSize ); - bool Unlock( void *pDSLockedBuffer, dword dwDSLockedBufferSize ); - bool GetCurrentPosition( ulong *pdwCurrentWriteCursor ); - - int GetNumberOfSpeakers() { return numSpeakers; } - int GetMixBufferSize() { return MIXBUFFER_SAMPLES * blockAlign; } - - // WIN32 driver doesn't support write API - bool Flush( void ) { return true; } - void Write( bool ) { } - short* GetMixBuffer( void ) { return NULL; } - -private: - LPDIRECTSOUND m_pDS; - LPDIRECTSOUNDBUFFER pDSBPrimary; - idAudioBufferWIN32 *speakers; - - int numSpeakers; - int bitsPerSample; - int bufferSize; // allocate buffer handed over to DirectSound - int blockAlign; // channels * bits per sample / 8: sound frame size -}; - -idAudioHardware *idAudioHardware::Alloc() { return new idAudioHardwareWIN32; } -idAudioHardware::~idAudioHardware() {} - -/* -================ -idAudioHardwareWIN32::idAudioHardware -================ -*/ -idAudioHardwareWIN32::idAudioHardwareWIN32() { - m_pDS = NULL; - pDSBPrimary = NULL; - speakers = NULL; -} - -/* -================ -idAudioHardwareWIN32::~idAudioHardware -================ -*/ -idAudioHardwareWIN32::~idAudioHardwareWIN32() { - SAFE_DELETE( speakers ); - SAFE_RELEASE( pDSBPrimary ); - SAFE_RELEASE( m_pDS ); -} - -/* -=============== -idAudioHardwareWIN32::Initialize -=============== -*/ -bool idAudioHardwareWIN32::Initialize( void ) { - int hr; - - bufferSize = 0; - numSpeakers = 0; - blockAlign = 0; - - SAFE_RELEASE( m_pDS ); - - // Create IDirectSound using the primary sound device - if( FAILED( hr = DirectSoundCreate( NULL, &m_pDS, NULL ) )) { - return false; - } - - // Set primary buffer format - SetPrimaryBufferFormat( PRIMARYFREQ, 16, idSoundSystemLocal::s_numberOfSpeakers.GetInteger() ); - return true; -} - -/* -=============== -idAudioHardwareWIN32::InitializeSpeakers -=============== -*/ -bool idAudioHardwareWIN32::InitializeSpeakers( byte *speakerData, int bufferSize, dword dwPrimaryFreq, dword dwPrimaryBitRate, dword dwSpeakers ) { - if ( dwSpeakers == 2 ) { - WAVEFORMATEXTENSIBLE wfx; - ZeroMemory( &wfx, sizeof(WAVEFORMATEXTENSIBLE) ); - wfx.Format.wFormatTag = WAVE_FORMAT_PCM; - wfx.Format.nChannels = 2; - wfx.Format.nSamplesPerSec = dwPrimaryFreq; - wfx.Format.wBitsPerSample = dwPrimaryBitRate; - wfx.Format.nBlockAlign = wfx.Format.wBitsPerSample / 8 * wfx.Format.nChannels; - wfx.Format.nAvgBytesPerSec = wfx.Format.nSamplesPerSec * wfx.Format.nBlockAlign; - wfx.Format.cbSize = sizeof(WAVEFORMATEX); - - CreateFromMemory( &speakers, speakerData, bufferSize, (waveformatextensible_t *)&wfx ); - - common->Printf("sound: STEREO\n"); - } else { - WAVEFORMATEXTENSIBLE waveFormatPCMEx; - ZeroMemory( &waveFormatPCMEx, sizeof(WAVEFORMATEXTENSIBLE) ); - - waveFormatPCMEx.Format.wFormatTag = WAVE_FORMAT_EXTENSIBLE; - waveFormatPCMEx.Format.nChannels = 6; - waveFormatPCMEx.Format.nSamplesPerSec = dwPrimaryFreq; - waveFormatPCMEx.Format.wBitsPerSample = dwPrimaryBitRate; - waveFormatPCMEx.Format.nBlockAlign = waveFormatPCMEx.Format.wBitsPerSample / 8 * waveFormatPCMEx.Format.nChannels; - waveFormatPCMEx.Format.nAvgBytesPerSec = waveFormatPCMEx.Format.nSamplesPerSec * waveFormatPCMEx.Format.nBlockAlign; - waveFormatPCMEx.dwChannelMask = KSAUDIO_SPEAKER_5POINT1; - // SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT | - // SPEAKER_FRONT_CENTER | SPEAKER_LOW_FREQUENCY | - // SPEAKER_BACK_LEFT | SPEAKER_BACK_RIGHT - waveFormatPCMEx.SubFormat = KSDATAFORMAT_SUBTYPE_PCM; // Specify PCM - waveFormatPCMEx.Format.cbSize = sizeof(WAVEFORMATEXTENSIBLE); - waveFormatPCMEx.Samples.wValidBitsPerSample = 16; - - CreateFromMemory( &speakers, speakerData, bufferSize, (waveformatextensible_t *)&waveFormatPCMEx ); - - common->Printf("sound: MULTICHANNEL\n"); - } - - if (!speakers) { - return false; - } - - speakers->Play(0,DSBPLAY_LOOPING); - - return true; -} - -/* -=============== -idAudioHardwareWIN32::SetPrimaryBufferFormat -Set primary buffer to a specified format -For example, to set the primary buffer format to 22kHz stereo, 16-bit -then: dwPrimaryChannels = 2 - dwPrimaryFreq = 22050, - dwPrimaryBitRate = 16 -=============== -*/ -void idAudioHardwareWIN32::SetPrimaryBufferFormat( dword dwPrimaryFreq, dword dwPrimaryBitRate, dword dwSpeakers ) { - HRESULT hr; - - if( m_pDS == NULL ) { - return; - } - - ulong cfgSpeakers; - m_pDS->GetSpeakerConfig( &cfgSpeakers ); - - DSCAPS dscaps; - dscaps.dwSize = sizeof(DSCAPS); - m_pDS->GetCaps(&dscaps); - - if (dscaps.dwFlags & DSCAPS_EMULDRIVER) { - return; - } - - // Get the primary buffer - DSBUFFERDESC dsbd; - ZeroMemory( &dsbd, sizeof(DSBUFFERDESC) ); - dsbd.dwSize = sizeof(DSBUFFERDESC); - dsbd.dwFlags = DSBCAPS_PRIMARYBUFFER; - dsbd.dwBufferBytes = 0; - dsbd.lpwfxFormat = NULL; - - // Obtain write-primary cooperative level. - if( FAILED( hr = m_pDS->SetCooperativeLevel(win32.hWnd, DSSCL_PRIORITY ) ) ) { - DXTRACE_ERR( TEXT("SetPrimaryBufferFormat"), hr ); - return; - } - - if( FAILED( hr = m_pDS->CreateSoundBuffer( &dsbd, &pDSBPrimary, NULL ) ) ) { - return; - } - - if ( dwSpeakers == 6 && (cfgSpeakers == DSSPEAKER_5POINT1 || cfgSpeakers == DSSPEAKER_SURROUND) ) { - WAVEFORMATEXTENSIBLE waveFormatPCMEx; - ZeroMemory( &waveFormatPCMEx, sizeof(WAVEFORMATEXTENSIBLE) ); - - waveFormatPCMEx.Format.wFormatTag = WAVE_FORMAT_EXTENSIBLE; - waveFormatPCMEx.Format.nChannels = 6; - waveFormatPCMEx.Format.nSamplesPerSec = dwPrimaryFreq; - waveFormatPCMEx.Format.wBitsPerSample = (WORD) dwPrimaryBitRate; - waveFormatPCMEx.Format.nBlockAlign = waveFormatPCMEx.Format.wBitsPerSample / 8 * waveFormatPCMEx.Format.nChannels; - waveFormatPCMEx.Format.nAvgBytesPerSec = waveFormatPCMEx.Format.nSamplesPerSec * waveFormatPCMEx.Format.nBlockAlign; - waveFormatPCMEx.dwChannelMask = KSAUDIO_SPEAKER_5POINT1; - // SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT | - // SPEAKER_FRONT_CENTER | SPEAKER_LOW_FREQUENCY | - // SPEAKER_BACK_LEFT | SPEAKER_BACK_RIGHT - waveFormatPCMEx.SubFormat = KSDATAFORMAT_SUBTYPE_PCM; // Specify PCM - waveFormatPCMEx.Format.cbSize = sizeof(WAVEFORMATEXTENSIBLE); - waveFormatPCMEx.Samples.wValidBitsPerSample = 16; - - if( FAILED( hr = pDSBPrimary->SetFormat((WAVEFORMATEX*)&waveFormatPCMEx) ) ) { - DXTRACE_ERR( TEXT("SetPrimaryBufferFormat"), hr ); - return; - } - numSpeakers = 6; // force it to think 5.1 - blockAlign = waveFormatPCMEx.Format.nBlockAlign; - } else { - if (dwSpeakers == 6) { - common->Printf("sound: hardware reported unable to use multisound, defaulted to stereo\n"); - } - WAVEFORMATEX wfx; - ZeroMemory( &wfx, sizeof(WAVEFORMATEX) ); - wfx.wFormatTag = WAVE_FORMAT_PCM; - wfx.nChannels = 2; - wfx.nSamplesPerSec = dwPrimaryFreq; - wfx.wBitsPerSample = (WORD) dwPrimaryBitRate; - wfx.nBlockAlign = wfx.wBitsPerSample / 8 * wfx.nChannels; - wfx.nAvgBytesPerSec = wfx.nSamplesPerSec * wfx.nBlockAlign; - wfx.cbSize = sizeof(WAVEFORMATEX); - - if( FAILED( hr = pDSBPrimary->SetFormat(&wfx) ) ) { - return; - } - numSpeakers = 2; // force it to think stereo - blockAlign = wfx.nBlockAlign; - } - - byte *speakerData; - bufferSize = MIXBUFFER_SAMPLES * sizeof(word) * numSpeakers * ROOM_SLICES_IN_BUFFER; - speakerData = (byte *)Mem_Alloc( bufferSize ); - memset( speakerData, 0, bufferSize ); - - InitializeSpeakers( speakerData, bufferSize, dwPrimaryFreq, dwPrimaryBitRate, numSpeakers ); -} - -/* -=============== -idAudioHardwareWIN32::Create -=============== -*/ -int idAudioHardwareWIN32::Create( idAudioBuffer** ppSound, - const char* strWaveFileName, - dword dwCreationFlags ) { - int hr; - LPDIRECTSOUNDBUFFER apDSBuffer = NULL; - dword dwDSBufferSize = NULL; - idWaveFile* pWaveFile = NULL; - - if( m_pDS == NULL ) - return -1; - if( strWaveFileName == NULL || ppSound == NULL ) - return -1; - - pWaveFile = new idWaveFile(); - - pWaveFile->Open( strWaveFileName, NULL ); - - if( pWaveFile->GetOutputSize() == 0 ) { - // Wave is blank, so don't create it. - hr = E_FAIL; - goto LFail; - } - - // Make the DirectSound buffer the same size as the wav file - dwDSBufferSize = pWaveFile->GetOutputSize(); - - // Create the direct sound buffer, and only request the flags needed - // since each requires some overhead and limits if the buffer can - // be hardware accelerated - DSBUFFERDESC dsbd; - memset( &dsbd, 0, sizeof(DSBUFFERDESC) ); - dsbd.dwSize = sizeof(DSBUFFERDESC); - dsbd.dwFlags = dwCreationFlags; - dsbd.dwBufferBytes = dwDSBufferSize; - dsbd.guid3DAlgorithm = GUID_NULL; - dsbd.lpwfxFormat = (WAVEFORMATEX*)&pWaveFile->mpwfx; - - // DirectSound is only guarenteed to play PCM data. Other - // formats may or may not work depending the sound card driver. - if( FAILED( hr = m_pDS->CreateSoundBuffer( &dsbd, &apDSBuffer, NULL ) ) ) - return -1; - - // Create the sound - *ppSound = new idAudioBufferWIN32( apDSBuffer, dwDSBufferSize, pWaveFile ); - - pWaveFile->Close(); - - return 0; - -LFail: - // Cleanup - SAFE_DELETE( pWaveFile ); - return -1; -} - -/* -=============== -idAudioHardwareWIN32::Create -=============== -*/ -int idAudioHardwareWIN32::Create( idWaveFile* pWaveFile, idAudioBuffer** ppiab ) { - int hr; - LPDIRECTSOUNDBUFFER apDSBuffer = NULL; - dword dwDSBufferSize = NULL; - - if( m_pDS == NULL ) - return -1; - - if( pWaveFile == NULL ) - return -1; - - *ppiab = NULL; - - if( pWaveFile->GetOutputSize() == 0 ) { - // Wave is blank, so don't create it. - hr = E_FAIL; - goto LFail; - } - - // Make the DirectSound buffer the same size as the wav file - dwDSBufferSize = pWaveFile->GetOutputSize(); - - // Create the direct sound buffer, and only request the flags needed - // since each requires some overhead and limits if the buffer can - // be hardware accelerated - DSBUFFERDESC dsbd; - memset( &dsbd, 0, sizeof(DSBUFFERDESC) ); - dsbd.dwSize = sizeof(DSBUFFERDESC); - dsbd.dwFlags = 0; - dsbd.dwBufferBytes = dwDSBufferSize; - dsbd.guid3DAlgorithm = GUID_NULL; - dsbd.lpwfxFormat = (WAVEFORMATEX*)&pWaveFile->mpwfx; - - // DirectSound is only guarenteed to play PCM data. Other - // formats may or may not work depending the sound card driver. - if( FAILED( hr = m_pDS->CreateSoundBuffer( &dsbd, &apDSBuffer, NULL ) ) ) - return -1; - - // Create the sound - *ppiab = new idAudioBufferWIN32( apDSBuffer, dwDSBufferSize, pWaveFile ); - - return 0; - -LFail: - // Cleanup - SAFE_DELETE( pWaveFile ); - return -1; -} - -//----------------------------------------------------------------------------- -// Name: idAudioHardwareWIN32::CreateFromMemory() -// Desc: -//----------------------------------------------------------------------------- -int idAudioHardwareWIN32::CreateFromMemory( idAudioBufferWIN32** ppSound, - byte* pbData, - ulong ulDataSize, - waveformatextensible_t* pwfx, - dword dwCreationFlags ) { - int hr; - LPDIRECTSOUNDBUFFER apDSBuffer = NULL; - dword dwDSBufferSize = NULL; - idWaveFile* pWaveFile = NULL; - - if( m_pDS == NULL ) - return -1; - if( pbData == NULL || ppSound == NULL ) - return -1; - - pWaveFile = new idWaveFile(); - - pWaveFile->OpenFromMemory( (short *)pbData, ulDataSize, (waveformatextensible_t *)pwfx); - - - // Make the DirectSound buffer the same size as the wav file - dwDSBufferSize = ulDataSize; - - // Create the direct sound buffer, and only request the flags needed - // since each requires some overhead and limits if the buffer can - // be hardware accelerated - DSBUFFERDESC dsbd; - memset( &dsbd, 0, sizeof(DSBUFFERDESC) ); - dsbd.dwSize = sizeof(DSBUFFERDESC); - dsbd.dwFlags = dwCreationFlags | DSBCAPS_GETCURRENTPOSITION2; - dsbd.dwBufferBytes = dwDSBufferSize; - dsbd.guid3DAlgorithm = GUID_NULL; - dsbd.lpwfxFormat = (WAVEFORMATEX *)pwfx; - - if( FAILED( hr = m_pDS->CreateSoundBuffer( &dsbd, &apDSBuffer, NULL ) ) ) - return -1; - - // Create the sound - *ppSound = new idAudioBufferWIN32( apDSBuffer, dwDSBufferSize, pWaveFile ); - - return S_OK; -} - -/* -=============== -idAudioHardwareWIN32::Lock -=============== -*/ -bool idAudioHardwareWIN32::Lock( void **pDSLockedBuffer, ulong *dwDSLockedBufferSize ) { - if (speakers) { - return speakers->Lock( pDSLockedBuffer, dwDSLockedBufferSize ); - } - return false; -} - -/* -=============== -idAudioHardwareWIN32::Unlock -=============== -*/ -bool idAudioHardwareWIN32::Unlock(void *pDSLockedBuffer, dword dwDSLockedBufferSize ) { - if (speakers) { - return speakers->Unlock( pDSLockedBuffer, dwDSLockedBufferSize ); - } - return false; -} - -/* -=============== -idAudioHardwareWIN32::GetCurrentPosition -=============== -*/ -bool idAudioHardwareWIN32::GetCurrentPosition( ulong *pdwCurrentWriteCursor ) { - if (speakers) { - return speakers->GetCurrentPosition( pdwCurrentWriteCursor ); - } - return false; -} - -/* -=============== -idAudioBufferWIN32::idAudioBuffer -=============== -*/ -idAudioBufferWIN32::idAudioBufferWIN32( LPDIRECTSOUNDBUFFER apDSBuffer, dword dwDSBufferSize, idWaveFile* pWaveFile ) { - - m_apDSBuffer = apDSBuffer; - - m_dwDSBufferSize = dwDSBufferSize; - m_pWaveFile = pWaveFile; - - if (pWaveFile) { - FillBufferWithSound( m_apDSBuffer, false ); - - m_apDSBuffer->SetCurrentPosition(0); - } -} - -/* -=============== -idAudioBufferWIN32::~idAudioBuffer -=============== -*/ -idAudioBufferWIN32::~idAudioBufferWIN32() { - SAFE_DELETE(m_pWaveFile); - SAFE_RELEASE( m_apDSBuffer ); - m_pWaveFile = NULL; - m_apDSBuffer = NULL; -} - -/* -=============== -idAudioBufferWIN32::FillBufferWithSound -=============== -*/ -int idAudioBufferWIN32::FillBufferWithSound( LPDIRECTSOUNDBUFFER pDSB, bool bRepeatWavIfBufferLarger ) { - int hr; - void* pDSLockedBuffer = NULL; // Pointer to locked buffer memory - ulong dwDSLockedBufferSize = 0; // Size of the locked DirectSound buffer - int dwWavDataRead = 0; // Amount of data read from the wav file - - if( pDSB == NULL ) - return -1; - - // we may not even have a wavefile - if (m_pWaveFile==NULL) { - return -1; - } - - // Make sure we have focus, and we didn't just switch in from - // an app which had a DirectSound device - if( FAILED( hr = RestoreBuffer( pDSB, NULL ) ) ) { - DXTRACE_ERR( TEXT("RestoreBuffer"), hr ); - return -1; - } - - // Lock the buffer down - if( FAILED( hr = pDSB->Lock( 0, m_dwDSBufferSize, &pDSLockedBuffer, &dwDSLockedBufferSize, NULL, NULL, 0L ) ) ) { - DXTRACE_ERR( TEXT("Lock"), hr ); - return -1; - } - - // Reset the wave file to the beginning - m_pWaveFile->ResetFile(); - - if( FAILED( hr = m_pWaveFile->Read( (byte*) pDSLockedBuffer, dwDSLockedBufferSize, &dwWavDataRead ) ) ) { - return DXTRACE_ERR( TEXT("Read"), hr ); - } - - if( dwWavDataRead == 0 ) { - // Wav is blank, so just fill with silence - memset( pDSLockedBuffer, (byte)(m_pWaveFile->mpwfx.Format.wBitsPerSample == 8 ? 128 : 0 ), dwDSLockedBufferSize ); - } else if( dwWavDataRead < (int)dwDSLockedBufferSize ) { - // If the wav file was smaller than the DirectSound buffer, - // we need to fill the remainder of the buffer with data - if( bRepeatWavIfBufferLarger ) { - // Reset the file and fill the buffer with wav data - int dwReadSoFar = dwWavDataRead; // From previous call above. - while( dwReadSoFar < (int)dwDSLockedBufferSize ) { - // This will keep reading in until the buffer is full - // for very short files - if( FAILED( hr = m_pWaveFile->ResetFile() ) ) { - return DXTRACE_ERR( TEXT("ResetFile"), hr ); - } - - hr = m_pWaveFile->Read( (byte*)pDSLockedBuffer + dwReadSoFar, dwDSLockedBufferSize - dwReadSoFar, &dwWavDataRead ); - if( FAILED(hr) ) { - return DXTRACE_ERR( TEXT("Read"), hr ); - } - - dwReadSoFar += dwWavDataRead; - } - } else { - // Don't repeat the wav file, just fill in silence - memset( (byte*) pDSLockedBuffer + dwWavDataRead, (byte)(m_pWaveFile->mpwfx.Format.wBitsPerSample == 8 ? 128 : 0 ), dwDSLockedBufferSize - dwWavDataRead); - } - } - - // Unlock the buffer, we don't need it anymore. - pDSB->Unlock( pDSLockedBuffer, dwDSLockedBufferSize, NULL, 0 ); - - return S_OK; -} - -/* -=============== -idAudioBufferWIN32::RestoreBuffer -Desc: Restores the lost buffer. *pbWasRestored returns true if the buffer was - restored. It can also NULL if the information is not needed. -=============== -*/ -int idAudioBufferWIN32::RestoreBuffer( LPDIRECTSOUNDBUFFER pDSB, bool* pbWasRestored ) { - int hr; - - if( pDSB == NULL ) { - return -1; - } - if( pbWasRestored ) { - *pbWasRestored = false; - } - - ulong dwStatus; - if( FAILED( hr = pDSB->GetStatus( &dwStatus ) ) ) { - return DXTRACE_ERR( TEXT("GetStatus"), hr ); - } - - if( dwStatus & DSBSTATUS_BUFFERLOST ) { - // Since the app could have just been activated, then - // DirectSound may not be giving us control yet, so - // the restoring the buffer may fail. - // If it does, sleep until DirectSound gives us control. - do { - hr = pDSB->Restore(); - if( hr == DSERR_BUFFERLOST ) { - Sleep( 10 ); - } - hr = pDSB->Restore(); - } while( hr ); - - if( pbWasRestored != NULL ) { - *pbWasRestored = true; - } - - return S_OK; - } else { - return S_FALSE; - } -} - -/* -=============== -idAudioBufferWIN32::Play -Desc: Plays the sound using voice management flags. Pass in DSBPLAY_LOOPING - in the dwFlags to loop the sound -=============== -*/ -int idAudioBufferWIN32::Play( dword dwPriority, dword dwFlags ) { - int hr; - bool bRestored; - - if( m_apDSBuffer == NULL ) { - return -1; - } - - // Restore the buffer if it was lost - if( FAILED( hr = RestoreBuffer( m_apDSBuffer, &bRestored ) ) ) { - common->Error( TEXT("RestoreBuffer"), hr ); - } - - if( bRestored ) { - // The buffer was restored, so we need to fill it with new data - if( FAILED( hr = FillBufferWithSound( m_apDSBuffer, false ) ) ) { - common->Error( TEXT("FillBufferWithSound"), hr ); - } - - // Make DirectSound do pre-processing on sound effects - Reset(); - } - - m_apDSBuffer->Play( 0, dwPriority, dwFlags ); - return 0; -} - -/* -=============== -idAudioBufferWIN32::Stop -Desc: Stops the sound from playing -=============== -*/ -int idAudioBufferWIN32::Stop() { - if( this == NULL || m_apDSBuffer == NULL ) { - return -1; - } - - m_apDSBuffer->Stop(); - - return 0; -} - -/* -=============== -idAudioBufferWIN32::Reset -Desc: Reset all of the sound buffers -=============== -*/ -int idAudioBufferWIN32::Reset() { - if( m_apDSBuffer == NULL ) { - return -1; - } - - m_apDSBuffer->SetCurrentPosition( 0 ); - - return 0; -} - -/* -=============== -idAudioBufferWIN32::IsSoundPlaying -Desc: Checks to see if a buffer is playing and returns true if it -=============== -*/ -bool idAudioBufferWIN32::IsSoundPlaying( ) { - if( m_apDSBuffer == NULL ) { - return false; - } - - if( m_apDSBuffer ) { - ulong dwStatus = 0; - m_apDSBuffer->GetStatus( &dwStatus ); - if ( dwStatus & DSBSTATUS_PLAYING ) { - return true; - } - } - return false; -} - -/* -=============== -idAudioBufferWIN32::Lock -=============== -*/ -bool idAudioBufferWIN32::Lock( void **pDSLockedBuffer, ulong *dwDSLockedBufferSize ) { - int hr; - // Restore the buffer if it was lost - bool bRestored; - if( FAILED( hr = RestoreBuffer( m_apDSBuffer, &bRestored ) ) ) { - return false; - } - - // Lock the DirectSound buffer - if( FAILED( hr = m_apDSBuffer->Lock( 0, m_dwDSBufferSize, pDSLockedBuffer, dwDSLockedBufferSize, NULL, NULL, 0 ) ) ) { - return false; - } - return true; -} - -/* -=============== -idAudioBufferWIN32::Unlock -=============== -*/ -bool idAudioBufferWIN32::Unlock(void *pDSLockedBuffer, dword dwDSLockedBufferSize ) { - // Unlock the DirectSound buffer - m_apDSBuffer->Unlock( pDSLockedBuffer, dwDSLockedBufferSize, NULL, 0 ); - return true; -} - -/* -=============== -idAudioBufferWIN32::GetCurrentPosition -=============== -*/ -bool idAudioBufferWIN32::GetCurrentPosition( ulong *pdwCurrentWriteCursor ) { - int hr; - - // Make sure we have focus, and we didn't just switch in from - // an app which had a DirectSound device - if( FAILED( hr = RestoreBuffer( m_apDSBuffer, NULL ) ) ) { - DXTRACE_ERR( TEXT("RestoreBuffer"), hr ); - return false; - } - - if( FAILED( hr = m_apDSBuffer->GetCurrentPosition( NULL, pdwCurrentWriteCursor ) ) ) { - return false; - } - return true; -} - -/* -=============== -idAudioBufferWIN32::SetVolume -=============== -*/ -void idAudioBufferWIN32::SetVolume( float x) { - if (m_apDSBuffer) { - m_apDSBuffer->SetVolume(x); - } -}