2007-11-14 02:02:18 +00:00
|
|
|
/**
|
|
|
|
* OpenAL cross platform audio library
|
|
|
|
* Copyright (C) 1999-2007 by authors.
|
|
|
|
* This library is free software; you can redistribute it and/or
|
|
|
|
* modify it under the terms of the GNU Library General Public
|
|
|
|
* License as published by the Free Software Foundation; either
|
|
|
|
* version 2 of the License, or (at your option) any later version.
|
|
|
|
*
|
|
|
|
* This library is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
|
|
* Library General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU Library General Public
|
|
|
|
* License along with this library; if not, write to the
|
|
|
|
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
|
|
|
* Boston, MA 02111-1307, USA.
|
|
|
|
* Or go to http://www.gnu.org/copyleft/lgpl.html
|
|
|
|
*/
|
|
|
|
|
|
|
|
#define _CRT_SECURE_NO_DEPRECATE // get rid of sprintf security warnings on VS2005
|
|
|
|
|
|
|
|
#include "config.h"
|
|
|
|
|
|
|
|
#include <math.h>
|
|
|
|
#include "alMain.h"
|
|
|
|
#include "AL/al.h"
|
|
|
|
#include "AL/alc.h"
|
2007-12-31 09:09:57 +00:00
|
|
|
#include "alSource.h"
|
|
|
|
#include "alBuffer.h"
|
|
|
|
#include "alThunk.h"
|
|
|
|
#include "alListener.h"
|
2008-01-16 22:01:24 +00:00
|
|
|
#include "alAuxEffectSlot.h"
|
2008-01-03 13:36:51 +00:00
|
|
|
#include "bs2b.h"
|
2007-11-14 02:02:18 +00:00
|
|
|
|
|
|
|
#if defined(HAVE_STDINT_H)
|
|
|
|
#include <stdint.h>
|
|
|
|
typedef int64_t ALint64;
|
|
|
|
#elif defined(HAVE___INT64)
|
|
|
|
typedef __int64 ALint64;
|
|
|
|
#elif (SIZEOF_LONG == 8)
|
|
|
|
typedef long ALint64;
|
|
|
|
#elif (SIZEOF_LONG_LONG == 8)
|
|
|
|
typedef long long ALint64;
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifdef HAVE_SQRTF
|
|
|
|
#define aluSqrt(x) ((ALfloat)sqrtf((float)(x)))
|
|
|
|
#else
|
|
|
|
#define aluSqrt(x) ((ALfloat)sqrt((double)(x)))
|
|
|
|
#endif
|
|
|
|
|
2008-01-16 05:23:14 +00:00
|
|
|
#ifdef HAVE_ACOSF
|
|
|
|
#define aluAcos(x) ((ALfloat)acosf((float)(x)))
|
|
|
|
#else
|
|
|
|
#define aluAcos(x) ((ALfloat)acos((double)(x)))
|
|
|
|
#endif
|
|
|
|
|
2007-11-14 02:02:18 +00:00
|
|
|
// fixes for mingw32.
|
|
|
|
#if defined(max) && !defined(__max)
|
|
|
|
#define __max max
|
|
|
|
#endif
|
|
|
|
#if defined(min) && !defined(__min)
|
|
|
|
#define __min min
|
|
|
|
#endif
|
|
|
|
|
2008-07-09 02:37:14 +00:00
|
|
|
#define BUFFERSIZE 24000
|
2007-12-31 09:16:13 +00:00
|
|
|
#define FRACTIONBITS 14
|
|
|
|
#define FRACTIONMASK ((1L<<FRACTIONBITS)-1)
|
|
|
|
#define MAX_PITCH 4
|
2007-12-31 09:47:10 +00:00
|
|
|
|
|
|
|
enum {
|
|
|
|
FRONT_LEFT = 0,
|
|
|
|
FRONT_RIGHT,
|
2007-12-31 11:29:14 +00:00
|
|
|
SIDE_LEFT,
|
|
|
|
SIDE_RIGHT,
|
2007-12-31 09:47:10 +00:00
|
|
|
BACK_LEFT,
|
|
|
|
BACK_RIGHT,
|
|
|
|
CENTER,
|
|
|
|
LFE,
|
|
|
|
|
|
|
|
OUTPUTCHANNELS
|
|
|
|
};
|
2007-12-31 09:16:13 +00:00
|
|
|
|
2008-02-07 06:18:50 +00:00
|
|
|
ALboolean DuplicateStereo = AL_FALSE;
|
|
|
|
|
2007-12-31 11:29:14 +00:00
|
|
|
/* NOTE: The AL_FORMAT_REAR* enums aren't handled here be cause they're
|
|
|
|
* converted to AL_FORMAT_QUAD* when loaded */
|
2007-11-14 02:02:18 +00:00
|
|
|
__inline ALuint aluBytesFromFormat(ALenum format)
|
|
|
|
{
|
|
|
|
switch(format)
|
|
|
|
{
|
|
|
|
case AL_FORMAT_MONO8:
|
|
|
|
case AL_FORMAT_STEREO8:
|
2008-01-15 00:11:15 +00:00
|
|
|
case AL_FORMAT_QUAD8_LOKI:
|
2007-11-14 02:02:18 +00:00
|
|
|
case AL_FORMAT_QUAD8:
|
2007-12-27 07:01:22 +00:00
|
|
|
case AL_FORMAT_51CHN8:
|
2007-12-31 11:29:14 +00:00
|
|
|
case AL_FORMAT_61CHN8:
|
|
|
|
case AL_FORMAT_71CHN8:
|
2007-11-14 02:02:18 +00:00
|
|
|
return 1;
|
|
|
|
|
|
|
|
case AL_FORMAT_MONO16:
|
|
|
|
case AL_FORMAT_STEREO16:
|
2008-01-15 00:11:15 +00:00
|
|
|
case AL_FORMAT_QUAD16_LOKI:
|
2007-11-14 02:02:18 +00:00
|
|
|
case AL_FORMAT_QUAD16:
|
2007-12-27 07:01:22 +00:00
|
|
|
case AL_FORMAT_51CHN16:
|
2007-12-31 11:29:14 +00:00
|
|
|
case AL_FORMAT_61CHN16:
|
|
|
|
case AL_FORMAT_71CHN16:
|
2007-11-14 02:02:18 +00:00
|
|
|
return 2;
|
|
|
|
|
2007-12-29 06:41:14 +00:00
|
|
|
case AL_FORMAT_MONO_FLOAT32:
|
|
|
|
case AL_FORMAT_STEREO_FLOAT32:
|
2007-12-31 11:29:14 +00:00
|
|
|
case AL_FORMAT_QUAD32:
|
|
|
|
case AL_FORMAT_51CHN32:
|
|
|
|
case AL_FORMAT_61CHN32:
|
|
|
|
case AL_FORMAT_71CHN32:
|
2007-12-29 06:41:14 +00:00
|
|
|
return 4;
|
|
|
|
|
2007-11-14 02:02:18 +00:00
|
|
|
default:
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
__inline ALuint aluChannelsFromFormat(ALenum format)
|
|
|
|
{
|
|
|
|
switch(format)
|
|
|
|
{
|
|
|
|
case AL_FORMAT_MONO8:
|
|
|
|
case AL_FORMAT_MONO16:
|
2007-12-29 06:41:14 +00:00
|
|
|
case AL_FORMAT_MONO_FLOAT32:
|
2007-11-14 02:02:18 +00:00
|
|
|
return 1;
|
|
|
|
|
|
|
|
case AL_FORMAT_STEREO8:
|
|
|
|
case AL_FORMAT_STEREO16:
|
2007-12-29 06:41:14 +00:00
|
|
|
case AL_FORMAT_STEREO_FLOAT32:
|
2007-11-14 02:02:18 +00:00
|
|
|
return 2;
|
|
|
|
|
2008-01-15 00:11:15 +00:00
|
|
|
case AL_FORMAT_QUAD8_LOKI:
|
|
|
|
case AL_FORMAT_QUAD16_LOKI:
|
2007-11-14 02:02:18 +00:00
|
|
|
case AL_FORMAT_QUAD8:
|
|
|
|
case AL_FORMAT_QUAD16:
|
2007-12-31 11:29:14 +00:00
|
|
|
case AL_FORMAT_QUAD32:
|
2007-11-14 02:02:18 +00:00
|
|
|
return 4;
|
|
|
|
|
2007-12-27 07:01:22 +00:00
|
|
|
case AL_FORMAT_51CHN8:
|
|
|
|
case AL_FORMAT_51CHN16:
|
2007-12-31 11:29:14 +00:00
|
|
|
case AL_FORMAT_51CHN32:
|
2007-12-27 07:01:22 +00:00
|
|
|
return 6;
|
|
|
|
|
2007-12-31 11:29:14 +00:00
|
|
|
case AL_FORMAT_61CHN8:
|
|
|
|
case AL_FORMAT_61CHN16:
|
|
|
|
case AL_FORMAT_61CHN32:
|
|
|
|
return 7;
|
|
|
|
|
|
|
|
case AL_FORMAT_71CHN8:
|
|
|
|
case AL_FORMAT_71CHN16:
|
|
|
|
case AL_FORMAT_71CHN32:
|
|
|
|
return 8;
|
|
|
|
|
2007-11-14 02:02:18 +00:00
|
|
|
default:
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static __inline ALshort aluF2S(ALfloat Value)
|
|
|
|
{
|
|
|
|
ALint i;
|
|
|
|
|
2008-02-09 05:03:48 +00:00
|
|
|
i = (ALint)Value;
|
2007-11-14 02:02:18 +00:00
|
|
|
i = __min( 32767, i);
|
|
|
|
i = __max(-32768, i);
|
|
|
|
return ((ALshort)i);
|
|
|
|
}
|
|
|
|
|
|
|
|
static __inline ALvoid aluCrossproduct(ALfloat *inVector1,ALfloat *inVector2,ALfloat *outVector)
|
|
|
|
{
|
|
|
|
outVector[0] = inVector1[1]*inVector2[2] - inVector1[2]*inVector2[1];
|
|
|
|
outVector[1] = inVector1[2]*inVector2[0] - inVector1[0]*inVector2[2];
|
|
|
|
outVector[2] = inVector1[0]*inVector2[1] - inVector1[1]*inVector2[0];
|
|
|
|
}
|
|
|
|
|
|
|
|
static __inline ALfloat aluDotproduct(ALfloat *inVector1,ALfloat *inVector2)
|
|
|
|
{
|
|
|
|
return inVector1[0]*inVector2[0] + inVector1[1]*inVector2[1] +
|
|
|
|
inVector1[2]*inVector2[2];
|
|
|
|
}
|
|
|
|
|
|
|
|
static __inline ALvoid aluNormalize(ALfloat *inVector)
|
|
|
|
{
|
|
|
|
ALfloat length, inverse_length;
|
|
|
|
|
2008-02-09 05:01:05 +00:00
|
|
|
length = aluSqrt(aluDotproduct(inVector, inVector));
|
|
|
|
if(length != 0.0f)
|
2007-11-14 02:02:18 +00:00
|
|
|
{
|
|
|
|
inverse_length = 1.0f/length;
|
|
|
|
inVector[0] *= inverse_length;
|
|
|
|
inVector[1] *= inverse_length;
|
|
|
|
inVector[2] *= inverse_length;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static __inline ALvoid aluMatrixVector(ALfloat *vector,ALfloat matrix[3][3])
|
|
|
|
{
|
|
|
|
ALfloat result[3];
|
|
|
|
|
|
|
|
result[0] = vector[0]*matrix[0][0] + vector[1]*matrix[1][0] + vector[2]*matrix[2][0];
|
|
|
|
result[1] = vector[0]*matrix[0][1] + vector[1]*matrix[1][1] + vector[2]*matrix[2][1];
|
|
|
|
result[2] = vector[0]*matrix[0][2] + vector[1]*matrix[1][2] + vector[2]*matrix[2][2];
|
|
|
|
memcpy(vector, result, sizeof(result));
|
|
|
|
}
|
|
|
|
|
2008-07-24 05:29:53 +00:00
|
|
|
static __inline ALfloat aluComputeSample(ALfloat GainHF, ALfloat sample, ALfloat LowSample)
|
2007-12-18 05:00:52 +00:00
|
|
|
{
|
2008-07-24 05:29:53 +00:00
|
|
|
return LowSample + ((sample - LowSample) * GainHF);
|
2007-12-18 05:00:52 +00:00
|
|
|
}
|
|
|
|
|
2007-11-14 02:02:18 +00:00
|
|
|
static ALvoid CalcSourceParams(ALCcontext *ALContext, ALsource *ALSource,
|
|
|
|
ALenum isMono, ALenum OutputFormat,
|
|
|
|
ALfloat *drysend, ALfloat *wetsend,
|
2007-12-18 05:00:52 +00:00
|
|
|
ALfloat *pitch, ALfloat *drygainhf,
|
|
|
|
ALfloat *wetgainhf)
|
2007-11-14 02:02:18 +00:00
|
|
|
{
|
2008-01-16 20:43:25 +00:00
|
|
|
ALfloat InnerAngle,OuterAngle,Angle,Distance,DryMix,WetMix=0.0f;
|
2008-01-16 05:57:50 +00:00
|
|
|
ALfloat Direction[3],Position[3],SourceToListener[3];
|
2007-12-18 05:56:31 +00:00
|
|
|
ALfloat MinVolume,MaxVolume,MinDist,MaxDist,Rolloff,OuterGainHF;
|
2008-01-16 05:57:50 +00:00
|
|
|
ALfloat ConeVolume,SourceVolume,PanningFB,PanningLR,ListenerGain;
|
2007-11-14 02:02:18 +00:00
|
|
|
ALfloat U[3],V[3],N[3];
|
|
|
|
ALfloat DopplerFactor, DopplerVelocity, flSpeedOfSound, flMaxVelocity;
|
|
|
|
ALfloat Matrix[3][3];
|
|
|
|
ALfloat flAttenuation;
|
2007-12-19 03:03:40 +00:00
|
|
|
ALfloat RoomAttenuation;
|
2007-12-18 03:40:43 +00:00
|
|
|
ALfloat MetersPerUnit;
|
2007-12-19 03:03:40 +00:00
|
|
|
ALfloat RoomRolloff;
|
2007-12-18 05:56:31 +00:00
|
|
|
ALfloat DryGainHF = 1.0f;
|
|
|
|
ALfloat WetGainHF = 1.0f;
|
2007-11-14 02:02:18 +00:00
|
|
|
|
|
|
|
//Get context properties
|
2008-07-15 09:33:05 +00:00
|
|
|
DopplerFactor = ALContext->DopplerFactor * ALSource->DopplerFactor;
|
2007-11-14 02:02:18 +00:00
|
|
|
DopplerVelocity = ALContext->DopplerVelocity;
|
|
|
|
flSpeedOfSound = ALContext->flSpeedOfSound;
|
|
|
|
|
|
|
|
//Get listener properties
|
|
|
|
ListenerGain = ALContext->Listener.Gain;
|
2007-12-18 03:40:43 +00:00
|
|
|
MetersPerUnit = ALContext->Listener.MetersPerUnit;
|
2007-11-14 02:02:18 +00:00
|
|
|
|
|
|
|
//Get source properties
|
|
|
|
SourceVolume = ALSource->flGain;
|
|
|
|
memcpy(Position, ALSource->vPosition, sizeof(ALSource->vPosition));
|
|
|
|
memcpy(Direction, ALSource->vOrientation, sizeof(ALSource->vOrientation));
|
|
|
|
MinVolume = ALSource->flMinGain;
|
|
|
|
MaxVolume = ALSource->flMaxGain;
|
|
|
|
MinDist = ALSource->flRefDistance;
|
|
|
|
MaxDist = ALSource->flMaxDistance;
|
|
|
|
Rolloff = ALSource->flRollOffFactor;
|
|
|
|
InnerAngle = ALSource->flInnerAngle;
|
|
|
|
OuterAngle = ALSource->flOuterAngle;
|
2007-12-19 00:54:22 +00:00
|
|
|
OuterGainHF = ALSource->OuterGainHF;
|
2007-12-19 03:03:40 +00:00
|
|
|
RoomRolloff = ALSource->RoomRolloffFactor;
|
2007-11-14 02:02:18 +00:00
|
|
|
|
|
|
|
//Only apply 3D calculations for mono buffers
|
|
|
|
if(isMono != AL_FALSE)
|
|
|
|
{
|
|
|
|
//1. Translate Listener to origin (convert to head relative)
|
2008-07-03 10:13:43 +00:00
|
|
|
// Note that Direction and SourceToListener are *not* transformed.
|
|
|
|
// SourceToListener is used with the source and listener velocities,
|
|
|
|
// which are untransformed, and Direction is used with SourceToListener
|
|
|
|
// for the sound cone
|
2008-01-16 05:57:50 +00:00
|
|
|
if(ALSource->bHeadRelative==AL_FALSE)
|
2007-11-14 02:02:18 +00:00
|
|
|
{
|
2008-05-18 23:52:38 +00:00
|
|
|
// Build transform matrix
|
|
|
|
aluCrossproduct(ALContext->Listener.Forward, ALContext->Listener.Up, U); // Right-vector
|
|
|
|
aluNormalize(U); // Normalized Right-vector
|
|
|
|
memcpy(V, ALContext->Listener.Up, sizeof(V)); // Up-vector
|
|
|
|
aluNormalize(V); // Normalized Up-vector
|
|
|
|
memcpy(N, ALContext->Listener.Forward, sizeof(N)); // At-vector
|
|
|
|
aluNormalize(N); // Normalized At-vector
|
|
|
|
Matrix[0][0] = U[0]; Matrix[0][1] = V[0]; Matrix[0][2] = -N[0];
|
|
|
|
Matrix[1][0] = U[1]; Matrix[1][1] = V[1]; Matrix[1][2] = -N[1];
|
|
|
|
Matrix[2][0] = U[2]; Matrix[2][1] = V[2]; Matrix[2][2] = -N[2];
|
|
|
|
|
|
|
|
// Translate source position into listener space
|
2008-01-16 05:57:50 +00:00
|
|
|
Position[0] -= ALContext->Listener.Position[0];
|
|
|
|
Position[1] -= ALContext->Listener.Position[1];
|
|
|
|
Position[2] -= ALContext->Listener.Position[2];
|
2008-07-03 10:13:43 +00:00
|
|
|
|
|
|
|
SourceToListener[0] = -Position[0];
|
|
|
|
SourceToListener[1] = -Position[1];
|
|
|
|
SourceToListener[2] = -Position[2];
|
|
|
|
|
2008-05-18 23:52:38 +00:00
|
|
|
// Transform source position and direction into listener space
|
|
|
|
aluMatrixVector(Position, Matrix);
|
2007-11-14 02:02:18 +00:00
|
|
|
}
|
2008-07-03 10:13:43 +00:00
|
|
|
else
|
|
|
|
{
|
|
|
|
SourceToListener[0] = -Position[0];
|
|
|
|
SourceToListener[1] = -Position[1];
|
|
|
|
SourceToListener[2] = -Position[2];
|
|
|
|
}
|
|
|
|
aluNormalize(SourceToListener);
|
2008-05-18 23:52:38 +00:00
|
|
|
aluNormalize(Direction);
|
2007-11-14 02:02:18 +00:00
|
|
|
|
|
|
|
//2. Calculate distance attenuation
|
|
|
|
Distance = aluSqrt(aluDotproduct(Position, Position));
|
|
|
|
|
Implement AL_EFFECT_REVERB
Here is a quick description of how the reverb effect works:
+--->---+*(4)
| V new sample
+-----+---+---+ |
|extra|ltr|ref| <- +*(1)
+-----+---+---+
(3,5)*| |*(2)
+-->|
V
out sample
1) Apply master reverb gain to incoming sample and place it at the head of the
buffer. The master reverb gainhf was already applied when the source was
initially mixed.
2) Copy the delayed reflection sample to an output sample and apply the
reflection gain.
3) Apply the late reverb gain to the late reverb sample
4) Copy the end of the buffer, applying a decay gain and the decay hf ratio,
and add to the late reverb.
5) Copy the late reverb sample, adding to the output sample.
Then the head and sampling points are shifted forward, and done again for each
new sample. The extra buffer length is determined by the Reverb Density
property. A value of 0 gives a length of 0.1 seconds (long, with fairly
distinct echos) , and 1 gives 0.075 seconds (short, indistinct echos).
The decay gain is calculated such that after a number of loops to satisfy the
Decay Time, a sample will be 1/32768th as powerful (virtually insignificant to
the resulting output, and only getting further reduced). It is calculated as:
DecayGain = pow(1.0f/32768.0f, 1.0/(DecayTime/ExtraLength));
Things to note: Reverb Diffusion is not currently handled, nor is Decay HF
Limit. Decay HF Ratios above 1 probably give incorrect results. Also, this
method likely sucks, but it's the best I can come up with before release. :)
2008-01-19 05:25:40 +00:00
|
|
|
if(ALSource->Send[0].Slot && !ALSource->Send[0].Slot->AuxSendAuto)
|
|
|
|
{
|
|
|
|
if(ALSource->Send[0].Slot->effect.type == AL_EFFECT_REVERB)
|
2008-07-15 09:23:53 +00:00
|
|
|
RoomRolloff += ALSource->Send[0].Slot->effect.Reverb.RoomRolloffFactor;
|
Implement AL_EFFECT_REVERB
Here is a quick description of how the reverb effect works:
+--->---+*(4)
| V new sample
+-----+---+---+ |
|extra|ltr|ref| <- +*(1)
+-----+---+---+
(3,5)*| |*(2)
+-->|
V
out sample
1) Apply master reverb gain to incoming sample and place it at the head of the
buffer. The master reverb gainhf was already applied when the source was
initially mixed.
2) Copy the delayed reflection sample to an output sample and apply the
reflection gain.
3) Apply the late reverb gain to the late reverb sample
4) Copy the end of the buffer, applying a decay gain and the decay hf ratio,
and add to the late reverb.
5) Copy the late reverb sample, adding to the output sample.
Then the head and sampling points are shifted forward, and done again for each
new sample. The extra buffer length is determined by the Reverb Density
property. A value of 0 gives a length of 0.1 seconds (long, with fairly
distinct echos) , and 1 gives 0.075 seconds (short, indistinct echos).
The decay gain is calculated such that after a number of loops to satisfy the
Decay Time, a sample will be 1/32768th as powerful (virtually insignificant to
the resulting output, and only getting further reduced). It is calculated as:
DecayGain = pow(1.0f/32768.0f, 1.0/(DecayTime/ExtraLength));
Things to note: Reverb Diffusion is not currently handled, nor is Decay HF
Limit. Decay HF Ratios above 1 probably give incorrect results. Also, this
method likely sucks, but it's the best I can come up with before release. :)
2008-01-19 05:25:40 +00:00
|
|
|
}
|
|
|
|
|
2007-11-14 02:02:18 +00:00
|
|
|
flAttenuation = 1.0f;
|
2007-12-19 03:03:40 +00:00
|
|
|
RoomAttenuation = 1.0f;
|
2008-01-16 05:57:50 +00:00
|
|
|
switch (ALContext->DistanceModel)
|
2007-11-14 02:02:18 +00:00
|
|
|
{
|
|
|
|
case AL_INVERSE_DISTANCE_CLAMPED:
|
|
|
|
Distance=__max(Distance,MinDist);
|
|
|
|
Distance=__min(Distance,MaxDist);
|
|
|
|
if (MaxDist < MinDist)
|
|
|
|
break;
|
|
|
|
//fall-through
|
|
|
|
case AL_INVERSE_DISTANCE:
|
|
|
|
if (MinDist > 0.0f)
|
|
|
|
{
|
|
|
|
if ((MinDist + (Rolloff * (Distance - MinDist))) > 0.0f)
|
|
|
|
flAttenuation = MinDist / (MinDist + (Rolloff * (Distance - MinDist)));
|
2007-12-19 03:03:40 +00:00
|
|
|
if ((MinDist + (RoomRolloff * (Distance - MinDist))) > 0.0f)
|
|
|
|
RoomAttenuation = MinDist / (MinDist + (RoomRolloff * (Distance - MinDist)));
|
2007-11-14 02:02:18 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case AL_LINEAR_DISTANCE_CLAMPED:
|
|
|
|
Distance=__max(Distance,MinDist);
|
|
|
|
Distance=__min(Distance,MaxDist);
|
|
|
|
if (MaxDist < MinDist)
|
|
|
|
break;
|
|
|
|
//fall-through
|
|
|
|
case AL_LINEAR_DISTANCE:
|
|
|
|
Distance=__min(Distance,MaxDist);
|
|
|
|
if (MaxDist != MinDist)
|
2007-12-19 03:03:40 +00:00
|
|
|
{
|
2007-11-14 02:02:18 +00:00
|
|
|
flAttenuation = 1.0f - (Rolloff*(Distance-MinDist)/(MaxDist - MinDist));
|
2007-12-19 03:03:40 +00:00
|
|
|
RoomAttenuation = 1.0f - (RoomRolloff*(Distance-MinDist)/(MaxDist - MinDist));
|
|
|
|
}
|
2007-11-14 02:02:18 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case AL_EXPONENT_DISTANCE_CLAMPED:
|
|
|
|
Distance=__max(Distance,MinDist);
|
|
|
|
Distance=__min(Distance,MaxDist);
|
|
|
|
if (MaxDist < MinDist)
|
|
|
|
break;
|
|
|
|
//fall-through
|
|
|
|
case AL_EXPONENT_DISTANCE:
|
|
|
|
if ((Distance > 0.0f) && (MinDist > 0.0f))
|
2007-12-19 03:03:40 +00:00
|
|
|
{
|
2007-11-14 02:02:18 +00:00
|
|
|
flAttenuation = (ALfloat)pow(Distance/MinDist, -Rolloff);
|
2007-12-19 03:03:40 +00:00
|
|
|
RoomAttenuation = (ALfloat)pow(Distance/MinDist, -RoomRolloff);
|
|
|
|
}
|
2007-11-14 02:02:18 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case AL_NONE:
|
|
|
|
default:
|
|
|
|
flAttenuation = 1.0f;
|
2007-12-19 03:03:40 +00:00
|
|
|
RoomAttenuation = 1.0f;
|
2007-11-14 02:02:18 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2008-01-16 21:00:35 +00:00
|
|
|
// Source Gain + Attenuation and clamp to Min/Max Gain
|
2007-11-14 02:02:18 +00:00
|
|
|
DryMix = SourceVolume * flAttenuation;
|
2008-01-16 21:00:35 +00:00
|
|
|
DryMix = __min(DryMix,MaxVolume);
|
|
|
|
DryMix = __max(DryMix,MinVolume);
|
Implement AL_EFFECT_REVERB
Here is a quick description of how the reverb effect works:
+--->---+*(4)
| V new sample
+-----+---+---+ |
|extra|ltr|ref| <- +*(1)
+-----+---+---+
(3,5)*| |*(2)
+-->|
V
out sample
1) Apply master reverb gain to incoming sample and place it at the head of the
buffer. The master reverb gainhf was already applied when the source was
initially mixed.
2) Copy the delayed reflection sample to an output sample and apply the
reflection gain.
3) Apply the late reverb gain to the late reverb sample
4) Copy the end of the buffer, applying a decay gain and the decay hf ratio,
and add to the late reverb.
5) Copy the late reverb sample, adding to the output sample.
Then the head and sampling points are shifted forward, and done again for each
new sample. The extra buffer length is determined by the Reverb Density
property. A value of 0 gives a length of 0.1 seconds (long, with fairly
distinct echos) , and 1 gives 0.075 seconds (short, indistinct echos).
The decay gain is calculated such that after a number of loops to satisfy the
Decay Time, a sample will be 1/32768th as powerful (virtually insignificant to
the resulting output, and only getting further reduced). It is calculated as:
DecayGain = pow(1.0f/32768.0f, 1.0/(DecayTime/ExtraLength));
Things to note: Reverb Diffusion is not currently handled, nor is Decay HF
Limit. Decay HF Ratios above 1 probably give incorrect results. Also, this
method likely sucks, but it's the best I can come up with before release. :)
2008-01-19 05:25:40 +00:00
|
|
|
|
|
|
|
WetMix = SourceVolume * (ALSource->WetGainAuto ?
|
|
|
|
RoomAttenuation : 1.0f);
|
|
|
|
WetMix = __min(WetMix,MaxVolume);
|
|
|
|
WetMix = __max(WetMix,MinVolume);
|
2007-11-14 02:02:18 +00:00
|
|
|
|
|
|
|
//3. Apply directional soundcones
|
2008-01-16 05:23:14 +00:00
|
|
|
Angle = aluAcos(aluDotproduct(Direction,SourceToListener)) * 180.0f /
|
|
|
|
3.141592654f;
|
2007-11-14 02:02:18 +00:00
|
|
|
if(Angle >= InnerAngle && Angle <= OuterAngle)
|
2007-12-18 05:56:31 +00:00
|
|
|
{
|
|
|
|
ALfloat scale = (Angle-InnerAngle) / (OuterAngle-InnerAngle);
|
2008-01-16 05:57:50 +00:00
|
|
|
ConeVolume = (1.0f+(ALSource->flOuterGain-1.0f)*scale);
|
2007-12-19 03:13:41 +00:00
|
|
|
if(ALSource->WetGainAuto)
|
|
|
|
WetMix *= ConeVolume;
|
2007-12-19 00:54:22 +00:00
|
|
|
if(ALSource->DryGainHFAuto)
|
|
|
|
DryGainHF *= (1.0f+(OuterGainHF-1.0f)*scale);
|
|
|
|
if(ALSource->WetGainHFAuto)
|
|
|
|
WetGainHF *= (1.0f+(OuterGainHF-1.0f)*scale);
|
2007-12-18 05:56:31 +00:00
|
|
|
}
|
2007-11-14 02:02:18 +00:00
|
|
|
else if(Angle > OuterAngle)
|
2007-12-18 05:56:31 +00:00
|
|
|
{
|
2008-01-16 05:57:50 +00:00
|
|
|
ConeVolume = (1.0f+(ALSource->flOuterGain-1.0f));
|
2007-12-19 03:13:41 +00:00
|
|
|
if(ALSource->WetGainAuto)
|
|
|
|
WetMix *= ConeVolume;
|
2007-12-19 00:54:22 +00:00
|
|
|
if(ALSource->DryGainHFAuto)
|
|
|
|
DryGainHF *= (1.0f+(OuterGainHF-1.0f));
|
|
|
|
if(ALSource->WetGainHFAuto)
|
|
|
|
WetGainHF *= (1.0f+(OuterGainHF-1.0f));
|
2007-12-18 05:56:31 +00:00
|
|
|
}
|
2007-11-14 02:02:18 +00:00
|
|
|
else
|
|
|
|
ConeVolume = 1.0f;
|
|
|
|
|
|
|
|
//4. Calculate Velocity
|
|
|
|
if(DopplerFactor != 0.0f)
|
|
|
|
{
|
2008-05-18 23:52:38 +00:00
|
|
|
ALfloat flVSS, flVLS = 0.0f;
|
2008-01-16 05:57:50 +00:00
|
|
|
|
2008-05-18 23:52:38 +00:00
|
|
|
if(ALSource->bHeadRelative==AL_FALSE)
|
|
|
|
flVLS = aluDotproduct(ALContext->Listener.Velocity, SourceToListener);
|
2008-01-16 05:57:50 +00:00
|
|
|
flVSS = aluDotproduct(ALSource->vVelocity, SourceToListener);
|
2007-11-14 02:02:18 +00:00
|
|
|
|
|
|
|
flMaxVelocity = (DopplerVelocity * flSpeedOfSound) / DopplerFactor;
|
|
|
|
|
|
|
|
if (flVSS >= flMaxVelocity)
|
|
|
|
flVSS = (flMaxVelocity - 1.0f);
|
|
|
|
else if (flVSS <= -flMaxVelocity)
|
|
|
|
flVSS = -flMaxVelocity + 1.0f;
|
|
|
|
|
|
|
|
if (flVLS >= flMaxVelocity)
|
|
|
|
flVLS = (flMaxVelocity - 1.0f);
|
|
|
|
else if (flVLS <= -flMaxVelocity)
|
|
|
|
flVLS = -flMaxVelocity + 1.0f;
|
|
|
|
|
2008-01-16 05:57:50 +00:00
|
|
|
pitch[0] = ALSource->flPitch *
|
|
|
|
((flSpeedOfSound * DopplerVelocity) - (DopplerFactor * flVLS)) /
|
|
|
|
((flSpeedOfSound * DopplerVelocity) - (DopplerFactor * flVSS));
|
2007-11-14 02:02:18 +00:00
|
|
|
}
|
|
|
|
else
|
2008-01-16 05:57:50 +00:00
|
|
|
pitch[0] = ALSource->flPitch;
|
2007-11-14 02:02:18 +00:00
|
|
|
|
2008-05-18 23:52:38 +00:00
|
|
|
//5. Apply filter gains and filters
|
2008-04-12 14:25:18 +00:00
|
|
|
switch(ALSource->DirectFilter.type)
|
2007-12-18 06:42:38 +00:00
|
|
|
{
|
|
|
|
case AL_FILTER_LOWPASS:
|
|
|
|
DryMix *= ALSource->DirectFilter.Gain;
|
|
|
|
DryGainHF *= ALSource->DirectFilter.GainHF;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2008-04-12 14:25:18 +00:00
|
|
|
switch(ALSource->Send[0].WetFilter.type)
|
2007-12-18 23:10:21 +00:00
|
|
|
{
|
|
|
|
case AL_FILTER_LOWPASS:
|
|
|
|
WetMix *= ALSource->Send[0].WetFilter.Gain;
|
|
|
|
WetGainHF *= ALSource->Send[0].WetFilter.GainHF;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2007-12-18 21:37:07 +00:00
|
|
|
if(ALSource->AirAbsorptionFactor > 0.0f)
|
|
|
|
DryGainHF *= pow(ALSource->AirAbsorptionFactor * AIRABSORBGAINHF,
|
|
|
|
Distance * MetersPerUnit);
|
|
|
|
|
Implement AL_EFFECT_REVERB
Here is a quick description of how the reverb effect works:
+--->---+*(4)
| V new sample
+-----+---+---+ |
|extra|ltr|ref| <- +*(1)
+-----+---+---+
(3,5)*| |*(2)
+-->|
V
out sample
1) Apply master reverb gain to incoming sample and place it at the head of the
buffer. The master reverb gainhf was already applied when the source was
initially mixed.
2) Copy the delayed reflection sample to an output sample and apply the
reflection gain.
3) Apply the late reverb gain to the late reverb sample
4) Copy the end of the buffer, applying a decay gain and the decay hf ratio,
and add to the late reverb.
5) Copy the late reverb sample, adding to the output sample.
Then the head and sampling points are shifted forward, and done again for each
new sample. The extra buffer length is determined by the Reverb Density
property. A value of 0 gives a length of 0.1 seconds (long, with fairly
distinct echos) , and 1 gives 0.075 seconds (short, indistinct echos).
The decay gain is calculated such that after a number of loops to satisfy the
Decay Time, a sample will be 1/32768th as powerful (virtually insignificant to
the resulting output, and only getting further reduced). It is calculated as:
DecayGain = pow(1.0f/32768.0f, 1.0/(DecayTime/ExtraLength));
Things to note: Reverb Diffusion is not currently handled, nor is Decay HF
Limit. Decay HF Ratios above 1 probably give incorrect results. Also, this
method likely sucks, but it's the best I can come up with before release. :)
2008-01-19 05:25:40 +00:00
|
|
|
if(ALSource->Send[0].Slot)
|
|
|
|
{
|
|
|
|
WetMix *= ALSource->Send[0].Slot->Gain;
|
|
|
|
|
|
|
|
if(ALSource->Send[0].Slot->effect.type == AL_EFFECT_REVERB)
|
|
|
|
{
|
|
|
|
WetGainHF *= ALSource->Send[0].Slot->effect.Reverb.GainHF;
|
|
|
|
WetGainHF *= pow(ALSource->Send[0].Slot->effect.Reverb.AirAbsorptionGainHF,
|
|
|
|
Distance * MetersPerUnit);
|
|
|
|
}
|
|
|
|
}
|
2008-01-19 05:39:09 +00:00
|
|
|
else
|
|
|
|
{
|
|
|
|
WetMix = 0.0f;
|
|
|
|
WetGainHF = 1.0f;
|
|
|
|
}
|
Implement AL_EFFECT_REVERB
Here is a quick description of how the reverb effect works:
+--->---+*(4)
| V new sample
+-----+---+---+ |
|extra|ltr|ref| <- +*(1)
+-----+---+---+
(3,5)*| |*(2)
+-->|
V
out sample
1) Apply master reverb gain to incoming sample and place it at the head of the
buffer. The master reverb gainhf was already applied when the source was
initially mixed.
2) Copy the delayed reflection sample to an output sample and apply the
reflection gain.
3) Apply the late reverb gain to the late reverb sample
4) Copy the end of the buffer, applying a decay gain and the decay hf ratio,
and add to the late reverb.
5) Copy the late reverb sample, adding to the output sample.
Then the head and sampling points are shifted forward, and done again for each
new sample. The extra buffer length is determined by the Reverb Density
property. A value of 0 gives a length of 0.1 seconds (long, with fairly
distinct echos) , and 1 gives 0.075 seconds (short, indistinct echos).
The decay gain is calculated such that after a number of loops to satisfy the
Decay Time, a sample will be 1/32768th as powerful (virtually insignificant to
the resulting output, and only getting further reduced). It is calculated as:
DecayGain = pow(1.0f/32768.0f, 1.0/(DecayTime/ExtraLength));
Things to note: Reverb Diffusion is not currently handled, nor is Decay HF
Limit. Decay HF Ratios above 1 probably give incorrect results. Also, this
method likely sucks, but it's the best I can come up with before release. :)
2008-01-19 05:25:40 +00:00
|
|
|
|
2008-01-19 08:49:05 +00:00
|
|
|
DryMix *= ListenerGain * ConeVolume;
|
|
|
|
WetMix *= ListenerGain;
|
|
|
|
|
2008-05-18 23:52:38 +00:00
|
|
|
//6. Convert normalized position into pannings, then into channel volumes
|
2007-12-21 05:40:22 +00:00
|
|
|
aluNormalize(Position);
|
2007-12-27 07:29:32 +00:00
|
|
|
switch(aluChannelsFromFormat(OutputFormat))
|
2007-11-14 02:02:18 +00:00
|
|
|
{
|
2007-12-27 07:29:32 +00:00
|
|
|
case 1:
|
2008-01-19 08:49:05 +00:00
|
|
|
drysend[FRONT_LEFT] = DryMix * aluSqrt(1.0f); //Direct
|
|
|
|
drysend[FRONT_RIGHT] = DryMix * aluSqrt(1.0f); //Direct
|
|
|
|
wetsend[FRONT_LEFT] = WetMix * aluSqrt(1.0f); //Room
|
|
|
|
wetsend[FRONT_RIGHT] = WetMix * aluSqrt(1.0f); //Room
|
2007-11-14 02:02:18 +00:00
|
|
|
break;
|
2007-12-27 07:29:32 +00:00
|
|
|
case 2:
|
2007-12-21 05:40:22 +00:00
|
|
|
PanningLR = 0.5f + 0.5f*Position[0];
|
2008-01-19 08:49:05 +00:00
|
|
|
drysend[FRONT_LEFT] = DryMix * aluSqrt(1.0f-PanningLR); //L Direct
|
|
|
|
drysend[FRONT_RIGHT] = DryMix * aluSqrt( PanningLR); //R Direct
|
|
|
|
wetsend[FRONT_LEFT] = WetMix * aluSqrt(1.0f-PanningLR); //L Room
|
|
|
|
wetsend[FRONT_RIGHT] = WetMix * aluSqrt( PanningLR); //R Room
|
2007-11-14 02:02:18 +00:00
|
|
|
break;
|
2007-12-27 07:29:32 +00:00
|
|
|
case 4:
|
2007-12-27 07:01:22 +00:00
|
|
|
/* TODO: Add center/lfe channel in spatial calculations? */
|
2007-12-27 07:29:32 +00:00
|
|
|
case 6:
|
2007-12-21 05:40:22 +00:00
|
|
|
// Apply a scalar so each individual speaker has more weight
|
|
|
|
PanningLR = 0.5f + (0.5f*Position[0]*1.41421356f);
|
|
|
|
PanningLR = __min(1.0f, PanningLR);
|
|
|
|
PanningLR = __max(0.0f, PanningLR);
|
|
|
|
PanningFB = 0.5f + (0.5f*Position[2]*1.41421356f);
|
|
|
|
PanningFB = __min(1.0f, PanningFB);
|
|
|
|
PanningFB = __max(0.0f, PanningFB);
|
2008-01-19 08:49:05 +00:00
|
|
|
drysend[FRONT_LEFT] = DryMix * aluSqrt((1.0f-PanningLR)*(1.0f-PanningFB));
|
|
|
|
drysend[FRONT_RIGHT] = DryMix * aluSqrt(( PanningLR)*(1.0f-PanningFB));
|
|
|
|
drysend[BACK_LEFT] = DryMix * aluSqrt((1.0f-PanningLR)*( PanningFB));
|
|
|
|
drysend[BACK_RIGHT] = DryMix * aluSqrt(( PanningLR)*( PanningFB));
|
|
|
|
wetsend[FRONT_LEFT] = WetMix * aluSqrt((1.0f-PanningLR)*(1.0f-PanningFB));
|
|
|
|
wetsend[FRONT_RIGHT] = WetMix * aluSqrt(( PanningLR)*(1.0f-PanningFB));
|
|
|
|
wetsend[BACK_LEFT] = WetMix * aluSqrt((1.0f-PanningLR)*( PanningFB));
|
|
|
|
wetsend[BACK_RIGHT] = WetMix * aluSqrt(( PanningLR)*( PanningFB));
|
2007-11-14 02:02:18 +00:00
|
|
|
break;
|
2008-01-04 22:15:55 +00:00
|
|
|
case 7:
|
|
|
|
case 8:
|
|
|
|
PanningFB = 1.0f - fabs(Position[2]*1.15470054f);
|
|
|
|
PanningFB = __min(1.0f, PanningFB);
|
|
|
|
PanningFB = __max(0.0f, PanningFB);
|
|
|
|
PanningLR = 0.5f + (0.5*Position[0]*((1.0f-PanningFB)*2.0f));
|
|
|
|
PanningLR = __min(1.0f, PanningLR);
|
|
|
|
PanningLR = __max(0.0f, PanningLR);
|
|
|
|
if(Position[2] > 0.0f)
|
|
|
|
{
|
2008-01-19 08:49:05 +00:00
|
|
|
drysend[BACK_LEFT] = DryMix * aluSqrt((1.0f-PanningLR)*(1.0f-PanningFB));
|
|
|
|
drysend[BACK_RIGHT] = DryMix * aluSqrt(( PanningLR)*(1.0f-PanningFB));
|
|
|
|
drysend[SIDE_LEFT] = DryMix * aluSqrt((1.0f-PanningLR)*( PanningFB));
|
|
|
|
drysend[SIDE_RIGHT] = DryMix * aluSqrt(( PanningLR)*( PanningFB));
|
2008-01-04 22:15:55 +00:00
|
|
|
drysend[FRONT_LEFT] = 0.0f;
|
|
|
|
drysend[FRONT_RIGHT] = 0.0f;
|
2008-01-19 08:49:05 +00:00
|
|
|
wetsend[BACK_LEFT] = WetMix * aluSqrt((1.0f-PanningLR)*(1.0f-PanningFB));
|
|
|
|
wetsend[BACK_RIGHT] = WetMix * aluSqrt(( PanningLR)*(1.0f-PanningFB));
|
|
|
|
wetsend[SIDE_LEFT] = WetMix * aluSqrt((1.0f-PanningLR)*( PanningFB));
|
|
|
|
wetsend[SIDE_RIGHT] = WetMix * aluSqrt(( PanningLR)*( PanningFB));
|
2008-01-19 05:39:09 +00:00
|
|
|
wetsend[FRONT_LEFT] = 0.0f;
|
|
|
|
wetsend[FRONT_RIGHT] = 0.0f;
|
2008-01-04 22:15:55 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2008-01-19 08:49:05 +00:00
|
|
|
drysend[FRONT_LEFT] = DryMix * aluSqrt((1.0f-PanningLR)*(1.0f-PanningFB));
|
|
|
|
drysend[FRONT_RIGHT] = DryMix * aluSqrt(( PanningLR)*(1.0f-PanningFB));
|
|
|
|
drysend[SIDE_LEFT] = DryMix * aluSqrt((1.0f-PanningLR)*( PanningFB));
|
|
|
|
drysend[SIDE_RIGHT] = DryMix * aluSqrt(( PanningLR)*( PanningFB));
|
2008-01-04 22:15:55 +00:00
|
|
|
drysend[BACK_LEFT] = 0.0f;
|
|
|
|
drysend[BACK_RIGHT] = 0.0f;
|
2008-01-19 08:49:05 +00:00
|
|
|
wetsend[FRONT_LEFT] = WetMix * aluSqrt((1.0f-PanningLR)*(1.0f-PanningFB));
|
|
|
|
wetsend[FRONT_RIGHT] = WetMix * aluSqrt(( PanningLR)*(1.0f-PanningFB));
|
|
|
|
wetsend[SIDE_LEFT] = WetMix * aluSqrt((1.0f-PanningLR)*( PanningFB));
|
|
|
|
wetsend[SIDE_RIGHT] = WetMix * aluSqrt(( PanningLR)*( PanningFB));
|
2008-01-19 05:39:09 +00:00
|
|
|
wetsend[BACK_LEFT] = 0.0f;
|
|
|
|
wetsend[BACK_RIGHT] = 0.0f;
|
2008-01-04 22:15:55 +00:00
|
|
|
}
|
2007-11-14 02:02:18 +00:00
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
2008-01-12 15:36:22 +00:00
|
|
|
|
|
|
|
*drygainhf = DryGainHF;
|
|
|
|
*wetgainhf = WetGainHF;
|
2007-11-14 02:02:18 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
//1. Multi-channel buffers always play "normal"
|
2008-01-16 05:57:50 +00:00
|
|
|
pitch[0] = ALSource->flPitch;
|
2008-01-19 08:49:05 +00:00
|
|
|
|
|
|
|
drysend[FRONT_LEFT] = SourceVolume * ListenerGain;
|
|
|
|
drysend[FRONT_RIGHT] = SourceVolume * ListenerGain;
|
|
|
|
drysend[SIDE_LEFT] = SourceVolume * ListenerGain;
|
|
|
|
drysend[SIDE_RIGHT] = SourceVolume * ListenerGain;
|
|
|
|
drysend[BACK_LEFT] = SourceVolume * ListenerGain;
|
|
|
|
drysend[BACK_RIGHT] = SourceVolume * ListenerGain;
|
|
|
|
drysend[CENTER] = SourceVolume * ListenerGain;
|
|
|
|
drysend[LFE] = SourceVolume * ListenerGain;
|
|
|
|
wetsend[FRONT_LEFT] = 0.0f;
|
|
|
|
wetsend[FRONT_RIGHT] = 0.0f;
|
|
|
|
wetsend[SIDE_LEFT] = 0.0f;
|
|
|
|
wetsend[SIDE_RIGHT] = 0.0f;
|
|
|
|
wetsend[BACK_LEFT] = 0.0f;
|
|
|
|
wetsend[BACK_RIGHT] = 0.0f;
|
|
|
|
wetsend[CENTER] = 0.0f;
|
|
|
|
wetsend[LFE] = 0.0f;
|
|
|
|
WetGainHF = 1.0f;
|
|
|
|
|
|
|
|
*drygainhf = DryGainHF;
|
|
|
|
*wetgainhf = WetGainHF;
|
2007-11-14 02:02:18 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
ALvoid aluMixData(ALCcontext *ALContext,ALvoid *buffer,ALsizei size,ALenum format)
|
|
|
|
{
|
|
|
|
static float DryBuffer[BUFFERSIZE][OUTPUTCHANNELS];
|
|
|
|
static float WetBuffer[BUFFERSIZE][OUTPUTCHANNELS];
|
Implement AL_EFFECT_REVERB
Here is a quick description of how the reverb effect works:
+--->---+*(4)
| V new sample
+-----+---+---+ |
|extra|ltr|ref| <- +*(1)
+-----+---+---+
(3,5)*| |*(2)
+-->|
V
out sample
1) Apply master reverb gain to incoming sample and place it at the head of the
buffer. The master reverb gainhf was already applied when the source was
initially mixed.
2) Copy the delayed reflection sample to an output sample and apply the
reflection gain.
3) Apply the late reverb gain to the late reverb sample
4) Copy the end of the buffer, applying a decay gain and the decay hf ratio,
and add to the late reverb.
5) Copy the late reverb sample, adding to the output sample.
Then the head and sampling points are shifted forward, and done again for each
new sample. The extra buffer length is determined by the Reverb Density
property. A value of 0 gives a length of 0.1 seconds (long, with fairly
distinct echos) , and 1 gives 0.075 seconds (short, indistinct echos).
The decay gain is calculated such that after a number of loops to satisfy the
Decay Time, a sample will be 1/32768th as powerful (virtually insignificant to
the resulting output, and only getting further reduced). It is calculated as:
DecayGain = pow(1.0f/32768.0f, 1.0/(DecayTime/ExtraLength));
Things to note: Reverb Diffusion is not currently handled, nor is Decay HF
Limit. Decay HF Ratios above 1 probably give incorrect results. Also, this
method likely sucks, but it's the best I can come up with before release. :)
2008-01-19 05:25:40 +00:00
|
|
|
static float ReverbBuffer[BUFFERSIZE];
|
2007-12-31 11:29:14 +00:00
|
|
|
ALfloat DrySend[OUTPUTCHANNELS] = { 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f };
|
|
|
|
ALfloat WetSend[OUTPUTCHANNELS] = { 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f };
|
2007-12-18 05:00:52 +00:00
|
|
|
ALfloat DryGainHF = 0.0f;
|
|
|
|
ALfloat WetGainHF = 0.0f;
|
2007-11-14 02:02:18 +00:00
|
|
|
ALuint BlockAlign,BufferSize;
|
|
|
|
ALuint DataSize=0,DataPosInt=0,DataPosFrac=0;
|
2008-01-16 05:57:50 +00:00
|
|
|
ALuint Channels,Frequency,ulExtraSamples;
|
Implement AL_EFFECT_REVERB
Here is a quick description of how the reverb effect works:
+--->---+*(4)
| V new sample
+-----+---+---+ |
|extra|ltr|ref| <- +*(1)
+-----+---+---+
(3,5)*| |*(2)
+-->|
V
out sample
1) Apply master reverb gain to incoming sample and place it at the head of the
buffer. The master reverb gainhf was already applied when the source was
initially mixed.
2) Copy the delayed reflection sample to an output sample and apply the
reflection gain.
3) Apply the late reverb gain to the late reverb sample
4) Copy the end of the buffer, applying a decay gain and the decay hf ratio,
and add to the late reverb.
5) Copy the late reverb sample, adding to the output sample.
Then the head and sampling points are shifted forward, and done again for each
new sample. The extra buffer length is determined by the Reverb Density
property. A value of 0 gives a length of 0.1 seconds (long, with fairly
distinct echos) , and 1 gives 0.075 seconds (short, indistinct echos).
The decay gain is calculated such that after a number of loops to satisfy the
Decay Time, a sample will be 1/32768th as powerful (virtually insignificant to
the resulting output, and only getting further reduced). It is calculated as:
DecayGain = pow(1.0f/32768.0f, 1.0/(DecayTime/ExtraLength));
Things to note: Reverb Diffusion is not currently handled, nor is Decay HF
Limit. Decay HF Ratios above 1 probably give incorrect results. Also, this
method likely sucks, but it's the best I can come up with before release. :)
2008-01-19 05:25:40 +00:00
|
|
|
ALboolean doReverb;
|
2007-11-14 02:02:18 +00:00
|
|
|
ALfloat Pitch;
|
2008-07-24 05:29:53 +00:00
|
|
|
ALint Looping,State;
|
|
|
|
ALint fraction,increment;
|
|
|
|
ALint LowFrac;
|
|
|
|
ALuint LowStep;
|
|
|
|
ALuint Buffer;
|
2007-11-14 02:02:18 +00:00
|
|
|
ALuint SamplesToDo;
|
|
|
|
ALsource *ALSource;
|
|
|
|
ALbuffer *ALBuffer;
|
Implement AL_EFFECT_REVERB
Here is a quick description of how the reverb effect works:
+--->---+*(4)
| V new sample
+-----+---+---+ |
|extra|ltr|ref| <- +*(1)
+-----+---+---+
(3,5)*| |*(2)
+-->|
V
out sample
1) Apply master reverb gain to incoming sample and place it at the head of the
buffer. The master reverb gainhf was already applied when the source was
initially mixed.
2) Copy the delayed reflection sample to an output sample and apply the
reflection gain.
3) Apply the late reverb gain to the late reverb sample
4) Copy the end of the buffer, applying a decay gain and the decay hf ratio,
and add to the late reverb.
5) Copy the late reverb sample, adding to the output sample.
Then the head and sampling points are shifted forward, and done again for each
new sample. The extra buffer length is determined by the Reverb Density
property. A value of 0 gives a length of 0.1 seconds (long, with fairly
distinct echos) , and 1 gives 0.075 seconds (short, indistinct echos).
The decay gain is calculated such that after a number of loops to satisfy the
Decay Time, a sample will be 1/32768th as powerful (virtually insignificant to
the resulting output, and only getting further reduced). It is calculated as:
DecayGain = pow(1.0f/32768.0f, 1.0/(DecayTime/ExtraLength));
Things to note: Reverb Diffusion is not currently handled, nor is Decay HF
Limit. Decay HF Ratios above 1 probably give incorrect results. Also, this
method likely sucks, but it's the best I can come up with before release. :)
2008-01-19 05:25:40 +00:00
|
|
|
ALeffectslot *ALEffectSlot;
|
2007-11-14 02:02:18 +00:00
|
|
|
ALfloat value;
|
|
|
|
ALshort *Data;
|
|
|
|
ALuint i,j,k;
|
|
|
|
ALbufferlistitem *BufferListItem;
|
|
|
|
ALuint loop;
|
|
|
|
ALint64 DataSize64,DataPos64;
|
|
|
|
|
|
|
|
SuspendContext(ALContext);
|
|
|
|
|
2008-01-21 22:54:15 +00:00
|
|
|
//Figure output format variables
|
|
|
|
BlockAlign = aluChannelsFromFormat(format);
|
|
|
|
BlockAlign *= aluBytesFromFormat(format);
|
2007-11-14 02:02:18 +00:00
|
|
|
|
2008-01-21 22:54:15 +00:00
|
|
|
size /= BlockAlign;
|
|
|
|
while(size > 0)
|
|
|
|
{
|
|
|
|
//Setup variables
|
|
|
|
ALEffectSlot = (ALContext ? ALContext->AuxiliaryEffectSlot : NULL);
|
|
|
|
ALSource = (ALContext ? ALContext->Source : NULL);
|
|
|
|
SamplesToDo = min(size, BUFFERSIZE);
|
|
|
|
|
|
|
|
//Clear mixing buffer
|
|
|
|
memset(DryBuffer, 0, SamplesToDo*OUTPUTCHANNELS*sizeof(ALfloat));
|
|
|
|
memset(WetBuffer, 0, SamplesToDo*OUTPUTCHANNELS*sizeof(ALfloat));
|
|
|
|
memset(ReverbBuffer, 0, SamplesToDo*sizeof(ALfloat));
|
|
|
|
|
|
|
|
//Actual mixing loop
|
|
|
|
while(ALSource)
|
2007-11-14 02:02:18 +00:00
|
|
|
{
|
2008-01-21 22:54:15 +00:00
|
|
|
j = 0;
|
|
|
|
State = ALSource->state;
|
Implement AL_EFFECT_REVERB
Here is a quick description of how the reverb effect works:
+--->---+*(4)
| V new sample
+-----+---+---+ |
|extra|ltr|ref| <- +*(1)
+-----+---+---+
(3,5)*| |*(2)
+-->|
V
out sample
1) Apply master reverb gain to incoming sample and place it at the head of the
buffer. The master reverb gainhf was already applied when the source was
initially mixed.
2) Copy the delayed reflection sample to an output sample and apply the
reflection gain.
3) Apply the late reverb gain to the late reverb sample
4) Copy the end of the buffer, applying a decay gain and the decay hf ratio,
and add to the late reverb.
5) Copy the late reverb sample, adding to the output sample.
Then the head and sampling points are shifted forward, and done again for each
new sample. The extra buffer length is determined by the Reverb Density
property. A value of 0 gives a length of 0.1 seconds (long, with fairly
distinct echos) , and 1 gives 0.075 seconds (short, indistinct echos).
The decay gain is calculated such that after a number of loops to satisfy the
Decay Time, a sample will be 1/32768th as powerful (virtually insignificant to
the resulting output, and only getting further reduced). It is calculated as:
DecayGain = pow(1.0f/32768.0f, 1.0/(DecayTime/ExtraLength));
Things to note: Reverb Diffusion is not currently handled, nor is Decay HF
Limit. Decay HF Ratios above 1 probably give incorrect results. Also, this
method likely sucks, but it's the best I can come up with before release. :)
2008-01-19 05:25:40 +00:00
|
|
|
|
2008-01-21 22:54:15 +00:00
|
|
|
doReverb = ((ALSource->Send[0].Slot &&
|
|
|
|
ALSource->Send[0].Slot->effect.type == AL_EFFECT_REVERB) ?
|
|
|
|
AL_TRUE : AL_FALSE);
|
Implement AL_EFFECT_REVERB
Here is a quick description of how the reverb effect works:
+--->---+*(4)
| V new sample
+-----+---+---+ |
|extra|ltr|ref| <- +*(1)
+-----+---+---+
(3,5)*| |*(2)
+-->|
V
out sample
1) Apply master reverb gain to incoming sample and place it at the head of the
buffer. The master reverb gainhf was already applied when the source was
initially mixed.
2) Copy the delayed reflection sample to an output sample and apply the
reflection gain.
3) Apply the late reverb gain to the late reverb sample
4) Copy the end of the buffer, applying a decay gain and the decay hf ratio,
and add to the late reverb.
5) Copy the late reverb sample, adding to the output sample.
Then the head and sampling points are shifted forward, and done again for each
new sample. The extra buffer length is determined by the Reverb Density
property. A value of 0 gives a length of 0.1 seconds (long, with fairly
distinct echos) , and 1 gives 0.075 seconds (short, indistinct echos).
The decay gain is calculated such that after a number of loops to satisfy the
Decay Time, a sample will be 1/32768th as powerful (virtually insignificant to
the resulting output, and only getting further reduced). It is calculated as:
DecayGain = pow(1.0f/32768.0f, 1.0/(DecayTime/ExtraLength));
Things to note: Reverb Diffusion is not currently handled, nor is Decay HF
Limit. Decay HF Ratios above 1 probably give incorrect results. Also, this
method likely sucks, but it's the best I can come up with before release. :)
2008-01-19 05:25:40 +00:00
|
|
|
|
2008-01-21 22:54:15 +00:00
|
|
|
while(State == AL_PLAYING && j < SamplesToDo)
|
|
|
|
{
|
|
|
|
DataSize = 0;
|
|
|
|
DataPosInt = 0;
|
|
|
|
DataPosFrac = 0;
|
2007-11-14 02:02:18 +00:00
|
|
|
|
2008-01-21 22:54:15 +00:00
|
|
|
//Get buffer info
|
|
|
|
if((Buffer = ALSource->ulBufferID))
|
|
|
|
{
|
|
|
|
ALBuffer = (ALbuffer*)ALTHUNK_LOOKUPENTRY(Buffer);
|
|
|
|
|
|
|
|
Data = ALBuffer->data;
|
|
|
|
Channels = aluChannelsFromFormat(ALBuffer->format);
|
|
|
|
DataSize = ALBuffer->size;
|
|
|
|
Frequency = ALBuffer->frequency;
|
|
|
|
|
|
|
|
CalcSourceParams(ALContext, ALSource,
|
|
|
|
(Channels==1) ? AL_TRUE : AL_FALSE,
|
|
|
|
format, DrySend, WetSend, &Pitch,
|
|
|
|
&DryGainHF, &WetGainHF);
|
|
|
|
|
|
|
|
|
|
|
|
Pitch = (Pitch*Frequency) / ALContext->Frequency;
|
|
|
|
DataSize /= Channels * aluBytesFromFormat(ALBuffer->format);
|
|
|
|
|
|
|
|
//Get source info
|
|
|
|
DataPosInt = ALSource->position;
|
|
|
|
DataPosFrac = ALSource->position_fraction;
|
|
|
|
|
|
|
|
//Compute 18.14 fixed point step
|
2008-02-09 05:03:48 +00:00
|
|
|
increment = (ALint)(Pitch*(ALfloat)(1L<<FRACTIONBITS));
|
2008-01-21 22:54:15 +00:00
|
|
|
if(increment > (MAX_PITCH<<FRACTIONBITS))
|
|
|
|
increment = (MAX_PITCH<<FRACTIONBITS);
|
|
|
|
|
|
|
|
//Figure out how many samples we can mix.
|
2008-07-24 06:27:38 +00:00
|
|
|
DataSize64 = DataSize;
|
2008-01-21 22:54:15 +00:00
|
|
|
DataSize64 <<= FRACTIONBITS;
|
|
|
|
DataPos64 = DataPosInt;
|
|
|
|
DataPos64 <<= FRACTIONBITS;
|
|
|
|
DataPos64 += DataPosFrac;
|
2008-07-24 06:27:38 +00:00
|
|
|
BufferSize = (ALuint)((DataSize64-DataPos64+(increment-1)) / increment);
|
2008-01-21 22:54:15 +00:00
|
|
|
BufferListItem = ALSource->queue;
|
|
|
|
for(loop = 0; loop < ALSource->BuffersPlayed; loop++)
|
2007-11-14 02:02:18 +00:00
|
|
|
{
|
2008-01-21 22:54:15 +00:00
|
|
|
if(BufferListItem)
|
|
|
|
BufferListItem = BufferListItem->next;
|
|
|
|
}
|
|
|
|
if (BufferListItem)
|
|
|
|
{
|
|
|
|
if (BufferListItem->next)
|
2007-11-14 02:02:18 +00:00
|
|
|
{
|
2008-01-21 22:54:15 +00:00
|
|
|
ALbuffer *NextBuf = (ALbuffer*)ALTHUNK_LOOKUPENTRY(BufferListItem->next->buffer);
|
|
|
|
if(NextBuf && NextBuf->data)
|
2007-11-14 02:02:18 +00:00
|
|
|
{
|
2008-01-21 22:54:15 +00:00
|
|
|
ulExtraSamples = min(NextBuf->size, (ALint)(16*Channels));
|
|
|
|
memcpy(&Data[DataSize*Channels], NextBuf->data, ulExtraSamples);
|
2007-11-14 02:02:18 +00:00
|
|
|
}
|
2008-01-21 22:54:15 +00:00
|
|
|
}
|
|
|
|
else if (ALSource->bLooping)
|
|
|
|
{
|
|
|
|
ALbuffer *NextBuf = (ALbuffer*)ALTHUNK_LOOKUPENTRY(ALSource->queue->buffer);
|
|
|
|
if (NextBuf && NextBuf->data)
|
2007-11-14 02:02:18 +00:00
|
|
|
{
|
2008-01-21 22:54:15 +00:00
|
|
|
ulExtraSamples = min(NextBuf->size, (ALint)(16*Channels));
|
|
|
|
memcpy(&Data[DataSize*Channels], NextBuf->data, ulExtraSamples);
|
2007-11-14 02:02:18 +00:00
|
|
|
}
|
|
|
|
}
|
2008-01-21 22:54:15 +00:00
|
|
|
}
|
|
|
|
BufferSize = min(BufferSize, (SamplesToDo-j));
|
2007-11-14 02:02:18 +00:00
|
|
|
|
2008-01-21 22:54:15 +00:00
|
|
|
//Actual sample mixing loop
|
2008-07-24 05:29:53 +00:00
|
|
|
LowStep = Frequency/5000;
|
|
|
|
if(LowStep < 1) LowStep = 1;
|
|
|
|
if(LowStep > 8) LowStep = 8;
|
2008-01-21 22:54:15 +00:00
|
|
|
Data += DataPosInt*Channels;
|
|
|
|
while(BufferSize--)
|
|
|
|
{
|
|
|
|
k = DataPosFrac>>FRACTIONBITS;
|
|
|
|
fraction = DataPosFrac&FRACTIONMASK;
|
2008-07-24 05:29:53 +00:00
|
|
|
LowFrac = ((DataPosFrac+(DataPosInt<<FRACTIONBITS))/LowStep)&FRACTIONMASK;
|
2008-01-21 22:54:15 +00:00
|
|
|
if(Channels==1)
|
2007-11-14 02:02:18 +00:00
|
|
|
{
|
2008-07-24 05:29:53 +00:00
|
|
|
ALfloat sample, lowsamp, outsamp;
|
2008-01-21 22:54:15 +00:00
|
|
|
//First order interpolator
|
2008-07-24 05:29:53 +00:00
|
|
|
sample = (Data[k]*((1<<FRACTIONBITS)-fraction) +
|
|
|
|
Data[k+1]*fraction) >> FRACTIONBITS;
|
|
|
|
lowsamp = (Data[((k+DataPosInt)/LowStep )*LowStep - DataPosInt]*((1<<FRACTIONBITS)-LowFrac) +
|
|
|
|
Data[((k+DataPosInt)/LowStep + 1)*LowStep - DataPosInt]*LowFrac) >>
|
|
|
|
FRACTIONBITS;
|
2008-01-21 22:54:15 +00:00
|
|
|
|
|
|
|
//Direct path final mix buffer and panning
|
2008-07-24 05:29:53 +00:00
|
|
|
outsamp = aluComputeSample(DryGainHF, sample, lowsamp);
|
|
|
|
DryBuffer[j][FRONT_LEFT] += outsamp*DrySend[FRONT_LEFT];
|
|
|
|
DryBuffer[j][FRONT_RIGHT] += outsamp*DrySend[FRONT_RIGHT];
|
|
|
|
DryBuffer[j][SIDE_LEFT] += outsamp*DrySend[SIDE_LEFT];
|
|
|
|
DryBuffer[j][SIDE_RIGHT] += outsamp*DrySend[SIDE_RIGHT];
|
|
|
|
DryBuffer[j][BACK_LEFT] += outsamp*DrySend[BACK_LEFT];
|
|
|
|
DryBuffer[j][BACK_RIGHT] += outsamp*DrySend[BACK_RIGHT];
|
2008-01-21 22:54:15 +00:00
|
|
|
//Room path final mix buffer and panning
|
2008-07-24 05:29:53 +00:00
|
|
|
outsamp = aluComputeSample(WetGainHF, sample, lowsamp);
|
2008-01-21 22:54:15 +00:00
|
|
|
if(doReverb)
|
2008-07-24 05:29:53 +00:00
|
|
|
ReverbBuffer[j] += outsamp;
|
2008-01-21 22:54:15 +00:00
|
|
|
else
|
2007-11-14 02:02:18 +00:00
|
|
|
{
|
2008-07-24 05:29:53 +00:00
|
|
|
WetBuffer[j][FRONT_LEFT] += outsamp*WetSend[FRONT_LEFT];
|
|
|
|
WetBuffer[j][FRONT_RIGHT] += outsamp*WetSend[FRONT_RIGHT];
|
|
|
|
WetBuffer[j][SIDE_LEFT] += outsamp*WetSend[SIDE_LEFT];
|
|
|
|
WetBuffer[j][SIDE_RIGHT] += outsamp*WetSend[SIDE_RIGHT];
|
|
|
|
WetBuffer[j][BACK_LEFT] += outsamp*WetSend[BACK_LEFT];
|
|
|
|
WetBuffer[j][BACK_RIGHT] += outsamp*WetSend[BACK_RIGHT];
|
2007-11-14 02:02:18 +00:00
|
|
|
}
|
2008-01-21 22:54:15 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2008-02-07 06:18:50 +00:00
|
|
|
ALfloat samp1, samp2;
|
2008-01-21 22:54:15 +00:00
|
|
|
//First order interpolator (front left)
|
2008-02-07 06:18:50 +00:00
|
|
|
samp1 = (ALfloat)((ALshort)(((Data[k*Channels ]*((1L<<FRACTIONBITS)-fraction))+(Data[(k+1)*Channels ]*(fraction)))>>FRACTIONBITS));
|
|
|
|
DryBuffer[j][FRONT_LEFT] += samp1*DrySend[FRONT_LEFT];
|
|
|
|
WetBuffer[j][FRONT_LEFT] += samp1*WetSend[FRONT_LEFT];
|
2008-01-21 22:54:15 +00:00
|
|
|
//First order interpolator (front right)
|
2008-02-07 06:18:50 +00:00
|
|
|
samp2 = (ALfloat)((ALshort)(((Data[k*Channels+1]*((1L<<FRACTIONBITS)-fraction))+(Data[(k+1)*Channels+1]*(fraction)))>>FRACTIONBITS));
|
|
|
|
DryBuffer[j][FRONT_RIGHT] += samp2*DrySend[FRONT_RIGHT];
|
|
|
|
WetBuffer[j][FRONT_RIGHT] += samp2*WetSend[FRONT_RIGHT];
|
2008-01-21 22:54:15 +00:00
|
|
|
if(Channels >= 4)
|
2007-11-14 02:02:18 +00:00
|
|
|
{
|
2008-01-21 22:54:15 +00:00
|
|
|
int i = 2;
|
|
|
|
if(Channels >= 6)
|
2007-12-31 12:50:34 +00:00
|
|
|
{
|
2008-01-21 22:54:15 +00:00
|
|
|
if(Channels != 7)
|
2007-12-31 12:50:34 +00:00
|
|
|
{
|
2008-01-21 22:54:15 +00:00
|
|
|
//First order interpolator (center)
|
2007-12-31 12:50:34 +00:00
|
|
|
value = (ALfloat)((ALshort)(((Data[k*Channels+i]*((1L<<FRACTIONBITS)-fraction))+(Data[(k+1)*Channels+i]*(fraction)))>>FRACTIONBITS));
|
2008-01-21 22:54:15 +00:00
|
|
|
DryBuffer[j][CENTER] += value*DrySend[CENTER];
|
|
|
|
WetBuffer[j][CENTER] += value*WetSend[CENTER];
|
2008-01-01 14:16:19 +00:00
|
|
|
i++;
|
|
|
|
}
|
2008-01-21 22:54:15 +00:00
|
|
|
//First order interpolator (lfe)
|
2008-01-01 14:16:19 +00:00
|
|
|
value = (ALfloat)((ALshort)(((Data[k*Channels+i]*((1L<<FRACTIONBITS)-fraction))+(Data[(k+1)*Channels+i]*(fraction)))>>FRACTIONBITS));
|
2008-01-21 22:54:15 +00:00
|
|
|
DryBuffer[j][LFE] += value*DrySend[LFE];
|
|
|
|
WetBuffer[j][LFE] += value*WetSend[LFE];
|
2008-01-01 14:16:19 +00:00
|
|
|
i++;
|
2008-01-21 22:54:15 +00:00
|
|
|
}
|
|
|
|
//First order interpolator (back left)
|
|
|
|
value = (ALfloat)((ALshort)(((Data[k*Channels+i]*((1L<<FRACTIONBITS)-fraction))+(Data[(k+1)*Channels+i]*(fraction)))>>FRACTIONBITS));
|
|
|
|
DryBuffer[j][BACK_LEFT] += value*DrySend[BACK_LEFT];
|
|
|
|
WetBuffer[j][BACK_LEFT] += value*WetSend[BACK_LEFT];
|
|
|
|
i++;
|
|
|
|
//First order interpolator (back right)
|
|
|
|
value = (ALfloat)((ALshort)(((Data[k*Channels+i]*((1L<<FRACTIONBITS)-fraction))+(Data[(k+1)*Channels+i]*(fraction)))>>FRACTIONBITS));
|
|
|
|
DryBuffer[j][BACK_RIGHT] += value*DrySend[BACK_RIGHT];
|
|
|
|
WetBuffer[j][BACK_RIGHT] += value*WetSend[BACK_RIGHT];
|
|
|
|
i++;
|
|
|
|
if(Channels >= 7)
|
|
|
|
{
|
|
|
|
//First order interpolator (side left)
|
2008-01-01 14:16:19 +00:00
|
|
|
value = (ALfloat)((ALshort)(((Data[k*Channels+i]*((1L<<FRACTIONBITS)-fraction))+(Data[(k+1)*Channels+i]*(fraction)))>>FRACTIONBITS));
|
2008-01-21 22:54:15 +00:00
|
|
|
DryBuffer[j][SIDE_LEFT] += value*DrySend[SIDE_LEFT];
|
|
|
|
WetBuffer[j][SIDE_LEFT] += value*WetSend[SIDE_LEFT];
|
|
|
|
i++;
|
|
|
|
//First order interpolator (side right)
|
|
|
|
value = (ALfloat)((ALshort)(((Data[k*Channels+i]*((1L<<FRACTIONBITS)-fraction))+(Data[(k+1)*Channels+i]*(fraction)))>>FRACTIONBITS));
|
|
|
|
DryBuffer[j][SIDE_RIGHT] += value*DrySend[SIDE_RIGHT];
|
|
|
|
WetBuffer[j][SIDE_RIGHT] += value*WetSend[SIDE_RIGHT];
|
2008-01-01 14:16:19 +00:00
|
|
|
i++;
|
2007-12-31 12:50:34 +00:00
|
|
|
}
|
2007-11-14 02:02:18 +00:00
|
|
|
}
|
2008-02-07 06:18:50 +00:00
|
|
|
else if(DuplicateStereo)
|
|
|
|
{
|
|
|
|
//Duplicate stereo channels on the back speakers
|
|
|
|
DryBuffer[j][BACK_LEFT] += samp1*DrySend[BACK_LEFT];
|
|
|
|
WetBuffer[j][BACK_LEFT] += samp1*WetSend[BACK_LEFT];
|
|
|
|
DryBuffer[j][BACK_RIGHT] += samp2*DrySend[BACK_RIGHT];
|
|
|
|
WetBuffer[j][BACK_RIGHT] += samp2*WetSend[BACK_RIGHT];
|
|
|
|
}
|
2007-11-14 02:02:18 +00:00
|
|
|
}
|
2008-01-21 22:54:15 +00:00
|
|
|
DataPosFrac += increment;
|
|
|
|
j++;
|
2007-11-14 02:02:18 +00:00
|
|
|
}
|
2008-01-21 22:54:15 +00:00
|
|
|
DataPosInt += (DataPosFrac>>FRACTIONBITS);
|
|
|
|
DataPosFrac = (DataPosFrac&FRACTIONMASK);
|
|
|
|
|
|
|
|
//Update source info
|
|
|
|
ALSource->position = DataPosInt;
|
|
|
|
ALSource->position_fraction = DataPosFrac;
|
|
|
|
}
|
2007-11-14 02:02:18 +00:00
|
|
|
|
2008-01-21 22:54:15 +00:00
|
|
|
//Handle looping sources
|
|
|
|
if(!Buffer || DataPosInt >= DataSize)
|
|
|
|
{
|
|
|
|
//queueing
|
|
|
|
if(ALSource->queue)
|
2007-11-14 02:02:18 +00:00
|
|
|
{
|
2008-01-21 22:54:15 +00:00
|
|
|
Looping = ALSource->bLooping;
|
|
|
|
if(ALSource->BuffersPlayed < (ALSource->BuffersInQueue-1))
|
2007-11-14 02:02:18 +00:00
|
|
|
{
|
2008-01-21 22:54:15 +00:00
|
|
|
BufferListItem = ALSource->queue;
|
|
|
|
for(loop = 0; loop <= ALSource->BuffersPlayed; loop++)
|
2007-11-14 02:02:18 +00:00
|
|
|
{
|
2008-01-21 22:54:15 +00:00
|
|
|
if(BufferListItem)
|
|
|
|
{
|
|
|
|
if(!Looping)
|
|
|
|
BufferListItem->bufferstate = PROCESSED;
|
|
|
|
BufferListItem = BufferListItem->next;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if(!Looping)
|
|
|
|
ALSource->BuffersProcessed++;
|
|
|
|
if(BufferListItem)
|
|
|
|
ALSource->ulBufferID = BufferListItem->buffer;
|
|
|
|
ALSource->position = DataPosInt-DataSize;
|
|
|
|
ALSource->position_fraction = DataPosFrac;
|
|
|
|
ALSource->BuffersPlayed++;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if(!Looping)
|
|
|
|
{
|
|
|
|
/* alSourceStop */
|
|
|
|
ALSource->state = AL_STOPPED;
|
|
|
|
ALSource->inuse = AL_FALSE;
|
|
|
|
ALSource->BuffersPlayed = ALSource->BuffersProcessed = ALSource->BuffersInQueue;
|
2007-11-14 02:02:18 +00:00
|
|
|
BufferListItem = ALSource->queue;
|
2008-01-21 22:54:15 +00:00
|
|
|
while(BufferListItem != NULL)
|
2007-11-14 02:02:18 +00:00
|
|
|
{
|
2008-01-21 22:54:15 +00:00
|
|
|
BufferListItem->bufferstate = PROCESSED;
|
|
|
|
BufferListItem = BufferListItem->next;
|
2007-11-14 02:02:18 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2008-01-21 22:54:15 +00:00
|
|
|
/* alSourceRewind */
|
|
|
|
/* alSourcePlay */
|
|
|
|
ALSource->state = AL_PLAYING;
|
|
|
|
ALSource->inuse = AL_TRUE;
|
|
|
|
ALSource->play = AL_TRUE;
|
|
|
|
ALSource->BuffersPlayed = 0;
|
|
|
|
ALSource->BufferPosition = 0;
|
|
|
|
ALSource->lBytesPlayed = 0;
|
|
|
|
ALSource->BuffersProcessed = 0;
|
|
|
|
BufferListItem = ALSource->queue;
|
|
|
|
while(BufferListItem != NULL)
|
2007-11-14 02:02:18 +00:00
|
|
|
{
|
2008-01-21 22:54:15 +00:00
|
|
|
BufferListItem->bufferstate = PENDING;
|
|
|
|
BufferListItem = BufferListItem->next;
|
2007-11-14 02:02:18 +00:00
|
|
|
}
|
2008-01-21 22:54:15 +00:00
|
|
|
ALSource->ulBufferID = ALSource->queue->buffer;
|
2007-11-14 02:02:18 +00:00
|
|
|
|
2008-01-21 22:54:15 +00:00
|
|
|
ALSource->position = DataPosInt-DataSize;
|
|
|
|
ALSource->position_fraction = DataPosFrac;
|
2007-11-14 02:02:18 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-01-21 22:54:15 +00:00
|
|
|
//Get source state
|
|
|
|
State = ALSource->state;
|
2007-11-14 02:02:18 +00:00
|
|
|
}
|
|
|
|
|
2008-01-21 22:54:15 +00:00
|
|
|
ALSource = ALSource->next;
|
|
|
|
}
|
|
|
|
|
|
|
|
// effect slot processing
|
|
|
|
while(ALEffectSlot)
|
|
|
|
{
|
|
|
|
if(ALEffectSlot->effect.type == AL_EFFECT_REVERB)
|
Implement AL_EFFECT_REVERB
Here is a quick description of how the reverb effect works:
+--->---+*(4)
| V new sample
+-----+---+---+ |
|extra|ltr|ref| <- +*(1)
+-----+---+---+
(3,5)*| |*(2)
+-->|
V
out sample
1) Apply master reverb gain to incoming sample and place it at the head of the
buffer. The master reverb gainhf was already applied when the source was
initially mixed.
2) Copy the delayed reflection sample to an output sample and apply the
reflection gain.
3) Apply the late reverb gain to the late reverb sample
4) Copy the end of the buffer, applying a decay gain and the decay hf ratio,
and add to the late reverb.
5) Copy the late reverb sample, adding to the output sample.
Then the head and sampling points are shifted forward, and done again for each
new sample. The extra buffer length is determined by the Reverb Density
property. A value of 0 gives a length of 0.1 seconds (long, with fairly
distinct echos) , and 1 gives 0.075 seconds (short, indistinct echos).
The decay gain is calculated such that after a number of loops to satisfy the
Decay Time, a sample will be 1/32768th as powerful (virtually insignificant to
the resulting output, and only getting further reduced). It is calculated as:
DecayGain = pow(1.0f/32768.0f, 1.0/(DecayTime/ExtraLength));
Things to note: Reverb Diffusion is not currently handled, nor is Decay HF
Limit. Decay HF Ratios above 1 probably give incorrect results. Also, this
method likely sucks, but it's the best I can come up with before release. :)
2008-01-19 05:25:40 +00:00
|
|
|
{
|
2008-01-21 22:54:15 +00:00
|
|
|
ALfloat *DelayBuffer = ALEffectSlot->ReverbBuffer;
|
|
|
|
ALuint Pos = ALEffectSlot->ReverbPos;
|
|
|
|
ALuint LatePos = ALEffectSlot->ReverbLatePos;
|
|
|
|
ALuint ReflectPos = ALEffectSlot->ReverbReflectPos;
|
|
|
|
ALuint Length = ALEffectSlot->ReverbLength;
|
|
|
|
ALfloat DecayGain = ALEffectSlot->ReverbDecayGain;
|
|
|
|
ALfloat DecayHFRatio = ALEffectSlot->effect.Reverb.DecayHFRatio;
|
|
|
|
ALfloat Gain = ALEffectSlot->effect.Reverb.Gain;
|
|
|
|
ALfloat ReflectGain = ALEffectSlot->effect.Reverb.ReflectionsGain;
|
|
|
|
ALfloat LateReverbGain = ALEffectSlot->effect.Reverb.LateReverbGain;
|
|
|
|
ALfloat LastDecaySample = ALEffectSlot->LastDecaySample;
|
|
|
|
ALfloat sample;
|
|
|
|
|
|
|
|
for(i = 0;i < SamplesToDo;i++)
|
Implement AL_EFFECT_REVERB
Here is a quick description of how the reverb effect works:
+--->---+*(4)
| V new sample
+-----+---+---+ |
|extra|ltr|ref| <- +*(1)
+-----+---+---+
(3,5)*| |*(2)
+-->|
V
out sample
1) Apply master reverb gain to incoming sample and place it at the head of the
buffer. The master reverb gainhf was already applied when the source was
initially mixed.
2) Copy the delayed reflection sample to an output sample and apply the
reflection gain.
3) Apply the late reverb gain to the late reverb sample
4) Copy the end of the buffer, applying a decay gain and the decay hf ratio,
and add to the late reverb.
5) Copy the late reverb sample, adding to the output sample.
Then the head and sampling points are shifted forward, and done again for each
new sample. The extra buffer length is determined by the Reverb Density
property. A value of 0 gives a length of 0.1 seconds (long, with fairly
distinct echos) , and 1 gives 0.075 seconds (short, indistinct echos).
The decay gain is calculated such that after a number of loops to satisfy the
Decay Time, a sample will be 1/32768th as powerful (virtually insignificant to
the resulting output, and only getting further reduced). It is calculated as:
DecayGain = pow(1.0f/32768.0f, 1.0/(DecayTime/ExtraLength));
Things to note: Reverb Diffusion is not currently handled, nor is Decay HF
Limit. Decay HF Ratios above 1 probably give incorrect results. Also, this
method likely sucks, but it's the best I can come up with before release. :)
2008-01-19 05:25:40 +00:00
|
|
|
{
|
2008-01-21 22:54:15 +00:00
|
|
|
DelayBuffer[Pos] = ReverbBuffer[i] * Gain;
|
Implement AL_EFFECT_REVERB
Here is a quick description of how the reverb effect works:
+--->---+*(4)
| V new sample
+-----+---+---+ |
|extra|ltr|ref| <- +*(1)
+-----+---+---+
(3,5)*| |*(2)
+-->|
V
out sample
1) Apply master reverb gain to incoming sample and place it at the head of the
buffer. The master reverb gainhf was already applied when the source was
initially mixed.
2) Copy the delayed reflection sample to an output sample and apply the
reflection gain.
3) Apply the late reverb gain to the late reverb sample
4) Copy the end of the buffer, applying a decay gain and the decay hf ratio,
and add to the late reverb.
5) Copy the late reverb sample, adding to the output sample.
Then the head and sampling points are shifted forward, and done again for each
new sample. The extra buffer length is determined by the Reverb Density
property. A value of 0 gives a length of 0.1 seconds (long, with fairly
distinct echos) , and 1 gives 0.075 seconds (short, indistinct echos).
The decay gain is calculated such that after a number of loops to satisfy the
Decay Time, a sample will be 1/32768th as powerful (virtually insignificant to
the resulting output, and only getting further reduced). It is calculated as:
DecayGain = pow(1.0f/32768.0f, 1.0/(DecayTime/ExtraLength));
Things to note: Reverb Diffusion is not currently handled, nor is Decay HF
Limit. Decay HF Ratios above 1 probably give incorrect results. Also, this
method likely sucks, but it's the best I can come up with before release. :)
2008-01-19 05:25:40 +00:00
|
|
|
|
2008-01-21 22:54:15 +00:00
|
|
|
sample = DelayBuffer[ReflectPos] * ReflectGain;
|
Implement AL_EFFECT_REVERB
Here is a quick description of how the reverb effect works:
+--->---+*(4)
| V new sample
+-----+---+---+ |
|extra|ltr|ref| <- +*(1)
+-----+---+---+
(3,5)*| |*(2)
+-->|
V
out sample
1) Apply master reverb gain to incoming sample and place it at the head of the
buffer. The master reverb gainhf was already applied when the source was
initially mixed.
2) Copy the delayed reflection sample to an output sample and apply the
reflection gain.
3) Apply the late reverb gain to the late reverb sample
4) Copy the end of the buffer, applying a decay gain and the decay hf ratio,
and add to the late reverb.
5) Copy the late reverb sample, adding to the output sample.
Then the head and sampling points are shifted forward, and done again for each
new sample. The extra buffer length is determined by the Reverb Density
property. A value of 0 gives a length of 0.1 seconds (long, with fairly
distinct echos) , and 1 gives 0.075 seconds (short, indistinct echos).
The decay gain is calculated such that after a number of loops to satisfy the
Decay Time, a sample will be 1/32768th as powerful (virtually insignificant to
the resulting output, and only getting further reduced). It is calculated as:
DecayGain = pow(1.0f/32768.0f, 1.0/(DecayTime/ExtraLength));
Things to note: Reverb Diffusion is not currently handled, nor is Decay HF
Limit. Decay HF Ratios above 1 probably give incorrect results. Also, this
method likely sucks, but it's the best I can come up with before release. :)
2008-01-19 05:25:40 +00:00
|
|
|
|
2008-01-21 22:54:15 +00:00
|
|
|
DelayBuffer[LatePos] *= LateReverbGain;
|
Implement AL_EFFECT_REVERB
Here is a quick description of how the reverb effect works:
+--->---+*(4)
| V new sample
+-----+---+---+ |
|extra|ltr|ref| <- +*(1)
+-----+---+---+
(3,5)*| |*(2)
+-->|
V
out sample
1) Apply master reverb gain to incoming sample and place it at the head of the
buffer. The master reverb gainhf was already applied when the source was
initially mixed.
2) Copy the delayed reflection sample to an output sample and apply the
reflection gain.
3) Apply the late reverb gain to the late reverb sample
4) Copy the end of the buffer, applying a decay gain and the decay hf ratio,
and add to the late reverb.
5) Copy the late reverb sample, adding to the output sample.
Then the head and sampling points are shifted forward, and done again for each
new sample. The extra buffer length is determined by the Reverb Density
property. A value of 0 gives a length of 0.1 seconds (long, with fairly
distinct echos) , and 1 gives 0.075 seconds (short, indistinct echos).
The decay gain is calculated such that after a number of loops to satisfy the
Decay Time, a sample will be 1/32768th as powerful (virtually insignificant to
the resulting output, and only getting further reduced). It is calculated as:
DecayGain = pow(1.0f/32768.0f, 1.0/(DecayTime/ExtraLength));
Things to note: Reverb Diffusion is not currently handled, nor is Decay HF
Limit. Decay HF Ratios above 1 probably give incorrect results. Also, this
method likely sucks, but it's the best I can come up with before release. :)
2008-01-19 05:25:40 +00:00
|
|
|
|
2008-01-21 22:54:15 +00:00
|
|
|
Pos = (Pos+1) % Length;
|
|
|
|
DelayBuffer[Pos] *= DecayHFRatio;
|
|
|
|
DelayBuffer[Pos] += LastDecaySample * (1.0f-DecayHFRatio);
|
|
|
|
LastDecaySample = DelayBuffer[Pos];
|
|
|
|
DelayBuffer[Pos] *= DecayGain;
|
Implement AL_EFFECT_REVERB
Here is a quick description of how the reverb effect works:
+--->---+*(4)
| V new sample
+-----+---+---+ |
|extra|ltr|ref| <- +*(1)
+-----+---+---+
(3,5)*| |*(2)
+-->|
V
out sample
1) Apply master reverb gain to incoming sample and place it at the head of the
buffer. The master reverb gainhf was already applied when the source was
initially mixed.
2) Copy the delayed reflection sample to an output sample and apply the
reflection gain.
3) Apply the late reverb gain to the late reverb sample
4) Copy the end of the buffer, applying a decay gain and the decay hf ratio,
and add to the late reverb.
5) Copy the late reverb sample, adding to the output sample.
Then the head and sampling points are shifted forward, and done again for each
new sample. The extra buffer length is determined by the Reverb Density
property. A value of 0 gives a length of 0.1 seconds (long, with fairly
distinct echos) , and 1 gives 0.075 seconds (short, indistinct echos).
The decay gain is calculated such that after a number of loops to satisfy the
Decay Time, a sample will be 1/32768th as powerful (virtually insignificant to
the resulting output, and only getting further reduced). It is calculated as:
DecayGain = pow(1.0f/32768.0f, 1.0/(DecayTime/ExtraLength));
Things to note: Reverb Diffusion is not currently handled, nor is Decay HF
Limit. Decay HF Ratios above 1 probably give incorrect results. Also, this
method likely sucks, but it's the best I can come up with before release. :)
2008-01-19 05:25:40 +00:00
|
|
|
|
2008-01-21 22:54:15 +00:00
|
|
|
DelayBuffer[LatePos] += DelayBuffer[Pos];
|
Implement AL_EFFECT_REVERB
Here is a quick description of how the reverb effect works:
+--->---+*(4)
| V new sample
+-----+---+---+ |
|extra|ltr|ref| <- +*(1)
+-----+---+---+
(3,5)*| |*(2)
+-->|
V
out sample
1) Apply master reverb gain to incoming sample and place it at the head of the
buffer. The master reverb gainhf was already applied when the source was
initially mixed.
2) Copy the delayed reflection sample to an output sample and apply the
reflection gain.
3) Apply the late reverb gain to the late reverb sample
4) Copy the end of the buffer, applying a decay gain and the decay hf ratio,
and add to the late reverb.
5) Copy the late reverb sample, adding to the output sample.
Then the head and sampling points are shifted forward, and done again for each
new sample. The extra buffer length is determined by the Reverb Density
property. A value of 0 gives a length of 0.1 seconds (long, with fairly
distinct echos) , and 1 gives 0.075 seconds (short, indistinct echos).
The decay gain is calculated such that after a number of loops to satisfy the
Decay Time, a sample will be 1/32768th as powerful (virtually insignificant to
the resulting output, and only getting further reduced). It is calculated as:
DecayGain = pow(1.0f/32768.0f, 1.0/(DecayTime/ExtraLength));
Things to note: Reverb Diffusion is not currently handled, nor is Decay HF
Limit. Decay HF Ratios above 1 probably give incorrect results. Also, this
method likely sucks, but it's the best I can come up with before release. :)
2008-01-19 05:25:40 +00:00
|
|
|
|
2008-01-21 22:54:15 +00:00
|
|
|
sample += DelayBuffer[LatePos];
|
Implement AL_EFFECT_REVERB
Here is a quick description of how the reverb effect works:
+--->---+*(4)
| V new sample
+-----+---+---+ |
|extra|ltr|ref| <- +*(1)
+-----+---+---+
(3,5)*| |*(2)
+-->|
V
out sample
1) Apply master reverb gain to incoming sample and place it at the head of the
buffer. The master reverb gainhf was already applied when the source was
initially mixed.
2) Copy the delayed reflection sample to an output sample and apply the
reflection gain.
3) Apply the late reverb gain to the late reverb sample
4) Copy the end of the buffer, applying a decay gain and the decay hf ratio,
and add to the late reverb.
5) Copy the late reverb sample, adding to the output sample.
Then the head and sampling points are shifted forward, and done again for each
new sample. The extra buffer length is determined by the Reverb Density
property. A value of 0 gives a length of 0.1 seconds (long, with fairly
distinct echos) , and 1 gives 0.075 seconds (short, indistinct echos).
The decay gain is calculated such that after a number of loops to satisfy the
Decay Time, a sample will be 1/32768th as powerful (virtually insignificant to
the resulting output, and only getting further reduced). It is calculated as:
DecayGain = pow(1.0f/32768.0f, 1.0/(DecayTime/ExtraLength));
Things to note: Reverb Diffusion is not currently handled, nor is Decay HF
Limit. Decay HF Ratios above 1 probably give incorrect results. Also, this
method likely sucks, but it's the best I can come up with before release. :)
2008-01-19 05:25:40 +00:00
|
|
|
|
2008-01-21 22:54:15 +00:00
|
|
|
WetBuffer[i][FRONT_LEFT] += sample;
|
|
|
|
WetBuffer[i][FRONT_RIGHT] += sample;
|
|
|
|
WetBuffer[i][SIDE_LEFT] += sample;
|
|
|
|
WetBuffer[i][SIDE_RIGHT] += sample;
|
|
|
|
WetBuffer[i][BACK_LEFT] += sample;
|
|
|
|
WetBuffer[i][BACK_RIGHT] += sample;
|
Implement AL_EFFECT_REVERB
Here is a quick description of how the reverb effect works:
+--->---+*(4)
| V new sample
+-----+---+---+ |
|extra|ltr|ref| <- +*(1)
+-----+---+---+
(3,5)*| |*(2)
+-->|
V
out sample
1) Apply master reverb gain to incoming sample and place it at the head of the
buffer. The master reverb gainhf was already applied when the source was
initially mixed.
2) Copy the delayed reflection sample to an output sample and apply the
reflection gain.
3) Apply the late reverb gain to the late reverb sample
4) Copy the end of the buffer, applying a decay gain and the decay hf ratio,
and add to the late reverb.
5) Copy the late reverb sample, adding to the output sample.
Then the head and sampling points are shifted forward, and done again for each
new sample. The extra buffer length is determined by the Reverb Density
property. A value of 0 gives a length of 0.1 seconds (long, with fairly
distinct echos) , and 1 gives 0.075 seconds (short, indistinct echos).
The decay gain is calculated such that after a number of loops to satisfy the
Decay Time, a sample will be 1/32768th as powerful (virtually insignificant to
the resulting output, and only getting further reduced). It is calculated as:
DecayGain = pow(1.0f/32768.0f, 1.0/(DecayTime/ExtraLength));
Things to note: Reverb Diffusion is not currently handled, nor is Decay HF
Limit. Decay HF Ratios above 1 probably give incorrect results. Also, this
method likely sucks, but it's the best I can come up with before release. :)
2008-01-19 05:25:40 +00:00
|
|
|
|
2008-01-21 22:54:15 +00:00
|
|
|
LatePos = (LatePos+1) % Length;
|
|
|
|
ReflectPos = (ReflectPos+1) % Length;
|
Implement AL_EFFECT_REVERB
Here is a quick description of how the reverb effect works:
+--->---+*(4)
| V new sample
+-----+---+---+ |
|extra|ltr|ref| <- +*(1)
+-----+---+---+
(3,5)*| |*(2)
+-->|
V
out sample
1) Apply master reverb gain to incoming sample and place it at the head of the
buffer. The master reverb gainhf was already applied when the source was
initially mixed.
2) Copy the delayed reflection sample to an output sample and apply the
reflection gain.
3) Apply the late reverb gain to the late reverb sample
4) Copy the end of the buffer, applying a decay gain and the decay hf ratio,
and add to the late reverb.
5) Copy the late reverb sample, adding to the output sample.
Then the head and sampling points are shifted forward, and done again for each
new sample. The extra buffer length is determined by the Reverb Density
property. A value of 0 gives a length of 0.1 seconds (long, with fairly
distinct echos) , and 1 gives 0.075 seconds (short, indistinct echos).
The decay gain is calculated such that after a number of loops to satisfy the
Decay Time, a sample will be 1/32768th as powerful (virtually insignificant to
the resulting output, and only getting further reduced). It is calculated as:
DecayGain = pow(1.0f/32768.0f, 1.0/(DecayTime/ExtraLength));
Things to note: Reverb Diffusion is not currently handled, nor is Decay HF
Limit. Decay HF Ratios above 1 probably give incorrect results. Also, this
method likely sucks, but it's the best I can come up with before release. :)
2008-01-19 05:25:40 +00:00
|
|
|
}
|
2008-01-21 06:16:28 +00:00
|
|
|
|
2008-01-21 22:54:15 +00:00
|
|
|
ALEffectSlot->ReverbPos = Pos;
|
|
|
|
ALEffectSlot->ReverbLatePos = LatePos;
|
|
|
|
ALEffectSlot->ReverbReflectPos = ReflectPos;
|
|
|
|
ALEffectSlot->LastDecaySample = LastDecaySample;
|
Implement AL_EFFECT_REVERB
Here is a quick description of how the reverb effect works:
+--->---+*(4)
| V new sample
+-----+---+---+ |
|extra|ltr|ref| <- +*(1)
+-----+---+---+
(3,5)*| |*(2)
+-->|
V
out sample
1) Apply master reverb gain to incoming sample and place it at the head of the
buffer. The master reverb gainhf was already applied when the source was
initially mixed.
2) Copy the delayed reflection sample to an output sample and apply the
reflection gain.
3) Apply the late reverb gain to the late reverb sample
4) Copy the end of the buffer, applying a decay gain and the decay hf ratio,
and add to the late reverb.
5) Copy the late reverb sample, adding to the output sample.
Then the head and sampling points are shifted forward, and done again for each
new sample. The extra buffer length is determined by the Reverb Density
property. A value of 0 gives a length of 0.1 seconds (long, with fairly
distinct echos) , and 1 gives 0.075 seconds (short, indistinct echos).
The decay gain is calculated such that after a number of loops to satisfy the
Decay Time, a sample will be 1/32768th as powerful (virtually insignificant to
the resulting output, and only getting further reduced). It is calculated as:
DecayGain = pow(1.0f/32768.0f, 1.0/(DecayTime/ExtraLength));
Things to note: Reverb Diffusion is not currently handled, nor is Decay HF
Limit. Decay HF Ratios above 1 probably give incorrect results. Also, this
method likely sucks, but it's the best I can come up with before release. :)
2008-01-19 05:25:40 +00:00
|
|
|
}
|
|
|
|
|
2008-01-21 22:54:15 +00:00
|
|
|
ALEffectSlot = ALEffectSlot->next;
|
|
|
|
}
|
|
|
|
|
|
|
|
//Post processing loop
|
|
|
|
switch(format)
|
|
|
|
{
|
|
|
|
case AL_FORMAT_MONO8:
|
|
|
|
for(i = 0;i < SamplesToDo;i++)
|
|
|
|
{
|
|
|
|
((ALubyte*)buffer)[0] = (ALubyte)((aluF2S(DryBuffer[i][FRONT_LEFT]+DryBuffer[i][FRONT_RIGHT]+
|
|
|
|
WetBuffer[i][FRONT_LEFT]+WetBuffer[i][FRONT_RIGHT])>>8)+128);
|
|
|
|
buffer = ((ALubyte*)buffer) + 1;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case AL_FORMAT_STEREO8:
|
|
|
|
if(ALContext && ALContext->bs2b)
|
|
|
|
{
|
2007-12-31 11:29:14 +00:00
|
|
|
for(i = 0;i < SamplesToDo;i++)
|
|
|
|
{
|
2008-01-21 22:54:15 +00:00
|
|
|
float samples[2];
|
|
|
|
samples[0] = DryBuffer[i][FRONT_LEFT] +WetBuffer[i][FRONT_LEFT];
|
|
|
|
samples[1] = DryBuffer[i][FRONT_RIGHT]+WetBuffer[i][FRONT_RIGHT];
|
|
|
|
bs2b_cross_feed(ALContext->bs2b, samples);
|
|
|
|
((ALubyte*)buffer)[0] = (ALubyte)((aluF2S(samples[0])>>8)+128);
|
|
|
|
((ALubyte*)buffer)[1] = (ALubyte)((aluF2S(samples[1])>>8)+128);
|
|
|
|
buffer = ((ALubyte*)buffer) + 2;
|
2007-11-14 02:02:18 +00:00
|
|
|
}
|
2008-01-21 22:54:15 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2007-12-31 11:29:14 +00:00
|
|
|
for(i = 0;i < SamplesToDo;i++)
|
|
|
|
{
|
|
|
|
((ALubyte*)buffer)[0] = (ALubyte)((aluF2S(DryBuffer[i][FRONT_LEFT] +WetBuffer[i][FRONT_LEFT])>>8)+128);
|
|
|
|
((ALubyte*)buffer)[1] = (ALubyte)((aluF2S(DryBuffer[i][FRONT_RIGHT]+WetBuffer[i][FRONT_RIGHT])>>8)+128);
|
2008-01-21 22:54:15 +00:00
|
|
|
buffer = ((ALubyte*)buffer) + 2;
|
2007-12-31 11:29:14 +00:00
|
|
|
}
|
2008-01-21 22:54:15 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
case AL_FORMAT_QUAD8:
|
|
|
|
for(i = 0;i < SamplesToDo;i++)
|
|
|
|
{
|
|
|
|
((ALubyte*)buffer)[0] = (ALubyte)((aluF2S(DryBuffer[i][FRONT_LEFT] +WetBuffer[i][FRONT_LEFT])>>8)+128);
|
|
|
|
((ALubyte*)buffer)[1] = (ALubyte)((aluF2S(DryBuffer[i][FRONT_RIGHT]+WetBuffer[i][FRONT_RIGHT])>>8)+128);
|
|
|
|
((ALubyte*)buffer)[2] = (ALubyte)((aluF2S(DryBuffer[i][BACK_LEFT] +WetBuffer[i][BACK_LEFT])>>8)+128);
|
|
|
|
((ALubyte*)buffer)[3] = (ALubyte)((aluF2S(DryBuffer[i][BACK_RIGHT] +WetBuffer[i][BACK_RIGHT])>>8)+128);
|
|
|
|
buffer = ((ALubyte*)buffer) + 4;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case AL_FORMAT_51CHN8:
|
|
|
|
for(i = 0;i < SamplesToDo;i++)
|
|
|
|
{
|
|
|
|
((ALubyte*)buffer)[0] = (ALubyte)((aluF2S(DryBuffer[i][FRONT_LEFT] +WetBuffer[i][FRONT_LEFT])>>8)+128);
|
|
|
|
((ALubyte*)buffer)[1] = (ALubyte)((aluF2S(DryBuffer[i][FRONT_RIGHT]+WetBuffer[i][FRONT_RIGHT])>>8)+128);
|
2008-01-27 15:04:13 +00:00
|
|
|
#ifdef _WIN32 /* Of course, Windows can't use the same ordering... */
|
|
|
|
((ALubyte*)buffer)[2] = (ALubyte)((aluF2S(DryBuffer[i][CENTER] +WetBuffer[i][CENTER])>>8)+128);
|
|
|
|
((ALubyte*)buffer)[3] = (ALubyte)((aluF2S(DryBuffer[i][LFE] +WetBuffer[i][LFE])>>8)+128);
|
|
|
|
((ALubyte*)buffer)[4] = (ALubyte)((aluF2S(DryBuffer[i][BACK_LEFT] +WetBuffer[i][BACK_LEFT])>>8)+128);
|
|
|
|
((ALubyte*)buffer)[5] = (ALubyte)((aluF2S(DryBuffer[i][BACK_RIGHT] +WetBuffer[i][BACK_RIGHT])>>8)+128);
|
|
|
|
#else
|
2008-01-21 22:54:15 +00:00
|
|
|
((ALubyte*)buffer)[2] = (ALubyte)((aluF2S(DryBuffer[i][BACK_LEFT] +WetBuffer[i][BACK_LEFT])>>8)+128);
|
|
|
|
((ALubyte*)buffer)[3] = (ALubyte)((aluF2S(DryBuffer[i][BACK_RIGHT] +WetBuffer[i][BACK_RIGHT])>>8)+128);
|
|
|
|
((ALubyte*)buffer)[4] = (ALubyte)((aluF2S(DryBuffer[i][CENTER] +WetBuffer[i][CENTER])>>8)+128);
|
|
|
|
((ALubyte*)buffer)[5] = (ALubyte)((aluF2S(DryBuffer[i][LFE] +WetBuffer[i][LFE])>>8)+128);
|
2008-01-27 15:04:13 +00:00
|
|
|
#endif
|
2008-01-21 22:54:15 +00:00
|
|
|
buffer = ((ALubyte*)buffer) + 6;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case AL_FORMAT_61CHN8:
|
|
|
|
for(i = 0;i < SamplesToDo;i++)
|
|
|
|
{
|
|
|
|
((ALubyte*)buffer)[0] = (ALubyte)((aluF2S(DryBuffer[i][FRONT_LEFT] +WetBuffer[i][FRONT_LEFT])>>8)+128);
|
|
|
|
((ALubyte*)buffer)[1] = (ALubyte)((aluF2S(DryBuffer[i][FRONT_RIGHT]+WetBuffer[i][FRONT_RIGHT])>>8)+128);
|
2008-01-27 15:04:13 +00:00
|
|
|
#ifdef _WIN32
|
|
|
|
((ALubyte*)buffer)[2] = (ALubyte)((aluF2S(DryBuffer[i][LFE] +WetBuffer[i][LFE])>>8)+128);
|
|
|
|
((ALubyte*)buffer)[3] = (ALubyte)((aluF2S(DryBuffer[i][BACK_LEFT] +WetBuffer[i][BACK_LEFT])>>8)+128);
|
|
|
|
((ALubyte*)buffer)[4] = (ALubyte)((aluF2S(DryBuffer[i][BACK_RIGHT] +WetBuffer[i][BACK_RIGHT])>>8)+128);
|
|
|
|
#else
|
2008-01-27 14:49:48 +00:00
|
|
|
((ALubyte*)buffer)[2] = (ALubyte)((aluF2S(DryBuffer[i][BACK_LEFT] +WetBuffer[i][BACK_LEFT])>>8)+128);
|
|
|
|
((ALubyte*)buffer)[3] = (ALubyte)((aluF2S(DryBuffer[i][BACK_RIGHT] +WetBuffer[i][BACK_RIGHT])>>8)+128);
|
|
|
|
((ALubyte*)buffer)[4] = (ALubyte)((aluF2S(DryBuffer[i][LFE] +WetBuffer[i][LFE])>>8)+128);
|
2008-01-27 15:04:13 +00:00
|
|
|
#endif
|
2008-01-27 14:49:48 +00:00
|
|
|
((ALubyte*)buffer)[5] = (ALubyte)((aluF2S(DryBuffer[i][SIDE_LEFT] +WetBuffer[i][SIDE_LEFT])>>8)+128);
|
|
|
|
((ALubyte*)buffer)[6] = (ALubyte)((aluF2S(DryBuffer[i][SIDE_RIGHT] +WetBuffer[i][SIDE_RIGHT])>>8)+128);
|
2008-01-21 22:54:15 +00:00
|
|
|
buffer = ((ALubyte*)buffer) + 7;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case AL_FORMAT_71CHN8:
|
|
|
|
for(i = 0;i < SamplesToDo;i++)
|
|
|
|
{
|
|
|
|
((ALubyte*)buffer)[0] = (ALubyte)((aluF2S(DryBuffer[i][FRONT_LEFT] +WetBuffer[i][FRONT_LEFT])>>8)+128);
|
|
|
|
((ALubyte*)buffer)[1] = (ALubyte)((aluF2S(DryBuffer[i][FRONT_RIGHT]+WetBuffer[i][FRONT_RIGHT])>>8)+128);
|
2008-01-27 15:04:13 +00:00
|
|
|
#ifdef _WIN32
|
|
|
|
((ALubyte*)buffer)[2] = (ALubyte)((aluF2S(DryBuffer[i][CENTER] +WetBuffer[i][CENTER])>>8)+128);
|
|
|
|
((ALubyte*)buffer)[3] = (ALubyte)((aluF2S(DryBuffer[i][LFE] +WetBuffer[i][LFE])>>8)+128);
|
|
|
|
((ALubyte*)buffer)[4] = (ALubyte)((aluF2S(DryBuffer[i][BACK_LEFT] +WetBuffer[i][BACK_LEFT])>>8)+128);
|
|
|
|
((ALubyte*)buffer)[5] = (ALubyte)((aluF2S(DryBuffer[i][BACK_RIGHT] +WetBuffer[i][BACK_RIGHT])>>8)+128);
|
|
|
|
#else
|
2008-01-27 14:49:48 +00:00
|
|
|
((ALubyte*)buffer)[2] = (ALubyte)((aluF2S(DryBuffer[i][BACK_LEFT] +WetBuffer[i][BACK_LEFT])>>8)+128);
|
|
|
|
((ALubyte*)buffer)[3] = (ALubyte)((aluF2S(DryBuffer[i][BACK_RIGHT] +WetBuffer[i][BACK_RIGHT])>>8)+128);
|
|
|
|
((ALubyte*)buffer)[4] = (ALubyte)((aluF2S(DryBuffer[i][CENTER] +WetBuffer[i][CENTER])>>8)+128);
|
|
|
|
((ALubyte*)buffer)[5] = (ALubyte)((aluF2S(DryBuffer[i][LFE] +WetBuffer[i][LFE])>>8)+128);
|
2008-01-27 15:04:13 +00:00
|
|
|
#endif
|
2008-01-27 14:49:48 +00:00
|
|
|
((ALubyte*)buffer)[6] = (ALubyte)((aluF2S(DryBuffer[i][SIDE_LEFT] +WetBuffer[i][SIDE_LEFT])>>8)+128);
|
|
|
|
((ALubyte*)buffer)[7] = (ALubyte)((aluF2S(DryBuffer[i][SIDE_RIGHT] +WetBuffer[i][SIDE_RIGHT])>>8)+128);
|
2008-01-21 22:54:15 +00:00
|
|
|
buffer = ((ALubyte*)buffer) + 8;
|
|
|
|
}
|
|
|
|
break;
|
2007-12-31 11:29:14 +00:00
|
|
|
|
2008-01-21 22:54:15 +00:00
|
|
|
case AL_FORMAT_MONO16:
|
|
|
|
for(i = 0;i < SamplesToDo;i++)
|
|
|
|
{
|
|
|
|
((ALshort*)buffer)[0] = aluF2S(DryBuffer[i][FRONT_LEFT]+DryBuffer[i][FRONT_RIGHT]+
|
|
|
|
WetBuffer[i][FRONT_LEFT]+WetBuffer[i][FRONT_RIGHT]);
|
|
|
|
buffer = ((ALshort*)buffer) + 1;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case AL_FORMAT_STEREO16:
|
|
|
|
if(ALContext && ALContext->bs2b)
|
|
|
|
{
|
2007-12-31 11:29:14 +00:00
|
|
|
for(i = 0;i < SamplesToDo;i++)
|
|
|
|
{
|
2008-01-21 22:54:15 +00:00
|
|
|
float samples[2];
|
|
|
|
samples[0] = DryBuffer[i][FRONT_LEFT] +WetBuffer[i][FRONT_LEFT];
|
|
|
|
samples[1] = DryBuffer[i][FRONT_RIGHT]+WetBuffer[i][FRONT_RIGHT];
|
|
|
|
bs2b_cross_feed(ALContext->bs2b, samples);
|
|
|
|
((ALshort*)buffer)[0] = aluF2S(samples[0]);
|
|
|
|
((ALshort*)buffer)[1] = aluF2S(samples[1]);
|
|
|
|
buffer = ((ALshort*)buffer) + 2;
|
2007-12-31 11:29:14 +00:00
|
|
|
}
|
2008-01-21 22:54:15 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2007-12-31 11:29:14 +00:00
|
|
|
for(i = 0;i < SamplesToDo;i++)
|
|
|
|
{
|
|
|
|
((ALshort*)buffer)[0] = aluF2S(DryBuffer[i][FRONT_LEFT] +WetBuffer[i][FRONT_LEFT]);
|
|
|
|
((ALshort*)buffer)[1] = aluF2S(DryBuffer[i][FRONT_RIGHT]+WetBuffer[i][FRONT_RIGHT]);
|
2008-01-21 22:54:15 +00:00
|
|
|
buffer = ((ALshort*)buffer) + 2;
|
2007-12-31 11:29:14 +00:00
|
|
|
}
|
2008-01-21 22:54:15 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
case AL_FORMAT_QUAD16:
|
|
|
|
for(i = 0;i < SamplesToDo;i++)
|
|
|
|
{
|
|
|
|
((ALshort*)buffer)[0] = aluF2S(DryBuffer[i][FRONT_LEFT] +WetBuffer[i][FRONT_LEFT]);
|
|
|
|
((ALshort*)buffer)[1] = aluF2S(DryBuffer[i][FRONT_RIGHT]+WetBuffer[i][FRONT_RIGHT]);
|
|
|
|
((ALshort*)buffer)[2] = aluF2S(DryBuffer[i][BACK_LEFT] +WetBuffer[i][BACK_LEFT]);
|
|
|
|
((ALshort*)buffer)[3] = aluF2S(DryBuffer[i][BACK_RIGHT] +WetBuffer[i][BACK_RIGHT]);
|
|
|
|
buffer = ((ALshort*)buffer) + 4;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case AL_FORMAT_51CHN16:
|
|
|
|
for(i = 0;i < SamplesToDo;i++)
|
|
|
|
{
|
|
|
|
((ALshort*)buffer)[0] = aluF2S(DryBuffer[i][FRONT_LEFT] +WetBuffer[i][FRONT_LEFT]);
|
|
|
|
((ALshort*)buffer)[1] = aluF2S(DryBuffer[i][FRONT_RIGHT]+WetBuffer[i][FRONT_RIGHT]);
|
2008-01-27 15:04:13 +00:00
|
|
|
#ifdef _WIN32
|
|
|
|
((ALshort*)buffer)[2] = aluF2S(DryBuffer[i][CENTER] +WetBuffer[i][CENTER]);
|
|
|
|
((ALshort*)buffer)[3] = aluF2S(DryBuffer[i][LFE] +WetBuffer[i][LFE]);
|
|
|
|
((ALshort*)buffer)[4] = aluF2S(DryBuffer[i][BACK_LEFT] +WetBuffer[i][BACK_LEFT]);
|
|
|
|
((ALshort*)buffer)[5] = aluF2S(DryBuffer[i][BACK_RIGHT] +WetBuffer[i][BACK_RIGHT]);
|
|
|
|
#else
|
2008-01-21 22:54:15 +00:00
|
|
|
((ALshort*)buffer)[2] = aluF2S(DryBuffer[i][BACK_LEFT] +WetBuffer[i][BACK_LEFT]);
|
|
|
|
((ALshort*)buffer)[3] = aluF2S(DryBuffer[i][BACK_RIGHT] +WetBuffer[i][BACK_RIGHT]);
|
|
|
|
((ALshort*)buffer)[4] = aluF2S(DryBuffer[i][CENTER] +WetBuffer[i][CENTER]);
|
|
|
|
((ALshort*)buffer)[5] = aluF2S(DryBuffer[i][LFE] +WetBuffer[i][LFE]);
|
2008-01-27 15:04:13 +00:00
|
|
|
#endif
|
2008-01-21 22:54:15 +00:00
|
|
|
buffer = ((ALshort*)buffer) + 6;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case AL_FORMAT_61CHN16:
|
|
|
|
for(i = 0;i < SamplesToDo;i++)
|
|
|
|
{
|
|
|
|
((ALshort*)buffer)[0] = aluF2S(DryBuffer[i][FRONT_LEFT] +WetBuffer[i][FRONT_LEFT]);
|
|
|
|
((ALshort*)buffer)[1] = aluF2S(DryBuffer[i][FRONT_RIGHT]+WetBuffer[i][FRONT_RIGHT]);
|
2008-01-27 15:04:13 +00:00
|
|
|
#ifdef _WIN32
|
|
|
|
((ALshort*)buffer)[2] = aluF2S(DryBuffer[i][LFE] +WetBuffer[i][LFE]);
|
|
|
|
((ALshort*)buffer)[3] = aluF2S(DryBuffer[i][BACK_LEFT] +WetBuffer[i][BACK_LEFT]);
|
|
|
|
((ALshort*)buffer)[4] = aluF2S(DryBuffer[i][BACK_RIGHT] +WetBuffer[i][BACK_RIGHT]);
|
|
|
|
#else
|
2008-01-27 14:49:48 +00:00
|
|
|
((ALshort*)buffer)[2] = aluF2S(DryBuffer[i][BACK_LEFT] +WetBuffer[i][BACK_LEFT]);
|
|
|
|
((ALshort*)buffer)[3] = aluF2S(DryBuffer[i][BACK_RIGHT] +WetBuffer[i][BACK_RIGHT]);
|
|
|
|
((ALshort*)buffer)[4] = aluF2S(DryBuffer[i][LFE] +WetBuffer[i][LFE]);
|
2008-01-27 15:04:13 +00:00
|
|
|
#endif
|
2008-01-27 14:49:48 +00:00
|
|
|
((ALshort*)buffer)[5] = aluF2S(DryBuffer[i][SIDE_LEFT] +WetBuffer[i][SIDE_LEFT]);
|
|
|
|
((ALshort*)buffer)[6] = aluF2S(DryBuffer[i][SIDE_RIGHT] +WetBuffer[i][SIDE_RIGHT]);
|
2008-01-21 22:54:15 +00:00
|
|
|
buffer = ((ALshort*)buffer) + 7;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case AL_FORMAT_71CHN16:
|
|
|
|
for(i = 0;i < SamplesToDo;i++)
|
|
|
|
{
|
|
|
|
((ALshort*)buffer)[0] = aluF2S(DryBuffer[i][FRONT_LEFT] +WetBuffer[i][FRONT_LEFT]);
|
|
|
|
((ALshort*)buffer)[1] = aluF2S(DryBuffer[i][FRONT_RIGHT]+WetBuffer[i][FRONT_RIGHT]);
|
2008-01-27 15:04:13 +00:00
|
|
|
#ifdef _WIN32
|
|
|
|
((ALshort*)buffer)[2] = aluF2S(DryBuffer[i][CENTER] +WetBuffer[i][CENTER]);
|
|
|
|
((ALshort*)buffer)[3] = aluF2S(DryBuffer[i][LFE] +WetBuffer[i][LFE]);
|
|
|
|
((ALshort*)buffer)[4] = aluF2S(DryBuffer[i][BACK_LEFT] +WetBuffer[i][BACK_LEFT]);
|
|
|
|
((ALshort*)buffer)[5] = aluF2S(DryBuffer[i][BACK_RIGHT] +WetBuffer[i][BACK_RIGHT]);
|
|
|
|
#else
|
2008-01-27 14:49:48 +00:00
|
|
|
((ALshort*)buffer)[2] = aluF2S(DryBuffer[i][BACK_LEFT] +WetBuffer[i][BACK_LEFT]);
|
|
|
|
((ALshort*)buffer)[3] = aluF2S(DryBuffer[i][BACK_RIGHT] +WetBuffer[i][BACK_RIGHT]);
|
|
|
|
((ALshort*)buffer)[4] = aluF2S(DryBuffer[i][CENTER] +WetBuffer[i][CENTER]);
|
|
|
|
((ALshort*)buffer)[5] = aluF2S(DryBuffer[i][LFE] +WetBuffer[i][LFE]);
|
2008-01-27 15:04:13 +00:00
|
|
|
#endif
|
2008-01-27 14:49:48 +00:00
|
|
|
((ALshort*)buffer)[6] = aluF2S(DryBuffer[i][SIDE_LEFT] +WetBuffer[i][SIDE_LEFT]);
|
|
|
|
((ALshort*)buffer)[7] = aluF2S(DryBuffer[i][SIDE_RIGHT] +WetBuffer[i][SIDE_RIGHT]);
|
2008-01-21 22:54:15 +00:00
|
|
|
buffer = ((ALshort*)buffer) + 8;
|
|
|
|
}
|
|
|
|
break;
|
2007-11-14 02:02:18 +00:00
|
|
|
|
2008-01-21 22:54:15 +00:00
|
|
|
default:
|
|
|
|
break;
|
2007-11-14 02:02:18 +00:00
|
|
|
}
|
2008-01-21 22:54:15 +00:00
|
|
|
|
|
|
|
size -= SamplesToDo;
|
2007-11-14 02:02:18 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
ProcessContext(ALContext);
|
|
|
|
}
|