From 51c5fa94aa9592d2c25209b94b6cbe4349850cbd Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Sat, 22 Dec 2007 13:35:52 -0800 Subject: [PATCH 01/33] Check for snprintf, and use _snprintf when needed --- CMakeLists.txt | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index 0dea95a6..ea296b72 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -115,6 +115,16 @@ IF(NOT "${HAVE_STRCASECMP}") ADD_DEFINITIONS(-Dstrcasecmp=_stricmp) ENDIF() +CHECK_FUNCTION_EXISTS(snprintf HAVE_SNPRINTF) +IF(NOT "${HAVE_SNPRINTF}") + CHECK_FUNCTION_EXISTS(_snprintf HAVE__SNPRINTF) + IF(NOT "${HAVE__SNPRINTF}") + MESSAGE(FATAL_ERROR "No snprintf function found, please report!") + ENDIF() + + ADD_DEFINITIONS(-Dsnprintf=_snprintf) +ENDIF() + # Check for the dlopen API (for dynamicly loading backend libs) IF(DLOPEN) CHECK_INCLUDE_FILE(dlfcn.h HAVE_DLFCN_H) From e516b3c0d317f2cceb5de6690705bfc6ff69f615 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Sat, 22 Dec 2007 14:00:10 -0800 Subject: [PATCH 02/33] Prevent possible buffer overflow in AL_PRINT --- OpenAL32/Include/alMain.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/OpenAL32/Include/alMain.h b/OpenAL32/Include/alMain.h index 71e29e47..1f62b535 100644 --- a/OpenAL32/Include/alMain.h +++ b/OpenAL32/Include/alMain.h @@ -82,7 +82,9 @@ extern char _alDebug[256]; if(!_al_print_fn) _al_print_fn = __FILE__; \ else _al_print_fn += 1; \ _al_print_i = snprintf(_alDebug, sizeof(_alDebug), "AL lib: %s:%d: ", _al_print_fn, __LINE__); \ - snprintf(_alDebug+_al_print_i, sizeof(_alDebug)-_al_print_i, __VA_ARGS__); \ + if(_al_print_i < (int)sizeof(_alDebug) && _al_print_i > 0) \ + snprintf(_alDebug+_al_print_i, sizeof(_alDebug)-_al_print_i, __VA_ARGS__); \ + _alDebug[sizeof(_alDebug)-1] = 0; \ fprintf(stderr, "%s", _alDebug); \ } while(0) From a48201ed94225ab103164b7a95946c1e6a586e69 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Sun, 23 Dec 2007 16:27:05 -0800 Subject: [PATCH 03/33] Fix target opts to remove prefix on the win32 dll CMake didn't like the previous attempt --- CMakeLists.txt | 21 ++++++++++----------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index ea296b72..5f107e5d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -33,15 +33,6 @@ SET(LIB_BUILD_VERSION "38") SET(LIB_VERSION "${LIB_MAJOR_VERSION}.${LIB_MINOR_VERSION}.${LIB_BUILD_VERSION}") -IF("${WIN32}") - SET(LIBNAME openal32) - SET(TARGET_OPTS "PREFIX \"\"") -ELSE() - SET(LIBNAME openal) - SET(TARGET_OPTS "") -ENDIF() - - CHECK_TYPE_SIZE("long" SIZEOF_LONG) CHECK_TYPE_SIZE("long long" SIZEOF_LONG_LONG) CHECK_TYPE_SIZE("unsigned int" SIZEOF_UINT) @@ -267,10 +258,18 @@ CONFIGURE_FILE( ADD_DEFINITIONS(-DAL_BUILD_LIBRARY) # Build a shared library +IF("${WIN32}") + SET(LIBNAME openal32) +ELSE() + SET(LIBNAME openal) +ENDIF() + ADD_LIBRARY(${LIBNAME} SHARED ${OPENAL_OBJS} ${ALC_OBJS}) SET_TARGET_PROPERTIES(${LIBNAME} PROPERTIES VERSION ${LIB_VERSION} - SOVERSION ${LIB_MAJOR_VERSION} - ${TARGET_OPTS}) + SOVERSION ${LIB_MAJOR_VERSION}) +IF("${WIN32}") + SET_TARGET_PROPERTIES(${LIBNAME} PROPERTIES PREFIX "") +ENDIF() TARGET_LINK_LIBRARIES(${LIBNAME} ${EXTRA_LIBS}) From 2ee389044bc6ff1a8b066eb70f41cc8ec883f5fa Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Sun, 23 Dec 2007 16:28:09 -0800 Subject: [PATCH 04/33] Check for libm before including it --- CMakeLists.txt | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 5f107e5d..d7093fa5 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -41,7 +41,6 @@ CHECK_TYPE_SIZE("void*" SIZEOF_VOIDP) # Add definitions, compiler switches, etc. INCLUDE_DIRECTORIES(OpenAL32/Include include "${OpenAL_BINARY_DIR}") -SET(EXTRA_LIBS m ${EXTRA_LIBS}) IF("${MSVC}") # ??? @@ -94,6 +93,9 @@ ELSEIF(NODEBUG) ENDIF() CHECK_LIBRARY_EXISTS(m sqrtf "" HAVE_SQRTF) +IF("${HAVE_SQRTF}") + SET(EXTRA_LIBS m ${EXTRA_LIBS}) +ENDIF() CHECK_FUNCTION_EXISTS(strtof HAVE_STRTOF) CHECK_FUNCTION_EXISTS(strcasecmp HAVE_STRCASECMP) From dcac0de44ce1856fea0ff2d8d71feb2346aa911c Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Wed, 26 Dec 2007 17:38:42 -0800 Subject: [PATCH 05/33] Allow empty device specifiers when opening; treat them like NULL --- Alc/ALc.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/Alc/ALc.c b/Alc/ALc.c index b4ec8e9f..fa591174 100644 --- a/Alc/ALc.c +++ b/Alc/ALc.c @@ -409,6 +409,9 @@ ALCAPI ALCdevice* ALCAPIENTRY alcCaptureOpenDevice(const ALCchar *deviceName, AL InitAL(); + if(deviceName && !deviceName[0]) + deviceName = NULL; + pDevice = malloc(sizeof(ALCdevice)); if (pDevice) { @@ -1034,6 +1037,9 @@ ALCAPI ALCdevice* ALCAPIENTRY alcOpenDevice(const ALCchar *deviceName) InitAL(); + if(deviceName && !deviceName[0]) + deviceName = NULL; + device = malloc(sizeof(ALCdevice)); if (device) { From ab8d342df06fdfcc1b630e318e121bcfb6a1cdfa Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Wed, 26 Dec 2007 23:01:22 -0800 Subject: [PATCH 06/33] Allow 5.1 channel output This doesn't use the center or LFE channel in spatial calculations, however --- Alc/ALu.c | 31 +++++++++++++++++++++++++++++-- OpenAL32/Include/alMain.h | 4 +++- OpenAL32/Include/alu.h | 2 +- OpenAL32/alExtension.c | 2 ++ 4 files changed, 35 insertions(+), 4 deletions(-) diff --git a/Alc/ALu.c b/Alc/ALu.c index 87764592..3e8ddd89 100644 --- a/Alc/ALu.c +++ b/Alc/ALu.c @@ -59,11 +59,13 @@ __inline ALuint aluBytesFromFormat(ALenum format) case AL_FORMAT_MONO8: case AL_FORMAT_STEREO8: case AL_FORMAT_QUAD8: + case AL_FORMAT_51CHN8: return 1; case AL_FORMAT_MONO16: case AL_FORMAT_STEREO16: case AL_FORMAT_QUAD16: + case AL_FORMAT_51CHN16: return 2; default: @@ -87,6 +89,10 @@ __inline ALuint aluChannelsFromFormat(ALenum format) case AL_FORMAT_QUAD16: return 4; + case AL_FORMAT_51CHN8: + case AL_FORMAT_51CHN16: + return 6; + default: return 0; } @@ -340,6 +346,9 @@ static ALvoid CalcSourceParams(ALCcontext *ALContext, ALsource *ALSource, break; case AL_FORMAT_QUAD8: case AL_FORMAT_QUAD16: + /* TODO: Add center/lfe channel in spatial calculations? */ + case AL_FORMAT_51CHN8: + case AL_FORMAT_51CHN16: // Apply a scalar so each individual speaker has more weight PanningLR = 0.5f + (0.5f*Position[0]*1.41421356f); PanningLR = __min(1.0f, PanningLR); @@ -367,10 +376,14 @@ static ALvoid CalcSourceParams(ALCcontext *ALContext, ALsource *ALSource, drysend[1] = SourceVolume * 1.0f * ListenerGain; drysend[2] = SourceVolume * 1.0f * ListenerGain; drysend[3] = SourceVolume * 1.0f * ListenerGain; + drysend[4] = SourceVolume * 1.0f * ListenerGain; + drysend[5] = SourceVolume * 1.0f * ListenerGain; wetsend[0] = SourceVolume * 0.0f * ListenerGain; wetsend[1] = SourceVolume * 0.0f * ListenerGain; wetsend[2] = SourceVolume * 0.0f * ListenerGain; wetsend[3] = SourceVolume * 0.0f * ListenerGain; + wetsend[4] = SourceVolume * 0.0f * ListenerGain; + wetsend[5] = SourceVolume * 0.0f * ListenerGain; pitch[0] = Pitch; } @@ -380,8 +393,8 @@ ALvoid aluMixData(ALCcontext *ALContext,ALvoid *buffer,ALsizei size,ALenum forma { static float DryBuffer[BUFFERSIZE][OUTPUTCHANNELS]; static float WetBuffer[BUFFERSIZE][OUTPUTCHANNELS]; - ALfloat DrySend[OUTPUTCHANNELS] = { 0.0f, 0.0f, 0.0f, 0.0f }; - ALfloat WetSend[OUTPUTCHANNELS] = { 0.0f, 0.0f, 0.0f, 0.0f }; + ALfloat DrySend[OUTPUTCHANNELS] = { 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f }; + ALfloat WetSend[OUTPUTCHANNELS] = { 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f }; ALuint BlockAlign,BufferSize; ALuint DataSize=0,DataPosInt=0,DataPosFrac=0; ALuint Channels,Bits,Frequency,ulExtraSamples; @@ -641,6 +654,13 @@ ALvoid aluMixData(ALCcontext *ALContext,ALvoid *buffer,ALsizei size,ALenum forma buffer = ((ALubyte*)buffer) + 1; } break; + case AL_FORMAT_51CHN8: + for(i = 0;i < SamplesToDo*6;i++) + { + *((ALubyte*)buffer) = (ALubyte)((aluF2S(DryBuffer[i/6][i%6]+WetBuffer[i/6][i%6])>>8)+128); + buffer = ((ALubyte*)buffer) + 1; + } + break; case AL_FORMAT_MONO16: for(i = 0;i < SamplesToDo;i++) { @@ -663,6 +683,13 @@ ALvoid aluMixData(ALCcontext *ALContext,ALvoid *buffer,ALsizei size,ALenum forma buffer = ((ALshort*)buffer) + 1; } break; + case AL_FORMAT_51CHN16: + for(i = 0;i < SamplesToDo*6;i++) + { + *((ALshort*)buffer) = aluF2S(DryBuffer[i/6][i%6]+WetBuffer[i/6][i%6]); + buffer = ((ALshort*)buffer) + 1; + } + break; } size -= SamplesToDo; diff --git a/OpenAL32/Include/alMain.h b/OpenAL32/Include/alMain.h index 1f62b535..30dd068f 100644 --- a/OpenAL32/Include/alMain.h +++ b/OpenAL32/Include/alMain.h @@ -92,9 +92,11 @@ extern char _alDebug[256]; #define AL_FORMAT_MONO_IMA4 0x1300 #define AL_FORMAT_STEREO_IMA4 0x1301 // These are from AL_EXT_MCFORMATS, which we don't support yet but the mixer -// can use 4-channel formats +// can use the extra formats #define AL_FORMAT_QUAD8 0x1204 #define AL_FORMAT_QUAD16 0x1205 +#define AL_FORMAT_51CHN8 0x120A +#define AL_FORMAT_51CHN16 0x120B #define SWMIXER_OUTPUT_RATE 44100 //#define OUTPUT_BUFFER_SIZE (32768*SWMIXER_OUTPUT_RATE/22050) diff --git a/OpenAL32/Include/alu.h b/OpenAL32/Include/alu.h index e4fe0dc3..ecf32e5c 100644 --- a/OpenAL32/Include/alu.h +++ b/OpenAL32/Include/alu.h @@ -5,7 +5,7 @@ #define FRACTIONBITS 14 #define FRACTIONMASK ((1L< Date: Wed, 26 Dec 2007 23:29:32 -0800 Subject: [PATCH 07/33] Don't check explicitly against formats, but rather their byte/channel count --- Alc/ALu.c | 14 +++++--------- Alc/alsa.c | 10 +++------- Alc/dsound.c | 2 +- Alc/oss.c | 20 ++++++-------------- 4 files changed, 15 insertions(+), 31 deletions(-) diff --git a/Alc/ALu.c b/Alc/ALu.c index 3e8ddd89..b5af500b 100644 --- a/Alc/ALu.c +++ b/Alc/ALu.c @@ -327,28 +327,24 @@ static ALvoid CalcSourceParams(ALCcontext *ALContext, ALsource *ALSource, //6. Convert normalized position into pannings, then into channel volumes aluNormalize(Position); - switch(OutputFormat) + switch(aluChannelsFromFormat(OutputFormat)) { - case AL_FORMAT_MONO8: - case AL_FORMAT_MONO16: + case 1: drysend[0] = ConeVolume * ListenerGain * DryMix * aluSqrt(1.0f); //Direct drysend[1] = ConeVolume * ListenerGain * DryMix * aluSqrt(1.0f); //Direct wetsend[0] = ListenerGain * WetMix * aluSqrt(1.0f); //Room wetsend[1] = ListenerGain * WetMix * aluSqrt(1.0f); //Room break; - case AL_FORMAT_STEREO8: - case AL_FORMAT_STEREO16: + case 2: PanningLR = 0.5f + 0.5f*Position[0]; drysend[0] = ConeVolume * ListenerGain * DryMix * aluSqrt(1.0f-PanningLR); //L Direct drysend[1] = ConeVolume * ListenerGain * DryMix * aluSqrt( PanningLR); //R Direct wetsend[0] = ListenerGain * WetMix * aluSqrt(1.0f-PanningLR); //L Room wetsend[1] = ListenerGain * WetMix * aluSqrt( PanningLR); //R Room break; - case AL_FORMAT_QUAD8: - case AL_FORMAT_QUAD16: + case 4: /* TODO: Add center/lfe channel in spatial calculations? */ - case AL_FORMAT_51CHN8: - case AL_FORMAT_51CHN16: + case 6: // Apply a scalar so each individual speaker has more weight PanningLR = 0.5f + (0.5f*Position[0]*1.41421356f); PanningLR = __min(1.0f, PanningLR); diff --git a/Alc/alsa.c b/Alc/alsa.c index 2a46eff0..a6035d46 100644 --- a/Alc/alsa.c +++ b/Alc/alsa.c @@ -324,16 +324,12 @@ open_alsa: return ALC_FALSE; } - switch(device->Format) + switch(aluBytesFromFormat(device->Format)) { - case AL_FORMAT_MONO8: - case AL_FORMAT_STEREO8: - case AL_FORMAT_QUAD8: + case 1: data->format = SND_PCM_FORMAT_U8; break; - case AL_FORMAT_MONO16: - case AL_FORMAT_STEREO16: - case AL_FORMAT_QUAD16: + case 2: data->format = SND_PCM_FORMAT_S16; break; default: diff --git a/Alc/dsound.c b/Alc/dsound.c index a2b036a1..90a422a2 100644 --- a/Alc/dsound.c +++ b/Alc/dsound.c @@ -129,7 +129,7 @@ static ALCboolean DSoundOpenPlayback(ALCdevice *device, const ALCchar *deviceNam memset(&OutputType, 0, sizeof(WAVEFORMATEX)); OutputType.wFormatTag = WAVE_FORMAT_PCM; OutputType.nChannels = device->Channels; - OutputType.wBitsPerSample = (((device->Format==AL_FORMAT_MONO16)||(device->Format==AL_FORMAT_STEREO16)||(device->Format==AL_FORMAT_QUAD16))?16:8); + OutputType.wBitsPerSample = aluBytesFromFormat(device->Format) * 8; OutputType.nBlockAlign = OutputType.nChannels*OutputType.wBitsPerSample/8; OutputType.nSamplesPerSec = device->Frequency; OutputType.nAvgBytesPerSec = OutputType.nSamplesPerSec*OutputType.nBlockAlign; diff --git a/Alc/oss.c b/Alc/oss.c index de8f6e43..a63acb9b 100644 --- a/Alc/oss.c +++ b/Alc/oss.c @@ -174,17 +174,13 @@ static ALCboolean oss_open_playback(ALCdevice *device, const ALCchar *deviceName return ALC_FALSE; } - switch(device->Format) + switch(aluBytesFromFormat(device->Format)) { - case AL_FORMAT_MONO8: - case AL_FORMAT_STEREO8: - case AL_FORMAT_QUAD8: + case 1: data->silence = 0x80; ossFormat = AFMT_U8; break; - case AL_FORMAT_MONO16: - case AL_FORMAT_STEREO16: - case AL_FORMAT_QUAD16: + case 2: data->silence = 0; ossFormat = AFMT_S16_NE; break; @@ -337,17 +333,13 @@ static ALCboolean oss_open_capture(ALCdevice *device, const ALCchar *deviceName, return ALC_FALSE; } - switch(format) + switch(aluBytesFromFormat(format)) { - case AL_FORMAT_MONO8: - case AL_FORMAT_STEREO8: - case AL_FORMAT_QUAD8: + case 1: data->silence = 0x80; ossFormat = AFMT_U8; break; - case AL_FORMAT_MONO16: - case AL_FORMAT_STEREO16: - case AL_FORMAT_QUAD16: + case 2: data->silence = 0; ossFormat = AFMT_S16_NE; break; From 9eed1e8609abd1760c26a3983e47d4c18b9c1aa4 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Thu, 27 Dec 2007 01:00:19 -0800 Subject: [PATCH 08/33] Add new output formats to sample config --- openalrc.sample | 2 ++ 1 file changed, 2 insertions(+) diff --git a/openalrc.sample b/openalrc.sample index ca6fe390..c456d544 100644 --- a/openalrc.sample +++ b/openalrc.sample @@ -12,9 +12,11 @@ format = AL_FORMAT_STEREO16 # Sets the output format. Can be one of: # AL_FORMAT_MONO8 (8-bit mono) # AL_FORMAT_STEREO8 (8-bit stereo) # AL_FORMAT_QUAD8 (8-bit 4-channel) + # AL_FORMAT_51CHN8 (8-bit 5.1 output) # AL_FORMAT_MONO16 (16-bit mono) # AL_FORMAT_STEREO16 (16-bit stereo) # AL_FORMAT_QUAD16 (16-bit 4-channel) + # AL_FORMAT_51CHN16 (16-bit 5.1 output) # Default is AL_FORMAT_STEREO16 frequency = 44100 # Sets the output frequency. Default is 44100 From d7bf7a8b0d638b167bae04503305ed081eb9d640 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Fri, 28 Dec 2007 18:53:46 -0800 Subject: [PATCH 09/33] Don't rely on the exact formats as much for sources --- OpenAL32/alSource.c | 28 ++++++++++++++++++---------- 1 file changed, 18 insertions(+), 10 deletions(-) diff --git a/OpenAL32/alSource.c b/OpenAL32/alSource.c index ec8783c3..a06c6060 100644 --- a/OpenAL32/alSource.c +++ b/OpenAL32/alSource.c @@ -1846,6 +1846,7 @@ static ALvoid InitSourceParams(ALsource *pSource) static ALboolean GetSourceOffset(ALsource *pSource, ALenum eName, ALfloat *pflOffset) { ALbufferlistitem *pBufferList; + ALbuffer *pBuffer; ALfloat flBufferFreq; ALint lBytesPlayed, lChannels; ALenum eOriginalFormat; @@ -1854,10 +1855,11 @@ static ALboolean GetSourceOffset(ALsource *pSource, ALenum eName, ALfloat *pflOf if (((pSource->state == AL_PLAYING) || (pSource->state == AL_PAUSED)) && (pSource->ulBufferID)) { + pBuffer = ALTHUNK_LOOKUPENTRY(pSource->ulBufferID); // Get Current Buffer Size and frequency (in milliseconds) - flBufferFreq = (ALfloat)(((ALbuffer*)ALTHUNK_LOOKUPENTRY(pSource->ulBufferID))->frequency); - eOriginalFormat = ((ALbuffer*)ALTHUNK_LOOKUPENTRY(pSource->ulBufferID))->eOriginalFormat; - lChannels = ((((ALbuffer*)ALTHUNK_LOOKUPENTRY(pSource->ulBufferID))->format == AL_FORMAT_MONO16)?1:2); + flBufferFreq = (ALfloat)pBuffer->frequency; + eOriginalFormat = pBuffer->eOriginalFormat; + lChannels = aluChannelsFromFormat(pBuffer->format); // Get Current BytesPlayed lBytesPlayed = pSource->position * lChannels * 2; // NOTE : This is the byte offset into the *current* buffer @@ -1904,11 +1906,12 @@ static ALboolean GetSourceOffset(ALsource *pSource, ALenum eName, ALfloat *pflOf break; case AL_BYTE_OFFSET: // Take into account the original format of the Buffer - if ((eOriginalFormat == AL_FORMAT_MONO8) || (eOriginalFormat == AL_FORMAT_STEREO8)) + if (aluBytesFromFormat(eOriginalFormat) == 1) { *pflOffset = (ALfloat)(lBytesPlayed >> 1); } - else if ((eOriginalFormat == AL_FORMAT_MONO_IMA4) || (eOriginalFormat == AL_FORMAT_STEREO_IMA4)) + else if ((eOriginalFormat == AL_FORMAT_MONO_IMA4) || + (eOriginalFormat == AL_FORMAT_STEREO_IMA4)) { // Compression rate of the ADPCM supported is 3.6111 to 1 lBytesPlayed = (ALint)((ALfloat)lBytesPlayed / 3.6111f); @@ -1940,6 +1943,7 @@ static ALboolean GetSourceOffset(ALsource *pSource, ALenum eName, ALfloat *pflOf static void ApplyOffset(ALsource *pSource, ALboolean bUpdateContext) { ALbufferlistitem *pBufferList; + ALbuffer *pBuffer; ALint lBufferSize, lTotalBufferSize; ALint lByteOffset; @@ -1956,7 +1960,8 @@ static void ApplyOffset(ALsource *pSource, ALboolean bUpdateContext) pSource->BuffersProcessed = 0; while (pBufferList) { - lBufferSize = pBufferList->buffer ? ((ALbuffer*)ALTHUNK_LOOKUPENTRY(pBufferList->buffer))->size : 0; + pBuffer = ALTHUNK_LOOKUPENTRY(pBufferList->buffer); + lBufferSize = pBuffer ? pBuffer->size : 0; if ((lTotalBufferSize + lBufferSize) <= lByteOffset) { @@ -1985,7 +1990,9 @@ static void ApplyOffset(ALsource *pSource, ALboolean bUpdateContext) pSource->lBytesPlayed = lByteOffset; // SW Mixer Positions are in Samples - pSource->position = pSource->BufferPosition / ((((ALbuffer*)ALTHUNK_LOOKUPENTRY(pBufferList->buffer))->format == AL_FORMAT_MONO16)?2:4); + pSource->position = pSource->BufferPosition / + aluBytesFromFormat(pBuffer->format) / + aluChannelsFromFormat(pBuffer->format); } else { @@ -2042,19 +2049,20 @@ static ALint GetByteOffset(ALsource *pSource) if (pBuffer) { flBufferFreq = ((ALfloat)pBuffer->frequency); - lChannels = (pBuffer->format == AL_FORMAT_MONO16)?1:2; + lChannels = aluChannelsFromFormat(pBuffer->format); // Determine the ByteOffset (and ensure it is block aligned) switch (pSource->lOffsetType) { case AL_BYTE_OFFSET: // Take into consideration the original format - if ((pBuffer->eOriginalFormat == AL_FORMAT_MONO8) || (pBuffer->eOriginalFormat == AL_FORMAT_STEREO8)) + if (aluBytesFromFormat(pBuffer->eOriginalFormat) == 1) { lByteOffset = pSource->lOffset * 2; lByteOffset -= (lByteOffset % (lChannels * 2)); } - else if ((pBuffer->eOriginalFormat == AL_FORMAT_MONO_IMA4) || (pBuffer->eOriginalFormat == AL_FORMAT_STEREO_IMA4)) + else if ((pBuffer->eOriginalFormat == AL_FORMAT_MONO_IMA4) || + (pBuffer->eOriginalFormat == AL_FORMAT_STEREO_IMA4)) { // Round down to nearest ADPCM block lByteOffset = (pSource->lOffset / (36 * lChannels)) * 36 * lChannels; From 8343a98ec6f044ac94be9cc3d200c6d0e1ce544c Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Fri, 28 Dec 2007 19:21:21 -0800 Subject: [PATCH 10/33] Avoid a couple explicit format checks for buffers --- OpenAL32/alBuffer.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/OpenAL32/alBuffer.c b/OpenAL32/alBuffer.c index 0abdb61f..a5d7130f 100644 --- a/OpenAL32/alBuffer.c +++ b/OpenAL32/alBuffer.c @@ -817,11 +817,11 @@ ALAPI ALvoid ALAPIENTRY alGetBufferi(ALuint buffer, ALenum eParam, ALint *plValu break; case AL_BITS: - *plValue= (((pBuffer->format==AL_FORMAT_MONO8)||(pBuffer->format==AL_FORMAT_STEREO8))?8:16); + *plValue = aluBytesFromFormat(pBuffer->format) * 8; break; case AL_CHANNELS: - *plValue = (((pBuffer->format==AL_FORMAT_MONO8)||(pBuffer->format==AL_FORMAT_MONO16))?1:2); + *plValue = aluChannelsFromFormat(pBuffer->format); break; case AL_SIZE: From 87615fffc965e397a12cbb89bc5e07e480319d3b Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Fri, 28 Dec 2007 20:25:18 -0800 Subject: [PATCH 11/33] Consolidate buffer loading/conversion a bit --- OpenAL32/alBuffer.c | 155 ++++++++++++++++++++++---------------------- 1 file changed, 78 insertions(+), 77 deletions(-) diff --git a/OpenAL32/alBuffer.c b/OpenAL32/alBuffer.c index a5d7130f..ab5b60d8 100644 --- a/OpenAL32/alBuffer.c +++ b/OpenAL32/alBuffer.c @@ -29,6 +29,8 @@ #include "alBuffer.h" +static void LoadData(ALbuffer *ALBuf, const ALubyte *data, ALsizei size, ALuint freq, ALenum OrigFormat, ALenum NewFormat); + /* * AL Buffer Functions * @@ -273,91 +275,19 @@ ALAPI ALvoid ALAPIENTRY alBufferData(ALuint buffer,ALenum format,const ALvoid *d switch(format) { case AL_FORMAT_MONO8: - if ((size%1) == 0) - { - // 8bit Samples are converted to 16 bit here - // Allocate 8 extra samples (16 bytes) - ALBuf->data=realloc(ALBuf->data,16+(size/sizeof(ALubyte))*(1*sizeof(ALshort))); - if (ALBuf->data) - { - ALBuf->format = AL_FORMAT_MONO16; - ALBuf->eOriginalFormat = AL_FORMAT_MONO8; - for (i=0;i<(ALsizei)(size/sizeof(ALubyte));i++) - ALBuf->data[i]=(ALshort)((((ALubyte *)data)[i]-128)<<8); - memset(&(ALBuf->data[size/sizeof(ALubyte)]), 0, 16); - ALBuf->size=size/sizeof(ALubyte)*1*sizeof(ALshort); - ALBuf->frequency=freq; - } - else - alSetError(AL_OUT_OF_MEMORY); - } - else - alSetError(AL_INVALID_VALUE); + LoadData(ALBuf, data, size, freq, format, AL_FORMAT_MONO16); break; case AL_FORMAT_MONO16: - if ((size%2) == 0) - { - // Allocate 8 extra samples (16 bytes) - ALBuf->data=realloc(ALBuf->data,16+(size/sizeof(ALshort))*(1*sizeof(ALshort))); - if (ALBuf->data) - { - ALBuf->format = AL_FORMAT_MONO16; - ALBuf->eOriginalFormat = AL_FORMAT_MONO16; - memcpy(ALBuf->data,data,size/sizeof(ALshort)*1*sizeof(ALshort)); - memset(&(ALBuf->data[size/sizeof(ALshort)]), 0, 16); - ALBuf->size=size/sizeof(ALshort)*1*sizeof(ALshort); - ALBuf->frequency=freq; - } - else - alSetError(AL_OUT_OF_MEMORY); - } - else - alSetError(AL_INVALID_VALUE); + LoadData(ALBuf, data, size, freq, format, AL_FORMAT_MONO16); break; case AL_FORMAT_STEREO8: - if ((size%2) == 0) - { - // 8bit Samples are converted to 16 bit here - // Allocate 8 extra samples (32 bytes) - ALBuf->data=realloc(ALBuf->data,32+(size/sizeof(ALubyte))*(1*sizeof(ALshort))); - if (ALBuf->data) - { - ALBuf->format = AL_FORMAT_STEREO16; - ALBuf->eOriginalFormat = AL_FORMAT_STEREO8; - for (i=0;i<(ALsizei)(size/sizeof(ALubyte));i++) - ALBuf->data[i]=(ALshort)((((ALubyte *)data)[i]-128)<<8); - memset(&(ALBuf->data[size/sizeof(ALubyte)]), 0, 32); - ALBuf->size=size/sizeof(ALubyte)*1*sizeof(ALshort); - ALBuf->frequency=freq; - } - else - alSetError(AL_OUT_OF_MEMORY); - } - else - alSetError(AL_INVALID_VALUE); + LoadData(ALBuf, data, size, freq, format, AL_FORMAT_STEREO16); break; case AL_FORMAT_STEREO16: - if ((size%4) == 0) - { - // Allocate 8 extra samples (32 bytes) - ALBuf->data=realloc(ALBuf->data,32+(size/sizeof(ALshort))*(1*sizeof(ALshort))); - if (ALBuf->data) - { - ALBuf->format = AL_FORMAT_STEREO16; - ALBuf->eOriginalFormat = AL_FORMAT_STEREO16; - memcpy(ALBuf->data,data,size/sizeof(ALshort)*1*sizeof(ALshort)); - memset(&(ALBuf->data[size/sizeof(ALshort)]), 0, 32); - ALBuf->size=size/sizeof(ALshort)*1*sizeof(ALshort); - ALBuf->frequency=freq; - } - else - alSetError(AL_OUT_OF_MEMORY); - } - else - alSetError(AL_INVALID_VALUE); + LoadData(ALBuf, data, size, freq, format, AL_FORMAT_STEREO16); break; case AL_FORMAT_MONO_IMA4: @@ -489,7 +419,7 @@ ALAPI ALvoid ALAPIENTRY alBufferData(ALuint buffer,ALenum format,const ALvoid *d else if (LeftIndex>88) LeftIndex=88; ALBuf->data[i*2*65+j+k+2]=(short)LeftSample; LeftIMACode>>=4; - + RightSample+=((g_IMAStep_size[RightIndex]*g_IMACodeword_4[RightIMACode&15])/8); RightIndex+=g_IMAIndex_adjust_4[RightIMACode&15]; if (RightSample<-32768) RightSample=-32768; @@ -917,6 +847,77 @@ ALAPI void ALAPIENTRY alGetBufferiv(ALuint buffer, ALenum eParam, ALint* plValue ProcessContext(pContext); } +/* + * LoadData + * + * Loads the specified data into the buffer, using the specified formats. + * Currently, the new format must be 16-bit, and must have the same channel + * configuration as the original format. This does NOT handle compressed + * formats (eg. IMA4). + */ +static void LoadData(ALbuffer *ALBuf, const ALubyte *data, ALsizei size, ALuint freq, ALenum OrigFormat, ALenum NewFormat) +{ + ALuint NewChannels = aluChannelsFromFormat(NewFormat); + ALuint OrigBytes = aluBytesFromFormat(OrigFormat); + ALuint OrigChannels = aluChannelsFromFormat(OrigFormat); + ALsizei i; + + assert(aluBytesFromFormat(NewFormat) == 2); + assert(NewChannels == OrigChannels); + + if ((size%(OrigBytes*OrigChannels)) != 0) + { + alSetError(AL_INVALID_VALUE); + return; + } + + switch(OrigBytes) + { + case 1: + size /= sizeof(ALubyte); + + // 8bit Samples are converted to 16 bit here + // Allocate 8 extra samples + ALBuf->data = realloc(ALBuf->data, (8*NewChannels + size) * (1*sizeof(ALshort))); + if (ALBuf->data) + { + for (i = 0;i < size;i++) + ALBuf->data[i] = (ALshort)((data[i]-128) << 8); + memset(&(ALBuf->data[size]), 0, 16*NewChannels); + + ALBuf->format = NewFormat; + ALBuf->eOriginalFormat = OrigFormat; + ALBuf->size = size*1*sizeof(ALshort); + ALBuf->frequency = freq; + } + else + alSetError(AL_OUT_OF_MEMORY); + break; + + case 2: + size /= sizeof(ALshort); + + // Allocate 8 extra samples + ALBuf->data = realloc(ALBuf->data, (8*NewChannels + size) * (1*sizeof(ALshort))); + if (ALBuf->data) + { + memcpy(ALBuf->data, data, size*1*sizeof(ALshort)); + memset(&(ALBuf->data[size]), 0, 16*NewChannels); + + ALBuf->format = NewFormat; + ALBuf->eOriginalFormat = OrigFormat; + ALBuf->size = size*1*sizeof(ALshort); + ALBuf->frequency = freq; + } + else + alSetError(AL_OUT_OF_MEMORY); + break; + + default: + assert(0); + } +} + /* * ReleaseALBuffers() From d90b36cf1147b0b14068db55a7510ffb0d2d2641 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Fri, 28 Dec 2007 22:14:36 -0800 Subject: [PATCH 12/33] Advertise AL_EXT_IMA4, since it's been supported all this time --- Alc/ALc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Alc/ALc.c b/Alc/ALc.c index fa591174..8c75b32c 100644 --- a/Alc/ALc.c +++ b/Alc/ALc.c @@ -357,7 +357,7 @@ static ALvoid InitContext(ALCcontext *pContext) pContext->lNumStereoSources = 1; pContext->lNumMonoSources = pContext->Device->MaxNoOfSources - pContext->lNumStereoSources; - strcpy(pContext->ExtensionList, "AL_EXT_EXPONENT_DISTANCE AL_EXT_LINEAR_DISTANCE AL_EXT_OFFSET"); + strcpy(pContext->ExtensionList, "AL_EXT_EXPONENT_DISTANCE AL_EXT_IMA4 AL_EXT_LINEAR_DISTANCE AL_EXT_OFFSET"); } From 5f8e65e09941c9c5d48e2277a8b1be1e35f04a9a Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Fri, 28 Dec 2007 22:41:14 -0800 Subject: [PATCH 13/33] Implement AL_EXT_FLOAT32 --- Alc/ALc.c | 2 +- Alc/ALu.c | 6 ++++++ OpenAL32/Include/alMain.h | 3 +++ OpenAL32/alBuffer.c | 28 ++++++++++++++++++++++++++++ OpenAL32/alSource.c | 9 +++++++++ 5 files changed, 47 insertions(+), 1 deletion(-) diff --git a/Alc/ALc.c b/Alc/ALc.c index 8c75b32c..0db68efe 100644 --- a/Alc/ALc.c +++ b/Alc/ALc.c @@ -357,7 +357,7 @@ static ALvoid InitContext(ALCcontext *pContext) pContext->lNumStereoSources = 1; pContext->lNumMonoSources = pContext->Device->MaxNoOfSources - pContext->lNumStereoSources; - strcpy(pContext->ExtensionList, "AL_EXT_EXPONENT_DISTANCE AL_EXT_IMA4 AL_EXT_LINEAR_DISTANCE AL_EXT_OFFSET"); + strcpy(pContext->ExtensionList, "AL_EXT_EXPONENT_DISTANCE AL_EXT_FLOAT32 AL_EXT_IMA4 AL_EXT_LINEAR_DISTANCE AL_EXT_OFFSET"); } diff --git a/Alc/ALu.c b/Alc/ALu.c index b5af500b..f77990a7 100644 --- a/Alc/ALu.c +++ b/Alc/ALu.c @@ -68,6 +68,10 @@ __inline ALuint aluBytesFromFormat(ALenum format) case AL_FORMAT_51CHN16: return 2; + case AL_FORMAT_MONO_FLOAT32: + case AL_FORMAT_STEREO_FLOAT32: + return 4; + default: return 0; } @@ -79,10 +83,12 @@ __inline ALuint aluChannelsFromFormat(ALenum format) { case AL_FORMAT_MONO8: case AL_FORMAT_MONO16: + case AL_FORMAT_MONO_FLOAT32: return 1; case AL_FORMAT_STEREO8: case AL_FORMAT_STEREO16: + case AL_FORMAT_STEREO_FLOAT32: return 2; case AL_FORMAT_QUAD8: diff --git a/OpenAL32/Include/alMain.h b/OpenAL32/Include/alMain.h index 30dd068f..f11f8fd9 100644 --- a/OpenAL32/Include/alMain.h +++ b/OpenAL32/Include/alMain.h @@ -89,6 +89,9 @@ extern char _alDebug[256]; } while(0) +#define AL_FORMAT_MONO_FLOAT32 0x10010 +#define AL_FORMAT_STEREO_FLOAT32 0x10011 + #define AL_FORMAT_MONO_IMA4 0x1300 #define AL_FORMAT_STEREO_IMA4 0x1301 // These are from AL_EXT_MCFORMATS, which we don't support yet but the mixer diff --git a/OpenAL32/alBuffer.c b/OpenAL32/alBuffer.c index ab5b60d8..d1a8c359 100644 --- a/OpenAL32/alBuffer.c +++ b/OpenAL32/alBuffer.c @@ -282,6 +282,10 @@ ALAPI ALvoid ALAPIENTRY alBufferData(ALuint buffer,ALenum format,const ALvoid *d LoadData(ALBuf, data, size, freq, format, AL_FORMAT_MONO16); break; + case AL_FORMAT_MONO_FLOAT32: + LoadData(ALBuf, data, size, freq, format, AL_FORMAT_MONO16); + break; + case AL_FORMAT_STEREO8: LoadData(ALBuf, data, size, freq, format, AL_FORMAT_STEREO16); break; @@ -290,6 +294,10 @@ ALAPI ALvoid ALAPIENTRY alBufferData(ALuint buffer,ALenum format,const ALvoid *d LoadData(ALBuf, data, size, freq, format, AL_FORMAT_STEREO16); break; + case AL_FORMAT_STEREO_FLOAT32: + LoadData(ALBuf, data, size, freq, format, AL_FORMAT_STEREO16); + break; + case AL_FORMAT_MONO_IMA4: // Here is where things vary: // nVidia and Apple use 64+1 samples per block => block_size=36 bytes @@ -913,6 +921,26 @@ static void LoadData(ALbuffer *ALBuf, const ALubyte *data, ALsizei size, ALuint alSetError(AL_OUT_OF_MEMORY); break; + case 4: + size /= sizeof(ALfloat); + + // Allocate 8 extra samples + ALBuf->data = realloc(ALBuf->data, (8*NewChannels + size) * (1*sizeof(ALshort))); + if (ALBuf->data) + { + for (i = 0;i < size;i++) + ALBuf->data[i] = (ALshort)(((ALfloat*)data)[i] * 32767.5f - 0.5); + memset(&(ALBuf->data[size]), 0, 16*NewChannels); + + ALBuf->format = NewFormat; + ALBuf->eOriginalFormat = OrigFormat; + ALBuf->size = size*1*sizeof(ALshort); + ALBuf->frequency = freq; + } + else + alSetError(AL_OUT_OF_MEMORY); + break; + default: assert(0); } diff --git a/OpenAL32/alSource.c b/OpenAL32/alSource.c index a06c6060..7c022e6c 100644 --- a/OpenAL32/alSource.c +++ b/OpenAL32/alSource.c @@ -1910,6 +1910,10 @@ static ALboolean GetSourceOffset(ALsource *pSource, ALenum eName, ALfloat *pflOf { *pflOffset = (ALfloat)(lBytesPlayed >> 1); } + else if (aluBytesFromFormat(eOriginalFormat) == 4) + { + *pflOffset = (ALfloat)(lBytesPlayed << 1); + } else if ((eOriginalFormat == AL_FORMAT_MONO_IMA4) || (eOriginalFormat == AL_FORMAT_STEREO_IMA4)) { @@ -2061,6 +2065,11 @@ static ALint GetByteOffset(ALsource *pSource) lByteOffset = pSource->lOffset * 2; lByteOffset -= (lByteOffset % (lChannels * 2)); } + else if (aluBytesFromFormat(pBuffer->eOriginalFormat) == 4) + { + lByteOffset = pSource->lOffset / 2; + lByteOffset -= (lByteOffset % (lChannels * 2)); + } else if ((pBuffer->eOriginalFormat == AL_FORMAT_MONO_IMA4) || (pBuffer->eOriginalFormat == AL_FORMAT_STEREO_IMA4)) { From 1061108c6146416068e489febe89173ca40eb2ee Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Fri, 28 Dec 2007 22:56:48 -0800 Subject: [PATCH 14/33] Remove some duplication --- OpenAL32/alBuffer.c | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/OpenAL32/alBuffer.c b/OpenAL32/alBuffer.c index d1a8c359..33db7cfb 100644 --- a/OpenAL32/alBuffer.c +++ b/OpenAL32/alBuffer.c @@ -275,25 +275,13 @@ ALAPI ALvoid ALAPIENTRY alBufferData(ALuint buffer,ALenum format,const ALvoid *d switch(format) { case AL_FORMAT_MONO8: - LoadData(ALBuf, data, size, freq, format, AL_FORMAT_MONO16); - break; - case AL_FORMAT_MONO16: - LoadData(ALBuf, data, size, freq, format, AL_FORMAT_MONO16); - break; - case AL_FORMAT_MONO_FLOAT32: LoadData(ALBuf, data, size, freq, format, AL_FORMAT_MONO16); break; case AL_FORMAT_STEREO8: - LoadData(ALBuf, data, size, freq, format, AL_FORMAT_STEREO16); - break; - case AL_FORMAT_STEREO16: - LoadData(ALBuf, data, size, freq, format, AL_FORMAT_STEREO16); - break; - case AL_FORMAT_STEREO_FLOAT32: LoadData(ALBuf, data, size, freq, format, AL_FORMAT_STEREO16); break; From 2e88a3d03bce05010b2f14d4615271e3462834f9 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Sun, 30 Dec 2007 01:28:25 -0800 Subject: [PATCH 15/33] Check for the correct ALSA driver option name --- Alc/alsa.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Alc/alsa.c b/Alc/alsa.c index a6035d46..a181eebd 100644 --- a/Alc/alsa.c +++ b/Alc/alsa.c @@ -269,7 +269,7 @@ static ALCboolean alsa_open_playback(ALCdevice *device, const ALCchar *deviceNam char *err; int i; - strncpy(driver, GetConfigValue("alsa", "default", "default"), sizeof(driver)-1); + strncpy(driver, GetConfigValue("alsa", "device", "default"), sizeof(driver)-1); driver[sizeof(driver)-1] = 0; if(deviceName) { From fcff17c567a0143787bd82ab4fe7ae1d69aee323 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Sun, 30 Dec 2007 02:09:39 -0800 Subject: [PATCH 16/33] Fallback to non-mmap access for ALSA if mmap isn't available --- Alc/alsa.c | 117 +++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 114 insertions(+), 3 deletions(-) diff --git a/Alc/alsa.c b/Alc/alsa.c index a181eebd..bef6ac99 100644 --- a/Alc/alsa.c +++ b/Alc/alsa.c @@ -36,6 +36,10 @@ typedef struct { snd_pcm_t *pcmHandle; snd_pcm_format_t format; + + ALvoid *buffer; + ALsizei size; + int killNow; ALvoid *thread; } alsa_data; @@ -63,6 +67,7 @@ MAKE_FUNC(snd_pcm_hw_params_set_rate_near); MAKE_FUNC(snd_pcm_hw_params_set_rate); MAKE_FUNC(snd_pcm_hw_params_set_buffer_size_near); MAKE_FUNC(snd_pcm_hw_params_set_buffer_size_min); +MAKE_FUNC(snd_pcm_hw_params_get_access); MAKE_FUNC(snd_pcm_hw_params); MAKE_FUNC(snd_pcm_prepare); MAKE_FUNC(snd_pcm_start); @@ -72,6 +77,7 @@ MAKE_FUNC(snd_pcm_avail_update); MAKE_FUNC(snd_pcm_areas_silence); MAKE_FUNC(snd_pcm_mmap_begin); MAKE_FUNC(snd_pcm_mmap_commit); +MAKE_FUNC(snd_pcm_writei); MAKE_FUNC(snd_pcm_drain); MAKE_FUNC(snd_pcm_info_malloc); MAKE_FUNC(snd_pcm_info_free); @@ -210,6 +216,76 @@ static ALuint ALSAProc(ALvoid *ptr) return 0; } +static ALuint ALSANoMMapProc(ALvoid *ptr) +{ + ALCdevice *pDevice = (ALCdevice*)ptr; + alsa_data *data = (alsa_data*)pDevice->ExtraData; + snd_pcm_sframes_t avail; + char *WritePtr; + int err; + + while(!data->killNow) + { + snd_pcm_state_t state = psnd_pcm_state(data->pcmHandle); + if(state == SND_PCM_STATE_XRUN) + { + err = xrun_recovery(data->pcmHandle, -EPIPE); + if (err < 0) + { + AL_PRINT("XRUN recovery failed: %s\n", psnd_strerror(err)); + break; + } + } + else if (state == SND_PCM_STATE_SUSPENDED) + { + err = xrun_recovery(data->pcmHandle, -ESTRPIPE); + if (err < 0) + { + AL_PRINT("SUSPEND recovery failed: %s\n", psnd_strerror(err)); + break; + } + } + + SuspendContext(NULL); + aluMixData(pDevice->Context, data->buffer, data->size, pDevice->Format); + ProcessContext(NULL); + + WritePtr = data->buffer; + avail = (snd_pcm_uframes_t)data->size / psnd_pcm_frames_to_bytes(data->pcmHandle, 1); + while(avail > 0) + { + int ret = psnd_pcm_writei(data->pcmHandle, WritePtr, avail); + switch (ret) + { + case -EAGAIN: + continue; + case -ESTRPIPE: + do { + ret = psnd_pcm_resume(data->pcmHandle); + } while(ret == -EAGAIN); + break; + case -EPIPE: + break; + default: + if (ret >= 0) + { + WritePtr += psnd_pcm_frames_to_bytes(data->pcmHandle, ret); + avail -= ret; + } + break; + } + if (ret < 0) + { + ret = psnd_pcm_prepare(data->pcmHandle); + if(ret < 0) + break; + } + } + } + + return 0; +} + static void fill_silence(snd_pcm_t *pcmHandle, snd_pcm_format_t alsaFormat, int channels) { const snd_pcm_channel_area_t *areas = NULL; @@ -263,6 +339,7 @@ static ALCboolean alsa_open_playback(ALCdevice *device, const ALCchar *deviceNam { snd_pcm_uframes_t bufferSizeInFrames; snd_pcm_hw_params_t *p = NULL; + snd_pcm_access_t access; unsigned int periods; alsa_data *data; char driver[64]; @@ -347,7 +424,8 @@ open_alsa: /* start with the largest configuration space possible */ if(!(ok(psnd_pcm_hw_params_any(data->pcmHandle, p), "any") && /* set interleaved access */ - ok(psnd_pcm_hw_params_set_access(data->pcmHandle, p, SND_PCM_ACCESS_MMAP_INTERLEAVED), "set access") && + (ok(psnd_pcm_hw_params_set_access(data->pcmHandle, p, SND_PCM_ACCESS_MMAP_INTERLEAVED), "set access") || + ok(psnd_pcm_hw_params_set_access(data->pcmHandle, p, SND_PCM_ACCESS_RW_INTERLEAVED), "set access"))&& /* set format (implicitly sets sample bits) */ ok(psnd_pcm_hw_params_set_format(data->pcmHandle, p, data->format), "set format") && /* set channels (implicitly sets frame bits) */ @@ -368,6 +446,16 @@ open_alsa: return ALC_FALSE; } #undef ok + + if((i=psnd_pcm_hw_params_get_access(p, &access)) < 0) + { + AL_PRINT("get_access failed: %s\n", psnd_strerror(i)); + psnd_pcm_hw_params_free(p); + psnd_pcm_close(data->pcmHandle); + free(data); + return ALC_FALSE; + } + psnd_pcm_hw_params_free(p); device->MaxNoOfSources = 256; @@ -378,26 +466,46 @@ open_alsa: { AL_PRINT("prepare error: %s\n", psnd_strerror(i)); psnd_pcm_close(data->pcmHandle); + free(data->buffer); free(data); return ALC_FALSE; } - fill_silence(data->pcmHandle, data->format, device->Channels); + data->size = psnd_pcm_frames_to_bytes(data->pcmHandle, bufferSizeInFrames); + if(access == SND_PCM_ACCESS_RW_INTERLEAVED) + { + data->buffer = malloc(data->size); + if(!data->buffer) + { + AL_PRINT("buffer malloc failed\n"); + psnd_pcm_close(data->pcmHandle); + free(data); + return ALC_FALSE; + } + } + else + fill_silence(data->pcmHandle, data->format, device->Channels); + i = psnd_pcm_start(data->pcmHandle); if(i < 0) { AL_PRINT("start error: %s\n", psnd_strerror(i)); psnd_pcm_close(data->pcmHandle); + free(data->buffer); free(data); return ALC_FALSE; } device->ExtraData = data; - data->thread = StartThread(ALSAProc, device); + if(access == SND_PCM_ACCESS_RW_INTERLEAVED) + data->thread = StartThread(ALSANoMMapProc, device); + else + data->thread = StartThread(ALSAProc, device); if(data->thread == NULL) { psnd_pcm_close(data->pcmHandle); device->ExtraData = NULL; + free(data->buffer); free(data); return ALC_FALSE; } @@ -412,6 +520,7 @@ static void alsa_close_playback(ALCdevice *device) StopThread(data->thread); psnd_pcm_close(data->pcmHandle); + free(data->buffer); free(data); device->ExtraData = NULL; } @@ -686,6 +795,7 @@ LOAD_FUNC(snd_pcm_hw_params_set_rate_near); LOAD_FUNC(snd_pcm_hw_params_set_rate); LOAD_FUNC(snd_pcm_hw_params_set_buffer_size_near); LOAD_FUNC(snd_pcm_hw_params_set_buffer_size_min); +LOAD_FUNC(snd_pcm_hw_params_get_access); LOAD_FUNC(snd_pcm_hw_params); LOAD_FUNC(snd_pcm_prepare); LOAD_FUNC(snd_pcm_start); @@ -695,6 +805,7 @@ LOAD_FUNC(snd_pcm_avail_update); LOAD_FUNC(snd_pcm_areas_silence); LOAD_FUNC(snd_pcm_mmap_begin); LOAD_FUNC(snd_pcm_mmap_commit); +LOAD_FUNC(snd_pcm_writei); LOAD_FUNC(snd_pcm_drain); LOAD_FUNC(snd_pcm_info_malloc); From 927763902f13e9f28f0093df3579946183fef83e Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Mon, 31 Dec 2007 00:05:29 -0800 Subject: [PATCH 17/33] Loop per frame, not per sample, when writing the output buffer --- Alc/ALu.c | 58 ++++++++++++++++++++++++++++++++++++------------------- 1 file changed, 38 insertions(+), 20 deletions(-) diff --git a/Alc/ALu.c b/Alc/ALu.c index f77990a7..038bf5d3 100644 --- a/Alc/ALu.c +++ b/Alc/ALu.c @@ -638,58 +638,76 @@ ALvoid aluMixData(ALCcontext *ALContext,ALvoid *buffer,ALsizei size,ALenum forma case AL_FORMAT_MONO8: for(i = 0;i < SamplesToDo;i++) { - *((ALubyte*)buffer) = (ALubyte)((aluF2S(DryBuffer[i][0]+DryBuffer[i][1]+WetBuffer[i][0]+WetBuffer[i][1])>>8)+128); + ((ALubyte*)buffer)[0] = (ALubyte)((aluF2S(DryBuffer[i][0]+DryBuffer[i][1]+WetBuffer[i][0]+WetBuffer[i][1])>>8)+128); buffer = ((ALubyte*)buffer) + 1; } break; case AL_FORMAT_STEREO8: - for(i = 0;i < SamplesToDo*2;i++) + for(i = 0;i < SamplesToDo;i++) { - *((ALubyte*)buffer) = (ALubyte)((aluF2S(DryBuffer[i>>1][i&1]+WetBuffer[i>>1][i&1])>>8)+128); - buffer = ((ALubyte*)buffer) + 1; + ((ALubyte*)buffer)[0] = (ALubyte)((aluF2S(DryBuffer[i][0]+WetBuffer[i][0])>>8)+128); + ((ALubyte*)buffer)[1] = (ALubyte)((aluF2S(DryBuffer[i][1]+WetBuffer[i][1])>>8)+128); + buffer = ((ALubyte*)buffer) + 2; } break; case AL_FORMAT_QUAD8: - for(i = 0;i < SamplesToDo*4;i++) + for(i = 0;i < SamplesToDo;i++) { - *((ALubyte*)buffer) = (ALubyte)((aluF2S(DryBuffer[i>>2][i&3]+WetBuffer[i>>2][i&3])>>8)+128); - buffer = ((ALubyte*)buffer) + 1; + ((ALubyte*)buffer)[0] = (ALubyte)((aluF2S(DryBuffer[i][0]+WetBuffer[i][0])>>8)+128); + ((ALubyte*)buffer)[1] = (ALubyte)((aluF2S(DryBuffer[i][1]+WetBuffer[i][1])>>8)+128); + ((ALubyte*)buffer)[2] = (ALubyte)((aluF2S(DryBuffer[i][2]+WetBuffer[i][2])>>8)+128); + ((ALubyte*)buffer)[3] = (ALubyte)((aluF2S(DryBuffer[i][3]+WetBuffer[i][3])>>8)+128); + buffer = ((ALubyte*)buffer) + 4; } break; case AL_FORMAT_51CHN8: - for(i = 0;i < SamplesToDo*6;i++) + for(i = 0;i < SamplesToDo;i++) { - *((ALubyte*)buffer) = (ALubyte)((aluF2S(DryBuffer[i/6][i%6]+WetBuffer[i/6][i%6])>>8)+128); - buffer = ((ALubyte*)buffer) + 1; + ((ALubyte*)buffer)[0] = (ALubyte)((aluF2S(DryBuffer[i][0]+WetBuffer[i][0])>>8)+128); + ((ALubyte*)buffer)[1] = (ALubyte)((aluF2S(DryBuffer[i][1]+WetBuffer[i][1])>>8)+128); + ((ALubyte*)buffer)[2] = (ALubyte)((aluF2S(DryBuffer[i][2]+WetBuffer[i][2])>>8)+128); + ((ALubyte*)buffer)[3] = (ALubyte)((aluF2S(DryBuffer[i][3]+WetBuffer[i][3])>>8)+128); + ((ALubyte*)buffer)[4] = (ALubyte)((aluF2S(DryBuffer[i][4]+WetBuffer[i][4])>>8)+128); + ((ALubyte*)buffer)[5] = (ALubyte)((aluF2S(DryBuffer[i][5]+WetBuffer[i][5])>>8)+128); + buffer = ((ALubyte*)buffer) + 6; } break; case AL_FORMAT_MONO16: for(i = 0;i < SamplesToDo;i++) { - *((ALshort*)buffer) = aluF2S(DryBuffer[i][0]+DryBuffer[i][1]+WetBuffer[i][0]+WetBuffer[i][1]); + ((ALshort*)buffer)[0] = aluF2S(DryBuffer[i][0]+DryBuffer[i][1]+WetBuffer[i][0]+WetBuffer[i][1]); buffer = ((ALshort*)buffer) + 1; } break; case AL_FORMAT_STEREO16: default: - for(i = 0;i < SamplesToDo*2;i++) + for(i = 0;i < SamplesToDo;i++) { - *((ALshort*)buffer) = aluF2S(DryBuffer[i>>1][i&1]+WetBuffer[i>>1][i&1]); - buffer = ((ALshort*)buffer) + 1; + ((ALshort*)buffer)[0] = aluF2S(DryBuffer[i][0]+WetBuffer[i][0]); + ((ALshort*)buffer)[1] = aluF2S(DryBuffer[i][1]+WetBuffer[i][1]); + buffer = ((ALshort*)buffer) + 2; } break; case AL_FORMAT_QUAD16: - for(i = 0;i < SamplesToDo*4;i++) + for(i = 0;i < SamplesToDo;i++) { - *((ALshort*)buffer) = aluF2S(DryBuffer[i>>2][i&3]+WetBuffer[i>>2][i&3]); - buffer = ((ALshort*)buffer) + 1; + ((ALshort*)buffer)[0] = aluF2S(DryBuffer[i][0]+WetBuffer[i][0]); + ((ALshort*)buffer)[1] = aluF2S(DryBuffer[i][1]+WetBuffer[i][1]); + ((ALshort*)buffer)[2] = aluF2S(DryBuffer[i][2]+WetBuffer[i][2]); + ((ALshort*)buffer)[3] = aluF2S(DryBuffer[i][3]+WetBuffer[i][3]); + buffer = ((ALshort*)buffer) + 4; } break; case AL_FORMAT_51CHN16: - for(i = 0;i < SamplesToDo*6;i++) + for(i = 0;i < SamplesToDo;i++) { - *((ALshort*)buffer) = aluF2S(DryBuffer[i/6][i%6]+WetBuffer[i/6][i%6]); - buffer = ((ALshort*)buffer) + 1; + ((ALshort*)buffer)[0] = aluF2S(DryBuffer[i][0]+WetBuffer[i][0]); + ((ALshort*)buffer)[1] = aluF2S(DryBuffer[i][1]+WetBuffer[i][1]); + ((ALshort*)buffer)[2] = aluF2S(DryBuffer[i][2]+WetBuffer[i][2]); + ((ALshort*)buffer)[3] = aluF2S(DryBuffer[i][3]+WetBuffer[i][3]); + ((ALshort*)buffer)[4] = aluF2S(DryBuffer[i][4]+WetBuffer[i][4]); + ((ALshort*)buffer)[5] = aluF2S(DryBuffer[i][5]+WetBuffer[i][5]); + buffer = ((ALshort*)buffer) + 6; } break; } From f7ef5c169bff8366bb5ea4b245111ace5669109e Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Mon, 31 Dec 2007 00:08:07 -0800 Subject: [PATCH 18/33] Don't default to AL_FORMAT_STEREO16 when writing to the output buffer --- Alc/ALu.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Alc/ALu.c b/Alc/ALu.c index 038bf5d3..f3cd24f5 100644 --- a/Alc/ALu.c +++ b/Alc/ALu.c @@ -680,7 +680,6 @@ ALvoid aluMixData(ALCcontext *ALContext,ALvoid *buffer,ALsizei size,ALenum forma } break; case AL_FORMAT_STEREO16: - default: for(i = 0;i < SamplesToDo;i++) { ((ALshort*)buffer)[0] = aluF2S(DryBuffer[i][0]+WetBuffer[i][0]); @@ -710,6 +709,9 @@ ALvoid aluMixData(ALCcontext *ALContext,ALvoid *buffer,ALsizei size,ALenum forma buffer = ((ALshort*)buffer) + 6; } break; + + default: + break; } size -= SamplesToDo; From 1e0fa58d79d046ec244289ff8dc59ec188051d21 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Mon, 31 Dec 2007 00:52:34 -0800 Subject: [PATCH 19/33] Remove unused macros --- OpenAL32/Include/alMain.h | 4 ---- 1 file changed, 4 deletions(-) diff --git a/OpenAL32/Include/alMain.h b/OpenAL32/Include/alMain.h index f11f8fd9..c6738868 100644 --- a/OpenAL32/Include/alMain.h +++ b/OpenAL32/Include/alMain.h @@ -1,9 +1,6 @@ #ifndef AL_MAIN_H #define AL_MAIN_H -#define AL_MAX_CHANNELS 4 -#define AL_MAX_SOURCES 32 - #include #include "alu.h" @@ -102,7 +99,6 @@ extern char _alDebug[256]; #define AL_FORMAT_51CHN16 0x120B #define SWMIXER_OUTPUT_RATE 44100 -//#define OUTPUT_BUFFER_SIZE (32768*SWMIXER_OUTPUT_RATE/22050) #define SPEEDOFSOUNDMETRESPERSEC (343.3f) From f32098e04d7533782e66f8a06641703383b627b3 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Mon, 31 Dec 2007 01:09:21 -0800 Subject: [PATCH 20/33] Don't append _struct to the source struct name --- OpenAL32/Include/alSource.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/OpenAL32/Include/alSource.h b/OpenAL32/Include/alSource.h index 499ddcf4..5edbfd1e 100644 --- a/OpenAL32/Include/alSource.h +++ b/OpenAL32/Include/alSource.h @@ -17,7 +17,7 @@ typedef struct ALbufferlistitem struct ALbufferlistitem *next; } ALbufferlistitem; -typedef struct ALsource_struct +typedef struct ALsource { ALfloat flPitch; ALfloat flGain; @@ -61,7 +61,7 @@ typedef struct ALsource_struct // Source Type (Static, Streaming, or Undetermined) ALint lSourceType; - struct ALsource_struct *next; + struct ALsource *next; } ALsource; #ifdef __cplusplus From e82c27ab0402fae11811a34b5b44ba4462f35f4e Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Mon, 31 Dec 2007 01:09:57 -0800 Subject: [PATCH 21/33] Fix includes so alMain.h doesn't include so much by itself --- Alc/ALc.c | 3 +++ Alc/ALu.c | 4 ++++ OpenAL32/Include/alMain.h | 10 ++-------- OpenAL32/alBuffer.c | 1 + OpenAL32/alSource.c | 2 ++ 5 files changed, 12 insertions(+), 8 deletions(-) diff --git a/Alc/ALc.c b/Alc/ALc.c index 0db68efe..376a3ce8 100644 --- a/Alc/ALc.c +++ b/Alc/ALc.c @@ -29,6 +29,9 @@ #include "alMain.h" #include "AL/al.h" #include "AL/alc.h" +#include "alThunk.h" +#include "alSource.h" +#include "alExtension.h" /////////////////////////////////////////////////////// // DEBUG INFORMATION diff --git a/Alc/ALu.c b/Alc/ALu.c index f3cd24f5..b19bd518 100644 --- a/Alc/ALu.c +++ b/Alc/ALu.c @@ -26,6 +26,10 @@ #include "alMain.h" #include "AL/al.h" #include "AL/alc.h" +#include "alSource.h" +#include "alBuffer.h" +#include "alThunk.h" +#include "alListener.h" #if defined(HAVE_STDINT_H) #include diff --git a/OpenAL32/Include/alMain.h b/OpenAL32/Include/alMain.h index c6738868..f2beb30f 100644 --- a/OpenAL32/Include/alMain.h +++ b/OpenAL32/Include/alMain.h @@ -56,13 +56,7 @@ static inline void DeleteCriticalSection(CRITICAL_SECTION *cs) #define max(x,y) (((x)>(y))?(x):(y)) #endif -#include "alBuffer.h" -#include "alError.h" -#include "alExtension.h" #include "alListener.h" -#include "alSource.h" -#include "alState.h" -#include "alThunk.h" #ifdef __cplusplus extern "C" @@ -156,8 +150,8 @@ struct ALCcontext_struct { ALlistener Listener; - ALsource *Source; - ALuint SourceCount; + struct ALsource *Source; + ALuint SourceCount; ALenum LastError; ALboolean InUse; diff --git a/OpenAL32/alBuffer.c b/OpenAL32/alBuffer.c index 33db7cfb..13b98b21 100644 --- a/OpenAL32/alBuffer.c +++ b/OpenAL32/alBuffer.c @@ -27,6 +27,7 @@ #include "AL/alc.h" #include "alError.h" #include "alBuffer.h" +#include "alThunk.h" static void LoadData(ALbuffer *ALBuf, const ALubyte *data, ALsizei size, ALuint freq, ALenum OrigFormat, ALenum NewFormat); diff --git a/OpenAL32/alSource.c b/OpenAL32/alSource.c index 7c022e6c..44cd8b41 100644 --- a/OpenAL32/alSource.c +++ b/OpenAL32/alSource.c @@ -26,6 +26,8 @@ #include "AL/alc.h" #include "alError.h" #include "alSource.h" +#include "alBuffer.h" +#include "alThunk.h" static ALvoid InitSourceParams(ALsource *pSource); static ALboolean GetSourceOffset(ALsource *pSource, ALenum eName, ALfloat *pflOffset); From 7a99b1fa32341460eb3144e860e6bd23467ae919 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Mon, 31 Dec 2007 01:16:13 -0800 Subject: [PATCH 22/33] Make some defines local to ALu.c --- Alc/ALu.c | 6 ++++++ OpenAL32/Include/alu.h | 6 ------ 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/Alc/ALu.c b/Alc/ALu.c index b19bd518..bb2bbd0a 100644 --- a/Alc/ALu.c +++ b/Alc/ALu.c @@ -56,6 +56,12 @@ typedef long long ALint64; #define __min min #endif +#define BUFFERSIZE 48000 +#define FRACTIONBITS 14 +#define FRACTIONMASK ((1L< Date: Mon, 31 Dec 2007 01:47:10 -0800 Subject: [PATCH 23/33] Use an enum list for dealing with channels This will make it easier to remap channels, especially the center and lfe channels --- Alc/ALu.c | 146 +++++++++++++++++++++++++++++------------------------- 1 file changed, 79 insertions(+), 67 deletions(-) diff --git a/Alc/ALu.c b/Alc/ALu.c index bb2bbd0a..682132e1 100644 --- a/Alc/ALu.c +++ b/Alc/ALu.c @@ -60,7 +60,17 @@ typedef long long ALint64; #define FRACTIONBITS 14 #define FRACTIONMASK ((1L<>FRACTIONBITS)); //Direct path final mix buffer and panning - DryBuffer[j][0] += value*DrySend[0]; - DryBuffer[j][1] += value*DrySend[1]; - DryBuffer[j][2] += value*DrySend[2]; - DryBuffer[j][3] += value*DrySend[3]; + DryBuffer[j][FRONT_LEFT] += value*DrySend[FRONT_LEFT]; + DryBuffer[j][FRONT_RIGHT] += value*DrySend[FRONT_RIGHT]; + DryBuffer[j][BACK_LEFT] += value*DrySend[BACK_LEFT]; + DryBuffer[j][BACK_RIGHT] += value*DrySend[BACK_RIGHT]; //Room path final mix buffer and panning - WetBuffer[j][0] += value*WetSend[0]; - WetBuffer[j][1] += value*WetSend[1]; - WetBuffer[j][2] += value*WetSend[2]; - WetBuffer[j][3] += value*WetSend[3]; + WetBuffer[j][FRONT_LEFT] += value*WetSend[FRONT_LEFT]; + WetBuffer[j][FRONT_RIGHT] += value*WetSend[FRONT_RIGHT]; + WetBuffer[j][BACK_LEFT] += value*WetSend[BACK_LEFT]; + WetBuffer[j][BACK_RIGHT] += value*WetSend[BACK_RIGHT]; } else { //First order interpolator (left) value = (ALfloat)((ALshort)(((Data[k*2 ]*((1L<>FRACTIONBITS)); //Direct path final mix buffer and panning (left) - DryBuffer[j][0] += value*DrySend[0]; + DryBuffer[j][FRONT_LEFT] += value*DrySend[FRONT_LEFT]; //Room path final mix buffer and panning (left) - WetBuffer[j][0] += value*WetSend[0]; + WetBuffer[j][FRONT_LEFT] += value*WetSend[FRONT_LEFT]; //First order interpolator (right) value = (ALfloat)((ALshort)(((Data[k*2+1]*((1L<>FRACTIONBITS)); //Direct path final mix buffer and panning (right) - DryBuffer[j][1] += value*DrySend[1]; + DryBuffer[j][FRONT_RIGHT] += value*DrySend[FRONT_RIGHT]; //Room path final mix buffer and panning (right) - WetBuffer[j][1] += value*WetSend[1]; + WetBuffer[j][FRONT_RIGHT] += value*WetSend[FRONT_RIGHT]; } DataPosFrac += increment; j++; @@ -648,74 +658,76 @@ ALvoid aluMixData(ALCcontext *ALContext,ALvoid *buffer,ALsizei size,ALenum forma case AL_FORMAT_MONO8: for(i = 0;i < SamplesToDo;i++) { - ((ALubyte*)buffer)[0] = (ALubyte)((aluF2S(DryBuffer[i][0]+DryBuffer[i][1]+WetBuffer[i][0]+WetBuffer[i][1])>>8)+128); + ((ALubyte*)buffer)[0] = (ALubyte)((aluF2S(DryBuffer[i][FRONT_LEFT]+DryBuffer[i][FRONT_RIGHT]+ + WetBuffer[i][FRONT_LEFT]+WetBuffer[i][FRONT_RIGHT])>>8)+128); buffer = ((ALubyte*)buffer) + 1; } break; case AL_FORMAT_STEREO8: for(i = 0;i < SamplesToDo;i++) { - ((ALubyte*)buffer)[0] = (ALubyte)((aluF2S(DryBuffer[i][0]+WetBuffer[i][0])>>8)+128); - ((ALubyte*)buffer)[1] = (ALubyte)((aluF2S(DryBuffer[i][1]+WetBuffer[i][1])>>8)+128); + ((ALubyte*)buffer)[0] = (ALubyte)((aluF2S(DryBuffer[i][FRONT_LEFT] +WetBuffer[i][FRONT_LEFT])>>8)+128); + ((ALubyte*)buffer)[1] = (ALubyte)((aluF2S(DryBuffer[i][FRONT_RIGHT]+WetBuffer[i][FRONT_RIGHT])>>8)+128); buffer = ((ALubyte*)buffer) + 2; } break; case AL_FORMAT_QUAD8: for(i = 0;i < SamplesToDo;i++) { - ((ALubyte*)buffer)[0] = (ALubyte)((aluF2S(DryBuffer[i][0]+WetBuffer[i][0])>>8)+128); - ((ALubyte*)buffer)[1] = (ALubyte)((aluF2S(DryBuffer[i][1]+WetBuffer[i][1])>>8)+128); - ((ALubyte*)buffer)[2] = (ALubyte)((aluF2S(DryBuffer[i][2]+WetBuffer[i][2])>>8)+128); - ((ALubyte*)buffer)[3] = (ALubyte)((aluF2S(DryBuffer[i][3]+WetBuffer[i][3])>>8)+128); + ((ALubyte*)buffer)[0] = (ALubyte)((aluF2S(DryBuffer[i][FRONT_LEFT] +WetBuffer[i][FRONT_LEFT])>>8)+128); + ((ALubyte*)buffer)[1] = (ALubyte)((aluF2S(DryBuffer[i][FRONT_RIGHT]+WetBuffer[i][FRONT_RIGHT])>>8)+128); + ((ALubyte*)buffer)[2] = (ALubyte)((aluF2S(DryBuffer[i][BACK_LEFT] +WetBuffer[i][BACK_LEFT])>>8)+128); + ((ALubyte*)buffer)[3] = (ALubyte)((aluF2S(DryBuffer[i][BACK_RIGHT] +WetBuffer[i][BACK_RIGHT])>>8)+128); buffer = ((ALubyte*)buffer) + 4; } break; case AL_FORMAT_51CHN8: for(i = 0;i < SamplesToDo;i++) { - ((ALubyte*)buffer)[0] = (ALubyte)((aluF2S(DryBuffer[i][0]+WetBuffer[i][0])>>8)+128); - ((ALubyte*)buffer)[1] = (ALubyte)((aluF2S(DryBuffer[i][1]+WetBuffer[i][1])>>8)+128); - ((ALubyte*)buffer)[2] = (ALubyte)((aluF2S(DryBuffer[i][2]+WetBuffer[i][2])>>8)+128); - ((ALubyte*)buffer)[3] = (ALubyte)((aluF2S(DryBuffer[i][3]+WetBuffer[i][3])>>8)+128); - ((ALubyte*)buffer)[4] = (ALubyte)((aluF2S(DryBuffer[i][4]+WetBuffer[i][4])>>8)+128); - ((ALubyte*)buffer)[5] = (ALubyte)((aluF2S(DryBuffer[i][5]+WetBuffer[i][5])>>8)+128); + ((ALubyte*)buffer)[0] = (ALubyte)((aluF2S(DryBuffer[i][FRONT_LEFT] +WetBuffer[i][FRONT_LEFT])>>8)+128); + ((ALubyte*)buffer)[1] = (ALubyte)((aluF2S(DryBuffer[i][FRONT_RIGHT]+WetBuffer[i][FRONT_RIGHT])>>8)+128); + ((ALubyte*)buffer)[2] = (ALubyte)((aluF2S(DryBuffer[i][BACK_LEFT] +WetBuffer[i][BACK_LEFT])>>8)+128); + ((ALubyte*)buffer)[3] = (ALubyte)((aluF2S(DryBuffer[i][BACK_RIGHT] +WetBuffer[i][BACK_RIGHT])>>8)+128); + ((ALubyte*)buffer)[4] = (ALubyte)((aluF2S(DryBuffer[i][CENTER] +WetBuffer[i][CENTER])>>8)+128); + ((ALubyte*)buffer)[5] = (ALubyte)((aluF2S(DryBuffer[i][LFE] +WetBuffer[i][LFE])>>8)+128); buffer = ((ALubyte*)buffer) + 6; } break; case AL_FORMAT_MONO16: for(i = 0;i < SamplesToDo;i++) { - ((ALshort*)buffer)[0] = aluF2S(DryBuffer[i][0]+DryBuffer[i][1]+WetBuffer[i][0]+WetBuffer[i][1]); + ((ALshort*)buffer)[0] = aluF2S(DryBuffer[i][FRONT_LEFT]+DryBuffer[i][FRONT_RIGHT]+ + WetBuffer[i][FRONT_LEFT]+WetBuffer[i][FRONT_RIGHT]); buffer = ((ALshort*)buffer) + 1; } break; case AL_FORMAT_STEREO16: for(i = 0;i < SamplesToDo;i++) { - ((ALshort*)buffer)[0] = aluF2S(DryBuffer[i][0]+WetBuffer[i][0]); - ((ALshort*)buffer)[1] = aluF2S(DryBuffer[i][1]+WetBuffer[i][1]); + ((ALshort*)buffer)[0] = aluF2S(DryBuffer[i][FRONT_LEFT] +WetBuffer[i][FRONT_LEFT]); + ((ALshort*)buffer)[1] = aluF2S(DryBuffer[i][FRONT_RIGHT]+WetBuffer[i][FRONT_RIGHT]); buffer = ((ALshort*)buffer) + 2; } break; case AL_FORMAT_QUAD16: for(i = 0;i < SamplesToDo;i++) { - ((ALshort*)buffer)[0] = aluF2S(DryBuffer[i][0]+WetBuffer[i][0]); - ((ALshort*)buffer)[1] = aluF2S(DryBuffer[i][1]+WetBuffer[i][1]); - ((ALshort*)buffer)[2] = aluF2S(DryBuffer[i][2]+WetBuffer[i][2]); - ((ALshort*)buffer)[3] = aluF2S(DryBuffer[i][3]+WetBuffer[i][3]); + ((ALshort*)buffer)[0] = aluF2S(DryBuffer[i][FRONT_LEFT] +WetBuffer[i][FRONT_LEFT]); + ((ALshort*)buffer)[1] = aluF2S(DryBuffer[i][FRONT_RIGHT]+WetBuffer[i][FRONT_RIGHT]); + ((ALshort*)buffer)[2] = aluF2S(DryBuffer[i][BACK_LEFT] +WetBuffer[i][BACK_LEFT]); + ((ALshort*)buffer)[3] = aluF2S(DryBuffer[i][BACK_RIGHT] +WetBuffer[i][BACK_RIGHT]); buffer = ((ALshort*)buffer) + 4; } break; case AL_FORMAT_51CHN16: for(i = 0;i < SamplesToDo;i++) { - ((ALshort*)buffer)[0] = aluF2S(DryBuffer[i][0]+WetBuffer[i][0]); - ((ALshort*)buffer)[1] = aluF2S(DryBuffer[i][1]+WetBuffer[i][1]); - ((ALshort*)buffer)[2] = aluF2S(DryBuffer[i][2]+WetBuffer[i][2]); - ((ALshort*)buffer)[3] = aluF2S(DryBuffer[i][3]+WetBuffer[i][3]); - ((ALshort*)buffer)[4] = aluF2S(DryBuffer[i][4]+WetBuffer[i][4]); - ((ALshort*)buffer)[5] = aluF2S(DryBuffer[i][5]+WetBuffer[i][5]); + ((ALshort*)buffer)[0] = aluF2S(DryBuffer[i][FRONT_LEFT] +WetBuffer[i][FRONT_LEFT]); + ((ALshort*)buffer)[1] = aluF2S(DryBuffer[i][FRONT_RIGHT]+WetBuffer[i][FRONT_RIGHT]); + ((ALshort*)buffer)[2] = aluF2S(DryBuffer[i][BACK_LEFT] +WetBuffer[i][BACK_LEFT]); + ((ALshort*)buffer)[3] = aluF2S(DryBuffer[i][BACK_RIGHT] +WetBuffer[i][BACK_RIGHT]); + ((ALshort*)buffer)[4] = aluF2S(DryBuffer[i][CENTER] +WetBuffer[i][CENTER]); + ((ALshort*)buffer)[5] = aluF2S(DryBuffer[i][LFE] +WetBuffer[i][LFE]); buffer = ((ALshort*)buffer) + 6; } break; From 76dd568971fcefb4a1aee523dc02c83fe5950bf4 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Mon, 31 Dec 2007 02:53:56 -0800 Subject: [PATCH 24/33] Add some more formats --- OpenAL32/Include/alMain.h | 18 +++++++++++++++--- OpenAL32/alExtension.c | 11 +++++++++++ 2 files changed, 26 insertions(+), 3 deletions(-) diff --git a/OpenAL32/Include/alMain.h b/OpenAL32/Include/alMain.h index f2beb30f..08f0a9ff 100644 --- a/OpenAL32/Include/alMain.h +++ b/OpenAL32/Include/alMain.h @@ -85,12 +85,24 @@ extern char _alDebug[256]; #define AL_FORMAT_MONO_IMA4 0x1300 #define AL_FORMAT_STEREO_IMA4 0x1301 + // These are from AL_EXT_MCFORMATS, which we don't support yet but the mixer -// can use the extra formats -#define AL_FORMAT_QUAD8 0x1204 -#define AL_FORMAT_QUAD16 0x1205 +// can use some of the extra formats #define AL_FORMAT_51CHN8 0x120A #define AL_FORMAT_51CHN16 0x120B +#define AL_FORMAT_51CHN32 0x120C +#define AL_FORMAT_61CHN8 0x120D +#define AL_FORMAT_61CHN16 0x120E +#define AL_FORMAT_61CHN32 0x120F +#define AL_FORMAT_71CHN8 0x1210 +#define AL_FORMAT_71CHN16 0x1211 +#define AL_FORMAT_71CHN32 0x1212 +#define AL_FORMAT_QUAD8 0x1204 +#define AL_FORMAT_QUAD16 0x1205 +#define AL_FORMAT_QUAD32 0x1206 +#define AL_FORMAT_REAR8 0x1207 +#define AL_FORMAT_REAR16 0x1208 +#define AL_FORMAT_REAR32 0x1209 #define SWMIXER_OUTPUT_RATE 44100 diff --git a/OpenAL32/alExtension.c b/OpenAL32/alExtension.c index 24ea48db..a48eba9f 100644 --- a/OpenAL32/alExtension.c +++ b/OpenAL32/alExtension.c @@ -156,8 +156,19 @@ static ALenums enumeration[]={ { (ALchar *)"AL_FORMAT_STEREO_IMA4", AL_FORMAT_STEREO_IMA4 }, { (ALchar *)"AL_FORMAT_QUAD8", AL_FORMAT_QUAD8 }, { (ALchar *)"AL_FORMAT_QUAD16", AL_FORMAT_QUAD16 }, + { (ALchar *)"AL_FORMAT_QUAD32", AL_FORMAT_QUAD32 }, { (ALchar *)"AL_FORMAT_51CHN8", AL_FORMAT_51CHN8 }, { (ALchar *)"AL_FORMAT_51CHN16", AL_FORMAT_51CHN16 }, + { (ALchar *)"AL_FORMAT_51CHN32", AL_FORMAT_51CHN32 }, + { (ALchar *)"AL_FORMAT_61CHN8", AL_FORMAT_61CHN8 }, + { (ALchar *)"AL_FORMAT_61CHN16", AL_FORMAT_61CHN16 }, + { (ALchar *)"AL_FORMAT_61CHN32", AL_FORMAT_61CHN32 }, + { (ALchar *)"AL_FORMAT_71CHN8", AL_FORMAT_71CHN8 }, + { (ALchar *)"AL_FORMAT_71CHN16", AL_FORMAT_71CHN16 }, + { (ALchar *)"AL_FORMAT_71CHN32", AL_FORMAT_71CHN32 }, + { (ALchar *)"AL_FORMAT_REAR8", AL_FORMAT_REAR8 }, + { (ALchar *)"AL_FORMAT_REAR16", AL_FORMAT_REAR16 }, + { (ALchar *)"AL_FORMAT_REAR32", AL_FORMAT_REAR32 }, // Buffer attributes { (ALchar *)"AL_FREQUENCY", AL_FREQUENCY }, From 1c852736620d97e2ce5be27479167046074c347e Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Mon, 31 Dec 2007 02:55:35 -0800 Subject: [PATCH 25/33] Export float32 formats --- OpenAL32/alExtension.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/OpenAL32/alExtension.c b/OpenAL32/alExtension.c index a48eba9f..82ee3f62 100644 --- a/OpenAL32/alExtension.c +++ b/OpenAL32/alExtension.c @@ -150,8 +150,10 @@ static ALenums enumeration[]={ // Buffer Formats { (ALchar *)"AL_FORMAT_MONO8", AL_FORMAT_MONO8 }, { (ALchar *)"AL_FORMAT_MONO16", AL_FORMAT_MONO16 }, + { (ALchar *)"AL_FORMAT_MONO_FLOAT32", AL_FORMAT_MONO_FLOAT32 }, { (ALchar *)"AL_FORMAT_STEREO8", AL_FORMAT_STEREO8 }, { (ALchar *)"AL_FORMAT_STEREO16", AL_FORMAT_STEREO16 }, + { (ALchar *)"AL_FORMAT_STEREO_FLOAT32", AL_FORMAT_STEREO_FLOAT32 }, { (ALchar *)"AL_FORMAT_MONO_IMA4", AL_FORMAT_MONO_IMA4 }, { (ALchar *)"AL_FORMAT_STEREO_IMA4", AL_FORMAT_STEREO_IMA4 }, { (ALchar *)"AL_FORMAT_QUAD8", AL_FORMAT_QUAD8 }, From 79b95da0a3084dc1ba285f4f464b67d2ac76a9eb Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Mon, 31 Dec 2007 02:57:58 -0800 Subject: [PATCH 26/33] Check specific formats before general properties --- OpenAL32/alSource.c | 38 +++++++++++++++++++------------------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/OpenAL32/alSource.c b/OpenAL32/alSource.c index 44cd8b41..9b4909c5 100644 --- a/OpenAL32/alSource.c +++ b/OpenAL32/alSource.c @@ -1908,7 +1908,15 @@ static ALboolean GetSourceOffset(ALsource *pSource, ALenum eName, ALfloat *pflOf break; case AL_BYTE_OFFSET: // Take into account the original format of the Buffer - if (aluBytesFromFormat(eOriginalFormat) == 1) + if ((eOriginalFormat == AL_FORMAT_MONO_IMA4) || + (eOriginalFormat == AL_FORMAT_STEREO_IMA4)) + { + // Compression rate of the ADPCM supported is 3.6111 to 1 + lBytesPlayed = (ALint)((ALfloat)lBytesPlayed / 3.6111f); + // Round down to nearest ADPCM block + *pflOffset = (ALfloat)((lBytesPlayed / (36 * lChannels)) * 36 * lChannels); + } + else if (aluBytesFromFormat(eOriginalFormat) == 1) { *pflOffset = (ALfloat)(lBytesPlayed >> 1); } @@ -1916,14 +1924,6 @@ static ALboolean GetSourceOffset(ALsource *pSource, ALenum eName, ALfloat *pflOf { *pflOffset = (ALfloat)(lBytesPlayed << 1); } - else if ((eOriginalFormat == AL_FORMAT_MONO_IMA4) || - (eOriginalFormat == AL_FORMAT_STEREO_IMA4)) - { - // Compression rate of the ADPCM supported is 3.6111 to 1 - lBytesPlayed = (ALint)((ALfloat)lBytesPlayed / 3.6111f); - // Round down to nearest ADPCM block - *pflOffset = (ALfloat)((lBytesPlayed / (36 * lChannels)) * 36 * lChannels); - } else { *pflOffset = (ALfloat)lBytesPlayed; @@ -2062,7 +2062,16 @@ static ALint GetByteOffset(ALsource *pSource) { case AL_BYTE_OFFSET: // Take into consideration the original format - if (aluBytesFromFormat(pBuffer->eOriginalFormat) == 1) + if ((pBuffer->eOriginalFormat == AL_FORMAT_MONO_IMA4) || + (pBuffer->eOriginalFormat == AL_FORMAT_STEREO_IMA4)) + { + // Round down to nearest ADPCM block + lByteOffset = (pSource->lOffset / (36 * lChannels)) * 36 * lChannels; + // Multiply by compression rate + lByteOffset = (ALint)(3.6111f * (ALfloat)lByteOffset); + lByteOffset -= (lByteOffset % (lChannels * 2)); + } + else if (aluBytesFromFormat(pBuffer->eOriginalFormat) == 1) { lByteOffset = pSource->lOffset * 2; lByteOffset -= (lByteOffset % (lChannels * 2)); @@ -2072,15 +2081,6 @@ static ALint GetByteOffset(ALsource *pSource) lByteOffset = pSource->lOffset / 2; lByteOffset -= (lByteOffset % (lChannels * 2)); } - else if ((pBuffer->eOriginalFormat == AL_FORMAT_MONO_IMA4) || - (pBuffer->eOriginalFormat == AL_FORMAT_STEREO_IMA4)) - { - // Round down to nearest ADPCM block - lByteOffset = (pSource->lOffset / (36 * lChannels)) * 36 * lChannels; - // Multiply by compression rate - lByteOffset = (ALint)(3.6111f * (ALfloat)lByteOffset); - lByteOffset -= (lByteOffset % (lChannels * 2)); - } else { lByteOffset = pSource->lOffset; From 73678f3b78a54d0dcc43abbd168ede2fd58bb205 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Mon, 31 Dec 2007 03:29:14 -0800 Subject: [PATCH 27/33] Allow psuedo 6.1 and 7.1 output This only does spatial calculations on the 4 corner speakers, but it's necessary groundwork for AL_EXT_MCFORMATS support. Spatial calculations for 6 speakers can be added later. --- Alc/ALu.c | 98 ++++++++++++++++++++++++++++++++++++++++++++++++- openalrc.sample | 4 ++ 2 files changed, 100 insertions(+), 2 deletions(-) diff --git a/Alc/ALu.c b/Alc/ALu.c index 682132e1..0473a4b0 100644 --- a/Alc/ALu.c +++ b/Alc/ALu.c @@ -64,6 +64,8 @@ typedef long long ALint64; enum { FRONT_LEFT = 0, FRONT_RIGHT, + SIDE_LEFT, + SIDE_RIGHT, BACK_LEFT, BACK_RIGHT, CENTER, @@ -72,6 +74,8 @@ enum { OUTPUTCHANNELS }; +/* NOTE: The AL_FORMAT_REAR* enums aren't handled here be cause they're + * converted to AL_FORMAT_QUAD* when loaded */ __inline ALuint aluBytesFromFormat(ALenum format) { switch(format) @@ -80,16 +84,24 @@ __inline ALuint aluBytesFromFormat(ALenum format) case AL_FORMAT_STEREO8: case AL_FORMAT_QUAD8: case AL_FORMAT_51CHN8: + case AL_FORMAT_61CHN8: + case AL_FORMAT_71CHN8: return 1; case AL_FORMAT_MONO16: case AL_FORMAT_STEREO16: case AL_FORMAT_QUAD16: case AL_FORMAT_51CHN16: + case AL_FORMAT_61CHN16: + case AL_FORMAT_71CHN16: return 2; case AL_FORMAT_MONO_FLOAT32: case AL_FORMAT_STEREO_FLOAT32: + case AL_FORMAT_QUAD32: + case AL_FORMAT_51CHN32: + case AL_FORMAT_61CHN32: + case AL_FORMAT_71CHN32: return 4; default: @@ -113,12 +125,24 @@ __inline ALuint aluChannelsFromFormat(ALenum format) case AL_FORMAT_QUAD8: case AL_FORMAT_QUAD16: + case AL_FORMAT_QUAD32: return 4; case AL_FORMAT_51CHN8: case AL_FORMAT_51CHN16: + case AL_FORMAT_51CHN32: return 6; + case AL_FORMAT_61CHN8: + case AL_FORMAT_61CHN16: + case AL_FORMAT_61CHN32: + return 7; + + case AL_FORMAT_71CHN8: + case AL_FORMAT_71CHN16: + case AL_FORMAT_71CHN32: + return 8; + default: return 0; } @@ -371,6 +395,9 @@ static ALvoid CalcSourceParams(ALCcontext *ALContext, ALsource *ALSource, case 4: /* TODO: Add center/lfe channel in spatial calculations? */ case 6: + /* TODO: Special paths for 6.1 and 7.1 output would be nice */ + case 7: + case 8: // Apply a scalar so each individual speaker has more weight PanningLR = 0.5f + (0.5f*Position[0]*1.41421356f); PanningLR = __min(1.0f, PanningLR); @@ -382,10 +409,14 @@ static ALvoid CalcSourceParams(ALCcontext *ALContext, ALsource *ALSource, drysend[FRONT_RIGHT] = ConeVolume * ListenerGain * DryMix * aluSqrt(( PanningLR)*(1.0f-PanningFB)); drysend[BACK_LEFT] = ConeVolume * ListenerGain * DryMix * aluSqrt((1.0f-PanningLR)*( PanningFB)); drysend[BACK_RIGHT] = ConeVolume * ListenerGain * DryMix * aluSqrt(( PanningLR)*( PanningFB)); + drysend[SIDE_LEFT] = 0.0f; + drysend[SIDE_RIGHT] = 0.0f; wetsend[FRONT_LEFT] = ListenerGain * WetMix * aluSqrt((1.0f-PanningLR)*(1.0f-PanningFB)); wetsend[FRONT_RIGHT] = ListenerGain * WetMix * aluSqrt(( PanningLR)*(1.0f-PanningFB)); wetsend[BACK_LEFT] = ListenerGain * WetMix * aluSqrt((1.0f-PanningLR)*( PanningFB)); wetsend[BACK_RIGHT] = ListenerGain * WetMix * aluSqrt(( PanningLR)*( PanningFB)); + wetsend[SIDE_LEFT] = 0.0f; + wetsend[SIDE_RIGHT] = 0.0f; break; default: break; @@ -396,12 +427,16 @@ static ALvoid CalcSourceParams(ALCcontext *ALContext, ALsource *ALSource, //1. Multi-channel buffers always play "normal" drysend[FRONT_LEFT] = SourceVolume * 1.0f * ListenerGain; drysend[FRONT_RIGHT] = SourceVolume * 1.0f * ListenerGain; + drysend[SIDE_LEFT] = SourceVolume * 1.0f * ListenerGain; + drysend[SIDE_RIGHT] = SourceVolume * 1.0f * ListenerGain; drysend[BACK_LEFT] = SourceVolume * 1.0f * ListenerGain; drysend[BACK_RIGHT] = SourceVolume * 1.0f * ListenerGain; drysend[CENTER] = SourceVolume * 1.0f * ListenerGain; drysend[LFE] = SourceVolume * 1.0f * ListenerGain; wetsend[FRONT_LEFT] = SourceVolume * 0.0f * ListenerGain; wetsend[FRONT_RIGHT] = SourceVolume * 0.0f * ListenerGain; + wetsend[SIDE_LEFT] = SourceVolume * 0.0f * ListenerGain; + wetsend[SIDE_RIGHT] = SourceVolume * 0.0f * ListenerGain; wetsend[BACK_LEFT] = SourceVolume * 0.0f * ListenerGain; wetsend[BACK_RIGHT] = SourceVolume * 0.0f * ListenerGain; wetsend[CENTER] = SourceVolume * 0.0f * ListenerGain; @@ -415,8 +450,8 @@ ALvoid aluMixData(ALCcontext *ALContext,ALvoid *buffer,ALsizei size,ALenum forma { static float DryBuffer[BUFFERSIZE][OUTPUTCHANNELS]; static float WetBuffer[BUFFERSIZE][OUTPUTCHANNELS]; - ALfloat DrySend[OUTPUTCHANNELS] = { 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f }; - ALfloat WetSend[OUTPUTCHANNELS] = { 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f }; + ALfloat DrySend[OUTPUTCHANNELS] = { 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f }; + ALfloat WetSend[OUTPUTCHANNELS] = { 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f }; ALuint BlockAlign,BufferSize; ALuint DataSize=0,DataPosInt=0,DataPosFrac=0; ALuint Channels,Bits,Frequency,ulExtraSamples; @@ -543,11 +578,15 @@ ALvoid aluMixData(ALCcontext *ALContext,ALvoid *buffer,ALsizei size,ALenum forma //Direct path final mix buffer and panning DryBuffer[j][FRONT_LEFT] += value*DrySend[FRONT_LEFT]; DryBuffer[j][FRONT_RIGHT] += value*DrySend[FRONT_RIGHT]; + DryBuffer[j][SIDE_LEFT] += value*DrySend[SIDE_LEFT]; + DryBuffer[j][SIDE_RIGHT] += value*DrySend[SIDE_RIGHT]; DryBuffer[j][BACK_LEFT] += value*DrySend[BACK_LEFT]; DryBuffer[j][BACK_RIGHT] += value*DrySend[BACK_RIGHT]; //Room path final mix buffer and panning WetBuffer[j][FRONT_LEFT] += value*WetSend[FRONT_LEFT]; WetBuffer[j][FRONT_RIGHT] += value*WetSend[FRONT_RIGHT]; + WetBuffer[j][SIDE_LEFT] += value*WetSend[SIDE_LEFT]; + WetBuffer[j][SIDE_RIGHT] += value*WetSend[SIDE_RIGHT]; WetBuffer[j][BACK_LEFT] += value*WetSend[BACK_LEFT]; WetBuffer[j][BACK_RIGHT] += value*WetSend[BACK_RIGHT]; } @@ -693,6 +732,34 @@ ALvoid aluMixData(ALCcontext *ALContext,ALvoid *buffer,ALsizei size,ALenum forma buffer = ((ALubyte*)buffer) + 6; } break; + case AL_FORMAT_61CHN8: + for(i = 0;i < SamplesToDo;i++) + { + ((ALubyte*)buffer)[0] = (ALubyte)((aluF2S(DryBuffer[i][FRONT_LEFT] +WetBuffer[i][FRONT_LEFT])>>8)+128); + ((ALubyte*)buffer)[1] = (ALubyte)((aluF2S(DryBuffer[i][FRONT_RIGHT]+WetBuffer[i][FRONT_RIGHT])>>8)+128); + ((ALubyte*)buffer)[2] = (ALubyte)((aluF2S(DryBuffer[i][SIDE_LEFT] +WetBuffer[i][SIDE_LEFT])>>8)+128); + ((ALubyte*)buffer)[3] = (ALubyte)((aluF2S(DryBuffer[i][SIDE_RIGHT] +WetBuffer[i][SIDE_RIGHT])>>8)+128); + ((ALubyte*)buffer)[4] = (ALubyte)((aluF2S(DryBuffer[i][BACK_LEFT] +WetBuffer[i][BACK_LEFT])>>8)+128); + ((ALubyte*)buffer)[5] = (ALubyte)((aluF2S(DryBuffer[i][BACK_RIGHT] +WetBuffer[i][BACK_RIGHT])>>8)+128); + ((ALubyte*)buffer)[6] = (ALubyte)((aluF2S(DryBuffer[i][LFE] +WetBuffer[i][LFE])>>8)+128); + buffer = ((ALubyte*)buffer) + 7; + } + break; + case AL_FORMAT_71CHN8: + for(i = 0;i < SamplesToDo;i++) + { + ((ALubyte*)buffer)[0] = (ALubyte)((aluF2S(DryBuffer[i][FRONT_LEFT] +WetBuffer[i][FRONT_LEFT])>>8)+128); + ((ALubyte*)buffer)[1] = (ALubyte)((aluF2S(DryBuffer[i][FRONT_RIGHT]+WetBuffer[i][FRONT_RIGHT])>>8)+128); + ((ALubyte*)buffer)[2] = (ALubyte)((aluF2S(DryBuffer[i][SIDE_LEFT] +WetBuffer[i][SIDE_LEFT])>>8)+128); + ((ALubyte*)buffer)[3] = (ALubyte)((aluF2S(DryBuffer[i][SIDE_RIGHT] +WetBuffer[i][SIDE_RIGHT])>>8)+128); + ((ALubyte*)buffer)[4] = (ALubyte)((aluF2S(DryBuffer[i][BACK_LEFT] +WetBuffer[i][BACK_LEFT])>>8)+128); + ((ALubyte*)buffer)[5] = (ALubyte)((aluF2S(DryBuffer[i][BACK_RIGHT] +WetBuffer[i][BACK_RIGHT])>>8)+128); + ((ALubyte*)buffer)[6] = (ALubyte)((aluF2S(DryBuffer[i][CENTER] +WetBuffer[i][CENTER])>>8)+128); + ((ALubyte*)buffer)[7] = (ALubyte)((aluF2S(DryBuffer[i][LFE] +WetBuffer[i][LFE])>>8)+128); + buffer = ((ALubyte*)buffer) + 8; + } + break; + case AL_FORMAT_MONO16: for(i = 0;i < SamplesToDo;i++) { @@ -731,6 +798,33 @@ ALvoid aluMixData(ALCcontext *ALContext,ALvoid *buffer,ALsizei size,ALenum forma buffer = ((ALshort*)buffer) + 6; } break; + case AL_FORMAT_61CHN16: + for(i = 0;i < SamplesToDo;i++) + { + ((ALshort*)buffer)[0] = aluF2S(DryBuffer[i][FRONT_LEFT] +WetBuffer[i][FRONT_LEFT]); + ((ALshort*)buffer)[1] = aluF2S(DryBuffer[i][FRONT_RIGHT]+WetBuffer[i][FRONT_RIGHT]); + ((ALshort*)buffer)[2] = aluF2S(DryBuffer[i][SIDE_LEFT] +WetBuffer[i][SIDE_LEFT]); + ((ALshort*)buffer)[3] = aluF2S(DryBuffer[i][SIDE_RIGHT] +WetBuffer[i][SIDE_RIGHT]); + ((ALshort*)buffer)[4] = aluF2S(DryBuffer[i][BACK_LEFT] +WetBuffer[i][BACK_LEFT]); + ((ALshort*)buffer)[5] = aluF2S(DryBuffer[i][BACK_RIGHT] +WetBuffer[i][BACK_RIGHT]); + ((ALshort*)buffer)[6] = aluF2S(DryBuffer[i][LFE] +WetBuffer[i][LFE]); + buffer = ((ALshort*)buffer) + 7; + } + break; + case AL_FORMAT_71CHN16: + for(i = 0;i < SamplesToDo;i++) + { + ((ALshort*)buffer)[0] = aluF2S(DryBuffer[i][FRONT_LEFT] +WetBuffer[i][FRONT_LEFT]); + ((ALshort*)buffer)[1] = aluF2S(DryBuffer[i][FRONT_RIGHT]+WetBuffer[i][FRONT_RIGHT]); + ((ALshort*)buffer)[2] = aluF2S(DryBuffer[i][SIDE_LEFT] +WetBuffer[i][SIDE_LEFT]); + ((ALshort*)buffer)[3] = aluF2S(DryBuffer[i][SIDE_RIGHT] +WetBuffer[i][SIDE_RIGHT]); + ((ALshort*)buffer)[4] = aluF2S(DryBuffer[i][BACK_LEFT] +WetBuffer[i][BACK_LEFT]); + ((ALshort*)buffer)[5] = aluF2S(DryBuffer[i][BACK_RIGHT] +WetBuffer[i][BACK_RIGHT]); + ((ALshort*)buffer)[6] = aluF2S(DryBuffer[i][CENTER] +WetBuffer[i][CENTER]); + ((ALshort*)buffer)[7] = aluF2S(DryBuffer[i][LFE] +WetBuffer[i][LFE]); + buffer = ((ALshort*)buffer) + 8; + } + break; default: break; diff --git a/openalrc.sample b/openalrc.sample index c456d544..cb4b28dc 100644 --- a/openalrc.sample +++ b/openalrc.sample @@ -13,10 +13,14 @@ format = AL_FORMAT_STEREO16 # Sets the output format. Can be one of: # AL_FORMAT_STEREO8 (8-bit stereo) # AL_FORMAT_QUAD8 (8-bit 4-channel) # AL_FORMAT_51CHN8 (8-bit 5.1 output) + # AL_FORMAT_61CHN8 (8-bit 6.1 output) + # AL_FORMAT_71CHN8 (8-bit 7.1 output) # AL_FORMAT_MONO16 (16-bit mono) # AL_FORMAT_STEREO16 (16-bit stereo) # AL_FORMAT_QUAD16 (16-bit 4-channel) # AL_FORMAT_51CHN16 (16-bit 5.1 output) + # AL_FORMAT_61CHN16 (16-bit 6.1 output) + # AL_FORMAT_71CHN16 (16-bit 7.1 output) # Default is AL_FORMAT_STEREO16 frequency = 44100 # Sets the output frequency. Default is 44100 From 1cbd625b4e88a75deafbed3d30b7e7068ec819c0 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Mon, 31 Dec 2007 03:45:26 -0800 Subject: [PATCH 28/33] Disable unnecessary calculations --- Alc/ALu.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Alc/ALu.c b/Alc/ALu.c index 0473a4b0..d62dd1b4 100644 --- a/Alc/ALu.c +++ b/Alc/ALu.c @@ -578,15 +578,19 @@ ALvoid aluMixData(ALCcontext *ALContext,ALvoid *buffer,ALsizei size,ALenum forma //Direct path final mix buffer and panning DryBuffer[j][FRONT_LEFT] += value*DrySend[FRONT_LEFT]; DryBuffer[j][FRONT_RIGHT] += value*DrySend[FRONT_RIGHT]; +#if 0 /* FIXME: Re-enable when proper 6-channel spatialization is used */ DryBuffer[j][SIDE_LEFT] += value*DrySend[SIDE_LEFT]; DryBuffer[j][SIDE_RIGHT] += value*DrySend[SIDE_RIGHT]; +#endif DryBuffer[j][BACK_LEFT] += value*DrySend[BACK_LEFT]; DryBuffer[j][BACK_RIGHT] += value*DrySend[BACK_RIGHT]; //Room path final mix buffer and panning WetBuffer[j][FRONT_LEFT] += value*WetSend[FRONT_LEFT]; WetBuffer[j][FRONT_RIGHT] += value*WetSend[FRONT_RIGHT]; +#if 0 /* FIXME: Re-enable when proper 6-channel spatialization is used */ WetBuffer[j][SIDE_LEFT] += value*WetSend[SIDE_LEFT]; WetBuffer[j][SIDE_RIGHT] += value*WetSend[SIDE_RIGHT]; +#endif WetBuffer[j][BACK_LEFT] += value*WetSend[BACK_LEFT]; WetBuffer[j][BACK_RIGHT] += value*WetSend[BACK_RIGHT]; } From cb1d62f254a26f0bb1af545df9966312b08e1161 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Mon, 31 Dec 2007 04:50:34 -0800 Subject: [PATCH 29/33] Add paths for 4 to 7.1 channel buffer mixing --- Alc/ALu.c | 53 +++++++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 45 insertions(+), 8 deletions(-) diff --git a/Alc/ALu.c b/Alc/ALu.c index d62dd1b4..c35b050f 100644 --- a/Alc/ALu.c +++ b/Alc/ALu.c @@ -596,18 +596,55 @@ ALvoid aluMixData(ALCcontext *ALContext,ALvoid *buffer,ALsizei size,ALenum forma } else { - //First order interpolator (left) - value = (ALfloat)((ALshort)(((Data[k*2 ]*((1L<>FRACTIONBITS)); - //Direct path final mix buffer and panning (left) + //First order interpolator (front left) + value = (ALfloat)((ALshort)(((Data[k*Channels ]*((1L<>FRACTIONBITS)); DryBuffer[j][FRONT_LEFT] += value*DrySend[FRONT_LEFT]; - //Room path final mix buffer and panning (left) WetBuffer[j][FRONT_LEFT] += value*WetSend[FRONT_LEFT]; - //First order interpolator (right) - value = (ALfloat)((ALshort)(((Data[k*2+1]*((1L<>FRACTIONBITS)); - //Direct path final mix buffer and panning (right) + //First order interpolator (front right) + value = (ALfloat)((ALshort)(((Data[k*Channels+1]*((1L<>FRACTIONBITS)); DryBuffer[j][FRONT_RIGHT] += value*DrySend[FRONT_RIGHT]; - //Room path final mix buffer and panning (right) WetBuffer[j][FRONT_RIGHT] += value*WetSend[FRONT_RIGHT]; + if(Channels >= 4) + { + int i = 2; + if(Channels >= 7) + { + //First order interpolator (side left) + value = (ALfloat)((ALshort)(((Data[k*Channels+2]*((1L<>FRACTIONBITS)); + DryBuffer[j][SIDE_LEFT] += value*DrySend[SIDE_LEFT]; + WetBuffer[j][SIDE_LEFT] += value*WetSend[SIDE_LEFT]; + //First order interpolator (side right) + value = (ALfloat)((ALshort)(((Data[k*Channels+3]*((1L<>FRACTIONBITS)); + DryBuffer[j][SIDE_RIGHT] += value*DrySend[SIDE_RIGHT]; + WetBuffer[j][SIDE_RIGHT] += value*WetSend[SIDE_RIGHT]; + i += 2; + } + //First order interpolator (back left) + value = (ALfloat)((ALshort)(((Data[k*Channels+i]*((1L<>FRACTIONBITS)); + DryBuffer[j][BACK_LEFT] += value*DrySend[BACK_LEFT]; + WetBuffer[j][BACK_LEFT] += value*WetSend[BACK_LEFT]; + i++; + //First order interpolator (back right) + value = (ALfloat)((ALshort)(((Data[k*Channels+i]*((1L<>FRACTIONBITS)); + DryBuffer[j][BACK_RIGHT] += value*DrySend[BACK_RIGHT]; + WetBuffer[j][BACK_RIGHT] += value*WetSend[BACK_RIGHT]; + i++; + if(Channels >= 6) + { + if(Channels != 7) + { + //First order interpolator (center) + value = (ALfloat)((ALshort)(((Data[k*Channels+i]*((1L<>FRACTIONBITS)); + DryBuffer[j][CENTER] += value*DrySend[CENTER]; + WetBuffer[j][CENTER] += value*WetSend[CENTER]; + i++; + } + //First order interpolator (lfe) + value = (ALfloat)((ALshort)(((Data[k*Channels+i]*((1L<>FRACTIONBITS)); + DryBuffer[j][LFE] += value*DrySend[LFE]; + WetBuffer[j][LFE] += value*WetSend[LFE]; + } + } } DataPosFrac += increment; j++; From c9a539eade6b5930bd2995b6226f5982d189190b Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Mon, 31 Dec 2007 05:06:59 -0800 Subject: [PATCH 30/33] Allow loading of 4, 5.1, 6.1, and 7.1 sample data --- OpenAL32/alBuffer.c | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/OpenAL32/alBuffer.c b/OpenAL32/alBuffer.c index 13b98b21..c881e1e4 100644 --- a/OpenAL32/alBuffer.c +++ b/OpenAL32/alBuffer.c @@ -287,6 +287,30 @@ ALAPI ALvoid ALAPIENTRY alBufferData(ALuint buffer,ALenum format,const ALvoid *d LoadData(ALBuf, data, size, freq, format, AL_FORMAT_STEREO16); break; + case AL_FORMAT_QUAD8: + case AL_FORMAT_QUAD16: + case AL_FORMAT_QUAD32: + LoadData(ALBuf, data, size, freq, format, AL_FORMAT_QUAD16); + break; + + case AL_FORMAT_51CHN8: + case AL_FORMAT_51CHN16: + case AL_FORMAT_51CHN32: + LoadData(ALBuf, data, size, freq, format, AL_FORMAT_51CHN16); + break; + + case AL_FORMAT_61CHN8: + case AL_FORMAT_61CHN16: + case AL_FORMAT_61CHN32: + LoadData(ALBuf, data, size, freq, format, AL_FORMAT_61CHN16); + break; + + case AL_FORMAT_71CHN8: + case AL_FORMAT_71CHN16: + case AL_FORMAT_71CHN32: + LoadData(ALBuf, data, size, freq, format, AL_FORMAT_71CHN16); + break; + case AL_FORMAT_MONO_IMA4: // Here is where things vary: // nVidia and Apple use 64+1 samples per block => block_size=36 bytes From 1397417fcd399663a91534c45b7863b2492af530 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Mon, 31 Dec 2007 05:46:20 -0800 Subject: [PATCH 31/33] Handle AL_FORMAT_REAR* formats --- OpenAL32/alBuffer.c | 104 ++++++++++++++++++++++++++++++++++++++++++++ OpenAL32/alSource.c | 18 ++++++++ 2 files changed, 122 insertions(+) diff --git a/OpenAL32/alBuffer.c b/OpenAL32/alBuffer.c index c881e1e4..2bcb6562 100644 --- a/OpenAL32/alBuffer.c +++ b/OpenAL32/alBuffer.c @@ -287,6 +287,110 @@ ALAPI ALvoid ALAPIENTRY alBufferData(ALuint buffer,ALenum format,const ALvoid *d LoadData(ALBuf, data, size, freq, format, AL_FORMAT_STEREO16); break; + case AL_FORMAT_REAR8: + case AL_FORMAT_REAR16: + case AL_FORMAT_REAR32: { + ALuint NewFormat = AL_FORMAT_QUAD16; + ALuint NewChannels = aluChannelsFromFormat(NewFormat); + ALuint OrigBytes = ((format==AL_FORMAT_REAR8) ? 1 : + ((format==AL_FORMAT_REAR16) ? 2 : + 4)); + ALsizei i; + + assert(aluBytesFromFormat(NewFormat) == 2); + + if ((size%(OrigBytes*2)) != 0) + { + alSetError(AL_INVALID_VALUE); + break; + } + + switch(OrigBytes) + { + case 1: + size /= sizeof(ALubyte); + size *= 2; + + // 8bit Samples are converted to 16 bit here + // Allocate 8 extra samples + ALBuf->data = realloc(ALBuf->data, (8*NewChannels + size) * (1*sizeof(ALshort))); + if (ALBuf->data) + { + for (i = 0;i < size;i+=4) + { + ALBuf->data[i+0] = 0; + ALBuf->data[i+1] = 0; + ALBuf->data[i+2] = (ALshort)((((ALubyte*)data)[i/2+0]-128) << 8); + ALBuf->data[i+3] = (ALshort)((((ALubyte*)data)[i/2+1]-128) << 8); + } + memset(&(ALBuf->data[size]), 0, 16*NewChannels); + + ALBuf->format = NewFormat; + ALBuf->eOriginalFormat = format; + ALBuf->size = size*1*sizeof(ALshort); + ALBuf->frequency = freq; + } + else + alSetError(AL_OUT_OF_MEMORY); + break; + + case 2: + size /= sizeof(ALshort); + size *= 2; + + // Allocate 8 extra samples + ALBuf->data = realloc(ALBuf->data, (8*NewChannels + size) * (1*sizeof(ALshort))); + if (ALBuf->data) + { + for (i = 0;i < size;i+=4) + { + ALBuf->data[i+0] = 0; + ALBuf->data[i+1] = 0; + ALBuf->data[i+2] = ((ALshort*)data)[i/2+0]; + ALBuf->data[i+3] = ((ALshort*)data)[i/2+1]; + } + memset(&(ALBuf->data[size]), 0, 16*NewChannels); + + ALBuf->format = NewFormat; + ALBuf->eOriginalFormat = format; + ALBuf->size = size*1*sizeof(ALshort); + ALBuf->frequency = freq; + } + else + alSetError(AL_OUT_OF_MEMORY); + break; + + case 4: + size /= sizeof(ALfloat); + size *= 2; + + // Allocate 8 extra samples + ALBuf->data = realloc(ALBuf->data, (8*NewChannels + size) * (1*sizeof(ALshort))); + if (ALBuf->data) + { + for (i = 0;i < size;i+=4) + { + ALBuf->data[i+0] = 0; + ALBuf->data[i+1] = 0; + ALBuf->data[i+2] = (ALshort)(((ALfloat*)data)[i/2+0] * 32767.5f - 0.5); + ALBuf->data[i+3] = (ALshort)(((ALfloat*)data)[i/2+1] * 32767.5f - 0.5); + } + memset(&(ALBuf->data[size]), 0, 16*NewChannels); + + ALBuf->format = NewFormat; + ALBuf->eOriginalFormat = format; + ALBuf->size = size*1*sizeof(ALshort); + ALBuf->frequency = freq; + } + else + alSetError(AL_OUT_OF_MEMORY); + break; + + default: + assert(0); + } + } break; + case AL_FORMAT_QUAD8: case AL_FORMAT_QUAD16: case AL_FORMAT_QUAD32: diff --git a/OpenAL32/alSource.c b/OpenAL32/alSource.c index 9b4909c5..7fad9b90 100644 --- a/OpenAL32/alSource.c +++ b/OpenAL32/alSource.c @@ -1916,6 +1916,14 @@ static ALboolean GetSourceOffset(ALsource *pSource, ALenum eName, ALfloat *pflOf // Round down to nearest ADPCM block *pflOffset = (ALfloat)((lBytesPlayed / (36 * lChannels)) * 36 * lChannels); } + else if (eOriginalFormat == AL_FORMAT_REAR8) + { + *pflOffset = (ALfloat)(lBytesPlayed >> 2); + } + else if (eOriginalFormat == AL_FORMAT_REAR16) + { + *pflOffset = (ALfloat)(lBytesPlayed >> 1); + } else if (aluBytesFromFormat(eOriginalFormat) == 1) { *pflOffset = (ALfloat)(lBytesPlayed >> 1); @@ -2071,6 +2079,16 @@ static ALint GetByteOffset(ALsource *pSource) lByteOffset = (ALint)(3.6111f * (ALfloat)lByteOffset); lByteOffset -= (lByteOffset % (lChannels * 2)); } + else if (pBuffer->eOriginalFormat == AL_FORMAT_REAR8) + { + lByteOffset = pSource->lOffset * 4; + lByteOffset -= (lByteOffset % (lChannels * 2)); + } + else if (pBuffer->eOriginalFormat == AL_FORMAT_REAR16) + { + lByteOffset = pSource->lOffset * 2; + lByteOffset -= (lByteOffset % (lChannels * 2)); + } else if (aluBytesFromFormat(pBuffer->eOriginalFormat) == 1) { lByteOffset = pSource->lOffset * 2; From 42027a3f948170ef4c3425512c32806d0e58a388 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Mon, 31 Dec 2007 05:52:22 -0800 Subject: [PATCH 32/33] Advertise the AL_EXT_MCFORMATS extension --- Alc/ALc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Alc/ALc.c b/Alc/ALc.c index 376a3ce8..9bd4086d 100644 --- a/Alc/ALc.c +++ b/Alc/ALc.c @@ -360,7 +360,7 @@ static ALvoid InitContext(ALCcontext *pContext) pContext->lNumStereoSources = 1; pContext->lNumMonoSources = pContext->Device->MaxNoOfSources - pContext->lNumStereoSources; - strcpy(pContext->ExtensionList, "AL_EXT_EXPONENT_DISTANCE AL_EXT_FLOAT32 AL_EXT_IMA4 AL_EXT_LINEAR_DISTANCE AL_EXT_OFFSET"); + strcpy(pContext->ExtensionList, "AL_EXT_EXPONENT_DISTANCE AL_EXT_FLOAT32 AL_EXT_IMA4 AL_EXT_LINEAR_DISTANCE AL_EXT_MCFORMATS AL_EXT_OFFSET"); } From 9382956b0ec459a696805a23656a9e94b6ed94d9 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Mon, 31 Dec 2007 06:00:50 -0800 Subject: [PATCH 33/33] Remove obsolete comment --- OpenAL32/Include/alMain.h | 2 -- 1 file changed, 2 deletions(-) diff --git a/OpenAL32/Include/alMain.h b/OpenAL32/Include/alMain.h index 08f0a9ff..3449b57e 100644 --- a/OpenAL32/Include/alMain.h +++ b/OpenAL32/Include/alMain.h @@ -86,8 +86,6 @@ extern char _alDebug[256]; #define AL_FORMAT_MONO_IMA4 0x1300 #define AL_FORMAT_STEREO_IMA4 0x1301 -// These are from AL_EXT_MCFORMATS, which we don't support yet but the mixer -// can use some of the extra formats #define AL_FORMAT_51CHN8 0x120A #define AL_FORMAT_51CHN16 0x120B #define AL_FORMAT_51CHN32 0x120C