OpenAL channels now use their own sound buffers

This commit is contained in:
Sergeanur 2020-10-27 09:35:09 +02:00
parent ba0c96c39c
commit 4cfb3b0984
4 changed files with 96 additions and 179 deletions

View File

@ -10,17 +10,49 @@
extern bool IsFXSupported(); extern bool IsFXSupported();
ALuint alSources[MAXCHANNELS+MAX2DCHANNELS];
ALuint alFilters[MAXCHANNELS+MAX2DCHANNELS];
ALuint alBuffers[MAXCHANNELS+MAX2DCHANNELS];
bool bChannelsCreated = false;
void
CChannel::InitChannels()
{
alGenSources(MAXCHANNELS+MAX2DCHANNELS, alSources);
alGenBuffers(MAXCHANNELS+MAX2DCHANNELS, alBuffers);
if (IsFXSupported())
alGenFilters(MAXCHANNELS + MAX2DCHANNELS, alFilters);
bChannelsCreated = true;
}
void
CChannel::DestroyChannels()
{
if (bChannelsCreated)
{
alDeleteSources(MAXCHANNELS + MAX2DCHANNELS, alSources);
memset(alSources, 0, sizeof(alSources));
alDeleteBuffers(MAXCHANNELS + MAX2DCHANNELS, alBuffers);
memset(alBuffers, 0, sizeof(alBuffers));
if (IsFXSupported())
{
alDeleteFilters(MAXCHANNELS + MAX2DCHANNELS, alFilters);
memset(alFilters, 0, sizeof(alFilters));
}
bChannelsCreated = false;
}
}
CChannel::CChannel() CChannel::CChannel()
{ {
alSource = AL_NONE; Data = nil;
alFilter = AL_FILTER_NULL; DataSize = 0;
SetDefault(); SetDefault();
} }
void CChannel::SetDefault() void CChannel::SetDefault()
{ {
alBuffer = AL_NONE;
Pitch = 1.0f; Pitch = 1.0f;
Gain = 1.0f; Gain = 1.0f;
Mix = 0.0f; Mix = 0.0f;
@ -39,25 +71,19 @@ void CChannel::Reset()
SetDefault(); SetDefault();
} }
void CChannel::Init(bool Is2D) void CChannel::Init(uint32 _id, bool Is2D)
{ {
ASSERT(!HasSource()); id = _id;
alGenSources(1, &alSource);
if ( HasSource() ) if ( HasSource() )
{ {
alSourcei(alSource, AL_SOURCE_RELATIVE, AL_TRUE); alSourcei(alSources[id], AL_SOURCE_RELATIVE, AL_TRUE);
if ( IsFXSupported() ) if ( IsFXSupported() )
alSource3i(alSource, AL_AUXILIARY_SEND_FILTER, AL_EFFECTSLOT_NULL, 0, AL_FILTER_NULL); alSource3i(alSources[id], AL_AUXILIARY_SEND_FILTER, AL_EFFECTSLOT_NULL, 0, AL_FILTER_NULL);
if ( Is2D ) if ( Is2D )
{ {
alSource3f(alSource, AL_POSITION, 0.0f, 0.0f, 0.0f); alSource3f(alSources[id], AL_POSITION, 0.0f, 0.0f, 0.0f);
alSourcef (alSource, AL_GAIN, 1.0f); alSourcef(alSources[id], AL_GAIN, 1.0f);
}
else
{
if ( IsFXSupported() )
alGenFilters(1,&alFilter);
} }
} }
} }
@ -69,39 +95,34 @@ void CChannel::Term()
{ {
if ( IsFXSupported() ) if ( IsFXSupported() )
{ {
alSource3i(alSource, AL_AUXILIARY_SEND_FILTER, AL_EFFECTSLOT_NULL, 0, AL_FILTER_NULL); alSource3i(alSources[id], AL_AUXILIARY_SEND_FILTER, AL_EFFECTSLOT_NULL, 0, AL_FILTER_NULL);
if(alFilter != AL_FILTER_NULL)
alDeleteFilters(1,&alFilter);
} }
alDeleteSources(1, &alSource);
} }
alSource = AL_NONE;
alFilter = AL_FILTER_NULL;
} }
void CChannel::Start() void CChannel::Start()
{ {
if ( !HasSource() ) return; if ( !HasSource() ) return;
if ( !Data ) return;
alBufferData(alBuffers[id], AL_FORMAT_MONO16, Data, DataSize, Frequency);
if ( LoopPoints[0] != 0 && LoopPoints[0] != -1 ) if ( LoopPoints[0] != 0 && LoopPoints[0] != -1 )
alBufferiv(alBuffer, AL_LOOP_POINTS_SOFT, LoopPoints); alBufferiv(alBuffers[id], AL_LOOP_POINTS_SOFT, LoopPoints);
alSourcei (alSource, AL_BUFFER, alBuffer); alSourcei(alSources[id], AL_BUFFER, alBuffers[id]);
alSourcePlay(alSource); alSourcePlay(alSources[id]);
} }
void CChannel::Stop() void CChannel::Stop()
{ {
if ( HasSource() ) if ( HasSource() )
alSourceStop(alSource); alSourceStop(alSources[id]);
Reset(); Reset();
} }
bool CChannel::HasSource() bool CChannel::HasSource()
{ {
return alSource != AL_NONE; return alSources[id] != AL_NONE;
} }
bool CChannel::IsUsed() bool CChannel::IsUsed()
@ -109,7 +130,7 @@ bool CChannel::IsUsed()
if ( HasSource() ) if ( HasSource() )
{ {
ALint sourceState; ALint sourceState;
alGetSourcei(alSource, AL_SOURCE_STATE, &sourceState); alGetSourcei(alSources[id], AL_SOURCE_STATE, &sourceState);
return sourceState == AL_PLAYING; return sourceState == AL_PLAYING;
} }
return false; return false;
@ -118,27 +139,24 @@ bool CChannel::IsUsed()
void CChannel::SetPitch(float pitch) void CChannel::SetPitch(float pitch)
{ {
if ( !HasSource() ) return; if ( !HasSource() ) return;
alSourcef(alSource, AL_PITCH, pitch); alSourcef(alSources[id], AL_PITCH, pitch);
} }
void CChannel::SetGain(float gain) void CChannel::SetGain(float gain)
{ {
if ( !HasSource() ) return; if ( !HasSource() ) return;
alSourcef(alSource, AL_GAIN, gain); alSourcef(alSources[id], AL_GAIN, gain);
} }
void CChannel::SetVolume(int32 vol) void CChannel::SetVolume(int32 vol)
{ {
SetGain(ALfloat(vol) / MAX_VOLUME); SetGain(ALfloat(vol) / MAX_VOLUME);
} }
void CChannel::SetSampleID(uint32 nSfx) void CChannel::SetSampleData(void *_data, size_t _DataSize, int32 freq)
{
Sample = nSfx;
}
void CChannel::SetFreq(int32 freq)
{ {
Data = _data;
DataSize = _DataSize;
Frequency = freq; Frequency = freq;
} }
@ -150,7 +168,7 @@ void CChannel::SetCurrentFreq(uint32 freq)
void CChannel::SetLoopCount(int32 loopCount) // fake. TODO: void CChannel::SetLoopCount(int32 loopCount) // fake. TODO:
{ {
if ( !HasSource() ) return; if ( !HasSource() ) return;
alSourcei(alSource, AL_LOOPING, loopCount == 1 ? AL_FALSE : AL_TRUE); alSourcei(alSources[id], AL_LOOPING, loopCount == 1 ? AL_FALSE : AL_TRUE);
} }
void CChannel::SetLoopPoints(ALint start, ALint end) void CChannel::SetLoopPoints(ALint start, ALint end)
@ -162,53 +180,49 @@ void CChannel::SetLoopPoints(ALint start, ALint end)
void CChannel::SetPosition(float x, float y, float z) void CChannel::SetPosition(float x, float y, float z)
{ {
if ( !HasSource() ) return; if ( !HasSource() ) return;
alSource3f(alSource, AL_POSITION, x, y, z); alSource3f(alSources[id], AL_POSITION, x, y, z);
} }
void CChannel::SetDistances(float max, float min) void CChannel::SetDistances(float max, float min)
{ {
if ( !HasSource() ) return; if ( !HasSource() ) return;
alSourcef (alSource, AL_MAX_DISTANCE, max); alSourcef (alSources[id], AL_MAX_DISTANCE, max);
alSourcef (alSource, AL_REFERENCE_DISTANCE, min); alSourcef (alSources[id], AL_REFERENCE_DISTANCE, min);
alSourcef (alSource, AL_MAX_GAIN, 1.0f); alSourcef (alSources[id], AL_MAX_GAIN, 1.0f);
alSourcef (alSource, AL_ROLLOFF_FACTOR, 1.0f); alSourcef (alSources[id], AL_ROLLOFF_FACTOR, 1.0f);
} }
void CChannel::SetPan(uint32 pan) void CChannel::SetPan(int32 pan)
{ {
SetPosition((pan-63)/64.0f, 0.0f, Sqrt(1.0f-SQR((pan-63)/64.0f))); SetPosition((pan-63)/64.0f, 0.0f, Sqrt(1.0f-SQR((pan-63)/64.0f)));
} }
void CChannel::SetBuffer(ALuint buffer)
{
alBuffer = buffer;
}
void CChannel::ClearBuffer() void CChannel::ClearBuffer()
{ {
if ( !HasSource() ) return; if ( !HasSource() ) return;
SetBuffer(AL_NONE); alSourcei(alSources[id], AL_BUFFER, AL_NONE);
alSourcei(alSource, AL_BUFFER, AL_NONE); Data = nil;
DataSize = 0;
} }
void CChannel::SetReverbMix(ALuint slot, float mix) void CChannel::SetReverbMix(ALuint slot, float mix)
{ {
if ( !IsFXSupported() ) return; if ( !IsFXSupported() ) return;
if ( !HasSource() ) return; if ( !HasSource() ) return;
if ( alFilter == AL_FILTER_NULL ) return; if ( alFilters[id] == AL_FILTER_NULL ) return;
Mix = mix; Mix = mix;
EAX3_SetReverbMix(alFilter, mix); EAX3_SetReverbMix(alFilters[id], mix);
alSource3i(alSource, AL_AUXILIARY_SEND_FILTER, slot, 0, alFilter); alSource3i(alSources[id], AL_AUXILIARY_SEND_FILTER, slot, 0, alFilters[id]);
} }
void CChannel::UpdateReverb(ALuint slot) void CChannel::UpdateReverb(ALuint slot)
{ {
if ( !IsFXSupported() ) return; if ( !IsFXSupported() ) return;
if ( !HasSource() ) return; if ( !HasSource() ) return;
if ( alFilter == AL_FILTER_NULL ) return; if ( alFilters[id] == AL_FILTER_NULL ) return;
EAX3_SetReverbMix(alFilter, Mix); EAX3_SetReverbMix(alFilters[id], Mix);
alSource3i(alSource, AL_AUXILIARY_SEND_FILTER, slot, 0, alFilter); alSource3i(alSources[id], AL_AUXILIARY_SEND_FILTER, slot, 0, alFilters[id]);
} }
#endif #endif

View File

@ -9,22 +9,24 @@
class CChannel class CChannel
{ {
ALuint alSource; uint32 id;
ALuint alFilter;
ALuint alBuffer;
float Pitch, Gain; float Pitch, Gain;
float Mix; float Mix;
void *Data;
size_t DataSize;
int32 Frequency; int32 Frequency;
float Position[3]; float Position[3];
float Distances[2]; float Distances[2];
int32 LoopCount; int32 LoopCount;
ALint LoopPoints[2]; ALint LoopPoints[2];
uint32 Sample;
public: public:
static void InitChannels();
static void DestroyChannels();
CChannel(); CChannel();
void SetDefault(); void SetDefault();
void Reset(); void Reset();
void Init(bool Is2D = false); void Init(uint32 _id, bool Is2D = false);
void Term(); void Term();
void Start(); void Start();
void Stop(); void Stop();
@ -33,15 +35,13 @@ public:
void SetPitch(float pitch); void SetPitch(float pitch);
void SetGain(float gain); void SetGain(float gain);
void SetVolume(int32 vol); void SetVolume(int32 vol);
void SetSampleID(uint32 nSfx); void SetSampleData(void *_data, size_t _DataSize, int32 freq);
void SetFreq(int32 freq);
void SetCurrentFreq(uint32 freq); void SetCurrentFreq(uint32 freq);
void SetLoopCount(int32 loopCount); // fake void SetLoopCount(int32 loopCount); // fake
void SetLoopPoints(ALint start, ALint end); void SetLoopPoints(ALint start, ALint end);
void SetPosition(float x, float y, float z); void SetPosition(float x, float y, float z);
void SetDistances(float max, float min); void SetDistances(float max, float min);
void SetPan(uint32 pan); void SetPan(int32 pan);
void SetBuffer(ALuint buffer);
void ClearBuffer(); void ClearBuffer();
void SetReverbMix(ALuint slot, float mix); void SetReverbMix(ALuint slot, float mix);
void UpdateReverb(ALuint slot); void UpdateReverb(ALuint slot);

View File

@ -153,11 +153,7 @@ public:
bool Initialise(void); bool Initialise(void);
void Terminate (void); void Terminate (void);
#ifdef AUDIO_OAL
void UpdateSoundBuffers(void);
#endif
bool CheckForAnAudioFileOnCD(void); bool CheckForAnAudioFileOnCD(void);
char GetCDAudioDriveLetter (void); char GetCDAudioDriveLetter (void);

View File

@ -98,58 +98,12 @@ int32 nPedSlotSfx [MAX_PEDSFX];
int32 nPedSlotSfxAddr[MAX_PEDSFX]; int32 nPedSlotSfxAddr[MAX_PEDSFX];
uint8 nCurrentPedSlot; uint8 nCurrentPedSlot;
ALuint pedBuffers[MAX_PEDSFX];
CChannel aChannel[MAXCHANNELS+MAX2DCHANNELS]; CChannel aChannel[MAXCHANNELS+MAX2DCHANNELS];
uint8 nChannelVolume[MAXCHANNELS+MAX2DCHANNELS]; uint8 nChannelVolume[MAXCHANNELS+MAX2DCHANNELS];
uint32 nStreamLength[TOTAL_STREAMED_SOUNDS]; uint32 nStreamLength[TOTAL_STREAMED_SOUNDS];
ALuint ALStreamSources[MAX_STREAMS]; ALuint ALStreamSources[MAX_STREAMS];
ALuint ALStreamBuffers[MAX_STREAMS][NUM_STREAMBUFFERS]; ALuint ALStreamBuffers[MAX_STREAMS][NUM_STREAMBUFFERS];
struct
{
ALuint buffer;
ALint timer;
bool IsEmpty() { return buffer == 0; }
void Set(ALuint buf) { buffer = buf; }
void Wait() { timer = 10000; }
void Init()
{
buffer = 0;
timer = 0;
}
void Term()
{
if (buffer != 0 && alIsBuffer(buffer)) {
alDeleteBuffers(1, &buffer);
assert(alGetError() == AL_NO_ERROR);
}
timer = 0;
buffer = 0;
}
void Update()
{
if ( !(timer > 0) ) return;
timer -= ALint(CTimer::GetTimeStepInMilliseconds());
if ( timer > 0 ) return;
timer = 0;
if ( buffer != 0 )
{
if (!alIsBuffer(buffer))
{
buffer = 0;
return;
}
alDeleteBuffers(1, &buffer);
ALenum error = alGetError();
if (error != AL_NO_ERROR)
timer = 10000;
else
buffer = 0;
}
}
}ALBuffers[SAMPLEBANK_MAX];
struct tMP3Entry struct tMP3Entry
{ {
@ -295,12 +249,7 @@ release_existing()
alDeleteBuffers(NUM_STREAMBUFFERS, ALStreamBuffers[i]); alDeleteBuffers(NUM_STREAMBUFFERS, ALStreamBuffers[i]);
} }
alDeleteBuffers(MAX_PEDSFX, pedBuffers); CChannel::DestroyChannels();
for ( int32 i = 0; i < SAMPLEBANK_MAX; i++ )
{
ALBuffers[i].Term();
}
if ( ALContext ) if ( ALContext )
{ {
@ -381,13 +330,6 @@ set_new_provider(int index)
stream->ProviderInit(); stream->ProviderInit();
} }
for ( int32 i = 0; i < SAMPLEBANK_MAX; i++ )
{
ALBuffers[i].Init();
}
alGenBuffers(MAX_PEDSFX, pedBuffers);
usingEAX = 0; usingEAX = 0;
usingEAX3 = 0; usingEAX3 = 0;
_usingEFX = false; _usingEFX = false;
@ -419,10 +361,12 @@ set_new_provider(int index)
} }
//SampleManager.SetSpeakerConfig(speaker_type); //SampleManager.SetSpeakerConfig(speaker_type);
CChannel::InitChannels();
for ( int32 i = 0; i < MAXCHANNELS; i++ ) for ( int32 i = 0; i < MAXCHANNELS; i++ )
aChannel[i].Init(); aChannel[i].Init(i);
aChannel[CHANNEL2D].Init(true); aChannel[CHANNEL2D].Init(CHANNEL2D, true);
if ( IsFXSupported() ) if ( IsFXSupported() )
{ {
@ -1166,7 +1110,7 @@ cSampleManager::Terminate(void)
_DeleteMP3Entries(); _DeleteMP3Entries();
CStream::Terminate(); CStream::Terminate();
if ( nSampleBankMemoryStartAddress[SFX_BANK_0] != 0 ) if ( nSampleBankMemoryStartAddress[SFX_BANK_0] != 0 )
{ {
free((void *)nSampleBankMemoryStartAddress[SFX_BANK_0]); free((void *)nSampleBankMemoryStartAddress[SFX_BANK_0]);
@ -1182,15 +1126,6 @@ cSampleManager::Terminate(void)
_bSampmanInitialised = false; _bSampmanInitialised = false;
} }
void
cSampleManager::UpdateSoundBuffers(void)
{
for ( int32 i = 0; i < SAMPLEBANK_MAX; i++ )
{
ALBuffers[i].Update();
}
}
bool cSampleManager::CheckForAnAudioFileOnCD(void) bool cSampleManager::CheckForAnAudioFileOnCD(void)
{ {
return true; return true;
@ -1399,13 +1334,7 @@ cSampleManager::LoadPedComment(uint32 nComment)
#endif #endif
nPedSlotSfx[nCurrentPedSlot] = nComment; nPedSlotSfx[nCurrentPedSlot] = nComment;
alBufferData(pedBuffers[nCurrentPedSlot],
AL_FORMAT_MONO16,
(void *)(nSampleBankMemoryStartAddress[SFX_BANK_PED_COMMENTS] + PED_BLOCKSIZE*nCurrentPedSlot),
m_aSamples[nComment].nSize,
m_aSamples[nComment].nFrequency);
if ( ++nCurrentPedSlot >= MAX_PEDSFX ) if ( ++nCurrentPedSlot >= MAX_PEDSFX )
nCurrentPedSlot = 0; nCurrentPedSlot = 0;
@ -1541,25 +1470,14 @@ cSampleManager::InitialiseChannel(uint32 nChannel, uint32 nSfx, uint8 nBank)
{ {
ASSERT( nChannel < MAXCHANNELS+MAX2DCHANNELS ); ASSERT( nChannel < MAXCHANNELS+MAX2DCHANNELS );
ALuint buffer; uintptr addr;
if ( nSfx < SAMPLEBANK_MAX ) if ( nSfx < SAMPLEBANK_MAX )
{ {
if ( !IsSampleBankLoaded(nBank) ) if ( !IsSampleBankLoaded(nBank) )
return false; return false;
uintptr addr = nSampleBankMemoryStartAddress[nBank] + m_aSamples[nSfx].nOffset - m_aSamples[BankStartOffset[nBank]].nOffset; addr = nSampleBankMemoryStartAddress[nBank] + m_aSamples[nSfx].nOffset - m_aSamples[BankStartOffset[nBank]].nOffset;
if ( ALBuffers[nSfx].IsEmpty() )
{
ALuint buf;
alGenBuffers(1, &buf);
alBufferData(buf, AL_FORMAT_MONO16, (void *)addr, m_aSamples[nSfx].nSize, m_aSamples[nSfx].nFrequency);
ALBuffers[nSfx].Set(buf);
}
ALBuffers[nSfx].Wait();
buffer = ALBuffers[nSfx].buffer;
} }
else else
{ {
@ -1567,14 +1485,7 @@ cSampleManager::InitialiseChannel(uint32 nChannel, uint32 nSfx, uint8 nBank)
return false; return false;
int32 slot = _GetPedCommentSlot(nSfx); int32 slot = _GetPedCommentSlot(nSfx);
addr = (nSampleBankMemoryStartAddress[SFX_BANK_PED_COMMENTS] + PED_BLOCKSIZE * slot);
buffer = pedBuffers[slot];
}
if ( buffer == 0 )
{
TRACE("No buffer to play id %d", nSfx);
return false;
} }
if ( GetChannelUsedFlag(nChannel) ) if ( GetChannelUsedFlag(nChannel) )
@ -1586,10 +1497,8 @@ cSampleManager::InitialiseChannel(uint32 nChannel, uint32 nSfx, uint8 nBank)
aChannel[nChannel].Reset(); aChannel[nChannel].Reset();
if ( aChannel[nChannel].HasSource() ) if ( aChannel[nChannel].HasSource() )
{ {
aChannel[nChannel].SetSampleID (nSfx); aChannel[nChannel].SetSampleData ((void*)addr, m_aSamples[nSfx].nSize, m_aSamples[nSfx].nFrequency);
aChannel[nChannel].SetFreq (m_aSamples[nSfx].nFrequency);
aChannel[nChannel].SetLoopPoints (0, -1); aChannel[nChannel].SetLoopPoints (0, -1);
aChannel[nChannel].SetBuffer (buffer);
aChannel[nChannel].SetPitch (1.0f); aChannel[nChannel].SetPitch (1.0f);
return true; return true;
} }
@ -2040,8 +1949,6 @@ cSampleManager::Service(void)
if ( stream ) if ( stream )
stream->Update(); stream->Update();
} }
UpdateSoundBuffers();
} }
bool bool