1
0
Fork 0
mirror of https://github.com/halpz/re3.git synced 2024-12-24 17:55:29 +00:00

OAL Loops, fixes

This commit is contained in:
erorcun 2021-02-02 16:39:08 +03:00
parent 1b293a3cfb
commit 713562685a
6 changed files with 143 additions and 66 deletions

View file

@ -15,6 +15,8 @@ ALuint alFilters[MAXCHANNELS+MAX2DCHANNELS];
ALuint alBuffers[MAXCHANNELS+MAX2DCHANNELS]; ALuint alBuffers[MAXCHANNELS+MAX2DCHANNELS];
bool bChannelsCreated = false; bool bChannelsCreated = false;
int32 CChannel::channelsThatNeedService = 0;
void void
CChannel::InitChannels() CChannel::InitChannels()
{ {
@ -59,7 +61,9 @@ void CChannel::SetDefault()
Position[0] = 0.0f; Position[1] = 0.0f; Position[2] = 0.0f; Position[0] = 0.0f; Position[1] = 0.0f; Position[2] = 0.0f;
Distances[0] = 0.0f; Distances[1] = FLT_MAX; Distances[0] = 0.0f; Distances[1] = FLT_MAX;
LoopCount = 1; LoopCount = 1;
LastProcessedOffset = UINT32_MAX;
LoopPoints[0] = 0; LoopPoints[1] = -1; LoopPoints[0] = 0; LoopPoints[1] = -1;
Frequency = MAX_FREQ; Frequency = MAX_FREQ;
@ -67,6 +71,10 @@ void CChannel::SetDefault()
void CChannel::Reset() void CChannel::Reset()
{ {
// Here is safe because ctor don't call this
if (LoopCount > 1)
channelsThatNeedService--;
ClearBuffer(); ClearBuffer();
SetDefault(); SetDefault();
} }
@ -165,10 +173,51 @@ void CChannel::SetCurrentFreq(uint32 freq)
SetPitch(ALfloat(freq) / Frequency); SetPitch(ALfloat(freq) / Frequency);
} }
void CChannel::SetLoopCount(int32 loopCount) // fake. TODO: void CChannel::SetLoopCount(int32 count)
{ {
if ( !HasSource() ) return; if ( !HasSource() ) return;
alSourcei(alSources[id], AL_LOOPING, loopCount == 1 ? AL_FALSE : AL_TRUE);
// 0: loop indefinitely, 1: play one time, 2: play two times etc...
// only > 1 needs manual processing
if (LoopCount > 1 && count < 2)
channelsThatNeedService--;
else if (LoopCount < 2 && count > 1)
channelsThatNeedService++;
alSourcei(alSources[id], AL_LOOPING, count == 1 ? AL_FALSE : AL_TRUE);
LoopCount = count;
}
bool CChannel::Update()
{
if (!HasSource()) return false;
if (LoopCount < 2) return false;
ALint state;
alGetSourcei(alSources[id], AL_SOURCE_STATE, &state);
if (state == AL_STOPPED) {
debug("Looping channels(%d in this case) shouldn't report AL_STOPPED, but nvm\n", id);
SetLoopCount(1);
return true;
}
assert(channelsThatNeedService > 0 && "Ref counting is broken");
ALint offset;
alGetSourcei(alSources[id], AL_SAMPLE_OFFSET, &offset);
// Rewound
if (offset < LastProcessedOffset) {
LoopCount--;
if (LoopCount == 1) {
// Playing last tune...
channelsThatNeedService--;
alSourcei(alSources[id], AL_LOOPING, AL_FALSE);
}
}
LastProcessedOffset = offset;
return true;
} }
void CChannel::SetLoopPoints(ALint start, ALint end) void CChannel::SetLoopPoints(ALint start, ALint end)
@ -200,6 +249,7 @@ void CChannel::SetPan(int32 pan)
void CChannel::ClearBuffer() void CChannel::ClearBuffer()
{ {
if ( !HasSource() ) return; if ( !HasSource() ) return;
alSourcei(alSources[id], AL_LOOPING, AL_FALSE);
alSourcei(alSources[id], AL_BUFFER, AL_NONE); alSourcei(alSources[id], AL_BUFFER, AL_NONE);
Data = nil; Data = nil;
DataSize = 0; DataSize = 0;

View file

@ -19,7 +19,10 @@ class CChannel
float Distances[2]; float Distances[2];
int32 LoopCount; int32 LoopCount;
ALint LoopPoints[2]; ALint LoopPoints[2];
ALint LastProcessedOffset;
public: public:
static int32 channelsThatNeedService;
static void InitChannels(); static void InitChannels();
static void DestroyChannels(); static void DestroyChannels();
@ -37,7 +40,7 @@ public:
void SetVolume(int32 vol); void SetVolume(int32 vol);
void SetSampleData(void *_data, size_t _DataSize, int32 freq); void SetSampleData(void *_data, size_t _DataSize, int32 freq);
void SetCurrentFreq(uint32 freq); void SetCurrentFreq(uint32 freq);
void SetLoopCount(int32 loopCount); // fake void SetLoopCount(int32 count);
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);
@ -45,6 +48,7 @@ public:
void ClearBuffer(); void ClearBuffer();
void SetReverbMix(ALuint slot, float mix); void SetReverbMix(ALuint slot, float mix);
void UpdateReverb(ALuint slot); void UpdateReverb(ALuint slot);
bool Update();
}; };
#endif #endif

View file

@ -499,6 +499,7 @@ public:
m_bOpened = mpg123_open(m_pMH, path) == MPG123_OK m_bOpened = mpg123_open(m_pMH, path) == MPG123_OK
&& mpg123_getformat(m_pMH, &rate, &channels, &encoding) == MPG123_OK; && mpg123_getformat(m_pMH, &rate, &channels, &encoding) == MPG123_OK;
m_nRate = rate; m_nRate = rate;
m_nChannels = channels; m_nChannels = channels;
@ -980,7 +981,8 @@ CStream::CStream(char *filename, ALuint *sources, ALuint (&buffers)[NUM_STREAMBU
m_bReset(false), m_bReset(false),
m_nVolume(0), m_nVolume(0),
m_nPan(0), m_nPan(0),
m_nPosBeforeReset(0) m_nPosBeforeReset(0),
m_nLoopCount(1)
{ {
// Be case-insensitive on linux (from https://github.com/OneSadCookie/fcaseopen/) // Be case-insensitive on linux (from https://github.com/OneSadCookie/fcaseopen/)
@ -1078,7 +1080,7 @@ bool CStream::IsPlaying()
ALint sourceState[2]; ALint sourceState[2];
alGetSourcei(m_pAlSources[0], AL_SOURCE_STATE, &sourceState[0]); alGetSourcei(m_pAlSources[0], AL_SOURCE_STATE, &sourceState[0]);
alGetSourcei(m_pAlSources[1], AL_SOURCE_STATE, &sourceState[1]); alGetSourcei(m_pAlSources[1], AL_SOURCE_STATE, &sourceState[1]);
if ( m_bActive || sourceState[0] == AL_PLAYING || sourceState[1] == AL_PLAYING) if (sourceState[0] == AL_PLAYING || sourceState[1] == AL_PLAYING)
return true; return true;
} }
@ -1236,6 +1238,8 @@ bool CStream::Setup()
{ {
if ( IsOpened() ) if ( IsOpened() )
{ {
alSourcei(m_pAlSources[0], AL_LOOPING, AL_FALSE);
alSourcei(m_pAlSources[1], AL_LOOPING, AL_FALSE);
m_pSoundFile->Seek(0); m_pSoundFile->Seek(0);
//SetPosition(0.0f, 0.0f, 0.0f); //SetPosition(0.0f, 0.0f, 0.0f);
SetPitch(1.0f); SetPitch(1.0f);
@ -1246,6 +1250,13 @@ bool CStream::Setup()
return IsOpened(); return IsOpened();
} }
void CStream::SetLoopCount(int32 count)
{
if ( !HasSource() ) return;
m_nLoopCount = count;
}
void CStream::SetPlay(bool state) void CStream::SetPlay(bool state)
{ {
if ( !HasSource() ) return; if ( !HasSource() ) return;
@ -1305,7 +1316,7 @@ void CStream::Update()
if ( !m_bPaused ) if ( !m_bPaused )
{ {
ALint sourceState[2]; ALint totalBuffers[2] = { 0, 0 };
ALint buffersProcessed[2] = { 0, 0 }; ALint buffersProcessed[2] = { 0, 0 };
// Relying a lot on left buffer states in here // Relying a lot on left buffer states in here
@ -1313,25 +1324,32 @@ void CStream::Update()
do do
{ {
//alSourcef(m_pAlSources[0], AL_ROLLOFF_FACTOR, 0.0f); //alSourcef(m_pAlSources[0], AL_ROLLOFF_FACTOR, 0.0f);
alGetSourcei(m_pAlSources[0], AL_SOURCE_STATE, &sourceState[0]); alGetSourcei(m_pAlSources[0], AL_BUFFERS_QUEUED, &totalBuffers[0]);
alGetSourcei(m_pAlSources[0], AL_BUFFERS_PROCESSED, &buffersProcessed[0]); alGetSourcei(m_pAlSources[0], AL_BUFFERS_PROCESSED, &buffersProcessed[0]);
//alSourcef(m_pAlSources[1], AL_ROLLOFF_FACTOR, 0.0f); //alSourcef(m_pAlSources[1], AL_ROLLOFF_FACTOR, 0.0f);
alGetSourcei(m_pAlSources[1], AL_SOURCE_STATE, &sourceState[1]); alGetSourcei(m_pAlSources[1], AL_BUFFERS_QUEUED, &totalBuffers[1]);
alGetSourcei(m_pAlSources[1], AL_BUFFERS_PROCESSED, &buffersProcessed[1]); alGetSourcei(m_pAlSources[1], AL_BUFFERS_PROCESSED, &buffersProcessed[1]);
} while (buffersProcessed[0] != buffersProcessed[1]); } while (buffersProcessed[0] != buffersProcessed[1]);
ALint looping = AL_FALSE;
alGetSourcei(m_pAlSources[0], AL_LOOPING, &looping);
if ( looping == AL_TRUE )
{
TRACE("stream set looping");
alSourcei(m_pAlSources[0], AL_LOOPING, AL_TRUE);
alSourcei(m_pAlSources[1], AL_LOOPING, AL_TRUE);
}
assert(buffersProcessed[0] == buffersProcessed[1]); assert(buffersProcessed[0] == buffersProcessed[1]);
// Correcting OpenAL concepts here:
// AL_BUFFERS_QUEUED = Number of *all* buffers in queue, including processed, processing and pending
// AL_BUFFERS_PROCESSED = Index of the buffer being processing right now. Buffers coming after that(have greater index) are pending buffers.
// which means: totalBuffers[0] - buffersProcessed[0] = pending buffers
bool buffersRefilled = false;
// We should wait queue to be cleared to loop track, because position calculation relies on queue.
if (m_nLoopCount != 1 && m_bActive && totalBuffers[0] == 0)
{
Setup();
buffersRefilled = FillBuffers() != 0;
if (m_nLoopCount != 0)
m_nLoopCount--;
}
else
{
while( buffersProcessed[0]-- ) while( buffersProcessed[0]-- )
{ {
ALuint buffer[2]; ALuint buffer[2];
@ -1341,16 +1359,16 @@ void CStream::Update()
if (m_bActive && FillBuffer(buffer)) if (m_bActive && FillBuffer(buffer))
{ {
buffersRefilled = true;
alSourceQueueBuffers(m_pAlSources[0], 1, &buffer[0]); alSourceQueueBuffers(m_pAlSources[0], 1, &buffer[0]);
alSourceQueueBuffers(m_pAlSources[1], 1, &buffer[1]); alSourceQueueBuffers(m_pAlSources[1], 1, &buffer[1]);
} }
} }
if ( sourceState[0] != AL_PLAYING )
{
alGetSourcei(m_pAlSources[0], AL_BUFFERS_PROCESSED, &buffersProcessed[0]);
SetPlay(buffersProcessed[0]!=0);
} }
// Two reasons: 1-Source may be starved to audio and stopped itself, 2- We're already waiting it to starve and die for looping track!
if (m_bActive && (buffersRefilled || (totalBuffers[1] - buffersProcessed[1] != 0)))
SetPlay(true);
} }
} }
@ -1362,6 +1380,7 @@ void CStream::ProviderInit()
{ {
SetPan(m_nPan); SetPan(m_nPan);
SetVolume(m_nVolume); SetVolume(m_nVolume);
SetLoopCount(m_nLoopCount);
SetPosMS(m_nPosBeforeReset); SetPosMS(m_nPosBeforeReset);
if (m_bActive) if (m_bActive)
FillBuffers(); FillBuffers();

View file

@ -69,6 +69,7 @@ class CStream
uint32 m_nVolume; uint32 m_nVolume;
uint8 m_nPan; uint8 m_nPan;
uint32 m_nPosBeforeReset; uint32 m_nPosBeforeReset;
int32 m_nLoopCount;
IDecoder *m_pSoundFile; IDecoder *m_pSoundFile;
@ -103,6 +104,8 @@ public:
void Start(); void Start();
void Stop(); void Stop();
void Update(void); void Update(void);
void SetLoopCount(int32);
void ProviderInit(); void ProviderInit();
void ProviderTerm(); void ProviderTerm();

View file

@ -46,7 +46,6 @@
//TODO: fix eax3 reverb //TODO: fix eax3 reverb
//TODO: max channels //TODO: max channels
//TODO: loop count
cSampleManager SampleManager; cSampleManager SampleManager;
bool _bSampmanInitialised = false; bool _bSampmanInitialised = false;
@ -1695,7 +1694,7 @@ cSampleManager::PreloadStreamedFile(uint32 nFile, uint8 nStream)
ASSERT(stream != NULL); ASSERT(stream != NULL);
aStream[nStream] = stream; aStream[nStream] = stream;
if ( !stream->IsOpened() ) if ( !stream->Setup() )
{ {
delete stream; delete stream;
aStream[nStream] = NULL; aStream[nStream] = NULL;
@ -1725,7 +1724,7 @@ cSampleManager::StartPreloadedStreamedFile(uint8 nStream)
if ( stream ) if ( stream )
{ {
if ( stream->Setup() ) if ( stream->IsOpened() )
{ {
stream->Start(); stream->Start();
} }
@ -1771,13 +1770,13 @@ cSampleManager::StartStreamedFile(uint32 nFile, uint32 nPos, uint8 nStream)
aStream[nStream] = stream; aStream[nStream] = stream;
if (stream->IsOpened()) {
if (stream->Setup()) { if (stream->Setup()) {
stream->SetLoopCount(nStreamLoopedFlag[nStream] ? 0 : 1);
nStreamLoopedFlag[nStream] = true;
if (position != 0) if (position != 0)
stream->SetPosMS(position); stream->SetPosMS(position);
stream->Start(); stream->Start();
}
return true; return true;
} else { } else {
@ -1798,10 +1797,8 @@ cSampleManager::StartStreamedFile(uint32 nFile, uint32 nPos, uint8 nStream)
aStream[nStream] = new CStream(filename, ALStreamSources[nStream], ALStreamBuffers[nStream], IsThisTrackAt16KHz(nFile) ? 16000 : 32000); aStream[nStream] = new CStream(filename, ALStreamSources[nStream], ALStreamBuffers[nStream], IsThisTrackAt16KHz(nFile) ? 16000 : 32000);
} }
if (aStream[nStream]->IsOpened()) {
if (aStream[nStream]->Setup()) { if (aStream[nStream]->Setup()) {
aStream[nStream]->Start(); aStream[nStream]->Start();
}
return true; return true;
} else { } else {
@ -1827,13 +1824,13 @@ cSampleManager::StartStreamedFile(uint32 nFile, uint32 nPos, uint8 nStream)
aStream[nStream] = stream; aStream[nStream] = stream;
if (stream->IsOpened()) {
if (stream->Setup()) { if (stream->Setup()) {
stream->SetLoopCount(nStreamLoopedFlag[nStream] ? 0 : 1);
nStreamLoopedFlag[nStream] = true;
if (position != 0) if (position != 0)
stream->SetPosMS(position); stream->SetPosMS(position);
stream->Start(); stream->Start();
}
return true; return true;
} else { } else {
@ -1854,13 +1851,11 @@ cSampleManager::StartStreamedFile(uint32 nFile, uint32 nPos, uint8 nStream)
aStream[nStream] = new CStream(filename, ALStreamSources[nStream], ALStreamBuffers[nStream]); aStream[nStream] = new CStream(filename, ALStreamSources[nStream], ALStreamBuffers[nStream]);
} }
if (aStream[nStream]->IsOpened()) {
if (aStream[nStream]->Setup()) { if (aStream[nStream]->Setup()) {
if (position != 0) if (position != 0)
aStream[nStream]->SetPosMS(position); aStream[nStream]->SetPosMS(position);
aStream[nStream]->Start(); aStream[nStream]->Start();
}
_bIsMp3Active = true; _bIsMp3Active = true;
return true; return true;
@ -1884,13 +1879,13 @@ cSampleManager::StartStreamedFile(uint32 nFile, uint32 nPos, uint8 nStream)
aStream[nStream] = stream; aStream[nStream] = stream;
if ( stream->IsOpened() ) {
if ( stream->Setup() ) { if ( stream->Setup() ) {
stream->SetLoopCount(nStreamLoopedFlag[nStream] ? 0 : 1);
nStreamLoopedFlag[nStream] = true;
if (position != 0) if (position != 0)
stream->SetPosMS(position); stream->SetPosMS(position);
stream->Start(); stream->Start();
}
return true; return true;
} else { } else {
@ -2001,6 +1996,12 @@ cSampleManager::Service(void)
if ( stream ) if ( stream )
stream->Update(); stream->Update();
} }
int refCount = CChannel::channelsThatNeedService;
for ( int32 i = 0; refCount && i < MAXCHANNELS+MAX2DCHANNELS; i++ )
{
if ( aChannel[i].Update() )
refCount--;
}
} }
bool bool

View file

@ -5591,7 +5591,7 @@ CMenuManager::DrawQuitGameScreen(void)
if (splash == nil) if (splash == nil)
splash = LoadSplash("OUTRO"); splash = LoadSplash("OUTRO");
m_aFrontEndSprites[MENUSPRITE_VCLOGO].Draw(CRect(MENU_X(28.0f), MENU_Y(8.0f), MENU_X(157.0f), MENU_Y(138.0f)), CRGBA(255, 255, 255, 255 - alpha)); m_aFrontEndSprites[MENUSPRITE_VCLOGO].Draw(CRect(SCREEN_STRETCH_X(28.0f), MENU_Y(8.0f), SCREEN_STRETCH_X(27.0f) + MENU_X(130.f), MENU_Y(138.0f)), CRGBA(255, 255, 255, 255 - alpha));
// Or we can see menu background from sides // Or we can see menu background from sides
#ifdef ASPECT_RATIO_SCALE #ifdef ASPECT_RATIO_SCALE