Compare commits
55 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| f8acdc9497 | |||
| 90d825e7f8 | |||
| 1178e900eb | |||
| 298f6f440a | |||
| 8553fb9e30 | |||
| da3b270488 | |||
| dd60366aec | |||
| 017fc93307 | |||
| 042ec206e7 | |||
| b3badbf97d | |||
| 4d5885e27b | |||
| 8fe39042da | |||
| 7ef623c71d | |||
| 733cd120b3 | |||
| 9382956b0e | |||
| 42027a3f94 | |||
| 1397417fcd | |||
| c9a539eade | |||
| cb1d62f254 | |||
| 1cbd625b4e | |||
| 73678f3b78 | |||
| 79b95da0a3 | |||
| 1c85273662 | |||
| 76dd568971 | |||
| a43868c32b | |||
| 7a99b1fa32 | |||
| e82c27ab04 | |||
| f32098e04d | |||
| 1e0fa58d79 | |||
| f7ef5c169b | |||
| 927763902f | |||
| fcff17c567 | |||
| 2e88a3d03b | |||
| 1061108c61 | |||
| 5f8e65e099 | |||
| d90b36cf11 | |||
| 87615fffc9 | |||
| 8343a98ec6 | |||
| d7bf7a8b0d | |||
| 9eed1e8609 | |||
| 8011ad97b5 | |||
| ab8d342df0 | |||
| dcac0de44c | |||
| 2ee389044b | |||
| a48201ed94 | |||
| e516b3c0d3 | |||
| 51c5fa94aa | |||
| 5b0514a829 | |||
| 0bef94cb48 | |||
| 44df5c3567 | |||
| d14ea2965d | |||
| e773887b4b | |||
| 5b85067f9c | |||
| 1fa1edf16b | |||
| 19156ab895 |
@@ -29,11 +29,15 @@
|
||||
#include "alMain.h"
|
||||
#include "AL/al.h"
|
||||
#include "AL/alc.h"
|
||||
#include "alThunk.h"
|
||||
#include "alSource.h"
|
||||
#include "alExtension.h"
|
||||
#include "bs2b.h"
|
||||
|
||||
///////////////////////////////////////////////////////
|
||||
// DEBUG INFORMATION
|
||||
|
||||
char szDebug[256];
|
||||
char _alDebug[256];
|
||||
|
||||
///////////////////////////////////////////////////////
|
||||
|
||||
@@ -193,7 +197,7 @@ static void InitAL(void)
|
||||
int i;
|
||||
const char *devs;
|
||||
|
||||
InitializeCriticalSection(&g_mutex);
|
||||
InitializeCriticalSection(&_alMutex);
|
||||
ALTHUNK_INIT();
|
||||
ReadALConfig();
|
||||
|
||||
@@ -303,7 +307,7 @@ ALCvoid SetALCError(ALenum errorCode)
|
||||
ALCvoid SuspendContext(ALCcontext *pContext)
|
||||
{
|
||||
(void)pContext;
|
||||
EnterCriticalSection(&g_mutex);
|
||||
EnterCriticalSection(&_alMutex);
|
||||
}
|
||||
|
||||
|
||||
@@ -315,7 +319,7 @@ ALCvoid SuspendContext(ALCcontext *pContext)
|
||||
ALCvoid ProcessContext(ALCcontext *pContext)
|
||||
{
|
||||
(void)pContext;
|
||||
LeaveCriticalSection(&g_mutex);
|
||||
LeaveCriticalSection(&_alMutex);
|
||||
}
|
||||
|
||||
|
||||
@@ -326,6 +330,8 @@ ALCvoid ProcessContext(ALCcontext *pContext)
|
||||
*/
|
||||
static ALvoid InitContext(ALCcontext *pContext)
|
||||
{
|
||||
int level;
|
||||
|
||||
//Initialise listener
|
||||
pContext->Listener.Gain = 1.0f;
|
||||
pContext->Listener.Position[0] = 0.0f;
|
||||
@@ -357,7 +363,15 @@ 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_FLOAT32 AL_EXT_IMA4 AL_EXT_LINEAR_DISTANCE AL_EXT_MCFORMATS AL_EXT_OFFSET");
|
||||
|
||||
level = GetConfigValueInt(NULL, "cf_level", 0);
|
||||
if(level > 0 && level <= 6)
|
||||
{
|
||||
pContext->bs2b = calloc(1, sizeof(*pContext->bs2b));
|
||||
bs2b_set_srate(pContext->bs2b, pContext->Frequency);
|
||||
bs2b_set_level(pContext->bs2b, level);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -391,6 +405,9 @@ static ALCvoid ExitContext(ALCcontext *pContext)
|
||||
//Invalidate context
|
||||
pContext->LastError = AL_NO_ERROR;
|
||||
pContext->InUse = AL_FALSE;
|
||||
|
||||
free(pContext->bs2b);
|
||||
pContext->bs2b = NULL;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////
|
||||
@@ -409,6 +426,9 @@ ALCAPI ALCdevice* ALCAPIENTRY alcCaptureOpenDevice(const ALCchar *deviceName, AL
|
||||
|
||||
InitAL();
|
||||
|
||||
if(deviceName && !deviceName[0])
|
||||
deviceName = NULL;
|
||||
|
||||
pDevice = malloc(sizeof(ALCdevice));
|
||||
if (pDevice)
|
||||
{
|
||||
@@ -687,7 +707,7 @@ ALCAPI ALCvoid ALCAPIENTRY alcGetIntegerv(ALCdevice *device,ALCenum param,ALsize
|
||||
data[i++] = device->Frequency;
|
||||
|
||||
data[i++] = ALC_REFRESH;
|
||||
data[i++] = device->UpdateFreq;
|
||||
data[i++] = device->Frequency / device->UpdateFreq;
|
||||
|
||||
data[i++] = ALC_SYNC;
|
||||
data[i++] = ALC_FALSE;
|
||||
@@ -722,7 +742,7 @@ ALCAPI ALCvoid ALCAPIENTRY alcGetIntegerv(ALCdevice *device,ALCenum param,ALsize
|
||||
else if(!size)
|
||||
SetALCError(ALC_INVALID_VALUE);
|
||||
else
|
||||
*data = device->UpdateFreq;
|
||||
*data = device->Frequency / device->UpdateFreq;
|
||||
break;
|
||||
|
||||
case ALC_SYNC:
|
||||
@@ -1034,6 +1054,9 @@ ALCAPI ALCdevice* ALCAPIENTRY alcOpenDevice(const ALCchar *deviceName)
|
||||
|
||||
InitAL();
|
||||
|
||||
if(deviceName && !deviceName[0])
|
||||
deviceName = NULL;
|
||||
|
||||
device = malloc(sizeof(ALCdevice));
|
||||
if (device)
|
||||
{
|
||||
|
||||
@@ -26,6 +26,11 @@
|
||||
#include "alMain.h"
|
||||
#include "AL/al.h"
|
||||
#include "AL/alc.h"
|
||||
#include "alSource.h"
|
||||
#include "alBuffer.h"
|
||||
#include "alThunk.h"
|
||||
#include "alListener.h"
|
||||
#include "bs2b.h"
|
||||
|
||||
#if defined(HAVE_STDINT_H)
|
||||
#include <stdint.h>
|
||||
@@ -52,6 +57,26 @@ typedef long long ALint64;
|
||||
#define __min min
|
||||
#endif
|
||||
|
||||
#define BUFFERSIZE 48000
|
||||
#define FRACTIONBITS 14
|
||||
#define FRACTIONMASK ((1L<<FRACTIONBITS)-1)
|
||||
#define MAX_PITCH 4
|
||||
|
||||
enum {
|
||||
FRONT_LEFT = 0,
|
||||
FRONT_RIGHT,
|
||||
SIDE_LEFT,
|
||||
SIDE_RIGHT,
|
||||
BACK_LEFT,
|
||||
BACK_RIGHT,
|
||||
CENTER,
|
||||
LFE,
|
||||
|
||||
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)
|
||||
@@ -59,13 +84,27 @@ __inline ALuint aluBytesFromFormat(ALenum format)
|
||||
case AL_FORMAT_MONO8:
|
||||
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:
|
||||
return 0;
|
||||
}
|
||||
@@ -77,16 +116,34 @@ __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:
|
||||
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;
|
||||
}
|
||||
@@ -94,12 +151,14 @@ __inline ALuint aluChannelsFromFormat(ALenum format)
|
||||
|
||||
static __inline ALint aluF2L(ALfloat Value)
|
||||
{
|
||||
#if 0
|
||||
if(sizeof(ALint) == 4 && sizeof(double) == 8)
|
||||
{
|
||||
double temp;
|
||||
temp = Value + (((65536.0*65536.0*16.0)+(65536.0*65536.0*8.0))*65536.0);
|
||||
return *((ALint*)&temp);
|
||||
}
|
||||
#endif
|
||||
return (ALint)Value;
|
||||
}
|
||||
|
||||
@@ -319,47 +378,80 @@ static ALvoid CalcSourceParams(ALCcontext *ALContext, ALsource *ALSource,
|
||||
Matrix[2][0] = U[2]; Matrix[2][1] = V[2]; Matrix[2][2] = -N[2];
|
||||
aluMatrixVector(Position, Matrix);
|
||||
|
||||
//6. Convert normalized position into left/right front/back pannings
|
||||
if(Distance != 0.0f)
|
||||
//6. Convert normalized position into pannings, then into channel volumes
|
||||
aluNormalize(Position);
|
||||
switch(aluChannelsFromFormat(OutputFormat))
|
||||
{
|
||||
aluNormalize(Position);
|
||||
PanningLR = 0.5f + 0.5f*Position[0];
|
||||
PanningFB = 0.5f + 0.5f*Position[2];
|
||||
}
|
||||
else
|
||||
{
|
||||
PanningLR = 0.5f;
|
||||
PanningFB = 0.5f;
|
||||
}
|
||||
|
||||
//7. Convert pannings into channel volumes
|
||||
switch(OutputFormat)
|
||||
{
|
||||
case AL_FORMAT_MONO8:
|
||||
case AL_FORMAT_MONO16:
|
||||
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
|
||||
case 1:
|
||||
drysend[FRONT_LEFT] = ConeVolume * ListenerGain * DryMix * aluSqrt(1.0f); //Direct
|
||||
drysend[FRONT_RIGHT] = ConeVolume * ListenerGain * DryMix * aluSqrt(1.0f); //Direct
|
||||
wetsend[FRONT_LEFT] = ListenerGain * WetMix * aluSqrt(1.0f); //Room
|
||||
wetsend[FRONT_RIGHT] = ListenerGain * WetMix * aluSqrt(1.0f); //Room
|
||||
break;
|
||||
case AL_FORMAT_STEREO8:
|
||||
case AL_FORMAT_STEREO16:
|
||||
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
|
||||
case 2:
|
||||
PanningLR = 0.5f + 0.5f*Position[0];
|
||||
drysend[FRONT_LEFT] = ConeVolume * ListenerGain * DryMix * aluSqrt(1.0f-PanningLR);
|
||||
drysend[FRONT_RIGHT] = ConeVolume * ListenerGain * DryMix * aluSqrt( PanningLR);
|
||||
wetsend[FRONT_LEFT] = ListenerGain * WetMix * aluSqrt(1.0f-PanningLR);
|
||||
wetsend[FRONT_RIGHT] = ListenerGain * WetMix * aluSqrt( PanningLR);
|
||||
break;
|
||||
case AL_FORMAT_QUAD8:
|
||||
case AL_FORMAT_QUAD16:
|
||||
drysend[0] = ConeVolume * ListenerGain * DryMix * aluSqrt((1.0f-PanningLR)*(1.0f-PanningFB)); //FL Direct
|
||||
drysend[1] = ConeVolume * ListenerGain * DryMix * aluSqrt(( PanningLR)*(1.0f-PanningFB)); //FR Direct
|
||||
drysend[2] = ConeVolume * ListenerGain * DryMix * aluSqrt((1.0f-PanningLR)*( PanningFB)); //BL Direct
|
||||
drysend[3] = ConeVolume * ListenerGain * DryMix * aluSqrt(( PanningLR)*( PanningFB)); //BR Direct
|
||||
wetsend[0] = ListenerGain * WetMix * aluSqrt((1.0f-PanningLR)*(1.0f-PanningFB)); //FL Room
|
||||
wetsend[1] = ListenerGain * WetMix * aluSqrt(( PanningLR)*(1.0f-PanningFB)); //FR Room
|
||||
wetsend[2] = ListenerGain * WetMix * aluSqrt((1.0f-PanningLR)*( PanningFB)); //BL Room
|
||||
wetsend[3] = ListenerGain * WetMix * aluSqrt(( PanningLR)*( PanningFB)); //BR Room
|
||||
case 4:
|
||||
/* TODO: Add center/lfe channel in spatial calculations? */
|
||||
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);
|
||||
PanningLR = __max(0.0f, PanningLR);
|
||||
PanningFB = 0.5f + (0.5f*Position[2]*1.41421356f);
|
||||
PanningFB = __min(1.0f, PanningFB);
|
||||
PanningFB = __max(0.0f, PanningFB);
|
||||
drysend[FRONT_LEFT] = ConeVolume * ListenerGain * DryMix * aluSqrt((1.0f-PanningLR)*(1.0f-PanningFB));
|
||||
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));
|
||||
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));
|
||||
break;
|
||||
case 7:
|
||||
case 8:
|
||||
PanningFB = 1.0f - fabs(Position[2]*1.15470054f);
|
||||
PanningFB = __min(1.0f, PanningFB);
|
||||
PanningFB = __max(0.0f, PanningFB);
|
||||
PanningLR = 0.5f + (0.5*Position[0]*((1.0f-PanningFB)*2.0f));
|
||||
PanningLR = __min(1.0f, PanningLR);
|
||||
PanningLR = __max(0.0f, PanningLR);
|
||||
if(Position[2] > 0.0f)
|
||||
{
|
||||
drysend[BACK_LEFT] = ConeVolume * ListenerGain * DryMix * aluSqrt((1.0f-PanningLR)*(1.0f-PanningFB));
|
||||
drysend[BACK_RIGHT] = ConeVolume * ListenerGain * DryMix * aluSqrt(( PanningLR)*(1.0f-PanningFB));
|
||||
drysend[SIDE_LEFT] = ConeVolume * ListenerGain * DryMix * aluSqrt((1.0f-PanningLR)*( PanningFB));
|
||||
drysend[SIDE_RIGHT] = ConeVolume * ListenerGain * DryMix * aluSqrt(( PanningLR)*( PanningFB));
|
||||
drysend[FRONT_LEFT] = 0.0f;
|
||||
drysend[FRONT_RIGHT] = 0.0f;
|
||||
wetsend[BACK_LEFT] = ListenerGain * WetMix * aluSqrt((1.0f-PanningLR)*(1.0f-PanningFB));
|
||||
wetsend[BACK_RIGHT] = ListenerGain * WetMix * aluSqrt(( PanningLR)*(1.0f-PanningFB));
|
||||
wetsend[SIDE_LEFT] = ListenerGain * WetMix * aluSqrt((1.0f-PanningLR)*( PanningFB));
|
||||
wetsend[SIDE_RIGHT] = ListenerGain * WetMix * aluSqrt(( PanningLR)*( PanningFB));
|
||||
wetsend[FRONT_LEFT] = 0.0f;
|
||||
wetsend[FRONT_RIGHT] = 0.0f;
|
||||
}
|
||||
else
|
||||
{
|
||||
drysend[FRONT_LEFT] = ConeVolume * ListenerGain * DryMix * aluSqrt((1.0f-PanningLR)*(1.0f-PanningFB));
|
||||
drysend[FRONT_RIGHT] = ConeVolume * ListenerGain * DryMix * aluSqrt(( PanningLR)*(1.0f-PanningFB));
|
||||
drysend[SIDE_LEFT] = ConeVolume * ListenerGain * DryMix * aluSqrt((1.0f-PanningLR)*( PanningFB));
|
||||
drysend[SIDE_RIGHT] = ConeVolume * ListenerGain * DryMix * aluSqrt(( PanningLR)*( PanningFB));
|
||||
drysend[BACK_LEFT] = 0.0f;
|
||||
drysend[BACK_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[SIDE_LEFT] = ListenerGain * WetMix * aluSqrt((1.0f-PanningLR)*( PanningFB));
|
||||
wetsend[SIDE_RIGHT] = ListenerGain * WetMix * aluSqrt(( PanningLR)*( PanningFB));
|
||||
wetsend[BACK_LEFT] = 0.0f;
|
||||
wetsend[BACK_RIGHT] = 0.0f;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@@ -367,14 +459,22 @@ static ALvoid CalcSourceParams(ALCcontext *ALContext, ALsource *ALSource,
|
||||
else
|
||||
{
|
||||
//1. Multi-channel buffers always play "normal"
|
||||
drysend[0] = SourceVolume * 1.0f * ListenerGain;
|
||||
drysend[1] = SourceVolume * 1.0f * ListenerGain;
|
||||
drysend[2] = SourceVolume * 1.0f * ListenerGain;
|
||||
drysend[3] = 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;
|
||||
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;
|
||||
wetsend[LFE] = SourceVolume * 0.0f * ListenerGain;
|
||||
|
||||
pitch[0] = Pitch;
|
||||
}
|
||||
@@ -384,8 +484,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, 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;
|
||||
@@ -510,30 +610,73 @@ ALvoid aluMixData(ALCcontext *ALContext,ALvoid *buffer,ALsizei size,ALenum forma
|
||||
//First order interpolator
|
||||
value = (ALfloat)((ALshort)(((Data[k]*((1L<<FRACTIONBITS)-fraction))+(Data[k+1]*(fraction)))>>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][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][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][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];
|
||||
}
|
||||
else
|
||||
{
|
||||
//First order interpolator (left)
|
||||
value = (ALfloat)((ALshort)(((Data[k*2 ]*((1L<<FRACTIONBITS)-fraction))+(Data[k*2+2]*(fraction)))>>FRACTIONBITS));
|
||||
//Direct path final mix buffer and panning (left)
|
||||
DryBuffer[j][0] += value*DrySend[0];
|
||||
//Room path final mix buffer and panning (left)
|
||||
WetBuffer[j][0] += value*WetSend[0];
|
||||
//First order interpolator (right)
|
||||
value = (ALfloat)((ALshort)(((Data[k*2+1]*((1L<<FRACTIONBITS)-fraction))+(Data[k*2+3]*(fraction)))>>FRACTIONBITS));
|
||||
//Direct path final mix buffer and panning (right)
|
||||
DryBuffer[j][1] += value*DrySend[1];
|
||||
//Room path final mix buffer and panning (right)
|
||||
WetBuffer[j][1] += value*WetSend[1];
|
||||
//First order interpolator (front left)
|
||||
value = (ALfloat)((ALshort)(((Data[k*Channels ]*((1L<<FRACTIONBITS)-fraction))+(Data[(k+1)*Channels ]*(fraction)))>>FRACTIONBITS));
|
||||
DryBuffer[j][FRONT_LEFT] += value*DrySend[FRONT_LEFT];
|
||||
WetBuffer[j][FRONT_LEFT] += value*WetSend[FRONT_LEFT];
|
||||
//First order interpolator (front right)
|
||||
value = (ALfloat)((ALshort)(((Data[k*Channels+1]*((1L<<FRACTIONBITS)-fraction))+(Data[(k+1)*Channels+1]*(fraction)))>>FRACTIONBITS));
|
||||
DryBuffer[j][FRONT_RIGHT] += value*DrySend[FRONT_RIGHT];
|
||||
WetBuffer[j][FRONT_RIGHT] += value*WetSend[FRONT_RIGHT];
|
||||
if(Channels >= 4)
|
||||
{
|
||||
int i = 2;
|
||||
if(Channels >= 6)
|
||||
{
|
||||
if(Channels != 7)
|
||||
{
|
||||
//First order interpolator (center)
|
||||
value = (ALfloat)((ALshort)(((Data[k*Channels+i]*((1L<<FRACTIONBITS)-fraction))+(Data[(k+1)*Channels+i]*(fraction)))>>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)-fraction))+(Data[(k+1)*Channels+i]*(fraction)))>>FRACTIONBITS));
|
||||
DryBuffer[j][LFE] += value*DrySend[LFE];
|
||||
WetBuffer[j][LFE] += value*WetSend[LFE];
|
||||
i++;
|
||||
}
|
||||
//First order interpolator (back left)
|
||||
value = (ALfloat)((ALshort)(((Data[k*Channels+i]*((1L<<FRACTIONBITS)-fraction))+(Data[(k+1)*Channels+i]*(fraction)))>>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)-fraction))+(Data[(k+1)*Channels+i]*(fraction)))>>FRACTIONBITS));
|
||||
DryBuffer[j][BACK_RIGHT] += value*DrySend[BACK_RIGHT];
|
||||
WetBuffer[j][BACK_RIGHT] += value*WetSend[BACK_RIGHT];
|
||||
i++;
|
||||
if(Channels >= 7)
|
||||
{
|
||||
//First order interpolator (side left)
|
||||
value = (ALfloat)((ALshort)(((Data[k*Channels+i]*((1L<<FRACTIONBITS)-fraction))+(Data[(k+1)*Channels+i]*(fraction)))>>FRACTIONBITS));
|
||||
DryBuffer[j][SIDE_LEFT] += value*DrySend[SIDE_LEFT];
|
||||
WetBuffer[j][SIDE_LEFT] += value*WetSend[SIDE_LEFT];
|
||||
i++;
|
||||
//First order interpolator (side right)
|
||||
value = (ALfloat)((ALshort)(((Data[k*Channels+i]*((1L<<FRACTIONBITS)-fraction))+(Data[(k+1)*Channels+i]*(fraction)))>>FRACTIONBITS));
|
||||
DryBuffer[j][SIDE_RIGHT] += value*DrySend[SIDE_RIGHT];
|
||||
WetBuffer[j][SIDE_RIGHT] += value*WetSend[SIDE_RIGHT];
|
||||
i++;
|
||||
}
|
||||
}
|
||||
}
|
||||
DataPosFrac += increment;
|
||||
j++;
|
||||
@@ -627,46 +770,169 @@ 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][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*2;i++)
|
||||
if(ALContext->bs2b)
|
||||
{
|
||||
*((ALubyte*)buffer) = (ALubyte)((aluF2S(DryBuffer[i>>1][i&1]+WetBuffer[i>>1][i&1])>>8)+128);
|
||||
buffer = ((ALubyte*)buffer) + 1;
|
||||
for(i = 0;i < SamplesToDo;i++)
|
||||
{
|
||||
float samples[2];
|
||||
samples[0] = DryBuffer[i][FRONT_LEFT] +WetBuffer[i][FRONT_LEFT];
|
||||
samples[1] = DryBuffer[i][FRONT_RIGHT]+WetBuffer[i][FRONT_RIGHT];
|
||||
bs2b_cross_feed(ALContext->bs2b, samples);
|
||||
((ALubyte*)buffer)[0] = (ALubyte)((aluF2S(samples[0])>>8)+128);
|
||||
((ALubyte*)buffer)[1] = (ALubyte)((aluF2S(samples[1])>>8)+128);
|
||||
buffer = ((ALubyte*)buffer) + 2;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
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);
|
||||
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][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][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_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++)
|
||||
{
|
||||
*((ALshort*)buffer) = 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:
|
||||
default:
|
||||
for(i = 0;i < SamplesToDo*2;i++)
|
||||
if(ALContext->bs2b)
|
||||
{
|
||||
*((ALshort*)buffer) = aluF2S(DryBuffer[i>>1][i&1]+WetBuffer[i>>1][i&1]);
|
||||
buffer = ((ALshort*)buffer) + 1;
|
||||
for(i = 0;i < SamplesToDo;i++)
|
||||
{
|
||||
float samples[2];
|
||||
samples[0] = DryBuffer[i][FRONT_LEFT] +WetBuffer[i][FRONT_LEFT];
|
||||
samples[1] = DryBuffer[i][FRONT_RIGHT]+WetBuffer[i][FRONT_RIGHT];
|
||||
bs2b_cross_feed(ALContext->bs2b, samples);
|
||||
((ALshort*)buffer)[0] = aluF2S(samples[0]);
|
||||
((ALshort*)buffer)[1] = aluF2S(samples[1]);
|
||||
buffer = ((ALshort*)buffer) + 2;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
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]);
|
||||
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][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][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;
|
||||
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;
|
||||
}
|
||||
|
||||
size -= SamplesToDo;
|
||||
|
||||
+118
@@ -0,0 +1,118 @@
|
||||
/**
|
||||
* OpenAL cross platform audio library
|
||||
* Copyright (C) 1999-2007 by authors.
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library 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
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
* Or go to http://www.gnu.org/copyleft/lgpl.html
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "alMain.h"
|
||||
|
||||
|
||||
struct RingBuffer {
|
||||
ALubyte *mem;
|
||||
|
||||
ALsizei frame_size;
|
||||
ALsizei length;
|
||||
ALint read_pos;
|
||||
ALint write_pos;
|
||||
|
||||
CRITICAL_SECTION cs;
|
||||
};
|
||||
|
||||
|
||||
RingBuffer *CreateRingBuffer(ALsizei frame_size, ALsizei length)
|
||||
{
|
||||
RingBuffer *ring = calloc(1, sizeof(*ring));
|
||||
if(ring)
|
||||
{
|
||||
ring->frame_size = frame_size;
|
||||
ring->length = length+1;
|
||||
ring->write_pos = 1;
|
||||
ring->mem = malloc((length+1)*frame_size);
|
||||
if(!ring->mem)
|
||||
{
|
||||
free(ring);
|
||||
ring = NULL;
|
||||
}
|
||||
|
||||
InitializeCriticalSection(&ring->cs);
|
||||
}
|
||||
return ring;
|
||||
}
|
||||
|
||||
void DestroyRingBuffer(RingBuffer *ring)
|
||||
{
|
||||
if(ring)
|
||||
{
|
||||
DeleteCriticalSection(&ring->cs);
|
||||
free(ring->mem);
|
||||
free(ring);
|
||||
}
|
||||
}
|
||||
|
||||
ALsizei RingBufferSize(RingBuffer *ring)
|
||||
{
|
||||
return (ring->write_pos-ring->read_pos-1+ring->length) % ring->length;
|
||||
}
|
||||
|
||||
void WriteRingBuffer(RingBuffer *ring, const ALubyte *data, ALsizei len)
|
||||
{
|
||||
int remain = ring->length - ring->write_pos;
|
||||
|
||||
EnterCriticalSection(&ring->cs);
|
||||
|
||||
if((ring->read_pos-ring->write_pos+ring->length)%ring->length < len)
|
||||
ring->read_pos = (ring->write_pos+len) % ring->length;
|
||||
|
||||
if(remain < len)
|
||||
{
|
||||
memcpy(ring->mem+(ring->write_pos*ring->frame_size), data, remain*ring->frame_size);
|
||||
memcpy(ring->mem, data+(remain*ring->frame_size), (len-remain)*ring->frame_size);
|
||||
}
|
||||
else
|
||||
memcpy(ring->mem+(ring->write_pos*ring->frame_size), data, len*ring->frame_size);
|
||||
|
||||
ring->write_pos += len;
|
||||
ring->write_pos %= ring->length;
|
||||
|
||||
LeaveCriticalSection(&ring->cs);
|
||||
}
|
||||
|
||||
void ReadRingBuffer(RingBuffer *ring, ALubyte *data, ALsizei len)
|
||||
{
|
||||
int remain = ring->length - ring->read_pos;
|
||||
|
||||
EnterCriticalSection(&ring->cs);
|
||||
|
||||
if(remain < len)
|
||||
{
|
||||
memcpy(data, ring->mem+(ring->read_pos*ring->frame_size), remain*ring->frame_size);
|
||||
memcpy(data+(remain*ring->frame_size), ring->mem, (len-remain)*ring->frame_size);
|
||||
}
|
||||
else
|
||||
memcpy(data, ring->mem+(ring->read_pos*ring->frame_size), len*ring->frame_size);
|
||||
|
||||
ring->read_pos += len;
|
||||
ring->read_pos %= ring->length;
|
||||
|
||||
LeaveCriticalSection(&ring->cs);
|
||||
}
|
||||
|
||||
+116
-26
@@ -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,55 @@ 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;
|
||||
|
||||
while(!data->killNow)
|
||||
{
|
||||
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,13 +318,14 @@ 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];
|
||||
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)
|
||||
{
|
||||
@@ -324,16 +380,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:
|
||||
@@ -344,14 +396,15 @@ open_alsa:
|
||||
periods = GetConfigValueInt("alsa", "periods", 4);
|
||||
if((int)periods <= 0)
|
||||
periods = 4;
|
||||
bufferSizeInFrames = device->UpdateFreq;
|
||||
bufferSizeInFrames = device->UpdateFreq / periods;
|
||||
|
||||
psnd_pcm_hw_params_malloc(&p);
|
||||
#define ok(func, str) (i=(func),((i<0)?(err=(str)),0:1))
|
||||
/* 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) */
|
||||
@@ -372,36 +425,68 @@ 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;
|
||||
device->UpdateFreq = bufferSizeInFrames;
|
||||
|
||||
i = psnd_pcm_prepare(data->pcmHandle);
|
||||
if(i < 0)
|
||||
data->size = psnd_pcm_frames_to_bytes(data->pcmHandle, device->UpdateFreq);
|
||||
if(access == SND_PCM_ACCESS_RW_INTERLEAVED)
|
||||
{
|
||||
AL_PRINT("prepare error: %s\n", psnd_strerror(i));
|
||||
psnd_pcm_close(data->pcmHandle);
|
||||
free(data);
|
||||
return ALC_FALSE;
|
||||
data->buffer = malloc(data->size);
|
||||
if(!data->buffer)
|
||||
{
|
||||
AL_PRINT("buffer malloc failed\n");
|
||||
psnd_pcm_close(data->pcmHandle);
|
||||
free(data);
|
||||
return ALC_FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
fill_silence(data->pcmHandle, data->format, device->Channels);
|
||||
i = psnd_pcm_start(data->pcmHandle);
|
||||
if(i < 0)
|
||||
else
|
||||
{
|
||||
AL_PRINT("start error: %s\n", psnd_strerror(i));
|
||||
psnd_pcm_close(data->pcmHandle);
|
||||
free(data);
|
||||
return ALC_FALSE;
|
||||
i = psnd_pcm_prepare(data->pcmHandle);
|
||||
if(i < 0)
|
||||
{
|
||||
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);
|
||||
|
||||
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;
|
||||
}
|
||||
@@ -416,6 +501,7 @@ static void alsa_close_playback(ALCdevice *device)
|
||||
StopThread(data->thread);
|
||||
psnd_pcm_close(data->pcmHandle);
|
||||
|
||||
free(data->buffer);
|
||||
free(data);
|
||||
device->ExtraData = NULL;
|
||||
}
|
||||
@@ -426,7 +512,7 @@ static ALCboolean alsa_open_capture(ALCdevice *pDevice, const ALCchar *deviceNam
|
||||
snd_pcm_format_t alsaFormat;
|
||||
snd_pcm_hw_params_t *p;
|
||||
unsigned int periods = 4;
|
||||
snd_pcm_uframes_t bufferSizeInFrames = SampleSize;
|
||||
snd_pcm_uframes_t bufferSizeInFrames;
|
||||
alsa_data *data;
|
||||
char driver[64];
|
||||
char *err;
|
||||
@@ -489,6 +575,8 @@ open_alsa:
|
||||
AL_PRINT("Unknown format?! %x\n", format);
|
||||
}
|
||||
|
||||
bufferSizeInFrames = SampleSize / periods;
|
||||
|
||||
psnd_pcm_hw_params_malloc(&p);
|
||||
#define ok(func, str) (i=(func),((i<0)?(err=(str)),0:1))
|
||||
/* start with the largest configuration space possible */
|
||||
@@ -690,6 +778,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);
|
||||
@@ -699,6 +788,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);
|
||||
|
||||
+201
@@ -0,0 +1,201 @@
|
||||
/*-
|
||||
* Copyright (c) 2005 Boris Mikhaylov
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <math.h>
|
||||
|
||||
#include "bs2b.h"
|
||||
|
||||
#ifndef M_PI
|
||||
#define M_PI 3.14159265358979323846
|
||||
#endif
|
||||
|
||||
/* Single pole IIR filter.
|
||||
* O[n] = a0*I[n] + a1*I[n-1] + b1*O[n-1]
|
||||
*/
|
||||
|
||||
/* Lowpass filter */
|
||||
#define lo_filter(in, out_1) (bs2b->a0_lo*(in) + bs2b->b1_lo*(out_1))
|
||||
|
||||
/* Highboost filter */
|
||||
#define hi_filter(in, in_1, out_1) (bs2b->a0_hi*(in) + bs2b->a1_hi*(in_1) + bs2b->b1_hi*(out_1))
|
||||
|
||||
/* Set up all data. */
|
||||
static void init(struct bs2b *bs2b)
|
||||
{
|
||||
double Fc_lo, Fc_hi;
|
||||
double G_lo, G_hi;
|
||||
double x;
|
||||
|
||||
if ((bs2b->srate > 192000) || (bs2b->srate < 2000))
|
||||
bs2b->srate = BS2B_DEFAULT_SRATE;
|
||||
|
||||
switch(bs2b->level)
|
||||
{
|
||||
case BS2B_LOW_CLEVEL: /* Low crossfeed level */
|
||||
Fc_lo = 360.0;
|
||||
Fc_hi = 501.0;
|
||||
G_lo = 0.398107170553497;
|
||||
G_hi = 0.205671765275719;
|
||||
break;
|
||||
|
||||
case BS2B_MIDDLE_CLEVEL: /* Middle crossfeed level */
|
||||
Fc_lo = 500.0;
|
||||
Fc_hi = 711.0;
|
||||
G_lo = 0.459726988530872;
|
||||
G_hi = 0.228208484414988;
|
||||
break;
|
||||
|
||||
case BS2B_HIGH_CLEVEL: /* High crossfeed level (virtual speakers are closer to itself) */
|
||||
Fc_lo = 700.0;
|
||||
Fc_hi = 1021.0;
|
||||
G_lo = 0.530884444230988;
|
||||
G_hi = 0.250105790667544;
|
||||
break;
|
||||
|
||||
case BS2B_LOW_ECLEVEL: /* Low easy crossfeed level */
|
||||
Fc_lo = 360.0;
|
||||
Fc_hi = 494.0;
|
||||
G_lo = 0.316227766016838;
|
||||
G_hi = 0.168236228897329;
|
||||
break;
|
||||
|
||||
case BS2B_MIDDLE_ECLEVEL: /* Middle easy crossfeed level */
|
||||
Fc_lo = 500.0;
|
||||
Fc_hi = 689.0;
|
||||
G_lo = 0.354813389233575;
|
||||
G_hi = 0.187169483835901;
|
||||
break;
|
||||
|
||||
default: /* High easy crossfeed level */
|
||||
bs2b->level = BS2B_HIGH_ECLEVEL;
|
||||
|
||||
Fc_lo = 700.0;
|
||||
Fc_hi = 975.0;
|
||||
G_lo = 0.398107170553497;
|
||||
G_hi = 0.205671765275719;
|
||||
break;
|
||||
} /* switch */
|
||||
|
||||
/* $fc = $Fc / $s;
|
||||
* $d = 1 / 2 / pi / $fc;
|
||||
* $x = exp(-1 / $d);
|
||||
*/
|
||||
|
||||
x = exp(-2.0 * M_PI * Fc_lo / bs2b->srate);
|
||||
bs2b->b1_lo = x;
|
||||
bs2b->a0_lo = G_lo * (1.0 - x);
|
||||
|
||||
x = exp(-2.0 * M_PI * Fc_hi / bs2b->srate);
|
||||
bs2b->b1_hi = x;
|
||||
bs2b->a0_hi = 1.0 - G_hi * (1.0 - x);
|
||||
bs2b->a1_hi = -x;
|
||||
|
||||
bs2b->gain = 1.0 / (1.0 - G_hi + G_lo);
|
||||
|
||||
bs2b_clear(bs2b);
|
||||
} /* init */
|
||||
|
||||
/* Exported functions.
|
||||
* See descriptions in "bs2b.h"
|
||||
*/
|
||||
|
||||
void bs2b_set_level(struct bs2b *bs2b, int level)
|
||||
{
|
||||
if(level == bs2b->level)
|
||||
return;
|
||||
bs2b->level = level;
|
||||
init(bs2b);
|
||||
} /* bs2b_set_level */
|
||||
|
||||
int bs2b_get_level(struct bs2b *bs2b)
|
||||
{
|
||||
return bs2b->level;
|
||||
} /* bs2b_get_level */
|
||||
|
||||
void bs2b_set_srate(struct bs2b *bs2b, int srate)
|
||||
{
|
||||
if (srate == bs2b->srate)
|
||||
return;
|
||||
bs2b->srate = srate;
|
||||
init(bs2b);
|
||||
} /* bs2b_set_srate */
|
||||
|
||||
int bs2b_get_srate(struct bs2b *bs2b)
|
||||
{
|
||||
return bs2b->srate;
|
||||
} /* bs2b_get_srate */
|
||||
|
||||
void bs2b_clear(struct bs2b *bs2b)
|
||||
{
|
||||
int loopv = sizeof(bs2b->last_sample);
|
||||
|
||||
while (loopv)
|
||||
{
|
||||
((char *)&bs2b->last_sample)[--loopv] = 0;
|
||||
}
|
||||
} /* bs2b_clear */
|
||||
|
||||
int bs2b_is_clear(struct bs2b *bs2b)
|
||||
{
|
||||
int loopv = sizeof(bs2b->last_sample);
|
||||
|
||||
while (loopv)
|
||||
{
|
||||
if (((char *)&bs2b->last_sample)[--loopv] != 0)
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
} /* bs2b_is_clear */
|
||||
|
||||
void bs2b_cross_feed(struct bs2b *bs2b, float *sample)
|
||||
{
|
||||
/* Lowpass filter */
|
||||
bs2b->last_sample.lo[0] = lo_filter(sample[0], bs2b->last_sample.lo[0]);
|
||||
bs2b->last_sample.lo[1] = lo_filter(sample[1], bs2b->last_sample.lo[1]);
|
||||
|
||||
/* Highboost filter */
|
||||
bs2b->last_sample.hi[0] = hi_filter(sample[0], bs2b->last_sample.asis[0], bs2b->last_sample.hi[0]);
|
||||
bs2b->last_sample.hi[1] = hi_filter(sample[1], bs2b->last_sample.asis[1], bs2b->last_sample.hi[1]);
|
||||
bs2b->last_sample.asis[0] = sample[0];
|
||||
bs2b->last_sample.asis[1] = sample[1];
|
||||
|
||||
/* Crossfeed */
|
||||
sample[0] = bs2b->last_sample.hi[0] + bs2b->last_sample.lo[1];
|
||||
sample[1] = bs2b->last_sample.hi[1] + bs2b->last_sample.lo[0];
|
||||
|
||||
/* Bass boost cause allpass attenuation */
|
||||
sample[0] *= bs2b->gain;
|
||||
sample[1] *= bs2b->gain;
|
||||
|
||||
/* Clipping of overloaded samples */
|
||||
#if 0
|
||||
if (sample[0] > 1.0)
|
||||
sample[0] = 1.0;
|
||||
if (sample[0] < -1.0)
|
||||
sample[0] = -1.0;
|
||||
if (sample[1] > 1.0)
|
||||
sample[1] = 1.0;
|
||||
if (sample[1] < -1.0)
|
||||
sample[1] = -1.0;
|
||||
#endif
|
||||
} /* bs2b_cross_feed */
|
||||
+3
-3
@@ -60,7 +60,7 @@ static void CALLBACK DirectSoundProc(UINT uID,UINT uReserved,DWORD_PTR dwUser,DW
|
||||
(void)dwReserved1;
|
||||
(void)dwReserved2;
|
||||
|
||||
BufSize = pDevice->UpdateFreq * pDevice->FrameSize;
|
||||
BufSize = pDevice->UpdateFreq * 2 * pDevice->FrameSize;
|
||||
|
||||
// Get current play and write cursors
|
||||
IDirectSoundBuffer_GetCurrentPosition(pData->DSsbuffer,&PlayCursor,&WriteCursor);
|
||||
@@ -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;
|
||||
@@ -169,7 +169,7 @@ static ALCboolean DSoundOpenPlayback(ALCdevice *device, const ALCchar *deviceNam
|
||||
memset(&DSBDescription,0,sizeof(DSBUFFERDESC));
|
||||
DSBDescription.dwSize=sizeof(DSBUFFERDESC);
|
||||
DSBDescription.dwFlags=DSBCAPS_GLOBALFOCUS|DSBCAPS_GETCURRENTPOSITION2;
|
||||
DSBDescription.dwBufferBytes=device->UpdateFreq * device->FrameSize;
|
||||
DSBDescription.dwBufferBytes=device->UpdateFreq * 2 * device->FrameSize;
|
||||
DSBDescription.lpwfxFormat=&OutputType;
|
||||
hr = IDirectSound_CreateSoundBuffer(pData->lpDS, &DSBDescription, &pData->DSsbuffer, NULL);
|
||||
}
|
||||
|
||||
@@ -46,6 +46,7 @@
|
||||
#endif
|
||||
|
||||
static char *oss_device;
|
||||
static char *oss_device_capture;
|
||||
|
||||
typedef struct {
|
||||
int fd;
|
||||
@@ -55,6 +56,9 @@ typedef struct {
|
||||
ALubyte *mix_data;
|
||||
int data_size;
|
||||
int silence;
|
||||
|
||||
RingBuffer *ring;
|
||||
int doCapture;
|
||||
} oss_data;
|
||||
|
||||
|
||||
@@ -74,31 +78,65 @@ static ALuint OSSProc(ALvoid *ptr)
|
||||
{
|
||||
ALCdevice *pDevice = (ALCdevice*)ptr;
|
||||
oss_data *data = (oss_data*)pDevice->ExtraData;
|
||||
int remaining;
|
||||
int remaining = 0;
|
||||
int wrote;
|
||||
|
||||
while(!data->killNow)
|
||||
{
|
||||
SuspendContext(NULL);
|
||||
aluMixData(pDevice->Context,data->mix_data,data->data_size,pDevice->Format);
|
||||
ProcessContext(NULL);
|
||||
int len = data->data_size - remaining;
|
||||
|
||||
remaining = data->data_size;
|
||||
while(remaining > 0)
|
||||
if(len > 0)
|
||||
{
|
||||
wrote = write(data->fd, data->mix_data+data->data_size-remaining, remaining);
|
||||
if(wrote < 0)
|
||||
{
|
||||
AL_PRINT("write failed: %s\n", strerror(errno));
|
||||
break;
|
||||
}
|
||||
if(wrote == 0)
|
||||
{
|
||||
usleep(1000);
|
||||
continue;
|
||||
}
|
||||
remaining -= wrote;
|
||||
SuspendContext(NULL);
|
||||
aluMixData(pDevice->Context, data->mix_data+remaining, len, pDevice->Format);
|
||||
ProcessContext(NULL);
|
||||
}
|
||||
|
||||
remaining += len;
|
||||
wrote = write(data->fd, data->mix_data, remaining);
|
||||
if(wrote < 0)
|
||||
{
|
||||
AL_PRINT("write failed: %s\n", strerror(errno));
|
||||
remaining = 0;
|
||||
}
|
||||
else if(wrote > 0)
|
||||
{
|
||||
remaining -= wrote;
|
||||
if(remaining > 0)
|
||||
memmove(data->mix_data, data->mix_data+wrote, remaining);
|
||||
}
|
||||
else
|
||||
usleep(1000);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static ALuint OSSCaptureProc(ALvoid *ptr)
|
||||
{
|
||||
ALCdevice *pDevice = (ALCdevice*)ptr;
|
||||
oss_data *data = (oss_data*)pDevice->ExtraData;
|
||||
int frameSize;
|
||||
int amt;
|
||||
|
||||
frameSize = aluBytesFromFormat(pDevice->Format);
|
||||
frameSize *= aluChannelsFromFormat(pDevice->Format);
|
||||
|
||||
while(!data->killNow)
|
||||
{
|
||||
amt = read(data->fd, data->mix_data, data->data_size);
|
||||
if(amt < 0)
|
||||
{
|
||||
AL_PRINT("read failed: %s\n", strerror(errno));
|
||||
break;
|
||||
}
|
||||
if(amt == 0)
|
||||
{
|
||||
usleep(1000);
|
||||
continue;
|
||||
}
|
||||
if(data->doCapture)
|
||||
WriteRingBuffer(data->ring, data->mix_data, amt/frameSize);
|
||||
}
|
||||
|
||||
return 0;
|
||||
@@ -140,17 +178,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;
|
||||
@@ -160,7 +194,7 @@ static ALCboolean oss_open_playback(ALCdevice *device, const ALCchar *deviceName
|
||||
}
|
||||
|
||||
periods = GetConfigValueInt("oss", "periods", 4);
|
||||
if((int)periods < 0)
|
||||
if((int)periods <= 0)
|
||||
periods = 4;
|
||||
numChannels = device->Channels;
|
||||
ossSpeed = device->Frequency;
|
||||
@@ -178,7 +212,135 @@ static ALCboolean oss_open_playback(ALCdevice *device, const ALCchar *deviceName
|
||||
ok(ioctl(data->fd, SNDCTL_DSP_SPEED, &ossSpeed), "set speed") &&
|
||||
ok(ioctl(data->fd, SNDCTL_DSP_GETOSPACE, &info), "get space")))
|
||||
{
|
||||
AL_PRINT("%s failed: %s\n", err, strerror(i));
|
||||
AL_PRINT("%s failed: %s\n", err, strerror(errno));
|
||||
close(data->fd);
|
||||
free(data);
|
||||
return ALC_FALSE;
|
||||
}
|
||||
#undef ok
|
||||
|
||||
device->Frequency = ossSpeed;
|
||||
|
||||
if((int)device->Channels != numChannels)
|
||||
{
|
||||
AL_PRINT("Could not set %d channels, got %d instead\n", device->Channels, numChannels);
|
||||
close(data->fd);
|
||||
free(data);
|
||||
return ALC_FALSE;
|
||||
}
|
||||
|
||||
if(!((ossFormat == AFMT_U8 && aluBytesFromFormat(device->Format) == 1) ||
|
||||
(ossFormat == AFMT_S16_NE && aluBytesFromFormat(device->Format) == 2)))
|
||||
{
|
||||
AL_PRINT("Could not set %d-bit output, got format %#x\n", aluBytesFromFormat(device->Format)*8, ossFormat);
|
||||
close(data->fd);
|
||||
free(data);
|
||||
return ALC_FALSE;
|
||||
}
|
||||
|
||||
device->UpdateFreq = info.fragsize / device->FrameSize;
|
||||
|
||||
data->data_size = device->UpdateFreq * device->FrameSize;
|
||||
data->mix_data = calloc(1, data->data_size);
|
||||
|
||||
device->MaxNoOfSources = 256;
|
||||
|
||||
device->ExtraData = data;
|
||||
data->thread = StartThread(OSSProc, device);
|
||||
if(data->thread == NULL)
|
||||
{
|
||||
device->ExtraData = NULL;
|
||||
free(data->mix_data);
|
||||
free(data);
|
||||
return ALC_FALSE;
|
||||
}
|
||||
|
||||
return ALC_TRUE;
|
||||
}
|
||||
|
||||
static void oss_close_playback(ALCdevice *device)
|
||||
{
|
||||
oss_data *data = (oss_data*)device->ExtraData;
|
||||
data->killNow = 1;
|
||||
StopThread(data->thread);
|
||||
|
||||
close(data->fd);
|
||||
|
||||
free(data->mix_data);
|
||||
free(data);
|
||||
device->ExtraData = NULL;
|
||||
}
|
||||
|
||||
|
||||
static ALCboolean oss_open_capture(ALCdevice *device, const ALCchar *deviceName, ALCuint frequency, ALCenum format, ALCsizei SampleSize)
|
||||
{
|
||||
int numFragmentsLogSize;
|
||||
int log2FragmentSize;
|
||||
unsigned int periods;
|
||||
audio_buf_info info;
|
||||
int numChannels;
|
||||
char driver[64];
|
||||
oss_data *data;
|
||||
int ossFormat;
|
||||
int ossSpeed;
|
||||
char *err;
|
||||
int i;
|
||||
|
||||
strncpy(driver, GetConfigValue("oss", "capture", "/dev/dsp"), sizeof(driver)-1);
|
||||
driver[sizeof(driver)-1] = 0;
|
||||
if(deviceName)
|
||||
{
|
||||
if(strcmp(deviceName, oss_device_capture))
|
||||
return ALC_FALSE;
|
||||
device->szDeviceName = oss_device_capture;
|
||||
}
|
||||
else
|
||||
device->szDeviceName = oss_device_capture;
|
||||
|
||||
data = (oss_data*)calloc(1, sizeof(oss_data));
|
||||
data->killNow = 0;
|
||||
|
||||
data->fd = open(driver, O_RDONLY);
|
||||
if(data->fd == -1)
|
||||
{
|
||||
free(data);
|
||||
AL_PRINT("Could not open %s: %s\n", driver, strerror(errno));
|
||||
return ALC_FALSE;
|
||||
}
|
||||
|
||||
switch(aluBytesFromFormat(format))
|
||||
{
|
||||
case 1:
|
||||
data->silence = 0x80;
|
||||
ossFormat = AFMT_U8;
|
||||
break;
|
||||
case 2:
|
||||
data->silence = 0;
|
||||
ossFormat = AFMT_S16_NE;
|
||||
break;
|
||||
default:
|
||||
ossFormat = -1;
|
||||
AL_PRINT("Unknown format?! %x\n", device->Format);
|
||||
}
|
||||
|
||||
periods = 4;
|
||||
numChannels = device->Channels;
|
||||
ossSpeed = frequency;
|
||||
log2FragmentSize = log2i(device->UpdateFreq * device->FrameSize / periods);
|
||||
|
||||
/* according to the OSS spec, 16 bytes are the minimum */
|
||||
if (log2FragmentSize < 4)
|
||||
log2FragmentSize = 4;
|
||||
numFragmentsLogSize = (periods << 16) | log2FragmentSize;
|
||||
|
||||
#define ok(func, str) (i=(func),((i<0)?(err=(str)),0:1))
|
||||
if (!(ok(ioctl(data->fd, SNDCTL_DSP_SETFRAGMENT, &numFragmentsLogSize), "set fragment") &&
|
||||
ok(ioctl(data->fd, SNDCTL_DSP_SETFMT, &ossFormat), "set format") &&
|
||||
ok(ioctl(data->fd, SNDCTL_DSP_CHANNELS, &numChannels), "set channels") &&
|
||||
ok(ioctl(data->fd, SNDCTL_DSP_SPEED, &ossSpeed), "set speed") &&
|
||||
ok(ioctl(data->fd, SNDCTL_DSP_GETISPACE, &info), "get space")))
|
||||
{
|
||||
AL_PRINT("%s failed: %s\n", err, strerror(errno));
|
||||
close(data->fd);
|
||||
free(data);
|
||||
return ALC_FALSE;
|
||||
@@ -233,15 +395,22 @@ static ALCboolean oss_open_playback(ALCdevice *device, const ALCchar *deviceName
|
||||
return ALC_FALSE;
|
||||
}
|
||||
|
||||
data->ring = CreateRingBuffer(device->FrameSize, SampleSize);
|
||||
if(!data->ring)
|
||||
{
|
||||
AL_PRINT("ring buffer create failed\n");
|
||||
close(data->fd);
|
||||
free(data);
|
||||
return ALC_FALSE;
|
||||
}
|
||||
|
||||
device->UpdateFreq = info.fragsize / device->FrameSize;
|
||||
|
||||
data->data_size = device->UpdateFreq * device->FrameSize;
|
||||
data->data_size = device->UpdateFreq * device->FrameSize * info.fragments;
|
||||
data->mix_data = calloc(1, data->data_size);
|
||||
|
||||
device->MaxNoOfSources = 256;
|
||||
|
||||
device->ExtraData = data;
|
||||
data->thread = StartThread(OSSProc, device);
|
||||
data->thread = StartThread(OSSCaptureProc, device);
|
||||
if(data->thread == NULL)
|
||||
{
|
||||
device->ExtraData = NULL;
|
||||
@@ -253,7 +422,7 @@ static ALCboolean oss_open_playback(ALCdevice *device, const ALCchar *deviceName
|
||||
return ALC_TRUE;
|
||||
}
|
||||
|
||||
static void oss_close_playback(ALCdevice *device)
|
||||
static void oss_close_capture(ALCdevice *device)
|
||||
{
|
||||
oss_data *data = (oss_data*)device->ExtraData;
|
||||
data->killNow = 1;
|
||||
@@ -261,48 +430,38 @@ static void oss_close_playback(ALCdevice *device)
|
||||
|
||||
close(data->fd);
|
||||
|
||||
DestroyRingBuffer(data->ring);
|
||||
|
||||
free(data->mix_data);
|
||||
free(data);
|
||||
device->ExtraData = NULL;
|
||||
}
|
||||
|
||||
|
||||
static ALCboolean oss_open_capture(ALCdevice *pDevice, const ALCchar *deviceName, ALCuint frequency, ALCenum format, ALCsizei SampleSize)
|
||||
{
|
||||
(void)pDevice;
|
||||
(void)deviceName;
|
||||
(void)frequency;
|
||||
(void)format;
|
||||
(void)SampleSize;
|
||||
return ALC_FALSE;
|
||||
}
|
||||
|
||||
static void oss_close_capture(ALCdevice *pDevice)
|
||||
{
|
||||
(void)pDevice;
|
||||
}
|
||||
|
||||
static void oss_start_capture(ALCdevice *pDevice)
|
||||
{
|
||||
(void)pDevice;
|
||||
oss_data *data = (oss_data*)pDevice->ExtraData;
|
||||
data->doCapture = 1;
|
||||
}
|
||||
|
||||
static void oss_stop_capture(ALCdevice *pDevice)
|
||||
{
|
||||
(void)pDevice;
|
||||
oss_data *data = (oss_data*)pDevice->ExtraData;
|
||||
data->doCapture = 0;
|
||||
}
|
||||
|
||||
static void oss_capture_samples(ALCdevice *pDevice, ALCvoid *pBuffer, ALCuint lSamples)
|
||||
{
|
||||
(void)pDevice;
|
||||
(void)pBuffer;
|
||||
(void)lSamples;
|
||||
oss_data *data = (oss_data*)pDevice->ExtraData;
|
||||
if(lSamples <= (ALCuint)RingBufferSize(data->ring))
|
||||
ReadRingBuffer(data->ring, pBuffer, lSamples);
|
||||
else
|
||||
SetALCError(ALC_INVALID_VALUE);
|
||||
}
|
||||
|
||||
static ALCuint oss_available_samples(ALCdevice *pDevice)
|
||||
{
|
||||
(void)pDevice;
|
||||
return 0;
|
||||
oss_data *data = (oss_data*)pDevice->ExtraData;
|
||||
return RingBufferSize(data->ring);
|
||||
}
|
||||
|
||||
|
||||
@@ -323,4 +482,6 @@ void alc_oss_init(BackendFuncs *func_list)
|
||||
|
||||
oss_device = AppendDeviceList("OSS Software");
|
||||
AppendAllDeviceList(oss_device);
|
||||
|
||||
oss_device_capture = AppendCaptureDeviceList("OSS Capture");
|
||||
}
|
||||
|
||||
+28
-11
@@ -28,18 +28,11 @@ OPTION(WERROR "Treat compile warnings as errors" OFF)
|
||||
|
||||
|
||||
SET(LIB_MAJOR_VERSION "1")
|
||||
SET(LIB_MINOR_VERSION "0")
|
||||
SET(LIB_BUILD_VERSION "38")
|
||||
SET(LIB_MINOR_VERSION "1")
|
||||
SET(LIB_BUILD_VERSION "93")
|
||||
SET(LIB_VERSION "${LIB_MAJOR_VERSION}.${LIB_MINOR_VERSION}.${LIB_BUILD_VERSION}")
|
||||
|
||||
|
||||
IF("${WIN32}")
|
||||
SET(LIBNAME openal32)
|
||||
ELSE()
|
||||
SET(LIBNAME openal)
|
||||
ENDIF()
|
||||
|
||||
|
||||
CHECK_TYPE_SIZE("long" SIZEOF_LONG)
|
||||
CHECK_TYPE_SIZE("long long" SIZEOF_LONG_LONG)
|
||||
CHECK_TYPE_SIZE("unsigned int" SIZEOF_UINT)
|
||||
@@ -48,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}")
|
||||
# ???
|
||||
@@ -101,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)
|
||||
@@ -113,6 +108,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)
|
||||
@@ -172,7 +177,9 @@ SET(OPENAL_OBJS OpenAL32/alBuffer.c
|
||||
SET(ALC_OBJS Alc/ALc.c
|
||||
Alc/ALu.c
|
||||
Alc/alcConfig.c
|
||||
Alc/alcRing.c
|
||||
Alc/alcThread.c
|
||||
Alc/bs2b.c
|
||||
)
|
||||
|
||||
SET(BACKENDS "")
|
||||
@@ -254,8 +261,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})
|
||||
SET_TARGET_PROPERTIES(${LIBNAME} PROPERTIES VERSION ${LIB_VERSION}
|
||||
SOVERSION ${LIB_MAJOR_VERSION})
|
||||
IF("${WIN32}")
|
||||
SET_TARGET_PROPERTIES(${LIBNAME} PROPERTIES PREFIX "")
|
||||
ENDIF()
|
||||
|
||||
TARGET_LINK_LIBRARIES(${LIBNAME} ${EXTRA_LIBS})
|
||||
|
||||
|
||||
+35
-19
@@ -1,9 +1,6 @@
|
||||
#ifndef AL_MAIN_H
|
||||
#define AL_MAIN_H
|
||||
|
||||
#define AL_MAX_CHANNELS 4
|
||||
#define AL_MAX_SOURCES 32
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "alu.h"
|
||||
@@ -59,43 +56,53 @@ 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"
|
||||
{
|
||||
#endif
|
||||
|
||||
extern CRITICAL_SECTION g_mutex;
|
||||
extern CRITICAL_SECTION _alMutex;
|
||||
|
||||
extern char szDebug[256];
|
||||
extern char _alDebug[256];
|
||||
|
||||
#define AL_PRINT(...) do { \
|
||||
int _al_print_i; \
|
||||
char *_al_print_fn = strrchr(__FILE__, '/'); \
|
||||
if(!_al_print_fn) _al_print_fn = __FILE__; \
|
||||
else _al_print_fn += 1; \
|
||||
_al_print_i = snprintf(szDebug, sizeof(szDebug), "AL lib: %s:%d: ", _al_print_fn, __LINE__); \
|
||||
snprintf(szDebug+_al_print_i, sizeof(szDebug)-_al_print_i, __VA_ARGS__); \
|
||||
fprintf(stderr, "%s", szDebug); \
|
||||
_al_print_i = snprintf(_alDebug, sizeof(_alDebug), "AL lib: %s:%d: ", _al_print_fn, __LINE__); \
|
||||
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)
|
||||
|
||||
|
||||
#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
|
||||
// can use 4-channel 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
|
||||
//#define OUTPUT_BUFFER_SIZE (32768*SWMIXER_OUTPUT_RATE/22050)
|
||||
|
||||
#define SPEEDOFSOUNDMETRESPERSEC (343.3f)
|
||||
|
||||
@@ -153,8 +160,8 @@ struct ALCcontext_struct
|
||||
{
|
||||
ALlistener Listener;
|
||||
|
||||
ALsource *Source;
|
||||
ALuint SourceCount;
|
||||
struct ALsource *Source;
|
||||
ALuint SourceCount;
|
||||
|
||||
ALenum LastError;
|
||||
ALboolean InUse;
|
||||
@@ -173,6 +180,8 @@ struct ALCcontext_struct
|
||||
ALCdevice *Device;
|
||||
ALCchar ExtensionList[1024];
|
||||
|
||||
struct bs2b *bs2b;
|
||||
|
||||
ALCcontext *next;
|
||||
};
|
||||
|
||||
@@ -188,6 +197,13 @@ ALCvoid ProcessContext(ALCcontext *context);
|
||||
ALvoid *StartThread(ALuint (*func)(ALvoid*), ALvoid *ptr);
|
||||
ALuint StopThread(ALvoid *thread);
|
||||
|
||||
typedef struct RingBuffer RingBuffer;
|
||||
RingBuffer *CreateRingBuffer(ALsizei frame_size, ALsizei length);
|
||||
void DestroyRingBuffer(RingBuffer *ring);
|
||||
ALsizei RingBufferSize(RingBuffer *ring);
|
||||
void WriteRingBuffer(RingBuffer *ring, const ALubyte *data, ALsizei len);
|
||||
void ReadRingBuffer(RingBuffer *ring, ALubyte *data, ALsizei len);
|
||||
|
||||
void ReadALConfig(void);
|
||||
void FreeALConfig(void);
|
||||
const char *GetConfigValue(const char *blockName, const char *keyName, const char *def);
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -1,12 +1,6 @@
|
||||
#ifndef _ALU_H_
|
||||
#define _ALU_H_
|
||||
|
||||
#define BUFFERSIZE 48000
|
||||
#define FRACTIONBITS 14
|
||||
#define FRACTIONMASK ((1L<<FRACTIONBITS)-1)
|
||||
#define MAX_PITCH 4
|
||||
#define OUTPUTCHANNELS 4
|
||||
|
||||
#include "AL/al.h"
|
||||
#include "AL/alc.h"
|
||||
|
||||
|
||||
@@ -0,0 +1,109 @@
|
||||
/*-
|
||||
* Copyright (c) 2005 Boris Mikhaylov
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef BS2B_H
|
||||
#define BS2B_H
|
||||
|
||||
/* Number of crossfeed levels */
|
||||
#define BS2B_CLEVELS 3
|
||||
|
||||
/* Normal crossfeed levels */
|
||||
#define BS2B_HIGH_CLEVEL 3
|
||||
#define BS2B_MIDDLE_CLEVEL 2
|
||||
#define BS2B_LOW_CLEVEL 1
|
||||
|
||||
/* Easy crossfeed levels */
|
||||
#define BS2B_HIGH_ECLEVEL BS2B_HIGH_CLEVEL + BS2B_CLEVELS
|
||||
#define BS2B_MIDDLE_ECLEVEL BS2B_MIDDLE_CLEVEL + BS2B_CLEVELS
|
||||
#define BS2B_LOW_ECLEVEL BS2B_LOW_CLEVEL + BS2B_CLEVELS
|
||||
|
||||
/* Default crossfeed levels */
|
||||
#define BS2B_DEFAULT_CLEVEL BS2B_HIGH_ECLEVEL
|
||||
/* Default sample rate (Hz) */
|
||||
#define BS2B_DEFAULT_SRATE 44100
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
|
||||
struct bs2b {
|
||||
int level; /* Crossfeed level */
|
||||
int srate; /* Sample rate (Hz) */
|
||||
|
||||
/* Lowpass IIR filter coefficients */
|
||||
double a0_lo;
|
||||
double b1_lo;
|
||||
|
||||
/* Highboost IIR filter coefficients */
|
||||
double a0_hi;
|
||||
double a1_hi;
|
||||
double b1_hi;
|
||||
|
||||
/* Global gain against overloading */
|
||||
double gain;
|
||||
|
||||
/* Buffer of last filtered sample.
|
||||
* [0] - first channel, [1] - second channel
|
||||
*/
|
||||
struct t_last_sample {
|
||||
double asis[2];
|
||||
double lo[2];
|
||||
double hi[2];
|
||||
} last_sample;
|
||||
};
|
||||
|
||||
/* Clear buffers and set new coefficients with new crossfeed level value.
|
||||
* level - crossfeed level of *LEVEL values.
|
||||
*/
|
||||
void bs2b_set_level(struct bs2b *bs2b, int level);
|
||||
|
||||
/* Return current crossfeed level value */
|
||||
int bs2b_get_level(struct bs2b *bs2b);
|
||||
|
||||
/* Clear buffers and set new coefficients with new sample rate value.
|
||||
* srate - sample rate by Hz.
|
||||
*/
|
||||
void bs2b_set_srate(struct bs2b *bs2b, int srate);
|
||||
|
||||
/* Return current sample rate value */
|
||||
int bs2b_get_srate(struct bs2b *bs2b);
|
||||
|
||||
/* Clear buffer */
|
||||
void bs2b_clear(struct bs2b *bs2b);
|
||||
|
||||
/* Return 1 if buffer is clear */
|
||||
int bs2b_is_clear(struct bs2b *bs2b);
|
||||
|
||||
/* Crossfeeds one stereo sample that are pointed by sample.
|
||||
* [0] - first channel, [1] - second channel.
|
||||
* Returns crossfided samle by sample pointer.
|
||||
*/
|
||||
|
||||
/* sample poits to floats */
|
||||
void bs2b_cross_feed(struct bs2b *bs2b, float *sample);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#endif /* BS2B_H */
|
||||
+3
-3
@@ -22,7 +22,7 @@
|
||||
#include "alBuffer.h"
|
||||
#include "alThunk.h"
|
||||
|
||||
CRITICAL_SECTION g_mutex;
|
||||
CRITICAL_SECTION _alMutex;
|
||||
|
||||
#ifdef _WIN32
|
||||
BOOL APIENTRY DllMain(HANDLE hModule,DWORD ul_reason_for_call,LPVOID lpReserved)
|
||||
@@ -40,7 +40,7 @@ BOOL APIENTRY DllMain(HANDLE hModule,DWORD ul_reason_for_call,LPVOID lpReserved)
|
||||
ReleaseALBuffers();
|
||||
FreeALConfig();
|
||||
ALTHUNK_EXIT();
|
||||
DeleteCriticalSection(&g_mutex);
|
||||
DeleteCriticalSection(&_alMutex);
|
||||
break;
|
||||
}
|
||||
return TRUE;
|
||||
@@ -57,7 +57,7 @@ static void my_deinit()
|
||||
ReleaseALBuffers();
|
||||
FreeALConfig();
|
||||
ALTHUNK_EXIT();
|
||||
DeleteCriticalSection(&g_mutex);
|
||||
DeleteCriticalSection(&_alMutex);
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
+222
-75
@@ -22,13 +22,17 @@
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <assert.h>
|
||||
#include "alMain.h"
|
||||
#include "AL/al.h"
|
||||
#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);
|
||||
|
||||
/*
|
||||
* AL Buffer Functions
|
||||
*
|
||||
@@ -273,91 +277,143 @@ 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);
|
||||
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);
|
||||
case AL_FORMAT_MONO_FLOAT32:
|
||||
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);
|
||||
case AL_FORMAT_STEREO16:
|
||||
case AL_FORMAT_STEREO_FLOAT32:
|
||||
LoadData(ALBuf, data, size, freq, format, AL_FORMAT_STEREO16);
|
||||
break;
|
||||
|
||||
case AL_FORMAT_STEREO16:
|
||||
if ((size%4) == 0)
|
||||
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)
|
||||
{
|
||||
// Allocate 8 extra samples (32 bytes)
|
||||
ALBuf->data=realloc(ALBuf->data,32+(size/sizeof(ALshort))*(1*sizeof(ALshort)));
|
||||
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)
|
||||
{
|
||||
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;
|
||||
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);
|
||||
}
|
||||
else
|
||||
alSetError(AL_INVALID_VALUE);
|
||||
} 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:
|
||||
@@ -489,7 +545,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;
|
||||
@@ -817,11 +873,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:
|
||||
@@ -917,6 +973,97 @@ 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;
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* ReleaseALBuffers()
|
||||
|
||||
@@ -150,12 +150,27 @@ 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 },
|
||||
{ (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 },
|
||||
|
||||
+54
-17
@@ -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);
|
||||
@@ -1846,6 +1848,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 +1857,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,17 +1908,30 @@ 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))
|
||||
{
|
||||
*pflOffset = (ALfloat)(lBytesPlayed >> 1);
|
||||
}
|
||||
else if ((eOriginalFormat == AL_FORMAT_MONO_IMA4) || (eOriginalFormat == AL_FORMAT_STEREO_IMA4))
|
||||
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 (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);
|
||||
}
|
||||
else if (aluBytesFromFormat(eOriginalFormat) == 4)
|
||||
{
|
||||
*pflOffset = (ALfloat)(lBytesPlayed << 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
*pflOffset = (ALfloat)lBytesPlayed;
|
||||
@@ -1940,6 +1957,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 +1974,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 +2004,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 +2063,15 @@ 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))
|
||||
{
|
||||
lByteOffset = pSource->lOffset * 2;
|
||||
lByteOffset -= (lByteOffset % (lChannels * 2));
|
||||
}
|
||||
else if ((pBuffer->eOriginalFormat == AL_FORMAT_MONO_IMA4) || (pBuffer->eOriginalFormat == AL_FORMAT_STEREO_IMA4))
|
||||
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;
|
||||
@@ -2062,6 +2079,26 @@ 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;
|
||||
lByteOffset -= (lByteOffset % (lChannels * 2));
|
||||
}
|
||||
else if (aluBytesFromFormat(pBuffer->eOriginalFormat) == 4)
|
||||
{
|
||||
lByteOffset = pSource->lOffset / 2;
|
||||
lByteOffset -= (lByteOffset % (lChannels * 2));
|
||||
}
|
||||
else
|
||||
{
|
||||
lByteOffset = pSource->lOffset;
|
||||
|
||||
@@ -12,11 +12,28 @@ 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_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
|
||||
|
||||
cf_level = 0 # Sets the crossfeed level for stereo output. Valid values are:
|
||||
# 0 - No crossfeed
|
||||
# 1 - Low crossfeed
|
||||
# 2 - Middle crossfeed
|
||||
# 3 - High crossfeed (virtual speakers are closer to itself)
|
||||
# 4 - Low easy crossfeed
|
||||
# 5 - Middle easy crossfeed
|
||||
# 6 - High easy crossfeed
|
||||
# Default is 0. Users of headphones may want to try various
|
||||
# settings. Has no effect on non-stereo modes.
|
||||
|
||||
frequency = 44100 # Sets the output frequency. Default is 44100
|
||||
|
||||
refresh = 0 # Sets the number of frames-per-update. Default is calculated as
|
||||
@@ -43,6 +60,8 @@ device = /dev/dsp # Sets the device name for OSS output. Default is /dev/dsp
|
||||
|
||||
periods = 4 # Sets the number of update buffers. Default is 4
|
||||
|
||||
capture = /dev/dsp # Sets the device name for OSS capture. Default is /dev/dsp
|
||||
|
||||
[dsound] # DirectSound backend stuff
|
||||
# Nothing yet...
|
||||
|
||||
|
||||
Reference in New Issue
Block a user