Merge branch 'master' of git://repo.or.cz/openal-soft
This commit is contained in:
commit
eb37458eb1
361
Alc/ALu.c
361
Alc/ALu.c
@ -37,6 +37,11 @@
|
|||||||
#include "bs2b.h"
|
#include "bs2b.h"
|
||||||
|
|
||||||
|
|
||||||
|
struct ChanMap {
|
||||||
|
enum Channel channel;
|
||||||
|
ALfloat angle;
|
||||||
|
};
|
||||||
|
|
||||||
/* Cone scalar */
|
/* Cone scalar */
|
||||||
ALfloat ConeScale = 0.5f;
|
ALfloat ConeScale = 0.5f;
|
||||||
|
|
||||||
@ -58,56 +63,69 @@ static __inline ALvoid aluMatrixVector(ALfloat *vector,ALfloat w,ALfloat matrix[
|
|||||||
|
|
||||||
ALvoid CalcNonAttnSourceParams(ALsource *ALSource, const ALCcontext *ALContext)
|
ALvoid CalcNonAttnSourceParams(ALsource *ALSource, const ALCcontext *ALContext)
|
||||||
{
|
{
|
||||||
static const ALfloat angles_Mono[1] = { 0.0f };
|
static const struct ChanMap MonoMap[1] = { { FRONT_CENTER, 0.0f } };
|
||||||
static const ALfloat angles_Stereo[2] = { -30.0f, 30.0f };
|
static const struct ChanMap StereoMap[2] = {
|
||||||
static const ALfloat angles_Rear[2] = { -150.0f, 150.0f };
|
{ FRONT_LEFT, -30.0f * F_PI/180.0f },
|
||||||
static const ALfloat angles_Quad[4] = { -45.0f, 45.0f, -135.0f, 135.0f };
|
{ FRONT_RIGHT, 30.0f * F_PI/180.0f }
|
||||||
static const ALfloat angles_X51[6] = { -30.0f, 30.0f, 0.0f, 0.0f,
|
};
|
||||||
-110.0f, 110.0f };
|
static const struct ChanMap RearMap[2] = {
|
||||||
static const ALfloat angles_X61[7] = { -30.0f, 30.0f, 0.0f, 0.0f,
|
{ BACK_LEFT, -150.0f * F_PI/180.0f },
|
||||||
180.0f, -90.0f, 90.0f };
|
{ BACK_RIGHT, 150.0f * F_PI/180.0f }
|
||||||
static const ALfloat angles_X71[8] = { -30.0f, 30.0f, 0.0f, 0.0f,
|
};
|
||||||
-110.0f, 110.0f, -90.0f, 90.0f };
|
static const struct ChanMap QuadMap[4] = {
|
||||||
|
{ FRONT_LEFT, -45.0f * F_PI/180.0f },
|
||||||
static const enum Channel chans_Mono[1] = { FRONT_CENTER };
|
{ FRONT_RIGHT, 45.0f * F_PI/180.0f },
|
||||||
static const enum Channel chans_Stereo[2] = { FRONT_LEFT, FRONT_RIGHT };
|
{ BACK_LEFT, -135.0f * F_PI/180.0f },
|
||||||
static const enum Channel chans_Rear[2] = { BACK_LEFT, BACK_RIGHT };
|
{ BACK_RIGHT, 135.0f * F_PI/180.0f }
|
||||||
static const enum Channel chans_Quad[4] = { FRONT_LEFT, FRONT_RIGHT,
|
};
|
||||||
BACK_LEFT, BACK_RIGHT };
|
static const struct ChanMap X51Map[6] = {
|
||||||
static const enum Channel chans_X51[6] = { FRONT_LEFT, FRONT_RIGHT,
|
{ FRONT_LEFT, -30.0f * F_PI/180.0f },
|
||||||
FRONT_CENTER, LFE,
|
{ FRONT_RIGHT, 30.0f * F_PI/180.0f },
|
||||||
BACK_LEFT, BACK_RIGHT };
|
{ FRONT_CENTER, 0.0f * F_PI/180.0f },
|
||||||
static const enum Channel chans_X61[7] = { FRONT_LEFT, FRONT_RIGHT,
|
{ LFE, 0.0f },
|
||||||
FRONT_CENTER, LFE, BACK_CENTER,
|
{ BACK_LEFT, -110.0f * F_PI/180.0f },
|
||||||
SIDE_LEFT, SIDE_RIGHT };
|
{ BACK_RIGHT, 110.0f * F_PI/180.0f }
|
||||||
static const enum Channel chans_X71[8] = { FRONT_LEFT, FRONT_RIGHT,
|
};
|
||||||
FRONT_CENTER, LFE,
|
static const struct ChanMap X61Map[7] = {
|
||||||
BACK_LEFT, BACK_RIGHT,
|
{ FRONT_LEFT, -30.0f * F_PI/180.0f },
|
||||||
SIDE_LEFT, SIDE_RIGHT };
|
{ FRONT_RIGHT, 30.0f * F_PI/180.0f },
|
||||||
|
{ FRONT_CENTER, 0.0f * F_PI/180.0f },
|
||||||
|
{ LFE, 0.0f },
|
||||||
|
{ BACK_CENTER, 180.0f * F_PI/180.0f },
|
||||||
|
{ SIDE_LEFT, -90.0f * F_PI/180.0f },
|
||||||
|
{ SIDE_RIGHT, 90.0f * F_PI/180.0f }
|
||||||
|
};
|
||||||
|
static const struct ChanMap X71Map[8] = {
|
||||||
|
{ FRONT_LEFT, -30.0f * F_PI/180.0f },
|
||||||
|
{ FRONT_RIGHT, 30.0f * F_PI/180.0f },
|
||||||
|
{ FRONT_CENTER, 0.0f * F_PI/180.0f },
|
||||||
|
{ LFE, 0.0f },
|
||||||
|
{ BACK_LEFT, -150.0f * F_PI/180.0f },
|
||||||
|
{ BACK_RIGHT, 150.0f * F_PI/180.0f },
|
||||||
|
{ SIDE_LEFT, -90.0f * F_PI/180.0f },
|
||||||
|
{ SIDE_RIGHT, 90.0f * F_PI/180.0f }
|
||||||
|
};
|
||||||
|
|
||||||
ALCdevice *Device = ALContext->Device;
|
ALCdevice *Device = ALContext->Device;
|
||||||
ALfloat SourceVolume,ListenerGain,MinVolume,MaxVolume;
|
ALfloat SourceVolume,ListenerGain,MinVolume,MaxVolume;
|
||||||
ALbufferlistitem *BufferListItem;
|
ALbufferlistitem *BufferListItem;
|
||||||
enum DevFmtChannels DevChans;
|
|
||||||
enum FmtChannels Channels;
|
enum FmtChannels Channels;
|
||||||
ALfloat (*SrcMatrix)[MAXCHANNELS];
|
ALfloat (*SrcMatrix)[MAXCHANNELS];
|
||||||
ALfloat DryGain, DryGainHF;
|
ALfloat DryGain, DryGainHF;
|
||||||
ALfloat WetGain[MAX_SENDS];
|
ALfloat WetGain[MAX_SENDS];
|
||||||
ALfloat WetGainHF[MAX_SENDS];
|
ALfloat WetGainHF[MAX_SENDS];
|
||||||
ALint NumSends, Frequency;
|
ALint NumSends, Frequency;
|
||||||
const ALfloat *SpeakerGain;
|
const ALfloat *ChannelGain;
|
||||||
const ALfloat *angles = NULL;
|
const struct ChanMap *chans = NULL;
|
||||||
const enum Channel *chans = NULL;
|
|
||||||
enum Resampler Resampler;
|
enum Resampler Resampler;
|
||||||
ALint num_channels = 0;
|
ALint num_channels = 0;
|
||||||
ALboolean VirtualChannels;
|
ALboolean DirectChannels;
|
||||||
ALfloat Pitch;
|
ALfloat Pitch;
|
||||||
ALfloat cw;
|
ALfloat cw;
|
||||||
ALuint pos;
|
ALuint pos;
|
||||||
ALint i, c;
|
ALint i, c;
|
||||||
|
|
||||||
/* Get device properties */
|
/* Get device properties */
|
||||||
DevChans = Device->FmtChans;
|
|
||||||
NumSends = Device->NumAuxSends;
|
NumSends = Device->NumAuxSends;
|
||||||
Frequency = Device->Frequency;
|
Frequency = Device->Frequency;
|
||||||
|
|
||||||
@ -120,7 +138,7 @@ ALvoid CalcNonAttnSourceParams(ALsource *ALSource, const ALCcontext *ALContext)
|
|||||||
MaxVolume = ALSource->flMaxGain;
|
MaxVolume = ALSource->flMaxGain;
|
||||||
Pitch = ALSource->flPitch;
|
Pitch = ALSource->flPitch;
|
||||||
Resampler = ALSource->Resampler;
|
Resampler = ALSource->Resampler;
|
||||||
VirtualChannels = ALSource->VirtualChannels;
|
DirectChannels = ALSource->DirectChannels;
|
||||||
|
|
||||||
/* Calculate the stepping value */
|
/* Calculate the stepping value */
|
||||||
Channels = FmtMono;
|
Channels = FmtMono;
|
||||||
@ -130,8 +148,8 @@ ALvoid CalcNonAttnSourceParams(ALsource *ALSource, const ALCcontext *ALContext)
|
|||||||
ALbuffer *ALBuffer;
|
ALbuffer *ALBuffer;
|
||||||
if((ALBuffer=BufferListItem->buffer) != NULL)
|
if((ALBuffer=BufferListItem->buffer) != NULL)
|
||||||
{
|
{
|
||||||
ALint maxstep = STACK_DATA_SIZE / ALSource->NumChannels /
|
ALsizei maxstep = STACK_DATA_SIZE/sizeof(ALfloat) /
|
||||||
ALSource->SampleSize;
|
ALSource->NumChannels;
|
||||||
maxstep -= ResamplerPadding[Resampler] +
|
maxstep -= ResamplerPadding[Resampler] +
|
||||||
ResamplerPrePadding[Resampler] + 1;
|
ResamplerPrePadding[Resampler] + 1;
|
||||||
maxstep = mini(maxstep, INT_MAX>>FRACTIONBITS);
|
maxstep = mini(maxstep, INT_MAX>>FRACTIONBITS);
|
||||||
@ -145,18 +163,18 @@ ALvoid CalcNonAttnSourceParams(ALsource *ALSource, const ALCcontext *ALContext)
|
|||||||
if(ALSource->Params.Step == 0)
|
if(ALSource->Params.Step == 0)
|
||||||
ALSource->Params.Step = 1;
|
ALSource->Params.Step = 1;
|
||||||
}
|
}
|
||||||
|
if(ALSource->Params.Step == FRACTIONONE)
|
||||||
|
Resampler = PointResampler;
|
||||||
|
|
||||||
Channels = ALBuffer->FmtChannels;
|
Channels = ALBuffer->FmtChannels;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
BufferListItem = BufferListItem->next;
|
BufferListItem = BufferListItem->next;
|
||||||
}
|
}
|
||||||
if(VirtualChannels && Device->Hrtf)
|
if(!DirectChannels && Device->Hrtf)
|
||||||
ALSource->Params.DoMix = SelectHrtfMixer((ALSource->Params.Step==FRACTIONONE) ?
|
ALSource->Params.DoMix = SelectHrtfMixer(Resampler);
|
||||||
POINT_RESAMPLER : Resampler);
|
|
||||||
else
|
else
|
||||||
ALSource->Params.DoMix = SelectMixer((ALSource->Params.Step==FRACTIONONE) ?
|
ALSource->Params.DoMix = SelectMixer(Resampler);
|
||||||
POINT_RESAMPLER : Resampler);
|
|
||||||
|
|
||||||
/* Calculate gains */
|
/* Calculate gains */
|
||||||
DryGain = clampf(SourceVolume, MinVolume, MaxVolume);
|
DryGain = clampf(SourceVolume, MinVolume, MaxVolume);
|
||||||
@ -178,74 +196,77 @@ ALvoid CalcNonAttnSourceParams(ALsource *ALSource, const ALCcontext *ALContext)
|
|||||||
switch(Channels)
|
switch(Channels)
|
||||||
{
|
{
|
||||||
case FmtMono:
|
case FmtMono:
|
||||||
angles = angles_Mono;
|
chans = MonoMap;
|
||||||
chans = chans_Mono;
|
|
||||||
num_channels = 1;
|
num_channels = 1;
|
||||||
break;
|
break;
|
||||||
case FmtStereo:
|
case FmtStereo:
|
||||||
if(VirtualChannels && (Device->Flags&DEVICE_DUPLICATE_STEREO))
|
if(!DirectChannels && (Device->Flags&DEVICE_DUPLICATE_STEREO))
|
||||||
{
|
{
|
||||||
DryGain *= aluSqrt(2.0f/4.0f);
|
DryGain *= aluSqrt(2.0f/4.0f);
|
||||||
for(c = 0;c < 2;c++)
|
for(c = 0;c < 2;c++)
|
||||||
{
|
{
|
||||||
pos = aluCart2LUTpos(aluCos(F_PI/180.0f * angles_Rear[c]),
|
pos = aluCart2LUTpos(aluCos(RearMap[c].angle),
|
||||||
aluSin(F_PI/180.0f * angles_Rear[c]));
|
aluSin(RearMap[c].angle));
|
||||||
SpeakerGain = Device->PanningLUT[pos];
|
ChannelGain = Device->PanningLUT[pos];
|
||||||
|
|
||||||
for(i = 0;i < (ALint)Device->NumChan;i++)
|
for(i = 0;i < (ALint)Device->NumChan;i++)
|
||||||
{
|
{
|
||||||
enum Channel chan = Device->Speaker2Chan[i];
|
enum Channel chan = Device->Speaker2Chan[i];
|
||||||
SrcMatrix[c][chan] += DryGain * ListenerGain *
|
SrcMatrix[c][chan] += DryGain * ListenerGain *
|
||||||
SpeakerGain[chan];
|
ChannelGain[chan];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
angles = angles_Stereo;
|
chans = StereoMap;
|
||||||
chans = chans_Stereo;
|
|
||||||
num_channels = 2;
|
num_channels = 2;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case FmtRear:
|
case FmtRear:
|
||||||
angles = angles_Rear;
|
chans = RearMap;
|
||||||
chans = chans_Rear;
|
|
||||||
num_channels = 2;
|
num_channels = 2;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case FmtQuad:
|
case FmtQuad:
|
||||||
angles = angles_Quad;
|
chans = QuadMap;
|
||||||
chans = chans_Quad;
|
|
||||||
num_channels = 4;
|
num_channels = 4;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case FmtX51:
|
case FmtX51:
|
||||||
angles = angles_X51;
|
chans = X51Map;
|
||||||
chans = chans_X51;
|
|
||||||
num_channels = 6;
|
num_channels = 6;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case FmtX61:
|
case FmtX61:
|
||||||
angles = angles_X61;
|
chans = X61Map;
|
||||||
chans = chans_X61;
|
|
||||||
num_channels = 7;
|
num_channels = 7;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case FmtX71:
|
case FmtX71:
|
||||||
angles = angles_X71;
|
chans = X71Map;
|
||||||
chans = chans_X71;
|
|
||||||
num_channels = 8;
|
num_channels = 8;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(VirtualChannels == AL_FALSE)
|
if(DirectChannels != AL_FALSE)
|
||||||
{
|
{
|
||||||
for(c = 0;c < num_channels;c++)
|
for(c = 0;c < num_channels;c++)
|
||||||
SrcMatrix[c][chans[c]] += DryGain * ListenerGain;
|
{
|
||||||
|
for(i = 0;i < (ALint)Device->NumChan;i++)
|
||||||
|
{
|
||||||
|
enum Channel chan = Device->Speaker2Chan[i];
|
||||||
|
if(chan == chans[c].channel)
|
||||||
|
{
|
||||||
|
SrcMatrix[c][chan] += DryGain * ListenerGain;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else if(Device->Hrtf)
|
else if(Device->Hrtf)
|
||||||
{
|
{
|
||||||
for(c = 0;c < num_channels;c++)
|
for(c = 0;c < num_channels;c++)
|
||||||
{
|
{
|
||||||
if(chans[c] == LFE)
|
if(chans[c].channel == LFE)
|
||||||
{
|
{
|
||||||
/* Skip LFE */
|
/* Skip LFE */
|
||||||
ALSource->Params.HrtfDelay[c][0] = 0;
|
ALSource->Params.HrtfDelay[c][0] = 0;
|
||||||
@ -261,7 +282,7 @@ ALvoid CalcNonAttnSourceParams(ALsource *ALSource, const ALCcontext *ALContext)
|
|||||||
/* Get the static HRIR coefficients and delays for this
|
/* Get the static HRIR coefficients and delays for this
|
||||||
* channel. */
|
* channel. */
|
||||||
GetLerpedHrtfCoeffs(Device->Hrtf,
|
GetLerpedHrtfCoeffs(Device->Hrtf,
|
||||||
0.0f, F_PI/180.0f * angles[c],
|
0.0f, chans[c].angle,
|
||||||
DryGain*ListenerGain,
|
DryGain*ListenerGain,
|
||||||
ALSource->Params.HrtfCoeffs[c],
|
ALSource->Params.HrtfCoeffs[c],
|
||||||
ALSource->Params.HrtfDelay[c]);
|
ALSource->Params.HrtfDelay[c]);
|
||||||
@ -273,26 +294,31 @@ ALvoid CalcNonAttnSourceParams(ALsource *ALSource, const ALCcontext *ALContext)
|
|||||||
{
|
{
|
||||||
for(c = 0;c < num_channels;c++)
|
for(c = 0;c < num_channels;c++)
|
||||||
{
|
{
|
||||||
if(chans[c] == LFE) /* Special-case LFE */
|
if(chans[c].channel == LFE) /* Special-case LFE */
|
||||||
{
|
{
|
||||||
SrcMatrix[c][LFE] += DryGain * ListenerGain;
|
SrcMatrix[c][LFE] += DryGain * ListenerGain;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
pos = aluCart2LUTpos(aluCos(F_PI/180.0f * angles[c]),
|
pos = aluCart2LUTpos(aluCos(chans[c].angle), aluSin(chans[c].angle));
|
||||||
aluSin(F_PI/180.0f * angles[c]));
|
ChannelGain = Device->PanningLUT[pos];
|
||||||
SpeakerGain = Device->PanningLUT[pos];
|
|
||||||
|
|
||||||
for(i = 0;i < (ALint)Device->NumChan;i++)
|
for(i = 0;i < (ALint)Device->NumChan;i++)
|
||||||
{
|
{
|
||||||
enum Channel chan = Device->Speaker2Chan[i];
|
enum Channel chan = Device->Speaker2Chan[i];
|
||||||
SrcMatrix[c][chan] += DryGain * ListenerGain *
|
SrcMatrix[c][chan] += DryGain * ListenerGain *
|
||||||
SpeakerGain[chan];
|
ChannelGain[chan];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for(i = 0;i < NumSends;i++)
|
for(i = 0;i < NumSends;i++)
|
||||||
{
|
{
|
||||||
ALSource->Params.Send[i].Slot = ALSource->Send[i].Slot;
|
ALeffectslot *Slot = ALSource->Send[i].Slot;
|
||||||
|
|
||||||
|
if(!Slot && i == 0)
|
||||||
|
Slot = Device->DefaultSlot;
|
||||||
|
if(Slot && Slot->effect.type == AL_EFFECT_NULL)
|
||||||
|
Slot = NULL;
|
||||||
|
ALSource->Params.Send[i].Slot = Slot;
|
||||||
ALSource->Params.Send[i].WetGain = WetGain[i] * ListenerGain;
|
ALSource->Params.Send[i].WetGain = WetGain[i] * ListenerGain;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -320,7 +346,7 @@ ALvoid CalcSourceParams(ALsource *ALSource, const ALCcontext *ALContext)
|
|||||||
ALfloat Velocity[3],ListenerVel[3];
|
ALfloat Velocity[3],ListenerVel[3];
|
||||||
ALfloat MinVolume,MaxVolume,MinDist,MaxDist,Rolloff;
|
ALfloat MinVolume,MaxVolume,MinDist,MaxDist,Rolloff;
|
||||||
ALfloat ConeVolume,ConeHF,SourceVolume,ListenerGain;
|
ALfloat ConeVolume,ConeHF,SourceVolume,ListenerGain;
|
||||||
ALfloat DopplerFactor, DopplerVelocity, SpeedOfSound;
|
ALfloat DopplerFactor, SpeedOfSound;
|
||||||
ALfloat AirAbsorptionFactor;
|
ALfloat AirAbsorptionFactor;
|
||||||
ALfloat RoomAirAbsorption[MAX_SENDS];
|
ALfloat RoomAirAbsorption[MAX_SENDS];
|
||||||
ALbufferlistitem *BufferListItem;
|
ALbufferlistitem *BufferListItem;
|
||||||
@ -338,22 +364,22 @@ ALvoid CalcSourceParams(ALsource *ALSource, const ALCcontext *ALContext)
|
|||||||
ALboolean WetGainAuto;
|
ALboolean WetGainAuto;
|
||||||
ALboolean WetGainHFAuto;
|
ALboolean WetGainHFAuto;
|
||||||
enum Resampler Resampler;
|
enum Resampler Resampler;
|
||||||
|
ALfloat Matrix[4][4];
|
||||||
ALfloat Pitch;
|
ALfloat Pitch;
|
||||||
ALuint Frequency;
|
ALuint Frequency;
|
||||||
ALint NumSends;
|
ALint NumSends;
|
||||||
ALfloat cw;
|
ALfloat cw;
|
||||||
ALint i;
|
ALint i, j;
|
||||||
|
|
||||||
DryGainHF = 1.0f;
|
DryGainHF = 1.0f;
|
||||||
for(i = 0;i < MAX_SENDS;i++)
|
for(i = 0;i < MAX_SENDS;i++)
|
||||||
WetGainHF[i] = 1.0f;
|
WetGainHF[i] = 1.0f;
|
||||||
|
|
||||||
//Get context properties
|
//Get context properties
|
||||||
DopplerFactor = ALContext->DopplerFactor * ALSource->DopplerFactor;
|
DopplerFactor = ALContext->DopplerFactor * ALSource->DopplerFactor;
|
||||||
DopplerVelocity = ALContext->DopplerVelocity;
|
SpeedOfSound = ALContext->flSpeedOfSound * ALContext->DopplerVelocity;
|
||||||
SpeedOfSound = ALContext->flSpeedOfSound;
|
NumSends = Device->NumAuxSends;
|
||||||
NumSends = Device->NumAuxSends;
|
Frequency = Device->Frequency;
|
||||||
Frequency = Device->Frequency;
|
|
||||||
|
|
||||||
//Get listener properties
|
//Get listener properties
|
||||||
ListenerGain = ALContext->Listener.Gain;
|
ListenerGain = ALContext->Listener.Gain;
|
||||||
@ -391,8 +417,11 @@ ALvoid CalcSourceParams(ALsource *ALSource, const ALCcontext *ALContext)
|
|||||||
{
|
{
|
||||||
ALeffectslot *Slot = ALSource->Send[i].Slot;
|
ALeffectslot *Slot = ALSource->Send[i].Slot;
|
||||||
|
|
||||||
|
if(!Slot && i == 0)
|
||||||
|
Slot = Device->DefaultSlot;
|
||||||
if(!Slot || Slot->effect.type == AL_EFFECT_NULL)
|
if(!Slot || Slot->effect.type == AL_EFFECT_NULL)
|
||||||
{
|
{
|
||||||
|
Slot = NULL;
|
||||||
RoomRolloff[i] = 0.0f;
|
RoomRolloff[i] = 0.0f;
|
||||||
DecayDistance[i] = 0.0f;
|
DecayDistance[i] = 0.0f;
|
||||||
RoomAirAbsorption[i] = 1.0f;
|
RoomAirAbsorption[i] = 1.0f;
|
||||||
@ -425,17 +454,15 @@ ALvoid CalcSourceParams(ALsource *ALSource, const ALCcontext *ALContext)
|
|||||||
ALSource->Params.Send[i].Slot = Slot;
|
ALSource->Params.Send[i].Slot = Slot;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for(i = 0;i < 4;i++)
|
||||||
|
{
|
||||||
|
for(j = 0;j < 4;j++)
|
||||||
|
Matrix[i][j] = ALContext->Listener.Matrix[i][j];
|
||||||
|
}
|
||||||
|
|
||||||
//1. Translate Listener to origin (convert to head relative)
|
//1. Translate Listener to origin (convert to head relative)
|
||||||
if(ALSource->bHeadRelative == AL_FALSE)
|
if(ALSource->bHeadRelative == AL_FALSE)
|
||||||
{
|
{
|
||||||
ALfloat Matrix[4][4];
|
|
||||||
for(i = 0;i < 4;i++)
|
|
||||||
{
|
|
||||||
ALint i2;
|
|
||||||
for(i2 = 0;i2 < 4;i2++)
|
|
||||||
Matrix[i][i2] = ALContext->Listener.Matrix[i][i2];
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Translate position */
|
/* Translate position */
|
||||||
Position[0] -= ALContext->Listener.Position[0];
|
Position[0] -= ALContext->Listener.Position[0];
|
||||||
Position[1] -= ALContext->Listener.Position[1];
|
Position[1] -= ALContext->Listener.Position[1];
|
||||||
@ -445,12 +472,17 @@ ALvoid CalcSourceParams(ALsource *ALSource, const ALCcontext *ALContext)
|
|||||||
aluMatrixVector(Position, 1.0f, Matrix);
|
aluMatrixVector(Position, 1.0f, Matrix);
|
||||||
aluMatrixVector(Direction, 0.0f, Matrix);
|
aluMatrixVector(Direction, 0.0f, Matrix);
|
||||||
aluMatrixVector(Velocity, 0.0f, Matrix);
|
aluMatrixVector(Velocity, 0.0f, Matrix);
|
||||||
|
/* Transform listener velocity into listener space */
|
||||||
|
aluMatrixVector(ListenerVel, 0.0f, Matrix);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
ListenerVel[0] = 0.0f;
|
/* Transform listener velocity into listener space */
|
||||||
ListenerVel[1] = 0.0f;
|
aluMatrixVector(ListenerVel, 0.0f, Matrix);
|
||||||
ListenerVel[2] = 0.0f;
|
/* Offset the source velocity to be relative of the listener velocity */
|
||||||
|
Velocity[0] += ListenerVel[0];
|
||||||
|
Velocity[1] += ListenerVel[1];
|
||||||
|
Velocity[2] += ListenerVel[2];
|
||||||
}
|
}
|
||||||
|
|
||||||
SourceToListener[0] = -Position[0];
|
SourceToListener[0] = -Position[0];
|
||||||
@ -605,26 +637,15 @@ ALvoid CalcSourceParams(ALsource *ALSource, const ALCcontext *ALContext)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Calculate Velocity
|
// Calculate Velocity
|
||||||
if(DopplerFactor != 0.0f)
|
if(DopplerFactor > 0.0f && SpeedOfSound > 0.5f)
|
||||||
{
|
{
|
||||||
ALfloat VSS, VLS;
|
ALfloat VSS, VLS;
|
||||||
ALfloat MaxVelocity = (SpeedOfSound*DopplerVelocity) /
|
|
||||||
DopplerFactor;
|
|
||||||
|
|
||||||
VSS = aluDotproduct(Velocity, SourceToListener);
|
VSS = aluDotproduct(Velocity, SourceToListener) * DopplerFactor;
|
||||||
if(VSS >= MaxVelocity)
|
VLS = aluDotproduct(ListenerVel, SourceToListener) * DopplerFactor;
|
||||||
VSS = (MaxVelocity - 1.0f);
|
|
||||||
else if(VSS <= -MaxVelocity)
|
|
||||||
VSS = -MaxVelocity + 1.0f;
|
|
||||||
|
|
||||||
VLS = aluDotproduct(ListenerVel, SourceToListener);
|
Pitch *= clampf(SpeedOfSound-VLS, 1.0f, SpeedOfSound*2.0f - 1.0f) /
|
||||||
if(VLS >= MaxVelocity)
|
clampf(SpeedOfSound-VSS, 1.0f, SpeedOfSound*2.0f - 1.0f);
|
||||||
VLS = (MaxVelocity - 1.0f);
|
|
||||||
else if(VLS <= -MaxVelocity)
|
|
||||||
VLS = -MaxVelocity + 1.0f;
|
|
||||||
|
|
||||||
Pitch *= ((SpeedOfSound*DopplerVelocity) - (DopplerFactor*VLS)) /
|
|
||||||
((SpeedOfSound*DopplerVelocity) - (DopplerFactor*VSS));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
BufferListItem = ALSource->queue;
|
BufferListItem = ALSource->queue;
|
||||||
@ -633,8 +654,8 @@ ALvoid CalcSourceParams(ALsource *ALSource, const ALCcontext *ALContext)
|
|||||||
ALbuffer *ALBuffer;
|
ALbuffer *ALBuffer;
|
||||||
if((ALBuffer=BufferListItem->buffer) != NULL)
|
if((ALBuffer=BufferListItem->buffer) != NULL)
|
||||||
{
|
{
|
||||||
ALint maxstep = STACK_DATA_SIZE / ALSource->NumChannels /
|
ALsizei maxstep = STACK_DATA_SIZE/sizeof(ALfloat) /
|
||||||
ALSource->SampleSize;
|
ALSource->NumChannels;
|
||||||
maxstep -= ResamplerPadding[Resampler] +
|
maxstep -= ResamplerPadding[Resampler] +
|
||||||
ResamplerPrePadding[Resampler] + 1;
|
ResamplerPrePadding[Resampler] + 1;
|
||||||
maxstep = mini(maxstep, INT_MAX>>FRACTIONBITS);
|
maxstep = mini(maxstep, INT_MAX>>FRACTIONBITS);
|
||||||
@ -648,17 +669,17 @@ ALvoid CalcSourceParams(ALsource *ALSource, const ALCcontext *ALContext)
|
|||||||
if(ALSource->Params.Step == 0)
|
if(ALSource->Params.Step == 0)
|
||||||
ALSource->Params.Step = 1;
|
ALSource->Params.Step = 1;
|
||||||
}
|
}
|
||||||
|
if(ALSource->Params.Step == FRACTIONONE)
|
||||||
|
Resampler = PointResampler;
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
BufferListItem = BufferListItem->next;
|
BufferListItem = BufferListItem->next;
|
||||||
}
|
}
|
||||||
if(Device->Hrtf)
|
if(Device->Hrtf)
|
||||||
ALSource->Params.DoMix = SelectHrtfMixer((ALSource->Params.Step==FRACTIONONE) ?
|
ALSource->Params.DoMix = SelectHrtfMixer(Resampler);
|
||||||
POINT_RESAMPLER : Resampler);
|
|
||||||
else
|
else
|
||||||
ALSource->Params.DoMix = SelectMixer((ALSource->Params.Step==FRACTIONONE) ?
|
ALSource->Params.DoMix = SelectMixer(Resampler);
|
||||||
POINT_RESAMPLER : Resampler);
|
|
||||||
|
|
||||||
if(Device->Hrtf)
|
if(Device->Hrtf)
|
||||||
{
|
{
|
||||||
@ -719,7 +740,7 @@ ALvoid CalcSourceParams(ALsource *ALSource, const ALCcontext *ALContext)
|
|||||||
{
|
{
|
||||||
// Use energy-preserving panning algorithm for multi-speaker playback
|
// Use energy-preserving panning algorithm for multi-speaker playback
|
||||||
ALfloat DirGain, AmbientGain;
|
ALfloat DirGain, AmbientGain;
|
||||||
const ALfloat *SpeakerGain;
|
const ALfloat *ChannelGain;
|
||||||
ALfloat length;
|
ALfloat length;
|
||||||
ALint pos;
|
ALint pos;
|
||||||
|
|
||||||
@ -733,7 +754,7 @@ ALvoid CalcSourceParams(ALsource *ALSource, const ALCcontext *ALContext)
|
|||||||
}
|
}
|
||||||
|
|
||||||
pos = aluCart2LUTpos(-Position[2]*ZScale, Position[0]);
|
pos = aluCart2LUTpos(-Position[2]*ZScale, Position[0]);
|
||||||
SpeakerGain = Device->PanningLUT[pos];
|
ChannelGain = Device->PanningLUT[pos];
|
||||||
|
|
||||||
DirGain = aluSqrt(Position[0]*Position[0] + Position[2]*Position[2]);
|
DirGain = aluSqrt(Position[0]*Position[0] + Position[2]*Position[2]);
|
||||||
// elevation adjustment for directional gain. this sucks, but
|
// elevation adjustment for directional gain. this sucks, but
|
||||||
@ -748,7 +769,7 @@ ALvoid CalcSourceParams(ALsource *ALSource, const ALCcontext *ALContext)
|
|||||||
for(i = 0;i < (ALint)Device->NumChan;i++)
|
for(i = 0;i < (ALint)Device->NumChan;i++)
|
||||||
{
|
{
|
||||||
enum Channel chan = Device->Speaker2Chan[i];
|
enum Channel chan = Device->Speaker2Chan[i];
|
||||||
ALfloat gain = lerp(AmbientGain, SpeakerGain[chan], DirGain);
|
ALfloat gain = lerp(AmbientGain, ChannelGain[chan], DirGain);
|
||||||
ALSource->Params.DryGains[0][chan] = DryGain * gain;
|
ALSource->Params.DryGains[0][chan] = DryGain * gain;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -769,18 +790,22 @@ ALvoid CalcSourceParams(ALsource *ALSource, const ALCcontext *ALContext)
|
|||||||
|
|
||||||
static __inline ALfloat aluF2F(ALfloat val)
|
static __inline ALfloat aluF2F(ALfloat val)
|
||||||
{ return val; }
|
{ return val; }
|
||||||
static __inline ALshort aluF2S(ALfloat val)
|
static __inline ALint aluF2I(ALfloat val)
|
||||||
{
|
{
|
||||||
if(val > 1.0f) return 32767;
|
if(val > 1.0f) return 2147483647;
|
||||||
if(val < -1.0f) return -32768;
|
if(val < -1.0f) return -2147483647-1;
|
||||||
return fastf2i(val*32767.0f);
|
return fastf2i((ALfloat)(val*2147483647.0));
|
||||||
}
|
}
|
||||||
|
static __inline ALuint aluF2UI(ALfloat val)
|
||||||
|
{ return aluF2I(val)+2147483648u; }
|
||||||
|
static __inline ALshort aluF2S(ALfloat val)
|
||||||
|
{ return aluF2I(val)>>16; }
|
||||||
static __inline ALushort aluF2US(ALfloat val)
|
static __inline ALushort aluF2US(ALfloat val)
|
||||||
{ return aluF2S(val)+32768; }
|
{ return aluF2S(val)+32768; }
|
||||||
static __inline ALbyte aluF2B(ALfloat val)
|
static __inline ALbyte aluF2B(ALfloat val)
|
||||||
{ return aluF2S(val)>>8; }
|
{ return aluF2I(val)>>24; }
|
||||||
static __inline ALubyte aluF2UB(ALfloat val)
|
static __inline ALubyte aluF2UB(ALfloat val)
|
||||||
{ return aluF2US(val)>>8; }
|
{ return aluF2B(val)+128; }
|
||||||
|
|
||||||
#define DECL_TEMPLATE(T, N, func) \
|
#define DECL_TEMPLATE(T, N, func) \
|
||||||
static void Write_##T##_##N(ALCdevice *device, T *RESTRICT buffer, \
|
static void Write_##T##_##N(ALCdevice *device, T *RESTRICT buffer, \
|
||||||
@ -790,38 +815,60 @@ static void Write_##T##_##N(ALCdevice *device, T *RESTRICT buffer, \
|
|||||||
const enum Channel *ChanMap = device->DevChannels; \
|
const enum Channel *ChanMap = device->DevChannels; \
|
||||||
ALuint i, j; \
|
ALuint i, j; \
|
||||||
\
|
\
|
||||||
for(i = 0;i < SamplesToDo;i++) \
|
for(j = 0;j < N;j++) \
|
||||||
{ \
|
{ \
|
||||||
for(j = 0;j < N;j++) \
|
T *RESTRICT out = buffer + j; \
|
||||||
*(buffer++) = func(DryBuffer[i][ChanMap[j]]); \
|
enum Channel chan = ChanMap[j]; \
|
||||||
|
\
|
||||||
|
for(i = 0;i < SamplesToDo;i++) \
|
||||||
|
out[i*N] = func(DryBuffer[i][chan]); \
|
||||||
} \
|
} \
|
||||||
}
|
}
|
||||||
|
|
||||||
DECL_TEMPLATE(ALfloat, 1, aluF2F)
|
DECL_TEMPLATE(ALfloat, 1, aluF2F)
|
||||||
|
DECL_TEMPLATE(ALfloat, 2, aluF2F)
|
||||||
DECL_TEMPLATE(ALfloat, 4, aluF2F)
|
DECL_TEMPLATE(ALfloat, 4, aluF2F)
|
||||||
DECL_TEMPLATE(ALfloat, 6, aluF2F)
|
DECL_TEMPLATE(ALfloat, 6, aluF2F)
|
||||||
DECL_TEMPLATE(ALfloat, 7, aluF2F)
|
DECL_TEMPLATE(ALfloat, 7, aluF2F)
|
||||||
DECL_TEMPLATE(ALfloat, 8, aluF2F)
|
DECL_TEMPLATE(ALfloat, 8, aluF2F)
|
||||||
|
|
||||||
|
DECL_TEMPLATE(ALuint, 1, aluF2UI)
|
||||||
|
DECL_TEMPLATE(ALuint, 2, aluF2UI)
|
||||||
|
DECL_TEMPLATE(ALuint, 4, aluF2UI)
|
||||||
|
DECL_TEMPLATE(ALuint, 6, aluF2UI)
|
||||||
|
DECL_TEMPLATE(ALuint, 7, aluF2UI)
|
||||||
|
DECL_TEMPLATE(ALuint, 8, aluF2UI)
|
||||||
|
|
||||||
|
DECL_TEMPLATE(ALint, 1, aluF2I)
|
||||||
|
DECL_TEMPLATE(ALint, 2, aluF2I)
|
||||||
|
DECL_TEMPLATE(ALint, 4, aluF2I)
|
||||||
|
DECL_TEMPLATE(ALint, 6, aluF2I)
|
||||||
|
DECL_TEMPLATE(ALint, 7, aluF2I)
|
||||||
|
DECL_TEMPLATE(ALint, 8, aluF2I)
|
||||||
|
|
||||||
DECL_TEMPLATE(ALushort, 1, aluF2US)
|
DECL_TEMPLATE(ALushort, 1, aluF2US)
|
||||||
|
DECL_TEMPLATE(ALushort, 2, aluF2US)
|
||||||
DECL_TEMPLATE(ALushort, 4, aluF2US)
|
DECL_TEMPLATE(ALushort, 4, aluF2US)
|
||||||
DECL_TEMPLATE(ALushort, 6, aluF2US)
|
DECL_TEMPLATE(ALushort, 6, aluF2US)
|
||||||
DECL_TEMPLATE(ALushort, 7, aluF2US)
|
DECL_TEMPLATE(ALushort, 7, aluF2US)
|
||||||
DECL_TEMPLATE(ALushort, 8, aluF2US)
|
DECL_TEMPLATE(ALushort, 8, aluF2US)
|
||||||
|
|
||||||
DECL_TEMPLATE(ALshort, 1, aluF2S)
|
DECL_TEMPLATE(ALshort, 1, aluF2S)
|
||||||
|
DECL_TEMPLATE(ALshort, 2, aluF2S)
|
||||||
DECL_TEMPLATE(ALshort, 4, aluF2S)
|
DECL_TEMPLATE(ALshort, 4, aluF2S)
|
||||||
DECL_TEMPLATE(ALshort, 6, aluF2S)
|
DECL_TEMPLATE(ALshort, 6, aluF2S)
|
||||||
DECL_TEMPLATE(ALshort, 7, aluF2S)
|
DECL_TEMPLATE(ALshort, 7, aluF2S)
|
||||||
DECL_TEMPLATE(ALshort, 8, aluF2S)
|
DECL_TEMPLATE(ALshort, 8, aluF2S)
|
||||||
|
|
||||||
DECL_TEMPLATE(ALubyte, 1, aluF2UB)
|
DECL_TEMPLATE(ALubyte, 1, aluF2UB)
|
||||||
|
DECL_TEMPLATE(ALubyte, 2, aluF2UB)
|
||||||
DECL_TEMPLATE(ALubyte, 4, aluF2UB)
|
DECL_TEMPLATE(ALubyte, 4, aluF2UB)
|
||||||
DECL_TEMPLATE(ALubyte, 6, aluF2UB)
|
DECL_TEMPLATE(ALubyte, 6, aluF2UB)
|
||||||
DECL_TEMPLATE(ALubyte, 7, aluF2UB)
|
DECL_TEMPLATE(ALubyte, 7, aluF2UB)
|
||||||
DECL_TEMPLATE(ALubyte, 8, aluF2UB)
|
DECL_TEMPLATE(ALubyte, 8, aluF2UB)
|
||||||
|
|
||||||
DECL_TEMPLATE(ALbyte, 1, aluF2B)
|
DECL_TEMPLATE(ALbyte, 1, aluF2B)
|
||||||
|
DECL_TEMPLATE(ALbyte, 2, aluF2B)
|
||||||
DECL_TEMPLATE(ALbyte, 4, aluF2B)
|
DECL_TEMPLATE(ALbyte, 4, aluF2B)
|
||||||
DECL_TEMPLATE(ALbyte, 6, aluF2B)
|
DECL_TEMPLATE(ALbyte, 6, aluF2B)
|
||||||
DECL_TEMPLATE(ALbyte, 7, aluF2B)
|
DECL_TEMPLATE(ALbyte, 7, aluF2B)
|
||||||
@ -829,44 +876,6 @@ DECL_TEMPLATE(ALbyte, 8, aluF2B)
|
|||||||
|
|
||||||
#undef DECL_TEMPLATE
|
#undef DECL_TEMPLATE
|
||||||
|
|
||||||
#define DECL_TEMPLATE(T, N, func) \
|
|
||||||
static void Write_##T##_##N(ALCdevice *device, T *RESTRICT buffer, \
|
|
||||||
ALuint SamplesToDo) \
|
|
||||||
{ \
|
|
||||||
ALfloat (*RESTRICT DryBuffer)[MAXCHANNELS] = device->DryBuffer; \
|
|
||||||
const enum Channel *ChanMap = device->DevChannels; \
|
|
||||||
ALuint i, j; \
|
|
||||||
\
|
|
||||||
if(device->Bs2b) \
|
|
||||||
{ \
|
|
||||||
for(i = 0;i < SamplesToDo;i++) \
|
|
||||||
{ \
|
|
||||||
float samples[2]; \
|
|
||||||
samples[0] = DryBuffer[i][ChanMap[0]]; \
|
|
||||||
samples[1] = DryBuffer[i][ChanMap[1]]; \
|
|
||||||
bs2b_cross_feed(device->Bs2b, samples); \
|
|
||||||
*(buffer++) = func(samples[0]); \
|
|
||||||
*(buffer++) = func(samples[1]); \
|
|
||||||
} \
|
|
||||||
} \
|
|
||||||
else \
|
|
||||||
{ \
|
|
||||||
for(i = 0;i < SamplesToDo;i++) \
|
|
||||||
{ \
|
|
||||||
for(j = 0;j < N;j++) \
|
|
||||||
*(buffer++) = func(DryBuffer[i][ChanMap[j]]); \
|
|
||||||
} \
|
|
||||||
} \
|
|
||||||
}
|
|
||||||
|
|
||||||
DECL_TEMPLATE(ALfloat, 2, aluF2F)
|
|
||||||
DECL_TEMPLATE(ALushort, 2, aluF2US)
|
|
||||||
DECL_TEMPLATE(ALshort, 2, aluF2S)
|
|
||||||
DECL_TEMPLATE(ALubyte, 2, aluF2UB)
|
|
||||||
DECL_TEMPLATE(ALbyte, 2, aluF2B)
|
|
||||||
|
|
||||||
#undef DECL_TEMPLATE
|
|
||||||
|
|
||||||
#define DECL_TEMPLATE(T) \
|
#define DECL_TEMPLATE(T) \
|
||||||
static void Write_##T(ALCdevice *device, T *buffer, ALuint SamplesToDo) \
|
static void Write_##T(ALCdevice *device, T *buffer, ALuint SamplesToDo) \
|
||||||
{ \
|
{ \
|
||||||
@ -895,6 +904,8 @@ static void Write_##T(ALCdevice *device, T *buffer, ALuint SamplesToDo) \
|
|||||||
}
|
}
|
||||||
|
|
||||||
DECL_TEMPLATE(ALfloat)
|
DECL_TEMPLATE(ALfloat)
|
||||||
|
DECL_TEMPLATE(ALuint)
|
||||||
|
DECL_TEMPLATE(ALint)
|
||||||
DECL_TEMPLATE(ALushort)
|
DECL_TEMPLATE(ALushort)
|
||||||
DECL_TEMPLATE(ALshort)
|
DECL_TEMPLATE(ALshort)
|
||||||
DECL_TEMPLATE(ALubyte)
|
DECL_TEMPLATE(ALubyte)
|
||||||
@ -977,6 +988,27 @@ ALvoid aluMixData(ALCdevice *device, ALvoid *buffer, ALsizei size)
|
|||||||
|
|
||||||
ctx = ctx->next;
|
ctx = ctx->next;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
slot = &device->DefaultSlot;
|
||||||
|
if(*slot != NULL)
|
||||||
|
{
|
||||||
|
for(c = 0;c < SamplesToDo;c++)
|
||||||
|
{
|
||||||
|
(*slot)->WetBuffer[c] += (*slot)->ClickRemoval[0];
|
||||||
|
(*slot)->ClickRemoval[0] -= (*slot)->ClickRemoval[0] * (1.0f/256.0f);
|
||||||
|
}
|
||||||
|
(*slot)->ClickRemoval[0] += (*slot)->PendingClicks[0];
|
||||||
|
(*slot)->PendingClicks[0] = 0.0f;
|
||||||
|
|
||||||
|
if(ExchangeInt(&(*slot)->NeedsUpdate, AL_FALSE))
|
||||||
|
ALeffectState_Update((*slot)->EffectState, ctx, *slot);
|
||||||
|
|
||||||
|
ALeffectState_Process((*slot)->EffectState, SamplesToDo,
|
||||||
|
(*slot)->WetBuffer, device->DryBuffer);
|
||||||
|
|
||||||
|
for(i = 0;i < SamplesToDo;i++)
|
||||||
|
(*slot)->WetBuffer[i] = 0.0f;
|
||||||
|
}
|
||||||
UnlockDevice(device);
|
UnlockDevice(device);
|
||||||
|
|
||||||
//Post processing loop
|
//Post processing loop
|
||||||
@ -1006,6 +1038,11 @@ ALvoid aluMixData(ALCdevice *device, ALvoid *buffer, ALsizei size)
|
|||||||
device->ClickRemoval[c] += device->PendingClicks[c];
|
device->ClickRemoval[c] += device->PendingClicks[c];
|
||||||
device->PendingClicks[c] = 0.0f;
|
device->PendingClicks[c] = 0.0f;
|
||||||
}
|
}
|
||||||
|
if(device->Bs2b)
|
||||||
|
{
|
||||||
|
for(i = 0;i < SamplesToDo;i++)
|
||||||
|
bs2b_cross_feed(device->Bs2b, &device->DryBuffer[i][0]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -1040,6 +1077,12 @@ ALvoid aluMixData(ALCdevice *device, ALvoid *buffer, ALsizei size)
|
|||||||
case DevFmtUShort:
|
case DevFmtUShort:
|
||||||
Write_ALushort(device, buffer, SamplesToDo);
|
Write_ALushort(device, buffer, SamplesToDo);
|
||||||
break;
|
break;
|
||||||
|
case DevFmtInt:
|
||||||
|
Write_ALint(device, buffer, SamplesToDo);
|
||||||
|
break;
|
||||||
|
case DevFmtUInt:
|
||||||
|
Write_ALuint(device, buffer, SamplesToDo);
|
||||||
|
break;
|
||||||
case DevFmtFloat:
|
case DevFmtFloat:
|
||||||
Write_ALfloat(device, buffer, SamplesToDo);
|
Write_ALfloat(device, buffer, SamplesToDo);
|
||||||
break;
|
break;
|
||||||
|
@ -54,7 +54,7 @@ static ALvoid DedicatedUpdate(ALeffectState *effect, ALCcontext *Context, const
|
|||||||
{
|
{
|
||||||
ALdedicatedState *state = (ALdedicatedState*)effect;
|
ALdedicatedState *state = (ALdedicatedState*)effect;
|
||||||
ALCdevice *device = Context->Device;
|
ALCdevice *device = Context->Device;
|
||||||
const ALfloat *SpeakerGain;
|
const ALfloat *ChannelGain;
|
||||||
ALfloat Gain;
|
ALfloat Gain;
|
||||||
ALint pos;
|
ALint pos;
|
||||||
ALsizei s;
|
ALsizei s;
|
||||||
@ -66,10 +66,10 @@ static ALvoid DedicatedUpdate(ALeffectState *effect, ALCcontext *Context, const
|
|||||||
if(Slot->effect.type == AL_EFFECT_DEDICATED_DIALOGUE)
|
if(Slot->effect.type == AL_EFFECT_DEDICATED_DIALOGUE)
|
||||||
{
|
{
|
||||||
pos = aluCart2LUTpos(1.0f, 0.0f);
|
pos = aluCart2LUTpos(1.0f, 0.0f);
|
||||||
SpeakerGain = device->PanningLUT[pos];
|
ChannelGain = device->PanningLUT[pos];
|
||||||
|
|
||||||
for(s = 0;s < MAXCHANNELS;s++)
|
for(s = 0;s < MAXCHANNELS;s++)
|
||||||
state->gains[s] = SpeakerGain[s] * Gain;
|
state->gains[s] = ChannelGain[s] * Gain;
|
||||||
}
|
}
|
||||||
else if(Slot->effect.type == AL_EFFECT_DEDICATED_LOW_FREQUENCY_EFFECT)
|
else if(Slot->effect.type == AL_EFFECT_DEDICATED_LOW_FREQUENCY_EFFECT)
|
||||||
state->gains[LFE] = Gain;
|
state->gains[LFE] = Gain;
|
||||||
|
@ -96,7 +96,7 @@ static ALvoid EchoUpdate(ALeffectState *effect, ALCcontext *Context, const ALeff
|
|||||||
ALCdevice *Device = Context->Device;
|
ALCdevice *Device = Context->Device;
|
||||||
ALuint frequency = Device->Frequency;
|
ALuint frequency = Device->Frequency;
|
||||||
ALfloat dirGain, ambientGain;
|
ALfloat dirGain, ambientGain;
|
||||||
const ALfloat *speakerGain;
|
const ALfloat *ChannelGain;
|
||||||
ALfloat lrpan, cw, g, gain;
|
ALfloat lrpan, cw, g, gain;
|
||||||
ALuint i, pos;
|
ALuint i, pos;
|
||||||
|
|
||||||
@ -124,22 +124,22 @@ static ALvoid EchoUpdate(ALeffectState *effect, ALCcontext *Context, const ALeff
|
|||||||
|
|
||||||
/* First tap panning */
|
/* First tap panning */
|
||||||
pos = aluCart2LUTpos(0.0f, ((lrpan>0.0f)?-1.0f:1.0f));
|
pos = aluCart2LUTpos(0.0f, ((lrpan>0.0f)?-1.0f:1.0f));
|
||||||
speakerGain = Device->PanningLUT[pos];
|
ChannelGain = Device->PanningLUT[pos];
|
||||||
|
|
||||||
for(i = 0;i < Device->NumChan;i++)
|
for(i = 0;i < Device->NumChan;i++)
|
||||||
{
|
{
|
||||||
enum Channel chan = Device->Speaker2Chan[i];
|
enum Channel chan = Device->Speaker2Chan[i];
|
||||||
state->Gain[0][chan] = lerp(ambientGain, speakerGain[chan], dirGain) * gain;
|
state->Gain[0][chan] = lerp(ambientGain, ChannelGain[chan], dirGain) * gain;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Second tap panning */
|
/* Second tap panning */
|
||||||
pos = aluCart2LUTpos(0.0f, ((lrpan>0.0f)?1.0f:-1.0f));
|
pos = aluCart2LUTpos(0.0f, ((lrpan>0.0f)?1.0f:-1.0f));
|
||||||
speakerGain = Device->PanningLUT[pos];
|
ChannelGain = Device->PanningLUT[pos];
|
||||||
|
|
||||||
for(i = 0;i < Device->NumChan;i++)
|
for(i = 0;i < Device->NumChan;i++)
|
||||||
{
|
{
|
||||||
enum Channel chan = Device->Speaker2Chan[i];
|
enum Channel chan = Device->Speaker2Chan[i];
|
||||||
state->Gain[1][chan] = lerp(ambientGain, speakerGain[chan], dirGain) * gain;
|
state->Gain[1][chan] = lerp(ambientGain, ChannelGain[chan], dirGain) * gain;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1016,7 +1016,7 @@ static ALvoid Update3DPanning(const ALCdevice *Device, const ALfloat *Reflection
|
|||||||
ReflectionsPan[2] };
|
ReflectionsPan[2] };
|
||||||
ALfloat latePan[3] = { LateReverbPan[0], LateReverbPan[1],
|
ALfloat latePan[3] = { LateReverbPan[0], LateReverbPan[1],
|
||||||
LateReverbPan[2] };
|
LateReverbPan[2] };
|
||||||
const ALfloat *speakerGain;
|
const ALfloat *ChannelGain;
|
||||||
ALfloat ambientGain;
|
ALfloat ambientGain;
|
||||||
ALfloat dirGain;
|
ALfloat dirGain;
|
||||||
ALfloat length;
|
ALfloat length;
|
||||||
@ -1054,7 +1054,7 @@ static ALvoid Update3DPanning(const ALCdevice *Device, const ALfloat *Reflection
|
|||||||
* panning direction.
|
* panning direction.
|
||||||
*/
|
*/
|
||||||
pos = aluCart2LUTpos(earlyPan[2], earlyPan[0]);
|
pos = aluCart2LUTpos(earlyPan[2], earlyPan[0]);
|
||||||
speakerGain = Device->PanningLUT[pos];
|
ChannelGain = Device->PanningLUT[pos];
|
||||||
dirGain = aluSqrt((earlyPan[0] * earlyPan[0]) + (earlyPan[2] * earlyPan[2]));
|
dirGain = aluSqrt((earlyPan[0] * earlyPan[0]) + (earlyPan[2] * earlyPan[2]));
|
||||||
|
|
||||||
for(index = 0;index < MAXCHANNELS;index++)
|
for(index = 0;index < MAXCHANNELS;index++)
|
||||||
@ -1062,12 +1062,12 @@ static ALvoid Update3DPanning(const ALCdevice *Device, const ALfloat *Reflection
|
|||||||
for(index = 0;index < Device->NumChan;index++)
|
for(index = 0;index < Device->NumChan;index++)
|
||||||
{
|
{
|
||||||
enum Channel chan = Device->Speaker2Chan[index];
|
enum Channel chan = Device->Speaker2Chan[index];
|
||||||
State->Early.PanGain[chan] = lerp(ambientGain, speakerGain[chan], dirGain) * Gain;
|
State->Early.PanGain[chan] = lerp(ambientGain, ChannelGain[chan], dirGain) * Gain;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
pos = aluCart2LUTpos(latePan[2], latePan[0]);
|
pos = aluCart2LUTpos(latePan[2], latePan[0]);
|
||||||
speakerGain = Device->PanningLUT[pos];
|
ChannelGain = Device->PanningLUT[pos];
|
||||||
dirGain = aluSqrt((latePan[0] * latePan[0]) + (latePan[2] * latePan[2]));
|
dirGain = aluSqrt((latePan[0] * latePan[0]) + (latePan[2] * latePan[2]));
|
||||||
|
|
||||||
for(index = 0;index < MAXCHANNELS;index++)
|
for(index = 0;index < MAXCHANNELS;index++)
|
||||||
@ -1075,7 +1075,7 @@ static ALvoid Update3DPanning(const ALCdevice *Device, const ALfloat *Reflection
|
|||||||
for(index = 0;index < Device->NumChan;index++)
|
for(index = 0;index < Device->NumChan;index++)
|
||||||
{
|
{
|
||||||
enum Channel chan = Device->Speaker2Chan[index];
|
enum Channel chan = Device->Speaker2Chan[index];
|
||||||
State->Late.PanGain[chan] = lerp(ambientGain, speakerGain[chan], dirGain) * Gain;
|
State->Late.PanGain[chan] = lerp(ambientGain, ChannelGain[chan], dirGain) * Gain;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -173,6 +173,17 @@ static ALCenum ca_open_playback(ALCdevice *device, const ALCchar *deviceName)
|
|||||||
return ALC_INVALID_VALUE;
|
return ALC_INVALID_VALUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* init and start the default audio unit... */
|
||||||
|
err = AudioUnitInitialize(data->audioUnit);
|
||||||
|
if(err != noErr)
|
||||||
|
{
|
||||||
|
ERR("AudioUnitInitialize failed\n");
|
||||||
|
CloseComponent(data->audioUnit);
|
||||||
|
free(data);
|
||||||
|
device->ExtraData = NULL;
|
||||||
|
return ALC_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
return ALC_NO_ERROR;
|
return ALC_NO_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -180,6 +191,7 @@ static void ca_close_playback(ALCdevice *device)
|
|||||||
{
|
{
|
||||||
ca_data *data = (ca_data*)device->ExtraData;
|
ca_data *data = (ca_data*)device->ExtraData;
|
||||||
|
|
||||||
|
AudioUnitUninitialize(data->audioUnit);
|
||||||
CloseComponent(data->audioUnit);
|
CloseComponent(data->audioUnit);
|
||||||
|
|
||||||
free(data);
|
free(data);
|
||||||
@ -194,20 +206,9 @@ static ALCboolean ca_reset_playback(ALCdevice *device)
|
|||||||
OSStatus err;
|
OSStatus err;
|
||||||
UInt32 size;
|
UInt32 size;
|
||||||
|
|
||||||
/* init and start the default audio unit... */
|
err = AudioUnitUninitialize(data->audioUnit);
|
||||||
err = AudioUnitInitialize(data->audioUnit);
|
|
||||||
if(err != noErr)
|
if(err != noErr)
|
||||||
{
|
ERR("-- AudioUnitUninitialize failed.\n");
|
||||||
ERR("AudioUnitInitialize failed\n");
|
|
||||||
return ALC_FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
err = AudioOutputUnitStart(data->audioUnit);
|
|
||||||
if(err != noErr)
|
|
||||||
{
|
|
||||||
ERR("AudioOutputUnitStart failed\n");
|
|
||||||
return ALC_FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* retrieve default output unit's properties (output side) */
|
/* retrieve default output unit's properties (output side) */
|
||||||
size = sizeof(AudioStreamBasicDescription);
|
size = sizeof(AudioStreamBasicDescription);
|
||||||
@ -238,10 +239,6 @@ static ALCboolean ca_reset_playback(ALCdevice *device)
|
|||||||
|
|
||||||
if(device->Frequency != streamFormat.mSampleRate)
|
if(device->Frequency != streamFormat.mSampleRate)
|
||||||
{
|
{
|
||||||
if((device->Flags&DEVICE_FREQUENCY_REQUEST))
|
|
||||||
ERR("CoreAudio does not support changing sample rates (wanted %dhz, got %dhz)\n", device->Frequency, streamFormat.mSampleRate);
|
|
||||||
device->Flags &= ~DEVICE_FREQUENCY_REQUEST;
|
|
||||||
|
|
||||||
device->UpdateSize = (ALuint)((ALuint64)device->UpdateSize *
|
device->UpdateSize = (ALuint)((ALuint64)device->UpdateSize *
|
||||||
streamFormat.mSampleRate /
|
streamFormat.mSampleRate /
|
||||||
device->Frequency);
|
device->Frequency);
|
||||||
@ -253,62 +250,25 @@ static ALCboolean ca_reset_playback(ALCdevice *device)
|
|||||||
switch(streamFormat.mChannelsPerFrame)
|
switch(streamFormat.mChannelsPerFrame)
|
||||||
{
|
{
|
||||||
case 1:
|
case 1:
|
||||||
if((device->Flags&DEVICE_CHANNELS_REQUEST) &&
|
|
||||||
device->FmtChans != DevFmtMono)
|
|
||||||
{
|
|
||||||
ERR("Failed to set %s, got Mono instead\n", DevFmtChannelsString(device->FmtChans));
|
|
||||||
device->Flags &= ~DEVICE_CHANNELS_REQUEST;
|
|
||||||
}
|
|
||||||
device->FmtChans = DevFmtMono;
|
device->FmtChans = DevFmtMono;
|
||||||
break;
|
break;
|
||||||
case 2:
|
case 2:
|
||||||
if((device->Flags&DEVICE_CHANNELS_REQUEST) &&
|
|
||||||
device->FmtChans != DevFmtStereo)
|
|
||||||
{
|
|
||||||
ERR("Failed to set %s, got Stereo instead\n", DevFmtChannelsString(device->FmtChans));
|
|
||||||
device->Flags &= ~DEVICE_CHANNELS_REQUEST;
|
|
||||||
}
|
|
||||||
device->FmtChans = DevFmtStereo;
|
device->FmtChans = DevFmtStereo;
|
||||||
break;
|
break;
|
||||||
case 4:
|
case 4:
|
||||||
if((device->Flags&DEVICE_CHANNELS_REQUEST) &&
|
|
||||||
device->FmtChans != DevFmtQuad)
|
|
||||||
{
|
|
||||||
ERR("Failed to set %s, got Quad instead\n", DevFmtChannelsString(device->FmtChans));
|
|
||||||
device->Flags &= ~DEVICE_CHANNELS_REQUEST;
|
|
||||||
}
|
|
||||||
device->FmtChans = DevFmtQuad;
|
device->FmtChans = DevFmtQuad;
|
||||||
break;
|
break;
|
||||||
case 6:
|
case 6:
|
||||||
if((device->Flags&DEVICE_CHANNELS_REQUEST) &&
|
|
||||||
device->FmtChans != DevFmtX51)
|
|
||||||
{
|
|
||||||
ERR("Failed to set %s, got 5.1 Surround instead\n", DevFmtChannelsString(device->FmtChans));
|
|
||||||
device->Flags &= ~DEVICE_CHANNELS_REQUEST;
|
|
||||||
}
|
|
||||||
device->FmtChans = DevFmtX51;
|
device->FmtChans = DevFmtX51;
|
||||||
break;
|
break;
|
||||||
case 7:
|
case 7:
|
||||||
if((device->Flags&DEVICE_CHANNELS_REQUEST) &&
|
|
||||||
device->FmtChans != DevFmtX61)
|
|
||||||
{
|
|
||||||
ERR("Failed to set %s, got 6.1 Surround instead\n", DevFmtChannelsString(device->FmtChans));
|
|
||||||
device->Flags &= ~DEVICE_CHANNELS_REQUEST;
|
|
||||||
}
|
|
||||||
device->FmtChans = DevFmtX61;
|
device->FmtChans = DevFmtX61;
|
||||||
break;
|
break;
|
||||||
case 8:
|
case 8:
|
||||||
if((device->Flags&DEVICE_CHANNELS_REQUEST) &&
|
|
||||||
device->FmtChans != DevFmtX71)
|
|
||||||
{
|
|
||||||
ERR("Failed to set %s, got 7.1 Surround instead\n", DevFmtChannelsString(device->FmtChans));
|
|
||||||
device->Flags &= ~DEVICE_CHANNELS_REQUEST;
|
|
||||||
}
|
|
||||||
device->FmtChans = DevFmtX71;
|
device->FmtChans = DevFmtX71;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
ERR("Unhandled channel count (%d), using Stereo\n", streamFormat.mChannelsPerFrame);
|
ERR("Unhandled channel count (%d), using Stereo\n", streamFormat.mChannelsPerFrame);
|
||||||
device->Flags &= ~DEVICE_CHANNELS_REQUEST;
|
|
||||||
device->FmtChans = DevFmtStereo;
|
device->FmtChans = DevFmtStereo;
|
||||||
streamFormat.mChannelsPerFrame = 2;
|
streamFormat.mChannelsPerFrame = 2;
|
||||||
break;
|
break;
|
||||||
@ -337,6 +297,14 @@ static ALCboolean ca_reset_playback(ALCdevice *device)
|
|||||||
streamFormat.mBytesPerPacket = 2 * streamFormat.mChannelsPerFrame;
|
streamFormat.mBytesPerPacket = 2 * streamFormat.mChannelsPerFrame;
|
||||||
streamFormat.mBytesPerFrame = 2 * streamFormat.mChannelsPerFrame;
|
streamFormat.mBytesPerFrame = 2 * streamFormat.mChannelsPerFrame;
|
||||||
break;
|
break;
|
||||||
|
case DevFmtUInt:
|
||||||
|
device->FmtType = DevFmtInt;
|
||||||
|
/* fall-through */
|
||||||
|
case DevFmtInt:
|
||||||
|
streamFormat.mBitsPerChannel = 32;
|
||||||
|
streamFormat.mBytesPerPacket = 2 * streamFormat.mChannelsPerFrame;
|
||||||
|
streamFormat.mBytesPerFrame = 2 * streamFormat.mChannelsPerFrame;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
streamFormat.mFormatID = kAudioFormatLinearPCM;
|
streamFormat.mFormatID = kAudioFormatLinearPCM;
|
||||||
streamFormat.mFormatFlags = kLinearPCMFormatFlagIsSignedInteger |
|
streamFormat.mFormatFlags = kLinearPCMFormatFlagIsSignedInteger |
|
||||||
@ -362,6 +330,29 @@ static ALCboolean ca_reset_playback(ALCdevice *device)
|
|||||||
return ALC_FALSE;
|
return ALC_FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* init the default audio unit... */
|
||||||
|
err = AudioUnitInitialize(data->audioUnit);
|
||||||
|
if(err != noErr)
|
||||||
|
{
|
||||||
|
ERR("AudioUnitInitialize failed\n");
|
||||||
|
return ALC_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ALC_TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static ALCboolean ca_start_playback(ALCdevice *device)
|
||||||
|
{
|
||||||
|
ca_data *data = (ca_data*)device->ExtraData;
|
||||||
|
OSStatus err;
|
||||||
|
|
||||||
|
err = AudioOutputUnitStart(data->audioUnit);
|
||||||
|
if(err != noErr)
|
||||||
|
{
|
||||||
|
ERR("AudioOutputUnitStart failed\n");
|
||||||
|
return ALC_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
return ALC_TRUE;
|
return ALC_TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -370,10 +361,9 @@ static void ca_stop_playback(ALCdevice *device)
|
|||||||
ca_data *data = (ca_data*)device->ExtraData;
|
ca_data *data = (ca_data*)device->ExtraData;
|
||||||
OSStatus err;
|
OSStatus err;
|
||||||
|
|
||||||
AudioOutputUnitStop(data->audioUnit);
|
err = AudioOutputUnitStop(data->audioUnit);
|
||||||
err = AudioUnitUninitialize(data->audioUnit);
|
|
||||||
if(err != noErr)
|
if(err != noErr)
|
||||||
ERR("-- AudioUnitUninitialize failed.\n");
|
ERR("AudioOutputUnitStop failed\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
static ALCenum ca_open_capture(ALCdevice *device, const ALCchar *deviceName)
|
static ALCenum ca_open_capture(ALCdevice *device, const ALCchar *deviceName)
|
||||||
@ -496,12 +486,17 @@ static ALCenum ca_open_capture(ALCdevice *device, const ALCchar *deviceName)
|
|||||||
requestedFormat.mBitsPerChannel = 16;
|
requestedFormat.mBitsPerChannel = 16;
|
||||||
requestedFormat.mFormatFlags = kAudioFormatFlagIsSignedInteger | kAudioFormatFlagsNativeEndian | kAudioFormatFlagIsPacked;
|
requestedFormat.mFormatFlags = kAudioFormatFlagIsSignedInteger | kAudioFormatFlagsNativeEndian | kAudioFormatFlagIsPacked;
|
||||||
break;
|
break;
|
||||||
|
case DevFmtInt:
|
||||||
|
requestedFormat.mBitsPerChannel = 32;
|
||||||
|
requestedFormat.mFormatFlags = kAudioFormatFlagIsSignedInteger | kAudioFormatFlagsNativeEndian | kAudioFormatFlagIsPacked;
|
||||||
|
break;
|
||||||
case DevFmtFloat:
|
case DevFmtFloat:
|
||||||
requestedFormat.mBitsPerChannel = 32;
|
requestedFormat.mBitsPerChannel = 32;
|
||||||
requestedFormat.mFormatFlags = kAudioFormatFlagIsPacked;
|
requestedFormat.mFormatFlags = kAudioFormatFlagIsPacked;
|
||||||
break;
|
break;
|
||||||
case DevFmtByte:
|
case DevFmtByte:
|
||||||
case DevFmtUShort:
|
case DevFmtUShort:
|
||||||
|
case DevFmtUInt:
|
||||||
ERR("%s samples not supported\n", DevFmtTypeString(device->FmtType));
|
ERR("%s samples not supported\n", DevFmtTypeString(device->FmtType));
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
@ -673,6 +668,7 @@ static const BackendFuncs ca_funcs = {
|
|||||||
ca_open_playback,
|
ca_open_playback,
|
||||||
ca_close_playback,
|
ca_close_playback,
|
||||||
ca_reset_playback,
|
ca_reset_playback,
|
||||||
|
ca_start_playback,
|
||||||
ca_stop_playback,
|
ca_stop_playback,
|
||||||
ca_open_capture,
|
ca_open_capture,
|
||||||
ca_close_capture,
|
ca_close_capture,
|
||||||
@ -696,9 +692,6 @@ void alc_ca_probe(enum DevProbe type)
|
|||||||
{
|
{
|
||||||
switch(type)
|
switch(type)
|
||||||
{
|
{
|
||||||
case DEVICE_PROBE:
|
|
||||||
AppendDeviceList(ca_device);
|
|
||||||
break;
|
|
||||||
case ALL_DEVICE_PROBE:
|
case ALL_DEVICE_PROBE:
|
||||||
AppendAllDeviceList(ca_device);
|
AppendAllDeviceList(ca_device);
|
||||||
break;
|
break;
|
||||||
|
@ -47,12 +47,16 @@ DEFINE_GUID(KSDATAFORMAT_SUBTYPE_PCM, 0x00000001, 0x0000, 0x0010, 0x80, 0x00, 0x
|
|||||||
DEFINE_GUID(KSDATAFORMAT_SUBTYPE_IEEE_FLOAT, 0x00000003, 0x0000, 0x0010, 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71);
|
DEFINE_GUID(KSDATAFORMAT_SUBTYPE_IEEE_FLOAT, 0x00000003, 0x0000, 0x0010, 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71);
|
||||||
|
|
||||||
|
|
||||||
static HMODULE ds_handle;
|
static void *ds_handle;
|
||||||
static HRESULT (WINAPI *pDirectSoundCreate)(LPCGUID pcGuidDevice, IDirectSound **ppDS, IUnknown *pUnkOuter);
|
static HRESULT (WINAPI *pDirectSoundCreate)(LPCGUID pcGuidDevice, IDirectSound **ppDS, IUnknown *pUnkOuter);
|
||||||
static HRESULT (WINAPI *pDirectSoundEnumerateA)(LPDSENUMCALLBACKA pDSEnumCallback, void *pContext);
|
static HRESULT (WINAPI *pDirectSoundEnumerateA)(LPDSENUMCALLBACKA pDSEnumCallback, void *pContext);
|
||||||
|
static HRESULT (WINAPI *pDirectSoundCaptureCreate)(LPCGUID pcGuidDevice, IDirectSoundCapture **ppDSC, IUnknown *pUnkOuter);
|
||||||
|
static HRESULT (WINAPI *pDirectSoundCaptureEnumerateA)(LPDSENUMCALLBACKA pDSEnumCallback, void *pContext);
|
||||||
|
|
||||||
#define DirectSoundCreate pDirectSoundCreate
|
#define DirectSoundCreate pDirectSoundCreate
|
||||||
#define DirectSoundEnumerateA pDirectSoundEnumerateA
|
#define DirectSoundEnumerateA pDirectSoundEnumerateA
|
||||||
|
#define DirectSoundCaptureCreate pDirectSoundCaptureCreate
|
||||||
|
#define DirectSoundCaptureEnumerateA pDirectSoundCaptureEnumerateA
|
||||||
|
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
@ -65,7 +69,16 @@ typedef struct {
|
|||||||
|
|
||||||
volatile int killNow;
|
volatile int killNow;
|
||||||
ALvoid *thread;
|
ALvoid *thread;
|
||||||
} DSoundData;
|
} DSoundPlaybackData;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
// DirectSound Capture Device
|
||||||
|
IDirectSoundCapture *lpDSC;
|
||||||
|
IDirectSoundCaptureBuffer *DSCbuffer;
|
||||||
|
DWORD dwBufferBytes;
|
||||||
|
DWORD dwCursor;
|
||||||
|
RingBuffer *pRing;
|
||||||
|
} DSoundCaptureData;
|
||||||
|
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
@ -73,47 +86,47 @@ typedef struct {
|
|||||||
GUID guid;
|
GUID guid;
|
||||||
} DevMap;
|
} DevMap;
|
||||||
|
|
||||||
static const ALCchar dsDevice[] = "DirectSound Default";
|
static DevMap *PlaybackDeviceList;
|
||||||
static DevMap *DeviceList;
|
static ALuint NumPlaybackDevices;
|
||||||
static ALuint NumDevices;
|
static DevMap *CaptureDeviceList;
|
||||||
|
static ALuint NumCaptureDevices;
|
||||||
|
|
||||||
#define MAX_UPDATES 128
|
#define MAX_UPDATES 128
|
||||||
|
|
||||||
static ALCboolean DSoundLoad(void)
|
static ALCboolean DSoundLoad(void)
|
||||||
{
|
{
|
||||||
ALCboolean ok = ALC_TRUE;
|
|
||||||
if(!ds_handle)
|
if(!ds_handle)
|
||||||
{
|
{
|
||||||
ds_handle = LoadLibraryA("dsound.dll");
|
ds_handle = LoadLib("dsound.dll");
|
||||||
if(ds_handle == NULL)
|
if(ds_handle == NULL)
|
||||||
{
|
{
|
||||||
ERR("Failed to load dsound.dll\n");
|
ERR("Failed to load dsound.dll\n");
|
||||||
return ALC_FALSE;
|
return ALC_FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
#define LOAD_FUNC(x) do { \
|
#define LOAD_FUNC(f) do { \
|
||||||
if((p##x = (void*)GetProcAddress(ds_handle, #x)) == NULL) { \
|
p##f = GetSymbol(ds_handle, #f); \
|
||||||
ERR("Could not load %s from dsound.dll\n", #x); \
|
if(p##f == NULL) { \
|
||||||
ok = ALC_FALSE; \
|
CloseLib(ds_handle); \
|
||||||
|
ds_handle = NULL; \
|
||||||
|
return ALC_FALSE; \
|
||||||
} \
|
} \
|
||||||
} while(0)
|
} while(0)
|
||||||
LOAD_FUNC(DirectSoundCreate);
|
LOAD_FUNC(DirectSoundCreate);
|
||||||
LOAD_FUNC(DirectSoundEnumerateA);
|
LOAD_FUNC(DirectSoundEnumerateA);
|
||||||
|
LOAD_FUNC(DirectSoundCaptureCreate);
|
||||||
|
LOAD_FUNC(DirectSoundCaptureEnumerateA);
|
||||||
#undef LOAD_FUNC
|
#undef LOAD_FUNC
|
||||||
|
|
||||||
if(!ok)
|
|
||||||
{
|
|
||||||
FreeLibrary(ds_handle);
|
|
||||||
ds_handle = NULL;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return ok;
|
return ALC_TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static BOOL CALLBACK DSoundEnumDevices(LPGUID guid, LPCSTR desc, LPCSTR drvname, LPVOID data)
|
static BOOL CALLBACK DSoundEnumPlaybackDevices(LPGUID guid, LPCSTR desc, LPCSTR drvname, LPVOID data)
|
||||||
{
|
{
|
||||||
|
LPOLESTR guidstr = NULL;
|
||||||
char str[1024];
|
char str[1024];
|
||||||
|
HRESULT hr;
|
||||||
void *temp;
|
void *temp;
|
||||||
int count;
|
int count;
|
||||||
ALuint i;
|
ALuint i;
|
||||||
@ -132,30 +145,87 @@ static BOOL CALLBACK DSoundEnumDevices(LPGUID guid, LPCSTR desc, LPCSTR drvname,
|
|||||||
snprintf(str, sizeof(str), "%s #%d", desc, count+1);
|
snprintf(str, sizeof(str), "%s #%d", desc, count+1);
|
||||||
count++;
|
count++;
|
||||||
|
|
||||||
for(i = 0;i < NumDevices;i++)
|
for(i = 0;i < NumPlaybackDevices;i++)
|
||||||
{
|
{
|
||||||
if(strcmp(str, DeviceList[i].name) == 0)
|
if(strcmp(str, PlaybackDeviceList[i].name) == 0)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
} while(i != NumDevices);
|
} while(i != NumPlaybackDevices);
|
||||||
|
|
||||||
temp = realloc(DeviceList, sizeof(DevMap) * (NumDevices+1));
|
hr = StringFromCLSID(guid, &guidstr);
|
||||||
|
if(SUCCEEDED(hr))
|
||||||
|
{
|
||||||
|
TRACE("Got device \"%s\", GUID \"%ls\"\n", str, guidstr);
|
||||||
|
CoTaskMemFree(guidstr);
|
||||||
|
}
|
||||||
|
|
||||||
|
temp = realloc(PlaybackDeviceList, sizeof(DevMap) * (NumPlaybackDevices+1));
|
||||||
if(temp)
|
if(temp)
|
||||||
{
|
{
|
||||||
DeviceList = temp;
|
PlaybackDeviceList = temp;
|
||||||
DeviceList[NumDevices].name = strdup(str);
|
PlaybackDeviceList[NumPlaybackDevices].name = strdup(str);
|
||||||
DeviceList[NumDevices].guid = *guid;
|
PlaybackDeviceList[NumPlaybackDevices].guid = *guid;
|
||||||
NumDevices++;
|
NumPlaybackDevices++;
|
||||||
}
|
}
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static ALuint DSoundProc(ALvoid *ptr)
|
static BOOL CALLBACK DSoundEnumCaptureDevices(LPGUID guid, LPCSTR desc, LPCSTR drvname, LPVOID data)
|
||||||
|
{
|
||||||
|
LPOLESTR guidstr = NULL;
|
||||||
|
char str[1024];
|
||||||
|
HRESULT hr;
|
||||||
|
void *temp;
|
||||||
|
int count;
|
||||||
|
ALuint i;
|
||||||
|
|
||||||
|
(void)data;
|
||||||
|
(void)drvname;
|
||||||
|
|
||||||
|
if(!guid)
|
||||||
|
return TRUE;
|
||||||
|
|
||||||
|
count = 0;
|
||||||
|
do {
|
||||||
|
if(count == 0)
|
||||||
|
snprintf(str, sizeof(str), "%s", desc);
|
||||||
|
else
|
||||||
|
snprintf(str, sizeof(str), "%s #%d", desc, count+1);
|
||||||
|
count++;
|
||||||
|
|
||||||
|
for(i = 0;i < NumCaptureDevices;i++)
|
||||||
|
{
|
||||||
|
if(strcmp(str, CaptureDeviceList[i].name) == 0)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} while(i != NumCaptureDevices);
|
||||||
|
|
||||||
|
hr = StringFromCLSID(guid, &guidstr);
|
||||||
|
if(SUCCEEDED(hr))
|
||||||
|
{
|
||||||
|
TRACE("Got device \"%s\", GUID \"%ls\"\n", str, guidstr);
|
||||||
|
CoTaskMemFree(guidstr);
|
||||||
|
}
|
||||||
|
|
||||||
|
temp = realloc(CaptureDeviceList, sizeof(DevMap) * (NumCaptureDevices+1));
|
||||||
|
if(temp)
|
||||||
|
{
|
||||||
|
CaptureDeviceList = temp;
|
||||||
|
CaptureDeviceList[NumCaptureDevices].name = strdup(str);
|
||||||
|
CaptureDeviceList[NumCaptureDevices].guid = *guid;
|
||||||
|
NumCaptureDevices++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static ALuint DSoundPlaybackProc(ALvoid *ptr)
|
||||||
{
|
{
|
||||||
ALCdevice *pDevice = (ALCdevice*)ptr;
|
ALCdevice *pDevice = (ALCdevice*)ptr;
|
||||||
DSoundData *pData = (DSoundData*)pDevice->ExtraData;
|
DSoundPlaybackData *pData = (DSoundPlaybackData*)pDevice->ExtraData;
|
||||||
DSBCAPS DSBCaps;
|
DSBCAPS DSBCaps;
|
||||||
DWORD LastCursor = 0;
|
DWORD LastCursor = 0;
|
||||||
DWORD PlayCursor;
|
DWORD PlayCursor;
|
||||||
@ -255,37 +325,40 @@ static ALuint DSoundProc(ALvoid *ptr)
|
|||||||
|
|
||||||
static ALCenum DSoundOpenPlayback(ALCdevice *device, const ALCchar *deviceName)
|
static ALCenum DSoundOpenPlayback(ALCdevice *device, const ALCchar *deviceName)
|
||||||
{
|
{
|
||||||
DSoundData *pData = NULL;
|
DSoundPlaybackData *pData = NULL;
|
||||||
LPGUID guid = NULL;
|
LPGUID guid = NULL;
|
||||||
HRESULT hr;
|
HRESULT hr;
|
||||||
|
|
||||||
if(!deviceName)
|
if(!PlaybackDeviceList)
|
||||||
deviceName = dsDevice;
|
{
|
||||||
else if(strcmp(deviceName, dsDevice) != 0)
|
hr = DirectSoundEnumerateA(DSoundEnumPlaybackDevices, NULL);
|
||||||
|
if(FAILED(hr))
|
||||||
|
ERR("Error enumerating DirectSound devices (%#x)!\n", (unsigned int)hr);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!deviceName && NumPlaybackDevices > 0)
|
||||||
|
{
|
||||||
|
deviceName = PlaybackDeviceList[0].name;
|
||||||
|
guid = &PlaybackDeviceList[0].guid;
|
||||||
|
}
|
||||||
|
else
|
||||||
{
|
{
|
||||||
ALuint i;
|
ALuint i;
|
||||||
|
|
||||||
if(!DeviceList)
|
for(i = 0;i < NumPlaybackDevices;i++)
|
||||||
{
|
{
|
||||||
hr = DirectSoundEnumerateA(DSoundEnumDevices, NULL);
|
if(strcmp(deviceName, PlaybackDeviceList[i].name) == 0)
|
||||||
if(FAILED(hr))
|
|
||||||
ERR("Error enumerating DirectSound devices (%#x)!\n", (unsigned int)hr);
|
|
||||||
}
|
|
||||||
|
|
||||||
for(i = 0;i < NumDevices;i++)
|
|
||||||
{
|
|
||||||
if(strcmp(deviceName, DeviceList[i].name) == 0)
|
|
||||||
{
|
{
|
||||||
guid = &DeviceList[i].guid;
|
guid = &PlaybackDeviceList[i].guid;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(i == NumDevices)
|
if(i == NumPlaybackDevices)
|
||||||
return ALC_INVALID_VALUE;
|
return ALC_INVALID_VALUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
//Initialise requested device
|
//Initialise requested device
|
||||||
pData = calloc(1, sizeof(DSoundData));
|
pData = calloc(1, sizeof(DSoundPlaybackData));
|
||||||
if(!pData)
|
if(!pData)
|
||||||
return ALC_OUT_OF_MEMORY;
|
return ALC_OUT_OF_MEMORY;
|
||||||
|
|
||||||
@ -317,7 +390,17 @@ static ALCenum DSoundOpenPlayback(ALCdevice *device, const ALCchar *deviceName)
|
|||||||
|
|
||||||
static void DSoundClosePlayback(ALCdevice *device)
|
static void DSoundClosePlayback(ALCdevice *device)
|
||||||
{
|
{
|
||||||
DSoundData *pData = device->ExtraData;
|
DSoundPlaybackData *pData = device->ExtraData;
|
||||||
|
|
||||||
|
if(pData->DSnotify)
|
||||||
|
IDirectSoundNotify_Release(pData->DSnotify);
|
||||||
|
pData->DSnotify = NULL;
|
||||||
|
if(pData->DSsbuffer)
|
||||||
|
IDirectSoundBuffer_Release(pData->DSsbuffer);
|
||||||
|
pData->DSsbuffer = NULL;
|
||||||
|
if(pData->DSpbuffer != NULL)
|
||||||
|
IDirectSoundBuffer_Release(pData->DSpbuffer);
|
||||||
|
pData->DSpbuffer = NULL;
|
||||||
|
|
||||||
IDirectSound_Release(pData->lpDS);
|
IDirectSound_Release(pData->lpDS);
|
||||||
CloseHandle(pData->hNotifyEvent);
|
CloseHandle(pData->hNotifyEvent);
|
||||||
@ -327,7 +410,7 @@ static void DSoundClosePlayback(ALCdevice *device)
|
|||||||
|
|
||||||
static ALCboolean DSoundResetPlayback(ALCdevice *device)
|
static ALCboolean DSoundResetPlayback(ALCdevice *device)
|
||||||
{
|
{
|
||||||
DSoundData *pData = (DSoundData*)device->ExtraData;
|
DSoundPlaybackData *pData = (DSoundPlaybackData*)device->ExtraData;
|
||||||
DSBUFFERDESC DSBDescription;
|
DSBUFFERDESC DSBDescription;
|
||||||
WAVEFORMATEXTENSIBLE OutputType;
|
WAVEFORMATEXTENSIBLE OutputType;
|
||||||
DWORD speakers;
|
DWORD speakers;
|
||||||
@ -335,6 +418,16 @@ static ALCboolean DSoundResetPlayback(ALCdevice *device)
|
|||||||
|
|
||||||
memset(&OutputType, 0, sizeof(OutputType));
|
memset(&OutputType, 0, sizeof(OutputType));
|
||||||
|
|
||||||
|
if(pData->DSnotify)
|
||||||
|
IDirectSoundNotify_Release(pData->DSnotify);
|
||||||
|
pData->DSnotify = NULL;
|
||||||
|
if(pData->DSsbuffer)
|
||||||
|
IDirectSoundBuffer_Release(pData->DSsbuffer);
|
||||||
|
pData->DSsbuffer = NULL;
|
||||||
|
if(pData->DSpbuffer != NULL)
|
||||||
|
IDirectSoundBuffer_Release(pData->DSpbuffer);
|
||||||
|
pData->DSpbuffer = NULL;
|
||||||
|
|
||||||
switch(device->FmtType)
|
switch(device->FmtType)
|
||||||
{
|
{
|
||||||
case DevFmtByte:
|
case DevFmtByte:
|
||||||
@ -343,8 +436,12 @@ static ALCboolean DSoundResetPlayback(ALCdevice *device)
|
|||||||
case DevFmtUShort:
|
case DevFmtUShort:
|
||||||
device->FmtType = DevFmtShort;
|
device->FmtType = DevFmtShort;
|
||||||
break;
|
break;
|
||||||
|
case DevFmtUInt:
|
||||||
|
device->FmtType = DevFmtInt;
|
||||||
|
break;
|
||||||
case DevFmtUByte:
|
case DevFmtUByte:
|
||||||
case DevFmtShort:
|
case DevFmtShort:
|
||||||
|
case DevFmtInt:
|
||||||
case DevFmtFloat:
|
case DevFmtFloat:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -421,6 +518,8 @@ static ALCboolean DSoundResetPlayback(ALCdevice *device)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
retry_open:
|
||||||
|
hr = S_OK;
|
||||||
OutputType.Format.wFormatTag = WAVE_FORMAT_PCM;
|
OutputType.Format.wFormatTag = WAVE_FORMAT_PCM;
|
||||||
OutputType.Format.nChannels = ChannelsFromDevFmt(device->FmtChans);
|
OutputType.Format.nChannels = ChannelsFromDevFmt(device->FmtChans);
|
||||||
OutputType.Format.wBitsPerSample = BytesFromDevFmt(device->FmtType) * 8;
|
OutputType.Format.wBitsPerSample = BytesFromDevFmt(device->FmtType) * 8;
|
||||||
@ -439,6 +538,10 @@ static ALCboolean DSoundResetPlayback(ALCdevice *device)
|
|||||||
OutputType.SubFormat = KSDATAFORMAT_SUBTYPE_IEEE_FLOAT;
|
OutputType.SubFormat = KSDATAFORMAT_SUBTYPE_IEEE_FLOAT;
|
||||||
else
|
else
|
||||||
OutputType.SubFormat = KSDATAFORMAT_SUBTYPE_PCM;
|
OutputType.SubFormat = KSDATAFORMAT_SUBTYPE_PCM;
|
||||||
|
|
||||||
|
if(pData->DSpbuffer)
|
||||||
|
IDirectSoundBuffer_Release(pData->DSpbuffer);
|
||||||
|
pData->DSpbuffer = NULL;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -469,6 +572,11 @@ static ALCboolean DSoundResetPlayback(ALCdevice *device)
|
|||||||
OutputType.Format.nBlockAlign;
|
OutputType.Format.nBlockAlign;
|
||||||
DSBDescription.lpwfxFormat=&OutputType.Format;
|
DSBDescription.lpwfxFormat=&OutputType.Format;
|
||||||
hr = IDirectSound_CreateSoundBuffer(pData->lpDS, &DSBDescription, &pData->DSsbuffer, NULL);
|
hr = IDirectSound_CreateSoundBuffer(pData->lpDS, &DSBDescription, &pData->DSsbuffer, NULL);
|
||||||
|
if(FAILED(hr) && device->FmtType == DevFmtFloat)
|
||||||
|
{
|
||||||
|
device->FmtType = DevFmtShort;
|
||||||
|
goto retry_open;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(SUCCEEDED(hr))
|
if(SUCCEEDED(hr))
|
||||||
@ -490,15 +598,6 @@ static ALCboolean DSoundResetPlayback(ALCdevice *device)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(SUCCEEDED(hr))
|
|
||||||
{
|
|
||||||
ResetEvent(pData->hNotifyEvent);
|
|
||||||
SetDefaultWFXChannelOrder(device);
|
|
||||||
pData->thread = StartThread(DSoundProc, device);
|
|
||||||
if(pData->thread == NULL)
|
|
||||||
hr = E_FAIL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(FAILED(hr))
|
if(FAILED(hr))
|
||||||
{
|
{
|
||||||
if(pData->DSnotify != NULL)
|
if(pData->DSnotify != NULL)
|
||||||
@ -513,12 +612,26 @@ static ALCboolean DSoundResetPlayback(ALCdevice *device)
|
|||||||
return ALC_FALSE;
|
return ALC_FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ResetEvent(pData->hNotifyEvent);
|
||||||
|
SetDefaultWFXChannelOrder(device);
|
||||||
|
|
||||||
|
return ALC_TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static ALCboolean DSoundStartPlayback(ALCdevice *device)
|
||||||
|
{
|
||||||
|
DSoundPlaybackData *pData = (DSoundPlaybackData*)device->ExtraData;
|
||||||
|
|
||||||
|
pData->thread = StartThread(DSoundPlaybackProc, device);
|
||||||
|
if(pData->thread == NULL)
|
||||||
|
return ALC_FALSE;
|
||||||
|
|
||||||
return ALC_TRUE;
|
return ALC_TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void DSoundStopPlayback(ALCdevice *device)
|
static void DSoundStopPlayback(ALCdevice *device)
|
||||||
{
|
{
|
||||||
DSoundData *pData = device->ExtraData;
|
DSoundPlaybackData *pData = device->ExtraData;
|
||||||
|
|
||||||
if(!pData->thread)
|
if(!pData->thread)
|
||||||
return;
|
return;
|
||||||
@ -528,28 +641,309 @@ static void DSoundStopPlayback(ALCdevice *device)
|
|||||||
pData->thread = NULL;
|
pData->thread = NULL;
|
||||||
|
|
||||||
pData->killNow = 0;
|
pData->killNow = 0;
|
||||||
|
IDirectSoundBuffer_Stop(pData->DSsbuffer);
|
||||||
IDirectSoundNotify_Release(pData->DSnotify);
|
|
||||||
pData->DSnotify = NULL;
|
|
||||||
IDirectSoundBuffer_Release(pData->DSsbuffer);
|
|
||||||
pData->DSsbuffer = NULL;
|
|
||||||
if(pData->DSpbuffer != NULL)
|
|
||||||
IDirectSoundBuffer_Release(pData->DSpbuffer);
|
|
||||||
pData->DSpbuffer = NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static ALCenum DSoundOpenCapture(ALCdevice *device, const ALCchar *deviceName)
|
||||||
|
{
|
||||||
|
DSoundCaptureData *pData = NULL;
|
||||||
|
WAVEFORMATEXTENSIBLE InputType;
|
||||||
|
DSCBUFFERDESC DSCBDescription;
|
||||||
|
LPGUID guid = NULL;
|
||||||
|
HRESULT hr, hrcom;
|
||||||
|
ALuint samples;
|
||||||
|
|
||||||
|
if(!CaptureDeviceList)
|
||||||
|
{
|
||||||
|
/* Initialize COM to prevent name truncation */
|
||||||
|
hrcom = CoInitialize(NULL);
|
||||||
|
hr = DirectSoundCaptureEnumerateA(DSoundEnumCaptureDevices, NULL);
|
||||||
|
if(FAILED(hr))
|
||||||
|
ERR("Error enumerating DirectSound devices (%#x)!\n", (unsigned int)hr);
|
||||||
|
if(SUCCEEDED(hrcom))
|
||||||
|
CoUninitialize();
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!deviceName && NumCaptureDevices > 0)
|
||||||
|
{
|
||||||
|
deviceName = CaptureDeviceList[0].name;
|
||||||
|
guid = &CaptureDeviceList[0].guid;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ALuint i;
|
||||||
|
|
||||||
|
for(i = 0;i < NumCaptureDevices;i++)
|
||||||
|
{
|
||||||
|
if(strcmp(deviceName, CaptureDeviceList[i].name) == 0)
|
||||||
|
{
|
||||||
|
guid = &CaptureDeviceList[i].guid;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(i == NumCaptureDevices)
|
||||||
|
return ALC_INVALID_VALUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch(device->FmtType)
|
||||||
|
{
|
||||||
|
case DevFmtByte:
|
||||||
|
case DevFmtUShort:
|
||||||
|
case DevFmtUInt:
|
||||||
|
WARN("%s capture samples not supported\n", DevFmtTypeString(device->FmtType));
|
||||||
|
return ALC_INVALID_ENUM;
|
||||||
|
|
||||||
|
case DevFmtUByte:
|
||||||
|
case DevFmtShort:
|
||||||
|
case DevFmtInt:
|
||||||
|
case DevFmtFloat:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
//Initialise requested device
|
||||||
|
pData = calloc(1, sizeof(DSoundCaptureData));
|
||||||
|
if(!pData)
|
||||||
|
return ALC_OUT_OF_MEMORY;
|
||||||
|
|
||||||
|
hr = DS_OK;
|
||||||
|
|
||||||
|
//DirectSoundCapture Init code
|
||||||
|
if(SUCCEEDED(hr))
|
||||||
|
hr = DirectSoundCaptureCreate(guid, &pData->lpDSC, NULL);
|
||||||
|
if(SUCCEEDED(hr))
|
||||||
|
{
|
||||||
|
memset(&InputType, 0, sizeof(InputType));
|
||||||
|
|
||||||
|
switch(device->FmtChans)
|
||||||
|
{
|
||||||
|
case DevFmtMono:
|
||||||
|
InputType.dwChannelMask = SPEAKER_FRONT_CENTER;
|
||||||
|
break;
|
||||||
|
case DevFmtStereo:
|
||||||
|
InputType.dwChannelMask = SPEAKER_FRONT_LEFT |
|
||||||
|
SPEAKER_FRONT_RIGHT;
|
||||||
|
break;
|
||||||
|
case DevFmtQuad:
|
||||||
|
InputType.dwChannelMask = SPEAKER_FRONT_LEFT |
|
||||||
|
SPEAKER_FRONT_RIGHT |
|
||||||
|
SPEAKER_BACK_LEFT |
|
||||||
|
SPEAKER_BACK_RIGHT;
|
||||||
|
break;
|
||||||
|
case DevFmtX51:
|
||||||
|
InputType.dwChannelMask = SPEAKER_FRONT_LEFT |
|
||||||
|
SPEAKER_FRONT_RIGHT |
|
||||||
|
SPEAKER_FRONT_CENTER |
|
||||||
|
SPEAKER_LOW_FREQUENCY |
|
||||||
|
SPEAKER_BACK_LEFT |
|
||||||
|
SPEAKER_BACK_RIGHT;
|
||||||
|
break;
|
||||||
|
case DevFmtX51Side:
|
||||||
|
InputType.dwChannelMask = SPEAKER_FRONT_LEFT |
|
||||||
|
SPEAKER_FRONT_RIGHT |
|
||||||
|
SPEAKER_FRONT_CENTER |
|
||||||
|
SPEAKER_LOW_FREQUENCY |
|
||||||
|
SPEAKER_SIDE_LEFT |
|
||||||
|
SPEAKER_SIDE_RIGHT;
|
||||||
|
break;
|
||||||
|
case DevFmtX61:
|
||||||
|
InputType.dwChannelMask = SPEAKER_FRONT_LEFT |
|
||||||
|
SPEAKER_FRONT_RIGHT |
|
||||||
|
SPEAKER_FRONT_CENTER |
|
||||||
|
SPEAKER_LOW_FREQUENCY |
|
||||||
|
SPEAKER_BACK_CENTER |
|
||||||
|
SPEAKER_SIDE_LEFT |
|
||||||
|
SPEAKER_SIDE_RIGHT;
|
||||||
|
break;
|
||||||
|
case DevFmtX71:
|
||||||
|
InputType.dwChannelMask = SPEAKER_FRONT_LEFT |
|
||||||
|
SPEAKER_FRONT_RIGHT |
|
||||||
|
SPEAKER_FRONT_CENTER |
|
||||||
|
SPEAKER_LOW_FREQUENCY |
|
||||||
|
SPEAKER_BACK_LEFT |
|
||||||
|
SPEAKER_BACK_RIGHT |
|
||||||
|
SPEAKER_SIDE_LEFT |
|
||||||
|
SPEAKER_SIDE_RIGHT;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
InputType.Format.wFormatTag = WAVE_FORMAT_PCM;
|
||||||
|
InputType.Format.nChannels = ChannelsFromDevFmt(device->FmtChans);
|
||||||
|
InputType.Format.wBitsPerSample = BytesFromDevFmt(device->FmtType) * 8;
|
||||||
|
InputType.Format.nBlockAlign = InputType.Format.nChannels*InputType.Format.wBitsPerSample/8;
|
||||||
|
InputType.Format.nSamplesPerSec = device->Frequency;
|
||||||
|
InputType.Format.nAvgBytesPerSec = InputType.Format.nSamplesPerSec*InputType.Format.nBlockAlign;
|
||||||
|
InputType.Format.cbSize = 0;
|
||||||
|
|
||||||
|
if(InputType.Format.nChannels > 2 || device->FmtType == DevFmtFloat)
|
||||||
|
{
|
||||||
|
InputType.Format.wFormatTag = WAVE_FORMAT_EXTENSIBLE;
|
||||||
|
InputType.Format.cbSize = sizeof(WAVEFORMATEXTENSIBLE) - sizeof(WAVEFORMATEX);
|
||||||
|
InputType.Samples.wValidBitsPerSample = InputType.Format.wBitsPerSample;
|
||||||
|
if(device->FmtType == DevFmtFloat)
|
||||||
|
InputType.SubFormat = KSDATAFORMAT_SUBTYPE_IEEE_FLOAT;
|
||||||
|
else
|
||||||
|
InputType.SubFormat = KSDATAFORMAT_SUBTYPE_PCM;
|
||||||
|
}
|
||||||
|
|
||||||
|
samples = device->UpdateSize * device->NumUpdates;
|
||||||
|
samples = maxu(samples, 100 * device->Frequency / 1000);
|
||||||
|
|
||||||
|
memset(&DSCBDescription, 0, sizeof(DSCBUFFERDESC));
|
||||||
|
DSCBDescription.dwSize = sizeof(DSCBUFFERDESC);
|
||||||
|
DSCBDescription.dwFlags = 0;
|
||||||
|
DSCBDescription.dwBufferBytes = samples * InputType.Format.nBlockAlign;
|
||||||
|
DSCBDescription.lpwfxFormat = &InputType.Format;
|
||||||
|
|
||||||
|
hr = IDirectSoundCapture_CreateCaptureBuffer(pData->lpDSC, &DSCBDescription, &pData->DSCbuffer, NULL);
|
||||||
|
}
|
||||||
|
if(SUCCEEDED(hr))
|
||||||
|
{
|
||||||
|
pData->pRing = CreateRingBuffer(InputType.Format.nBlockAlign, device->UpdateSize * device->NumUpdates);
|
||||||
|
if(pData->pRing == NULL)
|
||||||
|
hr = DSERR_OUTOFMEMORY;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(FAILED(hr))
|
||||||
|
{
|
||||||
|
ERR("Device init failed: 0x%08lx\n", hr);
|
||||||
|
|
||||||
|
DestroyRingBuffer(pData->pRing);
|
||||||
|
pData->pRing = NULL;
|
||||||
|
if(pData->DSCbuffer != NULL)
|
||||||
|
IDirectSoundCaptureBuffer_Release(pData->DSCbuffer);
|
||||||
|
pData->DSCbuffer = NULL;
|
||||||
|
if(pData->lpDSC)
|
||||||
|
IDirectSoundCapture_Release(pData->lpDSC);
|
||||||
|
pData->lpDSC = NULL;
|
||||||
|
|
||||||
|
free(pData);
|
||||||
|
return ALC_INVALID_VALUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
pData->dwBufferBytes = DSCBDescription.dwBufferBytes;
|
||||||
|
SetDefaultWFXChannelOrder(device);
|
||||||
|
|
||||||
|
device->szDeviceName = strdup(deviceName);
|
||||||
|
device->ExtraData = pData;
|
||||||
|
|
||||||
|
return ALC_NO_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void DSoundCloseCapture(ALCdevice *device)
|
||||||
|
{
|
||||||
|
DSoundCaptureData *pData = device->ExtraData;
|
||||||
|
|
||||||
|
DestroyRingBuffer(pData->pRing);
|
||||||
|
pData->pRing = NULL;
|
||||||
|
|
||||||
|
if(pData->DSCbuffer != NULL)
|
||||||
|
{
|
||||||
|
IDirectSoundCaptureBuffer_Stop(pData->DSCbuffer);
|
||||||
|
IDirectSoundCaptureBuffer_Release(pData->DSCbuffer);
|
||||||
|
pData->DSCbuffer = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
IDirectSoundCapture_Release(pData->lpDSC);
|
||||||
|
pData->lpDSC = NULL;
|
||||||
|
|
||||||
|
free(pData);
|
||||||
|
device->ExtraData = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void DSoundStartCapture(ALCdevice *device)
|
||||||
|
{
|
||||||
|
DSoundCaptureData *pData = device->ExtraData;
|
||||||
|
HRESULT hr;
|
||||||
|
|
||||||
|
hr = IDirectSoundCaptureBuffer_Start(pData->DSCbuffer, DSCBSTART_LOOPING);
|
||||||
|
if(FAILED(hr))
|
||||||
|
{
|
||||||
|
ERR("start failed: 0x%08lx\n", hr);
|
||||||
|
aluHandleDisconnect(device);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void DSoundStopCapture(ALCdevice *device)
|
||||||
|
{
|
||||||
|
DSoundCaptureData *pData = device->ExtraData;
|
||||||
|
HRESULT hr;
|
||||||
|
|
||||||
|
hr = IDirectSoundCaptureBuffer_Stop(pData->DSCbuffer);
|
||||||
|
if(FAILED(hr))
|
||||||
|
{
|
||||||
|
ERR("stop failed: 0x%08lx\n", hr);
|
||||||
|
aluHandleDisconnect(device);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static ALCenum DSoundCaptureSamples(ALCdevice *pDevice, ALCvoid *pBuffer, ALCuint lSamples)
|
||||||
|
{
|
||||||
|
DSoundCaptureData *pData = pDevice->ExtraData;
|
||||||
|
ReadRingBuffer(pData->pRing, pBuffer, lSamples);
|
||||||
|
return ALC_NO_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
static ALCuint DSoundAvailableSamples(ALCdevice *pDevice)
|
||||||
|
{
|
||||||
|
DSoundCaptureData *pData = pDevice->ExtraData;
|
||||||
|
DWORD dwRead, dwCursor, dwBufferBytes, dwNumBytes;
|
||||||
|
void *pvAudio1, *pvAudio2;
|
||||||
|
DWORD dwAudioBytes1, dwAudioBytes2;
|
||||||
|
DWORD FrameSize;
|
||||||
|
HRESULT hr;
|
||||||
|
|
||||||
|
if(!pDevice->Connected)
|
||||||
|
goto done;
|
||||||
|
|
||||||
|
FrameSize = FrameSizeFromDevFmt(pDevice->FmtChans, pDevice->FmtType);
|
||||||
|
dwBufferBytes = pData->dwBufferBytes;
|
||||||
|
dwCursor = pData->dwCursor;
|
||||||
|
|
||||||
|
hr = IDirectSoundCaptureBuffer_GetCurrentPosition(pData->DSCbuffer, NULL, &dwRead);
|
||||||
|
if(SUCCEEDED(hr))
|
||||||
|
{
|
||||||
|
dwNumBytes = (dwBufferBytes + dwRead - dwCursor) % dwBufferBytes;
|
||||||
|
if(dwNumBytes == 0)
|
||||||
|
goto done;
|
||||||
|
hr = IDirectSoundCaptureBuffer_Lock(pData->DSCbuffer,
|
||||||
|
dwCursor, dwNumBytes,
|
||||||
|
&pvAudio1, &dwAudioBytes1,
|
||||||
|
&pvAudio2, &dwAudioBytes2, 0);
|
||||||
|
}
|
||||||
|
if(SUCCEEDED(hr))
|
||||||
|
{
|
||||||
|
WriteRingBuffer(pData->pRing, pvAudio1, dwAudioBytes1/FrameSize);
|
||||||
|
if(pvAudio2 != NULL)
|
||||||
|
WriteRingBuffer(pData->pRing, pvAudio2, dwAudioBytes2/FrameSize);
|
||||||
|
hr = IDirectSoundCaptureBuffer_Unlock(pData->DSCbuffer,
|
||||||
|
pvAudio1, dwAudioBytes1,
|
||||||
|
pvAudio2, dwAudioBytes2);
|
||||||
|
pData->dwCursor = (dwCursor + dwAudioBytes1 + dwAudioBytes2) % dwBufferBytes;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(FAILED(hr))
|
||||||
|
{
|
||||||
|
ERR("update failed: 0x%08lx\n", hr);
|
||||||
|
aluHandleDisconnect(pDevice);
|
||||||
|
}
|
||||||
|
|
||||||
|
done:
|
||||||
|
return RingBufferSize(pData->pRing);
|
||||||
|
}
|
||||||
|
|
||||||
static const BackendFuncs DSoundFuncs = {
|
static const BackendFuncs DSoundFuncs = {
|
||||||
DSoundOpenPlayback,
|
DSoundOpenPlayback,
|
||||||
DSoundClosePlayback,
|
DSoundClosePlayback,
|
||||||
DSoundResetPlayback,
|
DSoundResetPlayback,
|
||||||
|
DSoundStartPlayback,
|
||||||
DSoundStopPlayback,
|
DSoundStopPlayback,
|
||||||
NULL,
|
DSoundOpenCapture,
|
||||||
NULL,
|
DSoundCloseCapture,
|
||||||
NULL,
|
DSoundStartCapture,
|
||||||
NULL,
|
DSoundStopCapture,
|
||||||
NULL,
|
DSoundCaptureSamples,
|
||||||
NULL
|
DSoundAvailableSamples
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -565,46 +959,66 @@ void alcDSoundDeinit(void)
|
|||||||
{
|
{
|
||||||
ALuint i;
|
ALuint i;
|
||||||
|
|
||||||
for(i = 0;i < NumDevices;++i)
|
for(i = 0;i < NumPlaybackDevices;++i)
|
||||||
free(DeviceList[i].name);
|
free(PlaybackDeviceList[i].name);
|
||||||
free(DeviceList);
|
free(PlaybackDeviceList);
|
||||||
DeviceList = NULL;
|
PlaybackDeviceList = NULL;
|
||||||
NumDevices = 0;
|
NumPlaybackDevices = 0;
|
||||||
|
|
||||||
|
for(i = 0;i < NumCaptureDevices;++i)
|
||||||
|
free(CaptureDeviceList[i].name);
|
||||||
|
free(CaptureDeviceList);
|
||||||
|
CaptureDeviceList = NULL;
|
||||||
|
NumCaptureDevices = 0;
|
||||||
|
|
||||||
if(ds_handle)
|
if(ds_handle)
|
||||||
FreeLibrary(ds_handle);
|
CloseLib(ds_handle);
|
||||||
ds_handle = NULL;
|
ds_handle = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
void alcDSoundProbe(enum DevProbe type)
|
void alcDSoundProbe(enum DevProbe type)
|
||||||
{
|
{
|
||||||
HRESULT hr;
|
HRESULT hr, hrcom;
|
||||||
ALuint i;
|
ALuint i;
|
||||||
|
|
||||||
switch(type)
|
switch(type)
|
||||||
{
|
{
|
||||||
case DEVICE_PROBE:
|
|
||||||
AppendDeviceList(dsDevice);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case ALL_DEVICE_PROBE:
|
case ALL_DEVICE_PROBE:
|
||||||
for(i = 0;i < NumDevices;++i)
|
for(i = 0;i < NumPlaybackDevices;++i)
|
||||||
free(DeviceList[i].name);
|
free(PlaybackDeviceList[i].name);
|
||||||
free(DeviceList);
|
free(PlaybackDeviceList);
|
||||||
DeviceList = NULL;
|
PlaybackDeviceList = NULL;
|
||||||
NumDevices = 0;
|
NumPlaybackDevices = 0;
|
||||||
|
|
||||||
hr = DirectSoundEnumerateA(DSoundEnumDevices, NULL);
|
hr = DirectSoundEnumerateA(DSoundEnumPlaybackDevices, NULL);
|
||||||
if(FAILED(hr))
|
if(FAILED(hr))
|
||||||
ERR("Error enumerating DirectSound devices (%#x)!\n", (unsigned int)hr);
|
ERR("Error enumerating DirectSound playback devices (%#x)!\n", (unsigned int)hr);
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
for(i = 0;i < NumDevices;i++)
|
for(i = 0;i < NumPlaybackDevices;i++)
|
||||||
AppendAllDeviceList(DeviceList[i].name);
|
AppendAllDeviceList(PlaybackDeviceList[i].name);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case CAPTURE_DEVICE_PROBE:
|
case CAPTURE_DEVICE_PROBE:
|
||||||
|
for(i = 0;i < NumCaptureDevices;++i)
|
||||||
|
free(CaptureDeviceList[i].name);
|
||||||
|
free(CaptureDeviceList);
|
||||||
|
CaptureDeviceList = NULL;
|
||||||
|
NumCaptureDevices = 0;
|
||||||
|
|
||||||
|
/* Initialize COM to prevent name truncation */
|
||||||
|
hrcom = CoInitialize(NULL);
|
||||||
|
hr = DirectSoundCaptureEnumerateA(DSoundEnumCaptureDevices, NULL);
|
||||||
|
if(FAILED(hr))
|
||||||
|
ERR("Error enumerating DirectSound capture devices (%#x)!\n", (unsigned int)hr);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
for(i = 0;i < NumCaptureDevices;i++)
|
||||||
|
AppendCaptureDeviceList(CaptureDeviceList[i].name);
|
||||||
|
}
|
||||||
|
if(SUCCEEDED(hrcom))
|
||||||
|
CoUninitialize();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -43,6 +43,12 @@ static ALCboolean loopback_reset_playback(ALCdevice *device)
|
|||||||
return ALC_TRUE;
|
return ALC_TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static ALCboolean loopback_start_playback(ALCdevice *device)
|
||||||
|
{
|
||||||
|
return ALC_TRUE;
|
||||||
|
(void)device;
|
||||||
|
}
|
||||||
|
|
||||||
static void loopback_stop_playback(ALCdevice *device)
|
static void loopback_stop_playback(ALCdevice *device)
|
||||||
{
|
{
|
||||||
(void)device;
|
(void)device;
|
||||||
@ -52,6 +58,7 @@ static const BackendFuncs loopback_funcs = {
|
|||||||
loopback_open_playback,
|
loopback_open_playback,
|
||||||
loopback_close_playback,
|
loopback_close_playback,
|
||||||
loopback_reset_playback,
|
loopback_reset_playback,
|
||||||
|
loopback_start_playback,
|
||||||
loopback_stop_playback,
|
loopback_stop_playback,
|
||||||
NULL,
|
NULL,
|
||||||
NULL,
|
NULL,
|
||||||
|
@ -29,6 +29,9 @@
|
|||||||
#include <audioclient.h>
|
#include <audioclient.h>
|
||||||
#include <cguid.h>
|
#include <cguid.h>
|
||||||
#include <mmreg.h>
|
#include <mmreg.h>
|
||||||
|
#include <propsys.h>
|
||||||
|
#include <propkey.h>
|
||||||
|
#include <devpkey.h>
|
||||||
#ifndef _WAVEFORMATEXTENSIBLE_
|
#ifndef _WAVEFORMATEXTENSIBLE_
|
||||||
#include <ks.h>
|
#include <ks.h>
|
||||||
#include <ksmedia.h>
|
#include <ksmedia.h>
|
||||||
@ -52,8 +55,11 @@ DEFINE_GUID(KSDATAFORMAT_SUBTYPE_IEEE_FLOAT, 0x00000003, 0x0000, 0x0010, 0x80, 0
|
|||||||
|
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
|
WCHAR *devid;
|
||||||
|
|
||||||
IMMDevice *mmdev;
|
IMMDevice *mmdev;
|
||||||
IAudioClient *client;
|
IAudioClient *client;
|
||||||
|
IAudioRenderClient *render;
|
||||||
HANDLE hNotifyEvent;
|
HANDLE hNotifyEvent;
|
||||||
|
|
||||||
HANDLE MsgEvent;
|
HANDLE MsgEvent;
|
||||||
@ -63,7 +69,15 @@ typedef struct {
|
|||||||
} MMDevApiData;
|
} MMDevApiData;
|
||||||
|
|
||||||
|
|
||||||
static const ALCchar mmDevice[] = "WASAPI Default";
|
typedef struct {
|
||||||
|
ALCchar *name;
|
||||||
|
WCHAR *devid;
|
||||||
|
} DevMap;
|
||||||
|
|
||||||
|
static DevMap *PlaybackDeviceList;
|
||||||
|
static ALuint NumPlaybackDevices;
|
||||||
|
static DevMap *CaptureDeviceList;
|
||||||
|
static ALuint NumCaptureDevices;
|
||||||
|
|
||||||
|
|
||||||
static HANDLE ThreadHdl;
|
static HANDLE ThreadHdl;
|
||||||
@ -76,8 +90,10 @@ typedef struct {
|
|||||||
|
|
||||||
#define WM_USER_OpenDevice (WM_USER+0)
|
#define WM_USER_OpenDevice (WM_USER+0)
|
||||||
#define WM_USER_ResetDevice (WM_USER+1)
|
#define WM_USER_ResetDevice (WM_USER+1)
|
||||||
#define WM_USER_StopDevice (WM_USER+2)
|
#define WM_USER_StartDevice (WM_USER+2)
|
||||||
#define WM_USER_CloseDevice (WM_USER+3)
|
#define WM_USER_StopDevice (WM_USER+3)
|
||||||
|
#define WM_USER_CloseDevice (WM_USER+4)
|
||||||
|
#define WM_USER_Enumerate (WM_USER+5)
|
||||||
|
|
||||||
static HRESULT WaitForResponse(ThreadRequest *req)
|
static HRESULT WaitForResponse(ThreadRequest *req)
|
||||||
{
|
{
|
||||||
@ -88,15 +104,120 @@ static HRESULT WaitForResponse(ThreadRequest *req)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static ALCchar *get_device_name(IMMDevice *device)
|
||||||
|
{
|
||||||
|
ALCchar *name = NULL;
|
||||||
|
IPropertyStore *ps;
|
||||||
|
PROPVARIANT pvname;
|
||||||
|
HRESULT hr;
|
||||||
|
int len;
|
||||||
|
|
||||||
|
hr = IMMDevice_OpenPropertyStore(device, STGM_READ, &ps);
|
||||||
|
if(FAILED(hr))
|
||||||
|
{
|
||||||
|
WARN("OpenPropertyStore failed: 0x%08lx\n", hr);
|
||||||
|
return calloc(1, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
PropVariantInit(&pvname);
|
||||||
|
|
||||||
|
hr = IPropertyStore_GetValue(ps, (const PROPERTYKEY*)&DEVPKEY_Device_FriendlyName, &pvname);
|
||||||
|
if(FAILED(hr))
|
||||||
|
{
|
||||||
|
WARN("GetValue failed: 0x%08lx\n", hr);
|
||||||
|
name = calloc(1, 1);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if((len=WideCharToMultiByte(CP_ACP, 0, pvname.pwszVal, -1, NULL, 0, NULL, NULL)) > 0)
|
||||||
|
{
|
||||||
|
name = calloc(1, len);
|
||||||
|
WideCharToMultiByte(CP_ACP, 0, pvname.pwszVal, -1, name, len, NULL, NULL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
PropVariantClear(&pvname);
|
||||||
|
IPropertyStore_Release(ps);
|
||||||
|
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void add_device(IMMDevice *device, DevMap *devmap)
|
||||||
|
{
|
||||||
|
LPWSTR devid;
|
||||||
|
HRESULT hr;
|
||||||
|
|
||||||
|
hr = IMMDevice_GetId(device, &devid);
|
||||||
|
if(SUCCEEDED(hr))
|
||||||
|
{
|
||||||
|
devmap->devid = strdupW(devid);
|
||||||
|
devmap->name = get_device_name(device);
|
||||||
|
TRACE("Got device \"%s\", \"%ls\"\n", devmap->name, devmap->devid);
|
||||||
|
CoTaskMemFree(devid);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static DevMap *ProbeDevices(IMMDeviceEnumerator *devenum, EDataFlow flowdir, ALuint *numdevs)
|
||||||
|
{
|
||||||
|
IMMDeviceCollection *coll;
|
||||||
|
IMMDevice *defdev = NULL;
|
||||||
|
DevMap *devlist = NULL;
|
||||||
|
HRESULT hr;
|
||||||
|
UINT count;
|
||||||
|
UINT idx;
|
||||||
|
UINT i;
|
||||||
|
|
||||||
|
hr = IMMDeviceEnumerator_EnumAudioEndpoints(devenum, flowdir, DEVICE_STATE_ACTIVE, &coll);
|
||||||
|
if(FAILED(hr))
|
||||||
|
{
|
||||||
|
ERR("Failed to enumerate audio endpoints: 0x%08lx\n", hr);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
idx = count = 0;
|
||||||
|
hr = IMMDeviceCollection_GetCount(coll, &count);
|
||||||
|
if(SUCCEEDED(hr) && count > 0)
|
||||||
|
{
|
||||||
|
devlist = calloc(count, sizeof(*devlist));
|
||||||
|
if(!devlist)
|
||||||
|
{
|
||||||
|
IMMDeviceCollection_Release(coll);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
hr = IMMDeviceEnumerator_GetDefaultAudioEndpoint(devenum, flowdir,
|
||||||
|
eMultimedia, &defdev);
|
||||||
|
}
|
||||||
|
if(SUCCEEDED(hr) && defdev != NULL)
|
||||||
|
add_device(defdev, &devlist[idx++]);
|
||||||
|
|
||||||
|
for(i = 0;i < count && idx < count;++i)
|
||||||
|
{
|
||||||
|
IMMDevice *device;
|
||||||
|
|
||||||
|
if(FAILED(IMMDeviceCollection_Item(coll, i, &device)))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if(device != defdev)
|
||||||
|
add_device(device, &devlist[idx++]);
|
||||||
|
|
||||||
|
IMMDevice_Release(device);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(defdev) IMMDevice_Release(defdev);
|
||||||
|
IMMDeviceCollection_Release(coll);
|
||||||
|
|
||||||
|
*numdevs = idx;
|
||||||
|
return devlist;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static ALuint MMDevApiProc(ALvoid *ptr)
|
static ALuint MMDevApiProc(ALvoid *ptr)
|
||||||
{
|
{
|
||||||
ALCdevice *device = ptr;
|
ALCdevice *device = ptr;
|
||||||
MMDevApiData *data = device->ExtraData;
|
MMDevApiData *data = device->ExtraData;
|
||||||
union {
|
UINT32 buffer_len, written;
|
||||||
IAudioRenderClient *iface;
|
ALuint update_size, len;
|
||||||
void *ptr;
|
|
||||||
} render;
|
|
||||||
UINT32 written, len;
|
|
||||||
BYTE *buffer;
|
BYTE *buffer;
|
||||||
HRESULT hr;
|
HRESULT hr;
|
||||||
|
|
||||||
@ -108,16 +229,18 @@ static ALuint MMDevApiProc(ALvoid *ptr)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
hr = IAudioClient_GetService(data->client, &IID_IAudioRenderClient, &render.ptr);
|
hr = IAudioClient_GetBufferSize(data->client, &buffer_len);
|
||||||
if(FAILED(hr))
|
if(FAILED(hr))
|
||||||
{
|
{
|
||||||
ERR("Failed to get AudioRenderClient service: 0x%08lx\n", hr);
|
ERR("Failed to get audio buffer size: 0x%08lx\n", hr);
|
||||||
aluHandleDisconnect(device);
|
aluHandleDisconnect(device);
|
||||||
|
CoUninitialize();
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
SetRTPriority();
|
SetRTPriority();
|
||||||
|
|
||||||
|
update_size = device->UpdateSize;
|
||||||
while(!data->killNow)
|
while(!data->killNow)
|
||||||
{
|
{
|
||||||
hr = IAudioClient_GetCurrentPadding(data->client, &written);
|
hr = IAudioClient_GetCurrentPadding(data->client, &written);
|
||||||
@ -128,8 +251,8 @@ static ALuint MMDevApiProc(ALvoid *ptr)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
len = device->UpdateSize*device->NumUpdates - written;
|
len = buffer_len - written;
|
||||||
if(len < device->UpdateSize)
|
if(len < update_size)
|
||||||
{
|
{
|
||||||
DWORD res;
|
DWORD res;
|
||||||
res = WaitForSingleObjectEx(data->hNotifyEvent, 2000, FALSE);
|
res = WaitForSingleObjectEx(data->hNotifyEvent, 2000, FALSE);
|
||||||
@ -137,13 +260,13 @@ static ALuint MMDevApiProc(ALvoid *ptr)
|
|||||||
ERR("WaitForSingleObjectEx error: 0x%lx\n", res);
|
ERR("WaitForSingleObjectEx error: 0x%lx\n", res);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
len -= len%device->UpdateSize;
|
len -= len%update_size;
|
||||||
|
|
||||||
hr = IAudioRenderClient_GetBuffer(render.iface, len, &buffer);
|
hr = IAudioRenderClient_GetBuffer(data->render, len, &buffer);
|
||||||
if(SUCCEEDED(hr))
|
if(SUCCEEDED(hr))
|
||||||
{
|
{
|
||||||
aluMixData(device, buffer, len);
|
aluMixData(device, buffer, len);
|
||||||
hr = IAudioRenderClient_ReleaseBuffer(render.iface, len, 0);
|
hr = IAudioRenderClient_ReleaseBuffer(data->render, len, 0);
|
||||||
}
|
}
|
||||||
if(FAILED(hr))
|
if(FAILED(hr))
|
||||||
{
|
{
|
||||||
@ -153,8 +276,6 @@ static ALuint MMDevApiProc(ALvoid *ptr)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
IAudioRenderClient_Release(render.iface);
|
|
||||||
|
|
||||||
CoUninitialize();
|
CoUninitialize();
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -164,7 +285,7 @@ static ALCboolean MakeExtensible(WAVEFORMATEXTENSIBLE *out, const WAVEFORMATEX *
|
|||||||
{
|
{
|
||||||
memset(out, 0, sizeof(*out));
|
memset(out, 0, sizeof(*out));
|
||||||
if(in->wFormatTag == WAVE_FORMAT_EXTENSIBLE)
|
if(in->wFormatTag == WAVE_FORMAT_EXTENSIBLE)
|
||||||
*out = *(WAVEFORMATEXTENSIBLE*)in;
|
*out = *(const WAVEFORMATEXTENSIBLE*)in;
|
||||||
else if(in->wFormatTag == WAVE_FORMAT_PCM)
|
else if(in->wFormatTag == WAVE_FORMAT_PCM)
|
||||||
{
|
{
|
||||||
out->Format = *in;
|
out->Format = *in;
|
||||||
@ -204,7 +325,7 @@ static HRESULT DoReset(ALCdevice *device)
|
|||||||
MMDevApiData *data = device->ExtraData;
|
MMDevApiData *data = device->ExtraData;
|
||||||
WAVEFORMATEXTENSIBLE OutputType;
|
WAVEFORMATEXTENSIBLE OutputType;
|
||||||
WAVEFORMATEX *wfx = NULL;
|
WAVEFORMATEX *wfx = NULL;
|
||||||
REFERENCE_TIME min_per;
|
REFERENCE_TIME min_per, buf_time;
|
||||||
UINT32 buffer_len, min_len;
|
UINT32 buffer_len, min_len;
|
||||||
HRESULT hr;
|
HRESULT hr;
|
||||||
|
|
||||||
@ -223,6 +344,9 @@ static HRESULT DoReset(ALCdevice *device)
|
|||||||
CoTaskMemFree(wfx);
|
CoTaskMemFree(wfx);
|
||||||
wfx = NULL;
|
wfx = NULL;
|
||||||
|
|
||||||
|
buf_time = ((REFERENCE_TIME)device->UpdateSize*device->NumUpdates*10000000 +
|
||||||
|
device->Frequency-1) / device->Frequency;
|
||||||
|
|
||||||
if(!(device->Flags&DEVICE_FREQUENCY_REQUEST))
|
if(!(device->Flags&DEVICE_FREQUENCY_REQUEST))
|
||||||
device->Frequency = OutputType.Format.nSamplesPerSec;
|
device->Frequency = OutputType.Format.nSamplesPerSec;
|
||||||
if(!(device->Flags&DEVICE_CHANNELS_REQUEST))
|
if(!(device->Flags&DEVICE_CHANNELS_REQUEST))
|
||||||
@ -294,6 +418,14 @@ static HRESULT DoReset(ALCdevice *device)
|
|||||||
OutputType.Samples.wValidBitsPerSample = 16;
|
OutputType.Samples.wValidBitsPerSample = 16;
|
||||||
OutputType.SubFormat = KSDATAFORMAT_SUBTYPE_PCM;
|
OutputType.SubFormat = KSDATAFORMAT_SUBTYPE_PCM;
|
||||||
break;
|
break;
|
||||||
|
case DevFmtUInt:
|
||||||
|
device->FmtType = DevFmtInt;
|
||||||
|
/* fall-through */
|
||||||
|
case DevFmtInt:
|
||||||
|
OutputType.Format.wBitsPerSample = 32;
|
||||||
|
OutputType.Samples.wValidBitsPerSample = 32;
|
||||||
|
OutputType.SubFormat = KSDATAFORMAT_SUBTYPE_PCM;
|
||||||
|
break;
|
||||||
case DevFmtFloat:
|
case DevFmtFloat:
|
||||||
OutputType.Format.wBitsPerSample = 32;
|
OutputType.Format.wBitsPerSample = 32;
|
||||||
OutputType.Samples.wValidBitsPerSample = 32;
|
OutputType.Samples.wValidBitsPerSample = 32;
|
||||||
@ -329,153 +461,91 @@ static HRESULT DoReset(ALCdevice *device)
|
|||||||
CoTaskMemFree(wfx);
|
CoTaskMemFree(wfx);
|
||||||
wfx = NULL;
|
wfx = NULL;
|
||||||
|
|
||||||
if(device->Frequency != OutputType.Format.nSamplesPerSec)
|
device->Frequency = OutputType.Format.nSamplesPerSec;
|
||||||
|
if(OutputType.Format.nChannels == 1 && OutputType.dwChannelMask == MONO)
|
||||||
|
device->FmtChans = DevFmtMono;
|
||||||
|
else if(OutputType.Format.nChannels == 2 && OutputType.dwChannelMask == STEREO)
|
||||||
|
device->FmtChans = DevFmtStereo;
|
||||||
|
else if(OutputType.Format.nChannels == 4 && OutputType.dwChannelMask == QUAD)
|
||||||
|
device->FmtChans = DevFmtQuad;
|
||||||
|
else if(OutputType.Format.nChannels == 6 && OutputType.dwChannelMask == X5DOT1)
|
||||||
|
device->FmtChans = DevFmtX51;
|
||||||
|
else if(OutputType.Format.nChannels == 6 && OutputType.dwChannelMask == X5DOT1SIDE)
|
||||||
|
device->FmtChans = DevFmtX51Side;
|
||||||
|
else if(OutputType.Format.nChannels == 7 && OutputType.dwChannelMask == X6DOT1)
|
||||||
|
device->FmtChans = DevFmtX61;
|
||||||
|
else if(OutputType.Format.nChannels == 8 && OutputType.dwChannelMask == X7DOT1)
|
||||||
|
device->FmtChans = DevFmtX71;
|
||||||
|
else
|
||||||
{
|
{
|
||||||
if((device->Flags&DEVICE_FREQUENCY_REQUEST))
|
ERR("Unhandled extensible channels: %d -- 0x%08lx\n", OutputType.Format.nChannels, OutputType.dwChannelMask);
|
||||||
ERR("Failed to set %dhz, got %ldhz instead\n", device->Frequency, OutputType.Format.nSamplesPerSec);
|
device->FmtChans = DevFmtStereo;
|
||||||
device->Flags &= ~DEVICE_FREQUENCY_REQUEST;
|
OutputType.Format.nChannels = 2;
|
||||||
device->Frequency = OutputType.Format.nSamplesPerSec;
|
OutputType.dwChannelMask = STEREO;
|
||||||
}
|
|
||||||
|
|
||||||
if(!((device->FmtChans == DevFmtMono && OutputType.Format.nChannels == 1 && OutputType.dwChannelMask == MONO) ||
|
|
||||||
(device->FmtChans == DevFmtStereo && OutputType.Format.nChannels == 2 && OutputType.dwChannelMask == STEREO) ||
|
|
||||||
(device->FmtChans == DevFmtQuad && OutputType.Format.nChannels == 4 && OutputType.dwChannelMask == QUAD) ||
|
|
||||||
(device->FmtChans == DevFmtX51 && OutputType.Format.nChannels == 6 && OutputType.dwChannelMask == X5DOT1) ||
|
|
||||||
(device->FmtChans == DevFmtX51Side && OutputType.Format.nChannels == 6 && OutputType.dwChannelMask == X5DOT1SIDE) ||
|
|
||||||
(device->FmtChans == DevFmtX61 && OutputType.Format.nChannels == 7 && OutputType.dwChannelMask == X6DOT1) ||
|
|
||||||
(device->FmtChans == DevFmtX71 && OutputType.Format.nChannels == 8 && OutputType.dwChannelMask == X7DOT1)))
|
|
||||||
{
|
|
||||||
if((device->Flags&DEVICE_CHANNELS_REQUEST))
|
|
||||||
ERR("Failed to set %s, got %d channels (0x%08lx) instead\n", DevFmtChannelsString(device->FmtChans), OutputType.Format.nChannels, OutputType.dwChannelMask);
|
|
||||||
device->Flags &= ~DEVICE_CHANNELS_REQUEST;
|
|
||||||
|
|
||||||
if(OutputType.Format.nChannels == 1 && OutputType.dwChannelMask == MONO)
|
|
||||||
device->FmtChans = DevFmtMono;
|
|
||||||
else if(OutputType.Format.nChannels == 2 && OutputType.dwChannelMask == STEREO)
|
|
||||||
device->FmtChans = DevFmtStereo;
|
|
||||||
else if(OutputType.Format.nChannels == 4 && OutputType.dwChannelMask == QUAD)
|
|
||||||
device->FmtChans = DevFmtQuad;
|
|
||||||
else if(OutputType.Format.nChannels == 6 && OutputType.dwChannelMask == X5DOT1)
|
|
||||||
device->FmtChans = DevFmtX51;
|
|
||||||
else if(OutputType.Format.nChannels == 6 && OutputType.dwChannelMask == X5DOT1SIDE)
|
|
||||||
device->FmtChans = DevFmtX51Side;
|
|
||||||
else if(OutputType.Format.nChannels == 7 && OutputType.dwChannelMask == X6DOT1)
|
|
||||||
device->FmtChans = DevFmtX61;
|
|
||||||
else if(OutputType.Format.nChannels == 8 && OutputType.dwChannelMask == X7DOT1)
|
|
||||||
device->FmtChans = DevFmtX71;
|
|
||||||
else
|
|
||||||
{
|
|
||||||
ERR("Unhandled extensible channels: %d -- 0x%08lx\n", OutputType.Format.nChannels, OutputType.dwChannelMask);
|
|
||||||
device->FmtChans = DevFmtStereo;
|
|
||||||
OutputType.Format.nChannels = 2;
|
|
||||||
OutputType.dwChannelMask = STEREO;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if(IsEqualGUID(&OutputType.SubFormat, &KSDATAFORMAT_SUBTYPE_PCM))
|
if(IsEqualGUID(&OutputType.SubFormat, &KSDATAFORMAT_SUBTYPE_PCM))
|
||||||
{
|
{
|
||||||
if(OutputType.Samples.wValidBitsPerSample == 0)
|
if(OutputType.Format.wBitsPerSample == 8)
|
||||||
OutputType.Samples.wValidBitsPerSample = OutputType.Format.wBitsPerSample;
|
device->FmtType = DevFmtUByte;
|
||||||
if(OutputType.Samples.wValidBitsPerSample != OutputType.Format.wBitsPerSample ||
|
else if(OutputType.Format.wBitsPerSample == 16)
|
||||||
!((device->FmtType == DevFmtUByte && OutputType.Format.wBitsPerSample == 8) ||
|
device->FmtType = DevFmtShort;
|
||||||
(device->FmtType == DevFmtShort && OutputType.Format.wBitsPerSample == 16)))
|
else if(OutputType.Format.wBitsPerSample == 32)
|
||||||
|
device->FmtType = DevFmtInt;
|
||||||
|
else
|
||||||
{
|
{
|
||||||
ERR("Failed to set %s samples, got %d/%d-bit instead\n", DevFmtTypeString(device->FmtType), OutputType.Samples.wValidBitsPerSample, OutputType.Format.wBitsPerSample);
|
device->FmtType = DevFmtShort;
|
||||||
if(OutputType.Format.wBitsPerSample == 8)
|
OutputType.Format.wBitsPerSample = 16;
|
||||||
device->FmtType = DevFmtUByte;
|
|
||||||
else if(OutputType.Format.wBitsPerSample == 16)
|
|
||||||
device->FmtType = DevFmtShort;
|
|
||||||
else
|
|
||||||
{
|
|
||||||
device->FmtType = DevFmtShort;
|
|
||||||
OutputType.Format.wBitsPerSample = 16;
|
|
||||||
}
|
|
||||||
OutputType.Samples.wValidBitsPerSample = OutputType.Format.wBitsPerSample;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if(IsEqualGUID(&OutputType.SubFormat, &KSDATAFORMAT_SUBTYPE_IEEE_FLOAT))
|
else if(IsEqualGUID(&OutputType.SubFormat, &KSDATAFORMAT_SUBTYPE_IEEE_FLOAT))
|
||||||
{
|
{
|
||||||
if(OutputType.Samples.wValidBitsPerSample == 0)
|
device->FmtType = DevFmtFloat;
|
||||||
OutputType.Samples.wValidBitsPerSample = OutputType.Format.wBitsPerSample;
|
OutputType.Format.wBitsPerSample = 32;
|
||||||
if(OutputType.Samples.wValidBitsPerSample != OutputType.Format.wBitsPerSample ||
|
|
||||||
!((device->FmtType == DevFmtFloat && OutputType.Format.wBitsPerSample == 32)))
|
|
||||||
{
|
|
||||||
ERR("Failed to set %s samples, got %d/%d-bit instead\n", DevFmtTypeString(device->FmtType), OutputType.Samples.wValidBitsPerSample, OutputType.Format.wBitsPerSample);
|
|
||||||
if(OutputType.Format.wBitsPerSample != 32)
|
|
||||||
{
|
|
||||||
device->FmtType = DevFmtFloat;
|
|
||||||
OutputType.Format.wBitsPerSample = 32;
|
|
||||||
}
|
|
||||||
OutputType.Samples.wValidBitsPerSample = OutputType.Format.wBitsPerSample;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
ERR("Unhandled format sub-type\n");
|
ERR("Unhandled format sub-type\n");
|
||||||
device->FmtType = DevFmtShort;
|
device->FmtType = DevFmtShort;
|
||||||
OutputType.Format.wBitsPerSample = 16;
|
OutputType.Format.wBitsPerSample = 16;
|
||||||
OutputType.Samples.wValidBitsPerSample = OutputType.Format.wBitsPerSample;
|
|
||||||
OutputType.SubFormat = KSDATAFORMAT_SUBTYPE_PCM;
|
OutputType.SubFormat = KSDATAFORMAT_SUBTYPE_PCM;
|
||||||
}
|
}
|
||||||
|
OutputType.Samples.wValidBitsPerSample = OutputType.Format.wBitsPerSample;
|
||||||
}
|
}
|
||||||
|
|
||||||
SetDefaultWFXChannelOrder(device);
|
SetDefaultWFXChannelOrder(device);
|
||||||
|
|
||||||
hr = IAudioClient_GetDevicePeriod(data->client, &min_per, NULL);
|
hr = IAudioClient_Initialize(data->client, AUDCLNT_SHAREMODE_SHARED,
|
||||||
if(SUCCEEDED(hr))
|
AUDCLNT_STREAMFLAGS_EVENTCALLBACK,
|
||||||
{
|
buf_time, 0, &OutputType.Format, NULL);
|
||||||
min_len = (min_per*device->Frequency + 10000000-1) / 10000000;
|
|
||||||
if(min_len < device->UpdateSize)
|
|
||||||
min_len *= (device->UpdateSize + min_len/2)/min_len;
|
|
||||||
|
|
||||||
device->NumUpdates = (device->NumUpdates*device->UpdateSize + min_len/2) /
|
|
||||||
min_len;
|
|
||||||
device->NumUpdates = maxu(device->NumUpdates, 2);
|
|
||||||
device->UpdateSize = min_len;
|
|
||||||
|
|
||||||
hr = IAudioClient_Initialize(data->client, AUDCLNT_SHAREMODE_SHARED,
|
|
||||||
AUDCLNT_STREAMFLAGS_EVENTCALLBACK,
|
|
||||||
((REFERENCE_TIME)device->UpdateSize*
|
|
||||||
device->NumUpdates*10000000 +
|
|
||||||
device->Frequency-1) / device->Frequency,
|
|
||||||
0, &OutputType.Format, NULL);
|
|
||||||
}
|
|
||||||
if(FAILED(hr))
|
if(FAILED(hr))
|
||||||
{
|
{
|
||||||
ERR("Failed to initialize audio client: 0x%08lx\n", hr);
|
ERR("Failed to initialize audio client: 0x%08lx\n", hr);
|
||||||
return hr;
|
return hr;
|
||||||
}
|
}
|
||||||
|
|
||||||
hr = IAudioClient_GetBufferSize(data->client, &buffer_len);
|
hr = IAudioClient_GetDevicePeriod(data->client, &min_per, NULL);
|
||||||
|
if(SUCCEEDED(hr))
|
||||||
|
{
|
||||||
|
min_len = (UINT32)((min_per*device->Frequency + 10000000-1) / 10000000);
|
||||||
|
/* Find the nearest multiple of the period size to the update size */
|
||||||
|
if(min_len < device->UpdateSize)
|
||||||
|
min_len *= (device->UpdateSize + min_len/2)/min_len;
|
||||||
|
hr = IAudioClient_GetBufferSize(data->client, &buffer_len);
|
||||||
|
}
|
||||||
if(FAILED(hr))
|
if(FAILED(hr))
|
||||||
{
|
{
|
||||||
ERR("Failed to get audio buffer info: 0x%08lx\n", hr);
|
ERR("Failed to get audio buffer info: 0x%08lx\n", hr);
|
||||||
return hr;
|
return hr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
device->UpdateSize = min_len;
|
||||||
device->NumUpdates = buffer_len / device->UpdateSize;
|
device->NumUpdates = buffer_len / device->UpdateSize;
|
||||||
if(device->NumUpdates <= 1)
|
if(device->NumUpdates <= 1)
|
||||||
{
|
{
|
||||||
device->NumUpdates = 1;
|
|
||||||
ERR("Audio client returned buffer_len < period*2; expect break up\n");
|
ERR("Audio client returned buffer_len < period*2; expect break up\n");
|
||||||
}
|
device->NumUpdates = 2;
|
||||||
|
device->UpdateSize = buffer_len / device->NumUpdates;
|
||||||
ResetEvent(data->hNotifyEvent);
|
|
||||||
hr = IAudioClient_SetEventHandle(data->client, data->hNotifyEvent);
|
|
||||||
if(SUCCEEDED(hr))
|
|
||||||
hr = IAudioClient_Start(data->client);
|
|
||||||
if(FAILED(hr))
|
|
||||||
{
|
|
||||||
ERR("Failed to start audio client: 0x%08lx\n", hr);
|
|
||||||
return hr;
|
|
||||||
}
|
|
||||||
|
|
||||||
data->thread = StartThread(MMDevApiProc, device);
|
|
||||||
if(!data->thread)
|
|
||||||
{
|
|
||||||
IAudioClient_Stop(data->client);
|
|
||||||
ERR("Failed to start thread\n");
|
|
||||||
return E_FAIL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return hr;
|
return hr;
|
||||||
@ -489,16 +559,16 @@ static DWORD CALLBACK MMDevApiMsgProc(void *ptr)
|
|||||||
ALuint deviceCount = 0;
|
ALuint deviceCount = 0;
|
||||||
MMDevApiData *data;
|
MMDevApiData *data;
|
||||||
ALCdevice *device;
|
ALCdevice *device;
|
||||||
HRESULT hr;
|
HRESULT hr, cohr;
|
||||||
MSG msg;
|
MSG msg;
|
||||||
|
|
||||||
TRACE("Starting message thread\n");
|
TRACE("Starting message thread\n");
|
||||||
|
|
||||||
hr = CoInitialize(NULL);
|
cohr = CoInitialize(NULL);
|
||||||
if(FAILED(hr))
|
if(FAILED(cohr))
|
||||||
{
|
{
|
||||||
WARN("Failed to initialize COM: 0x%08lx\n", hr);
|
WARN("Failed to initialize COM: 0x%08lx\n", cohr);
|
||||||
req->result = hr;
|
req->result = cohr;
|
||||||
SetEvent(req->FinishedEvt);
|
SetEvent(req->FinishedEvt);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -532,28 +602,36 @@ static DWORD CALLBACK MMDevApiMsgProc(void *ptr)
|
|||||||
device = (ALCdevice*)msg.lParam;
|
device = (ALCdevice*)msg.lParam;
|
||||||
data = device->ExtraData;
|
data = device->ExtraData;
|
||||||
|
|
||||||
hr = S_OK;
|
hr = cohr = S_OK;
|
||||||
if(++deviceCount == 1)
|
if(++deviceCount == 1)
|
||||||
hr = CoInitialize(NULL);
|
hr = cohr = CoInitialize(NULL);
|
||||||
if(SUCCEEDED(hr))
|
if(SUCCEEDED(hr))
|
||||||
hr = CoCreateInstance(&CLSID_MMDeviceEnumerator, NULL, CLSCTX_INPROC_SERVER, &IID_IMMDeviceEnumerator, &ptr);
|
hr = CoCreateInstance(&CLSID_MMDeviceEnumerator, NULL, CLSCTX_INPROC_SERVER, &IID_IMMDeviceEnumerator, &ptr);
|
||||||
if(SUCCEEDED(hr))
|
if(SUCCEEDED(hr))
|
||||||
{
|
{
|
||||||
Enumerator = ptr;
|
Enumerator = ptr;
|
||||||
hr = IMMDeviceEnumerator_GetDefaultAudioEndpoint(Enumerator, eRender, eMultimedia, &data->mmdev);
|
if(!data->devid)
|
||||||
|
hr = IMMDeviceEnumerator_GetDefaultAudioEndpoint(Enumerator, eRender, eMultimedia, &data->mmdev);
|
||||||
|
else
|
||||||
|
hr = IMMDeviceEnumerator_GetDevice(Enumerator, data->devid, &data->mmdev);
|
||||||
IMMDeviceEnumerator_Release(Enumerator);
|
IMMDeviceEnumerator_Release(Enumerator);
|
||||||
Enumerator = NULL;
|
Enumerator = NULL;
|
||||||
}
|
}
|
||||||
if(SUCCEEDED(hr))
|
if(SUCCEEDED(hr))
|
||||||
hr = IMMDevice_Activate(data->mmdev, &IID_IAudioClient, CLSCTX_INPROC_SERVER, NULL, &ptr);
|
hr = IMMDevice_Activate(data->mmdev, &IID_IAudioClient, CLSCTX_INPROC_SERVER, NULL, &ptr);
|
||||||
if(SUCCEEDED(hr))
|
if(SUCCEEDED(hr))
|
||||||
|
{
|
||||||
data->client = ptr;
|
data->client = ptr;
|
||||||
|
device->szDeviceName = get_device_name(data->mmdev);
|
||||||
|
}
|
||||||
|
|
||||||
if(FAILED(hr))
|
if(FAILED(hr))
|
||||||
{
|
{
|
||||||
if(data->mmdev)
|
if(data->mmdev)
|
||||||
IMMDevice_Release(data->mmdev);
|
IMMDevice_Release(data->mmdev);
|
||||||
data->mmdev = NULL;
|
data->mmdev = NULL;
|
||||||
|
if(--deviceCount == 0 && SUCCEEDED(cohr))
|
||||||
|
CoUninitialize();
|
||||||
}
|
}
|
||||||
|
|
||||||
req->result = hr;
|
req->result = hr;
|
||||||
@ -568,6 +646,43 @@ static DWORD CALLBACK MMDevApiMsgProc(void *ptr)
|
|||||||
SetEvent(req->FinishedEvt);
|
SetEvent(req->FinishedEvt);
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
case WM_USER_StartDevice:
|
||||||
|
req = (ThreadRequest*)msg.wParam;
|
||||||
|
device = (ALCdevice*)msg.lParam;
|
||||||
|
data = device->ExtraData;
|
||||||
|
|
||||||
|
ResetEvent(data->hNotifyEvent);
|
||||||
|
hr = IAudioClient_SetEventHandle(data->client, data->hNotifyEvent);
|
||||||
|
if(FAILED(hr))
|
||||||
|
ERR("Failed to set event handle: 0x%08lx\n", hr);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
hr = IAudioClient_Start(data->client);
|
||||||
|
if(FAILED(hr))
|
||||||
|
ERR("Failed to start audio client: 0x%08lx\n", hr);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(SUCCEEDED(hr))
|
||||||
|
hr = IAudioClient_GetService(data->client, &IID_IAudioRenderClient, &ptr);
|
||||||
|
if(SUCCEEDED(hr))
|
||||||
|
{
|
||||||
|
data->render = ptr;
|
||||||
|
data->thread = StartThread(MMDevApiProc, device);
|
||||||
|
if(!data->thread)
|
||||||
|
{
|
||||||
|
if(data->render)
|
||||||
|
IAudioRenderClient_Release(data->render);
|
||||||
|
data->render = NULL;
|
||||||
|
IAudioClient_Stop(data->client);
|
||||||
|
ERR("Failed to start thread\n");
|
||||||
|
hr = E_FAIL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
req->result = hr;
|
||||||
|
SetEvent(req->FinishedEvt);
|
||||||
|
continue;
|
||||||
|
|
||||||
case WM_USER_StopDevice:
|
case WM_USER_StopDevice:
|
||||||
req = (ThreadRequest*)msg.wParam;
|
req = (ThreadRequest*)msg.wParam;
|
||||||
device = (ALCdevice*)msg.lParam;
|
device = (ALCdevice*)msg.lParam;
|
||||||
@ -581,6 +696,8 @@ static DWORD CALLBACK MMDevApiMsgProc(void *ptr)
|
|||||||
|
|
||||||
data->killNow = 0;
|
data->killNow = 0;
|
||||||
|
|
||||||
|
IAudioRenderClient_Release(data->render);
|
||||||
|
data->render = NULL;
|
||||||
IAudioClient_Stop(data->client);
|
IAudioClient_Stop(data->client);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -606,6 +723,57 @@ static DWORD CALLBACK MMDevApiMsgProc(void *ptr)
|
|||||||
SetEvent(req->FinishedEvt);
|
SetEvent(req->FinishedEvt);
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
case WM_USER_Enumerate:
|
||||||
|
req = (ThreadRequest*)msg.wParam;
|
||||||
|
|
||||||
|
hr = cohr = S_OK;
|
||||||
|
if(++deviceCount == 1)
|
||||||
|
hr = cohr = CoInitialize(NULL);
|
||||||
|
if(SUCCEEDED(hr))
|
||||||
|
hr = CoCreateInstance(&CLSID_MMDeviceEnumerator, NULL, CLSCTX_INPROC_SERVER, &IID_IMMDeviceEnumerator, &ptr);
|
||||||
|
if(SUCCEEDED(hr))
|
||||||
|
{
|
||||||
|
EDataFlow flowdir;
|
||||||
|
DevMap **devlist;
|
||||||
|
ALuint *numdevs;
|
||||||
|
ALuint i;
|
||||||
|
|
||||||
|
Enumerator = ptr;
|
||||||
|
if(msg.lParam == CAPTURE_DEVICE_PROBE)
|
||||||
|
{
|
||||||
|
flowdir = eCapture;
|
||||||
|
devlist = &CaptureDeviceList;
|
||||||
|
numdevs = &NumCaptureDevices;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
flowdir = eRender;
|
||||||
|
devlist = &PlaybackDeviceList;
|
||||||
|
numdevs = &NumPlaybackDevices;
|
||||||
|
}
|
||||||
|
|
||||||
|
for(i = 0;i < *numdevs;i++)
|
||||||
|
{
|
||||||
|
free((*devlist)[i].name);
|
||||||
|
free((*devlist)[i].devid);
|
||||||
|
}
|
||||||
|
free(*devlist);
|
||||||
|
*devlist = NULL;
|
||||||
|
*numdevs = 0;
|
||||||
|
|
||||||
|
*devlist = ProbeDevices(Enumerator, flowdir, numdevs);
|
||||||
|
|
||||||
|
IMMDeviceEnumerator_Release(Enumerator);
|
||||||
|
Enumerator = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(--deviceCount == 0 && SUCCEEDED(cohr))
|
||||||
|
CoUninitialize();
|
||||||
|
|
||||||
|
req->result = S_OK;
|
||||||
|
SetEvent(req->FinishedEvt);
|
||||||
|
continue;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
ERR("Unexpected message: %u\n", msg.message);
|
ERR("Unexpected message: %u\n", msg.message);
|
||||||
continue;
|
continue;
|
||||||
@ -645,11 +813,6 @@ static ALCenum MMDevApiOpenPlayback(ALCdevice *device, const ALCchar *deviceName
|
|||||||
MMDevApiData *data = NULL;
|
MMDevApiData *data = NULL;
|
||||||
HRESULT hr;
|
HRESULT hr;
|
||||||
|
|
||||||
if(!deviceName)
|
|
||||||
deviceName = mmDevice;
|
|
||||||
else if(strcmp(deviceName, mmDevice) != 0)
|
|
||||||
return ALC_INVALID_VALUE;
|
|
||||||
|
|
||||||
//Initialise requested device
|
//Initialise requested device
|
||||||
data = calloc(1, sizeof(MMDevApiData));
|
data = calloc(1, sizeof(MMDevApiData));
|
||||||
if(!data)
|
if(!data)
|
||||||
@ -662,6 +825,32 @@ static ALCenum MMDevApiOpenPlayback(ALCdevice *device, const ALCchar *deviceName
|
|||||||
if(data->hNotifyEvent == NULL || data->MsgEvent == NULL)
|
if(data->hNotifyEvent == NULL || data->MsgEvent == NULL)
|
||||||
hr = E_FAIL;
|
hr = E_FAIL;
|
||||||
|
|
||||||
|
if(SUCCEEDED(hr))
|
||||||
|
{
|
||||||
|
if(deviceName)
|
||||||
|
{
|
||||||
|
ALuint i;
|
||||||
|
|
||||||
|
if(!PlaybackDeviceList)
|
||||||
|
{
|
||||||
|
ThreadRequest req = { data->MsgEvent, 0 };
|
||||||
|
if(PostThreadMessage(ThreadID, WM_USER_Enumerate, (WPARAM)&req, ALL_DEVICE_PROBE))
|
||||||
|
(void)WaitForResponse(&req);
|
||||||
|
}
|
||||||
|
|
||||||
|
hr = E_FAIL;
|
||||||
|
for(i = 0;i < NumPlaybackDevices;i++)
|
||||||
|
{
|
||||||
|
if(strcmp(deviceName, PlaybackDeviceList[i].name) == 0)
|
||||||
|
{
|
||||||
|
data->devid = strdupW(PlaybackDeviceList[i].devid);
|
||||||
|
hr = S_OK;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if(SUCCEEDED(hr))
|
if(SUCCEEDED(hr))
|
||||||
{
|
{
|
||||||
ThreadRequest req = { data->MsgEvent, 0 };
|
ThreadRequest req = { data->MsgEvent, 0 };
|
||||||
@ -687,7 +876,6 @@ static ALCenum MMDevApiOpenPlayback(ALCdevice *device, const ALCchar *deviceName
|
|||||||
return ALC_INVALID_VALUE;
|
return ALC_INVALID_VALUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
device->szDeviceName = strdup(deviceName);
|
|
||||||
return ALC_NO_ERROR;
|
return ALC_NO_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -705,6 +893,9 @@ static void MMDevApiClosePlayback(ALCdevice *device)
|
|||||||
CloseHandle(data->hNotifyEvent);
|
CloseHandle(data->hNotifyEvent);
|
||||||
data->hNotifyEvent = NULL;
|
data->hNotifyEvent = NULL;
|
||||||
|
|
||||||
|
free(data->devid);
|
||||||
|
data->devid = NULL;
|
||||||
|
|
||||||
free(data);
|
free(data);
|
||||||
device->ExtraData = NULL;
|
device->ExtraData = NULL;
|
||||||
}
|
}
|
||||||
@ -721,6 +912,18 @@ static ALCboolean MMDevApiResetPlayback(ALCdevice *device)
|
|||||||
return SUCCEEDED(hr) ? ALC_TRUE : ALC_FALSE;
|
return SUCCEEDED(hr) ? ALC_TRUE : ALC_FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static ALCboolean MMDevApiStartPlayback(ALCdevice *device)
|
||||||
|
{
|
||||||
|
MMDevApiData *data = device->ExtraData;
|
||||||
|
ThreadRequest req = { data->MsgEvent, 0 };
|
||||||
|
HRESULT hr = E_FAIL;
|
||||||
|
|
||||||
|
if(PostThreadMessage(ThreadID, WM_USER_StartDevice, (WPARAM)&req, (LPARAM)device))
|
||||||
|
hr = WaitForResponse(&req);
|
||||||
|
|
||||||
|
return SUCCEEDED(hr) ? ALC_TRUE : ALC_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
static void MMDevApiStopPlayback(ALCdevice *device)
|
static void MMDevApiStopPlayback(ALCdevice *device)
|
||||||
{
|
{
|
||||||
MMDevApiData *data = device->ExtraData;
|
MMDevApiData *data = device->ExtraData;
|
||||||
@ -735,6 +938,7 @@ static const BackendFuncs MMDevApiFuncs = {
|
|||||||
MMDevApiOpenPlayback,
|
MMDevApiOpenPlayback,
|
||||||
MMDevApiClosePlayback,
|
MMDevApiClosePlayback,
|
||||||
MMDevApiResetPlayback,
|
MMDevApiResetPlayback,
|
||||||
|
MMDevApiStartPlayback,
|
||||||
MMDevApiStopPlayback,
|
MMDevApiStopPlayback,
|
||||||
NULL,
|
NULL,
|
||||||
NULL,
|
NULL,
|
||||||
@ -755,6 +959,26 @@ ALCboolean alcMMDevApiInit(BackendFuncs *FuncList)
|
|||||||
|
|
||||||
void alcMMDevApiDeinit(void)
|
void alcMMDevApiDeinit(void)
|
||||||
{
|
{
|
||||||
|
ALuint i;
|
||||||
|
|
||||||
|
for(i = 0;i < NumPlaybackDevices;i++)
|
||||||
|
{
|
||||||
|
free(PlaybackDeviceList[i].name);
|
||||||
|
free(PlaybackDeviceList[i].devid);
|
||||||
|
}
|
||||||
|
free(PlaybackDeviceList);
|
||||||
|
PlaybackDeviceList = NULL;
|
||||||
|
NumPlaybackDevices = 0;
|
||||||
|
|
||||||
|
for(i = 0;i < NumCaptureDevices;i++)
|
||||||
|
{
|
||||||
|
free(CaptureDeviceList[i].name);
|
||||||
|
free(CaptureDeviceList[i].devid);
|
||||||
|
}
|
||||||
|
free(CaptureDeviceList);
|
||||||
|
CaptureDeviceList = NULL;
|
||||||
|
NumCaptureDevices = 0;
|
||||||
|
|
||||||
if(ThreadHdl)
|
if(ThreadHdl)
|
||||||
{
|
{
|
||||||
TRACE("Sending WM_QUIT to Thread %04lx\n", ThreadID);
|
TRACE("Sending WM_QUIT to Thread %04lx\n", ThreadID);
|
||||||
@ -766,15 +990,32 @@ void alcMMDevApiDeinit(void)
|
|||||||
|
|
||||||
void alcMMDevApiProbe(enum DevProbe type)
|
void alcMMDevApiProbe(enum DevProbe type)
|
||||||
{
|
{
|
||||||
|
ThreadRequest req = { NULL, 0 };
|
||||||
|
HRESULT hr = E_FAIL;
|
||||||
|
|
||||||
switch(type)
|
switch(type)
|
||||||
{
|
{
|
||||||
case DEVICE_PROBE:
|
|
||||||
AppendDeviceList(mmDevice);
|
|
||||||
break;
|
|
||||||
case ALL_DEVICE_PROBE:
|
case ALL_DEVICE_PROBE:
|
||||||
AppendAllDeviceList(mmDevice);
|
req.FinishedEvt = CreateEvent(NULL, FALSE, FALSE, NULL);
|
||||||
|
if(req.FinishedEvt == NULL)
|
||||||
|
ERR("Failed to create event: %lu\n", GetLastError());
|
||||||
|
else if(PostThreadMessage(ThreadID, WM_USER_Enumerate, (WPARAM)&req, type))
|
||||||
|
hr = WaitForResponse(&req);
|
||||||
|
if(SUCCEEDED(hr))
|
||||||
|
{
|
||||||
|
ALuint i;
|
||||||
|
for(i = 0;i < NumPlaybackDevices;i++)
|
||||||
|
{
|
||||||
|
if(PlaybackDeviceList[i].name)
|
||||||
|
AppendAllDeviceList(PlaybackDeviceList[i].name);
|
||||||
|
}
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case CAPTURE_DEVICE_PROBE:
|
case CAPTURE_DEVICE_PROBE:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
if(req.FinishedEvt != NULL)
|
||||||
|
CloseHandle(req.FinishedEvt);
|
||||||
|
req.FinishedEvt = NULL;
|
||||||
}
|
}
|
||||||
|
@ -52,9 +52,9 @@ static ALuint NullProc(ALvoid *ptr)
|
|||||||
avail = (ALuint64)(now-start) * Device->Frequency / 1000;
|
avail = (ALuint64)(now-start) * Device->Frequency / 1000;
|
||||||
if(avail < done)
|
if(avail < done)
|
||||||
{
|
{
|
||||||
/* Timer wrapped. Add the remainder of the cycle to the available
|
/* Timer wrapped (50 days???). Add the remainder of the cycle to
|
||||||
* count and reset the number of samples done */
|
* the available count and reset the number of samples done */
|
||||||
avail += (ALuint64)0xFFFFFFFFu*Device->Frequency/1000 - done;
|
avail += ((ALuint64)1<<32)*Device->Frequency/1000 - done;
|
||||||
done = 0;
|
done = 0;
|
||||||
}
|
}
|
||||||
if(avail-done < Device->UpdateSize)
|
if(avail-done < Device->UpdateSize)
|
||||||
@ -99,9 +99,13 @@ static void null_close_playback(ALCdevice *device)
|
|||||||
|
|
||||||
static ALCboolean null_reset_playback(ALCdevice *device)
|
static ALCboolean null_reset_playback(ALCdevice *device)
|
||||||
{
|
{
|
||||||
null_data *data = (null_data*)device->ExtraData;
|
|
||||||
|
|
||||||
SetDefaultWFXChannelOrder(device);
|
SetDefaultWFXChannelOrder(device);
|
||||||
|
return ALC_TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static ALCboolean null_start_playback(ALCdevice *device)
|
||||||
|
{
|
||||||
|
null_data *data = (null_data*)device->ExtraData;
|
||||||
|
|
||||||
data->thread = StartThread(NullProc, device);
|
data->thread = StartThread(NullProc, device);
|
||||||
if(data->thread == NULL)
|
if(data->thread == NULL)
|
||||||
@ -129,6 +133,7 @@ static const BackendFuncs null_funcs = {
|
|||||||
null_open_playback,
|
null_open_playback,
|
||||||
null_close_playback,
|
null_close_playback,
|
||||||
null_reset_playback,
|
null_reset_playback,
|
||||||
|
null_start_playback,
|
||||||
null_stop_playback,
|
null_stop_playback,
|
||||||
NULL,
|
NULL,
|
||||||
NULL,
|
NULL,
|
||||||
@ -152,9 +157,6 @@ void alc_null_probe(enum DevProbe type)
|
|||||||
{
|
{
|
||||||
switch(type)
|
switch(type)
|
||||||
{
|
{
|
||||||
case DEVICE_PROBE:
|
|
||||||
AppendDeviceList(nullDevice);
|
|
||||||
break;
|
|
||||||
case ALL_DEVICE_PROBE:
|
case ALL_DEVICE_PROBE:
|
||||||
AppendAllDeviceList(nullDevice);
|
AppendAllDeviceList(nullDevice);
|
||||||
break;
|
break;
|
||||||
|
@ -244,6 +244,10 @@ static void opensl_close_playback(ALCdevice *Device)
|
|||||||
{
|
{
|
||||||
osl_data *data = Device->ExtraData;
|
osl_data *data = Device->ExtraData;
|
||||||
|
|
||||||
|
if(data->bufferQueueObject != NULL)
|
||||||
|
SLObjectItf_Destroy(data->bufferQueueObject);
|
||||||
|
data->bufferQueueObject = NULL;
|
||||||
|
|
||||||
SLObjectItf_Destroy(data->outputMix);
|
SLObjectItf_Destroy(data->outputMix);
|
||||||
data->outputMix = NULL;
|
data->outputMix = NULL;
|
||||||
|
|
||||||
@ -259,16 +263,13 @@ static ALCboolean opensl_reset_playback(ALCdevice *Device)
|
|||||||
{
|
{
|
||||||
osl_data *data = Device->ExtraData;
|
osl_data *data = Device->ExtraData;
|
||||||
SLDataLocator_AndroidSimpleBufferQueue loc_bufq;
|
SLDataLocator_AndroidSimpleBufferQueue loc_bufq;
|
||||||
SLAndroidSimpleBufferQueueItf bufferQueue;
|
|
||||||
SLDataLocator_OutputMix loc_outmix;
|
SLDataLocator_OutputMix loc_outmix;
|
||||||
SLDataFormat_PCM format_pcm;
|
SLDataFormat_PCM format_pcm;
|
||||||
SLDataSource audioSrc;
|
SLDataSource audioSrc;
|
||||||
SLDataSink audioSnk;
|
SLDataSink audioSnk;
|
||||||
SLPlayItf player;
|
|
||||||
SLInterfaceID id;
|
SLInterfaceID id;
|
||||||
SLboolean req;
|
SLboolean req;
|
||||||
SLresult result;
|
SLresult result;
|
||||||
ALuint i;
|
|
||||||
|
|
||||||
|
|
||||||
Device->UpdateSize = (ALuint64)Device->UpdateSize * 44100 / Device->Frequency;
|
Device->UpdateSize = (ALuint64)Device->UpdateSize * 44100 / Device->Frequency;
|
||||||
@ -311,6 +312,10 @@ static ALCboolean opensl_reset_playback(ALCdevice *Device)
|
|||||||
audioSnk.pFormat = NULL;
|
audioSnk.pFormat = NULL;
|
||||||
|
|
||||||
|
|
||||||
|
if(data->bufferQueueObject != NULL)
|
||||||
|
SLObjectItf_Destroy(data->bufferQueueObject);
|
||||||
|
data->bufferQueueObject = NULL;
|
||||||
|
|
||||||
result = SLEngineItf_CreateAudioPlayer(data->engine, &data->bufferQueueObject, &audioSrc, &audioSnk, 1, &id, &req);
|
result = SLEngineItf_CreateAudioPlayer(data->engine, &data->bufferQueueObject, &audioSrc, &audioSnk, 1, &id, &req);
|
||||||
PRINTERR(result, "engine->CreateAudioPlayer");
|
PRINTERR(result, "engine->CreateAudioPlayer");
|
||||||
if(SL_RESULT_SUCCESS == result)
|
if(SL_RESULT_SUCCESS == result)
|
||||||
@ -318,11 +323,29 @@ static ALCboolean opensl_reset_playback(ALCdevice *Device)
|
|||||||
result = SLObjectItf_Realize(data->bufferQueueObject, SL_BOOLEAN_FALSE);
|
result = SLObjectItf_Realize(data->bufferQueueObject, SL_BOOLEAN_FALSE);
|
||||||
PRINTERR(result, "bufferQueue->Realize");
|
PRINTERR(result, "bufferQueue->Realize");
|
||||||
}
|
}
|
||||||
if(SL_RESULT_SUCCESS == result)
|
|
||||||
|
if(SL_RESULT_SUCCESS != result)
|
||||||
{
|
{
|
||||||
result = SLObjectItf_GetInterface(data->bufferQueueObject, SL_IID_BUFFERQUEUE, &bufferQueue);
|
if(data->bufferQueueObject != NULL)
|
||||||
PRINTERR(result, "bufferQueue->GetInterface");
|
SLObjectItf_Destroy(data->bufferQueueObject);
|
||||||
|
data->bufferQueueObject = NULL;
|
||||||
|
|
||||||
|
return ALC_FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return ALC_TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static ALCboolean opensl_start_playback(ALCdevice *Device)
|
||||||
|
{
|
||||||
|
osl_data *data = Device->ExtraData;
|
||||||
|
SLAndroidSimpleBufferQueueItf bufferQueue;
|
||||||
|
SLPlayItf player;
|
||||||
|
SLresult result;
|
||||||
|
ALuint i;
|
||||||
|
|
||||||
|
result = SLObjectItf_GetInterface(data->bufferQueueObject, SL_IID_BUFFERQUEUE, &bufferQueue);
|
||||||
|
PRINTERR(result, "bufferQueue->GetInterface");
|
||||||
if(SL_RESULT_SUCCESS == result)
|
if(SL_RESULT_SUCCESS == result)
|
||||||
{
|
{
|
||||||
result = (*bufferQueue)->RegisterCallback(bufferQueue, opensl_callback, Device);
|
result = (*bufferQueue)->RegisterCallback(bufferQueue, opensl_callback, Device);
|
||||||
@ -380,10 +403,6 @@ static void opensl_stop_playback(ALCdevice *Device)
|
|||||||
{
|
{
|
||||||
osl_data *data = Device->ExtraData;
|
osl_data *data = Device->ExtraData;
|
||||||
|
|
||||||
if(data->bufferQueueObject != NULL)
|
|
||||||
SLObjectItf_Destroy(data->bufferQueueObject);
|
|
||||||
data->bufferQueueObject = NULL;
|
|
||||||
|
|
||||||
free(data->buffer);
|
free(data->buffer);
|
||||||
data->buffer = NULL;
|
data->buffer = NULL;
|
||||||
data->bufferSize = 0;
|
data->bufferSize = 0;
|
||||||
@ -394,6 +413,7 @@ static const BackendFuncs opensl_funcs = {
|
|||||||
opensl_open_playback,
|
opensl_open_playback,
|
||||||
opensl_close_playback,
|
opensl_close_playback,
|
||||||
opensl_reset_playback,
|
opensl_reset_playback,
|
||||||
|
opensl_start_playback,
|
||||||
opensl_stop_playback,
|
opensl_stop_playback,
|
||||||
NULL,
|
NULL,
|
||||||
NULL,
|
NULL,
|
||||||
@ -418,9 +438,6 @@ void alc_opensl_probe(enum DevProbe type)
|
|||||||
{
|
{
|
||||||
switch(type)
|
switch(type)
|
||||||
{
|
{
|
||||||
case DEVICE_PROBE:
|
|
||||||
AppendDeviceList(opensl_device);
|
|
||||||
break;
|
|
||||||
case ALL_DEVICE_PROBE:
|
case ALL_DEVICE_PROBE:
|
||||||
AppendAllDeviceList(opensl_device);
|
AppendAllDeviceList(opensl_device);
|
||||||
break;
|
break;
|
||||||
|
@ -49,6 +49,9 @@
|
|||||||
|
|
||||||
static const ALCchar oss_device[] = "OSS Default";
|
static const ALCchar oss_device[] = "OSS Default";
|
||||||
|
|
||||||
|
static const char *oss_driver = "/dev/dsp";
|
||||||
|
static const char *oss_capture = "/dev/dsp";
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
int fd;
|
int fd;
|
||||||
volatile int killNow;
|
volatile int killNow;
|
||||||
@ -149,11 +152,8 @@ static ALuint OSSCaptureProc(ALvoid *ptr)
|
|||||||
|
|
||||||
static ALCenum oss_open_playback(ALCdevice *device, const ALCchar *deviceName)
|
static ALCenum oss_open_playback(ALCdevice *device, const ALCchar *deviceName)
|
||||||
{
|
{
|
||||||
char driver[64];
|
|
||||||
oss_data *data;
|
oss_data *data;
|
||||||
|
|
||||||
strncpy(driver, GetConfigValue("oss", "device", "/dev/dsp"), sizeof(driver)-1);
|
|
||||||
driver[sizeof(driver)-1] = 0;
|
|
||||||
if(!deviceName)
|
if(!deviceName)
|
||||||
deviceName = oss_device;
|
deviceName = oss_device;
|
||||||
else if(strcmp(deviceName, oss_device) != 0)
|
else if(strcmp(deviceName, oss_device) != 0)
|
||||||
@ -162,11 +162,11 @@ static ALCenum oss_open_playback(ALCdevice *device, const ALCchar *deviceName)
|
|||||||
data = (oss_data*)calloc(1, sizeof(oss_data));
|
data = (oss_data*)calloc(1, sizeof(oss_data));
|
||||||
data->killNow = 0;
|
data->killNow = 0;
|
||||||
|
|
||||||
data->fd = open(driver, O_WRONLY);
|
data->fd = open(oss_driver, O_WRONLY);
|
||||||
if(data->fd == -1)
|
if(data->fd == -1)
|
||||||
{
|
{
|
||||||
free(data);
|
free(data);
|
||||||
ERR("Could not open %s: %s\n", driver, strerror(errno));
|
ERR("Could not open %s: %s\n", oss_driver, strerror(errno));
|
||||||
return ALC_INVALID_VALUE;
|
return ALC_INVALID_VALUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -206,6 +206,8 @@ static ALCboolean oss_reset_playback(ALCdevice *device)
|
|||||||
ossFormat = AFMT_U8;
|
ossFormat = AFMT_U8;
|
||||||
break;
|
break;
|
||||||
case DevFmtUShort:
|
case DevFmtUShort:
|
||||||
|
case DevFmtInt:
|
||||||
|
case DevFmtUInt:
|
||||||
case DevFmtFloat:
|
case DevFmtFloat:
|
||||||
device->FmtType = DevFmtShort;
|
device->FmtType = DevFmtShort;
|
||||||
/* fall-through */
|
/* fall-through */
|
||||||
@ -262,21 +264,22 @@ static ALCboolean oss_reset_playback(ALCdevice *device)
|
|||||||
return ALC_FALSE;
|
return ALC_FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(device->Frequency != (ALuint)ossSpeed)
|
device->Frequency = ossSpeed;
|
||||||
{
|
|
||||||
if((device->Flags&DEVICE_FREQUENCY_REQUEST))
|
|
||||||
ERR("Failed to set %dhz, got %dhz instead\n", device->Frequency, ossSpeed);
|
|
||||||
device->Flags &= ~DEVICE_FREQUENCY_REQUEST;
|
|
||||||
device->Frequency = ossSpeed;
|
|
||||||
}
|
|
||||||
device->UpdateSize = info.fragsize / frameSize;
|
device->UpdateSize = info.fragsize / frameSize;
|
||||||
device->NumUpdates = info.fragments + 1;
|
device->NumUpdates = info.fragments + 1;
|
||||||
|
|
||||||
data->data_size = device->UpdateSize * frameSize;
|
|
||||||
data->mix_data = calloc(1, data->data_size);
|
|
||||||
|
|
||||||
SetDefaultChannelOrder(device);
|
SetDefaultChannelOrder(device);
|
||||||
|
|
||||||
|
return ALC_TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static ALCboolean oss_start_playback(ALCdevice *device)
|
||||||
|
{
|
||||||
|
oss_data *data = (oss_data*)device->ExtraData;
|
||||||
|
|
||||||
|
data->data_size = device->UpdateSize * FrameSizeFromDevFmt(device->FmtChans, device->FmtType);
|
||||||
|
data->mix_data = calloc(1, data->data_size);
|
||||||
|
|
||||||
data->thread = StartThread(OSSProc, device);
|
data->thread = StartThread(OSSProc, device);
|
||||||
if(data->thread == NULL)
|
if(data->thread == NULL)
|
||||||
{
|
{
|
||||||
@ -316,15 +319,11 @@ static ALCenum oss_open_capture(ALCdevice *device, const ALCchar *deviceName)
|
|||||||
audio_buf_info info;
|
audio_buf_info info;
|
||||||
ALuint frameSize;
|
ALuint frameSize;
|
||||||
int numChannels;
|
int numChannels;
|
||||||
char driver[64];
|
|
||||||
oss_data *data;
|
oss_data *data;
|
||||||
int ossFormat;
|
int ossFormat;
|
||||||
int ossSpeed;
|
int ossSpeed;
|
||||||
char *err;
|
char *err;
|
||||||
|
|
||||||
strncpy(driver, GetConfigValue("oss", "capture", "/dev/dsp"), sizeof(driver)-1);
|
|
||||||
driver[sizeof(driver)-1] = 0;
|
|
||||||
|
|
||||||
if(!deviceName)
|
if(!deviceName)
|
||||||
deviceName = oss_device;
|
deviceName = oss_device;
|
||||||
else if(strcmp(deviceName, oss_device) != 0)
|
else if(strcmp(deviceName, oss_device) != 0)
|
||||||
@ -333,11 +332,11 @@ static ALCenum oss_open_capture(ALCdevice *device, const ALCchar *deviceName)
|
|||||||
data = (oss_data*)calloc(1, sizeof(oss_data));
|
data = (oss_data*)calloc(1, sizeof(oss_data));
|
||||||
data->killNow = 0;
|
data->killNow = 0;
|
||||||
|
|
||||||
data->fd = open(driver, O_RDONLY);
|
data->fd = open(oss_capture, O_RDONLY);
|
||||||
if(data->fd == -1)
|
if(data->fd == -1)
|
||||||
{
|
{
|
||||||
free(data);
|
free(data);
|
||||||
ERR("Could not open %s: %s\n", driver, strerror(errno));
|
ERR("Could not open %s: %s\n", oss_capture, strerror(errno));
|
||||||
return ALC_INVALID_VALUE;
|
return ALC_INVALID_VALUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -353,9 +352,11 @@ static ALCenum oss_open_capture(ALCdevice *device, const ALCchar *deviceName)
|
|||||||
ossFormat = AFMT_S16_NE;
|
ossFormat = AFMT_S16_NE;
|
||||||
break;
|
break;
|
||||||
case DevFmtUShort:
|
case DevFmtUShort:
|
||||||
|
case DevFmtInt:
|
||||||
|
case DevFmtUInt:
|
||||||
case DevFmtFloat:
|
case DevFmtFloat:
|
||||||
free(data);
|
free(data);
|
||||||
ERR("%s capture samples not supported on OSS\n", DevFmtTypeString(device->FmtType));
|
ERR("%s capture samples not supported\n", DevFmtTypeString(device->FmtType));
|
||||||
return ALC_INVALID_VALUE;
|
return ALC_INVALID_VALUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -479,6 +480,7 @@ static const BackendFuncs oss_funcs = {
|
|||||||
oss_open_playback,
|
oss_open_playback,
|
||||||
oss_close_playback,
|
oss_close_playback,
|
||||||
oss_reset_playback,
|
oss_reset_playback,
|
||||||
|
oss_start_playback,
|
||||||
oss_stop_playback,
|
oss_stop_playback,
|
||||||
oss_open_capture,
|
oss_open_capture,
|
||||||
oss_close_capture,
|
oss_close_capture,
|
||||||
@ -490,6 +492,9 @@ static const BackendFuncs oss_funcs = {
|
|||||||
|
|
||||||
ALCboolean alc_oss_init(BackendFuncs *func_list)
|
ALCboolean alc_oss_init(BackendFuncs *func_list)
|
||||||
{
|
{
|
||||||
|
ConfigValueStr("oss", "device", &oss_driver);
|
||||||
|
ConfigValueStr("oss", "capture", &oss_capture);
|
||||||
|
|
||||||
*func_list = oss_funcs;
|
*func_list = oss_funcs;
|
||||||
return ALC_TRUE;
|
return ALC_TRUE;
|
||||||
}
|
}
|
||||||
@ -502,21 +507,11 @@ void alc_oss_probe(enum DevProbe type)
|
|||||||
{
|
{
|
||||||
switch(type)
|
switch(type)
|
||||||
{
|
{
|
||||||
case DEVICE_PROBE:
|
|
||||||
{
|
|
||||||
#ifdef HAVE_STAT
|
|
||||||
struct stat buf;
|
|
||||||
if(stat(GetConfigValue("oss", "device", "/dev/dsp"), &buf) == 0)
|
|
||||||
#endif
|
|
||||||
AppendDeviceList(oss_device);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case ALL_DEVICE_PROBE:
|
case ALL_DEVICE_PROBE:
|
||||||
{
|
{
|
||||||
#ifdef HAVE_STAT
|
#ifdef HAVE_STAT
|
||||||
struct stat buf;
|
struct stat buf;
|
||||||
if(stat(GetConfigValue("oss", "device", "/dev/dsp"), &buf) == 0)
|
if(stat(oss_device, &buf) == 0)
|
||||||
#endif
|
#endif
|
||||||
AppendAllDeviceList(oss_device);
|
AppendAllDeviceList(oss_device);
|
||||||
}
|
}
|
||||||
@ -526,7 +521,7 @@ void alc_oss_probe(enum DevProbe type)
|
|||||||
{
|
{
|
||||||
#ifdef HAVE_STAT
|
#ifdef HAVE_STAT
|
||||||
struct stat buf;
|
struct stat buf;
|
||||||
if(stat(GetConfigValue("oss", "capture", "/dev/dsp"), &buf) == 0)
|
if(stat(oss_capture, &buf) == 0)
|
||||||
#endif
|
#endif
|
||||||
AppendCaptureDeviceList(oss_device);
|
AppendCaptureDeviceList(oss_device);
|
||||||
}
|
}
|
||||||
|
@ -33,8 +33,8 @@
|
|||||||
static const ALCchar pa_device[] = "PortAudio Default";
|
static const ALCchar pa_device[] = "PortAudio Default";
|
||||||
|
|
||||||
|
|
||||||
static void *pa_handle;
|
|
||||||
#ifdef HAVE_DYNLOAD
|
#ifdef HAVE_DYNLOAD
|
||||||
|
static void *pa_handle;
|
||||||
#define MAKE_FUNC(x) static typeof(x) * p##x
|
#define MAKE_FUNC(x) static typeof(x) * p##x
|
||||||
MAKE_FUNC(Pa_Initialize);
|
MAKE_FUNC(Pa_Initialize);
|
||||||
MAKE_FUNC(Pa_Terminate);
|
MAKE_FUNC(Pa_Terminate);
|
||||||
@ -60,11 +60,11 @@ MAKE_FUNC(Pa_GetStreamInfo);
|
|||||||
|
|
||||||
static ALCboolean pa_load(void)
|
static ALCboolean pa_load(void)
|
||||||
{
|
{
|
||||||
if(!pa_handle)
|
PaError err;
|
||||||
{
|
|
||||||
PaError err;
|
|
||||||
|
|
||||||
#ifdef HAVE_DYNLOAD
|
#ifdef HAVE_DYNLOAD
|
||||||
|
if(!pa_handle)
|
||||||
|
{
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
# define PALIB "portaudio.dll"
|
# define PALIB "portaudio.dll"
|
||||||
#elif defined(__APPLE__) && defined(__MACH__)
|
#elif defined(__APPLE__) && defined(__MACH__)
|
||||||
@ -98,9 +98,6 @@ static ALCboolean pa_load(void)
|
|||||||
LOAD_FUNC(Pa_GetDefaultOutputDevice);
|
LOAD_FUNC(Pa_GetDefaultOutputDevice);
|
||||||
LOAD_FUNC(Pa_GetStreamInfo);
|
LOAD_FUNC(Pa_GetStreamInfo);
|
||||||
#undef LOAD_FUNC
|
#undef LOAD_FUNC
|
||||||
#else
|
|
||||||
pa_handle = (void*)0xDEADBEEF;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if((err=Pa_Initialize()) != paNoError)
|
if((err=Pa_Initialize()) != paNoError)
|
||||||
{
|
{
|
||||||
@ -110,6 +107,13 @@ static ALCboolean pa_load(void)
|
|||||||
return ALC_FALSE;
|
return ALC_FALSE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#else
|
||||||
|
if((err=Pa_Initialize()) != paNoError)
|
||||||
|
{
|
||||||
|
ERR("Pa_Initialize() returned an error: %s\n", Pa_GetErrorText(err));
|
||||||
|
return ALC_FALSE;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
return ALC_TRUE;
|
return ALC_TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -175,6 +179,9 @@ static ALCenum pa_open_playback(ALCdevice *device, const ALCchar *deviceName)
|
|||||||
(float)device->Frequency;
|
(float)device->Frequency;
|
||||||
outParams.hostApiSpecificStreamInfo = NULL;
|
outParams.hostApiSpecificStreamInfo = NULL;
|
||||||
|
|
||||||
|
outParams.channelCount = ((device->FmtChans == DevFmtMono) ? 1 : 2);
|
||||||
|
|
||||||
|
retry_open:
|
||||||
switch(device->FmtType)
|
switch(device->FmtType)
|
||||||
{
|
{
|
||||||
case DevFmtByte:
|
case DevFmtByte:
|
||||||
@ -189,26 +196,32 @@ static ALCenum pa_open_playback(ALCdevice *device, const ALCchar *deviceName)
|
|||||||
case DevFmtShort:
|
case DevFmtShort:
|
||||||
outParams.sampleFormat = paInt16;
|
outParams.sampleFormat = paInt16;
|
||||||
break;
|
break;
|
||||||
|
case DevFmtUInt:
|
||||||
|
device->FmtType = DevFmtInt;
|
||||||
|
/* fall-through */
|
||||||
|
case DevFmtInt:
|
||||||
|
outParams.sampleFormat = paInt32;
|
||||||
|
break;
|
||||||
case DevFmtFloat:
|
case DevFmtFloat:
|
||||||
outParams.sampleFormat = paFloat32;
|
outParams.sampleFormat = paFloat32;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
outParams.channelCount = ((device->FmtChans == DevFmtMono) ? 1 : 2);
|
|
||||||
|
|
||||||
SetDefaultChannelOrder(device);
|
|
||||||
|
|
||||||
err = Pa_OpenStream(&data->stream, NULL, &outParams, device->Frequency,
|
err = Pa_OpenStream(&data->stream, NULL, &outParams, device->Frequency,
|
||||||
device->UpdateSize, paNoFlag, pa_callback, device);
|
device->UpdateSize, paNoFlag, pa_callback, device);
|
||||||
if(err != paNoError)
|
if(err != paNoError)
|
||||||
{
|
{
|
||||||
|
if(device->FmtType == DevFmtFloat)
|
||||||
|
{
|
||||||
|
device->FmtType = DevFmtShort;
|
||||||
|
goto retry_open;
|
||||||
|
}
|
||||||
ERR("Pa_OpenStream() returned an error: %s\n", Pa_GetErrorText(err));
|
ERR("Pa_OpenStream() returned an error: %s\n", Pa_GetErrorText(err));
|
||||||
device->ExtraData = NULL;
|
device->ExtraData = NULL;
|
||||||
free(data);
|
free(data);
|
||||||
return ALC_INVALID_VALUE;
|
return ALC_INVALID_VALUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
device->szDeviceName = strdup(deviceName);
|
|
||||||
|
|
||||||
if((ALuint)outParams.channelCount != ChannelsFromDevFmt(device->FmtChans))
|
if((ALuint)outParams.channelCount != ChannelsFromDevFmt(device->FmtChans))
|
||||||
{
|
{
|
||||||
if(outParams.channelCount != 1 && outParams.channelCount != 2)
|
if(outParams.channelCount != 1 && outParams.channelCount != 2)
|
||||||
@ -224,6 +237,9 @@ static ALCenum pa_open_playback(ALCdevice *device, const ALCchar *deviceName)
|
|||||||
device->Flags &= ~DEVICE_CHANNELS_REQUEST;
|
device->Flags &= ~DEVICE_CHANNELS_REQUEST;
|
||||||
device->FmtChans = ((outParams.channelCount==1) ? DevFmtMono : DevFmtStereo);
|
device->FmtChans = ((outParams.channelCount==1) ? DevFmtMono : DevFmtStereo);
|
||||||
}
|
}
|
||||||
|
SetDefaultChannelOrder(device);
|
||||||
|
|
||||||
|
device->szDeviceName = strdup(deviceName);
|
||||||
|
|
||||||
return ALC_NO_ERROR;
|
return ALC_NO_ERROR;
|
||||||
}
|
}
|
||||||
@ -245,18 +261,19 @@ static ALCboolean pa_reset_playback(ALCdevice *device)
|
|||||||
{
|
{
|
||||||
pa_data *data = (pa_data*)device->ExtraData;
|
pa_data *data = (pa_data*)device->ExtraData;
|
||||||
const PaStreamInfo *streamInfo;
|
const PaStreamInfo *streamInfo;
|
||||||
PaError err;
|
|
||||||
|
|
||||||
streamInfo = Pa_GetStreamInfo(data->stream);
|
streamInfo = Pa_GetStreamInfo(data->stream);
|
||||||
if(device->Frequency != streamInfo->sampleRate)
|
device->Frequency = streamInfo->sampleRate;
|
||||||
{
|
|
||||||
if((device->Flags&DEVICE_FREQUENCY_REQUEST))
|
|
||||||
ERR("PortAudio does not support changing sample rates (wanted %dhz, got %.1fhz)\n", device->Frequency, streamInfo->sampleRate);
|
|
||||||
device->Flags &= ~DEVICE_FREQUENCY_REQUEST;
|
|
||||||
device->Frequency = streamInfo->sampleRate;
|
|
||||||
}
|
|
||||||
device->UpdateSize = data->update_size;
|
device->UpdateSize = data->update_size;
|
||||||
|
|
||||||
|
return ALC_TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static ALCboolean pa_start_playback(ALCdevice *device)
|
||||||
|
{
|
||||||
|
pa_data *data = (pa_data*)device->ExtraData;
|
||||||
|
PaError err;
|
||||||
|
|
||||||
err = Pa_StartStream(data->stream);
|
err = Pa_StartStream(data->stream);
|
||||||
if(err != paNoError)
|
if(err != paNoError)
|
||||||
{
|
{
|
||||||
@ -316,11 +333,15 @@ static ALCenum pa_open_capture(ALCdevice *device, const ALCchar *deviceName)
|
|||||||
case DevFmtShort:
|
case DevFmtShort:
|
||||||
inParams.sampleFormat = paInt16;
|
inParams.sampleFormat = paInt16;
|
||||||
break;
|
break;
|
||||||
|
case DevFmtInt:
|
||||||
|
inParams.sampleFormat = paInt32;
|
||||||
|
break;
|
||||||
case DevFmtFloat:
|
case DevFmtFloat:
|
||||||
inParams.sampleFormat = paFloat32;
|
inParams.sampleFormat = paFloat32;
|
||||||
break;
|
break;
|
||||||
|
case DevFmtUInt:
|
||||||
case DevFmtUShort:
|
case DevFmtUShort:
|
||||||
ERR("Unsigned short samples not supported\n");
|
ERR("%s samples not supported\n", DevFmtTypeString(device->FmtType));
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
inParams.channelCount = ChannelsFromDevFmt(device->FmtChans);
|
inParams.channelCount = ChannelsFromDevFmt(device->FmtChans);
|
||||||
@ -395,6 +416,7 @@ static const BackendFuncs pa_funcs = {
|
|||||||
pa_open_playback,
|
pa_open_playback,
|
||||||
pa_close_playback,
|
pa_close_playback,
|
||||||
pa_reset_playback,
|
pa_reset_playback,
|
||||||
|
pa_start_playback,
|
||||||
pa_stop_playback,
|
pa_stop_playback,
|
||||||
pa_open_capture,
|
pa_open_capture,
|
||||||
pa_close_capture,
|
pa_close_capture,
|
||||||
@ -414,23 +436,22 @@ ALCboolean alc_pa_init(BackendFuncs *func_list)
|
|||||||
|
|
||||||
void alc_pa_deinit(void)
|
void alc_pa_deinit(void)
|
||||||
{
|
{
|
||||||
|
#ifdef HAVE_DYNLOAD
|
||||||
if(pa_handle)
|
if(pa_handle)
|
||||||
{
|
{
|
||||||
Pa_Terminate();
|
Pa_Terminate();
|
||||||
#ifdef HAVE_DYNLOAD
|
|
||||||
CloseLib(pa_handle);
|
CloseLib(pa_handle);
|
||||||
#endif
|
|
||||||
pa_handle = NULL;
|
pa_handle = NULL;
|
||||||
}
|
}
|
||||||
|
#else
|
||||||
|
Pa_Terminate();
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void alc_pa_probe(enum DevProbe type)
|
void alc_pa_probe(enum DevProbe type)
|
||||||
{
|
{
|
||||||
switch(type)
|
switch(type)
|
||||||
{
|
{
|
||||||
case DEVICE_PROBE:
|
|
||||||
AppendDeviceList(pa_device);
|
|
||||||
break;
|
|
||||||
case ALL_DEVICE_PROBE:
|
case ALL_DEVICE_PROBE:
|
||||||
AppendAllDeviceList(pa_device);
|
AppendAllDeviceList(pa_device);
|
||||||
break;
|
break;
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -33,8 +33,8 @@
|
|||||||
static const ALCchar sndio_device[] = "SndIO Default";
|
static const ALCchar sndio_device[] = "SndIO Default";
|
||||||
|
|
||||||
|
|
||||||
static void *sndio_handle;
|
|
||||||
#ifdef HAVE_DYNLOAD
|
#ifdef HAVE_DYNLOAD
|
||||||
|
static void *sndio_handle;
|
||||||
#define MAKE_FUNC(x) static typeof(x) * p##x
|
#define MAKE_FUNC(x) static typeof(x) * p##x
|
||||||
MAKE_FUNC(sio_initpar);
|
MAKE_FUNC(sio_initpar);
|
||||||
MAKE_FUNC(sio_open);
|
MAKE_FUNC(sio_open);
|
||||||
@ -76,9 +76,9 @@ MAKE_FUNC(sio_onvol);
|
|||||||
|
|
||||||
static ALCboolean sndio_load(void)
|
static ALCboolean sndio_load(void)
|
||||||
{
|
{
|
||||||
|
#ifdef HAVE_DYNLOAD
|
||||||
if(!sndio_handle)
|
if(!sndio_handle)
|
||||||
{
|
{
|
||||||
#ifdef HAVE_DYNLOAD
|
|
||||||
sndio_handle = LoadLib("libsndio.so");
|
sndio_handle = LoadLib("libsndio.so");
|
||||||
if(!sndio_handle)
|
if(!sndio_handle)
|
||||||
return ALC_FALSE;
|
return ALC_FALSE;
|
||||||
@ -109,10 +109,8 @@ static ALCboolean sndio_load(void)
|
|||||||
LOAD_FUNC(sio_setvol);
|
LOAD_FUNC(sio_setvol);
|
||||||
LOAD_FUNC(sio_onvol);
|
LOAD_FUNC(sio_onvol);
|
||||||
#undef LOAD_FUNC
|
#undef LOAD_FUNC
|
||||||
#else
|
|
||||||
sndio_handle = (void*)0xDEADBEEF;
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
return ALC_TRUE;
|
return ALC_TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -208,7 +206,6 @@ static ALCboolean sndio_reset_playback(ALCdevice *device)
|
|||||||
sio_initpar(&par);
|
sio_initpar(&par);
|
||||||
|
|
||||||
par.rate = device->Frequency;
|
par.rate = device->Frequency;
|
||||||
|
|
||||||
par.pchan = ((device->FmtChans != DevFmtMono) ? 2 : 1);
|
par.pchan = ((device->FmtChans != DevFmtMono) ? 2 : 1);
|
||||||
|
|
||||||
switch(device->FmtType)
|
switch(device->FmtType)
|
||||||
@ -222,8 +219,6 @@ static ALCboolean sndio_reset_playback(ALCdevice *device)
|
|||||||
par.sig = 0;
|
par.sig = 0;
|
||||||
break;
|
break;
|
||||||
case DevFmtFloat:
|
case DevFmtFloat:
|
||||||
device->FmtType = DevFmtShort;
|
|
||||||
/* fall-through */
|
|
||||||
case DevFmtShort:
|
case DevFmtShort:
|
||||||
par.bits = 16;
|
par.bits = 16;
|
||||||
par.sig = 1;
|
par.sig = 1;
|
||||||
@ -232,6 +227,14 @@ static ALCboolean sndio_reset_playback(ALCdevice *device)
|
|||||||
par.bits = 16;
|
par.bits = 16;
|
||||||
par.sig = 0;
|
par.sig = 0;
|
||||||
break;
|
break;
|
||||||
|
case DevFmtInt:
|
||||||
|
par.bits = 32;
|
||||||
|
par.sig = 1;
|
||||||
|
break;
|
||||||
|
case DevFmtUInt:
|
||||||
|
par.bits = 32;
|
||||||
|
par.sig = 0;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
par.le = SIO_LE_NATIVE;
|
par.le = SIO_LE_NATIVE;
|
||||||
|
|
||||||
@ -239,40 +242,21 @@ static ALCboolean sndio_reset_playback(ALCdevice *device)
|
|||||||
par.appbufsz = device->UpdateSize * (device->NumUpdates-1);
|
par.appbufsz = device->UpdateSize * (device->NumUpdates-1);
|
||||||
if(!par.appbufsz) par.appbufsz = device->UpdateSize;
|
if(!par.appbufsz) par.appbufsz = device->UpdateSize;
|
||||||
|
|
||||||
|
|
||||||
if(!sio_setpar(data->sndHandle, &par) || !sio_getpar(data->sndHandle, &par))
|
if(!sio_setpar(data->sndHandle, &par) || !sio_getpar(data->sndHandle, &par))
|
||||||
{
|
{
|
||||||
ERR("Failed to set device parameters\n");
|
ERR("Failed to set device parameters\n");
|
||||||
return ALC_FALSE;
|
return ALC_FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(par.rate != device->Frequency)
|
|
||||||
{
|
|
||||||
if((device->Flags&DEVICE_FREQUENCY_REQUEST))
|
|
||||||
ERR("Failed to set frequency %uhz, got %uhz instead\n", device->Frequency, par.rate);
|
|
||||||
device->Flags &= ~DEVICE_FREQUENCY_REQUEST;
|
|
||||||
device->Frequency = par.rate;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(par.pchan != ChannelsFromDevFmt(device->FmtChans))
|
|
||||||
{
|
|
||||||
if(par.pchan != 1 && par.pchan != 2)
|
|
||||||
{
|
|
||||||
ERR("Unhandled channel count: %u\n", par.pchan);
|
|
||||||
return ALC_FALSE;
|
|
||||||
}
|
|
||||||
if((device->Flags&DEVICE_CHANNELS_REQUEST))
|
|
||||||
ERR("Failed to set %s, got %u channels instead\n", DevFmtChannelsString(device->FmtChans), par.pchan);
|
|
||||||
device->Flags &= ~DEVICE_CHANNELS_REQUEST;
|
|
||||||
device->FmtChans = ((par.pchan==1) ? DevFmtMono : DevFmtStereo);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(par.bits != par.bps*8)
|
if(par.bits != par.bps*8)
|
||||||
{
|
{
|
||||||
ERR("Padded samples not supported (%u of %u bits)\n", par.bits, par.bps*8);
|
ERR("Padded samples not supported (%u of %u bits)\n", par.bits, par.bps*8);
|
||||||
return ALC_FALSE;
|
return ALC_FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
device->Frequency = par.rate;
|
||||||
|
device->FmtChans = ((par.pchan==1) ? DevFmtMono : DevFmtStereo);
|
||||||
|
|
||||||
if(par.bits == 8 && par.sig == 1)
|
if(par.bits == 8 && par.sig == 1)
|
||||||
device->FmtType = DevFmtByte;
|
device->FmtType = DevFmtByte;
|
||||||
else if(par.bits == 8 && par.sig == 0)
|
else if(par.bits == 8 && par.sig == 0)
|
||||||
@ -281,18 +265,27 @@ static ALCboolean sndio_reset_playback(ALCdevice *device)
|
|||||||
device->FmtType = DevFmtShort;
|
device->FmtType = DevFmtShort;
|
||||||
else if(par.bits == 16 && par.sig == 0)
|
else if(par.bits == 16 && par.sig == 0)
|
||||||
device->FmtType = DevFmtUShort;
|
device->FmtType = DevFmtUShort;
|
||||||
|
else if(par.bits == 32 && par.sig == 1)
|
||||||
|
device->FmtType = DevFmtInt;
|
||||||
|
else if(par.bits == 32 && par.sig == 0)
|
||||||
|
device->FmtType = DevFmtUInt;
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
ERR("Unhandled sample format: %s %u-bit\n", (par.sig?"signed":"unsigned"), par.bits);
|
ERR("Unhandled sample format: %s %u-bit\n", (par.sig?"signed":"unsigned"), par.bits);
|
||||||
return ALC_FALSE;
|
return ALC_FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
device->UpdateSize = par.round;
|
device->UpdateSize = par.round;
|
||||||
device->NumUpdates = (par.bufsz/par.round) + 1;
|
device->NumUpdates = (par.bufsz/par.round) + 1;
|
||||||
|
|
||||||
SetDefaultChannelOrder(device);
|
SetDefaultChannelOrder(device);
|
||||||
|
|
||||||
|
return ALC_TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static ALCboolean sndio_start_playback(ALCdevice *device)
|
||||||
|
{
|
||||||
|
sndio_data *data = device->ExtraData;
|
||||||
|
|
||||||
if(!sio_start(data->sndHandle))
|
if(!sio_start(data->sndHandle))
|
||||||
{
|
{
|
||||||
@ -300,7 +293,7 @@ static ALCboolean sndio_reset_playback(ALCdevice *device)
|
|||||||
return ALC_FALSE;
|
return ALC_FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
data->data_size = device->UpdateSize * par.bps * par.pchan;
|
data->data_size = device->UpdateSize * FrameSizeFromDevFmt(device->FmtChans, device->FmtType);
|
||||||
data->mix_data = calloc(1, data->data_size);
|
data->mix_data = calloc(1, data->data_size);
|
||||||
|
|
||||||
data->thread = StartThread(sndio_proc, device);
|
data->thread = StartThread(sndio_proc, device);
|
||||||
@ -339,6 +332,7 @@ static const BackendFuncs sndio_funcs = {
|
|||||||
sndio_open_playback,
|
sndio_open_playback,
|
||||||
sndio_close_playback,
|
sndio_close_playback,
|
||||||
sndio_reset_playback,
|
sndio_reset_playback,
|
||||||
|
sndio_start_playback,
|
||||||
sndio_stop_playback,
|
sndio_stop_playback,
|
||||||
NULL,
|
NULL,
|
||||||
NULL,
|
NULL,
|
||||||
@ -369,9 +363,6 @@ void alc_sndio_probe(enum DevProbe type)
|
|||||||
{
|
{
|
||||||
switch(type)
|
switch(type)
|
||||||
{
|
{
|
||||||
case DEVICE_PROBE:
|
|
||||||
AppendDeviceList(sndio_device);
|
|
||||||
break;
|
|
||||||
case ALL_DEVICE_PROBE:
|
case ALL_DEVICE_PROBE:
|
||||||
AppendAllDeviceList(sndio_device);
|
AppendAllDeviceList(sndio_device);
|
||||||
break;
|
break;
|
||||||
|
@ -39,6 +39,8 @@
|
|||||||
|
|
||||||
static const ALCchar solaris_device[] = "Solaris Default";
|
static const ALCchar solaris_device[] = "Solaris Default";
|
||||||
|
|
||||||
|
static const char *solaris_driver = "/dev/audio";
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
int fd;
|
int fd;
|
||||||
volatile int killNow;
|
volatile int killNow;
|
||||||
@ -93,12 +95,8 @@ static ALuint SolarisProc(ALvoid *ptr)
|
|||||||
|
|
||||||
static ALCenum solaris_open_playback(ALCdevice *device, const ALCchar *deviceName)
|
static ALCenum solaris_open_playback(ALCdevice *device, const ALCchar *deviceName)
|
||||||
{
|
{
|
||||||
char driver[64];
|
|
||||||
solaris_data *data;
|
solaris_data *data;
|
||||||
|
|
||||||
strncpy(driver, GetConfigValue("solaris", "device", "/dev/audio"), sizeof(driver)-1);
|
|
||||||
driver[sizeof(driver)-1] = 0;
|
|
||||||
|
|
||||||
if(!deviceName)
|
if(!deviceName)
|
||||||
deviceName = solaris_device;
|
deviceName = solaris_device;
|
||||||
else if(strcmp(deviceName, solaris_device) != 0)
|
else if(strcmp(deviceName, solaris_device) != 0)
|
||||||
@ -107,11 +105,11 @@ static ALCenum solaris_open_playback(ALCdevice *device, const ALCchar *deviceNam
|
|||||||
data = (solaris_data*)calloc(1, sizeof(solaris_data));
|
data = (solaris_data*)calloc(1, sizeof(solaris_data));
|
||||||
data->killNow = 0;
|
data->killNow = 0;
|
||||||
|
|
||||||
data->fd = open(driver, O_WRONLY);
|
data->fd = open(solaris_driver, O_WRONLY);
|
||||||
if(data->fd == -1)
|
if(data->fd == -1)
|
||||||
{
|
{
|
||||||
free(data);
|
free(data);
|
||||||
ERR("Could not open %s: %s\n", driver, strerror(errno));
|
ERR("Could not open %s: %s\n", solaris_driver, strerror(errno));
|
||||||
return ALC_INVALID_VALUE;
|
return ALC_INVALID_VALUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -156,6 +154,8 @@ static ALCboolean solaris_reset_playback(ALCdevice *device)
|
|||||||
info.play.encoding = AUDIO_ENCODING_LINEAR8;
|
info.play.encoding = AUDIO_ENCODING_LINEAR8;
|
||||||
break;
|
break;
|
||||||
case DevFmtUShort:
|
case DevFmtUShort:
|
||||||
|
case DevFmtInt:
|
||||||
|
case DevFmtUInt:
|
||||||
case DevFmtFloat:
|
case DevFmtFloat:
|
||||||
device->FmtType = DevFmtShort;
|
device->FmtType = DevFmtShort;
|
||||||
/* fall-through */
|
/* fall-through */
|
||||||
@ -180,32 +180,31 @@ static ALCboolean solaris_reset_playback(ALCdevice *device)
|
|||||||
return ALC_FALSE;
|
return ALC_FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!((info.play.precision == 8 && info.play.encoding == AUDIO_ENCODING_LINEAR &&
|
if(!((info.play.precision == 8 && info.play.encoding == AUDIO_ENCODING_LINEAR8 && device->FmtType == DevFmtUByte) ||
|
||||||
device->FmtType == DevFmtByte) ||
|
(info.play.precision == 8 && info.play.encoding == AUDIO_ENCODING_LINEAR && device->FmtType == DevFmtByte) ||
|
||||||
(info.play.precision == 8 && info.play.encoding == AUDIO_ENCODING_LINEAR8 &&
|
(info.play.precision == 16 && info.play.encoding == AUDIO_ENCODING_LINEAR && device->FmtType == DevFmtShort) ||
|
||||||
device->FmtType == DevFmtUByte) ||
|
(info.play.precision == 32 && info.play.encoding == AUDIO_ENCODING_LINEAR && device->FmtType == DevFmtInt)))
|
||||||
(info.play.precision == 16 && info.play.encoding == AUDIO_ENCODING_LINEAR &&
|
|
||||||
device->FmtType == DevFmtShort)))
|
|
||||||
{
|
{
|
||||||
ERR("Could not set %#x sample type, got %d (%#x)\n",
|
ERR("Could not set %s samples, got %d (0x%x)\n", DevFmtTypeString(device->FmtType),
|
||||||
device->FmtType, info.play.precision, info.play.encoding);
|
info.play.precision, info.play.encoding);
|
||||||
return ALC_FALSE;
|
return ALC_FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(device->Frequency != info.play.sample_rate)
|
device->Frequency = info.play.sample_rate;
|
||||||
{
|
|
||||||
if((device->Flags&DEVICE_FREQUENCY_REQUEST))
|
|
||||||
ERR("Failed to set requested frequency %dhz, got %dhz instead\n", device->Frequency, info.play.sample_rate);
|
|
||||||
device->Flags &= ~DEVICE_FREQUENCY_REQUEST;
|
|
||||||
device->Frequency = info.play.sample_rate;
|
|
||||||
}
|
|
||||||
device->UpdateSize = (info.play.buffer_size/device->NumUpdates) + 1;
|
device->UpdateSize = (info.play.buffer_size/device->NumUpdates) + 1;
|
||||||
|
|
||||||
data->data_size = device->UpdateSize * frameSize;
|
|
||||||
data->mix_data = calloc(1, data->data_size);
|
|
||||||
|
|
||||||
SetDefaultChannelOrder(device);
|
SetDefaultChannelOrder(device);
|
||||||
|
|
||||||
|
return ALC_TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static ALCboolean solaris_start_playback(ALCdevice *device)
|
||||||
|
{
|
||||||
|
solaris_data *data = (solaris_data*)device->ExtraData;
|
||||||
|
|
||||||
|
data->data_size = device->UpdateSize * FrameSizeFromDevFmt(device->FmtChans, device->FmtType);
|
||||||
|
data->mix_data = calloc(1, data->data_size);
|
||||||
|
|
||||||
data->thread = StartThread(SolarisProc, device);
|
data->thread = StartThread(SolarisProc, device);
|
||||||
if(data->thread == NULL)
|
if(data->thread == NULL)
|
||||||
{
|
{
|
||||||
@ -241,6 +240,7 @@ static const BackendFuncs solaris_funcs = {
|
|||||||
solaris_open_playback,
|
solaris_open_playback,
|
||||||
solaris_close_playback,
|
solaris_close_playback,
|
||||||
solaris_reset_playback,
|
solaris_reset_playback,
|
||||||
|
solaris_start_playback,
|
||||||
solaris_stop_playback,
|
solaris_stop_playback,
|
||||||
NULL,
|
NULL,
|
||||||
NULL,
|
NULL,
|
||||||
@ -252,6 +252,8 @@ static const BackendFuncs solaris_funcs = {
|
|||||||
|
|
||||||
ALCboolean alc_solaris_init(BackendFuncs *func_list)
|
ALCboolean alc_solaris_init(BackendFuncs *func_list)
|
||||||
{
|
{
|
||||||
|
ConfigValueStr("solaris", "device", &solaris_driver);
|
||||||
|
|
||||||
*func_list = solaris_funcs;
|
*func_list = solaris_funcs;
|
||||||
return ALC_TRUE;
|
return ALC_TRUE;
|
||||||
}
|
}
|
||||||
@ -262,20 +264,18 @@ void alc_solaris_deinit(void)
|
|||||||
|
|
||||||
void alc_solaris_probe(enum DevProbe type)
|
void alc_solaris_probe(enum DevProbe type)
|
||||||
{
|
{
|
||||||
#ifdef HAVE_STAT
|
|
||||||
struct stat buf;
|
|
||||||
if(stat(GetConfigValue("solaris", "device", "/dev/audio"), &buf) != 0)
|
|
||||||
return;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
switch(type)
|
switch(type)
|
||||||
{
|
{
|
||||||
case DEVICE_PROBE:
|
|
||||||
AppendDeviceList(solaris_device);
|
|
||||||
break;
|
|
||||||
case ALL_DEVICE_PROBE:
|
case ALL_DEVICE_PROBE:
|
||||||
AppendAllDeviceList(solaris_device);
|
{
|
||||||
break;
|
#ifdef HAVE_STAT
|
||||||
|
struct stat buf;
|
||||||
|
if(stat(solaris_driver, &buf) == 0)
|
||||||
|
#endif
|
||||||
|
AppendAllDeviceList(solaris_device);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
case CAPTURE_DEVICE_PROBE:
|
case CAPTURE_DEVICE_PROBE:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -87,14 +87,9 @@ static ALuint WaveProc(ALvoid *ptr)
|
|||||||
ALuint now, start;
|
ALuint now, start;
|
||||||
ALuint64 avail, done;
|
ALuint64 avail, done;
|
||||||
size_t fs;
|
size_t fs;
|
||||||
union {
|
|
||||||
short s;
|
|
||||||
char b[sizeof(short)];
|
|
||||||
} uSB;
|
|
||||||
const ALuint restTime = (ALuint64)pDevice->UpdateSize * 1000 /
|
const ALuint restTime = (ALuint64)pDevice->UpdateSize * 1000 /
|
||||||
pDevice->Frequency / 2;
|
pDevice->Frequency / 2;
|
||||||
|
|
||||||
uSB.s = 1;
|
|
||||||
frameSize = FrameSizeFromDevFmt(pDevice->FmtChans, pDevice->FmtType);
|
frameSize = FrameSizeFromDevFmt(pDevice->FmtChans, pDevice->FmtType);
|
||||||
|
|
||||||
done = 0;
|
done = 0;
|
||||||
@ -106,9 +101,9 @@ static ALuint WaveProc(ALvoid *ptr)
|
|||||||
avail = (ALuint64)(now-start) * pDevice->Frequency / 1000;
|
avail = (ALuint64)(now-start) * pDevice->Frequency / 1000;
|
||||||
if(avail < done)
|
if(avail < done)
|
||||||
{
|
{
|
||||||
/* Timer wrapped. Add the remainder of the cycle to the available
|
/* Timer wrapped (50 days???). Add the remainder of the cycle to
|
||||||
* count and reset the number of samples done */
|
* the available count and reset the number of samples done */
|
||||||
avail += (ALuint64)0xFFFFFFFFu*pDevice->Frequency/1000 - done;
|
avail += ((ALuint64)1<<32)*pDevice->Frequency/1000 - done;
|
||||||
done = 0;
|
done = 0;
|
||||||
}
|
}
|
||||||
if(avail-done < pDevice->UpdateSize)
|
if(avail-done < pDevice->UpdateSize)
|
||||||
@ -122,7 +117,7 @@ static ALuint WaveProc(ALvoid *ptr)
|
|||||||
aluMixData(pDevice, data->buffer, pDevice->UpdateSize);
|
aluMixData(pDevice, data->buffer, pDevice->UpdateSize);
|
||||||
done += pDevice->UpdateSize;
|
done += pDevice->UpdateSize;
|
||||||
|
|
||||||
if(uSB.b[0] != 1)
|
if(!IS_LITTLE_ENDIAN)
|
||||||
{
|
{
|
||||||
ALuint bytesize = BytesFromDevFmt(pDevice->FmtType);
|
ALuint bytesize = BytesFromDevFmt(pDevice->FmtType);
|
||||||
ALubyte *bytes = data->buffer;
|
ALubyte *bytes = data->buffer;
|
||||||
@ -214,8 +209,12 @@ static ALCboolean wave_reset_playback(ALCdevice *device)
|
|||||||
case DevFmtUShort:
|
case DevFmtUShort:
|
||||||
device->FmtType = DevFmtShort;
|
device->FmtType = DevFmtShort;
|
||||||
break;
|
break;
|
||||||
|
case DevFmtUInt:
|
||||||
|
device->FmtType = DevFmtInt;
|
||||||
|
break;
|
||||||
case DevFmtUByte:
|
case DevFmtUByte:
|
||||||
case DevFmtShort:
|
case DevFmtShort:
|
||||||
|
case DevFmtInt:
|
||||||
case DevFmtFloat:
|
case DevFmtFloat:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -259,10 +258,18 @@ static ALCboolean wave_reset_playback(ALCdevice *device)
|
|||||||
ERR("Error writing header: %s\n", strerror(errno));
|
ERR("Error writing header: %s\n", strerror(errno));
|
||||||
return ALC_FALSE;
|
return ALC_FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
data->DataStart = ftell(data->f);
|
data->DataStart = ftell(data->f);
|
||||||
|
|
||||||
data->size = device->UpdateSize * channels * bits / 8;
|
SetDefaultWFXChannelOrder(device);
|
||||||
|
|
||||||
|
return ALC_TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static ALCboolean wave_start_playback(ALCdevice *device)
|
||||||
|
{
|
||||||
|
wave_data *data = (wave_data*)device->ExtraData;
|
||||||
|
|
||||||
|
data->size = device->UpdateSize * FrameSizeFromDevFmt(device->FmtChans, device->FmtType);
|
||||||
data->buffer = malloc(data->size);
|
data->buffer = malloc(data->size);
|
||||||
if(!data->buffer)
|
if(!data->buffer)
|
||||||
{
|
{
|
||||||
@ -270,8 +277,6 @@ static ALCboolean wave_reset_playback(ALCdevice *device)
|
|||||||
return ALC_FALSE;
|
return ALC_FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
SetDefaultWFXChannelOrder(device);
|
|
||||||
|
|
||||||
data->thread = StartThread(WaveProc, device);
|
data->thread = StartThread(WaveProc, device);
|
||||||
if(data->thread == NULL)
|
if(data->thread == NULL)
|
||||||
{
|
{
|
||||||
@ -317,6 +322,7 @@ static const BackendFuncs wave_funcs = {
|
|||||||
wave_open_playback,
|
wave_open_playback,
|
||||||
wave_close_playback,
|
wave_close_playback,
|
||||||
wave_reset_playback,
|
wave_reset_playback,
|
||||||
|
wave_start_playback,
|
||||||
wave_stop_playback,
|
wave_stop_playback,
|
||||||
NULL,
|
NULL,
|
||||||
NULL,
|
NULL,
|
||||||
@ -343,9 +349,6 @@ void alc_wave_probe(enum DevProbe type)
|
|||||||
|
|
||||||
switch(type)
|
switch(type)
|
||||||
{
|
{
|
||||||
case DEVICE_PROBE:
|
|
||||||
AppendDeviceList(waveDevice);
|
|
||||||
break;
|
|
||||||
case ALL_DEVICE_PROBE:
|
case ALL_DEVICE_PROBE:
|
||||||
AppendAllDeviceList(waveDevice);
|
AppendAllDeviceList(waveDevice);
|
||||||
break;
|
break;
|
||||||
|
@ -31,6 +31,10 @@
|
|||||||
#include "AL/al.h"
|
#include "AL/al.h"
|
||||||
#include "AL/alc.h"
|
#include "AL/alc.h"
|
||||||
|
|
||||||
|
#ifndef WAVE_FORMAT_IEEE_FLOAT
|
||||||
|
#define WAVE_FORMAT_IEEE_FLOAT 0x0003
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
// MMSYSTEM Device
|
// MMSYSTEM Device
|
||||||
@ -38,7 +42,7 @@ typedef struct {
|
|||||||
HANDLE hWaveThreadEvent;
|
HANDLE hWaveThreadEvent;
|
||||||
HANDLE hWaveThread;
|
HANDLE hWaveThread;
|
||||||
DWORD ulWaveThreadID;
|
DWORD ulWaveThreadID;
|
||||||
LONG lWaveBuffersCommitted;
|
volatile LONG lWaveBuffersCommitted;
|
||||||
WAVEHDR WaveBuffer[4];
|
WAVEHDR WaveBuffer[4];
|
||||||
|
|
||||||
union {
|
union {
|
||||||
@ -46,14 +50,12 @@ typedef struct {
|
|||||||
HWAVEOUT Out;
|
HWAVEOUT Out;
|
||||||
} hWaveHandle;
|
} hWaveHandle;
|
||||||
|
|
||||||
ALuint Frequency;
|
WAVEFORMATEX wfexFormat;
|
||||||
|
|
||||||
RingBuffer *pRing;
|
RingBuffer *pRing;
|
||||||
} WinMMData;
|
} WinMMData;
|
||||||
|
|
||||||
|
|
||||||
static const ALCchar woDefault[] = "WaveOut Default";
|
|
||||||
|
|
||||||
static ALCchar **PlaybackDeviceList;
|
static ALCchar **PlaybackDeviceList;
|
||||||
static ALuint NumPlaybackDevices;
|
static ALuint NumPlaybackDevices;
|
||||||
static ALCchar **CaptureDeviceList;
|
static ALCchar **CaptureDeviceList;
|
||||||
@ -156,22 +158,8 @@ static void CALLBACK WaveOutProc(HWAVEOUT hDevice,UINT uMsg,DWORD_PTR dwInstance
|
|||||||
if(uMsg != WOM_DONE)
|
if(uMsg != WOM_DONE)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// Decrement number of buffers in use
|
|
||||||
InterlockedDecrement(&pData->lWaveBuffersCommitted);
|
InterlockedDecrement(&pData->lWaveBuffersCommitted);
|
||||||
|
PostThreadMessage(pData->ulWaveThreadID, uMsg, 0, dwParam1);
|
||||||
if(pData->bWaveShutdown == AL_FALSE)
|
|
||||||
{
|
|
||||||
// Notify Wave Processor Thread that a Wave Header has returned
|
|
||||||
PostThreadMessage(pData->ulWaveThreadID, uMsg, 0, dwParam1);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if(pData->lWaveBuffersCommitted == 0)
|
|
||||||
{
|
|
||||||
// Post 'Quit' Message to WaveOut Processor Thread
|
|
||||||
PostThreadMessage(pData->ulWaveThreadID, WM_QUIT, 0, 0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -194,9 +182,16 @@ static DWORD WINAPI PlaybackThreadProc(LPVOID lpParameter)
|
|||||||
|
|
||||||
while(GetMessage(&msg, NULL, 0, 0))
|
while(GetMessage(&msg, NULL, 0, 0))
|
||||||
{
|
{
|
||||||
if(msg.message != WOM_DONE || pData->bWaveShutdown)
|
if(msg.message != WOM_DONE)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
if(pData->bWaveShutdown)
|
||||||
|
{
|
||||||
|
if(pData->lWaveBuffersCommitted == 0)
|
||||||
|
break;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
pWaveHdr = ((LPWAVEHDR)msg.lParam);
|
pWaveHdr = ((LPWAVEHDR)msg.lParam);
|
||||||
|
|
||||||
aluMixData(pDevice, pWaveHdr->lpData, pWaveHdr->dwBufferLength/FrameSize);
|
aluMixData(pDevice, pWaveHdr->lpData, pWaveHdr->dwBufferLength/FrameSize);
|
||||||
@ -232,22 +227,8 @@ static void CALLBACK WaveInProc(HWAVEIN hDevice,UINT uMsg,DWORD_PTR dwInstance,D
|
|||||||
if(uMsg != WIM_DATA)
|
if(uMsg != WIM_DATA)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// Decrement number of buffers in use
|
|
||||||
InterlockedDecrement(&pData->lWaveBuffersCommitted);
|
InterlockedDecrement(&pData->lWaveBuffersCommitted);
|
||||||
|
PostThreadMessage(pData->ulWaveThreadID,uMsg,0,dwParam1);
|
||||||
if(pData->bWaveShutdown == AL_FALSE)
|
|
||||||
{
|
|
||||||
// Notify Wave Processor Thread that a Wave Header has returned
|
|
||||||
PostThreadMessage(pData->ulWaveThreadID,uMsg,0,dwParam1);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if(pData->lWaveBuffersCommitted == 0)
|
|
||||||
{
|
|
||||||
// Post 'Quit' Message to WaveIn Processor Thread
|
|
||||||
PostThreadMessage(pData->ulWaveThreadID,WM_QUIT,0,0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -268,8 +249,12 @@ static DWORD WINAPI CaptureThreadProc(LPVOID lpParameter)
|
|||||||
|
|
||||||
while(GetMessage(&msg, NULL, 0, 0))
|
while(GetMessage(&msg, NULL, 0, 0))
|
||||||
{
|
{
|
||||||
if(msg.message != WIM_DATA || pData->bWaveShutdown)
|
if(msg.message != WIM_DATA)
|
||||||
continue;
|
continue;
|
||||||
|
/* Don't wait for other buffers to finish before quitting. We're
|
||||||
|
* closing so we don't need them. */
|
||||||
|
if(pData->bWaveShutdown)
|
||||||
|
break;
|
||||||
|
|
||||||
pWaveHdr = ((LPWAVEHDR)msg.lParam);
|
pWaveHdr = ((LPWAVEHDR)msg.lParam);
|
||||||
|
|
||||||
@ -293,75 +278,62 @@ static DWORD WINAPI CaptureThreadProc(LPVOID lpParameter)
|
|||||||
|
|
||||||
static ALCenum WinMMOpenPlayback(ALCdevice *pDevice, const ALCchar *deviceName)
|
static ALCenum WinMMOpenPlayback(ALCdevice *pDevice, const ALCchar *deviceName)
|
||||||
{
|
{
|
||||||
WAVEFORMATEX wfexFormat;
|
|
||||||
WinMMData *pData = NULL;
|
WinMMData *pData = NULL;
|
||||||
UINT lDeviceID = 0;
|
UINT lDeviceID = 0;
|
||||||
MMRESULT res;
|
MMRESULT res;
|
||||||
ALuint i = 0;
|
ALuint i = 0;
|
||||||
|
|
||||||
// Find the Device ID matching the deviceName if valid
|
if(!PlaybackDeviceList)
|
||||||
if(!deviceName || strcmp(deviceName, woDefault) == 0)
|
ProbePlaybackDevices();
|
||||||
lDeviceID = WAVE_MAPPER;
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if(!PlaybackDeviceList)
|
|
||||||
ProbePlaybackDevices();
|
|
||||||
|
|
||||||
for(i = 0;i < NumPlaybackDevices;i++)
|
// Find the Device ID matching the deviceName if valid
|
||||||
|
for(i = 0;i < NumPlaybackDevices;i++)
|
||||||
|
{
|
||||||
|
if(PlaybackDeviceList[i] &&
|
||||||
|
(!deviceName || strcmp(deviceName, PlaybackDeviceList[i]) == 0))
|
||||||
{
|
{
|
||||||
if(PlaybackDeviceList[i] &&
|
lDeviceID = i;
|
||||||
strcmp(deviceName, PlaybackDeviceList[i]) == 0)
|
break;
|
||||||
{
|
|
||||||
lDeviceID = i;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if(i == NumPlaybackDevices)
|
|
||||||
return ALC_INVALID_VALUE;
|
|
||||||
}
|
}
|
||||||
|
if(i == NumPlaybackDevices)
|
||||||
|
return ALC_INVALID_VALUE;
|
||||||
|
|
||||||
pData = calloc(1, sizeof(*pData));
|
pData = calloc(1, sizeof(*pData));
|
||||||
if(!pData)
|
if(!pData)
|
||||||
return ALC_OUT_OF_MEMORY;
|
return ALC_OUT_OF_MEMORY;
|
||||||
pDevice->ExtraData = pData;
|
pDevice->ExtraData = pData;
|
||||||
|
|
||||||
if(pDevice->FmtChans != DevFmtMono)
|
retry_open:
|
||||||
|
memset(&pData->wfexFormat, 0, sizeof(WAVEFORMATEX));
|
||||||
|
if(pDevice->FmtType == DevFmtFloat)
|
||||||
{
|
{
|
||||||
if((pDevice->Flags&DEVICE_CHANNELS_REQUEST) &&
|
pData->wfexFormat.wFormatTag = WAVE_FORMAT_IEEE_FLOAT;
|
||||||
pDevice->FmtChans != DevFmtStereo)
|
pData->wfexFormat.wBitsPerSample = 32;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
pData->wfexFormat.wFormatTag = WAVE_FORMAT_PCM;
|
||||||
|
if(pDevice->FmtType == DevFmtUByte || pDevice->FmtType == DevFmtByte)
|
||||||
|
pData->wfexFormat.wBitsPerSample = 8;
|
||||||
|
else
|
||||||
|
pData->wfexFormat.wBitsPerSample = 16;
|
||||||
|
}
|
||||||
|
pData->wfexFormat.nChannels = ((pDevice->FmtChans == DevFmtMono) ? 1 : 2);
|
||||||
|
pData->wfexFormat.nBlockAlign = pData->wfexFormat.wBitsPerSample *
|
||||||
|
pData->wfexFormat.nChannels / 8;
|
||||||
|
pData->wfexFormat.nSamplesPerSec = pDevice->Frequency;
|
||||||
|
pData->wfexFormat.nAvgBytesPerSec = pData->wfexFormat.nSamplesPerSec *
|
||||||
|
pData->wfexFormat.nBlockAlign;
|
||||||
|
pData->wfexFormat.cbSize = 0;
|
||||||
|
|
||||||
|
if((res=waveOutOpen(&pData->hWaveHandle.Out, lDeviceID, &pData->wfexFormat, (DWORD_PTR)&WaveOutProc, (DWORD_PTR)pDevice, CALLBACK_FUNCTION)) != MMSYSERR_NOERROR)
|
||||||
|
{
|
||||||
|
if(pDevice->FmtType == DevFmtFloat)
|
||||||
{
|
{
|
||||||
ERR("Failed to set %s, got Stereo instead\n", DevFmtChannelsString(pDevice->FmtChans));
|
|
||||||
pDevice->Flags &= ~DEVICE_CHANNELS_REQUEST;
|
|
||||||
}
|
|
||||||
pDevice->FmtChans = DevFmtStereo;
|
|
||||||
}
|
|
||||||
switch(pDevice->FmtType)
|
|
||||||
{
|
|
||||||
case DevFmtByte:
|
|
||||||
pDevice->FmtType = DevFmtUByte;
|
|
||||||
break;
|
|
||||||
case DevFmtUShort:
|
|
||||||
case DevFmtFloat:
|
|
||||||
pDevice->FmtType = DevFmtShort;
|
pDevice->FmtType = DevFmtShort;
|
||||||
break;
|
goto retry_open;
|
||||||
case DevFmtUByte:
|
}
|
||||||
case DevFmtShort:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
memset(&wfexFormat, 0, sizeof(WAVEFORMATEX));
|
|
||||||
wfexFormat.wFormatTag = WAVE_FORMAT_PCM;
|
|
||||||
wfexFormat.nChannels = ChannelsFromDevFmt(pDevice->FmtChans);
|
|
||||||
wfexFormat.wBitsPerSample = BytesFromDevFmt(pDevice->FmtType) * 8;
|
|
||||||
wfexFormat.nBlockAlign = wfexFormat.wBitsPerSample *
|
|
||||||
wfexFormat.nChannels / 8;
|
|
||||||
wfexFormat.nSamplesPerSec = pDevice->Frequency;
|
|
||||||
wfexFormat.nAvgBytesPerSec = wfexFormat.nSamplesPerSec *
|
|
||||||
wfexFormat.nBlockAlign;
|
|
||||||
wfexFormat.cbSize = 0;
|
|
||||||
|
|
||||||
if((res=waveOutOpen(&pData->hWaveHandle.Out, lDeviceID, &wfexFormat, (DWORD_PTR)&WaveOutProc, (DWORD_PTR)pDevice, CALLBACK_FUNCTION)) != MMSYSERR_NOERROR)
|
|
||||||
{
|
|
||||||
ERR("waveOutOpen failed: %u\n", res);
|
ERR("waveOutOpen failed: %u\n", res);
|
||||||
goto failure;
|
goto failure;
|
||||||
}
|
}
|
||||||
@ -373,10 +345,7 @@ static ALCenum WinMMOpenPlayback(ALCdevice *pDevice, const ALCchar *deviceName)
|
|||||||
goto failure;
|
goto failure;
|
||||||
}
|
}
|
||||||
|
|
||||||
pData->Frequency = pDevice->Frequency;
|
pDevice->szDeviceName = strdup(PlaybackDeviceList[lDeviceID]);
|
||||||
|
|
||||||
pDevice->szDeviceName = strdup((lDeviceID==WAVE_MAPPER) ? woDefault :
|
|
||||||
PlaybackDeviceList[lDeviceID]);
|
|
||||||
return ALC_NO_ERROR;
|
return ALC_NO_ERROR;
|
||||||
|
|
||||||
failure:
|
failure:
|
||||||
@ -407,6 +376,59 @@ static void WinMMClosePlayback(ALCdevice *device)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static ALCboolean WinMMResetPlayback(ALCdevice *device)
|
static ALCboolean WinMMResetPlayback(ALCdevice *device)
|
||||||
|
{
|
||||||
|
WinMMData *data = (WinMMData*)device->ExtraData;
|
||||||
|
|
||||||
|
device->UpdateSize = (ALuint)((ALuint64)device->UpdateSize *
|
||||||
|
data->wfexFormat.nSamplesPerSec /
|
||||||
|
device->Frequency);
|
||||||
|
device->UpdateSize = (device->UpdateSize*device->NumUpdates + 3) / 4;
|
||||||
|
device->NumUpdates = 4;
|
||||||
|
device->Frequency = data->wfexFormat.nSamplesPerSec;
|
||||||
|
|
||||||
|
if(data->wfexFormat.wFormatTag == WAVE_FORMAT_IEEE_FLOAT)
|
||||||
|
{
|
||||||
|
if(data->wfexFormat.wBitsPerSample == 32)
|
||||||
|
device->FmtType = DevFmtFloat;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ERR("Unhandled IEEE float sample depth: %d\n", data->wfexFormat.wBitsPerSample);
|
||||||
|
return ALC_FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if(data->wfexFormat.wFormatTag == WAVE_FORMAT_PCM)
|
||||||
|
{
|
||||||
|
if(data->wfexFormat.wBitsPerSample == 16)
|
||||||
|
device->FmtType = DevFmtShort;
|
||||||
|
else if(data->wfexFormat.wBitsPerSample == 8)
|
||||||
|
device->FmtType = DevFmtUByte;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ERR("Unhandled PCM sample depth: %d\n", data->wfexFormat.wBitsPerSample);
|
||||||
|
return ALC_FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ERR("Unhandled format tag: 0x%04x\n", data->wfexFormat.wFormatTag);
|
||||||
|
return ALC_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(data->wfexFormat.nChannels == 2)
|
||||||
|
device->FmtChans = DevFmtStereo;
|
||||||
|
else if(data->wfexFormat.nChannels == 1)
|
||||||
|
device->FmtChans = DevFmtMono;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ERR("Unhandled channel count: %d\n", data->wfexFormat.nChannels);
|
||||||
|
return ALC_FALSE;
|
||||||
|
}
|
||||||
|
SetDefaultWFXChannelOrder(device);
|
||||||
|
|
||||||
|
return ALC_TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static ALCboolean WinMMStartPlayback(ALCdevice *device)
|
||||||
{
|
{
|
||||||
WinMMData *pData = (WinMMData*)device->ExtraData;
|
WinMMData *pData = (WinMMData*)device->ExtraData;
|
||||||
ALbyte *BufferData;
|
ALbyte *BufferData;
|
||||||
@ -417,18 +439,6 @@ static ALCboolean WinMMResetPlayback(ALCdevice *device)
|
|||||||
if(pData->hWaveThread == NULL)
|
if(pData->hWaveThread == NULL)
|
||||||
return ALC_FALSE;
|
return ALC_FALSE;
|
||||||
|
|
||||||
device->UpdateSize = (ALuint)((ALuint64)device->UpdateSize *
|
|
||||||
pData->Frequency / device->Frequency);
|
|
||||||
if(device->Frequency != pData->Frequency)
|
|
||||||
{
|
|
||||||
if((device->Flags&DEVICE_FREQUENCY_REQUEST))
|
|
||||||
ERR("WinMM does not support changing sample rates (wanted %dhz, got %dhz)\n", device->Frequency, pData->Frequency);
|
|
||||||
device->Flags &= ~DEVICE_FREQUENCY_REQUEST;
|
|
||||||
device->Frequency = pData->Frequency;
|
|
||||||
}
|
|
||||||
|
|
||||||
SetDefaultWFXChannelOrder(device);
|
|
||||||
|
|
||||||
pData->lWaveBuffersCommitted = 0;
|
pData->lWaveBuffersCommitted = 0;
|
||||||
|
|
||||||
// Create 4 Buffers
|
// Create 4 Buffers
|
||||||
@ -484,7 +494,6 @@ static void WinMMStopPlayback(ALCdevice *device)
|
|||||||
|
|
||||||
static ALCenum WinMMOpenCapture(ALCdevice *pDevice, const ALCchar *deviceName)
|
static ALCenum WinMMOpenCapture(ALCdevice *pDevice, const ALCchar *deviceName)
|
||||||
{
|
{
|
||||||
WAVEFORMATEX wfexCaptureFormat;
|
|
||||||
ALbyte *BufferData = NULL;
|
ALbyte *BufferData = NULL;
|
||||||
DWORD ulCapturedDataSize;
|
DWORD ulCapturedDataSize;
|
||||||
WinMMData *pData = NULL;
|
WinMMData *pData = NULL;
|
||||||
@ -497,53 +506,64 @@ static ALCenum WinMMOpenCapture(ALCdevice *pDevice, const ALCchar *deviceName)
|
|||||||
ProbeCaptureDevices();
|
ProbeCaptureDevices();
|
||||||
|
|
||||||
// Find the Device ID matching the deviceName if valid
|
// Find the Device ID matching the deviceName if valid
|
||||||
if(deviceName)
|
for(i = 0;i < NumCaptureDevices;i++)
|
||||||
{
|
{
|
||||||
for(i = 0;i < NumCaptureDevices;i++)
|
if(CaptureDeviceList[i] &&
|
||||||
|
(!deviceName || strcmp(deviceName, CaptureDeviceList[i]) == 0))
|
||||||
{
|
{
|
||||||
if(CaptureDeviceList[i] &&
|
lDeviceID = i;
|
||||||
strcmp(deviceName, CaptureDeviceList[i]) == 0)
|
break;
|
||||||
{
|
|
||||||
lDeviceID = i;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
for(i = 0;i < NumCaptureDevices;i++)
|
|
||||||
{
|
|
||||||
if(CaptureDeviceList[i])
|
|
||||||
{
|
|
||||||
lDeviceID = i;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(i == NumCaptureDevices)
|
if(i == NumCaptureDevices)
|
||||||
return ALC_INVALID_VALUE;
|
return ALC_INVALID_VALUE;
|
||||||
|
|
||||||
|
switch(pDevice->FmtChans)
|
||||||
|
{
|
||||||
|
case DevFmtMono:
|
||||||
|
case DevFmtStereo:
|
||||||
|
break;
|
||||||
|
|
||||||
|
case DevFmtQuad:
|
||||||
|
case DevFmtX51:
|
||||||
|
case DevFmtX51Side:
|
||||||
|
case DevFmtX61:
|
||||||
|
case DevFmtX71:
|
||||||
|
return ALC_INVALID_ENUM;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch(pDevice->FmtType)
|
||||||
|
{
|
||||||
|
case DevFmtUByte:
|
||||||
|
case DevFmtShort:
|
||||||
|
case DevFmtInt:
|
||||||
|
case DevFmtFloat:
|
||||||
|
break;
|
||||||
|
|
||||||
|
case DevFmtByte:
|
||||||
|
case DevFmtUShort:
|
||||||
|
case DevFmtUInt:
|
||||||
|
return ALC_INVALID_ENUM;
|
||||||
|
}
|
||||||
|
|
||||||
pData = calloc(1, sizeof(*pData));
|
pData = calloc(1, sizeof(*pData));
|
||||||
if(!pData)
|
if(!pData)
|
||||||
return ALC_OUT_OF_MEMORY;
|
return ALC_OUT_OF_MEMORY;
|
||||||
pDevice->ExtraData = pData;
|
pDevice->ExtraData = pData;
|
||||||
|
|
||||||
if((pDevice->FmtChans != DevFmtMono && pDevice->FmtChans != DevFmtStereo) ||
|
memset(&pData->wfexFormat, 0, sizeof(WAVEFORMATEX));
|
||||||
(pDevice->FmtType != DevFmtUByte && pDevice->FmtType != DevFmtShort))
|
pData->wfexFormat.wFormatTag = ((pDevice->FmtType == DevFmtFloat) ?
|
||||||
goto failure;
|
WAVE_FORMAT_IEEE_FLOAT : WAVE_FORMAT_PCM);
|
||||||
|
pData->wfexFormat.nChannels = ChannelsFromDevFmt(pDevice->FmtChans);
|
||||||
|
pData->wfexFormat.wBitsPerSample = BytesFromDevFmt(pDevice->FmtType) * 8;
|
||||||
|
pData->wfexFormat.nBlockAlign = pData->wfexFormat.wBitsPerSample *
|
||||||
|
pData->wfexFormat.nChannels / 8;
|
||||||
|
pData->wfexFormat.nSamplesPerSec = pDevice->Frequency;
|
||||||
|
pData->wfexFormat.nAvgBytesPerSec = pData->wfexFormat.nSamplesPerSec *
|
||||||
|
pData->wfexFormat.nBlockAlign;
|
||||||
|
pData->wfexFormat.cbSize = 0;
|
||||||
|
|
||||||
memset(&wfexCaptureFormat, 0, sizeof(WAVEFORMATEX));
|
if((res=waveInOpen(&pData->hWaveHandle.In, lDeviceID, &pData->wfexFormat, (DWORD_PTR)&WaveInProc, (DWORD_PTR)pDevice, CALLBACK_FUNCTION)) != MMSYSERR_NOERROR)
|
||||||
wfexCaptureFormat.wFormatTag = WAVE_FORMAT_PCM;
|
|
||||||
wfexCaptureFormat.nChannels = ChannelsFromDevFmt(pDevice->FmtChans);
|
|
||||||
wfexCaptureFormat.wBitsPerSample = BytesFromDevFmt(pDevice->FmtType) * 8;
|
|
||||||
wfexCaptureFormat.nBlockAlign = wfexCaptureFormat.wBitsPerSample *
|
|
||||||
wfexCaptureFormat.nChannels / 8;
|
|
||||||
wfexCaptureFormat.nSamplesPerSec = pDevice->Frequency;
|
|
||||||
wfexCaptureFormat.nAvgBytesPerSec = wfexCaptureFormat.nSamplesPerSec *
|
|
||||||
wfexCaptureFormat.nBlockAlign;
|
|
||||||
wfexCaptureFormat.cbSize = 0;
|
|
||||||
|
|
||||||
if((res=waveInOpen(&pData->hWaveHandle.In, lDeviceID, &wfexCaptureFormat, (DWORD_PTR)&WaveInProc, (DWORD_PTR)pDevice, CALLBACK_FUNCTION)) != MMSYSERR_NOERROR)
|
|
||||||
{
|
{
|
||||||
ERR("waveInOpen failed: %u\n", res);
|
ERR("waveInOpen failed: %u\n", res);
|
||||||
goto failure;
|
goto failure;
|
||||||
@ -556,24 +576,22 @@ static ALCenum WinMMOpenCapture(ALCdevice *pDevice, const ALCchar *deviceName)
|
|||||||
goto failure;
|
goto failure;
|
||||||
}
|
}
|
||||||
|
|
||||||
pData->Frequency = pDevice->Frequency;
|
|
||||||
|
|
||||||
// Allocate circular memory buffer for the captured audio
|
// Allocate circular memory buffer for the captured audio
|
||||||
ulCapturedDataSize = pDevice->UpdateSize*pDevice->NumUpdates;
|
ulCapturedDataSize = pDevice->UpdateSize*pDevice->NumUpdates;
|
||||||
|
|
||||||
// Make sure circular buffer is at least 100ms in size
|
// Make sure circular buffer is at least 100ms in size
|
||||||
if(ulCapturedDataSize < (wfexCaptureFormat.nSamplesPerSec / 10))
|
if(ulCapturedDataSize < (pData->wfexFormat.nSamplesPerSec / 10))
|
||||||
ulCapturedDataSize = wfexCaptureFormat.nSamplesPerSec / 10;
|
ulCapturedDataSize = pData->wfexFormat.nSamplesPerSec / 10;
|
||||||
|
|
||||||
pData->pRing = CreateRingBuffer(wfexCaptureFormat.nBlockAlign, ulCapturedDataSize);
|
pData->pRing = CreateRingBuffer(pData->wfexFormat.nBlockAlign, ulCapturedDataSize);
|
||||||
if(!pData->pRing)
|
if(!pData->pRing)
|
||||||
goto failure;
|
goto failure;
|
||||||
|
|
||||||
pData->lWaveBuffersCommitted = 0;
|
pData->lWaveBuffersCommitted = 0;
|
||||||
|
|
||||||
// Create 4 Buffers of 50ms each
|
// Create 4 Buffers of 50ms each
|
||||||
lBufferSize = wfexCaptureFormat.nAvgBytesPerSec / 20;
|
lBufferSize = pData->wfexFormat.nAvgBytesPerSec / 20;
|
||||||
lBufferSize -= (lBufferSize % wfexCaptureFormat.nBlockAlign);
|
lBufferSize -= (lBufferSize % pData->wfexFormat.nBlockAlign);
|
||||||
|
|
||||||
BufferData = calloc(4, lBufferSize);
|
BufferData = calloc(4, lBufferSize);
|
||||||
if(!BufferData)
|
if(!BufferData)
|
||||||
@ -631,13 +649,15 @@ static void WinMMCloseCapture(ALCdevice *pDevice)
|
|||||||
void *buffer = NULL;
|
void *buffer = NULL;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
// Call waveOutReset to shutdown wave device
|
/* Tell the processing thread to quit and wait for it to do so. */
|
||||||
pData->bWaveShutdown = AL_TRUE;
|
pData->bWaveShutdown = AL_TRUE;
|
||||||
waveInReset(pData->hWaveHandle.In);
|
PostThreadMessage(pData->ulWaveThreadID, WM_QUIT, 0, 0);
|
||||||
|
|
||||||
// Wait for signal that Wave Thread has been destroyed
|
|
||||||
WaitForSingleObjectEx(pData->hWaveThreadEvent, 5000, FALSE);
|
WaitForSingleObjectEx(pData->hWaveThreadEvent, 5000, FALSE);
|
||||||
|
|
||||||
|
/* Make sure capture is stopped and all pending buffers are flushed. */
|
||||||
|
waveInReset(pData->hWaveHandle.In);
|
||||||
|
|
||||||
CloseHandle(pData->hWaveThread);
|
CloseHandle(pData->hWaveThread);
|
||||||
pData->hWaveThread = 0;
|
pData->hWaveThread = 0;
|
||||||
|
|
||||||
@ -694,6 +714,7 @@ static const BackendFuncs WinMMFuncs = {
|
|||||||
WinMMOpenPlayback,
|
WinMMOpenPlayback,
|
||||||
WinMMClosePlayback,
|
WinMMClosePlayback,
|
||||||
WinMMResetPlayback,
|
WinMMResetPlayback,
|
||||||
|
WinMMStartPlayback,
|
||||||
WinMMStopPlayback,
|
WinMMStopPlayback,
|
||||||
WinMMOpenCapture,
|
WinMMOpenCapture,
|
||||||
WinMMCloseCapture,
|
WinMMCloseCapture,
|
||||||
@ -735,16 +756,8 @@ void alcWinMMProbe(enum DevProbe type)
|
|||||||
|
|
||||||
switch(type)
|
switch(type)
|
||||||
{
|
{
|
||||||
case DEVICE_PROBE:
|
|
||||||
ProbePlaybackDevices();
|
|
||||||
if(NumPlaybackDevices > 0)
|
|
||||||
AppendDeviceList(woDefault);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case ALL_DEVICE_PROBE:
|
case ALL_DEVICE_PROBE:
|
||||||
ProbePlaybackDevices();
|
ProbePlaybackDevices();
|
||||||
if(NumPlaybackDevices > 0)
|
|
||||||
AppendAllDeviceList(woDefault);
|
|
||||||
for(i = 0;i < NumPlaybackDevices;i++)
|
for(i = 0;i < NumPlaybackDevices;i++)
|
||||||
{
|
{
|
||||||
if(PlaybackDeviceList[i])
|
if(PlaybackDeviceList[i])
|
||||||
|
20
Alc/bs2b.c
20
Alc/bs2b.c
@ -24,6 +24,7 @@
|
|||||||
#include "config.h"
|
#include "config.h"
|
||||||
|
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
#include "bs2b.h"
|
#include "bs2b.h"
|
||||||
|
|
||||||
@ -147,26 +148,9 @@ int bs2b_get_srate(struct bs2b *bs2b)
|
|||||||
|
|
||||||
void bs2b_clear(struct bs2b *bs2b)
|
void bs2b_clear(struct bs2b *bs2b)
|
||||||
{
|
{
|
||||||
int loopv = sizeof(bs2b->last_sample);
|
memset(&bs2b->last_sample, 0, sizeof(bs2b->last_sample));
|
||||||
|
|
||||||
while (loopv)
|
|
||||||
{
|
|
||||||
((char *)&bs2b->last_sample)[--loopv] = 0;
|
|
||||||
}
|
|
||||||
} /* bs2b_clear */
|
} /* 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)
|
void bs2b_cross_feed(struct bs2b *bs2b, float *sample)
|
||||||
{
|
{
|
||||||
/* Lowpass filter */
|
/* Lowpass filter */
|
||||||
|
@ -44,6 +44,12 @@ DEFINE_GUID(IID_IMMDeviceEnumerator, 0xa95664d2, 0x9614, 0x4f35, 0xa7,0x46, 0xd
|
|||||||
DEFINE_GUID(IID_IAudioClient, 0x1cb9ad4c, 0xdbfa, 0x4c32, 0xb1,0x78, 0xc2,0xf5,0x68,0xa7,0x03,0xb2);
|
DEFINE_GUID(IID_IAudioClient, 0x1cb9ad4c, 0xdbfa, 0x4c32, 0xb1,0x78, 0xc2,0xf5,0x68,0xa7,0x03,0xb2);
|
||||||
DEFINE_GUID(IID_IAudioRenderClient, 0xf294acfc, 0x3146, 0x4483, 0xa7,0xbf, 0xad,0xdc,0xa7,0xc2,0x60,0xe2);
|
DEFINE_GUID(IID_IAudioRenderClient, 0xf294acfc, 0x3146, 0x4483, 0xa7,0xbf, 0xad,0xdc,0xa7,0xc2,0x60,0xe2);
|
||||||
|
|
||||||
|
#ifdef HAVE_MMDEVAPI
|
||||||
|
#include <devpropdef.h>
|
||||||
|
|
||||||
|
DEFINE_DEVPROPKEY(DEVPKEY_Device_FriendlyName, 0xa45c254e, 0xdf1c, 0x4efd, 0x80,0x20, 0x67,0xd1,0x46,0xa8,0x50,0xe0, 14);
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "alMain.h"
|
#include "alMain.h"
|
||||||
@ -99,6 +105,22 @@ void *GetSymbol(void *handle, const char *name)
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
WCHAR *strdupW(const WCHAR *str)
|
||||||
|
{
|
||||||
|
const WCHAR *n;
|
||||||
|
WCHAR *ret;
|
||||||
|
size_t len;
|
||||||
|
|
||||||
|
n = str;
|
||||||
|
while(*n) n++;
|
||||||
|
len = n - str;
|
||||||
|
|
||||||
|
ret = calloc(sizeof(WCHAR), len+1);
|
||||||
|
if(ret != NULL)
|
||||||
|
memcpy(ret, str, sizeof(WCHAR)*len);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
|
||||||
void InitializeCriticalSection(CRITICAL_SECTION *cs)
|
void InitializeCriticalSection(CRITICAL_SECTION *cs)
|
||||||
|
20
Alc/hrtf.c
20
Alc/hrtf.c
@ -28,21 +28,6 @@
|
|||||||
#include "alMain.h"
|
#include "alMain.h"
|
||||||
#include "alSource.h"
|
#include "alSource.h"
|
||||||
|
|
||||||
/* External HRTF file format (LE byte order):
|
|
||||||
*
|
|
||||||
* ALchar magic[8] = "MinPHR00";
|
|
||||||
* ALuint sampleRate;
|
|
||||||
*
|
|
||||||
* ALushort hrirCount; // Required value: 828
|
|
||||||
* ALushort hrirSize; // Required value: 32
|
|
||||||
* ALubyte evCount; // Required value: 19
|
|
||||||
*
|
|
||||||
* ALushort evOffset[evCount]; // Required values:
|
|
||||||
* { 0, 1, 13, 37, 73, 118, 174, 234, 306, 378, 450, 522, 594, 654, 710, 755, 791, 815, 827 }
|
|
||||||
*
|
|
||||||
* ALshort coefficients[hrirCount][hrirSize];
|
|
||||||
* ALubyte delays[hrirCount]; // Element values must not exceed 127
|
|
||||||
*/
|
|
||||||
|
|
||||||
static const ALchar magicMarker[8] = "MinPHR00";
|
static const ALchar magicMarker[8] = "MinPHR00";
|
||||||
|
|
||||||
@ -94,7 +79,7 @@ static void CalcAzIndices(ALuint evidx, ALfloat az, ALuint *azidx, ALfloat *azmu
|
|||||||
// values.
|
// values.
|
||||||
ALfloat CalcHrtfDelta(ALfloat oldGain, ALfloat newGain, const ALfloat olddir[3], const ALfloat newdir[3])
|
ALfloat CalcHrtfDelta(ALfloat oldGain, ALfloat newGain, const ALfloat olddir[3], const ALfloat newdir[3])
|
||||||
{
|
{
|
||||||
ALfloat gainChange, angleChange;
|
ALfloat gainChange, angleChange, change;
|
||||||
|
|
||||||
// Calculate the normalized dB gain change.
|
// Calculate the normalized dB gain change.
|
||||||
newGain = maxf(newGain, 0.0001f);
|
newGain = maxf(newGain, 0.0001f);
|
||||||
@ -117,7 +102,8 @@ ALfloat CalcHrtfDelta(ALfloat oldGain, ALfloat newGain, const ALfloat olddir[3],
|
|||||||
|
|
||||||
// Use the largest of the two changes for the delta factor, and apply a
|
// Use the largest of the two changes for the delta factor, and apply a
|
||||||
// significance shaping function to it.
|
// significance shaping function to it.
|
||||||
return clampf(angleChange*2.0f, gainChange*2.0f, 1.0f);
|
change = maxf(angleChange, gainChange) * 2.0f;
|
||||||
|
return minf(change, 1.0f);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Calculates static HRIR coefficients and delays for the given polar
|
// Calculates static HRIR coefficients and delays for the given polar
|
||||||
|
22
Alc/mixer.c
22
Alc/mixer.c
@ -251,7 +251,7 @@ static void Mix_Hrtf_##T##_##sampler(ALsource *Source, ALCdevice *Device, \
|
|||||||
ALfloat *RESTRICT WetPendingClicks; \
|
ALfloat *RESTRICT WetPendingClicks; \
|
||||||
FILTER *WetFilter; \
|
FILTER *WetFilter; \
|
||||||
\
|
\
|
||||||
if(!Slot || Slot->effect.type == AL_EFFECT_NULL) \
|
if(Slot == NULL) \
|
||||||
continue; \
|
continue; \
|
||||||
\
|
\
|
||||||
WetBuffer = Slot->WetBuffer; \
|
WetBuffer = Slot->WetBuffer; \
|
||||||
@ -381,7 +381,7 @@ static void Mix_##T##_##sampler(ALsource *Source, ALCdevice *Device, \
|
|||||||
ALfloat *WetPendingClicks; \
|
ALfloat *WetPendingClicks; \
|
||||||
FILTER *WetFilter; \
|
FILTER *WetFilter; \
|
||||||
\
|
\
|
||||||
if(!Slot || Slot->effect.type == AL_EFFECT_NULL) \
|
if(Slot == NULL) \
|
||||||
continue; \
|
continue; \
|
||||||
\
|
\
|
||||||
WetBuffer = Slot->WetBuffer; \
|
WetBuffer = Slot->WetBuffer; \
|
||||||
@ -439,14 +439,13 @@ MixerFunc SelectMixer(enum Resampler Resampler)
|
|||||||
{
|
{
|
||||||
switch(Resampler)
|
switch(Resampler)
|
||||||
{
|
{
|
||||||
case POINT_RESAMPLER:
|
case PointResampler:
|
||||||
return Mix_ALfloat_point32;
|
return Mix_ALfloat_point32;
|
||||||
case LINEAR_RESAMPLER:
|
case LinearResampler:
|
||||||
return Mix_ALfloat_lerp32;
|
return Mix_ALfloat_lerp32;
|
||||||
case CUBIC_RESAMPLER:
|
case CubicResampler:
|
||||||
return Mix_ALfloat_cubic32;
|
return Mix_ALfloat_cubic32;
|
||||||
case RESAMPLER_MIN:
|
case ResamplerMax:
|
||||||
case RESAMPLER_MAX:
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
return NULL;
|
return NULL;
|
||||||
@ -456,14 +455,13 @@ MixerFunc SelectHrtfMixer(enum Resampler Resampler)
|
|||||||
{
|
{
|
||||||
switch(Resampler)
|
switch(Resampler)
|
||||||
{
|
{
|
||||||
case POINT_RESAMPLER:
|
case PointResampler:
|
||||||
return Mix_Hrtf_ALfloat_point32;
|
return Mix_Hrtf_ALfloat_point32;
|
||||||
case LINEAR_RESAMPLER:
|
case LinearResampler:
|
||||||
return Mix_Hrtf_ALfloat_lerp32;
|
return Mix_Hrtf_ALfloat_lerp32;
|
||||||
case CUBIC_RESAMPLER:
|
case CubicResampler:
|
||||||
return Mix_Hrtf_ALfloat_cubic32;
|
return Mix_Hrtf_ALfloat_cubic32;
|
||||||
case RESAMPLER_MIN:
|
case ResamplerMax:
|
||||||
case RESAMPLER_MAX:
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
return NULL;
|
return NULL;
|
||||||
|
@ -167,6 +167,7 @@ ALint aluCart2LUTpos(ALfloat re, ALfloat im)
|
|||||||
ALvoid aluInitPanning(ALCdevice *Device)
|
ALvoid aluInitPanning(ALCdevice *Device)
|
||||||
{
|
{
|
||||||
ALfloat SpeakerAngle[MAXCHANNELS];
|
ALfloat SpeakerAngle[MAXCHANNELS];
|
||||||
|
const char *layoutname = NULL;
|
||||||
enum Channel *Speaker2Chan;
|
enum Channel *Speaker2Chan;
|
||||||
ALfloat Alpha, Theta;
|
ALfloat Alpha, Theta;
|
||||||
ALint pos;
|
ALint pos;
|
||||||
@ -179,6 +180,7 @@ ALvoid aluInitPanning(ALCdevice *Device)
|
|||||||
Device->NumChan = 1;
|
Device->NumChan = 1;
|
||||||
Speaker2Chan[0] = FRONT_CENTER;
|
Speaker2Chan[0] = FRONT_CENTER;
|
||||||
SpeakerAngle[0] = F_PI/180.0f * 0.0f;
|
SpeakerAngle[0] = F_PI/180.0f * 0.0f;
|
||||||
|
layoutname = NULL;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case DevFmtStereo:
|
case DevFmtStereo:
|
||||||
@ -187,7 +189,7 @@ ALvoid aluInitPanning(ALCdevice *Device)
|
|||||||
Speaker2Chan[1] = FRONT_RIGHT;
|
Speaker2Chan[1] = FRONT_RIGHT;
|
||||||
SpeakerAngle[0] = F_PI/180.0f * -90.0f;
|
SpeakerAngle[0] = F_PI/180.0f * -90.0f;
|
||||||
SpeakerAngle[1] = F_PI/180.0f * 90.0f;
|
SpeakerAngle[1] = F_PI/180.0f * 90.0f;
|
||||||
SetSpeakerArrangement("layout_STEREO", SpeakerAngle, Speaker2Chan, Device->NumChan);
|
layoutname = "layout_stereo";
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case DevFmtQuad:
|
case DevFmtQuad:
|
||||||
@ -200,7 +202,7 @@ ALvoid aluInitPanning(ALCdevice *Device)
|
|||||||
SpeakerAngle[1] = F_PI/180.0f * -45.0f;
|
SpeakerAngle[1] = F_PI/180.0f * -45.0f;
|
||||||
SpeakerAngle[2] = F_PI/180.0f * 45.0f;
|
SpeakerAngle[2] = F_PI/180.0f * 45.0f;
|
||||||
SpeakerAngle[3] = F_PI/180.0f * 135.0f;
|
SpeakerAngle[3] = F_PI/180.0f * 135.0f;
|
||||||
SetSpeakerArrangement("layout_QUAD", SpeakerAngle, Speaker2Chan, Device->NumChan);
|
layoutname = "layout_quad";
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case DevFmtX51:
|
case DevFmtX51:
|
||||||
@ -215,7 +217,7 @@ ALvoid aluInitPanning(ALCdevice *Device)
|
|||||||
SpeakerAngle[2] = F_PI/180.0f * 0.0f;
|
SpeakerAngle[2] = F_PI/180.0f * 0.0f;
|
||||||
SpeakerAngle[3] = F_PI/180.0f * 30.0f;
|
SpeakerAngle[3] = F_PI/180.0f * 30.0f;
|
||||||
SpeakerAngle[4] = F_PI/180.0f * 110.0f;
|
SpeakerAngle[4] = F_PI/180.0f * 110.0f;
|
||||||
SetSpeakerArrangement("layout_51CHN", SpeakerAngle, Speaker2Chan, Device->NumChan);
|
layoutname = "layout_surround51";
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case DevFmtX51Side:
|
case DevFmtX51Side:
|
||||||
@ -230,7 +232,7 @@ ALvoid aluInitPanning(ALCdevice *Device)
|
|||||||
SpeakerAngle[2] = F_PI/180.0f * 0.0f;
|
SpeakerAngle[2] = F_PI/180.0f * 0.0f;
|
||||||
SpeakerAngle[3] = F_PI/180.0f * 30.0f;
|
SpeakerAngle[3] = F_PI/180.0f * 30.0f;
|
||||||
SpeakerAngle[4] = F_PI/180.0f * 90.0f;
|
SpeakerAngle[4] = F_PI/180.0f * 90.0f;
|
||||||
SetSpeakerArrangement("layout_51SIDECHN", SpeakerAngle, Speaker2Chan, Device->NumChan);
|
layoutname = "layout_side51";
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case DevFmtX61:
|
case DevFmtX61:
|
||||||
@ -247,7 +249,7 @@ ALvoid aluInitPanning(ALCdevice *Device)
|
|||||||
SpeakerAngle[3] = F_PI/180.0f * 30.0f;
|
SpeakerAngle[3] = F_PI/180.0f * 30.0f;
|
||||||
SpeakerAngle[4] = F_PI/180.0f * 90.0f;
|
SpeakerAngle[4] = F_PI/180.0f * 90.0f;
|
||||||
SpeakerAngle[5] = F_PI/180.0f * 180.0f;
|
SpeakerAngle[5] = F_PI/180.0f * 180.0f;
|
||||||
SetSpeakerArrangement("layout_61CHN", SpeakerAngle, Speaker2Chan, Device->NumChan);
|
layoutname = "layout_surround61";
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case DevFmtX71:
|
case DevFmtX71:
|
||||||
@ -266,9 +268,11 @@ ALvoid aluInitPanning(ALCdevice *Device)
|
|||||||
SpeakerAngle[4] = F_PI/180.0f * 30.0f;
|
SpeakerAngle[4] = F_PI/180.0f * 30.0f;
|
||||||
SpeakerAngle[5] = F_PI/180.0f * 90.0f;
|
SpeakerAngle[5] = F_PI/180.0f * 90.0f;
|
||||||
SpeakerAngle[6] = F_PI/180.0f * 150.0f;
|
SpeakerAngle[6] = F_PI/180.0f * 150.0f;
|
||||||
SetSpeakerArrangement("layout_71CHN", SpeakerAngle, Speaker2Chan, Device->NumChan);
|
layoutname = "layout_surround71";
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
if(layoutname && Device->Type != Loopback)
|
||||||
|
SetSpeakerArrangement(layoutname, SpeakerAngle, Speaker2Chan, Device->NumChan);
|
||||||
|
|
||||||
for(pos = 0; pos < LUT_NUM; pos++)
|
for(pos = 0; pos < LUT_NUM; pos++)
|
||||||
{
|
{
|
||||||
|
@ -17,6 +17,7 @@ INCLUDE(CheckSymbolExists)
|
|||||||
INCLUDE(CheckCCompilerFlag)
|
INCLUDE(CheckCCompilerFlag)
|
||||||
INCLUDE(CheckCSourceCompiles)
|
INCLUDE(CheckCSourceCompiles)
|
||||||
INCLUDE(CheckTypeSize)
|
INCLUDE(CheckTypeSize)
|
||||||
|
INCLUDE(FindPkgConfig)
|
||||||
|
|
||||||
|
|
||||||
PROJECT(OpenAL C)
|
PROJECT(OpenAL C)
|
||||||
@ -59,12 +60,14 @@ OPTION(WERROR "Treat compile warnings as errors" OFF)
|
|||||||
|
|
||||||
OPTION(UTILS "Build and install utility programs" ON)
|
OPTION(UTILS "Build and install utility programs" ON)
|
||||||
|
|
||||||
|
OPTION(EXAMPLES "Build and install example programs" ON)
|
||||||
|
|
||||||
OPTION(ALSOFT_CONFIG "Install alsoft.conf configuration file" OFF)
|
OPTION(ALSOFT_CONFIG "Install alsoft.conf configuration file" OFF)
|
||||||
|
|
||||||
|
|
||||||
IF(WIN32)
|
IF(WIN32)
|
||||||
SET(LIBNAME OpenAL32)
|
SET(LIBNAME OpenAL32)
|
||||||
ADD_DEFINITIONS("-D_WIN32 -D_WIN32_WINNT=0x0500")
|
ADD_DEFINITIONS("-D_WIN32 -D_WIN32_WINNT=0x0501")
|
||||||
ELSE()
|
ELSE()
|
||||||
SET(LIBNAME openal)
|
SET(LIBNAME openal)
|
||||||
ENDIF()
|
ENDIF()
|
||||||
@ -332,7 +335,7 @@ IF(DLOPEN)
|
|||||||
ENDIF()
|
ENDIF()
|
||||||
|
|
||||||
# Check if we have Windows headers
|
# Check if we have Windows headers
|
||||||
CHECK_INCLUDE_FILE(windows.h HAVE_WINDOWS_H -D_WIN32_WINNT=0x0500)
|
CHECK_INCLUDE_FILE(windows.h HAVE_WINDOWS_H -D_WIN32_WINNT=0x0501)
|
||||||
IF(NOT HAVE_WINDOWS_H)
|
IF(NOT HAVE_WINDOWS_H)
|
||||||
CHECK_FUNCTION_EXISTS(gettimeofday HAVE_GETTIMEOFDAY)
|
CHECK_FUNCTION_EXISTS(gettimeofday HAVE_GETTIMEOFDAY)
|
||||||
IF(NOT HAVE_GETTIMEOFDAY)
|
IF(NOT HAVE_GETTIMEOFDAY)
|
||||||
@ -378,7 +381,7 @@ ENDIF()
|
|||||||
CHECK_INCLUDE_FILE(stdint.h HAVE_STDINT_H)
|
CHECK_INCLUDE_FILE(stdint.h HAVE_STDINT_H)
|
||||||
IF(NOT HAVE_STDINT_H)
|
IF(NOT HAVE_STDINT_H)
|
||||||
IF(HAVE_WINDOWS_H)
|
IF(HAVE_WINDOWS_H)
|
||||||
CHECK_C_SOURCE_COMPILES("\#define _WIN32_WINNT 0x0500
|
CHECK_C_SOURCE_COMPILES("\#define _WIN32_WINNT 0x0501
|
||||||
\#include <windows.h>
|
\#include <windows.h>
|
||||||
__int64 foo;
|
__int64 foo;
|
||||||
int main() {return 0;}" HAVE___INT64)
|
int main() {return 0;}" HAVE___INT64)
|
||||||
@ -436,6 +439,7 @@ SET(HAVE_OSS 0)
|
|||||||
SET(HAVE_SOLARIS 0)
|
SET(HAVE_SOLARIS 0)
|
||||||
SET(HAVE_SNDIO 0)
|
SET(HAVE_SNDIO 0)
|
||||||
SET(HAVE_DSOUND 0)
|
SET(HAVE_DSOUND 0)
|
||||||
|
SET(HAVE_MMDEVAPI 0)
|
||||||
SET(HAVE_WINMM 0)
|
SET(HAVE_WINMM 0)
|
||||||
SET(HAVE_PORTAUDIO 0)
|
SET(HAVE_PORTAUDIO 0)
|
||||||
SET(HAVE_PULSEAUDIO 0)
|
SET(HAVE_PULSEAUDIO 0)
|
||||||
@ -552,7 +556,7 @@ ENDIF()
|
|||||||
|
|
||||||
IF(HAVE_WINDOWS_H)
|
IF(HAVE_WINDOWS_H)
|
||||||
IF(WINMM)
|
IF(WINMM)
|
||||||
CHECK_INCLUDE_FILES("windows.h;mmsystem.h" HAVE_MMSYSTEM_H -D_WIN32_WINNT=0x0500)
|
CHECK_INCLUDE_FILES("windows.h;mmsystem.h" HAVE_MMSYSTEM_H -D_WIN32_WINNT=0x0501)
|
||||||
IF(HAVE_MMSYSTEM_H AND HAVE_LIBWINMM)
|
IF(HAVE_MMSYSTEM_H AND HAVE_LIBWINMM)
|
||||||
SET(HAVE_WINMM 1)
|
SET(HAVE_WINMM 1)
|
||||||
SET(ALC_OBJS ${ALC_OBJS} Alc/backends/winmm.c)
|
SET(ALC_OBJS ${ALC_OBJS} Alc/backends/winmm.c)
|
||||||
@ -616,6 +620,18 @@ IF(COREAUDIO)
|
|||||||
SET(EXTRA_LIBS /System/Library/Frameworks/CoreAudio.framework ${EXTRA_LIBS})
|
SET(EXTRA_LIBS /System/Library/Frameworks/CoreAudio.framework ${EXTRA_LIBS})
|
||||||
SET(EXTRA_LIBS /System/Library/Frameworks/AudioUnit.framework ${EXTRA_LIBS})
|
SET(EXTRA_LIBS /System/Library/Frameworks/AudioUnit.framework ${EXTRA_LIBS})
|
||||||
SET(EXTRA_LIBS /System/Library/Frameworks/ApplicationServices.framework ${EXTRA_LIBS})
|
SET(EXTRA_LIBS /System/Library/Frameworks/ApplicationServices.framework ${EXTRA_LIBS})
|
||||||
|
|
||||||
|
# Some versions of OSX may need the AudioToolbox framework. Add it if
|
||||||
|
# it's found.
|
||||||
|
FIND_LIBRARY(AUDIOTOOLBOX_LIBRARY
|
||||||
|
NAMES AudioToolbox
|
||||||
|
PATHS ~/Library/Frameworks
|
||||||
|
/Library/Frameworks
|
||||||
|
/System/Library/Frameworks
|
||||||
|
)
|
||||||
|
IF(AUDIOTOOLBOX_LIBRARY)
|
||||||
|
SET(EXTRA_LIBS ${AUDIOTOOLBOX_LIBRARY} ${EXTRA_LIBS})
|
||||||
|
ENDIF()
|
||||||
ENDIF()
|
ENDIF()
|
||||||
ENDIF()
|
ENDIF()
|
||||||
IF(REQUIRE_COREAUDIO AND NOT HAVE_COREAUDIO)
|
IF(REQUIRE_COREAUDIO AND NOT HAVE_COREAUDIO)
|
||||||
@ -672,6 +688,10 @@ ENDIF()
|
|||||||
# This is always available
|
# This is always available
|
||||||
SET(BACKENDS "${BACKENDS} Null")
|
SET(BACKENDS "${BACKENDS} Null")
|
||||||
|
|
||||||
|
IF(EXAMPLES)
|
||||||
|
PKG_CHECK_MODULES(FFMPEG libavcodec libavformat)
|
||||||
|
ENDIF()
|
||||||
|
|
||||||
IF(LIBTYPE STREQUAL "STATIC")
|
IF(LIBTYPE STREQUAL "STATIC")
|
||||||
ADD_DEFINITIONS(-DAL_LIBTYPE_STATIC)
|
ADD_DEFINITIONS(-DAL_LIBTYPE_STATIC)
|
||||||
SET(PKG_CONFIG_CFLAGS -DAL_LIBTYPE_STATIC ${PKG_CONFIG_CFLAGS})
|
SET(PKG_CONFIG_CFLAGS -DAL_LIBTYPE_STATIC ${PKG_CONFIG_CFLAGS})
|
||||||
@ -717,6 +737,7 @@ INSTALL(FILES include/AL/al.h
|
|||||||
include/AL/alext.h
|
include/AL/alext.h
|
||||||
include/AL/efx.h
|
include/AL/efx.h
|
||||||
include/AL/efx-creative.h
|
include/AL/efx-creative.h
|
||||||
|
include/AL/efx-presets.h
|
||||||
DESTINATION include/AL
|
DESTINATION include/AL
|
||||||
)
|
)
|
||||||
INSTALL(FILES "${OpenAL_BINARY_DIR}/openal.pc"
|
INSTALL(FILES "${OpenAL_BINARY_DIR}/openal.pc"
|
||||||
@ -757,3 +778,19 @@ IF(UTILS)
|
|||||||
MESSAGE(STATUS "Building utility programs")
|
MESSAGE(STATUS "Building utility programs")
|
||||||
MESSAGE(STATUS "")
|
MESSAGE(STATUS "")
|
||||||
ENDIF()
|
ENDIF()
|
||||||
|
|
||||||
|
IF(EXAMPLES)
|
||||||
|
IF(FFMPEG_FOUND)
|
||||||
|
ADD_EXECUTABLE(alstream examples/alhelpers.c examples/alffmpeg.c examples/alstream.c)
|
||||||
|
TARGET_LINK_LIBRARIES(alstream ${FFMPEG_LIBRARIES} ${LIBNAME})
|
||||||
|
SET_TARGET_PROPERTIES(alstream PROPERTIES COMPILE_FLAGS "${FFMPEG_CFLAGS}")
|
||||||
|
INSTALL(TARGETS alstream
|
||||||
|
RUNTIME DESTINATION bin
|
||||||
|
LIBRARY DESTINATION "lib${LIB_SUFFIX}"
|
||||||
|
ARCHIVE DESTINATION "lib${LIB_SUFFIX}"
|
||||||
|
)
|
||||||
|
|
||||||
|
MESSAGE(STATUS "Building ffmpeg example programs")
|
||||||
|
MESSAGE(STATUS "")
|
||||||
|
ENDIF()
|
||||||
|
ENDIF()
|
||||||
|
@ -35,9 +35,9 @@ typedef struct ALeffectslot
|
|||||||
} ALeffectslot;
|
} ALeffectslot;
|
||||||
|
|
||||||
|
|
||||||
|
ALenum InitEffectSlot(ALeffectslot *slot);
|
||||||
ALvoid ReleaseALAuxiliaryEffectSlots(ALCcontext *Context);
|
ALvoid ReleaseALAuxiliaryEffectSlots(ALCcontext *Context);
|
||||||
|
|
||||||
|
|
||||||
struct ALeffectState {
|
struct ALeffectState {
|
||||||
ALvoid (*Destroy)(ALeffectState *State);
|
ALvoid (*Destroy)(ALeffectState *State);
|
||||||
ALboolean (*DeviceUpdate)(ALeffectState *State, ALCdevice *Device);
|
ALboolean (*DeviceUpdate)(ALeffectState *State, ALCdevice *Device);
|
||||||
@ -56,6 +56,7 @@ ALeffectState *DedicatedCreate(void);
|
|||||||
#define ALeffectState_Update(a,b,c) ((a)->Update((a),(b),(c)))
|
#define ALeffectState_Update(a,b,c) ((a)->Update((a),(b),(c)))
|
||||||
#define ALeffectState_Process(a,b,c,d) ((a)->Process((a),(b),(c),(d)))
|
#define ALeffectState_Process(a,b,c,d) ((a)->Process((a),(b),(c),(d)))
|
||||||
|
|
||||||
|
ALvoid InitializeEffect(ALCcontext *Context, ALeffectslot *EffectSlot, ALeffect *effect);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
@ -9,28 +9,28 @@ extern "C" {
|
|||||||
|
|
||||||
/* User formats */
|
/* User formats */
|
||||||
enum UserFmtType {
|
enum UserFmtType {
|
||||||
UserFmtByte = AL_BYTE,
|
UserFmtByte = AL_BYTE_SOFT,
|
||||||
UserFmtUByte = AL_UNSIGNED_BYTE,
|
UserFmtUByte = AL_UNSIGNED_BYTE_SOFT,
|
||||||
UserFmtShort = AL_SHORT,
|
UserFmtShort = AL_SHORT_SOFT,
|
||||||
UserFmtUShort = AL_UNSIGNED_SHORT,
|
UserFmtUShort = AL_UNSIGNED_SHORT_SOFT,
|
||||||
UserFmtInt = AL_INT,
|
UserFmtInt = AL_INT_SOFT,
|
||||||
UserFmtUInt = AL_UNSIGNED_INT,
|
UserFmtUInt = AL_UNSIGNED_INT_SOFT,
|
||||||
UserFmtFloat = AL_FLOAT,
|
UserFmtFloat = AL_FLOAT_SOFT,
|
||||||
UserFmtDouble = AL_DOUBLE,
|
UserFmtDouble = AL_DOUBLE_SOFT,
|
||||||
UserFmtMulaw = AL_MULAW,
|
UserFmtByte3 = AL_BYTE3_SOFT,
|
||||||
UserFmtAlaw = AL_ALAW,
|
UserFmtUByte3 = AL_UNSIGNED_BYTE3_SOFT,
|
||||||
UserFmtIMA4 = AL_IMA4,
|
UserFmtMulaw,
|
||||||
UserFmtByte3 = AL_BYTE3,
|
UserFmtAlaw,
|
||||||
UserFmtUByte3 = AL_UNSIGNED_BYTE3,
|
UserFmtIMA4,
|
||||||
};
|
};
|
||||||
enum UserFmtChannels {
|
enum UserFmtChannels {
|
||||||
UserFmtMono = AL_MONO,
|
UserFmtMono = AL_MONO_SOFT,
|
||||||
UserFmtStereo = AL_STEREO,
|
UserFmtStereo = AL_STEREO_SOFT,
|
||||||
UserFmtRear = AL_REAR,
|
UserFmtRear = AL_REAR_SOFT,
|
||||||
UserFmtQuad = AL_QUAD,
|
UserFmtQuad = AL_QUAD_SOFT,
|
||||||
UserFmtX51 = AL_5POINT1, /* (WFX order) */
|
UserFmtX51 = AL_5POINT1_SOFT, /* (WFX order) */
|
||||||
UserFmtX61 = AL_6POINT1, /* (WFX order) */
|
UserFmtX61 = AL_6POINT1_SOFT, /* (WFX order) */
|
||||||
UserFmtX71 = AL_7POINT1 /* (WFX order) */
|
UserFmtX71 = AL_7POINT1_SOFT, /* (WFX order) */
|
||||||
};
|
};
|
||||||
|
|
||||||
ALuint BytesFromUserFmt(enum UserFmtType type);
|
ALuint BytesFromUserFmt(enum UserFmtType type);
|
||||||
|
@ -102,8 +102,11 @@ typedef struct ALeffect
|
|||||||
static __inline ALboolean IsReverbEffect(ALenum type)
|
static __inline ALboolean IsReverbEffect(ALenum type)
|
||||||
{ return type == AL_EFFECT_REVERB || type == AL_EFFECT_EAXREVERB; }
|
{ return type == AL_EFFECT_REVERB || type == AL_EFFECT_EAXREVERB; }
|
||||||
|
|
||||||
|
ALenum InitEffect(ALeffect *effect);
|
||||||
ALvoid ReleaseALEffects(ALCdevice *device);
|
ALvoid ReleaseALEffects(ALCdevice *device);
|
||||||
|
|
||||||
|
ALvoid GetReverbEffect(const char *name, ALeffect *effect);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -39,94 +39,16 @@
|
|||||||
#define ALC_6POINT1_SOFT 0x1505 /* (WFX order) */
|
#define ALC_6POINT1_SOFT 0x1505 /* (WFX order) */
|
||||||
#define ALC_7POINT1_SOFT 0x1506 /* (WFX order) */
|
#define ALC_7POINT1_SOFT 0x1506 /* (WFX order) */
|
||||||
|
|
||||||
typedef ALCdevice* (ALC_APIENTRY*LPALCLOOPBACKOPENDEVICESOFT)(void);
|
typedef ALCdevice* (ALC_APIENTRY*LPALCLOOPBACKOPENDEVICESOFT)(const ALCchar*);
|
||||||
typedef ALCboolean (ALC_APIENTRY*LPALCISRENDERFORMATSUPPORTEDSOFT)(ALCdevice *device, ALCsizei freq, ALCenum channels, ALCenum type);
|
typedef ALCboolean (ALC_APIENTRY*LPALCISRENDERFORMATSUPPORTEDSOFT)(ALCdevice*,ALCsizei,ALCenum,ALCenum);
|
||||||
typedef void (ALC_APIENTRY*LPALCRENDERSAMPLESSOFT)(ALCdevice *device, ALCvoid *buffer, ALCsizei samples);
|
typedef void (ALC_APIENTRY*LPALCRENDERSAMPLESSOFT)(ALCdevice*,ALCvoid*,ALCsizei);
|
||||||
#ifdef AL_ALEXT_PROTOTYPES
|
#ifdef AL_ALEXT_PROTOTYPES
|
||||||
ALC_API ALCdevice* ALC_APIENTRY alcLoopbackOpenDeviceSOFT(void);
|
ALC_API ALCdevice* ALC_APIENTRY alcLoopbackOpenDeviceSOFT(const ALCchar *deviceName);
|
||||||
ALC_API ALCboolean ALC_APIENTRY alcIsRenderFormatSupportedSOFT(ALCdevice *device, ALCsizei freq, ALCenum channels, ALCenum type);
|
ALC_API ALCboolean ALC_APIENTRY alcIsRenderFormatSupportedSOFT(ALCdevice *device, ALCsizei freq, ALCenum channels, ALCenum type);
|
||||||
ALC_API void ALC_APIENTRY alcRenderSamplesSOFT(ALCdevice *device, ALCvoid *buffer, ALCsizei samples);
|
ALC_API void ALC_APIENTRY alcRenderSamplesSOFT(ALCdevice *device, ALCvoid *buffer, ALCsizei samples);
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef AL_SOFT_buffer_samples
|
|
||||||
#define AL_SOFT_buffer_samples 1
|
|
||||||
/* Sample types */
|
|
||||||
#define AL_BYTE 0x1400
|
|
||||||
#define AL_UNSIGNED_BYTE 0x1401
|
|
||||||
#define AL_SHORT 0x1402
|
|
||||||
#define AL_UNSIGNED_SHORT 0x1403
|
|
||||||
#define AL_INT 0x1404
|
|
||||||
#define AL_UNSIGNED_INT 0x1405
|
|
||||||
#define AL_FLOAT 0x1406
|
|
||||||
#define AL_DOUBLE 0x1407
|
|
||||||
#define AL_BYTE3 0x1408
|
|
||||||
#define AL_UNSIGNED_BYTE3 0x1409
|
|
||||||
#define AL_MULAW 0x1410
|
|
||||||
#define AL_ALAW 0x1411
|
|
||||||
#define AL_IMA4 0x1412
|
|
||||||
|
|
||||||
/* Channel configurations */
|
|
||||||
#define AL_MONO 0x1500
|
|
||||||
#define AL_STEREO 0x1501
|
|
||||||
#define AL_REAR 0x1502
|
|
||||||
#define AL_QUAD 0x1503
|
|
||||||
#define AL_5POINT1 0x1504 /* (WFX order) */
|
|
||||||
#define AL_6POINT1 0x1505 /* (WFX order) */
|
|
||||||
#define AL_7POINT1 0x1506 /* (WFX order) */
|
|
||||||
|
|
||||||
/* Storage formats */
|
|
||||||
#define AL_MONO8 0x1100
|
|
||||||
#define AL_MONO16 0x1101
|
|
||||||
#define AL_MONO32F 0x10010
|
|
||||||
#define AL_STEREO8 0x1102
|
|
||||||
#define AL_STEREO16 0x1103
|
|
||||||
#define AL_STEREO32F 0x10011
|
|
||||||
#define AL_QUAD8 0x1204
|
|
||||||
#define AL_QUAD16 0x1205
|
|
||||||
#define AL_QUAD32F 0x1206
|
|
||||||
#define AL_REAR8 0x1207
|
|
||||||
#define AL_REAR16 0x1208
|
|
||||||
#define AL_REAR32F 0x1209
|
|
||||||
#define AL_5POINT1_8 0x120A
|
|
||||||
#define AL_5POINT1_16 0x120B
|
|
||||||
#define AL_5POINT1_32F 0x120C
|
|
||||||
#define AL_6POINT1_8 0x120D
|
|
||||||
#define AL_6POINT1_16 0x120E
|
|
||||||
#define AL_6POINT1_32F 0x120F
|
|
||||||
#define AL_7POINT1_8 0x1210
|
|
||||||
#define AL_7POINT1_16 0x1211
|
|
||||||
#define AL_7POINT1_32F 0x1212
|
|
||||||
|
|
||||||
/* Buffer attributes */
|
|
||||||
#define AL_INTERNAL_FORMAT 0x2008
|
|
||||||
#define AL_BYTE_LENGTH 0x2009
|
|
||||||
#define AL_SAMPLE_LENGTH 0x200A
|
|
||||||
#define AL_SEC_LENGTH 0x200B
|
|
||||||
|
|
||||||
typedef void (AL_APIENTRY*LPALBUFFERSAMPLESSOFT)(ALuint,ALuint,ALenum,ALsizei,ALenum,ALenum,const ALvoid*);
|
|
||||||
typedef void (AL_APIENTRY*LPALBUFFERSUBSAMPLESSOFT)(ALuint,ALsizei,ALsizei,ALenum,ALenum,const ALvoid*);
|
|
||||||
typedef void (AL_APIENTRY*LPALGETBUFFERSAMPLESSOFT)(ALuint,ALsizei,ALsizei,ALenum,ALenum,ALvoid*);
|
|
||||||
typedef ALboolean (AL_APIENTRY*LPALISBUFFERFORMATSUPPORTEDSOFT)(ALenum);
|
|
||||||
#ifdef AL_ALEXT_PROTOTYPES
|
|
||||||
AL_API void AL_APIENTRY alBufferSamplesSOFT(ALuint buffer,
|
|
||||||
ALuint samplerate, ALenum internalformat, ALsizei samples,
|
|
||||||
ALenum channels, ALenum type, const ALvoid *data);
|
|
||||||
AL_API void AL_APIENTRY alBufferSubSamplesSOFT(ALuint buffer,
|
|
||||||
ALsizei offset, ALsizei samples,
|
|
||||||
ALenum channels, ALenum type, const ALvoid *data);
|
|
||||||
AL_API void AL_APIENTRY alGetBufferSamplesSOFT(ALuint buffer,
|
|
||||||
ALsizei offset, ALsizei samples,
|
|
||||||
ALenum channels, ALenum type, ALvoid *data);
|
|
||||||
AL_API ALboolean AL_APIENTRY alIsBufferFormatSupportedSOFT(ALenum format);
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef AL_SOFT_non_virtual_channels
|
|
||||||
#define AL_SOFT_non_virtual_channels 1
|
|
||||||
#define AL_VIRTUAL_CHANNELS_SOFT 0x1033
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef AL_SOFT_deferred_updates
|
#ifndef AL_SOFT_deferred_updates
|
||||||
#define AL_SOFT_deferred_updates 1
|
#define AL_SOFT_deferred_updates 1
|
||||||
#define AL_DEFERRED_UPDATES_SOFT 0xC002
|
#define AL_DEFERRED_UPDATES_SOFT 0xC002
|
||||||
@ -172,6 +94,14 @@ typedef ptrdiff_t ALsizeiptrEXT;
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
static const union {
|
||||||
|
ALuint u;
|
||||||
|
ALubyte b[sizeof(ALuint)];
|
||||||
|
} EndianTest = { 1 };
|
||||||
|
#define IS_LITTLE_ENDIAN (EndianTest.b[0] == 1)
|
||||||
|
|
||||||
|
#define COUNTOF(x) (sizeof((x))/sizeof((x)[0]))
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
|
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
@ -187,6 +117,8 @@ void *LoadLib(const char *name);
|
|||||||
void CloseLib(void *handle);
|
void CloseLib(void *handle);
|
||||||
void *GetSymbol(void *handle, const char *name);
|
void *GetSymbol(void *handle, const char *name);
|
||||||
|
|
||||||
|
WCHAR *strdupW(const WCHAR *str);
|
||||||
|
|
||||||
typedef LONG pthread_once_t;
|
typedef LONG pthread_once_t;
|
||||||
#define PTHREAD_ONCE_INIT 0
|
#define PTHREAD_ONCE_INIT 0
|
||||||
void pthread_once(pthread_once_t *once, void (*callback)(void));
|
void pthread_once(pthread_once_t *once, void (*callback)(void));
|
||||||
@ -226,6 +158,8 @@ void *GetSymbol(void *handle, const char *name);
|
|||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
typedef void *volatile XchgPtr;
|
||||||
|
|
||||||
#if defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 1))
|
#if defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 1))
|
||||||
typedef ALuint RefCount;
|
typedef ALuint RefCount;
|
||||||
static __inline RefCount IncrementRef(volatile RefCount *ptr)
|
static __inline RefCount IncrementRef(volatile RefCount *ptr)
|
||||||
@ -237,7 +171,7 @@ static __inline int ExchangeInt(volatile int *ptr, int newval)
|
|||||||
{
|
{
|
||||||
return __sync_lock_test_and_set(ptr, newval);
|
return __sync_lock_test_and_set(ptr, newval);
|
||||||
}
|
}
|
||||||
static __inline void *ExchangePtr(void *volatile*ptr, void *newval)
|
static __inline void *ExchangePtr(XchgPtr *ptr, void *newval)
|
||||||
{
|
{
|
||||||
return __sync_lock_test_and_set(ptr, newval);
|
return __sync_lock_test_and_set(ptr, newval);
|
||||||
}
|
}
|
||||||
@ -245,7 +179,7 @@ static __inline ALboolean CompExchangeInt(volatile int *ptr, int oldval, int new
|
|||||||
{
|
{
|
||||||
return __sync_bool_compare_and_swap(ptr, oldval, newval);
|
return __sync_bool_compare_and_swap(ptr, oldval, newval);
|
||||||
}
|
}
|
||||||
static __inline ALboolean CompExchangePtr(void *volatile*ptr, void *oldval, void *newval)
|
static __inline ALboolean CompExchangePtr(XchgPtr *ptr, void *oldval, void *newval)
|
||||||
{
|
{
|
||||||
return __sync_bool_compare_and_swap(ptr, oldval, newval);
|
return __sync_bool_compare_and_swap(ptr, oldval, newval);
|
||||||
}
|
}
|
||||||
@ -288,7 +222,7 @@ static __inline ALboolean CompExchangeInt(volatile int *dest, int oldval, int ne
|
|||||||
return ret == oldval;
|
return ret == oldval;
|
||||||
}
|
}
|
||||||
|
|
||||||
static __inline void *ExchangePtr(void *volatile*dest, void *newval)
|
static __inline void *ExchangePtr(XchgPtr *dest, void *newval)
|
||||||
{
|
{
|
||||||
void *ret;
|
void *ret;
|
||||||
__asm__ __volatile__(
|
__asm__ __volatile__(
|
||||||
@ -304,7 +238,7 @@ static __inline void *ExchangePtr(void *volatile*dest, void *newval)
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static __inline ALboolean CompExchangePtr(void *volatile*dest, void *oldval, void *newval)
|
static __inline ALboolean CompExchangePtr(XchgPtr *dest, void *oldval, void *newval)
|
||||||
{
|
{
|
||||||
void *ret;
|
void *ret;
|
||||||
__asm__ __volatile__(
|
__asm__ __volatile__(
|
||||||
@ -338,7 +272,7 @@ static __inline int ExchangeInt(volatile int *ptr, int newval)
|
|||||||
} u = { ptr };
|
} u = { ptr };
|
||||||
return InterlockedExchange(u.l, newval);
|
return InterlockedExchange(u.l, newval);
|
||||||
}
|
}
|
||||||
static __inline void *ExchangePtr(void *volatile*ptr, void *newval)
|
static __inline void *ExchangePtr(XchgPtr *ptr, void *newval)
|
||||||
{
|
{
|
||||||
return InterlockedExchangePointer(ptr, newval);
|
return InterlockedExchangePointer(ptr, newval);
|
||||||
}
|
}
|
||||||
@ -350,7 +284,7 @@ static __inline ALboolean CompExchangeInt(volatile int *ptr, int oldval, int new
|
|||||||
} u = { ptr };
|
} u = { ptr };
|
||||||
return InterlockedCompareExchange(u.l, newval, oldval) == oldval;
|
return InterlockedCompareExchange(u.l, newval, oldval) == oldval;
|
||||||
}
|
}
|
||||||
static __inline ALboolean CompExchangePtr(void *volatile*ptr, void *oldval, void *newval)
|
static __inline ALboolean CompExchangePtr(XchgPtr *ptr, void *oldval, void *newval)
|
||||||
{
|
{
|
||||||
return InterlockedCompareExchangePointer(ptr, newval, oldval) == oldval;
|
return InterlockedCompareExchangePointer(ptr, newval, oldval) == oldval;
|
||||||
}
|
}
|
||||||
@ -374,7 +308,7 @@ static __inline int ExchangeInt(volatile int *ptr, int newval)
|
|||||||
} while(!OSAtomicCompareAndSwap32Barrier(oldval, newval, ptr));
|
} while(!OSAtomicCompareAndSwap32Barrier(oldval, newval, ptr));
|
||||||
return oldval;
|
return oldval;
|
||||||
}
|
}
|
||||||
static __inline void *ExchangePtr(void *volatile*ptr, void *newval)
|
static __inline void *ExchangePtr(XchgPtr *ptr, void *newval)
|
||||||
{
|
{
|
||||||
void *oldval;
|
void *oldval;
|
||||||
do {
|
do {
|
||||||
@ -386,7 +320,7 @@ static __inline ALboolean CompExchangeInt(volatile int *ptr, int oldval, int new
|
|||||||
{
|
{
|
||||||
return OSAtomicCompareAndSwap32Barrier(oldval, newval, ptr);
|
return OSAtomicCompareAndSwap32Barrier(oldval, newval, ptr);
|
||||||
}
|
}
|
||||||
static __inline ALboolean CompExchangePtr(void *volatile*ptr, void *oldval, void *newval)
|
static __inline ALboolean CompExchangePtr(XchgPtr *ptr, void *oldval, void *newval)
|
||||||
{
|
{
|
||||||
return OSAtomicCompareAndSwapPtrBarrier(oldval, newval, ptr);
|
return OSAtomicCompareAndSwapPtrBarrier(oldval, newval, ptr);
|
||||||
}
|
}
|
||||||
@ -448,6 +382,7 @@ extern "C" {
|
|||||||
|
|
||||||
|
|
||||||
#define DEFAULT_OUTPUT_RATE (44100)
|
#define DEFAULT_OUTPUT_RATE (44100)
|
||||||
|
#define MIN_OUTPUT_RATE (8000)
|
||||||
|
|
||||||
#define SPEEDOFSOUNDMETRESPERSEC (343.3f)
|
#define SPEEDOFSOUNDMETRESPERSEC (343.3f)
|
||||||
#define AIRABSORBGAINHF (0.99426f) /* -0.05dB */
|
#define AIRABSORBGAINHF (0.99426f) /* -0.05dB */
|
||||||
@ -480,7 +415,7 @@ static __inline ALuint NextPowerOf2(ALuint value)
|
|||||||
static __inline ALint fastf2i(ALfloat f)
|
static __inline ALint fastf2i(ALfloat f)
|
||||||
{
|
{
|
||||||
ALint i;
|
ALint i;
|
||||||
#if defined(_MSC_VER) && !defined(_WIN64)
|
#if defined(_MSC_VER) && defined(_M_IX86)
|
||||||
__asm fld f
|
__asm fld f
|
||||||
__asm fistp i
|
__asm fistp i
|
||||||
#elif defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))
|
#elif defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))
|
||||||
@ -501,7 +436,6 @@ static __inline ALuint fastf2u(ALfloat f)
|
|||||||
|
|
||||||
|
|
||||||
enum DevProbe {
|
enum DevProbe {
|
||||||
DEVICE_PROBE,
|
|
||||||
ALL_DEVICE_PROBE,
|
ALL_DEVICE_PROBE,
|
||||||
CAPTURE_DEVICE_PROBE
|
CAPTURE_DEVICE_PROBE
|
||||||
};
|
};
|
||||||
@ -510,6 +444,7 @@ typedef struct {
|
|||||||
ALCenum (*OpenPlayback)(ALCdevice*, const ALCchar*);
|
ALCenum (*OpenPlayback)(ALCdevice*, const ALCchar*);
|
||||||
void (*ClosePlayback)(ALCdevice*);
|
void (*ClosePlayback)(ALCdevice*);
|
||||||
ALCboolean (*ResetPlayback)(ALCdevice*);
|
ALCboolean (*ResetPlayback)(ALCdevice*);
|
||||||
|
ALCboolean (*StartPlayback)(ALCdevice*);
|
||||||
void (*StopPlayback)(ALCdevice*);
|
void (*StopPlayback)(ALCdevice*);
|
||||||
|
|
||||||
ALCenum (*OpenCapture)(ALCdevice*, const ALCchar*);
|
ALCenum (*OpenCapture)(ALCdevice*, const ALCchar*);
|
||||||
@ -581,6 +516,8 @@ enum DevFmtType {
|
|||||||
DevFmtUByte = ALC_UNSIGNED_BYTE_SOFT,
|
DevFmtUByte = ALC_UNSIGNED_BYTE_SOFT,
|
||||||
DevFmtShort = ALC_SHORT_SOFT,
|
DevFmtShort = ALC_SHORT_SOFT,
|
||||||
DevFmtUShort = ALC_UNSIGNED_SHORT_SOFT,
|
DevFmtUShort = ALC_UNSIGNED_SHORT_SOFT,
|
||||||
|
DevFmtInt = ALC_INT_SOFT,
|
||||||
|
DevFmtUInt = ALC_UNSIGNED_INT_SOFT,
|
||||||
DevFmtFloat = ALC_FLOAT_SOFT
|
DevFmtFloat = ALC_FLOAT_SOFT
|
||||||
};
|
};
|
||||||
enum DevFmtChannels {
|
enum DevFmtChannels {
|
||||||
@ -612,13 +549,18 @@ extern const struct EffectList {
|
|||||||
} EffectList[];
|
} EffectList[];
|
||||||
|
|
||||||
|
|
||||||
|
enum DeviceType {
|
||||||
|
Playback,
|
||||||
|
Capture,
|
||||||
|
Loopback
|
||||||
|
};
|
||||||
|
|
||||||
struct ALCdevice_struct
|
struct ALCdevice_struct
|
||||||
{
|
{
|
||||||
volatile RefCount ref;
|
volatile RefCount ref;
|
||||||
|
|
||||||
ALCboolean Connected;
|
ALCboolean Connected;
|
||||||
ALboolean IsCaptureDevice;
|
enum DeviceType Type;
|
||||||
ALboolean IsLoopbackDevice;
|
|
||||||
|
|
||||||
CRITICAL_SECTION Mutex;
|
CRITICAL_SECTION Mutex;
|
||||||
|
|
||||||
@ -672,6 +614,9 @@ struct ALCdevice_struct
|
|||||||
ALfloat ClickRemoval[MAXCHANNELS];
|
ALfloat ClickRemoval[MAXCHANNELS];
|
||||||
ALfloat PendingClicks[MAXCHANNELS];
|
ALfloat PendingClicks[MAXCHANNELS];
|
||||||
|
|
||||||
|
/* Default effect slot */
|
||||||
|
struct ALeffectslot *DefaultSlot;
|
||||||
|
|
||||||
// Contexts created on this device
|
// Contexts created on this device
|
||||||
ALCcontext *volatile ContextList;
|
ALCcontext *volatile ContextList;
|
||||||
|
|
||||||
@ -684,6 +629,7 @@ struct ALCdevice_struct
|
|||||||
#define ALCdevice_OpenPlayback(a,b) ((a)->Funcs->OpenPlayback((a), (b)))
|
#define ALCdevice_OpenPlayback(a,b) ((a)->Funcs->OpenPlayback((a), (b)))
|
||||||
#define ALCdevice_ClosePlayback(a) ((a)->Funcs->ClosePlayback((a)))
|
#define ALCdevice_ClosePlayback(a) ((a)->Funcs->ClosePlayback((a)))
|
||||||
#define ALCdevice_ResetPlayback(a) ((a)->Funcs->ResetPlayback((a)))
|
#define ALCdevice_ResetPlayback(a) ((a)->Funcs->ResetPlayback((a)))
|
||||||
|
#define ALCdevice_StartPlayback(a) ((a)->Funcs->StartPlayback((a)))
|
||||||
#define ALCdevice_StopPlayback(a) ((a)->Funcs->StopPlayback((a)))
|
#define ALCdevice_StopPlayback(a) ((a)->Funcs->StopPlayback((a)))
|
||||||
#define ALCdevice_OpenCapture(a,b) ((a)->Funcs->OpenCapture((a), (b)))
|
#define ALCdevice_OpenCapture(a,b) ((a)->Funcs->OpenCapture((a), (b)))
|
||||||
#define ALCdevice_CloseCapture(a) ((a)->Funcs->CloseCapture((a)))
|
#define ALCdevice_CloseCapture(a) ((a)->Funcs->CloseCapture((a)))
|
||||||
@ -698,6 +644,8 @@ struct ALCdevice_struct
|
|||||||
#define DEVICE_FREQUENCY_REQUEST (1<<1)
|
#define DEVICE_FREQUENCY_REQUEST (1<<1)
|
||||||
// Channel configuration was requested by the config file
|
// Channel configuration was requested by the config file
|
||||||
#define DEVICE_CHANNELS_REQUEST (1<<2)
|
#define DEVICE_CHANNELS_REQUEST (1<<2)
|
||||||
|
// Sample type was requested by the config file
|
||||||
|
#define DEVICE_SAMPLE_TYPE_REQUEST (1<<3)
|
||||||
|
|
||||||
// Specifies if the device is currently running
|
// Specifies if the device is currently running
|
||||||
#define DEVICE_RUNNING (1<<31)
|
#define DEVICE_RUNNING (1<<31)
|
||||||
@ -755,14 +703,19 @@ ALCcontext *GetContextRef(void);
|
|||||||
void ALCcontext_IncRef(ALCcontext *context);
|
void ALCcontext_IncRef(ALCcontext *context);
|
||||||
void ALCcontext_DecRef(ALCcontext *context);
|
void ALCcontext_DecRef(ALCcontext *context);
|
||||||
|
|
||||||
void AppendDeviceList(const ALCchar *name);
|
|
||||||
void AppendAllDeviceList(const ALCchar *name);
|
void AppendAllDeviceList(const ALCchar *name);
|
||||||
void AppendCaptureDeviceList(const ALCchar *name);
|
void AppendCaptureDeviceList(const ALCchar *name);
|
||||||
|
|
||||||
ALCvoid LockDevice(ALCdevice *device);
|
static __inline void LockDevice(ALCdevice *device)
|
||||||
ALCvoid UnlockDevice(ALCdevice *device);
|
{ EnterCriticalSection(&device->Mutex); }
|
||||||
ALCvoid LockContext(ALCcontext *context);
|
static __inline void UnlockDevice(ALCdevice *device)
|
||||||
ALCvoid UnlockContext(ALCcontext *context);
|
{ LeaveCriticalSection(&device->Mutex); }
|
||||||
|
|
||||||
|
static __inline void LockContext(ALCcontext *context)
|
||||||
|
{ LockDevice(context->Device); }
|
||||||
|
static __inline void UnlockContext(ALCcontext *context)
|
||||||
|
{ UnlockDevice(context->Device); }
|
||||||
|
|
||||||
|
|
||||||
ALvoid *StartThread(ALuint (*func)(ALvoid*), ALvoid *ptr);
|
ALvoid *StartThread(ALuint (*func)(ALvoid*), ALvoid *ptr);
|
||||||
ALuint StopThread(ALvoid *thread);
|
ALuint StopThread(ALvoid *thread);
|
||||||
|
@ -17,8 +17,8 @@ extern "C" {
|
|||||||
|
|
||||||
extern enum Resampler DefaultResampler;
|
extern enum Resampler DefaultResampler;
|
||||||
|
|
||||||
extern const ALsizei ResamplerPadding[RESAMPLER_MAX];
|
extern const ALsizei ResamplerPadding[ResamplerMax];
|
||||||
extern const ALsizei ResamplerPrePadding[RESAMPLER_MAX];
|
extern const ALsizei ResamplerPrePadding[ResamplerMax];
|
||||||
|
|
||||||
|
|
||||||
typedef struct ALbufferlistitem
|
typedef struct ALbufferlistitem
|
||||||
@ -46,7 +46,7 @@ typedef struct ALsource
|
|||||||
volatile ALboolean bHeadRelative;
|
volatile ALboolean bHeadRelative;
|
||||||
volatile ALboolean bLooping;
|
volatile ALboolean bLooping;
|
||||||
volatile enum DistanceModel DistanceModel;
|
volatile enum DistanceModel DistanceModel;
|
||||||
volatile ALboolean VirtualChannels;
|
volatile ALboolean DirectChannels;
|
||||||
|
|
||||||
enum Resampler Resampler;
|
enum Resampler Resampler;
|
||||||
|
|
||||||
|
@ -127,13 +127,11 @@ typedef ALvoid (*MixerFunc)(struct ALsource *self, ALCdevice *Device,
|
|||||||
ALuint BufferSize);
|
ALuint BufferSize);
|
||||||
|
|
||||||
enum Resampler {
|
enum Resampler {
|
||||||
POINT_RESAMPLER = 0,
|
PointResampler,
|
||||||
LINEAR_RESAMPLER,
|
LinearResampler,
|
||||||
CUBIC_RESAMPLER,
|
CubicResampler,
|
||||||
|
|
||||||
RESAMPLER_MAX,
|
ResamplerMax,
|
||||||
RESAMPLER_MIN = -1,
|
|
||||||
RESAMPLER_DEFAULT = LINEAR_RESAMPLER
|
|
||||||
};
|
};
|
||||||
|
|
||||||
enum Channel {
|
enum Channel {
|
||||||
@ -157,7 +155,9 @@ enum DistanceModel {
|
|||||||
InverseDistance = AL_INVERSE_DISTANCE,
|
InverseDistance = AL_INVERSE_DISTANCE,
|
||||||
LinearDistance = AL_LINEAR_DISTANCE,
|
LinearDistance = AL_LINEAR_DISTANCE,
|
||||||
ExponentDistance = AL_EXPONENT_DISTANCE,
|
ExponentDistance = AL_EXPONENT_DISTANCE,
|
||||||
DisableDistance = AL_NONE
|
DisableDistance = AL_NONE,
|
||||||
|
|
||||||
|
DefaultDistanceModel = InverseDistanceClamped
|
||||||
};
|
};
|
||||||
|
|
||||||
#define BUFFERSIZE 4096
|
#define BUFFERSIZE 4096
|
||||||
|
@ -91,9 +91,6 @@ int bs2b_get_srate(struct bs2b *bs2b);
|
|||||||
/* Clear buffer */
|
/* Clear buffer */
|
||||||
void bs2b_clear(struct bs2b *bs2b);
|
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.
|
/* Crossfeeds one stereo sample that are pointed by sample.
|
||||||
* [0] - first channel, [1] - second channel.
|
* [0] - first channel, [1] - second channel.
|
||||||
* Returns crossfided samle by sample pointer.
|
* Returns crossfided samle by sample pointer.
|
||||||
|
@ -32,7 +32,6 @@
|
|||||||
#include "alSource.h"
|
#include "alSource.h"
|
||||||
|
|
||||||
|
|
||||||
static ALvoid InitializeEffect(ALCcontext *Context, ALeffectslot *EffectSlot, ALeffect *effect);
|
|
||||||
static ALenum ResizeEffectSlotArray(ALCcontext *Context, ALsizei count);
|
static ALenum ResizeEffectSlotArray(ALCcontext *Context, ALsizei count);
|
||||||
static ALvoid RemoveEffectSlotArray(ALCcontext *Context, ALeffectslot *val);
|
static ALvoid RemoveEffectSlotArray(ALCcontext *Context, ALeffectslot *val);
|
||||||
|
|
||||||
@ -40,18 +39,16 @@ static ALvoid RemoveEffectSlotArray(ALCcontext *Context, ALeffectslot *val);
|
|||||||
AL_API ALvoid AL_APIENTRY alGenAuxiliaryEffectSlots(ALsizei n, ALuint *effectslots)
|
AL_API ALvoid AL_APIENTRY alGenAuxiliaryEffectSlots(ALsizei n, ALuint *effectslots)
|
||||||
{
|
{
|
||||||
ALCcontext *Context;
|
ALCcontext *Context;
|
||||||
ALCdevice *Device;
|
|
||||||
|
|
||||||
Context = GetContextRef();
|
Context = GetContextRef();
|
||||||
if(!Context) return;
|
if(!Context) return;
|
||||||
|
|
||||||
Device = Context->Device;
|
|
||||||
if(n < 0 || IsBadWritePtr((void*)effectslots, n * sizeof(ALuint)))
|
if(n < 0 || IsBadWritePtr((void*)effectslots, n * sizeof(ALuint)))
|
||||||
alSetError(Context, AL_INVALID_VALUE);
|
alSetError(Context, AL_INVALID_VALUE);
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
ALenum err;
|
ALenum err;
|
||||||
ALsizei i, j;
|
ALsizei i;
|
||||||
|
|
||||||
err = ResizeEffectSlotArray(Context, n);
|
err = ResizeEffectSlotArray(Context, n);
|
||||||
if(err != AL_NO_ERROR)
|
if(err != AL_NO_ERROR)
|
||||||
@ -63,7 +60,7 @@ AL_API ALvoid AL_APIENTRY alGenAuxiliaryEffectSlots(ALsizei n, ALuint *effectslo
|
|||||||
for(i = 0;i < n;i++)
|
for(i = 0;i < n;i++)
|
||||||
{
|
{
|
||||||
ALeffectslot *slot = calloc(1, sizeof(ALeffectslot));
|
ALeffectslot *slot = calloc(1, sizeof(ALeffectslot));
|
||||||
if(!slot || !(slot->EffectState=NoneCreate()))
|
if(!slot || InitEffectSlot(slot) != AL_NO_ERROR)
|
||||||
{
|
{
|
||||||
free(slot);
|
free(slot);
|
||||||
// We must have run out or memory
|
// We must have run out or memory
|
||||||
@ -72,18 +69,6 @@ AL_API ALvoid AL_APIENTRY alGenAuxiliaryEffectSlots(ALsizei n, ALuint *effectslo
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
slot->Gain = 1.0;
|
|
||||||
slot->AuxSendAuto = AL_TRUE;
|
|
||||||
slot->NeedsUpdate = AL_FALSE;
|
|
||||||
for(j = 0;j < BUFFERSIZE;j++)
|
|
||||||
slot->WetBuffer[j] = 0.0f;
|
|
||||||
for(j = 0;j < 1;j++)
|
|
||||||
{
|
|
||||||
slot->ClickRemoval[j] = 0.0f;
|
|
||||||
slot->PendingClicks[j] = 0.0f;
|
|
||||||
}
|
|
||||||
slot->ref = 0;
|
|
||||||
|
|
||||||
LockContext(Context);
|
LockContext(Context);
|
||||||
err = ResizeEffectSlotArray(Context, 1);
|
err = ResizeEffectSlotArray(Context, 1);
|
||||||
if(err == AL_NO_ERROR)
|
if(err == AL_NO_ERROR)
|
||||||
@ -512,7 +497,7 @@ static ALenum ResizeEffectSlotArray(ALCcontext *Context, ALsizei count)
|
|||||||
return AL_NO_ERROR;
|
return AL_NO_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
static ALvoid InitializeEffect(ALCcontext *Context, ALeffectslot *EffectSlot, ALeffect *effect)
|
ALvoid InitializeEffect(ALCcontext *Context, ALeffectslot *EffectSlot, ALeffect *effect)
|
||||||
{
|
{
|
||||||
ALenum newtype = (effect ? effect->type : AL_EFFECT_NULL);
|
ALenum newtype = (effect ? effect->type : AL_EFFECT_NULL);
|
||||||
ALeffectState *State = NULL;
|
ALeffectState *State = NULL;
|
||||||
@ -565,12 +550,13 @@ static ALvoid InitializeEffect(ALCcontext *Context, ALeffectslot *EffectSlot, AL
|
|||||||
|
|
||||||
if(ALeffectState_DeviceUpdate(State, Context->Device) == AL_FALSE)
|
if(ALeffectState_DeviceUpdate(State, Context->Device) == AL_FALSE)
|
||||||
{
|
{
|
||||||
|
RestoreFPUMode(oldMode);
|
||||||
UnlockContext(Context);
|
UnlockContext(Context);
|
||||||
ALeffectState_Destroy(State);
|
ALeffectState_Destroy(State);
|
||||||
alSetError(Context, AL_OUT_OF_MEMORY);
|
alSetError(Context, AL_OUT_OF_MEMORY);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
State = ExchangePtr((void**)&EffectSlot->EffectState, State);
|
State = ExchangePtr((XchgPtr*)&EffectSlot->EffectState, State);
|
||||||
|
|
||||||
if(!effect)
|
if(!effect)
|
||||||
memset(&EffectSlot->effect, 0, sizeof(EffectSlot->effect));
|
memset(&EffectSlot->effect, 0, sizeof(EffectSlot->effect));
|
||||||
@ -600,6 +586,28 @@ static ALvoid InitializeEffect(ALCcontext *Context, ALeffectslot *EffectSlot, AL
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
ALenum InitEffectSlot(ALeffectslot *slot)
|
||||||
|
{
|
||||||
|
ALint i;
|
||||||
|
|
||||||
|
if(!(slot->EffectState=NoneCreate()))
|
||||||
|
return AL_OUT_OF_MEMORY;
|
||||||
|
|
||||||
|
slot->Gain = 1.0;
|
||||||
|
slot->AuxSendAuto = AL_TRUE;
|
||||||
|
slot->NeedsUpdate = AL_FALSE;
|
||||||
|
for(i = 0;i < BUFFERSIZE;i++)
|
||||||
|
slot->WetBuffer[i] = 0.0f;
|
||||||
|
for(i = 0;i < 1;i++)
|
||||||
|
{
|
||||||
|
slot->ClickRemoval[i] = 0.0f;
|
||||||
|
slot->PendingClicks[i] = 0.0f;
|
||||||
|
}
|
||||||
|
slot->ref = 0;
|
||||||
|
|
||||||
|
return AL_NO_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
ALvoid ReleaseALAuxiliaryEffectSlots(ALCcontext *Context)
|
ALvoid ReleaseALAuxiliaryEffectSlots(ALCcontext *Context)
|
||||||
{
|
{
|
||||||
ALsizei pos;
|
ALsizei pos;
|
||||||
|
@ -330,6 +330,8 @@ AL_API ALvoid AL_APIENTRY alBufferData(ALuint buffer,ALenum format,const ALvoid
|
|||||||
enum UserFmtType SrcType;
|
enum UserFmtType SrcType;
|
||||||
ALCcontext *Context;
|
ALCcontext *Context;
|
||||||
ALCdevice *device;
|
ALCdevice *device;
|
||||||
|
ALuint FrameSize;
|
||||||
|
ALenum NewFormat;
|
||||||
ALbuffer *ALBuf;
|
ALbuffer *ALBuf;
|
||||||
ALenum err;
|
ALenum err;
|
||||||
|
|
||||||
@ -351,8 +353,8 @@ AL_API ALvoid AL_APIENTRY alBufferData(ALuint buffer,ALenum format,const ALvoid
|
|||||||
case UserFmtUShort:
|
case UserFmtUShort:
|
||||||
case UserFmtInt:
|
case UserFmtInt:
|
||||||
case UserFmtUInt:
|
case UserFmtUInt:
|
||||||
case UserFmtFloat: {
|
case UserFmtFloat:
|
||||||
ALuint FrameSize = FrameSizeFromUserFmt(SrcChannels, SrcType);
|
FrameSize = FrameSizeFromUserFmt(SrcChannels, SrcType);
|
||||||
if((size%FrameSize) != 0)
|
if((size%FrameSize) != 0)
|
||||||
err = AL_INVALID_VALUE;
|
err = AL_INVALID_VALUE;
|
||||||
else
|
else
|
||||||
@ -360,13 +362,13 @@ AL_API ALvoid AL_APIENTRY alBufferData(ALuint buffer,ALenum format,const ALvoid
|
|||||||
SrcChannels, SrcType, data, AL_TRUE);
|
SrcChannels, SrcType, data, AL_TRUE);
|
||||||
if(err != AL_NO_ERROR)
|
if(err != AL_NO_ERROR)
|
||||||
alSetError(Context, err);
|
alSetError(Context, err);
|
||||||
} break;
|
break;
|
||||||
|
|
||||||
case UserFmtByte3:
|
case UserFmtByte3:
|
||||||
case UserFmtUByte3:
|
case UserFmtUByte3:
|
||||||
case UserFmtDouble: {
|
case UserFmtDouble:
|
||||||
ALuint FrameSize = FrameSizeFromUserFmt(SrcChannels, SrcType);
|
FrameSize = FrameSizeFromUserFmt(SrcChannels, SrcType);
|
||||||
ALenum NewFormat = AL_FORMAT_MONO_FLOAT32;
|
NewFormat = AL_FORMAT_MONO_FLOAT32;
|
||||||
switch(SrcChannels)
|
switch(SrcChannels)
|
||||||
{
|
{
|
||||||
case UserFmtMono: NewFormat = AL_FORMAT_MONO_FLOAT32; break;
|
case UserFmtMono: NewFormat = AL_FORMAT_MONO_FLOAT32; break;
|
||||||
@ -384,19 +386,12 @@ AL_API ALvoid AL_APIENTRY alBufferData(ALuint buffer,ALenum format,const ALvoid
|
|||||||
SrcChannels, SrcType, data, AL_TRUE);
|
SrcChannels, SrcType, data, AL_TRUE);
|
||||||
if(err != AL_NO_ERROR)
|
if(err != AL_NO_ERROR)
|
||||||
alSetError(Context, err);
|
alSetError(Context, err);
|
||||||
} break;
|
break;
|
||||||
|
|
||||||
case UserFmtMulaw:
|
case UserFmtMulaw:
|
||||||
case UserFmtAlaw:
|
case UserFmtAlaw:
|
||||||
case UserFmtIMA4: {
|
FrameSize = FrameSizeFromUserFmt(SrcChannels, SrcType);
|
||||||
/* Here is where things vary:
|
NewFormat = AL_FORMAT_MONO16;
|
||||||
* nVidia and Apple use 64+1 sample frames per block -> block_size=36 bytes per channel
|
|
||||||
* Most PC sound software uses 2040+1 sample frames per block -> block_size=1024 bytes per channel
|
|
||||||
*/
|
|
||||||
ALuint FrameSize = (SrcType == UserFmtIMA4) ?
|
|
||||||
(ChannelsFromUserFmt(SrcChannels) * 36) :
|
|
||||||
FrameSizeFromUserFmt(SrcChannels, SrcType);
|
|
||||||
ALenum NewFormat = AL_FORMAT_MONO16;
|
|
||||||
switch(SrcChannels)
|
switch(SrcChannels)
|
||||||
{
|
{
|
||||||
case UserFmtMono: NewFormat = AL_FORMAT_MONO16; break;
|
case UserFmtMono: NewFormat = AL_FORMAT_MONO16; break;
|
||||||
@ -414,6 +409,32 @@ AL_API ALvoid AL_APIENTRY alBufferData(ALuint buffer,ALenum format,const ALvoid
|
|||||||
SrcChannels, SrcType, data, AL_TRUE);
|
SrcChannels, SrcType, data, AL_TRUE);
|
||||||
if(err != AL_NO_ERROR)
|
if(err != AL_NO_ERROR)
|
||||||
alSetError(Context, err);
|
alSetError(Context, err);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case UserFmtIMA4: {
|
||||||
|
/* Here is where things vary:
|
||||||
|
* nVidia and Apple use 64+1 sample frames per block -> block_size=36 bytes per channel
|
||||||
|
* Most PC sound software uses 2040+1 sample frames per block -> block_size=1024 bytes per channel
|
||||||
|
*/
|
||||||
|
ALuint FrameSize = ChannelsFromUserFmt(SrcChannels) * 36;
|
||||||
|
ALenum NewFormat = AL_FORMAT_MONO16;
|
||||||
|
switch(SrcChannels)
|
||||||
|
{
|
||||||
|
case UserFmtMono: NewFormat = AL_FORMAT_MONO16; break;
|
||||||
|
case UserFmtStereo: NewFormat = AL_FORMAT_STEREO16; break;
|
||||||
|
case UserFmtRear: NewFormat = AL_FORMAT_REAR16; break;
|
||||||
|
case UserFmtQuad: NewFormat = AL_FORMAT_QUAD16; break;
|
||||||
|
case UserFmtX51: NewFormat = AL_FORMAT_51CHN16; break;
|
||||||
|
case UserFmtX61: NewFormat = AL_FORMAT_61CHN16; break;
|
||||||
|
case UserFmtX71: NewFormat = AL_FORMAT_71CHN16; break;
|
||||||
|
}
|
||||||
|
if((size%FrameSize) != 0)
|
||||||
|
err = AL_INVALID_VALUE;
|
||||||
|
else
|
||||||
|
err = LoadData(ALBuf, freq, NewFormat, size/FrameSize*65,
|
||||||
|
SrcChannels, SrcType, data, AL_TRUE);
|
||||||
|
if(err != AL_NO_ERROR)
|
||||||
|
alSetError(Context, err);
|
||||||
} break;
|
} break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -468,11 +489,12 @@ AL_API ALvoid AL_APIENTRY alBufferSubDataSOFT(ALuint buffer,ALenum format,const
|
|||||||
ALuint Bytes = BytesFromFmt(ALBuf->FmtType);
|
ALuint Bytes = BytesFromFmt(ALBuf->FmtType);
|
||||||
if(SrcType == UserFmtIMA4)
|
if(SrcType == UserFmtIMA4)
|
||||||
{
|
{
|
||||||
/* offset -> byte offset, length -> block count */
|
/* offset -> byte offset, length -> sample count */
|
||||||
offset /= 36;
|
offset /= 36;
|
||||||
offset *= 65;
|
offset *= 65;
|
||||||
offset *= Bytes;
|
offset *= Bytes;
|
||||||
length /= original_align;
|
length /= original_align;
|
||||||
|
length *= 65;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -513,15 +535,8 @@ AL_API void AL_APIENTRY alBufferSamplesSOFT(ALuint buffer,
|
|||||||
alSetError(Context, AL_INVALID_ENUM);
|
alSetError(Context, AL_INVALID_ENUM);
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
err = AL_NO_ERROR;
|
err = LoadData(ALBuf, samplerate, internalformat, samples,
|
||||||
if(type == UserFmtIMA4)
|
channels, type, data, AL_FALSE);
|
||||||
{
|
|
||||||
if((samples%65) == 0) samples /= 65;
|
|
||||||
else err = AL_INVALID_VALUE;
|
|
||||||
}
|
|
||||||
if(err == AL_NO_ERROR)
|
|
||||||
err = LoadData(ALBuf, samplerate, internalformat, samples,
|
|
||||||
channels, type, data, AL_FALSE);
|
|
||||||
if(err != AL_NO_ERROR)
|
if(err != AL_NO_ERROR)
|
||||||
alSetError(Context, err);
|
alSetError(Context, err);
|
||||||
}
|
}
|
||||||
@ -557,14 +572,10 @@ AL_API void AL_APIENTRY alBufferSubSamplesSOFT(ALuint buffer,
|
|||||||
alSetError(Context, AL_INVALID_ENUM);
|
alSetError(Context, AL_INVALID_ENUM);
|
||||||
else if(offset > ALBuf->SampleLen || samples > ALBuf->SampleLen-offset)
|
else if(offset > ALBuf->SampleLen || samples > ALBuf->SampleLen-offset)
|
||||||
alSetError(Context, AL_INVALID_VALUE);
|
alSetError(Context, AL_INVALID_VALUE);
|
||||||
else if(type == UserFmtIMA4 && (samples%65) != 0)
|
|
||||||
alSetError(Context, AL_INVALID_VALUE);
|
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* offset -> byte offset */
|
/* offset -> byte offset */
|
||||||
offset *= FrameSize;
|
offset *= FrameSize;
|
||||||
/* samples -> IMA4 block count */
|
|
||||||
if(type == UserFmtIMA4) samples /= 65;
|
|
||||||
ConvertData(&((ALubyte*)ALBuf->data)[offset], ALBuf->FmtType,
|
ConvertData(&((ALubyte*)ALBuf->data)[offset], ALBuf->FmtType,
|
||||||
data, type,
|
data, type,
|
||||||
ChannelsFromFmt(ALBuf->FmtChannels), samples);
|
ChannelsFromFmt(ALBuf->FmtChannels), samples);
|
||||||
@ -609,8 +620,6 @@ AL_API void AL_APIENTRY alGetBufferSamplesSOFT(ALuint buffer,
|
|||||||
{
|
{
|
||||||
/* offset -> byte offset */
|
/* offset -> byte offset */
|
||||||
offset *= FrameSize;
|
offset *= FrameSize;
|
||||||
/* samples -> IMA4 block count */
|
|
||||||
if(type == UserFmtIMA4) samples /= 65;
|
|
||||||
ConvertData(data, type,
|
ConvertData(data, type,
|
||||||
&((ALubyte*)ALBuf->data)[offset], ALBuf->FmtType,
|
&((ALubyte*)ALBuf->data)[offset], ALBuf->FmtType,
|
||||||
ChannelsFromFmt(ALBuf->FmtChannels), samples);
|
ChannelsFromFmt(ALBuf->FmtChannels), samples);
|
||||||
@ -839,7 +848,7 @@ AL_API ALvoid AL_APIENTRY alGetBufferf(ALuint buffer, ALenum eParam, ALfloat *pf
|
|||||||
{
|
{
|
||||||
switch(eParam)
|
switch(eParam)
|
||||||
{
|
{
|
||||||
case AL_SEC_LENGTH:
|
case AL_SEC_LENGTH_SOFT:
|
||||||
ReadLock(&pBuffer->lock);
|
ReadLock(&pBuffer->lock);
|
||||||
if(pBuffer->SampleLen != 0)
|
if(pBuffer->SampleLen != 0)
|
||||||
*pflValue = pBuffer->SampleLen / (ALfloat)pBuffer->Frequency;
|
*pflValue = pBuffer->SampleLen / (ALfloat)pBuffer->Frequency;
|
||||||
@ -892,7 +901,7 @@ AL_API void AL_APIENTRY alGetBufferfv(ALuint buffer, ALenum eParam, ALfloat* pfl
|
|||||||
|
|
||||||
switch(eParam)
|
switch(eParam)
|
||||||
{
|
{
|
||||||
case AL_SEC_LENGTH:
|
case AL_SEC_LENGTH_SOFT:
|
||||||
alGetBufferf(buffer, eParam, pflValues);
|
alGetBufferf(buffer, eParam, pflValues);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -956,15 +965,15 @@ AL_API ALvoid AL_APIENTRY alGetBufferi(ALuint buffer, ALenum eParam, ALint *plVa
|
|||||||
ReadUnlock(&pBuffer->lock);
|
ReadUnlock(&pBuffer->lock);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case AL_INTERNAL_FORMAT:
|
case AL_INTERNAL_FORMAT_SOFT:
|
||||||
*plValue = pBuffer->Format;
|
*plValue = pBuffer->Format;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case AL_BYTE_LENGTH:
|
case AL_BYTE_LENGTH_SOFT:
|
||||||
*plValue = pBuffer->OriginalSize;
|
*plValue = pBuffer->OriginalSize;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case AL_SAMPLE_LENGTH:
|
case AL_SAMPLE_LENGTH_SOFT:
|
||||||
*plValue = pBuffer->SampleLen;
|
*plValue = pBuffer->SampleLen;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -1017,9 +1026,9 @@ AL_API void AL_APIENTRY alGetBufferiv(ALuint buffer, ALenum eParam, ALint* plVal
|
|||||||
case AL_BITS:
|
case AL_BITS:
|
||||||
case AL_CHANNELS:
|
case AL_CHANNELS:
|
||||||
case AL_SIZE:
|
case AL_SIZE:
|
||||||
case AL_INTERNAL_FORMAT:
|
case AL_INTERNAL_FORMAT_SOFT:
|
||||||
case AL_BYTE_LENGTH:
|
case AL_BYTE_LENGTH_SOFT:
|
||||||
case AL_SAMPLE_LENGTH:
|
case AL_SAMPLE_LENGTH_SOFT:
|
||||||
alGetBufferi(buffer, eParam, plValues);
|
alGetBufferi(buffer, eParam, plValues);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -1059,9 +1068,11 @@ typedef ALubyte ALima4;
|
|||||||
typedef struct {
|
typedef struct {
|
||||||
ALbyte b[3];
|
ALbyte b[3];
|
||||||
} ALbyte3;
|
} ALbyte3;
|
||||||
|
extern ALbyte ALbyte3_size_is_not_3[(sizeof(ALbyte3)==sizeof(ALbyte[3]))?1:-1];
|
||||||
typedef struct {
|
typedef struct {
|
||||||
ALubyte b[3];
|
ALubyte b[3];
|
||||||
} ALubyte3;
|
} ALubyte3;
|
||||||
|
extern ALbyte ALubyte3_size_is_not_3[(sizeof(ALubyte3)==sizeof(ALubyte[3]))?1:-1];
|
||||||
|
|
||||||
static __inline ALshort DecodeMuLaw(ALmulaw val)
|
static __inline ALshort DecodeMuLaw(ALmulaw val)
|
||||||
{ return muLawDecompressionTable[val]; }
|
{ return muLawDecompressionTable[val]; }
|
||||||
@ -1234,11 +1245,6 @@ static void EncodeIMA4Block(ALima4 *dst, const ALshort *src, ALint *sample, ALin
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static const union {
|
|
||||||
ALuint u;
|
|
||||||
ALubyte b[sizeof(ALuint)];
|
|
||||||
} EndianTest = { 1 };
|
|
||||||
#define IS_LITTLE_ENDIAN (EndianTest.b[0] == 1)
|
|
||||||
|
|
||||||
static __inline ALint DecodeByte3(ALbyte3 val)
|
static __inline ALint DecodeByte3(ALbyte3 val)
|
||||||
{
|
{
|
||||||
@ -1784,16 +1790,22 @@ DECL_TEMPLATE(ALubyte3, ALubyte3)
|
|||||||
|
|
||||||
#define DECL_TEMPLATE(T) \
|
#define DECL_TEMPLATE(T) \
|
||||||
static void Convert_##T##_ALima4(T *dst, const ALima4 *src, ALuint numchans, \
|
static void Convert_##T##_ALima4(T *dst, const ALima4 *src, ALuint numchans, \
|
||||||
ALuint numblocks) \
|
ALuint len) \
|
||||||
{ \
|
{ \
|
||||||
ALuint i, j; \
|
|
||||||
ALshort tmp[65*MAXCHANNELS]; /* Max samples an IMA4 frame can be */ \
|
ALshort tmp[65*MAXCHANNELS]; /* Max samples an IMA4 frame can be */ \
|
||||||
for(i = 0;i < numblocks;i++) \
|
ALuint i, j, k; \
|
||||||
|
\
|
||||||
|
i = 0; \
|
||||||
|
while(i < len) \
|
||||||
{ \
|
{ \
|
||||||
DecodeIMA4Block(tmp, src, numchans); \
|
DecodeIMA4Block(tmp, src, numchans); \
|
||||||
src += 36*numchans; \
|
src += 36*numchans; \
|
||||||
for(j = 0;j < 65*numchans;j++) \
|
\
|
||||||
*(dst++) = Conv_##T##_ALshort(tmp[j]); \
|
for(j = 0;j < 65 && i < len;j++,i++) \
|
||||||
|
{ \
|
||||||
|
for(k = 0;k < numchans;k++) \
|
||||||
|
*(dst++) = Conv_##T##_ALshort(tmp[j*numchans + k]); \
|
||||||
|
} \
|
||||||
} \
|
} \
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1814,13 +1826,14 @@ DECL_TEMPLATE(ALubyte3)
|
|||||||
|
|
||||||
#define DECL_TEMPLATE(T) \
|
#define DECL_TEMPLATE(T) \
|
||||||
static void Convert_ALima4_##T(ALima4 *dst, const T *src, ALuint numchans, \
|
static void Convert_ALima4_##T(ALima4 *dst, const T *src, ALuint numchans, \
|
||||||
ALuint numblocks) \
|
ALuint len) \
|
||||||
{ \
|
{ \
|
||||||
ALuint i, j; \
|
|
||||||
ALshort tmp[65*MAXCHANNELS]; /* Max samples an IMA4 frame can be */ \
|
ALshort tmp[65*MAXCHANNELS]; /* Max samples an IMA4 frame can be */ \
|
||||||
ALint sample[MAXCHANNELS] = {0,0,0,0,0,0,0,0}; \
|
ALint sample[MAXCHANNELS] = {0,0,0,0,0,0,0,0}; \
|
||||||
ALint index[MAXCHANNELS] = {0,0,0,0,0,0,0,0}; \
|
ALint index[MAXCHANNELS] = {0,0,0,0,0,0,0,0}; \
|
||||||
for(i = 0;i < numblocks;i++) \
|
ALuint i, j; \
|
||||||
|
\
|
||||||
|
for(i = 0;i < len;i += 65) \
|
||||||
{ \
|
{ \
|
||||||
for(j = 0;j < 65*numchans;j++) \
|
for(j = 0;j < 65*numchans;j++) \
|
||||||
tmp[j] = Conv_ALshort_##T(*(src++)); \
|
tmp[j] = Conv_ALshort_##T(*(src++)); \
|
||||||
@ -1974,6 +1987,19 @@ static ALenum LoadData(ALbuffer *ALBuf, ALuint freq, ALenum NewFormat, ALsizei f
|
|||||||
ALuint64 newsize;
|
ALuint64 newsize;
|
||||||
ALvoid *temp;
|
ALvoid *temp;
|
||||||
|
|
||||||
|
if(DecomposeFormat(NewFormat, &DstChannels, &DstType) == AL_FALSE ||
|
||||||
|
(long)SrcChannels != (long)DstChannels)
|
||||||
|
return AL_INVALID_ENUM;
|
||||||
|
|
||||||
|
NewChannels = ChannelsFromFmt(DstChannels);
|
||||||
|
NewBytes = BytesFromFmt(DstType);
|
||||||
|
|
||||||
|
newsize = frames;
|
||||||
|
newsize *= NewBytes;
|
||||||
|
newsize *= NewChannels;
|
||||||
|
if(newsize > INT_MAX)
|
||||||
|
return AL_OUT_OF_MEMORY;
|
||||||
|
|
||||||
WriteLock(&ALBuf->lock);
|
WriteLock(&ALBuf->lock);
|
||||||
if(ALBuf->ref != 0)
|
if(ALBuf->ref != 0)
|
||||||
{
|
{
|
||||||
@ -1981,94 +2007,39 @@ static ALenum LoadData(ALbuffer *ALBuf, ALuint freq, ALenum NewFormat, ALsizei f
|
|||||||
return AL_INVALID_OPERATION;
|
return AL_INVALID_OPERATION;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(DecomposeFormat(NewFormat, &DstChannels, &DstType) == AL_FALSE ||
|
temp = realloc(ALBuf->data, (size_t)newsize);
|
||||||
(long)SrcChannels != (long)DstChannels)
|
if(!temp && newsize)
|
||||||
{
|
{
|
||||||
WriteUnlock(&ALBuf->lock);
|
WriteUnlock(&ALBuf->lock);
|
||||||
return AL_INVALID_ENUM;
|
return AL_OUT_OF_MEMORY;
|
||||||
}
|
}
|
||||||
|
ALBuf->data = temp;
|
||||||
|
|
||||||
NewChannels = ChannelsFromFmt(DstChannels);
|
if(data != NULL)
|
||||||
NewBytes = BytesFromFmt(DstType);
|
ConvertData(ALBuf->data, DstType, data, SrcType, NewChannels, frames);
|
||||||
|
|
||||||
if(SrcType == UserFmtIMA4)
|
if(storesrc)
|
||||||
{
|
{
|
||||||
ALuint OrigChannels = ChannelsFromUserFmt(SrcChannels);
|
ALBuf->OriginalChannels = SrcChannels;
|
||||||
|
ALBuf->OriginalType = SrcType;
|
||||||
newsize = frames;
|
if(SrcType == UserFmtIMA4)
|
||||||
newsize *= 65;
|
ALBuf->OriginalSize = frames / 65 * 36 * ChannelsFromUserFmt(SrcChannels);
|
||||||
newsize *= NewBytes;
|
else
|
||||||
newsize *= NewChannels;
|
ALBuf->OriginalSize = frames * FrameSizeFromUserFmt(SrcChannels, SrcType);
|
||||||
if(newsize > INT_MAX)
|
|
||||||
{
|
|
||||||
WriteUnlock(&ALBuf->lock);
|
|
||||||
return AL_OUT_OF_MEMORY;
|
|
||||||
}
|
|
||||||
|
|
||||||
temp = realloc(ALBuf->data, (size_t)newsize);
|
|
||||||
if(!temp && newsize)
|
|
||||||
{
|
|
||||||
WriteUnlock(&ALBuf->lock);
|
|
||||||
return AL_OUT_OF_MEMORY;
|
|
||||||
}
|
|
||||||
ALBuf->data = temp;
|
|
||||||
ALBuf->SampleLen = frames*65;
|
|
||||||
|
|
||||||
if(data != NULL)
|
|
||||||
ConvertData(ALBuf->data, DstType, data, SrcType, NewChannels, frames);
|
|
||||||
|
|
||||||
if(storesrc)
|
|
||||||
{
|
|
||||||
ALBuf->OriginalChannels = SrcChannels;
|
|
||||||
ALBuf->OriginalType = SrcType;
|
|
||||||
ALBuf->OriginalSize = frames * 36 * OrigChannels;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
|
||||||
ALuint OrigBytes = BytesFromUserFmt(SrcType);
|
|
||||||
ALuint OrigChannels = ChannelsFromUserFmt(SrcChannels);
|
|
||||||
|
|
||||||
newsize = frames;
|
|
||||||
newsize *= NewBytes;
|
|
||||||
newsize *= NewChannels;
|
|
||||||
if(newsize > INT_MAX)
|
|
||||||
{
|
|
||||||
WriteUnlock(&ALBuf->lock);
|
|
||||||
return AL_OUT_OF_MEMORY;
|
|
||||||
}
|
|
||||||
|
|
||||||
temp = realloc(ALBuf->data, (size_t)newsize);
|
|
||||||
if(!temp && newsize)
|
|
||||||
{
|
|
||||||
WriteUnlock(&ALBuf->lock);
|
|
||||||
return AL_OUT_OF_MEMORY;
|
|
||||||
}
|
|
||||||
ALBuf->data = temp;
|
|
||||||
ALBuf->SampleLen = frames;
|
|
||||||
|
|
||||||
if(data != NULL)
|
|
||||||
ConvertData(ALBuf->data, DstType, data, SrcType, NewChannels, frames);
|
|
||||||
|
|
||||||
if(storesrc)
|
|
||||||
{
|
|
||||||
ALBuf->OriginalChannels = SrcChannels;
|
|
||||||
ALBuf->OriginalType = SrcType;
|
|
||||||
ALBuf->OriginalSize = frames * OrigBytes * OrigChannels;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if(!storesrc)
|
|
||||||
{
|
{
|
||||||
ALBuf->OriginalChannels = DstChannels;
|
ALBuf->OriginalChannels = DstChannels;
|
||||||
ALBuf->OriginalType = DstType;
|
ALBuf->OriginalType = DstType;
|
||||||
ALBuf->OriginalSize = frames * NewBytes * NewChannels;
|
ALBuf->OriginalSize = frames * NewBytes * NewChannels;
|
||||||
}
|
}
|
||||||
|
|
||||||
ALBuf->Frequency = freq;
|
ALBuf->Frequency = freq;
|
||||||
ALBuf->FmtChannels = DstChannels;
|
ALBuf->FmtChannels = DstChannels;
|
||||||
ALBuf->FmtType = DstType;
|
ALBuf->FmtType = DstType;
|
||||||
ALBuf->Format = NewFormat;
|
ALBuf->Format = NewFormat;
|
||||||
|
|
||||||
|
ALBuf->SampleLen = frames;
|
||||||
ALBuf->LoopStart = 0;
|
ALBuf->LoopStart = 0;
|
||||||
ALBuf->LoopEnd = ALBuf->SampleLen;
|
ALBuf->LoopEnd = ALBuf->SampleLen;
|
||||||
|
|
||||||
@ -2165,7 +2136,7 @@ static ALboolean DecomposeUserFormat(ALenum format, enum UserFmtChannels *chans,
|
|||||||
};
|
};
|
||||||
ALuint i;
|
ALuint i;
|
||||||
|
|
||||||
for(i = 0;i < sizeof(list)/sizeof(list[0]);i++)
|
for(i = 0;i < COUNTOF(list);i++)
|
||||||
{
|
{
|
||||||
if(list[i].format == format)
|
if(list[i].format == format)
|
||||||
{
|
{
|
||||||
@ -2209,40 +2180,40 @@ static ALboolean DecomposeFormat(ALenum format, enum FmtChannels *chans, enum Fm
|
|||||||
enum FmtChannels channels;
|
enum FmtChannels channels;
|
||||||
enum FmtType type;
|
enum FmtType type;
|
||||||
} list[] = {
|
} list[] = {
|
||||||
{ AL_MONO8, FmtMono, FmtByte },
|
{ AL_MONO8_SOFT, FmtMono, FmtByte },
|
||||||
{ AL_MONO16, FmtMono, FmtShort },
|
{ AL_MONO16_SOFT, FmtMono, FmtShort },
|
||||||
{ AL_MONO32F, FmtMono, FmtFloat },
|
{ AL_MONO32F_SOFT, FmtMono, FmtFloat },
|
||||||
|
|
||||||
{ AL_STEREO8, FmtStereo, FmtByte },
|
{ AL_STEREO8_SOFT, FmtStereo, FmtByte },
|
||||||
{ AL_STEREO16, FmtStereo, FmtShort },
|
{ AL_STEREO16_SOFT, FmtStereo, FmtShort },
|
||||||
{ AL_STEREO32F, FmtStereo, FmtFloat },
|
{ AL_STEREO32F_SOFT, FmtStereo, FmtFloat },
|
||||||
|
|
||||||
{ AL_REAR8, FmtRear, FmtByte },
|
{ AL_REAR8_SOFT, FmtRear, FmtByte },
|
||||||
{ AL_REAR16, FmtRear, FmtShort },
|
{ AL_REAR16_SOFT, FmtRear, FmtShort },
|
||||||
{ AL_REAR32F, FmtRear, FmtFloat },
|
{ AL_REAR32F_SOFT, FmtRear, FmtFloat },
|
||||||
|
|
||||||
{ AL_FORMAT_QUAD8_LOKI, FmtQuad, FmtByte },
|
{ AL_FORMAT_QUAD8_LOKI, FmtQuad, FmtByte },
|
||||||
{ AL_FORMAT_QUAD16_LOKI, FmtQuad, FmtShort },
|
{ AL_FORMAT_QUAD16_LOKI, FmtQuad, FmtShort },
|
||||||
|
|
||||||
{ AL_QUAD8, FmtQuad, FmtByte },
|
{ AL_QUAD8_SOFT, FmtQuad, FmtByte },
|
||||||
{ AL_QUAD16, FmtQuad, FmtShort },
|
{ AL_QUAD16_SOFT, FmtQuad, FmtShort },
|
||||||
{ AL_QUAD32F, FmtQuad, FmtFloat },
|
{ AL_QUAD32F_SOFT, FmtQuad, FmtFloat },
|
||||||
|
|
||||||
{ AL_5POINT1_8, FmtX51, FmtByte },
|
{ AL_5POINT1_8_SOFT, FmtX51, FmtByte },
|
||||||
{ AL_5POINT1_16, FmtX51, FmtShort },
|
{ AL_5POINT1_16_SOFT, FmtX51, FmtShort },
|
||||||
{ AL_5POINT1_32F, FmtX51, FmtFloat },
|
{ AL_5POINT1_32F_SOFT, FmtX51, FmtFloat },
|
||||||
|
|
||||||
{ AL_6POINT1_8, FmtX61, FmtByte },
|
{ AL_6POINT1_8_SOFT, FmtX61, FmtByte },
|
||||||
{ AL_6POINT1_16, FmtX61, FmtShort },
|
{ AL_6POINT1_16_SOFT, FmtX61, FmtShort },
|
||||||
{ AL_6POINT1_32F, FmtX61, FmtFloat },
|
{ AL_6POINT1_32F_SOFT, FmtX61, FmtFloat },
|
||||||
|
|
||||||
{ AL_7POINT1_8, FmtX71, FmtByte },
|
{ AL_7POINT1_8_SOFT, FmtX71, FmtByte },
|
||||||
{ AL_7POINT1_16, FmtX71, FmtShort },
|
{ AL_7POINT1_16_SOFT, FmtX71, FmtShort },
|
||||||
{ AL_7POINT1_32F, FmtX71, FmtFloat },
|
{ AL_7POINT1_32F_SOFT, FmtX71, FmtFloat },
|
||||||
};
|
};
|
||||||
ALuint i;
|
ALuint i;
|
||||||
|
|
||||||
for(i = 0;i < sizeof(list)/sizeof(list[0]);i++)
|
for(i = 0;i < COUNTOF(list);i++)
|
||||||
{
|
{
|
||||||
if(list[i].format == format)
|
if(list[i].format == format)
|
||||||
{
|
{
|
||||||
@ -2260,19 +2231,16 @@ static ALboolean IsValidType(ALenum type)
|
|||||||
{
|
{
|
||||||
switch(type)
|
switch(type)
|
||||||
{
|
{
|
||||||
case AL_BYTE:
|
case AL_BYTE_SOFT:
|
||||||
case AL_UNSIGNED_BYTE:
|
case AL_UNSIGNED_BYTE_SOFT:
|
||||||
case AL_SHORT:
|
case AL_SHORT_SOFT:
|
||||||
case AL_UNSIGNED_SHORT:
|
case AL_UNSIGNED_SHORT_SOFT:
|
||||||
case AL_INT:
|
case AL_INT_SOFT:
|
||||||
case AL_UNSIGNED_INT:
|
case AL_UNSIGNED_INT_SOFT:
|
||||||
case AL_FLOAT:
|
case AL_FLOAT_SOFT:
|
||||||
case AL_DOUBLE:
|
case AL_DOUBLE_SOFT:
|
||||||
case AL_MULAW:
|
case AL_BYTE3_SOFT:
|
||||||
case AL_ALAW:
|
case AL_UNSIGNED_BYTE3_SOFT:
|
||||||
case AL_IMA4:
|
|
||||||
case AL_BYTE3:
|
|
||||||
case AL_UNSIGNED_BYTE3:
|
|
||||||
return AL_TRUE;
|
return AL_TRUE;
|
||||||
}
|
}
|
||||||
return AL_FALSE;
|
return AL_FALSE;
|
||||||
@ -2282,13 +2250,13 @@ static ALboolean IsValidChannels(ALenum channels)
|
|||||||
{
|
{
|
||||||
switch(channels)
|
switch(channels)
|
||||||
{
|
{
|
||||||
case AL_MONO:
|
case AL_MONO_SOFT:
|
||||||
case AL_STEREO:
|
case AL_STEREO_SOFT:
|
||||||
case AL_REAR:
|
case AL_REAR_SOFT:
|
||||||
case AL_QUAD:
|
case AL_QUAD_SOFT:
|
||||||
case AL_5POINT1:
|
case AL_5POINT1_SOFT:
|
||||||
case AL_6POINT1:
|
case AL_6POINT1_SOFT:
|
||||||
case AL_7POINT1:
|
case AL_7POINT1_SOFT:
|
||||||
return AL_TRUE;
|
return AL_TRUE;
|
||||||
}
|
}
|
||||||
return AL_FALSE;
|
return AL_FALSE;
|
||||||
|
@ -55,13 +55,13 @@ AL_API ALvoid AL_APIENTRY alGenEffects(ALsizei n, ALuint *effects)
|
|||||||
for(i = 0;i < n;i++)
|
for(i = 0;i < n;i++)
|
||||||
{
|
{
|
||||||
ALeffect *effect = calloc(1, sizeof(ALeffect));
|
ALeffect *effect = calloc(1, sizeof(ALeffect));
|
||||||
if(!effect)
|
if(!effect || InitEffect(effect) != AL_NO_ERROR)
|
||||||
{
|
{
|
||||||
|
free(effect);
|
||||||
alSetError(Context, AL_OUT_OF_MEMORY);
|
alSetError(Context, AL_OUT_OF_MEMORY);
|
||||||
alDeleteEffects(i, effects);
|
alDeleteEffects(i, effects);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
InitEffectParams(effect, AL_EFFECT_NULL);
|
|
||||||
|
|
||||||
err = NewThunkEntry(&effect->effect);
|
err = NewThunkEntry(&effect->effect);
|
||||||
if(err == AL_NO_ERROR)
|
if(err == AL_NO_ERROR)
|
||||||
@ -1173,6 +1173,12 @@ static void null_GetParamfv(ALeffect *effect, ALCcontext *context, ALenum param,
|
|||||||
{ (void)effect;(void)param;(void)vals; alSetError(context, AL_INVALID_ENUM); }
|
{ (void)effect;(void)param;(void)vals; alSetError(context, AL_INVALID_ENUM); }
|
||||||
|
|
||||||
|
|
||||||
|
ALenum InitEffect(ALeffect *effect)
|
||||||
|
{
|
||||||
|
InitEffectParams(effect, AL_EFFECT_NULL);
|
||||||
|
return AL_NO_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
ALvoid ReleaseALEffects(ALCdevice *device)
|
ALvoid ReleaseALEffects(ALCdevice *device)
|
||||||
{
|
{
|
||||||
ALsizei i;
|
ALsizei i;
|
||||||
@ -1306,3 +1312,200 @@ static void InitEffectParams(ALeffect *effect, ALenum type)
|
|||||||
}
|
}
|
||||||
effect->type = type;
|
effect->type = type;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#include "AL/efx-presets.h"
|
||||||
|
|
||||||
|
#define DECL(x) { #x, EFX_REVERB_PRESET_##x }
|
||||||
|
static const struct {
|
||||||
|
const char name[32];
|
||||||
|
EFXEAXREVERBPROPERTIES props;
|
||||||
|
} reverblist[] = {
|
||||||
|
DECL(GENERIC),
|
||||||
|
DECL(PADDEDCELL),
|
||||||
|
DECL(ROOM),
|
||||||
|
DECL(BATHROOM),
|
||||||
|
DECL(LIVINGROOM),
|
||||||
|
DECL(STONEROOM),
|
||||||
|
DECL(AUDITORIUM),
|
||||||
|
DECL(CONCERTHALL),
|
||||||
|
DECL(CAVE),
|
||||||
|
DECL(ARENA),
|
||||||
|
DECL(HANGAR),
|
||||||
|
DECL(CARPETEDHALLWAY),
|
||||||
|
DECL(HALLWAY),
|
||||||
|
DECL(STONECORRIDOR),
|
||||||
|
DECL(ALLEY),
|
||||||
|
DECL(FOREST),
|
||||||
|
DECL(CITY),
|
||||||
|
DECL(MOUNTAINS),
|
||||||
|
DECL(QUARRY),
|
||||||
|
DECL(PLAIN),
|
||||||
|
DECL(PARKINGLOT),
|
||||||
|
DECL(SEWERPIPE),
|
||||||
|
DECL(UNDERWATER),
|
||||||
|
DECL(DRUGGED),
|
||||||
|
DECL(DIZZY),
|
||||||
|
DECL(PSYCHOTIC),
|
||||||
|
|
||||||
|
DECL(CASTLE_SMALLROOM),
|
||||||
|
DECL(CASTLE_SHORTPASSAGE),
|
||||||
|
DECL(CASTLE_MEDIUMROOM),
|
||||||
|
DECL(CASTLE_LARGEROOM),
|
||||||
|
DECL(CASTLE_LONGPASSAGE),
|
||||||
|
DECL(CASTLE_HALL),
|
||||||
|
DECL(CASTLE_CUPBOARD),
|
||||||
|
DECL(CASTLE_COURTYARD),
|
||||||
|
DECL(CASTLE_ALCOVE),
|
||||||
|
|
||||||
|
DECL(FACTORY_SMALLROOM),
|
||||||
|
DECL(FACTORY_SHORTPASSAGE),
|
||||||
|
DECL(FACTORY_MEDIUMROOM),
|
||||||
|
DECL(FACTORY_LARGEROOM),
|
||||||
|
DECL(FACTORY_LONGPASSAGE),
|
||||||
|
DECL(FACTORY_HALL),
|
||||||
|
DECL(FACTORY_CUPBOARD),
|
||||||
|
DECL(FACTORY_COURTYARD),
|
||||||
|
DECL(FACTORY_ALCOVE),
|
||||||
|
|
||||||
|
DECL(ICEPALACE_SMALLROOM),
|
||||||
|
DECL(ICEPALACE_SHORTPASSAGE),
|
||||||
|
DECL(ICEPALACE_MEDIUMROOM),
|
||||||
|
DECL(ICEPALACE_LARGEROOM),
|
||||||
|
DECL(ICEPALACE_LONGPASSAGE),
|
||||||
|
DECL(ICEPALACE_HALL),
|
||||||
|
DECL(ICEPALACE_CUPBOARD),
|
||||||
|
DECL(ICEPALACE_COURTYARD),
|
||||||
|
DECL(ICEPALACE_ALCOVE),
|
||||||
|
|
||||||
|
DECL(SPACESTATION_SMALLROOM),
|
||||||
|
DECL(SPACESTATION_SHORTPASSAGE),
|
||||||
|
DECL(SPACESTATION_MEDIUMROOM),
|
||||||
|
DECL(SPACESTATION_LARGEROOM),
|
||||||
|
DECL(SPACESTATION_LONGPASSAGE),
|
||||||
|
DECL(SPACESTATION_HALL),
|
||||||
|
DECL(SPACESTATION_CUPBOARD),
|
||||||
|
DECL(SPACESTATION_ALCOVE),
|
||||||
|
|
||||||
|
DECL(WOODEN_SMALLROOM),
|
||||||
|
DECL(WOODEN_SHORTPASSAGE),
|
||||||
|
DECL(WOODEN_MEDIUMROOM),
|
||||||
|
DECL(WOODEN_LARGEROOM),
|
||||||
|
DECL(WOODEN_LONGPASSAGE),
|
||||||
|
DECL(WOODEN_HALL),
|
||||||
|
DECL(WOODEN_CUPBOARD),
|
||||||
|
DECL(WOODEN_COURTYARD),
|
||||||
|
DECL(WOODEN_ALCOVE),
|
||||||
|
|
||||||
|
DECL(SPORT_EMPTYSTADIUM),
|
||||||
|
DECL(SPORT_SQUASHCOURT),
|
||||||
|
DECL(SPORT_SMALLSWIMMINGPOOL),
|
||||||
|
DECL(SPORT_LARGESWIMMINGPOOL),
|
||||||
|
DECL(SPORT_GYMNASIUM),
|
||||||
|
DECL(SPORT_FULLSTADIUM),
|
||||||
|
DECL(SPORT_STADIUMTANNOY),
|
||||||
|
|
||||||
|
DECL(PREFAB_WORKSHOP),
|
||||||
|
DECL(PREFAB_SCHOOLROOM),
|
||||||
|
DECL(PREFAB_PRACTISEROOM),
|
||||||
|
DECL(PREFAB_OUTHOUSE),
|
||||||
|
DECL(PREFAB_CARAVAN),
|
||||||
|
|
||||||
|
DECL(DOME_TOMB),
|
||||||
|
DECL(PIPE_SMALL),
|
||||||
|
DECL(DOME_SAINTPAULS),
|
||||||
|
DECL(PIPE_LONGTHIN),
|
||||||
|
DECL(PIPE_LARGE),
|
||||||
|
DECL(PIPE_RESONANT),
|
||||||
|
|
||||||
|
DECL(OUTDOORS_BACKYARD),
|
||||||
|
DECL(OUTDOORS_ROLLINGPLAINS),
|
||||||
|
DECL(OUTDOORS_DEEPCANYON),
|
||||||
|
DECL(OUTDOORS_CREEK),
|
||||||
|
DECL(OUTDOORS_VALLEY),
|
||||||
|
|
||||||
|
DECL(MOOD_HEAVEN),
|
||||||
|
DECL(MOOD_HELL),
|
||||||
|
DECL(MOOD_MEMORY),
|
||||||
|
|
||||||
|
DECL(DRIVING_COMMENTATOR),
|
||||||
|
DECL(DRIVING_PITGARAGE),
|
||||||
|
DECL(DRIVING_INCAR_RACER),
|
||||||
|
DECL(DRIVING_INCAR_SPORTS),
|
||||||
|
DECL(DRIVING_INCAR_LUXURY),
|
||||||
|
DECL(DRIVING_FULLGRANDSTAND),
|
||||||
|
DECL(DRIVING_EMPTYGRANDSTAND),
|
||||||
|
DECL(DRIVING_TUNNEL),
|
||||||
|
|
||||||
|
DECL(CITY_STREETS),
|
||||||
|
DECL(CITY_SUBWAY),
|
||||||
|
DECL(CITY_MUSEUM),
|
||||||
|
DECL(CITY_LIBRARY),
|
||||||
|
DECL(CITY_UNDERPASS),
|
||||||
|
DECL(CITY_ABANDONED),
|
||||||
|
|
||||||
|
DECL(DUSTYROOM),
|
||||||
|
DECL(CHAPEL),
|
||||||
|
DECL(SMALLWATERROOM),
|
||||||
|
};
|
||||||
|
#undef DECL
|
||||||
|
static const ALsizei reverblistsize = COUNTOF(reverblist);
|
||||||
|
|
||||||
|
ALvoid GetReverbEffect(const char *name, ALeffect *effect)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
if(strcasecmp(name, "NONE") == 0)
|
||||||
|
{
|
||||||
|
InitEffectParams(effect, AL_EFFECT_NULL);
|
||||||
|
TRACE("Loading reverb '%s'\n", "NONE");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!DisabledEffects[EAXREVERB])
|
||||||
|
InitEffectParams(effect, AL_EFFECT_EAXREVERB);
|
||||||
|
else if(!DisabledEffects[REVERB])
|
||||||
|
InitEffectParams(effect, AL_EFFECT_REVERB);
|
||||||
|
else
|
||||||
|
InitEffectParams(effect, AL_EFFECT_NULL);
|
||||||
|
for(i = 0;i < reverblistsize;i++)
|
||||||
|
{
|
||||||
|
const EFXEAXREVERBPROPERTIES *props;
|
||||||
|
|
||||||
|
if(strcasecmp(name, reverblist[i].name) != 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
TRACE("Loading reverb '%s'\n", reverblist[i].name);
|
||||||
|
props = &reverblist[i].props;
|
||||||
|
effect->Reverb.Density = props->flDensity;
|
||||||
|
effect->Reverb.Diffusion = props->flDiffusion;
|
||||||
|
effect->Reverb.Gain = props->flGain;
|
||||||
|
effect->Reverb.GainHF = props->flGainHF;
|
||||||
|
effect->Reverb.GainLF = props->flGainLF;
|
||||||
|
effect->Reverb.DecayTime = props->flDecayTime;
|
||||||
|
effect->Reverb.DecayHFRatio = props->flDecayHFRatio;
|
||||||
|
effect->Reverb.DecayLFRatio = props->flDecayLFRatio;
|
||||||
|
effect->Reverb.ReflectionsGain = props->flReflectionsGain;
|
||||||
|
effect->Reverb.ReflectionsDelay = props->flReflectionsDelay;
|
||||||
|
effect->Reverb.ReflectionsPan[0] = props->flReflectionsPan[0];
|
||||||
|
effect->Reverb.ReflectionsPan[1] = props->flReflectionsPan[1];
|
||||||
|
effect->Reverb.ReflectionsPan[2] = props->flReflectionsPan[2];
|
||||||
|
effect->Reverb.LateReverbGain = props->flLateReverbGain;
|
||||||
|
effect->Reverb.LateReverbDelay = props->flLateReverbDelay;
|
||||||
|
effect->Reverb.LateReverbPan[0] = props->flLateReverbPan[0];
|
||||||
|
effect->Reverb.LateReverbPan[1] = props->flLateReverbPan[1];
|
||||||
|
effect->Reverb.LateReverbPan[2] = props->flLateReverbPan[2];
|
||||||
|
effect->Reverb.EchoTime = props->flEchoTime;
|
||||||
|
effect->Reverb.EchoDepth = props->flEchoDepth;
|
||||||
|
effect->Reverb.ModulationTime = props->flModulationTime;
|
||||||
|
effect->Reverb.ModulationDepth = props->flModulationDepth;
|
||||||
|
effect->Reverb.AirAbsorptionGainHF = props->flAirAbsorptionGainHF;
|
||||||
|
effect->Reverb.HFReference = props->flHFReference;
|
||||||
|
effect->Reverb.LFReference = props->flLFReference;
|
||||||
|
effect->Reverb.RoomRolloffFactor = props->flRoomRolloffFactor;
|
||||||
|
effect->Reverb.DecayHFLimit = props->iDecayHFLimit;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if(i == reverblistsize)
|
||||||
|
WARN("Reverb preset '%s' not found\n", name);
|
||||||
|
}
|
||||||
|
@ -75,7 +75,7 @@ static const ALenums enumeration[] = {
|
|||||||
{ "AL_STREAMING", AL_STREAMING },
|
{ "AL_STREAMING", AL_STREAMING },
|
||||||
{ "AL_UNDETERMINED", AL_UNDETERMINED },
|
{ "AL_UNDETERMINED", AL_UNDETERMINED },
|
||||||
{ "AL_METERS_PER_UNIT", AL_METERS_PER_UNIT },
|
{ "AL_METERS_PER_UNIT", AL_METERS_PER_UNIT },
|
||||||
{ "AL_VIRTUAL_CHANNELS_SOFT", AL_VIRTUAL_CHANNELS_SOFT },
|
{ "AL_DIRECT_CHANNELS_SOFT", AL_DIRECT_CHANNELS_SOFT },
|
||||||
|
|
||||||
// Source EFX Properties
|
// Source EFX Properties
|
||||||
{ "AL_DIRECT_FILTER", AL_DIRECT_FILTER },
|
{ "AL_DIRECT_FILTER", AL_DIRECT_FILTER },
|
||||||
@ -139,61 +139,58 @@ static const ALenums enumeration[] = {
|
|||||||
{ "AL_FORMAT_STEREO_ALAW_EXT", AL_FORMAT_STEREO_ALAW_EXT },
|
{ "AL_FORMAT_STEREO_ALAW_EXT", AL_FORMAT_STEREO_ALAW_EXT },
|
||||||
|
|
||||||
// Internal Buffer Formats
|
// Internal Buffer Formats
|
||||||
{ "AL_MONO8", AL_MONO8 },
|
{ "AL_MONO8_SOFT", AL_MONO8_SOFT },
|
||||||
{ "AL_MONO16", AL_MONO16 },
|
{ "AL_MONO16_SOFT", AL_MONO16_SOFT },
|
||||||
{ "AL_MONO32F", AL_MONO32F },
|
{ "AL_MONO32F_SOFT", AL_MONO32F_SOFT },
|
||||||
{ "AL_STEREO8", AL_STEREO8 },
|
{ "AL_STEREO8_SOFT", AL_STEREO8_SOFT },
|
||||||
{ "AL_STEREO16", AL_STEREO16 },
|
{ "AL_STEREO16_SOFT", AL_STEREO16_SOFT },
|
||||||
{ "AL_STEREO32F", AL_STEREO32F },
|
{ "AL_STEREO32F_SOFT", AL_STEREO32F_SOFT },
|
||||||
{ "AL_QUAD8", AL_QUAD8 },
|
{ "AL_QUAD8_SOFT", AL_QUAD8_SOFT },
|
||||||
{ "AL_QUAD16", AL_QUAD16 },
|
{ "AL_QUAD16_SOFT", AL_QUAD16_SOFT },
|
||||||
{ "AL_QUAD32F", AL_QUAD32F },
|
{ "AL_QUAD32F_SOFT", AL_QUAD32F_SOFT },
|
||||||
{ "AL_REAR8", AL_REAR8 },
|
{ "AL_REAR8_SOFT", AL_REAR8_SOFT },
|
||||||
{ "AL_REAR16", AL_REAR16 },
|
{ "AL_REAR16_SOFT", AL_REAR16_SOFT },
|
||||||
{ "AL_REAR32F", AL_REAR32F },
|
{ "AL_REAR32F_SOFT", AL_REAR32F_SOFT },
|
||||||
{ "AL_5POINT1_8", AL_5POINT1_8 },
|
{ "AL_5POINT1_8_SOFT", AL_5POINT1_8_SOFT },
|
||||||
{ "AL_5POINT1_16", AL_5POINT1_16 },
|
{ "AL_5POINT1_16_SOFT", AL_5POINT1_16_SOFT },
|
||||||
{ "AL_5POINT1_32F", AL_5POINT1_32F },
|
{ "AL_5POINT1_32F_SOFT", AL_5POINT1_32F_SOFT },
|
||||||
{ "AL_6POINT1_8", AL_6POINT1_8 },
|
{ "AL_6POINT1_8_SOFT", AL_6POINT1_8_SOFT },
|
||||||
{ "AL_6POINT1_16", AL_6POINT1_16 },
|
{ "AL_6POINT1_16_SOFT", AL_6POINT1_16_SOFT },
|
||||||
{ "AL_6POINT1_32F", AL_6POINT1_32F },
|
{ "AL_6POINT1_32F_SOFT", AL_6POINT1_32F_SOFT },
|
||||||
{ "AL_7POINT1_8", AL_7POINT1_8 },
|
{ "AL_7POINT1_8_SOFT", AL_7POINT1_8_SOFT },
|
||||||
{ "AL_7POINT1_16", AL_7POINT1_16 },
|
{ "AL_7POINT1_16_SOFT", AL_7POINT1_16_SOFT },
|
||||||
{ "AL_7POINT1_32F", AL_7POINT1_32F },
|
{ "AL_7POINT1_32F_SOFT", AL_7POINT1_32F_SOFT },
|
||||||
|
|
||||||
// Buffer Channel Configurations
|
// Buffer Channel Configurations
|
||||||
{ "AL_MONO", AL_MONO },
|
{ "AL_MONO_SOFT", AL_MONO_SOFT },
|
||||||
{ "AL_STEREO", AL_STEREO },
|
{ "AL_STEREO_SOFT", AL_STEREO_SOFT },
|
||||||
{ "AL_QUAD", AL_QUAD },
|
{ "AL_QUAD_SOFT", AL_QUAD_SOFT },
|
||||||
{ "AL_REAR", AL_REAR },
|
{ "AL_REAR_SOFT", AL_REAR_SOFT },
|
||||||
{ "AL_5POINT1", AL_5POINT1 },
|
{ "AL_5POINT1_SOFT", AL_5POINT1_SOFT },
|
||||||
{ "AL_6POINT1", AL_6POINT1 },
|
{ "AL_6POINT1_SOFT", AL_6POINT1_SOFT },
|
||||||
{ "AL_7POINT1", AL_7POINT1 },
|
{ "AL_7POINT1_SOFT", AL_7POINT1_SOFT },
|
||||||
|
|
||||||
// Buffer Sample Types
|
// Buffer Sample Types
|
||||||
{ "AL_BYTE", AL_BYTE },
|
{ "AL_BYTE_SOFT", AL_BYTE_SOFT },
|
||||||
{ "AL_UNSIGNED_BYTE", AL_UNSIGNED_BYTE },
|
{ "AL_UNSIGNED_BYTE_SOFT", AL_UNSIGNED_BYTE_SOFT },
|
||||||
{ "AL_SHORT", AL_SHORT },
|
{ "AL_SHORT_SOFT", AL_SHORT_SOFT },
|
||||||
{ "AL_UNSIGNED_SHORT", AL_UNSIGNED_SHORT },
|
{ "AL_UNSIGNED_SHORT_SOFT", AL_UNSIGNED_SHORT_SOFT },
|
||||||
{ "AL_INT", AL_INT },
|
{ "AL_INT_SOFT", AL_INT_SOFT },
|
||||||
{ "AL_UNSIGNED_INT", AL_UNSIGNED_INT },
|
{ "AL_UNSIGNED_INT_SOFT", AL_UNSIGNED_INT_SOFT },
|
||||||
{ "AL_FLOAT", AL_FLOAT },
|
{ "AL_FLOAT_SOFT", AL_FLOAT_SOFT },
|
||||||
{ "AL_DOUBLE", AL_DOUBLE },
|
{ "AL_DOUBLE_SOFT", AL_DOUBLE_SOFT },
|
||||||
{ "AL_MULAW", AL_MULAW },
|
{ "AL_BYTE3_SOFT", AL_BYTE3_SOFT },
|
||||||
{ "AL_ALAW", AL_ALAW },
|
{ "AL_UNSIGNED_BYTE3_SOFT", AL_UNSIGNED_BYTE3_SOFT },
|
||||||
{ "AL_IMA4", AL_IMA4 },
|
|
||||||
{ "AL_BYTE3", AL_BYTE3 },
|
|
||||||
{ "AL_UNSIGNED_BYTE3", AL_UNSIGNED_BYTE3 },
|
|
||||||
|
|
||||||
// Buffer attributes
|
// Buffer attributes
|
||||||
{ "AL_FREQUENCY", AL_FREQUENCY },
|
{ "AL_FREQUENCY", AL_FREQUENCY },
|
||||||
{ "AL_BITS", AL_BITS },
|
{ "AL_BITS", AL_BITS },
|
||||||
{ "AL_CHANNELS", AL_CHANNELS },
|
{ "AL_CHANNELS", AL_CHANNELS },
|
||||||
{ "AL_SIZE", AL_SIZE },
|
{ "AL_SIZE", AL_SIZE },
|
||||||
{ "AL_INTERNAL_FORMAT", AL_INTERNAL_FORMAT },
|
{ "AL_INTERNAL_FORMAT_SOFT", AL_INTERNAL_FORMAT_SOFT },
|
||||||
{ "AL_BYTE_LENGTH", AL_BYTE_LENGTH },
|
{ "AL_BYTE_LENGTH_SOFT", AL_BYTE_LENGTH_SOFT },
|
||||||
{ "AL_SAMPLE_LENGTH", AL_SAMPLE_LENGTH },
|
{ "AL_SAMPLE_LENGTH_SOFT", AL_SAMPLE_LENGTH_SOFT },
|
||||||
{ "AL_SEC_LENGTH", AL_SEC_LENGTH },
|
{ "AL_SEC_LENGTH_SOFT", AL_SEC_LENGTH_SOFT },
|
||||||
|
|
||||||
// Buffer States (not supported yet)
|
// Buffer States (not supported yet)
|
||||||
{ "AL_UNUSED", AL_UNUSED },
|
{ "AL_UNUSED", AL_UNUSED },
|
||||||
|
@ -33,13 +33,13 @@
|
|||||||
#include "alAuxEffectSlot.h"
|
#include "alAuxEffectSlot.h"
|
||||||
|
|
||||||
|
|
||||||
enum Resampler DefaultResampler = RESAMPLER_DEFAULT;
|
enum Resampler DefaultResampler = LinearResampler;
|
||||||
const ALsizei ResamplerPadding[RESAMPLER_MAX] = {
|
const ALsizei ResamplerPadding[ResamplerMax] = {
|
||||||
0, /* Point */
|
0, /* Point */
|
||||||
1, /* Linear */
|
1, /* Linear */
|
||||||
2, /* Cubic */
|
2, /* Cubic */
|
||||||
};
|
};
|
||||||
const ALsizei ResamplerPrePadding[RESAMPLER_MAX] = {
|
const ALsizei ResamplerPrePadding[ResamplerMax] = {
|
||||||
0, /* Point */
|
0, /* Point */
|
||||||
0, /* Linear */
|
0, /* Linear */
|
||||||
1, /* Cubic */
|
1, /* Cubic */
|
||||||
@ -54,12 +54,10 @@ static ALint GetSampleOffset(ALsource *Source);
|
|||||||
AL_API ALvoid AL_APIENTRY alGenSources(ALsizei n,ALuint *sources)
|
AL_API ALvoid AL_APIENTRY alGenSources(ALsizei n,ALuint *sources)
|
||||||
{
|
{
|
||||||
ALCcontext *Context;
|
ALCcontext *Context;
|
||||||
ALCdevice *Device;
|
|
||||||
|
|
||||||
Context = GetContextRef();
|
Context = GetContextRef();
|
||||||
if(!Context) return;
|
if(!Context) return;
|
||||||
|
|
||||||
Device = Context->Device;
|
|
||||||
if(n < 0 || IsBadWritePtr((void*)sources, n * sizeof(ALuint)))
|
if(n < 0 || IsBadWritePtr((void*)sources, n * sizeof(ALuint)))
|
||||||
alSetError(Context, AL_INVALID_VALUE);
|
alSetError(Context, AL_INVALID_VALUE);
|
||||||
else
|
else
|
||||||
@ -583,7 +581,7 @@ AL_API ALvoid AL_APIENTRY alSourcei(ALuint source,ALenum eParam,ALint lValue)
|
|||||||
// Increment reference counter for buffer
|
// Increment reference counter for buffer
|
||||||
IncrementRef(&buffer->ref);
|
IncrementRef(&buffer->ref);
|
||||||
|
|
||||||
oldlist = ExchangePtr((void**)&Source->queue, BufferListItem);
|
oldlist = ExchangePtr((XchgPtr*)&Source->queue, BufferListItem);
|
||||||
Source->BuffersInQueue = 1;
|
Source->BuffersInQueue = 1;
|
||||||
|
|
||||||
ReadLock(&buffer->lock);
|
ReadLock(&buffer->lock);
|
||||||
@ -600,7 +598,7 @@ AL_API ALvoid AL_APIENTRY alSourcei(ALuint source,ALenum eParam,ALint lValue)
|
|||||||
{
|
{
|
||||||
// Source is now in UNDETERMINED mode
|
// Source is now in UNDETERMINED mode
|
||||||
Source->lSourceType = AL_UNDETERMINED;
|
Source->lSourceType = AL_UNDETERMINED;
|
||||||
oldlist = ExchangePtr((void**)&Source->queue, NULL);
|
oldlist = ExchangePtr((XchgPtr*)&Source->queue, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Delete all previous elements in the queue
|
// Delete all previous elements in the queue
|
||||||
@ -706,10 +704,10 @@ AL_API ALvoid AL_APIENTRY alSourcei(ALuint source,ALenum eParam,ALint lValue)
|
|||||||
alSetError(pContext, AL_INVALID_VALUE);
|
alSetError(pContext, AL_INVALID_VALUE);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case AL_VIRTUAL_CHANNELS_SOFT:
|
case AL_DIRECT_CHANNELS_SOFT:
|
||||||
if(lValue == AL_TRUE || lValue == AL_FALSE)
|
if(lValue == AL_TRUE || lValue == AL_FALSE)
|
||||||
{
|
{
|
||||||
Source->VirtualChannels = lValue;
|
Source->DirectChannels = lValue;
|
||||||
Source->NeedsUpdate = AL_TRUE;
|
Source->NeedsUpdate = AL_TRUE;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -780,7 +778,7 @@ AL_API void AL_APIENTRY alSource3i(ALuint source, ALenum eParam, ALint lValue1,
|
|||||||
/* Release refcount on the previous slot, and add one for
|
/* Release refcount on the previous slot, and add one for
|
||||||
* the new slot */
|
* the new slot */
|
||||||
if(ALEffectSlot) IncrementRef(&ALEffectSlot->ref);
|
if(ALEffectSlot) IncrementRef(&ALEffectSlot->ref);
|
||||||
ALEffectSlot = ExchangePtr((void**)&Source->Send[lValue2].Slot, ALEffectSlot);
|
ALEffectSlot = ExchangePtr((XchgPtr*)&Source->Send[lValue2].Slot, ALEffectSlot);
|
||||||
if(ALEffectSlot) DecrementRef(&ALEffectSlot->ref);
|
if(ALEffectSlot) DecrementRef(&ALEffectSlot->ref);
|
||||||
|
|
||||||
if(!ALFilter)
|
if(!ALFilter)
|
||||||
@ -838,7 +836,7 @@ AL_API void AL_APIENTRY alSourceiv(ALuint source, ALenum eParam, const ALint* pl
|
|||||||
case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO:
|
case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO:
|
||||||
case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO:
|
case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO:
|
||||||
case AL_DISTANCE_MODEL:
|
case AL_DISTANCE_MODEL:
|
||||||
case AL_VIRTUAL_CHANNELS_SOFT:
|
case AL_DIRECT_CHANNELS_SOFT:
|
||||||
alSourcei(source, eParam, plValues[0]);
|
alSourcei(source, eParam, plValues[0]);
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@ -1211,8 +1209,8 @@ AL_API ALvoid AL_APIENTRY alGetSourcei(ALuint source, ALenum eParam, ALint *plVa
|
|||||||
*plValue = (ALint)Source->DopplerFactor;
|
*plValue = (ALint)Source->DopplerFactor;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case AL_VIRTUAL_CHANNELS_SOFT:
|
case AL_DIRECT_CHANNELS_SOFT:
|
||||||
*plValue = Source->VirtualChannels;
|
*plValue = Source->DirectChannels;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case AL_DISTANCE_MODEL:
|
case AL_DISTANCE_MODEL:
|
||||||
@ -1317,7 +1315,7 @@ AL_API void AL_APIENTRY alGetSourceiv(ALuint source, ALenum eParam, ALint* plVal
|
|||||||
case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO:
|
case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO:
|
||||||
case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO:
|
case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO:
|
||||||
case AL_DISTANCE_MODEL:
|
case AL_DISTANCE_MODEL:
|
||||||
case AL_VIRTUAL_CHANNELS_SOFT:
|
case AL_DIRECT_CHANNELS_SOFT:
|
||||||
alGetSourcei(source, eParam, plValues);
|
alGetSourcei(source, eParam, plValues);
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@ -1824,9 +1822,9 @@ static ALvoid InitSourceParams(ALsource *Source)
|
|||||||
Source->AirAbsorptionFactor = 0.0f;
|
Source->AirAbsorptionFactor = 0.0f;
|
||||||
Source->RoomRolloffFactor = 0.0f;
|
Source->RoomRolloffFactor = 0.0f;
|
||||||
Source->DopplerFactor = 1.0f;
|
Source->DopplerFactor = 1.0f;
|
||||||
Source->VirtualChannels = AL_TRUE;
|
Source->DirectChannels = AL_FALSE;
|
||||||
|
|
||||||
Source->DistanceModel = AL_INVERSE_DISTANCE_CLAMPED;
|
Source->DistanceModel = DefaultDistanceModel;
|
||||||
|
|
||||||
Source->Resampler = DefaultResampler;
|
Source->Resampler = DefaultResampler;
|
||||||
|
|
||||||
@ -1985,6 +1983,9 @@ static ALvoid GetSourceOffset(ALsource *Source, ALenum name, ALdouble *offset, A
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(updateLen > 0.0 && updateLen < 0.015)
|
||||||
|
updateLen = 0.015;
|
||||||
|
|
||||||
// Get Current SamplesPlayed (NOTE : This is the offset into the *current* buffer)
|
// Get Current SamplesPlayed (NOTE : This is the offset into the *current* buffer)
|
||||||
readPos = Source->position;
|
readPos = Source->position;
|
||||||
// Add length of any processed buffers in the queue
|
// Add length of any processed buffers in the queue
|
||||||
|
114
alsoftrc.sample
114
alsoftrc.sample
@ -5,35 +5,29 @@
|
|||||||
# The system-wide settings can be put in /etc/openal/alsoft.conf and user-
|
# The system-wide settings can be put in /etc/openal/alsoft.conf and user-
|
||||||
# specific override settings in ~/.alsoftrc.
|
# specific override settings in ~/.alsoftrc.
|
||||||
# For Windows, these settings should go into %AppData%\alsoft.ini
|
# For Windows, these settings should go into %AppData%\alsoft.ini
|
||||||
# The environment variable ALSOFT_CONF can be used to specify another config
|
|
||||||
# override
|
|
||||||
|
|
||||||
# Option and block names are case-insenstive. The supplied values are only
|
# Option and block names are case-insenstive. The supplied values are only
|
||||||
# hints and may not be honored (though generally it'll try to get as close as
|
# hints and may not be honored (though generally it'll try to get as close as
|
||||||
# possible). Note: options that are left unset may default to app- or system-
|
# possible). Note: options that are left unset may default to app- or system-
|
||||||
# specified values. These are the current available settings:
|
# specified values. These are the current available settings:
|
||||||
|
|
||||||
## format:
|
## channels:
|
||||||
# Sets the output format. Can be one of:
|
# Sets the output channel configuration. If left unspecified, one will try to
|
||||||
# AL_FORMAT_MONO8 (8-bit mono)
|
# be detected from the system, and defaulting to stereo. The available values
|
||||||
# AL_FORMAT_STEREO8 (8-bit stereo)
|
# are: mono, stereo, quad, surround51, surround61, surround71
|
||||||
# AL_FORMAT_QUAD8 (8-bit 4-channel)
|
#channels = stereo
|
||||||
# AL_FORMAT_51CHN8 (8-bit 5.1 output)
|
|
||||||
# AL_FORMAT_61CHN8 (8-bit 6.1 output)
|
## sample-type:
|
||||||
# AL_FORMAT_71CHN8 (8-bit 7.1 output)
|
# Sets the output sample type. Currently, all mixing is done with 32-bit float
|
||||||
# AL_FORMAT_MONO16 (16-bit mono)
|
# and converted to the output sample type as needed. Available values are:
|
||||||
# AL_FORMAT_STEREO16 (16-bit stereo)
|
# int8 - signed 8-bit int
|
||||||
# AL_FORMAT_QUAD16 (16-bit 4-channel)
|
# uint8 - unsigned 8-bit int
|
||||||
# AL_FORMAT_51CHN16 (16-bit 5.1 output)
|
# int16 - signed 16-bit int
|
||||||
# AL_FORMAT_61CHN16 (16-bit 6.1 output)
|
# uint16 - unsigned 16-bit int
|
||||||
# AL_FORMAT_71CHN16 (16-bit 7.1 output)
|
# int32 - signed 32-bit int
|
||||||
# AL_FORMAT_MONO32 (32-bit float mono)
|
# uint32 - unsigned 32-bit int
|
||||||
# AL_FORMAT_STEREO32 (32-bit float stereo)
|
# float32 - 32-bit float
|
||||||
# AL_FORMAT_QUAD32 (32-bit float 4-channel)
|
#sample-type = float32
|
||||||
# AL_FORMAT_51CHN32 (32-bit float 5.1 output)
|
|
||||||
# AL_FORMAT_61CHN32 (32-bit float 6.1 output)
|
|
||||||
# AL_FORMAT_71CHN32 (32-bit float 7.1 output)
|
|
||||||
#format = AL_FORMAT_STEREO16
|
|
||||||
|
|
||||||
## hrtf:
|
## hrtf:
|
||||||
# Enables HRTF filters. These filters provide for better sound spatialization
|
# Enables HRTF filters. These filters provide for better sound spatialization
|
||||||
@ -42,6 +36,12 @@
|
|||||||
# Default is disabled since stereo speaker output quality may suffer.
|
# Default is disabled since stereo speaker output quality may suffer.
|
||||||
#hrtf = false
|
#hrtf = false
|
||||||
|
|
||||||
|
## hrtf_tables
|
||||||
|
# Specifies a comma-separated list of files containing HRTF data sets. The
|
||||||
|
# listed data sets can be used in place of or in addiiton to the the built-in
|
||||||
|
# set. The format of the files are described in hrtf.txt.
|
||||||
|
#hrtf_tables =
|
||||||
|
|
||||||
## cf_level:
|
## cf_level:
|
||||||
# Sets the crossfeed level for stereo output. Valid values are:
|
# Sets the crossfeed level for stereo output. Valid values are:
|
||||||
# 0 - No crossfeed
|
# 0 - No crossfeed
|
||||||
@ -61,11 +61,11 @@
|
|||||||
|
|
||||||
## resampler:
|
## resampler:
|
||||||
# Selects the resampler used when mixing sources. Valid values are:
|
# Selects the resampler used when mixing sources. Valid values are:
|
||||||
# 0 - None (nearest sample, no interpolation)
|
# point - nearest sample, no interpolation
|
||||||
# 1 - Linear (extrapolates samples using a linear slope between samples)
|
# linear - extrapolates samples using a linear slope between samples
|
||||||
# 2 - Cubic (extrapolates samples using a Catmull-Rom spline)
|
# cubic - extrapolates samples using a Catmull-Rom spline
|
||||||
# Specifying other values will result in using the default (linear).
|
# Specifying other values will result in using the default (linear).
|
||||||
#resampler = 1
|
#resampler = linear
|
||||||
|
|
||||||
## rt-prio:
|
## rt-prio:
|
||||||
# Sets real-time priority for the mixing thread. Not all drivers may use this
|
# Sets real-time priority for the mixing thread. Not all drivers may use this
|
||||||
@ -78,13 +78,14 @@
|
|||||||
|
|
||||||
## period_size:
|
## period_size:
|
||||||
# Sets the update period size, in frames. This is the number of frames needed
|
# Sets the update period size, in frames. This is the number of frames needed
|
||||||
# for each mixing update.
|
# for each mixing update. Acceptable values range between 64 and 8192.
|
||||||
#period_size = 1024
|
#period_size = 1024
|
||||||
|
|
||||||
## periods:
|
## periods:
|
||||||
# Sets the number of update periods. Higher values create a larger mix ahead,
|
# Sets the number of update periods. Higher values create a larger mix ahead,
|
||||||
# which helps protect against skips when the CPU is under load, but increases
|
# which helps protect against skips when the CPU is under load, but increases
|
||||||
# the delay between a sound getting mixed and being heard.
|
# the delay between a sound getting mixed and being heard. Acceptable values
|
||||||
|
# range between 2 and 16.
|
||||||
#periods = 4
|
#periods = 4
|
||||||
|
|
||||||
## sources:
|
## sources:
|
||||||
@ -93,13 +94,13 @@
|
|||||||
#sources = 256
|
#sources = 256
|
||||||
|
|
||||||
## stereodup:
|
## stereodup:
|
||||||
# Sets whether to duplicate stereo sounds behind the listener for 4+ channel
|
# Sets whether to duplicate stereo sounds behind the listener. This provides a
|
||||||
# output. This provides a "fuller" playback quality for surround sound output
|
# "fuller" playback quality for surround sound output modes, although each
|
||||||
# modes, although each individual speaker will have a slight reduction in
|
# individual speaker will have a slight reduction in volume to compensate for
|
||||||
# volume to compensate for the extra output speakers. True, yes, on, and non-0
|
# the extra output speakers. True, yes, on, and non-0 values will duplicate
|
||||||
# values will duplicate stereo sources. 0 and anything else will cause stereo
|
# stereo sources. 0 and anything else will cause stereo sounds to only play in
|
||||||
# sounds to only play in front. This only has an effect when a suitable output
|
# front. This only has an effect when a suitable output format is used (ie.
|
||||||
# format is used (ie. those that contain side and/or rear speakers).
|
# those that contain side and/or rear speakers).
|
||||||
#stereodup = true
|
#stereodup = true
|
||||||
|
|
||||||
## drivers:
|
## drivers:
|
||||||
@ -144,26 +145,31 @@
|
|||||||
# Channel-specific layouts may be specified to override the layout option. The
|
# Channel-specific layouts may be specified to override the layout option. The
|
||||||
# same speakers as the layout option are available, and the default settings
|
# same speakers as the layout option are available, and the default settings
|
||||||
# are shown below.
|
# are shown below.
|
||||||
#layout_STEREO = fl=-90, fr=90
|
#layout_stereo = fl=-90, fr=90
|
||||||
#layout_QUAD = fl=-45, fr=45, bl=-135, br=135
|
#layout_quad = fl=-45, fr=45, bl=-135, br=135
|
||||||
#layout_51CHN = fl=-30, fr=30, fc=0, bl=-110, br=110
|
#layout_surround51 = fl=-30, fr=30, fc=0, bl=-110, br=110
|
||||||
#layout_61CHN = fl=-30, fr=30, fc=0, sl=-90, sr=90, bc=180
|
#layout_surround61 = fl=-30, fr=30, fc=0, sl=-90, sr=90, bc=180
|
||||||
#layout_71CHN = fl=-30, fr=30, fc=0, sl=-90, sr=90, bl=-150, br=150
|
#layout_surround71 = fl=-30, fr=30, fc=0, sl=-90, sr=90, bl=-150, br=150
|
||||||
|
|
||||||
|
## default-reverb:
|
||||||
|
# A reverb preset that applies by default to all sources on send 0
|
||||||
|
# (applications that set their own slots on send 0 will override this).
|
||||||
|
# Available presets are: None, Generic, PaddedCell, Room, Bathroom,
|
||||||
|
# Livingroom, Stoneroom, Auditorium, ConcertHall, Cave, Arena, Hangar,
|
||||||
|
# CarpetedHallway, Hallway, StoneCorridor, Alley, Forest, City, Moutains,
|
||||||
|
# Quarry, Plain, ParkingLot, SewerPipe, Underwater, Drugged, Dizzy, Psychotic.
|
||||||
|
#default-reverb =
|
||||||
|
|
||||||
## trap-alc-error:
|
## trap-alc-error:
|
||||||
# Generates a SIGTRAP signal when an ALC device error is generated, on systems
|
# Generates a SIGTRAP signal when an ALC device error is generated, on systems
|
||||||
# that support it. This helps when debugging, while trying to find the cause
|
# that support it. This helps when debugging, while trying to find the cause
|
||||||
# of a device error. On Windows, a breakpoint exception is generated.
|
# of a device error. On Windows, a breakpoint exception is generated.
|
||||||
# Optionally, the __ALSOFT_TRAP_ALC_ERROR env var may be set before running
|
|
||||||
# the app instead.
|
|
||||||
#trap-alc-error = false
|
#trap-alc-error = false
|
||||||
|
|
||||||
## trap-al-error:
|
## trap-al-error:
|
||||||
# Generates a SIGTRAP signal when an AL context error is generated, on systems
|
# Generates a SIGTRAP signal when an AL context error is generated, on systems
|
||||||
# that support it. This helps when debugging, while trying to find the cause
|
# that support it. This helps when debugging, while trying to find the cause
|
||||||
# of a context error. On Windows, a breakpoint exception is generated.
|
# of a context error. On Windows, a breakpoint exception is generated.
|
||||||
# Optionally, the __ALSOFT_TRAP_AL_ERROR env var may be set before running the
|
|
||||||
# app instead.
|
|
||||||
#trap-al-error = false
|
#trap-al-error = false
|
||||||
|
|
||||||
##
|
##
|
||||||
@ -199,16 +205,30 @@
|
|||||||
# device index for the requested device name.
|
# device index for the requested device name.
|
||||||
#device-prefix = plughw:
|
#device-prefix = plughw:
|
||||||
|
|
||||||
|
## device-prefix-*:
|
||||||
|
# Card- and device-specific prefixes may be used to override the device-prefix
|
||||||
|
# option. The option may specify the card id (eg, device-prefix-NVidia), or
|
||||||
|
# the card id and device index (eg, device-prefix-NVidia-0). The card id is
|
||||||
|
# case-sensitive.
|
||||||
|
#defice-prefix- =
|
||||||
|
|
||||||
## capture:
|
## capture:
|
||||||
# Sets the device name for the default capture device.
|
# Sets the device name for the default capture device.
|
||||||
#capture = default
|
#capture = default
|
||||||
|
|
||||||
## capture-prefix:
|
## capture-prefix:
|
||||||
# Sets the prefix used by the discovered (non-default) capture devices. This
|
# Sets the prefix used by the discovered (non-default) capture devices. This
|
||||||
# will be appended with "CARD=c,DEV=d", where c is the card number and d is
|
# will be appended with "CARD=c,DEV=d", where c is the card id and d is the
|
||||||
# the device number for the requested device name.
|
# device number for the requested device name.
|
||||||
#capture-prefix = plughw:
|
#capture-prefix = plughw:
|
||||||
|
|
||||||
|
## capture-prefix-*:
|
||||||
|
# Card- and device-specific prefixes may be used to override the
|
||||||
|
# capture-prefix option. The option may specify the card id (eg,
|
||||||
|
# capture-prefix-NVidia), or the card id and device index (eg,
|
||||||
|
# capture-prefix-NVidia-0). The card id is case-sensitive.
|
||||||
|
#capture-prefix- =
|
||||||
|
|
||||||
## mmap:
|
## mmap:
|
||||||
# Sets whether to try using mmap mode (helps reduce latencies and CPU
|
# Sets whether to try using mmap mode (helps reduce latencies and CPU
|
||||||
# consumption). If mmap isn't available, it will automatically fall back to
|
# consumption). If mmap isn't available, it will automatically fall back to
|
||||||
|
71
env-vars.txt
Normal file
71
env-vars.txt
Normal file
@ -0,0 +1,71 @@
|
|||||||
|
Useful Environment Variables
|
||||||
|
|
||||||
|
Below is a list of environment variables that can be set to aid with running or
|
||||||
|
debugging apps that use OpenAL Soft. They should be set before the app is run.
|
||||||
|
|
||||||
|
*** Logging ***
|
||||||
|
|
||||||
|
ALSOFT_LOGLEVEL
|
||||||
|
Specifies the amount of logging OpenAL Soft will write out:
|
||||||
|
0 - Effectively disables all logging
|
||||||
|
1 - Prints out errors only
|
||||||
|
2 - Prints out warnings and errors
|
||||||
|
3 - Prints out additional information, as well as warnings and errors
|
||||||
|
4 - Same as 3, but also device and context reference count changes. This will
|
||||||
|
print out *a lot* of info, and is generally not useful unless you're trying
|
||||||
|
to track a reference leak within the library.
|
||||||
|
|
||||||
|
ALSOFT_LOGFILE
|
||||||
|
Specifies a filename that logged output will be written to. Note that the file
|
||||||
|
will be first cleared when logging is initialized.
|
||||||
|
|
||||||
|
*** Overrides ***
|
||||||
|
|
||||||
|
ALSOFT_CONF
|
||||||
|
Specifies an additional configuration file to load settings from. These
|
||||||
|
settings will take precedence over the global and user configs, but not other
|
||||||
|
environment variable settings.
|
||||||
|
|
||||||
|
ALSOFT_DRIVERS
|
||||||
|
Overrides the drivers config option. This specifies which backend drivers to
|
||||||
|
consider or not consider for use. Please see the drivers option in
|
||||||
|
alsoftrc.sample for a list of available drivers.
|
||||||
|
|
||||||
|
ALSOFT_DEFAULT_REVERB
|
||||||
|
Specifies the default reverb preset to apply to sources. Please see the
|
||||||
|
default-reverb option in alsoftrc.sample for additional information and a list
|
||||||
|
of available presets.
|
||||||
|
|
||||||
|
ALSOFT_TRAP_AL_ERROR
|
||||||
|
Set to "true" or "1" to force trapping AL errors. Like the trap-al-error config
|
||||||
|
option, this will raise a SIGTRAP signal (or a breakpoint exception under
|
||||||
|
Windows) when a context-level error is generated. Useful when run under a
|
||||||
|
debugger as it will break execution right when the error occurs, making it
|
||||||
|
easier to track the cause.
|
||||||
|
|
||||||
|
ALSOFT_TRAP_ALC_ERROR
|
||||||
|
Set to "true" or "1" to force trapping ALC errors. Like the trap-alc-error
|
||||||
|
config option, this will raise a SIGTRAP signal (or a breakpoint exception
|
||||||
|
under Windows) when a device-level error is generated. Useful when run under a
|
||||||
|
debugger as it will break execution right when the error occurs, making it
|
||||||
|
easier to track the cause.
|
||||||
|
|
||||||
|
ALSOFT_TRAP_ERROR
|
||||||
|
Set to "true" or "1" to force trapping both ALC and AL errors.
|
||||||
|
|
||||||
|
*** Compatibility ***
|
||||||
|
|
||||||
|
__ALSOFT_HALF_ANGLE_CONES
|
||||||
|
Older versions of OpenAL Soft incorrectly calculated the cone angles to range
|
||||||
|
between 0 and 180 degrees, instead of the expected range of 0 to 360 degrees.
|
||||||
|
Setting this to "true" or "1" restores the old buggy behavior, for apps that
|
||||||
|
were written to expect the incorrect range.
|
||||||
|
|
||||||
|
__ALSOFT_REVERSE_Z
|
||||||
|
Applications that don't natively use OpenAL's coordinate system have to convert
|
||||||
|
to it before passing in 3D coordinates. Depending on how exactly this is done,
|
||||||
|
it can cause correct output for stereo but incorrect Z panning for surround
|
||||||
|
sound (i.e., sounds that are supposed to be behind you sound like they're in
|
||||||
|
front, and vice-versa). Setting this to "true" or "1" will negate the localized
|
||||||
|
Z coordinate to attempt to fix output for apps that have incorrect front/back
|
||||||
|
panning.
|
625
examples/alffmpeg.c
Normal file
625
examples/alffmpeg.c
Normal file
@ -0,0 +1,625 @@
|
|||||||
|
/*
|
||||||
|
* FFmpeg Decoder Helpers
|
||||||
|
*
|
||||||
|
* Copyright (c) 2011 by Chris Robinson <chris.kcat@gmail.com>
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* This file contains routines for helping to decode audio using libavformat
|
||||||
|
* and libavcodec (ffmpeg). There's very little OpenAL-specific code here. */
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <signal.h>
|
||||||
|
#include <assert.h>
|
||||||
|
|
||||||
|
#include "AL/al.h"
|
||||||
|
#include "AL/alc.h"
|
||||||
|
#include "AL/alext.h"
|
||||||
|
|
||||||
|
#include "alhelpers.h"
|
||||||
|
#include "alffmpeg.h"
|
||||||
|
|
||||||
|
|
||||||
|
static size_t NextPowerOf2(size_t value)
|
||||||
|
{
|
||||||
|
size_t powerOf2 = 1;
|
||||||
|
|
||||||
|
if(value)
|
||||||
|
{
|
||||||
|
value--;
|
||||||
|
while(value)
|
||||||
|
{
|
||||||
|
value >>= 1;
|
||||||
|
powerOf2 <<= 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return powerOf2;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
struct MemData {
|
||||||
|
char *buffer;
|
||||||
|
size_t length;
|
||||||
|
size_t pos;
|
||||||
|
};
|
||||||
|
|
||||||
|
static int MemData_read(void *opaque, uint8_t *buf, int buf_size)
|
||||||
|
{
|
||||||
|
struct MemData *membuf = (struct MemData*)opaque;
|
||||||
|
int rem = membuf->length - membuf->pos;
|
||||||
|
|
||||||
|
if(rem > buf_size)
|
||||||
|
rem = buf_size;
|
||||||
|
|
||||||
|
memcpy(buf, &membuf->buffer[membuf->pos], rem);
|
||||||
|
membuf->pos += rem;
|
||||||
|
|
||||||
|
return rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int MemData_write(void *opaque, uint8_t *buf, int buf_size)
|
||||||
|
{
|
||||||
|
struct MemData *membuf = (struct MemData*)opaque;
|
||||||
|
int rem = membuf->length - membuf->pos;
|
||||||
|
|
||||||
|
if(rem > buf_size)
|
||||||
|
rem = buf_size;
|
||||||
|
|
||||||
|
memcpy(&membuf->buffer[membuf->pos], buf, rem);
|
||||||
|
membuf->pos += rem;
|
||||||
|
|
||||||
|
return rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int64_t MemData_seek(void *opaque, int64_t offset, int whence)
|
||||||
|
{
|
||||||
|
struct MemData *membuf = (struct MemData*)opaque;
|
||||||
|
|
||||||
|
whence &= ~AVSEEK_FORCE;
|
||||||
|
switch(whence)
|
||||||
|
{
|
||||||
|
case SEEK_SET:
|
||||||
|
if(offset < 0 || offset > membuf->length)
|
||||||
|
return -1;
|
||||||
|
membuf->pos = offset;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SEEK_CUR:
|
||||||
|
if((offset >= 0 && offset > membuf->length-membuf->pos) ||
|
||||||
|
(offset < 0 && offset < -membuf->pos))
|
||||||
|
return -1;
|
||||||
|
membuf->pos += offset;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SEEK_END:
|
||||||
|
if(offset > 0 || offset < -membuf->length)
|
||||||
|
return -1;
|
||||||
|
membuf->pos = membuf->length + offset;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case AVSEEK_SIZE:
|
||||||
|
return membuf->length;
|
||||||
|
|
||||||
|
default:
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return membuf->pos;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
struct PacketList {
|
||||||
|
AVPacket pkt;
|
||||||
|
struct PacketList *next;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct MyStream {
|
||||||
|
AVCodecContext *CodecCtx;
|
||||||
|
int StreamIdx;
|
||||||
|
|
||||||
|
struct PacketList *Packets;
|
||||||
|
|
||||||
|
char *DecodedData;
|
||||||
|
size_t DecodedDataSize;
|
||||||
|
|
||||||
|
FilePtr parent;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct MyFile {
|
||||||
|
AVFormatContext *FmtCtx;
|
||||||
|
|
||||||
|
StreamPtr *Streams;
|
||||||
|
size_t StreamsSize;
|
||||||
|
|
||||||
|
struct MemData membuf;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
static int done_init = 0;
|
||||||
|
|
||||||
|
FilePtr openAVFile(const char *fname)
|
||||||
|
{
|
||||||
|
FilePtr file;
|
||||||
|
|
||||||
|
/* We need to make sure ffmpeg is initialized. Optionally silence warning
|
||||||
|
* output from the lib */
|
||||||
|
if(!done_init) {av_register_all();
|
||||||
|
av_log_set_level(AV_LOG_ERROR);
|
||||||
|
done_init = 1;}
|
||||||
|
|
||||||
|
file = (FilePtr)calloc(1, sizeof(*file));
|
||||||
|
if(file && avformat_open_input(&file->FmtCtx, fname, NULL, NULL) == 0)
|
||||||
|
{
|
||||||
|
/* After opening, we must search for the stream information because not
|
||||||
|
* all formats will have it in stream headers */
|
||||||
|
if(avformat_find_stream_info(file->FmtCtx, NULL) >= 0)
|
||||||
|
return file;
|
||||||
|
av_close_input_file(file->FmtCtx);
|
||||||
|
}
|
||||||
|
|
||||||
|
free(file);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
FilePtr openAVData(const char *name, char *buffer, size_t buffer_len)
|
||||||
|
{
|
||||||
|
FilePtr file;
|
||||||
|
|
||||||
|
if(!done_init) {av_register_all();
|
||||||
|
av_log_set_level(AV_LOG_ERROR);
|
||||||
|
done_init = 1;}
|
||||||
|
|
||||||
|
if(!name)
|
||||||
|
name = "";
|
||||||
|
|
||||||
|
file = (FilePtr)calloc(1, sizeof(*file));
|
||||||
|
if(file && (file->FmtCtx=avformat_alloc_context()) != NULL)
|
||||||
|
{
|
||||||
|
file->membuf.buffer = buffer;
|
||||||
|
file->membuf.length = buffer_len;
|
||||||
|
file->membuf.pos = 0;
|
||||||
|
|
||||||
|
file->FmtCtx->pb = avio_alloc_context(NULL, 0, 0, &file->membuf,
|
||||||
|
MemData_read, MemData_write,
|
||||||
|
MemData_seek);
|
||||||
|
if(file->FmtCtx->pb && avformat_open_input(&file->FmtCtx, name, NULL, NULL) == 0)
|
||||||
|
{
|
||||||
|
if(avformat_find_stream_info(file->FmtCtx, NULL) >= 0)
|
||||||
|
return file;
|
||||||
|
}
|
||||||
|
av_close_input_file(file->FmtCtx);
|
||||||
|
}
|
||||||
|
|
||||||
|
free(file);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
FilePtr openAVCustom(const char *name, void *user_data,
|
||||||
|
int (*read_packet)(void *user_data, uint8_t *buf, int buf_size),
|
||||||
|
int (*write_packet)(void *user_data, uint8_t *buf, int buf_size),
|
||||||
|
int64_t (*seek)(void *user_data, int64_t offset, int whence))
|
||||||
|
{
|
||||||
|
FilePtr file;
|
||||||
|
|
||||||
|
if(!done_init) {av_register_all();
|
||||||
|
av_log_set_level(AV_LOG_ERROR);
|
||||||
|
done_init = 1;}
|
||||||
|
|
||||||
|
if(!name)
|
||||||
|
name = "";
|
||||||
|
|
||||||
|
file = (FilePtr)calloc(1, sizeof(*file));
|
||||||
|
if(file && (file->FmtCtx=avformat_alloc_context()) != NULL)
|
||||||
|
{
|
||||||
|
file->FmtCtx->pb = avio_alloc_context(NULL, 0, 0, user_data,
|
||||||
|
read_packet, write_packet, seek);
|
||||||
|
if(file->FmtCtx->pb && avformat_open_input(&file->FmtCtx, name, NULL, NULL) == 0)
|
||||||
|
{
|
||||||
|
if(avformat_find_stream_info(file->FmtCtx, NULL) >= 0)
|
||||||
|
return file;
|
||||||
|
}
|
||||||
|
av_close_input_file(file->FmtCtx);
|
||||||
|
}
|
||||||
|
|
||||||
|
free(file);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void closeAVFile(FilePtr file)
|
||||||
|
{
|
||||||
|
size_t i;
|
||||||
|
|
||||||
|
if(!file) return;
|
||||||
|
|
||||||
|
for(i = 0;i < file->StreamsSize;i++)
|
||||||
|
{
|
||||||
|
StreamPtr stream = file->Streams[i];
|
||||||
|
|
||||||
|
while(stream->Packets)
|
||||||
|
{
|
||||||
|
struct PacketList *self;
|
||||||
|
|
||||||
|
self = stream->Packets;
|
||||||
|
stream->Packets = self->next;
|
||||||
|
|
||||||
|
av_free_packet(&self->pkt);
|
||||||
|
av_free(self);
|
||||||
|
}
|
||||||
|
|
||||||
|
avcodec_close(stream->CodecCtx);
|
||||||
|
av_free(stream->DecodedData);
|
||||||
|
free(stream);
|
||||||
|
}
|
||||||
|
free(file->Streams);
|
||||||
|
|
||||||
|
av_close_input_file(file->FmtCtx);
|
||||||
|
free(file);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int getAVFileInfo(FilePtr file, int *numaudiostreams)
|
||||||
|
{
|
||||||
|
unsigned int i;
|
||||||
|
int audiocount = 0;
|
||||||
|
|
||||||
|
if(!file) return 1;
|
||||||
|
for(i = 0;i < file->FmtCtx->nb_streams;i++)
|
||||||
|
{
|
||||||
|
if(file->FmtCtx->streams[i]->codec->codec_type == AVMEDIA_TYPE_AUDIO)
|
||||||
|
audiocount++;
|
||||||
|
}
|
||||||
|
*numaudiostreams = audiocount;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
StreamPtr getAVAudioStream(FilePtr file, int streamnum)
|
||||||
|
{
|
||||||
|
unsigned int i;
|
||||||
|
if(!file) return NULL;
|
||||||
|
for(i = 0;i < file->FmtCtx->nb_streams;i++)
|
||||||
|
{
|
||||||
|
if(file->FmtCtx->streams[i]->codec->codec_type != AVMEDIA_TYPE_AUDIO)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if(streamnum == 0)
|
||||||
|
{
|
||||||
|
StreamPtr stream;
|
||||||
|
AVCodec *codec;
|
||||||
|
void *temp;
|
||||||
|
size_t j;
|
||||||
|
|
||||||
|
/* Found the requested stream. Check if a handle to this stream
|
||||||
|
* already exists and return it if it does */
|
||||||
|
for(j = 0;j < file->StreamsSize;j++)
|
||||||
|
{
|
||||||
|
if(file->Streams[j]->StreamIdx == (int)i)
|
||||||
|
return file->Streams[j];
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Doesn't yet exist. Now allocate a new stream object and fill in
|
||||||
|
* its info */
|
||||||
|
stream = (StreamPtr)calloc(1, sizeof(*stream));
|
||||||
|
if(!stream) return NULL;
|
||||||
|
|
||||||
|
stream->parent = file;
|
||||||
|
stream->CodecCtx = file->FmtCtx->streams[i]->codec;
|
||||||
|
stream->StreamIdx = i;
|
||||||
|
|
||||||
|
/* Try to find the codec for the given codec ID, and open it */
|
||||||
|
codec = avcodec_find_decoder(stream->CodecCtx->codec_id);
|
||||||
|
if(!codec || avcodec_open(stream->CodecCtx, codec) < 0)
|
||||||
|
{
|
||||||
|
free(stream);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Allocate space for the decoded data to be stored in before it
|
||||||
|
* gets passed to the app */
|
||||||
|
stream->DecodedData = (char*)av_malloc(AVCODEC_MAX_AUDIO_FRAME_SIZE);
|
||||||
|
if(!stream->DecodedData)
|
||||||
|
{
|
||||||
|
avcodec_close(stream->CodecCtx);
|
||||||
|
free(stream);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Append the new stream object to the stream list. The original
|
||||||
|
* pointer will remain valid if realloc fails, so we need to use
|
||||||
|
* another pointer to watch for errors and not leak memory */
|
||||||
|
temp = realloc(file->Streams, (file->StreamsSize+1) *
|
||||||
|
sizeof(*file->Streams));
|
||||||
|
if(!temp)
|
||||||
|
{
|
||||||
|
avcodec_close(stream->CodecCtx);
|
||||||
|
av_free(stream->DecodedData);
|
||||||
|
free(stream);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
file->Streams = (StreamPtr*)temp;
|
||||||
|
file->Streams[file->StreamsSize++] = stream;
|
||||||
|
return stream;
|
||||||
|
}
|
||||||
|
streamnum--;
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
int getAVAudioInfo(StreamPtr stream, ALuint *rate, ALenum *channels, ALenum *type)
|
||||||
|
{
|
||||||
|
if(!stream || stream->CodecCtx->codec_type != AVMEDIA_TYPE_AUDIO)
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
/* Get the sample type for OpenAL given the format detected by ffmpeg. */
|
||||||
|
if(stream->CodecCtx->sample_fmt == AV_SAMPLE_FMT_U8)
|
||||||
|
*type = AL_UNSIGNED_BYTE_SOFT;
|
||||||
|
else if(stream->CodecCtx->sample_fmt == AV_SAMPLE_FMT_S16)
|
||||||
|
*type = AL_SHORT_SOFT;
|
||||||
|
else if(stream->CodecCtx->sample_fmt == AV_SAMPLE_FMT_S32)
|
||||||
|
*type = AL_INT_SOFT;
|
||||||
|
else if(stream->CodecCtx->sample_fmt == AV_SAMPLE_FMT_FLT)
|
||||||
|
*type = AL_FLOAT_SOFT;
|
||||||
|
else if(stream->CodecCtx->sample_fmt == AV_SAMPLE_FMT_DBL)
|
||||||
|
*type = AL_DOUBLE_SOFT;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
fprintf(stderr, "Unsupported ffmpeg sample format: %s\n",
|
||||||
|
av_get_sample_fmt_name(stream->CodecCtx->sample_fmt));
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Get the OpenAL channel configuration using the channel layout detected
|
||||||
|
* by ffmpeg. NOTE: some file types may not specify a channel layout. In
|
||||||
|
* that case, one must be guessed based on the channel count. */
|
||||||
|
if(stream->CodecCtx->channel_layout == AV_CH_LAYOUT_MONO)
|
||||||
|
*channels = AL_MONO_SOFT;
|
||||||
|
else if(stream->CodecCtx->channel_layout == AV_CH_LAYOUT_STEREO)
|
||||||
|
*channels = AL_STEREO_SOFT;
|
||||||
|
else if(stream->CodecCtx->channel_layout == AV_CH_LAYOUT_QUAD)
|
||||||
|
*channels = AL_QUAD_SOFT;
|
||||||
|
else if(stream->CodecCtx->channel_layout == AV_CH_LAYOUT_5POINT1_BACK)
|
||||||
|
*channels = AL_5POINT1_SOFT;
|
||||||
|
else if(stream->CodecCtx->channel_layout == AV_CH_LAYOUT_7POINT1)
|
||||||
|
*channels = AL_7POINT1_SOFT;
|
||||||
|
else if(stream->CodecCtx->channel_layout == 0)
|
||||||
|
{
|
||||||
|
/* Unknown channel layout. Try to guess. */
|
||||||
|
if(stream->CodecCtx->channels == 1)
|
||||||
|
*channels = AL_MONO_SOFT;
|
||||||
|
else if(stream->CodecCtx->channels == 2)
|
||||||
|
*channels = AL_STEREO_SOFT;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
fprintf(stderr, "Unsupported ffmpeg raw channel count: %d\n",
|
||||||
|
stream->CodecCtx->channels);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
char str[1024];
|
||||||
|
av_get_channel_layout_string(str, sizeof(str), stream->CodecCtx->channels,
|
||||||
|
stream->CodecCtx->channel_layout);
|
||||||
|
fprintf(stderr, "Unsupported ffmpeg channel layout: %s\n", str);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
*rate = stream->CodecCtx->sample_rate;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Used by getAV*Data to search for more compressed data, and buffer it in the
|
||||||
|
* correct stream. It won't buffer data for streams that the app doesn't have a
|
||||||
|
* handle for. */
|
||||||
|
static int getNextPacket(FilePtr file, int streamidx)
|
||||||
|
{
|
||||||
|
struct PacketList *packet;
|
||||||
|
|
||||||
|
packet = (struct PacketList*)av_malloc(sizeof(*packet));
|
||||||
|
packet->next = NULL;
|
||||||
|
|
||||||
|
next_packet:
|
||||||
|
while(av_read_frame(file->FmtCtx, &packet->pkt) >= 0)
|
||||||
|
{
|
||||||
|
StreamPtr *iter = file->Streams;
|
||||||
|
StreamPtr *iter_end = iter + file->StreamsSize;
|
||||||
|
|
||||||
|
/* Check each stream the user has a handle for, looking for the one
|
||||||
|
* this packet belongs to */
|
||||||
|
while(iter != iter_end)
|
||||||
|
{
|
||||||
|
if((*iter)->StreamIdx == packet->pkt.stream_index)
|
||||||
|
{
|
||||||
|
struct PacketList **last;
|
||||||
|
|
||||||
|
last = &(*iter)->Packets;
|
||||||
|
while(*last != NULL)
|
||||||
|
last = &(*last)->next;
|
||||||
|
|
||||||
|
*last = packet;
|
||||||
|
if((*iter)->StreamIdx == streamidx)
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
packet = (struct PacketList*)av_malloc(sizeof(*packet));
|
||||||
|
packet->next = NULL;
|
||||||
|
goto next_packet;
|
||||||
|
}
|
||||||
|
iter++;
|
||||||
|
}
|
||||||
|
/* Free the packet and look for another */
|
||||||
|
av_free_packet(&packet->pkt);
|
||||||
|
}
|
||||||
|
|
||||||
|
av_free(packet);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void *getAVAudioData(StreamPtr stream, size_t *length)
|
||||||
|
{
|
||||||
|
int size;
|
||||||
|
int len;
|
||||||
|
|
||||||
|
if(length) *length = 0;
|
||||||
|
|
||||||
|
if(!stream || stream->CodecCtx->codec_type != AVMEDIA_TYPE_AUDIO)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
stream->DecodedDataSize = 0;
|
||||||
|
|
||||||
|
next_packet:
|
||||||
|
if(!stream->Packets && !getNextPacket(stream->parent, stream->StreamIdx))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
/* Decode some data, and check for errors */
|
||||||
|
size = AVCODEC_MAX_AUDIO_FRAME_SIZE;
|
||||||
|
while((len=avcodec_decode_audio3(stream->CodecCtx,
|
||||||
|
(int16_t*)stream->DecodedData, &size,
|
||||||
|
&stream->Packets->pkt)) == 0)
|
||||||
|
{
|
||||||
|
struct PacketList *self;
|
||||||
|
|
||||||
|
if(size > 0)
|
||||||
|
break;
|
||||||
|
|
||||||
|
/* Packet went unread and no data was given? Drop it and try the next,
|
||||||
|
* I guess... */
|
||||||
|
self = stream->Packets;
|
||||||
|
stream->Packets = self->next;
|
||||||
|
|
||||||
|
av_free_packet(&self->pkt);
|
||||||
|
av_free(self);
|
||||||
|
|
||||||
|
if(!stream->Packets)
|
||||||
|
goto next_packet;
|
||||||
|
|
||||||
|
size = AVCODEC_MAX_AUDIO_FRAME_SIZE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(len < 0)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
if(len < stream->Packets->pkt.size)
|
||||||
|
{
|
||||||
|
/* Move the unread data to the front and clear the end bits */
|
||||||
|
int remaining = stream->Packets->pkt.size - len;
|
||||||
|
memmove(stream->Packets->pkt.data, &stream->Packets->pkt.data[len],
|
||||||
|
remaining);
|
||||||
|
memset(&stream->Packets->pkt.data[remaining], 0,
|
||||||
|
stream->Packets->pkt.size - remaining);
|
||||||
|
stream->Packets->pkt.size -= len;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
struct PacketList *self;
|
||||||
|
|
||||||
|
self = stream->Packets;
|
||||||
|
stream->Packets = self->next;
|
||||||
|
|
||||||
|
av_free_packet(&self->pkt);
|
||||||
|
av_free(self);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(size == 0)
|
||||||
|
goto next_packet;
|
||||||
|
|
||||||
|
/* Set the output buffer size */
|
||||||
|
stream->DecodedDataSize = size;
|
||||||
|
if(length) *length = stream->DecodedDataSize;
|
||||||
|
|
||||||
|
return stream->DecodedData;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t readAVAudioData(StreamPtr stream, void *data, size_t length)
|
||||||
|
{
|
||||||
|
size_t dec = 0;
|
||||||
|
|
||||||
|
if(!stream || stream->CodecCtx->codec_type != AVMEDIA_TYPE_AUDIO)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
while(dec < length)
|
||||||
|
{
|
||||||
|
/* If there's no decoded data, find some */
|
||||||
|
if(stream->DecodedDataSize == 0)
|
||||||
|
{
|
||||||
|
if(getAVAudioData(stream, NULL) == NULL)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(stream->DecodedDataSize > 0)
|
||||||
|
{
|
||||||
|
/* Get the amount of bytes remaining to be written, and clamp to
|
||||||
|
* the amount of decoded data we have */
|
||||||
|
size_t rem = length-dec;
|
||||||
|
if(rem > stream->DecodedDataSize)
|
||||||
|
rem = stream->DecodedDataSize;
|
||||||
|
|
||||||
|
/* Copy the data to the app's buffer and increment */
|
||||||
|
if(data != NULL)
|
||||||
|
{
|
||||||
|
memcpy(data, stream->DecodedData, rem);
|
||||||
|
data = (char*)data + rem;
|
||||||
|
}
|
||||||
|
dec += rem;
|
||||||
|
|
||||||
|
/* If there's any decoded data left, move it to the front of the
|
||||||
|
* buffer for next time */
|
||||||
|
if(rem < stream->DecodedDataSize)
|
||||||
|
memmove(stream->DecodedData, &stream->DecodedData[rem],
|
||||||
|
stream->DecodedDataSize - rem);
|
||||||
|
stream->DecodedDataSize -= rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Return the number of bytes we were able to get */
|
||||||
|
return dec;
|
||||||
|
}
|
||||||
|
|
||||||
|
void *decodeAVAudioStream(StreamPtr stream, size_t *length)
|
||||||
|
{
|
||||||
|
char *outbuf = NULL;
|
||||||
|
size_t buflen = 0;
|
||||||
|
void *inbuf;
|
||||||
|
size_t got;
|
||||||
|
|
||||||
|
*length = 0;
|
||||||
|
if(!stream || stream->CodecCtx->codec_type != AVMEDIA_TYPE_AUDIO)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
while((inbuf=getAVAudioData(stream, &got)) != NULL && got > 0)
|
||||||
|
{
|
||||||
|
void *ptr;
|
||||||
|
|
||||||
|
ptr = realloc(outbuf, NextPowerOf2(buflen+got));
|
||||||
|
if(ptr == NULL)
|
||||||
|
break;
|
||||||
|
outbuf = (char*)ptr;
|
||||||
|
|
||||||
|
memcpy(&outbuf[buflen], inbuf, got);
|
||||||
|
buflen += got;
|
||||||
|
}
|
||||||
|
outbuf = (char*)realloc(outbuf, buflen);
|
||||||
|
|
||||||
|
*length = buflen;
|
||||||
|
return outbuf;
|
||||||
|
}
|
66
examples/alffmpeg.h
Normal file
66
examples/alffmpeg.h
Normal file
@ -0,0 +1,66 @@
|
|||||||
|
#ifndef ALFFMPEG_H
|
||||||
|
#define ALFFMPEG_H
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif /* __cplusplus */
|
||||||
|
|
||||||
|
#include <libavcodec/avcodec.h>
|
||||||
|
#include <libavformat/avformat.h>
|
||||||
|
|
||||||
|
/* Opaque handles to files and streams. Apps don't need to concern themselves
|
||||||
|
* with the internals */
|
||||||
|
typedef struct MyFile *FilePtr;
|
||||||
|
typedef struct MyStream *StreamPtr;
|
||||||
|
|
||||||
|
/* Opens a file with ffmpeg and sets up the streams' information */
|
||||||
|
FilePtr openAVFile(const char *fname);
|
||||||
|
|
||||||
|
/* Opens a named file image with ffmpeg and sets up the streams' information */
|
||||||
|
FilePtr openAVData(const char *name, char *buffer, size_t buffer_len);
|
||||||
|
|
||||||
|
/* Opens a named data stream with ffmpeg, using the specified data pointer and
|
||||||
|
* callbacks, and sets up the streams' information */
|
||||||
|
FilePtr openAVCustom(const char *name, void *user_data,
|
||||||
|
int (*read_packet)(void *user_data, uint8_t *buf, int buf_size),
|
||||||
|
int (*write_packet)(void *user_data, uint8_t *buf, int buf_size),
|
||||||
|
int64_t (*seek)(void *user_data, int64_t offset, int whence));
|
||||||
|
|
||||||
|
/* Closes/frees an opened file and any of its streams */
|
||||||
|
void closeAVFile(FilePtr file);
|
||||||
|
|
||||||
|
/* Reports certain information from the file, eg, the number of audio
|
||||||
|
* streams. Returns 0 on success. */
|
||||||
|
int getAVFileInfo(FilePtr file, int *numaudiostreams);
|
||||||
|
|
||||||
|
/* Retrieves a handle for the given audio stream number (generally 0, but some
|
||||||
|
* files can have multiple audio streams in one file). */
|
||||||
|
StreamPtr getAVAudioStream(FilePtr file, int streamnum);
|
||||||
|
|
||||||
|
/* Returns information about the given audio stream. Returns 0 on success. */
|
||||||
|
int getAVAudioInfo(StreamPtr stream, ALuint *rate, ALenum *channels, ALenum *type);
|
||||||
|
|
||||||
|
/* Returns a pointer to the next available packet of decoded audio. Any data
|
||||||
|
* from a previously-decoded packet is dropped. The size (in bytes) of the
|
||||||
|
* returned data buffer is stored in 'length', and the returned pointer is only
|
||||||
|
* valid until the next call to getAVAudioData or readAVAudioData. */
|
||||||
|
void *getAVAudioData(StreamPtr stream, size_t *length);
|
||||||
|
|
||||||
|
/* The "meat" function. Decodes audio and writes, at most, length bytes into
|
||||||
|
* the provided data buffer. Will only return less for end-of-stream or error
|
||||||
|
* conditions. Returns the number of bytes written. */
|
||||||
|
size_t readAVAudioData(StreamPtr stream, void *data, size_t length);
|
||||||
|
|
||||||
|
/* Decodes all remaining data from the stream and returns a buffer containing
|
||||||
|
* the audio data, with the size stored in 'length'. The returned pointer must
|
||||||
|
* be freed with a call to free(). Note that since this decodes the whole
|
||||||
|
* stream, using it on lengthy streams (eg, music) will use a lot of memory.
|
||||||
|
* Such streams are better handled using getAVAudioData or readAVAudioData to
|
||||||
|
* keep smaller chunks in memory at any given time. */
|
||||||
|
void *decodeAVAudioStream(StreamPtr stream, size_t *length);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif /* __cplusplus */
|
||||||
|
|
||||||
|
#endif /* ALFFMPEG_H */
|
319
examples/alhelpers.c
Normal file
319
examples/alhelpers.c
Normal file
@ -0,0 +1,319 @@
|
|||||||
|
/*
|
||||||
|
* OpenAL Helpers
|
||||||
|
*
|
||||||
|
* Copyright (c) 2011 by Chris Robinson <chris.kcat@gmail.com>
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* This file contains routines to help with some menial OpenAL-related tasks,
|
||||||
|
* such as opening a device and setting up a context, closing the device and
|
||||||
|
* destroying its context, converting between frame counts and byte lengths,
|
||||||
|
* finding an appropriate buffer format, and getting readable strings for
|
||||||
|
* channel configs and sample types. */
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#include "AL/al.h"
|
||||||
|
#include "AL/alc.h"
|
||||||
|
#include "AL/alext.h"
|
||||||
|
|
||||||
|
#include "alhelpers.h"
|
||||||
|
|
||||||
|
|
||||||
|
const char *ChannelsName(ALenum chans)
|
||||||
|
{
|
||||||
|
switch(chans)
|
||||||
|
{
|
||||||
|
case AL_MONO_SOFT: return "Mono";
|
||||||
|
case AL_STEREO_SOFT: return "Stereo";
|
||||||
|
case AL_REAR_SOFT: return "Rear";
|
||||||
|
case AL_QUAD_SOFT: return "Quadraphonic";
|
||||||
|
case AL_5POINT1_SOFT: return "5.1 Surround";
|
||||||
|
case AL_6POINT1_SOFT: return "6.1 Surround";
|
||||||
|
case AL_7POINT1_SOFT: return "7.1 Surround";
|
||||||
|
}
|
||||||
|
return "Unknown Channels";
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *TypeName(ALenum type)
|
||||||
|
{
|
||||||
|
switch(type)
|
||||||
|
{
|
||||||
|
case AL_BYTE_SOFT: return "S8";
|
||||||
|
case AL_UNSIGNED_BYTE_SOFT: return "U8";
|
||||||
|
case AL_SHORT_SOFT: return "S16";
|
||||||
|
case AL_UNSIGNED_SHORT_SOFT: return "U16";
|
||||||
|
case AL_INT_SOFT: return "S32";
|
||||||
|
case AL_UNSIGNED_INT_SOFT: return "U32";
|
||||||
|
case AL_FLOAT_SOFT: return "Float32";
|
||||||
|
case AL_DOUBLE_SOFT: return "Float64";
|
||||||
|
}
|
||||||
|
return "Unknown Type";
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
ALsizei FramesToBytes(ALsizei size, ALenum channels, ALenum type)
|
||||||
|
{
|
||||||
|
switch(channels)
|
||||||
|
{
|
||||||
|
case AL_MONO_SOFT: size *= 1; break;
|
||||||
|
case AL_STEREO_SOFT: size *= 2; break;
|
||||||
|
case AL_REAR_SOFT: size *= 2; break;
|
||||||
|
case AL_QUAD_SOFT: size *= 4; break;
|
||||||
|
case AL_5POINT1_SOFT: size *= 6; break;
|
||||||
|
case AL_6POINT1_SOFT: size *= 7; break;
|
||||||
|
case AL_7POINT1_SOFT: size *= 8; break;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch(type)
|
||||||
|
{
|
||||||
|
case AL_BYTE_SOFT: size *= sizeof(ALbyte); break;
|
||||||
|
case AL_UNSIGNED_BYTE_SOFT: size *= sizeof(ALubyte); break;
|
||||||
|
case AL_SHORT_SOFT: size *= sizeof(ALshort); break;
|
||||||
|
case AL_UNSIGNED_SHORT_SOFT: size *= sizeof(ALushort); break;
|
||||||
|
case AL_INT_SOFT: size *= sizeof(ALint); break;
|
||||||
|
case AL_UNSIGNED_INT_SOFT: size *= sizeof(ALuint); break;
|
||||||
|
case AL_FLOAT_SOFT: size *= sizeof(ALfloat); break;
|
||||||
|
case AL_DOUBLE_SOFT: size *= sizeof(ALdouble); break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return size;
|
||||||
|
}
|
||||||
|
|
||||||
|
ALsizei BytesToFrames(ALsizei size, ALenum channels, ALenum type)
|
||||||
|
{
|
||||||
|
return size / FramesToBytes(1, channels, type);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
ALenum GetFormat(ALenum channels, ALenum type, LPALISBUFFERFORMATSUPPORTEDSOFT palIsBufferFormatSupportedSOFT)
|
||||||
|
{
|
||||||
|
ALenum format = AL_NONE;
|
||||||
|
|
||||||
|
/* If using AL_SOFT_buffer_samples, try looking through its formats */
|
||||||
|
if(palIsBufferFormatSupportedSOFT)
|
||||||
|
{
|
||||||
|
/* AL_SOFT_buffer_samples is more lenient with matching formats. The
|
||||||
|
* specified sample type does not need to match the returned format,
|
||||||
|
* but it is nice to try to get something close. */
|
||||||
|
if(type == AL_UNSIGNED_BYTE_SOFT || type == AL_BYTE_SOFT)
|
||||||
|
{
|
||||||
|
if(channels == AL_MONO_SOFT) format = AL_MONO8_SOFT;
|
||||||
|
else if(channels == AL_STEREO_SOFT) format = AL_STEREO8_SOFT;
|
||||||
|
else if(channels == AL_QUAD_SOFT) format = AL_QUAD8_SOFT;
|
||||||
|
else if(channels == AL_5POINT1_SOFT) format = AL_5POINT1_8_SOFT;
|
||||||
|
else if(channels == AL_6POINT1_SOFT) format = AL_6POINT1_8_SOFT;
|
||||||
|
else if(channels == AL_7POINT1_SOFT) format = AL_7POINT1_8_SOFT;
|
||||||
|
}
|
||||||
|
else if(type == AL_UNSIGNED_SHORT_SOFT || type == AL_SHORT_SOFT)
|
||||||
|
{
|
||||||
|
if(channels == AL_MONO_SOFT) format = AL_MONO16_SOFT;
|
||||||
|
else if(channels == AL_STEREO_SOFT) format = AL_STEREO16_SOFT;
|
||||||
|
else if(channels == AL_QUAD_SOFT) format = AL_QUAD16_SOFT;
|
||||||
|
else if(channels == AL_5POINT1_SOFT) format = AL_5POINT1_16_SOFT;
|
||||||
|
else if(channels == AL_6POINT1_SOFT) format = AL_6POINT1_16_SOFT;
|
||||||
|
else if(channels == AL_7POINT1_SOFT) format = AL_7POINT1_16_SOFT;
|
||||||
|
}
|
||||||
|
else if(type == AL_UNSIGNED_BYTE3_SOFT || type == AL_BYTE3_SOFT ||
|
||||||
|
type == AL_UNSIGNED_INT_SOFT || type == AL_INT_SOFT ||
|
||||||
|
type == AL_FLOAT_SOFT || type == AL_DOUBLE_SOFT)
|
||||||
|
{
|
||||||
|
if(channels == AL_MONO_SOFT) format = AL_MONO32F_SOFT;
|
||||||
|
else if(channels == AL_STEREO_SOFT) format = AL_STEREO32F_SOFT;
|
||||||
|
else if(channels == AL_QUAD_SOFT) format = AL_QUAD32F_SOFT;
|
||||||
|
else if(channels == AL_5POINT1_SOFT) format = AL_5POINT1_32F_SOFT;
|
||||||
|
else if(channels == AL_6POINT1_SOFT) format = AL_6POINT1_32F_SOFT;
|
||||||
|
else if(channels == AL_7POINT1_SOFT) format = AL_7POINT1_32F_SOFT;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(format != AL_NONE && !palIsBufferFormatSupportedSOFT(format))
|
||||||
|
format = AL_NONE;
|
||||||
|
|
||||||
|
/* A matching format was not found or supported. Try 32-bit float. */
|
||||||
|
if(format == AL_NONE)
|
||||||
|
{
|
||||||
|
if(channels == AL_MONO_SOFT) format = AL_MONO32F_SOFT;
|
||||||
|
else if(channels == AL_STEREO_SOFT) format = AL_STEREO32F_SOFT;
|
||||||
|
else if(channels == AL_QUAD_SOFT) format = AL_QUAD32F_SOFT;
|
||||||
|
else if(channels == AL_5POINT1_SOFT) format = AL_5POINT1_32F_SOFT;
|
||||||
|
else if(channels == AL_6POINT1_SOFT) format = AL_6POINT1_32F_SOFT;
|
||||||
|
else if(channels == AL_7POINT1_SOFT) format = AL_7POINT1_32F_SOFT;
|
||||||
|
|
||||||
|
if(format != AL_NONE && !palIsBufferFormatSupportedSOFT(format))
|
||||||
|
format = AL_NONE;
|
||||||
|
}
|
||||||
|
/* 32-bit float not supported. Try 16-bit int. */
|
||||||
|
if(format == AL_NONE)
|
||||||
|
{
|
||||||
|
if(channels == AL_MONO_SOFT) format = AL_MONO16_SOFT;
|
||||||
|
else if(channels == AL_STEREO_SOFT) format = AL_STEREO16_SOFT;
|
||||||
|
else if(channels == AL_QUAD_SOFT) format = AL_QUAD16_SOFT;
|
||||||
|
else if(channels == AL_5POINT1_SOFT) format = AL_5POINT1_16_SOFT;
|
||||||
|
else if(channels == AL_6POINT1_SOFT) format = AL_6POINT1_16_SOFT;
|
||||||
|
else if(channels == AL_7POINT1_SOFT) format = AL_7POINT1_16_SOFT;
|
||||||
|
|
||||||
|
if(format != AL_NONE && !palIsBufferFormatSupportedSOFT(format))
|
||||||
|
format = AL_NONE;
|
||||||
|
}
|
||||||
|
/* 16-bit int not supported. Try 8-bit int. */
|
||||||
|
if(format == AL_NONE)
|
||||||
|
{
|
||||||
|
if(channels == AL_MONO_SOFT) format = AL_MONO8_SOFT;
|
||||||
|
else if(channels == AL_STEREO_SOFT) format = AL_STEREO8_SOFT;
|
||||||
|
else if(channels == AL_QUAD_SOFT) format = AL_QUAD8_SOFT;
|
||||||
|
else if(channels == AL_5POINT1_SOFT) format = AL_5POINT1_8_SOFT;
|
||||||
|
else if(channels == AL_6POINT1_SOFT) format = AL_6POINT1_8_SOFT;
|
||||||
|
else if(channels == AL_7POINT1_SOFT) format = AL_7POINT1_8_SOFT;
|
||||||
|
|
||||||
|
if(format != AL_NONE && !palIsBufferFormatSupportedSOFT(format))
|
||||||
|
format = AL_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return format;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* We use the AL_EXT_MCFORMATS extension to provide output of Quad, 5.1,
|
||||||
|
* and 7.1 channel configs, AL_EXT_FLOAT32 for 32-bit float samples, and
|
||||||
|
* AL_EXT_DOUBLE for 64-bit float samples. */
|
||||||
|
if(type == AL_UNSIGNED_BYTE_SOFT)
|
||||||
|
{
|
||||||
|
if(channels == AL_MONO_SOFT)
|
||||||
|
format = AL_FORMAT_MONO8;
|
||||||
|
else if(channels == AL_STEREO_SOFT)
|
||||||
|
format = AL_FORMAT_STEREO8;
|
||||||
|
else if(alIsExtensionPresent("AL_EXT_MCFORMATS"))
|
||||||
|
{
|
||||||
|
if(channels == AL_QUAD_SOFT)
|
||||||
|
format = alGetEnumValue("AL_FORMAT_QUAD8");
|
||||||
|
else if(channels == AL_5POINT1_SOFT)
|
||||||
|
format = alGetEnumValue("AL_FORMAT_51CHN8");
|
||||||
|
else if(channels == AL_6POINT1_SOFT)
|
||||||
|
format = alGetEnumValue("AL_FORMAT_61CHN8");
|
||||||
|
else if(channels == AL_7POINT1_SOFT)
|
||||||
|
format = alGetEnumValue("AL_FORMAT_71CHN8");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if(type == AL_SHORT_SOFT)
|
||||||
|
{
|
||||||
|
if(channels == AL_MONO_SOFT)
|
||||||
|
format = AL_FORMAT_MONO16;
|
||||||
|
else if(channels == AL_STEREO_SOFT)
|
||||||
|
format = AL_FORMAT_STEREO16;
|
||||||
|
else if(alIsExtensionPresent("AL_EXT_MCFORMATS"))
|
||||||
|
{
|
||||||
|
if(channels == AL_QUAD_SOFT)
|
||||||
|
format = alGetEnumValue("AL_FORMAT_QUAD16");
|
||||||
|
else if(channels == AL_5POINT1_SOFT)
|
||||||
|
format = alGetEnumValue("AL_FORMAT_51CHN16");
|
||||||
|
else if(channels == AL_6POINT1_SOFT)
|
||||||
|
format = alGetEnumValue("AL_FORMAT_61CHN16");
|
||||||
|
else if(channels == AL_7POINT1_SOFT)
|
||||||
|
format = alGetEnumValue("AL_FORMAT_71CHN16");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if(type == AL_FLOAT_SOFT && alIsExtensionPresent("AL_EXT_FLOAT32"))
|
||||||
|
{
|
||||||
|
if(channels == AL_MONO_SOFT)
|
||||||
|
format = alGetEnumValue("AL_FORMAT_MONO_FLOAT32");
|
||||||
|
else if(channels == AL_STEREO_SOFT)
|
||||||
|
format = alGetEnumValue("AL_FORMAT_STEREO_FLOAT32");
|
||||||
|
else if(alIsExtensionPresent("AL_EXT_MCFORMATS"))
|
||||||
|
{
|
||||||
|
if(channels == AL_QUAD_SOFT)
|
||||||
|
format = alGetEnumValue("AL_FORMAT_QUAD32");
|
||||||
|
else if(channels == AL_5POINT1_SOFT)
|
||||||
|
format = alGetEnumValue("AL_FORMAT_51CHN32");
|
||||||
|
else if(channels == AL_6POINT1_SOFT)
|
||||||
|
format = alGetEnumValue("AL_FORMAT_61CHN32");
|
||||||
|
else if(channels == AL_7POINT1_SOFT)
|
||||||
|
format = alGetEnumValue("AL_FORMAT_71CHN32");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if(type == AL_DOUBLE_SOFT && alIsExtensionPresent("AL_EXT_DOUBLE"))
|
||||||
|
{
|
||||||
|
if(channels == AL_MONO_SOFT)
|
||||||
|
format = alGetEnumValue("AL_FORMAT_MONO_DOUBLE");
|
||||||
|
else if(channels == AL_STEREO_SOFT)
|
||||||
|
format = alGetEnumValue("AL_FORMAT_STEREO_DOUBLE");
|
||||||
|
}
|
||||||
|
|
||||||
|
/* NOTE: It seems OSX returns -1 from alGetEnumValue for unknown enums, as
|
||||||
|
* opposed to 0. Correct it. */
|
||||||
|
if(format == -1)
|
||||||
|
format = 0;
|
||||||
|
|
||||||
|
return format;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void AL_APIENTRY wrap_BufferSamples(ALuint buffer, ALuint samplerate,
|
||||||
|
ALenum internalformat, ALsizei samples,
|
||||||
|
ALenum channels, ALenum type,
|
||||||
|
const ALvoid *data)
|
||||||
|
{
|
||||||
|
alBufferData(buffer, internalformat, data,
|
||||||
|
FramesToBytes(samples, channels, type),
|
||||||
|
samplerate);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int InitAL(void)
|
||||||
|
{
|
||||||
|
ALCdevice *device;
|
||||||
|
ALCcontext *ctx;
|
||||||
|
|
||||||
|
/* Open and initialize a device with default settings */
|
||||||
|
device = alcOpenDevice(NULL);
|
||||||
|
if(!device)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "Could not open a device!\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx = alcCreateContext(device, NULL);
|
||||||
|
if(ctx == NULL || alcMakeContextCurrent(ctx) == ALC_FALSE)
|
||||||
|
{
|
||||||
|
if(ctx != NULL)
|
||||||
|
alcDestroyContext(ctx);
|
||||||
|
alcCloseDevice(device);
|
||||||
|
fprintf(stderr, "Could not set a context!\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CloseAL(void)
|
||||||
|
{
|
||||||
|
ALCdevice *device;
|
||||||
|
ALCcontext *ctx;
|
||||||
|
|
||||||
|
/* Close the device belonging to the current context, and destroy the
|
||||||
|
* context. */
|
||||||
|
ctx = alcGetCurrentContext();
|
||||||
|
if(ctx == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
device = alcGetContextsDevice(ctx);
|
||||||
|
|
||||||
|
alcMakeContextCurrent(NULL);
|
||||||
|
alcDestroyContext(ctx);
|
||||||
|
alcCloseDevice(device);
|
||||||
|
}
|
47
examples/alhelpers.h
Normal file
47
examples/alhelpers.h
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
#ifndef ALHELPERS_H
|
||||||
|
#define ALHELPERS_H
|
||||||
|
|
||||||
|
#ifndef _WIN32
|
||||||
|
#include <unistd.h>
|
||||||
|
#define Sleep(x) usleep((x)*1000)
|
||||||
|
#else
|
||||||
|
#define WIN32_LEAN_AND_MEAN
|
||||||
|
#include <windows.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif /* __cplusplus */
|
||||||
|
|
||||||
|
/* Some helper functions to get the name from the channel and type enums. */
|
||||||
|
const char *ChannelsName(ALenum chans);
|
||||||
|
const char *TypeName(ALenum type);
|
||||||
|
|
||||||
|
/* Helpers to convert frame counts and byte lengths. */
|
||||||
|
ALsizei FramesToBytes(ALsizei size, ALenum channels, ALenum type);
|
||||||
|
ALsizei BytesToFrames(ALsizei size, ALenum channels, ALenum type);
|
||||||
|
|
||||||
|
/* Retrieves a compatible buffer format given the channel configuration and
|
||||||
|
* sample type. If an alIsBufferFormatSupportedSOFT-compatible function is
|
||||||
|
* provided, it will be called to find the closest-matching format from
|
||||||
|
* AL_SOFT_buffer_samples. Returns AL_NONE (0) if no supported format can be
|
||||||
|
* found. */
|
||||||
|
ALenum GetFormat(ALenum channels, ALenum type, LPALISBUFFERFORMATSUPPORTEDSOFT palIsBufferFormatSupportedSOFT);
|
||||||
|
|
||||||
|
/* Loads samples into a buffer using the standard alBufferData call, but with a
|
||||||
|
* LPALBUFFERSAMPLESSOFT-compatible prototype. Assumes internalformat is valid
|
||||||
|
* for alBufferData, and that channels and type match it. */
|
||||||
|
void AL_APIENTRY wrap_BufferSamples(ALuint buffer, ALuint samplerate,
|
||||||
|
ALenum internalformat, ALsizei samples,
|
||||||
|
ALenum channels, ALenum type,
|
||||||
|
const ALvoid *data);
|
||||||
|
|
||||||
|
/* Easy device init/deinit functions. InitAL returns 0 on success. */
|
||||||
|
int InitAL(void);
|
||||||
|
void CloseAL(void);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif /* __cplusplus */
|
||||||
|
|
||||||
|
#endif /* ALHELPERS_H */
|
346
examples/alstream.c
Normal file
346
examples/alstream.c
Normal file
@ -0,0 +1,346 @@
|
|||||||
|
/*
|
||||||
|
* OpenAL Audio Stream Example
|
||||||
|
*
|
||||||
|
* Copyright (c) 2011 by Chris Robinson <chris.kcat@gmail.com>
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* This file contains a relatively simple streaming audio player. */
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <signal.h>
|
||||||
|
#include <assert.h>
|
||||||
|
|
||||||
|
#include "AL/al.h"
|
||||||
|
#include "AL/alc.h"
|
||||||
|
#include "AL/alext.h"
|
||||||
|
|
||||||
|
#include "alhelpers.h"
|
||||||
|
#include "alffmpeg.h"
|
||||||
|
|
||||||
|
|
||||||
|
LPALBUFFERSAMPLESSOFT palBufferSamplesSOFT = wrap_BufferSamples;
|
||||||
|
LPALISBUFFERFORMATSUPPORTEDSOFT palIsBufferFormatSupportedSOFT = NULL;
|
||||||
|
|
||||||
|
|
||||||
|
/* Define the number of buffers and buffer size (in samples) to use. 4 buffers
|
||||||
|
* with 8192 samples each gives a nice per-chunk size, and lets the queue last
|
||||||
|
* for almost 3/4ths of a second for a 44.1khz stream. */
|
||||||
|
#define NUM_BUFFERS 4
|
||||||
|
#define BUFFER_SIZE 8192
|
||||||
|
|
||||||
|
typedef struct StreamPlayer {
|
||||||
|
/* These are the buffers and source to play out through OpenAL with */
|
||||||
|
ALuint buffers[NUM_BUFFERS];
|
||||||
|
ALuint source;
|
||||||
|
|
||||||
|
/* Handles for the audio stream */
|
||||||
|
FilePtr file;
|
||||||
|
StreamPtr stream;
|
||||||
|
|
||||||
|
/* A temporary data buffer for readAVAudioData to write to and pass to
|
||||||
|
* OpenAL with */
|
||||||
|
ALbyte *data;
|
||||||
|
ALsizei datasize;
|
||||||
|
|
||||||
|
/* The format of the output stream */
|
||||||
|
ALenum format;
|
||||||
|
ALenum channels;
|
||||||
|
ALenum type;
|
||||||
|
ALuint rate;
|
||||||
|
} StreamPlayer;
|
||||||
|
|
||||||
|
static StreamPlayer *NewPlayer(void);
|
||||||
|
static void DeletePlayer(StreamPlayer *player);
|
||||||
|
static int OpenPlayerFile(StreamPlayer *player, const char *filename);
|
||||||
|
static void ClosePlayerFile(StreamPlayer *player);
|
||||||
|
static int StartPlayer(StreamPlayer *player);
|
||||||
|
static int UpdatePlayer(StreamPlayer *player);
|
||||||
|
|
||||||
|
/* Creates a new player object, and allocates the needed OpenAL source and
|
||||||
|
* buffer objects. Error checking is simplified for the purposes of this
|
||||||
|
* example, and will cause an abort if needed. */
|
||||||
|
static StreamPlayer *NewPlayer(void)
|
||||||
|
{
|
||||||
|
StreamPlayer *player;
|
||||||
|
|
||||||
|
player = malloc(sizeof(*player));
|
||||||
|
assert(player != NULL);
|
||||||
|
|
||||||
|
memset(player, 0, sizeof(*player));
|
||||||
|
|
||||||
|
/* Generate the buffers and source */
|
||||||
|
alGenBuffers(NUM_BUFFERS, player->buffers);
|
||||||
|
assert(alGetError() == AL_NO_ERROR && "Could not create buffers");
|
||||||
|
|
||||||
|
alGenSources(1, &player->source);
|
||||||
|
assert(alGetError() == AL_NO_ERROR && "Could not create source");
|
||||||
|
|
||||||
|
/* Set parameters so mono sources play out the front-center speaker and
|
||||||
|
* won't distance attenuate. */
|
||||||
|
alSource3i(player->source, AL_POSITION, 0, 0, -1);
|
||||||
|
alSourcei(player->source, AL_SOURCE_RELATIVE, AL_TRUE);
|
||||||
|
alSourcei(player->source, AL_ROLLOFF_FACTOR, 0);
|
||||||
|
assert(alGetError() == AL_NO_ERROR && "Could not set source parameters");
|
||||||
|
|
||||||
|
return player;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Destroys a player object, deleting the source and buffers. No error handling
|
||||||
|
* since these calls shouldn't fail with a properly-made player object. */
|
||||||
|
static void DeletePlayer(StreamPlayer *player)
|
||||||
|
{
|
||||||
|
ClosePlayerFile(player);
|
||||||
|
|
||||||
|
alDeleteSources(1, &player->source);
|
||||||
|
alDeleteBuffers(NUM_BUFFERS, player->buffers);
|
||||||
|
if(alGetError() != AL_NO_ERROR)
|
||||||
|
fprintf(stderr, "Failed to delete object IDs\n");
|
||||||
|
|
||||||
|
memset(player, 0, sizeof(*player));
|
||||||
|
free(player);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Opens the first audio stream of the named file. If a file is already open,
|
||||||
|
* it will be closed first. */
|
||||||
|
static int OpenPlayerFile(StreamPlayer *player, const char *filename)
|
||||||
|
{
|
||||||
|
ClosePlayerFile(player);
|
||||||
|
|
||||||
|
/* Open the file and get the first stream from it */
|
||||||
|
player->file = openAVFile(filename);
|
||||||
|
player->stream = getAVAudioStream(player->file, 0);
|
||||||
|
if(!player->stream)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "Could not open audio in %s\n", filename);
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Get the stream format, and figure out the OpenAL format */
|
||||||
|
if(getAVAudioInfo(player->stream, &player->rate, &player->channels,
|
||||||
|
&player->type) != 0)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "Error getting audio info for %s\n", filename);
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
player->format = GetFormat(player->channels, player->type, palIsBufferFormatSupportedSOFT);
|
||||||
|
if(player->format == 0)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "Unsupported format (%s, %s) for %s\n",
|
||||||
|
ChannelsName(player->channels), TypeName(player->type),
|
||||||
|
filename);
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Allocate enough space for the temp buffer, given the format */
|
||||||
|
player->datasize = FramesToBytes(BUFFER_SIZE, player->channels,
|
||||||
|
player->type);
|
||||||
|
player->data = malloc(player->datasize);
|
||||||
|
if(player->data == NULL)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "Error allocating %d bytes\n", player->datasize);
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
error:
|
||||||
|
closeAVFile(player->file);
|
||||||
|
player->file = NULL;
|
||||||
|
player->stream = NULL;
|
||||||
|
player->datasize = 0;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Closes the audio file stream */
|
||||||
|
static void ClosePlayerFile(StreamPlayer *player)
|
||||||
|
{
|
||||||
|
closeAVFile(player->file);
|
||||||
|
player->file = NULL;
|
||||||
|
player->stream = NULL;
|
||||||
|
|
||||||
|
free(player->data);
|
||||||
|
player->data = NULL;
|
||||||
|
player->datasize = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Prebuffers some audio from the file, and starts playing the source */
|
||||||
|
static int StartPlayer(StreamPlayer *player)
|
||||||
|
{
|
||||||
|
size_t i, got;
|
||||||
|
|
||||||
|
/* Rewind the source position and clear the buffer queue */
|
||||||
|
alSourceRewind(player->source);
|
||||||
|
alSourcei(player->source, AL_BUFFER, 0);
|
||||||
|
|
||||||
|
/* Fill the buffer queue */
|
||||||
|
for(i = 0;i < NUM_BUFFERS;i++)
|
||||||
|
{
|
||||||
|
/* Get some data to give it to the buffer */
|
||||||
|
got = readAVAudioData(player->stream, player->data, player->datasize);
|
||||||
|
if(got == 0) break;
|
||||||
|
|
||||||
|
palBufferSamplesSOFT(player->buffers[i], player->rate, player->format,
|
||||||
|
BytesToFrames(got, player->channels, player->type),
|
||||||
|
player->channels, player->type, player->data);
|
||||||
|
}
|
||||||
|
if(alGetError() != AL_NO_ERROR)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "Error buffering for playback\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Now queue and start playback! */
|
||||||
|
alSourceQueueBuffers(player->source, i, player->buffers);
|
||||||
|
alSourcePlay(player->source);
|
||||||
|
if(alGetError() != AL_NO_ERROR)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "Error starting playback\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int UpdatePlayer(StreamPlayer *player)
|
||||||
|
{
|
||||||
|
ALint processed, state;
|
||||||
|
|
||||||
|
/* Get relevant source info */
|
||||||
|
alGetSourcei(player->source, AL_SOURCE_STATE, &state);
|
||||||
|
alGetSourcei(player->source, AL_BUFFERS_PROCESSED, &processed);
|
||||||
|
if(alGetError() != AL_NO_ERROR)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "Error checking source state\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Unqueue and handle each processed buffer */
|
||||||
|
while(processed > 0)
|
||||||
|
{
|
||||||
|
ALuint bufid;
|
||||||
|
size_t got;
|
||||||
|
|
||||||
|
alSourceUnqueueBuffers(player->source, 1, &bufid);
|
||||||
|
processed--;
|
||||||
|
|
||||||
|
/* Read the next chunk of data, refill the buffer, and queue it
|
||||||
|
* back on the source */
|
||||||
|
got = readAVAudioData(player->stream, player->data, player->datasize);
|
||||||
|
if(got > 0)
|
||||||
|
{
|
||||||
|
palBufferSamplesSOFT(bufid, player->rate, player->format,
|
||||||
|
BytesToFrames(got, player->channels, player->type),
|
||||||
|
player->channels, player->type, player->data);
|
||||||
|
alSourceQueueBuffers(player->source, 1, &bufid);
|
||||||
|
}
|
||||||
|
if(alGetError() != AL_NO_ERROR)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "Error buffering data\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Make sure the source hasn't underrun */
|
||||||
|
if(state != AL_PLAYING && state != AL_PAUSED)
|
||||||
|
{
|
||||||
|
ALint queued;
|
||||||
|
|
||||||
|
/* If no buffers are queued, playback is finished */
|
||||||
|
alGetSourcei(player->source, AL_BUFFERS_QUEUED, &queued);
|
||||||
|
if(queued == 0)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
alSourcePlay(player->source);
|
||||||
|
if(alGetError() != AL_NO_ERROR)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "Error restarting playback\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int main(int argc, char **argv)
|
||||||
|
{
|
||||||
|
StreamPlayer *player;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
/* Print out usage if no file was specified */
|
||||||
|
if(argc < 2)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "Usage: %s <filenames...>\n", argv[0]);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(InitAL() != 0)
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
if(alIsExtensionPresent("AL_SOFT_buffer_samples"))
|
||||||
|
{
|
||||||
|
printf("AL_SOFT_buffer_samples supported!\n");
|
||||||
|
palBufferSamplesSOFT = alGetProcAddress("alBufferSamplesSOFT");
|
||||||
|
palIsBufferFormatSupportedSOFT = alGetProcAddress("alIsBufferFormatSupportedSOFT");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
printf("AL_SOFT_buffer_samples not supported\n");
|
||||||
|
|
||||||
|
player = NewPlayer();
|
||||||
|
|
||||||
|
/* Play each file listed on the command line */
|
||||||
|
for(i = 1;i < argc;i++)
|
||||||
|
{
|
||||||
|
if(!OpenPlayerFile(player, argv[i]))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
fprintf(stderr, "Playing %s (%s, %s, %dhz)\n", argv[i],
|
||||||
|
TypeName(player->type), ChannelsName(player->channels),
|
||||||
|
player->rate);
|
||||||
|
|
||||||
|
if(!StartPlayer(player))
|
||||||
|
{
|
||||||
|
ClosePlayerFile(player);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
while(UpdatePlayer(player))
|
||||||
|
Sleep(10);
|
||||||
|
|
||||||
|
/* All done with this file. Close it and go to the next */
|
||||||
|
ClosePlayerFile(player);
|
||||||
|
}
|
||||||
|
fprintf(stderr, "Done.\n");
|
||||||
|
|
||||||
|
/* All files done. Delete the player, and close OpenAL */
|
||||||
|
DeletePlayer(player);
|
||||||
|
player = NULL;
|
||||||
|
|
||||||
|
CloseAL();
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
93
hrtf.txt
Normal file
93
hrtf.txt
Normal file
@ -0,0 +1,93 @@
|
|||||||
|
HRTF Support
|
||||||
|
============
|
||||||
|
|
||||||
|
Starting with OpenAL Soft 1.14, HRTFs can be used to enable enhanced
|
||||||
|
spatialization for both 3D (mono) and multi-channel sources, when used with
|
||||||
|
headphones/stereo output. This can be enabled using the 'hrtf' config option.
|
||||||
|
|
||||||
|
For multi-channel sources this creates a virtual speaker effect, making it
|
||||||
|
sound as if speakers provide a discrete position for each channel around the
|
||||||
|
listener. For mono sources this provides much more versatility in the perceived
|
||||||
|
placement of sounds, making it seem as though they are coming from all around,
|
||||||
|
including above and below the listener, instead of just to the front, back, and
|
||||||
|
sides.
|
||||||
|
|
||||||
|
The built-in data set is based on the KEMAR HRTF diffuse data provided by MIT,
|
||||||
|
which can be found at <http://sound.media.mit.edu/resources/KEMAR.html>. It's
|
||||||
|
only available when using 44100hz playback.
|
||||||
|
|
||||||
|
|
||||||
|
External HRTF Data Sets
|
||||||
|
=======================
|
||||||
|
|
||||||
|
OpenAL Soft also provides an option to use user-specified data sets, in
|
||||||
|
addition to or in place of the built-in set. This allows users to provide their
|
||||||
|
own data sets, which could be better suited for their heads, or to work with
|
||||||
|
stereo speakers instead of headphones, or to support more playback sample
|
||||||
|
rates, for example.
|
||||||
|
|
||||||
|
The file format for the data sets is specified below. It uses little-endian
|
||||||
|
byte order. Certain data fields are restricted to specific values (these
|
||||||
|
restriction may be lifted in future versions of the lib).
|
||||||
|
|
||||||
|
==
|
||||||
|
ALchar magic[8] = "MinPHR00";
|
||||||
|
ALuint sampleRate;
|
||||||
|
|
||||||
|
ALushort hrirCount; /* Required value: 828 */
|
||||||
|
ALushort hrirSize; /* Required value: 32 */
|
||||||
|
ALubyte evCount; /* Required value: 19 */
|
||||||
|
|
||||||
|
ALushort evOffset[evCount]; /* Required values:
|
||||||
|
{ 0, 1, 13, 37, 73, 118, 174, 234, 306, 378, 450, 522, 594, 654, 710, 755,
|
||||||
|
791, 815, 827 } */
|
||||||
|
|
||||||
|
ALshort coefficients[hrirCount][hrirSize];
|
||||||
|
ALubyte delays[hrirCount]; /* Element values must not exceed 127 */
|
||||||
|
==
|
||||||
|
|
||||||
|
The data is described as thus:
|
||||||
|
|
||||||
|
The file first starts with the 8-byte marker, "MinPHR00", to identify it as an
|
||||||
|
HRTF data set. This is followed by an unsigned 32-bit integer, specifying the
|
||||||
|
sample rate the data set is designed for (OpenAL Soft will not use it if the
|
||||||
|
output device's playback rate doesn't match).
|
||||||
|
|
||||||
|
Afterward, an unsigned 16-bit integer specifies the total number of HRIR sets
|
||||||
|
(each HRIR set is a collection of impulse responses forming the coefficients
|
||||||
|
for a convolution filter). The next unsigned 16-bit integer specifies how many
|
||||||
|
samples are in each HRIR set (the number of coefficients in the filter). The
|
||||||
|
following unsigned 8-bit integer specifies the number of elevations used by the
|
||||||
|
data set. The elevations start at the bottom, and increment upwards.
|
||||||
|
|
||||||
|
Following this is an array of unsigned 16-bit integers, one for each elevation
|
||||||
|
which specifies the index offset to the start of the HRIR sets for each given
|
||||||
|
elevation (the number of HRIR sets at each elevation is infered by the offset
|
||||||
|
to the next elevation, or by the total count for the last elevation).
|
||||||
|
|
||||||
|
The actual coefficients follow. Each coefficient is a signed 16-bit sample,
|
||||||
|
with each HRIR set being a consecutive number of samples. For each elevation,
|
||||||
|
the HRIR sets first start with a neutral "in-front" set (that is, one that is
|
||||||
|
applied equally to the left and right outputs). After this, the sets follow a
|
||||||
|
clockwise pattern, constructing a full circle for the left ear only. The right
|
||||||
|
ear uses the same sets but in reverse (ie, left = angle, right = 360-angle).
|
||||||
|
|
||||||
|
After the coefficients is an array of unsigned 8-bit delay values, one for each
|
||||||
|
HRIR set. This is the delay, in samples, after recieving an input sample before
|
||||||
|
before it's added in to the convolution filter that the corresponding HRIR set
|
||||||
|
operates on and gets heard.
|
||||||
|
|
||||||
|
|
||||||
|
Note that the HRTF data is expected to be minimum-phase reconstructed. The
|
||||||
|
time delays are handled by OpenAL Soft according to the specified delay[]
|
||||||
|
values, and afterward the samples are fed into the convolution filter using the
|
||||||
|
corresponding coefficients. This allows for less processing by using a shorter
|
||||||
|
convolution filter, as it skips the first coefficients that do little more than
|
||||||
|
cause a timed delay, as well as the tailing coefficients that are used to
|
||||||
|
equalize the length of all the sets and contribute nothing.
|
||||||
|
|
||||||
|
For reference, the built-in data set uses a 32-sample convolution filter while
|
||||||
|
even the smallest data set provided by MIT used a 128-sample filter (a 4x
|
||||||
|
reduction by applying minimum-phase reconstruction). Theoretically, one could
|
||||||
|
further reduce the minimum-phase version down to a 16-sample convolution filter
|
||||||
|
with little quality loss.
|
@ -287,7 +287,7 @@ typedef void ALvoid;
|
|||||||
|
|
||||||
|
|
||||||
/** Errors: No Error. */
|
/** Errors: No Error. */
|
||||||
#define AL_NO_ERROR AL_FALSE
|
#define AL_NO_ERROR 0
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Invalid Name paramater passed to AL call.
|
* Invalid Name paramater passed to AL call.
|
||||||
|
@ -120,7 +120,7 @@ typedef void ALCvoid;
|
|||||||
/**
|
/**
|
||||||
* No error
|
* No error
|
||||||
*/
|
*/
|
||||||
#define ALC_NO_ERROR ALC_FALSE
|
#define ALC_NO_ERROR 0
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* No device
|
* No device
|
||||||
|
@ -188,6 +188,75 @@ AL_API void AL_APIENTRY alRequestFoldbackStop(void);
|
|||||||
#define AL_EFFECT_DEDICATED_LOW_FREQUENCY_EFFECT 0x9000
|
#define AL_EFFECT_DEDICATED_LOW_FREQUENCY_EFFECT 0x9000
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifndef AL_SOFT_buffer_samples
|
||||||
|
#define AL_SOFT_buffer_samples 1
|
||||||
|
/* Channel configurations */
|
||||||
|
#define AL_MONO_SOFT 0x1500
|
||||||
|
#define AL_STEREO_SOFT 0x1501
|
||||||
|
#define AL_REAR_SOFT 0x1502
|
||||||
|
#define AL_QUAD_SOFT 0x1503
|
||||||
|
#define AL_5POINT1_SOFT 0x1504
|
||||||
|
#define AL_6POINT1_SOFT 0x1505
|
||||||
|
#define AL_7POINT1_SOFT 0x1506
|
||||||
|
|
||||||
|
/* Sample types */
|
||||||
|
#define AL_BYTE_SOFT 0x1400
|
||||||
|
#define AL_UNSIGNED_BYTE_SOFT 0x1401
|
||||||
|
#define AL_SHORT_SOFT 0x1402
|
||||||
|
#define AL_UNSIGNED_SHORT_SOFT 0x1403
|
||||||
|
#define AL_INT_SOFT 0x1404
|
||||||
|
#define AL_UNSIGNED_INT_SOFT 0x1405
|
||||||
|
#define AL_FLOAT_SOFT 0x1406
|
||||||
|
#define AL_DOUBLE_SOFT 0x1407
|
||||||
|
#define AL_BYTE3_SOFT 0x1408
|
||||||
|
#define AL_UNSIGNED_BYTE3_SOFT 0x1409
|
||||||
|
|
||||||
|
/* Storage formats */
|
||||||
|
#define AL_MONO8_SOFT 0x1100
|
||||||
|
#define AL_MONO16_SOFT 0x1101
|
||||||
|
#define AL_MONO32F_SOFT 0x10010
|
||||||
|
#define AL_STEREO8_SOFT 0x1102
|
||||||
|
#define AL_STEREO16_SOFT 0x1103
|
||||||
|
#define AL_STEREO32F_SOFT 0x10011
|
||||||
|
#define AL_QUAD8_SOFT 0x1204
|
||||||
|
#define AL_QUAD16_SOFT 0x1205
|
||||||
|
#define AL_QUAD32F_SOFT 0x1206
|
||||||
|
#define AL_REAR8_SOFT 0x1207
|
||||||
|
#define AL_REAR16_SOFT 0x1208
|
||||||
|
#define AL_REAR32F_SOFT 0x1209
|
||||||
|
#define AL_5POINT1_8_SOFT 0x120A
|
||||||
|
#define AL_5POINT1_16_SOFT 0x120B
|
||||||
|
#define AL_5POINT1_32F_SOFT 0x120C
|
||||||
|
#define AL_6POINT1_8_SOFT 0x120D
|
||||||
|
#define AL_6POINT1_16_SOFT 0x120E
|
||||||
|
#define AL_6POINT1_32F_SOFT 0x120F
|
||||||
|
#define AL_7POINT1_8_SOFT 0x1210
|
||||||
|
#define AL_7POINT1_16_SOFT 0x1211
|
||||||
|
#define AL_7POINT1_32F_SOFT 0x1212
|
||||||
|
|
||||||
|
/* Buffer attributes */
|
||||||
|
#define AL_INTERNAL_FORMAT_SOFT 0x2008
|
||||||
|
#define AL_BYTE_LENGTH_SOFT 0x2009
|
||||||
|
#define AL_SAMPLE_LENGTH_SOFT 0x200A
|
||||||
|
#define AL_SEC_LENGTH_SOFT 0x200B
|
||||||
|
|
||||||
|
typedef void (AL_APIENTRY*LPALBUFFERSAMPLESSOFT)(ALuint,ALuint,ALenum,ALsizei,ALenum,ALenum,const ALvoid*);
|
||||||
|
typedef void (AL_APIENTRY*LPALBUFFERSUBSAMPLESSOFT)(ALuint,ALsizei,ALsizei,ALenum,ALenum,const ALvoid*);
|
||||||
|
typedef void (AL_APIENTRY*LPALGETBUFFERSAMPLESSOFT)(ALuint,ALsizei,ALsizei,ALenum,ALenum,ALvoid*);
|
||||||
|
typedef ALboolean (AL_APIENTRY*LPALISBUFFERFORMATSUPPORTEDSOFT)(ALenum);
|
||||||
|
#ifdef AL_ALEXT_PROTOTYPES
|
||||||
|
AL_API void AL_APIENTRY alBufferSamplesSOFT(ALuint buffer, ALuint samplerate, ALenum internalformat, ALsizei samples, ALenum channels, ALenum type, const ALvoid *data);
|
||||||
|
AL_API void AL_APIENTRY alBufferSubSamplesSOFT(ALuint buffer, ALsizei offset, ALsizei samples, ALenum channels, ALenum type, const ALvoid *data);
|
||||||
|
AL_API void AL_APIENTRY alGetBufferSamplesSOFT(ALuint buffer, ALsizei offset, ALsizei samples, ALenum channels, ALenum type, ALvoid *data);
|
||||||
|
AL_API ALboolean AL_APIENTRY alIsBufferFormatSupportedSOFT(ALenum format);
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef AL_SOFT_direct_channels
|
||||||
|
#define AL_SOFT_direct_channels 1
|
||||||
|
#define AL_DIRECT_CHANNELS_SOFT 0x1033
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
402
include/AL/efx-presets.h
Normal file
402
include/AL/efx-presets.h
Normal file
@ -0,0 +1,402 @@
|
|||||||
|
/* Reverb presets for EFX */
|
||||||
|
|
||||||
|
#ifndef EFX_PRESETS_H
|
||||||
|
#define EFX_PRESETS_H
|
||||||
|
|
||||||
|
#ifndef EFXEAXREVERBPROPERTIES_DEFINED
|
||||||
|
#define EFXEAXREVERBPROPERTIES_DEFINED
|
||||||
|
typedef struct {
|
||||||
|
float flDensity;
|
||||||
|
float flDiffusion;
|
||||||
|
float flGain;
|
||||||
|
float flGainHF;
|
||||||
|
float flGainLF;
|
||||||
|
float flDecayTime;
|
||||||
|
float flDecayHFRatio;
|
||||||
|
float flDecayLFRatio;
|
||||||
|
float flReflectionsGain;
|
||||||
|
float flReflectionsDelay;
|
||||||
|
float flReflectionsPan[3];
|
||||||
|
float flLateReverbGain;
|
||||||
|
float flLateReverbDelay;
|
||||||
|
float flLateReverbPan[3];
|
||||||
|
float flEchoTime;
|
||||||
|
float flEchoDepth;
|
||||||
|
float flModulationTime;
|
||||||
|
float flModulationDepth;
|
||||||
|
float flAirAbsorptionGainHF;
|
||||||
|
float flHFReference;
|
||||||
|
float flLFReference;
|
||||||
|
float flRoomRolloffFactor;
|
||||||
|
int iDecayHFLimit;
|
||||||
|
} EFXEAXREVERBPROPERTIES, *LPEFXEAXREVERBPROPERTIES;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Default Presets */
|
||||||
|
|
||||||
|
#define EFX_REVERB_PRESET_GENERIC \
|
||||||
|
{ 1.0000f, 1.0000f, 0.3162f, 0.8913f, 1.0000f, 1.4900f, 0.8300f, 1.0000f, 0.0500f, 0.0070f, { 0.0000f, 0.0000f, 0.0000f }, 1.2589f, 0.0110f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.0000f, 0.2500f, 0.0000f, 0.9943f, 5000.0000f, 250.0000f, 0.0000f, 0x1 }
|
||||||
|
|
||||||
|
#define EFX_REVERB_PRESET_PADDEDCELL \
|
||||||
|
{ 0.1715f, 1.0000f, 0.3162f, 0.0010f, 1.0000f, 0.1700f, 0.1000f, 1.0000f, 0.2500f, 0.0010f, { 0.0000f, 0.0000f, 0.0000f }, 1.2691f, 0.0020f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.0000f, 0.2500f, 0.0000f, 0.9943f, 5000.0000f, 250.0000f, 0.0000f, 0x1 }
|
||||||
|
|
||||||
|
#define EFX_REVERB_PRESET_ROOM \
|
||||||
|
{ 0.4287f, 1.0000f, 0.3162f, 0.5929f, 1.0000f, 0.4000f, 0.8300f, 1.0000f, 0.1503f, 0.0020f, { 0.0000f, 0.0000f, 0.0000f }, 1.0629f, 0.0030f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.0000f, 0.2500f, 0.0000f, 0.9943f, 5000.0000f, 250.0000f, 0.0000f, 0x1 }
|
||||||
|
|
||||||
|
#define EFX_REVERB_PRESET_BATHROOM \
|
||||||
|
{ 0.1715f, 1.0000f, 0.3162f, 0.2512f, 1.0000f, 1.4900f, 0.5400f, 1.0000f, 0.6531f, 0.0070f, { 0.0000f, 0.0000f, 0.0000f }, 3.2734f, 0.0110f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.0000f, 0.2500f, 0.0000f, 0.9943f, 5000.0000f, 250.0000f, 0.0000f, 0x1 }
|
||||||
|
|
||||||
|
#define EFX_REVERB_PRESET_LIVINGROOM \
|
||||||
|
{ 0.9766f, 1.0000f, 0.3162f, 0.0010f, 1.0000f, 0.5000f, 0.1000f, 1.0000f, 0.2051f, 0.0030f, { 0.0000f, 0.0000f, 0.0000f }, 0.2805f, 0.0040f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.0000f, 0.2500f, 0.0000f, 0.9943f, 5000.0000f, 250.0000f, 0.0000f, 0x1 }
|
||||||
|
|
||||||
|
#define EFX_REVERB_PRESET_STONEROOM \
|
||||||
|
{ 1.0000f, 1.0000f, 0.3162f, 0.7079f, 1.0000f, 2.3100f, 0.6400f, 1.0000f, 0.4411f, 0.0120f, { 0.0000f, 0.0000f, 0.0000f }, 1.1003f, 0.0170f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.0000f, 0.2500f, 0.0000f, 0.9943f, 5000.0000f, 250.0000f, 0.0000f, 0x1 }
|
||||||
|
|
||||||
|
#define EFX_REVERB_PRESET_AUDITORIUM \
|
||||||
|
{ 1.0000f, 1.0000f, 0.3162f, 0.5781f, 1.0000f, 4.3200f, 0.5900f, 1.0000f, 0.4032f, 0.0200f, { 0.0000f, 0.0000f, 0.0000f }, 0.7170f, 0.0300f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.0000f, 0.2500f, 0.0000f, 0.9943f, 5000.0000f, 250.0000f, 0.0000f, 0x1 }
|
||||||
|
|
||||||
|
#define EFX_REVERB_PRESET_CONCERTHALL \
|
||||||
|
{ 1.0000f, 1.0000f, 0.3162f, 0.5623f, 1.0000f, 3.9200f, 0.7000f, 1.0000f, 0.2427f, 0.0200f, { 0.0000f, 0.0000f, 0.0000f }, 0.9977f, 0.0290f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.0000f, 0.2500f, 0.0000f, 0.9943f, 5000.0000f, 250.0000f, 0.0000f, 0x1 }
|
||||||
|
|
||||||
|
#define EFX_REVERB_PRESET_CAVE \
|
||||||
|
{ 1.0000f, 1.0000f, 0.3162f, 1.0000f, 1.0000f, 2.9100f, 1.3000f, 1.0000f, 0.5000f, 0.0150f, { 0.0000f, 0.0000f, 0.0000f }, 0.7063f, 0.0220f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.0000f, 0.2500f, 0.0000f, 0.9943f, 5000.0000f, 250.0000f, 0.0000f, 0x0 }
|
||||||
|
|
||||||
|
#define EFX_REVERB_PRESET_ARENA \
|
||||||
|
{ 1.0000f, 1.0000f, 0.3162f, 0.4477f, 1.0000f, 7.2400f, 0.3300f, 1.0000f, 0.2612f, 0.0200f, { 0.0000f, 0.0000f, 0.0000f }, 1.0186f, 0.0300f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.0000f, 0.2500f, 0.0000f, 0.9943f, 5000.0000f, 250.0000f, 0.0000f, 0x1 }
|
||||||
|
|
||||||
|
#define EFX_REVERB_PRESET_HANGAR \
|
||||||
|
{ 1.0000f, 1.0000f, 0.3162f, 0.3162f, 1.0000f, 10.0500f, 0.2300f, 1.0000f, 0.5000f, 0.0200f, { 0.0000f, 0.0000f, 0.0000f }, 1.2560f, 0.0300f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.0000f, 0.2500f, 0.0000f, 0.9943f, 5000.0000f, 250.0000f, 0.0000f, 0x1 }
|
||||||
|
|
||||||
|
#define EFX_REVERB_PRESET_CARPETEDHALLWAY \
|
||||||
|
{ 0.4287f, 1.0000f, 0.3162f, 0.0100f, 1.0000f, 0.3000f, 0.1000f, 1.0000f, 0.1215f, 0.0020f, { 0.0000f, 0.0000f, 0.0000f }, 0.1531f, 0.0300f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.0000f, 0.2500f, 0.0000f, 0.9943f, 5000.0000f, 250.0000f, 0.0000f, 0x1 }
|
||||||
|
|
||||||
|
#define EFX_REVERB_PRESET_HALLWAY \
|
||||||
|
{ 0.3645f, 1.0000f, 0.3162f, 0.7079f, 1.0000f, 1.4900f, 0.5900f, 1.0000f, 0.2458f, 0.0070f, { 0.0000f, 0.0000f, 0.0000f }, 1.6615f, 0.0110f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.0000f, 0.2500f, 0.0000f, 0.9943f, 5000.0000f, 250.0000f, 0.0000f, 0x1 }
|
||||||
|
|
||||||
|
#define EFX_REVERB_PRESET_STONECORRIDOR \
|
||||||
|
{ 1.0000f, 1.0000f, 0.3162f, 0.7612f, 1.0000f, 2.7000f, 0.7900f, 1.0000f, 0.2472f, 0.0130f, { 0.0000f, 0.0000f, 0.0000f }, 1.5758f, 0.0200f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.0000f, 0.2500f, 0.0000f, 0.9943f, 5000.0000f, 250.0000f, 0.0000f, 0x1 }
|
||||||
|
|
||||||
|
#define EFX_REVERB_PRESET_ALLEY \
|
||||||
|
{ 1.0000f, 0.3000f, 0.3162f, 0.7328f, 1.0000f, 1.4900f, 0.8600f, 1.0000f, 0.2500f, 0.0070f, { 0.0000f, 0.0000f, 0.0000f }, 0.9954f, 0.0110f, { 0.0000f, 0.0000f, 0.0000f }, 0.1250f, 0.9500f, 0.2500f, 0.0000f, 0.9943f, 5000.0000f, 250.0000f, 0.0000f, 0x1 }
|
||||||
|
|
||||||
|
#define EFX_REVERB_PRESET_FOREST \
|
||||||
|
{ 1.0000f, 0.3000f, 0.3162f, 0.0224f, 1.0000f, 1.4900f, 0.5400f, 1.0000f, 0.0525f, 0.1620f, { 0.0000f, 0.0000f, 0.0000f }, 0.7682f, 0.0880f, { 0.0000f, 0.0000f, 0.0000f }, 0.1250f, 1.0000f, 0.2500f, 0.0000f, 0.9943f, 5000.0000f, 250.0000f, 0.0000f, 0x1 }
|
||||||
|
|
||||||
|
#define EFX_REVERB_PRESET_CITY \
|
||||||
|
{ 1.0000f, 0.5000f, 0.3162f, 0.3981f, 1.0000f, 1.4900f, 0.6700f, 1.0000f, 0.0730f, 0.0070f, { 0.0000f, 0.0000f, 0.0000f }, 0.1427f, 0.0110f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.0000f, 0.2500f, 0.0000f, 0.9943f, 5000.0000f, 250.0000f, 0.0000f, 0x1 }
|
||||||
|
|
||||||
|
#define EFX_REVERB_PRESET_MOUNTAINS \
|
||||||
|
{ 1.0000f, 0.2700f, 0.3162f, 0.0562f, 1.0000f, 1.4900f, 0.2100f, 1.0000f, 0.0407f, 0.3000f, { 0.0000f, 0.0000f, 0.0000f }, 0.1919f, 0.1000f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 1.0000f, 0.2500f, 0.0000f, 0.9943f, 5000.0000f, 250.0000f, 0.0000f, 0x0 }
|
||||||
|
|
||||||
|
#define EFX_REVERB_PRESET_QUARRY \
|
||||||
|
{ 1.0000f, 1.0000f, 0.3162f, 0.3162f, 1.0000f, 1.4900f, 0.8300f, 1.0000f, 0.0000f, 0.0610f, { 0.0000f, 0.0000f, 0.0000f }, 1.7783f, 0.0250f, { 0.0000f, 0.0000f, 0.0000f }, 0.1250f, 0.7000f, 0.2500f, 0.0000f, 0.9943f, 5000.0000f, 250.0000f, 0.0000f, 0x1 }
|
||||||
|
|
||||||
|
#define EFX_REVERB_PRESET_PLAIN \
|
||||||
|
{ 1.0000f, 0.2100f, 0.3162f, 0.1000f, 1.0000f, 1.4900f, 0.5000f, 1.0000f, 0.0585f, 0.1790f, { 0.0000f, 0.0000f, 0.0000f }, 0.1089f, 0.1000f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 1.0000f, 0.2500f, 0.0000f, 0.9943f, 5000.0000f, 250.0000f, 0.0000f, 0x1 }
|
||||||
|
|
||||||
|
#define EFX_REVERB_PRESET_PARKINGLOT \
|
||||||
|
{ 1.0000f, 1.0000f, 0.3162f, 1.0000f, 1.0000f, 1.6500f, 1.5000f, 1.0000f, 0.2082f, 0.0080f, { 0.0000f, 0.0000f, 0.0000f }, 0.2652f, 0.0120f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.0000f, 0.2500f, 0.0000f, 0.9943f, 5000.0000f, 250.0000f, 0.0000f, 0x0 }
|
||||||
|
|
||||||
|
#define EFX_REVERB_PRESET_SEWERPIPE \
|
||||||
|
{ 0.3071f, 0.8000f, 0.3162f, 0.3162f, 1.0000f, 2.8100f, 0.1400f, 1.0000f, 1.6387f, 0.0140f, { 0.0000f, 0.0000f, 0.0000f }, 3.2471f, 0.0210f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.0000f, 0.2500f, 0.0000f, 0.9943f, 5000.0000f, 250.0000f, 0.0000f, 0x1 }
|
||||||
|
|
||||||
|
#define EFX_REVERB_PRESET_UNDERWATER \
|
||||||
|
{ 0.3645f, 1.0000f, 0.3162f, 0.0100f, 1.0000f, 1.4900f, 0.1000f, 1.0000f, 0.5963f, 0.0070f, { 0.0000f, 0.0000f, 0.0000f }, 7.0795f, 0.0110f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.0000f, 1.1800f, 0.3480f, 0.9943f, 5000.0000f, 250.0000f, 0.0000f, 0x1 }
|
||||||
|
|
||||||
|
#define EFX_REVERB_PRESET_DRUGGED \
|
||||||
|
{ 0.4287f, 0.5000f, 0.3162f, 1.0000f, 1.0000f, 8.3900f, 1.3900f, 1.0000f, 0.8760f, 0.0020f, { 0.0000f, 0.0000f, 0.0000f }, 3.1081f, 0.0300f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.0000f, 0.2500f, 1.0000f, 0.9943f, 5000.0000f, 250.0000f, 0.0000f, 0x0 }
|
||||||
|
|
||||||
|
#define EFX_REVERB_PRESET_DIZZY \
|
||||||
|
{ 0.3645f, 0.6000f, 0.3162f, 0.6310f, 1.0000f, 17.2300f, 0.5600f, 1.0000f, 0.1392f, 0.0200f, { 0.0000f, 0.0000f, 0.0000f }, 0.4937f, 0.0300f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 1.0000f, 0.8100f, 0.3100f, 0.9943f, 5000.0000f, 250.0000f, 0.0000f, 0x0 }
|
||||||
|
|
||||||
|
#define EFX_REVERB_PRESET_PSYCHOTIC \
|
||||||
|
{ 0.0625f, 0.5000f, 0.3162f, 0.8404f, 1.0000f, 7.5600f, 0.9100f, 1.0000f, 0.4864f, 0.0200f, { 0.0000f, 0.0000f, 0.0000f }, 2.4378f, 0.0300f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.0000f, 4.0000f, 1.0000f, 0.9943f, 5000.0000f, 250.0000f, 0.0000f, 0x0 }
|
||||||
|
|
||||||
|
/* Castle Presets */
|
||||||
|
|
||||||
|
#define EFX_REVERB_PRESET_CASTLE_SMALLROOM \
|
||||||
|
{ 1.0000f, 0.8900f, 0.3162f, 0.3981f, 0.1000f, 1.2200f, 0.8300f, 0.3100f, 0.8913f, 0.0220f, { 0.0000f, 0.0000f, 0.0000f }, 1.9953f, 0.0110f, { 0.0000f, 0.0000f, 0.0000f }, 0.1380f, 0.0800f, 0.2500f, 0.0000f, 0.9943f, 5168.6001f, 139.5000f, 0.0000f, 0x1 }
|
||||||
|
|
||||||
|
#define EFX_REVERB_PRESET_CASTLE_SHORTPASSAGE \
|
||||||
|
{ 1.0000f, 0.8900f, 0.3162f, 0.3162f, 0.1000f, 2.3200f, 0.8300f, 0.3100f, 0.8913f, 0.0070f, { 0.0000f, 0.0000f, 0.0000f }, 1.2589f, 0.0230f, { 0.0000f, 0.0000f, 0.0000f }, 0.1380f, 0.0800f, 0.2500f, 0.0000f, 0.9943f, 5168.6001f, 139.5000f, 0.0000f, 0x1 }
|
||||||
|
|
||||||
|
#define EFX_REVERB_PRESET_CASTLE_MEDIUMROOM \
|
||||||
|
{ 1.0000f, 0.9300f, 0.3162f, 0.2818f, 0.1000f, 2.0400f, 0.8300f, 0.4600f, 0.6310f, 0.0220f, { 0.0000f, 0.0000f, 0.0000f }, 1.5849f, 0.0110f, { 0.0000f, 0.0000f, 0.0000f }, 0.1550f, 0.0300f, 0.2500f, 0.0000f, 0.9943f, 5168.6001f, 139.5000f, 0.0000f, 0x1 }
|
||||||
|
|
||||||
|
#define EFX_REVERB_PRESET_CASTLE_LARGEROOM \
|
||||||
|
{ 1.0000f, 0.8200f, 0.3162f, 0.2818f, 0.1259f, 2.5300f, 0.8300f, 0.5000f, 0.4467f, 0.0340f, { 0.0000f, 0.0000f, 0.0000f }, 1.2589f, 0.0160f, { 0.0000f, 0.0000f, 0.0000f }, 0.1850f, 0.0700f, 0.2500f, 0.0000f, 0.9943f, 5168.6001f, 139.5000f, 0.0000f, 0x1 }
|
||||||
|
|
||||||
|
#define EFX_REVERB_PRESET_CASTLE_LONGPASSAGE \
|
||||||
|
{ 1.0000f, 0.8900f, 0.3162f, 0.3981f, 0.1000f, 3.4200f, 0.8300f, 0.3100f, 0.8913f, 0.0070f, { 0.0000f, 0.0000f, 0.0000f }, 1.4125f, 0.0230f, { 0.0000f, 0.0000f, 0.0000f }, 0.1380f, 0.0800f, 0.2500f, 0.0000f, 0.9943f, 5168.6001f, 139.5000f, 0.0000f, 0x1 }
|
||||||
|
|
||||||
|
#define EFX_REVERB_PRESET_CASTLE_HALL \
|
||||||
|
{ 1.0000f, 0.8100f, 0.3162f, 0.2818f, 0.1778f, 3.1400f, 0.7900f, 0.6200f, 0.1778f, 0.0560f, { 0.0000f, 0.0000f, 0.0000f }, 1.1220f, 0.0240f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.0000f, 0.2500f, 0.0000f, 0.9943f, 5168.6001f, 139.5000f, 0.0000f, 0x1 }
|
||||||
|
|
||||||
|
#define EFX_REVERB_PRESET_CASTLE_CUPBOARD \
|
||||||
|
{ 1.0000f, 0.8900f, 0.3162f, 0.2818f, 0.1000f, 0.6700f, 0.8700f, 0.3100f, 1.4125f, 0.0100f, { 0.0000f, 0.0000f, 0.0000f }, 3.5481f, 0.0070f, { 0.0000f, 0.0000f, 0.0000f }, 0.1380f, 0.0800f, 0.2500f, 0.0000f, 0.9943f, 5168.6001f, 139.5000f, 0.0000f, 0x1 }
|
||||||
|
|
||||||
|
#define EFX_REVERB_PRESET_CASTLE_COURTYARD \
|
||||||
|
{ 1.0000f, 0.4200f, 0.3162f, 0.4467f, 0.1995f, 2.1300f, 0.6100f, 0.2300f, 0.2239f, 0.1600f, { 0.0000f, 0.0000f, 0.0000f }, 0.7079f, 0.0360f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.3700f, 0.2500f, 0.0000f, 0.9943f, 5000.0000f, 250.0000f, 0.0000f, 0x0 }
|
||||||
|
|
||||||
|
#define EFX_REVERB_PRESET_CASTLE_ALCOVE \
|
||||||
|
{ 1.0000f, 0.8900f, 0.3162f, 0.5012f, 0.1000f, 1.6400f, 0.8700f, 0.3100f, 1.0000f, 0.0070f, { 0.0000f, 0.0000f, 0.0000f }, 1.4125f, 0.0340f, { 0.0000f, 0.0000f, 0.0000f }, 0.1380f, 0.0800f, 0.2500f, 0.0000f, 0.9943f, 5168.6001f, 139.5000f, 0.0000f, 0x1 }
|
||||||
|
|
||||||
|
/* Factory Presets */
|
||||||
|
|
||||||
|
#define EFX_REVERB_PRESET_FACTORY_SMALLROOM \
|
||||||
|
{ 0.3645f, 0.8200f, 0.3162f, 0.7943f, 0.5012f, 1.7200f, 0.6500f, 1.3100f, 0.7079f, 0.0100f, { 0.0000f, 0.0000f, 0.0000f }, 1.7783f, 0.0240f, { 0.0000f, 0.0000f, 0.0000f }, 0.1190f, 0.0700f, 0.2500f, 0.0000f, 0.9943f, 3762.6001f, 362.5000f, 0.0000f, 0x1 }
|
||||||
|
|
||||||
|
#define EFX_REVERB_PRESET_FACTORY_SHORTPASSAGE \
|
||||||
|
{ 0.3645f, 0.6400f, 0.2512f, 0.7943f, 0.5012f, 2.5300f, 0.6500f, 1.3100f, 1.0000f, 0.0100f, { 0.0000f, 0.0000f, 0.0000f }, 1.2589f, 0.0380f, { 0.0000f, 0.0000f, 0.0000f }, 0.1350f, 0.2300f, 0.2500f, 0.0000f, 0.9943f, 3762.6001f, 362.5000f, 0.0000f, 0x1 }
|
||||||
|
|
||||||
|
#define EFX_REVERB_PRESET_FACTORY_MEDIUMROOM \
|
||||||
|
{ 0.4287f, 0.8200f, 0.2512f, 0.7943f, 0.5012f, 2.7600f, 0.6500f, 1.3100f, 0.2818f, 0.0220f, { 0.0000f, 0.0000f, 0.0000f }, 1.4125f, 0.0230f, { 0.0000f, 0.0000f, 0.0000f }, 0.1740f, 0.0700f, 0.2500f, 0.0000f, 0.9943f, 3762.6001f, 362.5000f, 0.0000f, 0x1 }
|
||||||
|
|
||||||
|
#define EFX_REVERB_PRESET_FACTORY_LARGEROOM \
|
||||||
|
{ 0.4287f, 0.7500f, 0.2512f, 0.7079f, 0.6310f, 4.2400f, 0.5100f, 1.3100f, 0.1778f, 0.0390f, { 0.0000f, 0.0000f, 0.0000f }, 1.1220f, 0.0230f, { 0.0000f, 0.0000f, 0.0000f }, 0.2310f, 0.0700f, 0.2500f, 0.0000f, 0.9943f, 3762.6001f, 362.5000f, 0.0000f, 0x1 }
|
||||||
|
|
||||||
|
#define EFX_REVERB_PRESET_FACTORY_LONGPASSAGE \
|
||||||
|
{ 0.3645f, 0.6400f, 0.2512f, 0.7943f, 0.5012f, 4.0600f, 0.6500f, 1.3100f, 1.0000f, 0.0200f, { 0.0000f, 0.0000f, 0.0000f }, 1.2589f, 0.0370f, { 0.0000f, 0.0000f, 0.0000f }, 0.1350f, 0.2300f, 0.2500f, 0.0000f, 0.9943f, 3762.6001f, 362.5000f, 0.0000f, 0x1 }
|
||||||
|
|
||||||
|
#define EFX_REVERB_PRESET_FACTORY_HALL \
|
||||||
|
{ 0.4287f, 0.7500f, 0.3162f, 0.7079f, 0.6310f, 7.4300f, 0.5100f, 1.3100f, 0.0631f, 0.0730f, { 0.0000f, 0.0000f, 0.0000f }, 0.8913f, 0.0270f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.0700f, 0.2500f, 0.0000f, 0.9943f, 3762.6001f, 362.5000f, 0.0000f, 0x1 }
|
||||||
|
|
||||||
|
#define EFX_REVERB_PRESET_FACTORY_CUPBOARD \
|
||||||
|
{ 0.3071f, 0.6300f, 0.2512f, 0.7943f, 0.5012f, 0.4900f, 0.6500f, 1.3100f, 1.2589f, 0.0100f, { 0.0000f, 0.0000f, 0.0000f }, 1.9953f, 0.0320f, { 0.0000f, 0.0000f, 0.0000f }, 0.1070f, 0.0700f, 0.2500f, 0.0000f, 0.9943f, 3762.6001f, 362.5000f, 0.0000f, 0x1 }
|
||||||
|
|
||||||
|
#define EFX_REVERB_PRESET_FACTORY_COURTYARD \
|
||||||
|
{ 0.3071f, 0.5700f, 0.3162f, 0.3162f, 0.6310f, 2.3200f, 0.2900f, 0.5600f, 0.2239f, 0.1400f, { 0.0000f, 0.0000f, 0.0000f }, 0.3981f, 0.0390f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.2900f, 0.2500f, 0.0000f, 0.9943f, 3762.6001f, 362.5000f, 0.0000f, 0x1 }
|
||||||
|
|
||||||
|
#define EFX_REVERB_PRESET_FACTORY_ALCOVE \
|
||||||
|
{ 0.3645f, 0.5900f, 0.2512f, 0.7943f, 0.5012f, 3.1400f, 0.6500f, 1.3100f, 1.4125f, 0.0100f, { 0.0000f, 0.0000f, 0.0000f }, 1.0000f, 0.0380f, { 0.0000f, 0.0000f, 0.0000f }, 0.1140f, 0.1000f, 0.2500f, 0.0000f, 0.9943f, 3762.6001f, 362.5000f, 0.0000f, 0x1 }
|
||||||
|
|
||||||
|
/* Ice Palace Presets */
|
||||||
|
|
||||||
|
#define EFX_REVERB_PRESET_ICEPALACE_SMALLROOM \
|
||||||
|
{ 1.0000f, 0.8400f, 0.3162f, 0.5623f, 0.2818f, 1.5100f, 1.5300f, 0.2700f, 0.8913f, 0.0100f, { 0.0000f, 0.0000f, 0.0000f }, 1.4125f, 0.0110f, { 0.0000f, 0.0000f, 0.0000f }, 0.1640f, 0.1400f, 0.2500f, 0.0000f, 0.9943f, 12428.5000f, 99.6000f, 0.0000f, 0x1 }
|
||||||
|
|
||||||
|
#define EFX_REVERB_PRESET_ICEPALACE_SHORTPASSAGE \
|
||||||
|
{ 1.0000f, 0.7500f, 0.3162f, 0.5623f, 0.2818f, 1.7900f, 1.4600f, 0.2800f, 0.5012f, 0.0100f, { 0.0000f, 0.0000f, 0.0000f }, 1.1220f, 0.0190f, { 0.0000f, 0.0000f, 0.0000f }, 0.1770f, 0.0900f, 0.2500f, 0.0000f, 0.9943f, 12428.5000f, 99.6000f, 0.0000f, 0x1 }
|
||||||
|
|
||||||
|
#define EFX_REVERB_PRESET_ICEPALACE_MEDIUMROOM \
|
||||||
|
{ 1.0000f, 0.8700f, 0.3162f, 0.5623f, 0.4467f, 2.2200f, 1.5300f, 0.3200f, 0.3981f, 0.0390f, { 0.0000f, 0.0000f, 0.0000f }, 1.1220f, 0.0270f, { 0.0000f, 0.0000f, 0.0000f }, 0.1860f, 0.1200f, 0.2500f, 0.0000f, 0.9943f, 12428.5000f, 99.6000f, 0.0000f, 0x1 }
|
||||||
|
|
||||||
|
#define EFX_REVERB_PRESET_ICEPALACE_LARGEROOM \
|
||||||
|
{ 1.0000f, 0.8100f, 0.3162f, 0.5623f, 0.4467f, 3.1400f, 1.5300f, 0.3200f, 0.2512f, 0.0390f, { 0.0000f, 0.0000f, 0.0000f }, 1.0000f, 0.0270f, { 0.0000f, 0.0000f, 0.0000f }, 0.2140f, 0.1100f, 0.2500f, 0.0000f, 0.9943f, 12428.5000f, 99.6000f, 0.0000f, 0x1 }
|
||||||
|
|
||||||
|
#define EFX_REVERB_PRESET_ICEPALACE_LONGPASSAGE \
|
||||||
|
{ 1.0000f, 0.7700f, 0.3162f, 0.5623f, 0.3981f, 3.0100f, 1.4600f, 0.2800f, 0.7943f, 0.0120f, { 0.0000f, 0.0000f, 0.0000f }, 1.2589f, 0.0250f, { 0.0000f, 0.0000f, 0.0000f }, 0.1860f, 0.0400f, 0.2500f, 0.0000f, 0.9943f, 12428.5000f, 99.6000f, 0.0000f, 0x1 }
|
||||||
|
|
||||||
|
#define EFX_REVERB_PRESET_ICEPALACE_HALL \
|
||||||
|
{ 1.0000f, 0.7600f, 0.3162f, 0.4467f, 0.5623f, 5.4900f, 1.5300f, 0.3800f, 0.1122f, 0.0540f, { 0.0000f, 0.0000f, 0.0000f }, 0.6310f, 0.0520f, { 0.0000f, 0.0000f, 0.0000f }, 0.2260f, 0.1100f, 0.2500f, 0.0000f, 0.9943f, 12428.5000f, 99.6000f, 0.0000f, 0x1 }
|
||||||
|
|
||||||
|
#define EFX_REVERB_PRESET_ICEPALACE_CUPBOARD \
|
||||||
|
{ 1.0000f, 0.8300f, 0.3162f, 0.5012f, 0.2239f, 0.7600f, 1.5300f, 0.2600f, 1.1220f, 0.0120f, { 0.0000f, 0.0000f, 0.0000f }, 1.9953f, 0.0160f, { 0.0000f, 0.0000f, 0.0000f }, 0.1430f, 0.0800f, 0.2500f, 0.0000f, 0.9943f, 12428.5000f, 99.6000f, 0.0000f, 0x1 }
|
||||||
|
|
||||||
|
#define EFX_REVERB_PRESET_ICEPALACE_COURTYARD \
|
||||||
|
{ 1.0000f, 0.5900f, 0.3162f, 0.2818f, 0.3162f, 2.0400f, 1.2000f, 0.3800f, 0.3162f, 0.1730f, { 0.0000f, 0.0000f, 0.0000f }, 0.3162f, 0.0430f, { 0.0000f, 0.0000f, 0.0000f }, 0.2350f, 0.4800f, 0.2500f, 0.0000f, 0.9943f, 12428.5000f, 99.6000f, 0.0000f, 0x1 }
|
||||||
|
|
||||||
|
#define EFX_REVERB_PRESET_ICEPALACE_ALCOVE \
|
||||||
|
{ 1.0000f, 0.8400f, 0.3162f, 0.5623f, 0.2818f, 2.7600f, 1.4600f, 0.2800f, 1.1220f, 0.0100f, { 0.0000f, 0.0000f, 0.0000f }, 0.8913f, 0.0300f, { 0.0000f, 0.0000f, 0.0000f }, 0.1610f, 0.0900f, 0.2500f, 0.0000f, 0.9943f, 12428.5000f, 99.6000f, 0.0000f, 0x1 }
|
||||||
|
|
||||||
|
/* Space Station Presets */
|
||||||
|
|
||||||
|
#define EFX_REVERB_PRESET_SPACESTATION_SMALLROOM \
|
||||||
|
{ 0.2109f, 0.7000f, 0.3162f, 0.7079f, 0.8913f, 1.7200f, 0.8200f, 0.5500f, 0.7943f, 0.0070f, { 0.0000f, 0.0000f, 0.0000f }, 1.4125f, 0.0130f, { 0.0000f, 0.0000f, 0.0000f }, 0.1880f, 0.2600f, 0.2500f, 0.0000f, 0.9943f, 3316.1001f, 458.2000f, 0.0000f, 0x1 }
|
||||||
|
|
||||||
|
#define EFX_REVERB_PRESET_SPACESTATION_SHORTPASSAGE \
|
||||||
|
{ 0.2109f, 0.8700f, 0.3162f, 0.6310f, 0.8913f, 3.5700f, 0.5000f, 0.5500f, 1.0000f, 0.0120f, { 0.0000f, 0.0000f, 0.0000f }, 1.1220f, 0.0160f, { 0.0000f, 0.0000f, 0.0000f }, 0.1720f, 0.2000f, 0.2500f, 0.0000f, 0.9943f, 3316.1001f, 458.2000f, 0.0000f, 0x1 }
|
||||||
|
|
||||||
|
#define EFX_REVERB_PRESET_SPACESTATION_MEDIUMROOM \
|
||||||
|
{ 0.2109f, 0.7500f, 0.3162f, 0.6310f, 0.8913f, 3.0100f, 0.5000f, 0.5500f, 0.3981f, 0.0340f, { 0.0000f, 0.0000f, 0.0000f }, 1.1220f, 0.0350f, { 0.0000f, 0.0000f, 0.0000f }, 0.2090f, 0.3100f, 0.2500f, 0.0000f, 0.9943f, 3316.1001f, 458.2000f, 0.0000f, 0x1 }
|
||||||
|
|
||||||
|
#define EFX_REVERB_PRESET_SPACESTATION_LARGEROOM \
|
||||||
|
{ 0.3645f, 0.8100f, 0.3162f, 0.6310f, 0.8913f, 3.8900f, 0.3800f, 0.6100f, 0.3162f, 0.0560f, { 0.0000f, 0.0000f, 0.0000f }, 0.8913f, 0.0350f, { 0.0000f, 0.0000f, 0.0000f }, 0.2330f, 0.2800f, 0.2500f, 0.0000f, 0.9943f, 3316.1001f, 458.2000f, 0.0000f, 0x1 }
|
||||||
|
|
||||||
|
#define EFX_REVERB_PRESET_SPACESTATION_LONGPASSAGE \
|
||||||
|
{ 0.4287f, 0.8200f, 0.3162f, 0.6310f, 0.8913f, 4.6200f, 0.6200f, 0.5500f, 1.0000f, 0.0120f, { 0.0000f, 0.0000f, 0.0000f }, 1.2589f, 0.0310f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.2300f, 0.2500f, 0.0000f, 0.9943f, 3316.1001f, 458.2000f, 0.0000f, 0x1 }
|
||||||
|
|
||||||
|
#define EFX_REVERB_PRESET_SPACESTATION_HALL \
|
||||||
|
{ 0.4287f, 0.8700f, 0.3162f, 0.6310f, 0.8913f, 7.1100f, 0.3800f, 0.6100f, 0.1778f, 0.1000f, { 0.0000f, 0.0000f, 0.0000f }, 0.6310f, 0.0470f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.2500f, 0.2500f, 0.0000f, 0.9943f, 3316.1001f, 458.2000f, 0.0000f, 0x1 }
|
||||||
|
|
||||||
|
#define EFX_REVERB_PRESET_SPACESTATION_CUPBOARD \
|
||||||
|
{ 0.1715f, 0.5600f, 0.3162f, 0.7079f, 0.8913f, 0.7900f, 0.8100f, 0.5500f, 1.4125f, 0.0070f, { 0.0000f, 0.0000f, 0.0000f }, 1.7783f, 0.0180f, { 0.0000f, 0.0000f, 0.0000f }, 0.1810f, 0.3100f, 0.2500f, 0.0000f, 0.9943f, 3316.1001f, 458.2000f, 0.0000f, 0x1 }
|
||||||
|
|
||||||
|
#define EFX_REVERB_PRESET_SPACESTATION_ALCOVE \
|
||||||
|
{ 0.2109f, 0.7800f, 0.3162f, 0.7079f, 0.8913f, 1.1600f, 0.8100f, 0.5500f, 1.4125f, 0.0070f, { 0.0000f, 0.0000f, 0.0000f }, 1.0000f, 0.0180f, { 0.0000f, 0.0000f, 0.0000f }, 0.1920f, 0.2100f, 0.2500f, 0.0000f, 0.9943f, 3316.1001f, 458.2000f, 0.0000f, 0x1 }
|
||||||
|
|
||||||
|
/* Wooden Galleon Presets */
|
||||||
|
|
||||||
|
#define EFX_REVERB_PRESET_WOODEN_SMALLROOM \
|
||||||
|
{ 1.0000f, 1.0000f, 0.3162f, 0.1122f, 0.3162f, 0.7900f, 0.3200f, 0.8700f, 1.0000f, 0.0320f, { 0.0000f, 0.0000f, 0.0000f }, 0.8913f, 0.0290f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.0000f, 0.2500f, 0.0000f, 0.9943f, 4705.0000f, 99.6000f, 0.0000f, 0x1 }
|
||||||
|
|
||||||
|
#define EFX_REVERB_PRESET_WOODEN_SHORTPASSAGE \
|
||||||
|
{ 1.0000f, 1.0000f, 0.3162f, 0.1259f, 0.3162f, 1.7500f, 0.5000f, 0.8700f, 0.8913f, 0.0120f, { 0.0000f, 0.0000f, 0.0000f }, 0.6310f, 0.0240f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.0000f, 0.2500f, 0.0000f, 0.9943f, 4705.0000f, 99.6000f, 0.0000f, 0x1 }
|
||||||
|
|
||||||
|
#define EFX_REVERB_PRESET_WOODEN_MEDIUMROOM \
|
||||||
|
{ 1.0000f, 1.0000f, 0.3162f, 0.1000f, 0.2818f, 1.4700f, 0.4200f, 0.8200f, 0.8913f, 0.0490f, { 0.0000f, 0.0000f, 0.0000f }, 0.8913f, 0.0290f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.0000f, 0.2500f, 0.0000f, 0.9943f, 4705.0000f, 99.6000f, 0.0000f, 0x1 }
|
||||||
|
|
||||||
|
#define EFX_REVERB_PRESET_WOODEN_LARGEROOM \
|
||||||
|
{ 1.0000f, 1.0000f, 0.3162f, 0.0891f, 0.2818f, 2.6500f, 0.3300f, 0.8200f, 0.8913f, 0.0660f, { 0.0000f, 0.0000f, 0.0000f }, 0.7943f, 0.0490f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.0000f, 0.2500f, 0.0000f, 0.9943f, 4705.0000f, 99.6000f, 0.0000f, 0x1 }
|
||||||
|
|
||||||
|
#define EFX_REVERB_PRESET_WOODEN_LONGPASSAGE \
|
||||||
|
{ 1.0000f, 1.0000f, 0.3162f, 0.1000f, 0.3162f, 1.9900f, 0.4000f, 0.7900f, 1.0000f, 0.0200f, { 0.0000f, 0.0000f, 0.0000f }, 0.4467f, 0.0360f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.0000f, 0.2500f, 0.0000f, 0.9943f, 4705.0000f, 99.6000f, 0.0000f, 0x1 }
|
||||||
|
|
||||||
|
#define EFX_REVERB_PRESET_WOODEN_HALL \
|
||||||
|
{ 1.0000f, 1.0000f, 0.3162f, 0.0794f, 0.2818f, 3.4500f, 0.3000f, 0.8200f, 0.8913f, 0.0880f, { 0.0000f, 0.0000f, 0.0000f }, 0.7943f, 0.0630f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.0000f, 0.2500f, 0.0000f, 0.9943f, 4705.0000f, 99.6000f, 0.0000f, 0x1 }
|
||||||
|
|
||||||
|
#define EFX_REVERB_PRESET_WOODEN_CUPBOARD \
|
||||||
|
{ 1.0000f, 1.0000f, 0.3162f, 0.1413f, 0.3162f, 0.5600f, 0.4600f, 0.9100f, 1.1220f, 0.0120f, { 0.0000f, 0.0000f, 0.0000f }, 1.1220f, 0.0280f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.0000f, 0.2500f, 0.0000f, 0.9943f, 4705.0000f, 99.6000f, 0.0000f, 0x1 }
|
||||||
|
|
||||||
|
#define EFX_REVERB_PRESET_WOODEN_COURTYARD \
|
||||||
|
{ 1.0000f, 0.6500f, 0.3162f, 0.0794f, 0.3162f, 1.7900f, 0.3500f, 0.7900f, 0.5623f, 0.1230f, { 0.0000f, 0.0000f, 0.0000f }, 0.1000f, 0.0320f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.0000f, 0.2500f, 0.0000f, 0.9943f, 4705.0000f, 99.6000f, 0.0000f, 0x1 }
|
||||||
|
|
||||||
|
#define EFX_REVERB_PRESET_WOODEN_ALCOVE \
|
||||||
|
{ 1.0000f, 1.0000f, 0.3162f, 0.1259f, 0.3162f, 1.2200f, 0.6200f, 0.9100f, 1.1220f, 0.0120f, { 0.0000f, 0.0000f, 0.0000f }, 0.7079f, 0.0240f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.0000f, 0.2500f, 0.0000f, 0.9943f, 4705.0000f, 99.6000f, 0.0000f, 0x1 }
|
||||||
|
|
||||||
|
/* Sports Presets */
|
||||||
|
|
||||||
|
#define EFX_REVERB_PRESET_SPORT_EMPTYSTADIUM \
|
||||||
|
{ 1.0000f, 1.0000f, 0.3162f, 0.4467f, 0.7943f, 6.2600f, 0.5100f, 1.1000f, 0.0631f, 0.1830f, { 0.0000f, 0.0000f, 0.0000f }, 0.3981f, 0.0380f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.0000f, 0.2500f, 0.0000f, 0.9943f, 5000.0000f, 250.0000f, 0.0000f, 0x1 }
|
||||||
|
|
||||||
|
#define EFX_REVERB_PRESET_SPORT_SQUASHCOURT \
|
||||||
|
{ 1.0000f, 0.7500f, 0.3162f, 0.3162f, 0.7943f, 2.2200f, 0.9100f, 1.1600f, 0.4467f, 0.0070f, { 0.0000f, 0.0000f, 0.0000f }, 0.7943f, 0.0110f, { 0.0000f, 0.0000f, 0.0000f }, 0.1260f, 0.1900f, 0.2500f, 0.0000f, 0.9943f, 7176.8999f, 211.2000f, 0.0000f, 0x1 }
|
||||||
|
|
||||||
|
#define EFX_REVERB_PRESET_SPORT_SMALLSWIMMINGPOOL \
|
||||||
|
{ 1.0000f, 0.7000f, 0.3162f, 0.7943f, 0.8913f, 2.7600f, 1.2500f, 1.1400f, 0.6310f, 0.0200f, { 0.0000f, 0.0000f, 0.0000f }, 0.7943f, 0.0300f, { 0.0000f, 0.0000f, 0.0000f }, 0.1790f, 0.1500f, 0.8950f, 0.1900f, 0.9943f, 5000.0000f, 250.0000f, 0.0000f, 0x0 }
|
||||||
|
|
||||||
|
#define EFX_REVERB_PRESET_SPORT_LARGESWIMMINGPOOL \
|
||||||
|
{ 1.0000f, 0.8200f, 0.3162f, 0.7943f, 1.0000f, 5.4900f, 1.3100f, 1.1400f, 0.4467f, 0.0390f, { 0.0000f, 0.0000f, 0.0000f }, 0.5012f, 0.0490f, { 0.0000f, 0.0000f, 0.0000f }, 0.2220f, 0.5500f, 1.1590f, 0.2100f, 0.9943f, 5000.0000f, 250.0000f, 0.0000f, 0x0 }
|
||||||
|
|
||||||
|
#define EFX_REVERB_PRESET_SPORT_GYMNASIUM \
|
||||||
|
{ 1.0000f, 0.8100f, 0.3162f, 0.4467f, 0.8913f, 3.1400f, 1.0600f, 1.3500f, 0.3981f, 0.0290f, { 0.0000f, 0.0000f, 0.0000f }, 0.5623f, 0.0450f, { 0.0000f, 0.0000f, 0.0000f }, 0.1460f, 0.1400f, 0.2500f, 0.0000f, 0.9943f, 7176.8999f, 211.2000f, 0.0000f, 0x1 }
|
||||||
|
|
||||||
|
#define EFX_REVERB_PRESET_SPORT_FULLSTADIUM \
|
||||||
|
{ 1.0000f, 1.0000f, 0.3162f, 0.0708f, 0.7943f, 5.2500f, 0.1700f, 0.8000f, 0.1000f, 0.1880f, { 0.0000f, 0.0000f, 0.0000f }, 0.2818f, 0.0380f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.0000f, 0.2500f, 0.0000f, 0.9943f, 5000.0000f, 250.0000f, 0.0000f, 0x1 }
|
||||||
|
|
||||||
|
#define EFX_REVERB_PRESET_SPORT_STADIUMTANNOY \
|
||||||
|
{ 1.0000f, 0.7800f, 0.3162f, 0.5623f, 0.5012f, 2.5300f, 0.8800f, 0.6800f, 0.2818f, 0.2300f, { 0.0000f, 0.0000f, 0.0000f }, 0.5012f, 0.0630f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.2000f, 0.2500f, 0.0000f, 0.9943f, 5000.0000f, 250.0000f, 0.0000f, 0x1 }
|
||||||
|
|
||||||
|
/* Prefab Presets */
|
||||||
|
|
||||||
|
#define EFX_REVERB_PRESET_PREFAB_WORKSHOP \
|
||||||
|
{ 0.4287f, 1.0000f, 0.3162f, 0.1413f, 0.3981f, 0.7600f, 1.0000f, 1.0000f, 1.0000f, 0.0120f, { 0.0000f, 0.0000f, 0.0000f }, 1.1220f, 0.0120f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.0000f, 0.2500f, 0.0000f, 0.9943f, 5000.0000f, 250.0000f, 0.0000f, 0x0 }
|
||||||
|
|
||||||
|
#define EFX_REVERB_PRESET_PREFAB_SCHOOLROOM \
|
||||||
|
{ 0.4022f, 0.6900f, 0.3162f, 0.6310f, 0.5012f, 0.9800f, 0.4500f, 0.1800f, 1.4125f, 0.0170f, { 0.0000f, 0.0000f, 0.0000f }, 1.4125f, 0.0150f, { 0.0000f, 0.0000f, 0.0000f }, 0.0950f, 0.1400f, 0.2500f, 0.0000f, 0.9943f, 7176.8999f, 211.2000f, 0.0000f, 0x1 }
|
||||||
|
|
||||||
|
#define EFX_REVERB_PRESET_PREFAB_PRACTISEROOM \
|
||||||
|
{ 0.4022f, 0.8700f, 0.3162f, 0.3981f, 0.5012f, 1.1200f, 0.5600f, 0.1800f, 1.2589f, 0.0100f, { 0.0000f, 0.0000f, 0.0000f }, 1.4125f, 0.0110f, { 0.0000f, 0.0000f, 0.0000f }, 0.0950f, 0.1400f, 0.2500f, 0.0000f, 0.9943f, 7176.8999f, 211.2000f, 0.0000f, 0x1 }
|
||||||
|
|
||||||
|
#define EFX_REVERB_PRESET_PREFAB_OUTHOUSE \
|
||||||
|
{ 1.0000f, 0.8200f, 0.3162f, 0.1122f, 0.1585f, 1.3800f, 0.3800f, 0.3500f, 0.8913f, 0.0240f, { 0.0000f, 0.0000f, -0.0000f }, 0.6310f, 0.0440f, { 0.0000f, 0.0000f, 0.0000f }, 0.1210f, 0.1700f, 0.2500f, 0.0000f, 0.9943f, 2854.3999f, 107.5000f, 0.0000f, 0x0 }
|
||||||
|
|
||||||
|
#define EFX_REVERB_PRESET_PREFAB_CARAVAN \
|
||||||
|
{ 1.0000f, 1.0000f, 0.3162f, 0.0891f, 0.1259f, 0.4300f, 1.5000f, 1.0000f, 1.0000f, 0.0120f, { 0.0000f, 0.0000f, 0.0000f }, 1.9953f, 0.0120f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.0000f, 0.2500f, 0.0000f, 0.9943f, 5000.0000f, 250.0000f, 0.0000f, 0x0 }
|
||||||
|
|
||||||
|
/* Dome and Pipe Presets */
|
||||||
|
|
||||||
|
#define EFX_REVERB_PRESET_DOME_TOMB \
|
||||||
|
{ 1.0000f, 0.7900f, 0.3162f, 0.3548f, 0.2239f, 4.1800f, 0.2100f, 0.1000f, 0.3868f, 0.0300f, { 0.0000f, 0.0000f, 0.0000f }, 1.6788f, 0.0220f, { 0.0000f, 0.0000f, 0.0000f }, 0.1770f, 0.1900f, 0.2500f, 0.0000f, 0.9943f, 2854.3999f, 20.0000f, 0.0000f, 0x0 }
|
||||||
|
|
||||||
|
#define EFX_REVERB_PRESET_PIPE_SMALL \
|
||||||
|
{ 1.0000f, 1.0000f, 0.3162f, 0.3548f, 0.2239f, 5.0400f, 0.1000f, 0.1000f, 0.5012f, 0.0320f, { 0.0000f, 0.0000f, 0.0000f }, 2.5119f, 0.0150f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.0000f, 0.2500f, 0.0000f, 0.9943f, 2854.3999f, 20.0000f, 0.0000f, 0x1 }
|
||||||
|
|
||||||
|
#define EFX_REVERB_PRESET_DOME_SAINTPAULS \
|
||||||
|
{ 1.0000f, 0.8700f, 0.3162f, 0.3548f, 0.2239f, 10.4800f, 0.1900f, 0.1000f, 0.1778f, 0.0900f, { 0.0000f, 0.0000f, 0.0000f }, 1.2589f, 0.0420f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.1200f, 0.2500f, 0.0000f, 0.9943f, 2854.3999f, 20.0000f, 0.0000f, 0x1 }
|
||||||
|
|
||||||
|
#define EFX_REVERB_PRESET_PIPE_LONGTHIN \
|
||||||
|
{ 0.2560f, 0.9100f, 0.3162f, 0.4467f, 0.2818f, 9.2100f, 0.1800f, 0.1000f, 0.7079f, 0.0100f, { 0.0000f, 0.0000f, 0.0000f }, 0.7079f, 0.0220f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.0000f, 0.2500f, 0.0000f, 0.9943f, 2854.3999f, 20.0000f, 0.0000f, 0x0 }
|
||||||
|
|
||||||
|
#define EFX_REVERB_PRESET_PIPE_LARGE \
|
||||||
|
{ 1.0000f, 1.0000f, 0.3162f, 0.3548f, 0.2239f, 8.4500f, 0.1000f, 0.1000f, 0.3981f, 0.0460f, { 0.0000f, 0.0000f, 0.0000f }, 1.5849f, 0.0320f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.0000f, 0.2500f, 0.0000f, 0.9943f, 2854.3999f, 20.0000f, 0.0000f, 0x1 }
|
||||||
|
|
||||||
|
#define EFX_REVERB_PRESET_PIPE_RESONANT \
|
||||||
|
{ 0.1373f, 0.9100f, 0.3162f, 0.4467f, 0.2818f, 6.8100f, 0.1800f, 0.1000f, 0.7079f, 0.0100f, { 0.0000f, 0.0000f, 0.0000f }, 1.0000f, 0.0220f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.0000f, 0.2500f, 0.0000f, 0.9943f, 2854.3999f, 20.0000f, 0.0000f, 0x0 }
|
||||||
|
|
||||||
|
/* Outdoors Presets */
|
||||||
|
|
||||||
|
#define EFX_REVERB_PRESET_OUTDOORS_BACKYARD \
|
||||||
|
{ 1.0000f, 0.4500f, 0.3162f, 0.2512f, 0.5012f, 1.1200f, 0.3400f, 0.4600f, 0.4467f, 0.0690f, { 0.0000f, 0.0000f, -0.0000f }, 0.7079f, 0.0230f, { 0.0000f, 0.0000f, 0.0000f }, 0.2180f, 0.3400f, 0.2500f, 0.0000f, 0.9943f, 4399.1001f, 242.9000f, 0.0000f, 0x0 }
|
||||||
|
|
||||||
|
#define EFX_REVERB_PRESET_OUTDOORS_ROLLINGPLAINS \
|
||||||
|
{ 1.0000f, 0.0000f, 0.3162f, 0.0112f, 0.6310f, 2.1300f, 0.2100f, 0.4600f, 0.1778f, 0.3000f, { 0.0000f, 0.0000f, -0.0000f }, 0.4467f, 0.0190f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 1.0000f, 0.2500f, 0.0000f, 0.9943f, 4399.1001f, 242.9000f, 0.0000f, 0x0 }
|
||||||
|
|
||||||
|
#define EFX_REVERB_PRESET_OUTDOORS_DEEPCANYON \
|
||||||
|
{ 1.0000f, 0.7400f, 0.3162f, 0.1778f, 0.6310f, 3.8900f, 0.2100f, 0.4600f, 0.3162f, 0.2230f, { 0.0000f, 0.0000f, -0.0000f }, 0.3548f, 0.0190f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 1.0000f, 0.2500f, 0.0000f, 0.9943f, 4399.1001f, 242.9000f, 0.0000f, 0x0 }
|
||||||
|
|
||||||
|
#define EFX_REVERB_PRESET_OUTDOORS_CREEK \
|
||||||
|
{ 1.0000f, 0.3500f, 0.3162f, 0.1778f, 0.5012f, 2.1300f, 0.2100f, 0.4600f, 0.3981f, 0.1150f, { 0.0000f, 0.0000f, -0.0000f }, 0.1995f, 0.0310f, { 0.0000f, 0.0000f, 0.0000f }, 0.2180f, 0.3400f, 0.2500f, 0.0000f, 0.9943f, 4399.1001f, 242.9000f, 0.0000f, 0x0 }
|
||||||
|
|
||||||
|
#define EFX_REVERB_PRESET_OUTDOORS_VALLEY \
|
||||||
|
{ 1.0000f, 0.2800f, 0.3162f, 0.0282f, 0.1585f, 2.8800f, 0.2600f, 0.3500f, 0.1413f, 0.2630f, { 0.0000f, 0.0000f, -0.0000f }, 0.3981f, 0.1000f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.3400f, 0.2500f, 0.0000f, 0.9943f, 2854.3999f, 107.5000f, 0.0000f, 0x0 }
|
||||||
|
|
||||||
|
/* Mood Presets */
|
||||||
|
|
||||||
|
#define EFX_REVERB_PRESET_MOOD_HEAVEN \
|
||||||
|
{ 1.0000f, 0.9400f, 0.3162f, 0.7943f, 0.4467f, 5.0400f, 1.1200f, 0.5600f, 0.2427f, 0.0200f, { 0.0000f, 0.0000f, 0.0000f }, 1.2589f, 0.0290f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.0800f, 2.7420f, 0.0500f, 0.9977f, 5000.0000f, 250.0000f, 0.0000f, 0x1 }
|
||||||
|
|
||||||
|
#define EFX_REVERB_PRESET_MOOD_HELL \
|
||||||
|
{ 1.0000f, 0.5700f, 0.3162f, 0.3548f, 0.4467f, 3.5700f, 0.4900f, 2.0000f, 0.0000f, 0.0200f, { 0.0000f, 0.0000f, 0.0000f }, 1.4125f, 0.0300f, { 0.0000f, 0.0000f, 0.0000f }, 0.1100f, 0.0400f, 2.1090f, 0.5200f, 0.9943f, 5000.0000f, 139.5000f, 0.0000f, 0x0 }
|
||||||
|
|
||||||
|
#define EFX_REVERB_PRESET_MOOD_MEMORY \
|
||||||
|
{ 1.0000f, 0.8500f, 0.3162f, 0.6310f, 0.3548f, 4.0600f, 0.8200f, 0.5600f, 0.0398f, 0.0000f, { 0.0000f, 0.0000f, 0.0000f }, 1.1220f, 0.0000f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.0000f, 0.4740f, 0.4500f, 0.9886f, 5000.0000f, 250.0000f, 0.0000f, 0x0 }
|
||||||
|
|
||||||
|
/* Driving Presets */
|
||||||
|
|
||||||
|
#define EFX_REVERB_PRESET_DRIVING_COMMENTATOR \
|
||||||
|
{ 1.0000f, 0.0000f, 3.1623f, 0.5623f, 0.5012f, 2.4200f, 0.8800f, 0.6800f, 0.1995f, 0.0930f, { 0.0000f, 0.0000f, 0.0000f }, 0.2512f, 0.0170f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 1.0000f, 0.2500f, 0.0000f, 0.9886f, 5000.0000f, 250.0000f, 0.0000f, 0x1 }
|
||||||
|
|
||||||
|
#define EFX_REVERB_PRESET_DRIVING_PITGARAGE \
|
||||||
|
{ 0.4287f, 0.5900f, 0.3162f, 0.7079f, 0.5623f, 1.7200f, 0.9300f, 0.8700f, 0.5623f, 0.0000f, { 0.0000f, 0.0000f, 0.0000f }, 1.2589f, 0.0160f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.1100f, 0.2500f, 0.0000f, 0.9943f, 5000.0000f, 250.0000f, 0.0000f, 0x0 }
|
||||||
|
|
||||||
|
#define EFX_REVERB_PRESET_DRIVING_INCAR_RACER \
|
||||||
|
{ 0.0832f, 0.8000f, 0.3162f, 1.0000f, 0.7943f, 0.1700f, 2.0000f, 0.4100f, 1.7783f, 0.0070f, { 0.0000f, 0.0000f, 0.0000f }, 0.7079f, 0.0150f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.0000f, 0.2500f, 0.0000f, 0.9943f, 10268.2002f, 251.0000f, 0.0000f, 0x1 }
|
||||||
|
|
||||||
|
#define EFX_REVERB_PRESET_DRIVING_INCAR_SPORTS \
|
||||||
|
{ 0.0832f, 0.8000f, 0.3162f, 0.6310f, 1.0000f, 0.1700f, 0.7500f, 0.4100f, 1.0000f, 0.0100f, { 0.0000f, 0.0000f, 0.0000f }, 0.5623f, 0.0000f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.0000f, 0.2500f, 0.0000f, 0.9943f, 10268.2002f, 251.0000f, 0.0000f, 0x1 }
|
||||||
|
|
||||||
|
#define EFX_REVERB_PRESET_DRIVING_INCAR_LUXURY \
|
||||||
|
{ 0.2560f, 1.0000f, 0.3162f, 0.1000f, 0.5012f, 0.1300f, 0.4100f, 0.4600f, 0.7943f, 0.0100f, { 0.0000f, 0.0000f, 0.0000f }, 1.5849f, 0.0100f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.0000f, 0.2500f, 0.0000f, 0.9943f, 10268.2002f, 251.0000f, 0.0000f, 0x1 }
|
||||||
|
|
||||||
|
#define EFX_REVERB_PRESET_DRIVING_FULLGRANDSTAND \
|
||||||
|
{ 1.0000f, 1.0000f, 0.3162f, 0.2818f, 0.6310f, 3.0100f, 1.3700f, 1.2800f, 0.3548f, 0.0900f, { 0.0000f, 0.0000f, 0.0000f }, 0.1778f, 0.0490f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.0000f, 0.2500f, 0.0000f, 0.9943f, 10420.2002f, 250.0000f, 0.0000f, 0x0 }
|
||||||
|
|
||||||
|
#define EFX_REVERB_PRESET_DRIVING_EMPTYGRANDSTAND \
|
||||||
|
{ 1.0000f, 1.0000f, 0.3162f, 1.0000f, 0.7943f, 4.6200f, 1.7500f, 1.4000f, 0.2082f, 0.0900f, { 0.0000f, 0.0000f, 0.0000f }, 0.2512f, 0.0490f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.0000f, 0.2500f, 0.0000f, 0.9943f, 10420.2002f, 250.0000f, 0.0000f, 0x0 }
|
||||||
|
|
||||||
|
#define EFX_REVERB_PRESET_DRIVING_TUNNEL \
|
||||||
|
{ 1.0000f, 0.8100f, 0.3162f, 0.3981f, 0.8913f, 3.4200f, 0.9400f, 1.3100f, 0.7079f, 0.0510f, { 0.0000f, 0.0000f, 0.0000f }, 0.7079f, 0.0470f, { 0.0000f, 0.0000f, 0.0000f }, 0.2140f, 0.0500f, 0.2500f, 0.0000f, 0.9943f, 5000.0000f, 155.3000f, 0.0000f, 0x1 }
|
||||||
|
|
||||||
|
/* City Presets */
|
||||||
|
|
||||||
|
#define EFX_REVERB_PRESET_CITY_STREETS \
|
||||||
|
{ 1.0000f, 0.7800f, 0.3162f, 0.7079f, 0.8913f, 1.7900f, 1.1200f, 0.9100f, 0.2818f, 0.0460f, { 0.0000f, 0.0000f, 0.0000f }, 0.1995f, 0.0280f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.2000f, 0.2500f, 0.0000f, 0.9943f, 5000.0000f, 250.0000f, 0.0000f, 0x1 }
|
||||||
|
|
||||||
|
#define EFX_REVERB_PRESET_CITY_SUBWAY \
|
||||||
|
{ 1.0000f, 0.7400f, 0.3162f, 0.7079f, 0.8913f, 3.0100f, 1.2300f, 0.9100f, 0.7079f, 0.0460f, { 0.0000f, 0.0000f, 0.0000f }, 1.2589f, 0.0280f, { 0.0000f, 0.0000f, 0.0000f }, 0.1250f, 0.2100f, 0.2500f, 0.0000f, 0.9943f, 5000.0000f, 250.0000f, 0.0000f, 0x1 }
|
||||||
|
|
||||||
|
#define EFX_REVERB_PRESET_CITY_MUSEUM \
|
||||||
|
{ 1.0000f, 0.8200f, 0.3162f, 0.1778f, 0.1778f, 3.2800f, 1.4000f, 0.5700f, 0.2512f, 0.0390f, { 0.0000f, 0.0000f, -0.0000f }, 0.8913f, 0.0340f, { 0.0000f, 0.0000f, 0.0000f }, 0.1300f, 0.1700f, 0.2500f, 0.0000f, 0.9943f, 2854.3999f, 107.5000f, 0.0000f, 0x0 }
|
||||||
|
|
||||||
|
#define EFX_REVERB_PRESET_CITY_LIBRARY \
|
||||||
|
{ 1.0000f, 0.8200f, 0.3162f, 0.2818f, 0.0891f, 2.7600f, 0.8900f, 0.4100f, 0.3548f, 0.0290f, { 0.0000f, 0.0000f, -0.0000f }, 0.8913f, 0.0200f, { 0.0000f, 0.0000f, 0.0000f }, 0.1300f, 0.1700f, 0.2500f, 0.0000f, 0.9943f, 2854.3999f, 107.5000f, 0.0000f, 0x0 }
|
||||||
|
|
||||||
|
#define EFX_REVERB_PRESET_CITY_UNDERPASS \
|
||||||
|
{ 1.0000f, 0.8200f, 0.3162f, 0.4467f, 0.8913f, 3.5700f, 1.1200f, 0.9100f, 0.3981f, 0.0590f, { 0.0000f, 0.0000f, 0.0000f }, 0.8913f, 0.0370f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.1400f, 0.2500f, 0.0000f, 0.9920f, 5000.0000f, 250.0000f, 0.0000f, 0x1 }
|
||||||
|
|
||||||
|
#define EFX_REVERB_PRESET_CITY_ABANDONED \
|
||||||
|
{ 1.0000f, 0.6900f, 0.3162f, 0.7943f, 0.8913f, 3.2800f, 1.1700f, 0.9100f, 0.4467f, 0.0440f, { 0.0000f, 0.0000f, 0.0000f }, 0.2818f, 0.0240f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.2000f, 0.2500f, 0.0000f, 0.9966f, 5000.0000f, 250.0000f, 0.0000f, 0x1 }
|
||||||
|
|
||||||
|
/* Misc. Presets */
|
||||||
|
|
||||||
|
#define EFX_REVERB_PRESET_DUSTYROOM \
|
||||||
|
{ 0.3645f, 0.5600f, 0.3162f, 0.7943f, 0.7079f, 1.7900f, 0.3800f, 0.2100f, 0.5012f, 0.0020f, { 0.0000f, 0.0000f, 0.0000f }, 1.2589f, 0.0060f, { 0.0000f, 0.0000f, 0.0000f }, 0.2020f, 0.0500f, 0.2500f, 0.0000f, 0.9886f, 13046.0000f, 163.3000f, 0.0000f, 0x1 }
|
||||||
|
|
||||||
|
#define EFX_REVERB_PRESET_CHAPEL \
|
||||||
|
{ 1.0000f, 0.8400f, 0.3162f, 0.5623f, 1.0000f, 4.6200f, 0.6400f, 1.2300f, 0.4467f, 0.0320f, { 0.0000f, 0.0000f, 0.0000f }, 0.7943f, 0.0490f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.0000f, 0.2500f, 0.1100f, 0.9943f, 5000.0000f, 250.0000f, 0.0000f, 0x1 }
|
||||||
|
|
||||||
|
#define EFX_REVERB_PRESET_SMALLWATERROOM \
|
||||||
|
{ 1.0000f, 0.7000f, 0.3162f, 0.4477f, 1.0000f, 1.5100f, 1.2500f, 1.1400f, 0.8913f, 0.0200f, { 0.0000f, 0.0000f, 0.0000f }, 1.4125f, 0.0300f, { 0.0000f, 0.0000f, 0.0000f }, 0.1790f, 0.1500f, 0.8950f, 0.1900f, 0.9920f, 5000.0000f, 250.0000f, 0.0000f, 0x0 }
|
||||||
|
|
||||||
|
#endif /* EFX_PRESETS_H */
|
@ -277,7 +277,10 @@ int main(int argc, char *argv[])
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
printf("\n** Info for device \"%s\" **\n", alcGetString(device, ALC_DEVICE_SPECIFIER));
|
if(alcIsExtensionPresent(device, "ALC_ENUMERATE_ALL_EXT") != AL_FALSE)
|
||||||
|
printf("\n** Info for device \"%s\" **\n", alcGetString(device, ALC_ALL_DEVICES_SPECIFIER));
|
||||||
|
else
|
||||||
|
printf("\n** Info for device \"%s\" **\n", alcGetString(device, ALC_DEVICE_SPECIFIER));
|
||||||
printALCInfo(device);
|
printALCInfo(device);
|
||||||
|
|
||||||
context = alcCreateContext(device, NULL);
|
context = alcCreateContext(device, NULL);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user