mirror of
https://github.com/halpz/re3.git
synced 2025-06-27 11:56:19 +00:00
oal wav/mp3 stream update
This commit is contained in:
@ -1,20 +1,21 @@
|
||||
#include "channel.h"
|
||||
|
||||
#ifdef AUDIO_OAL
|
||||
#include "common.h"
|
||||
#include "sampman.h"
|
||||
|
||||
extern bool IsFXSupported();
|
||||
|
||||
CChannel::CChannel()
|
||||
{
|
||||
alChannel = AL_NONE;
|
||||
alSource = AL_NONE;
|
||||
alFilter = AL_FILTER_NULL;
|
||||
SetDefault();
|
||||
}
|
||||
|
||||
void CChannel::SetDefault()
|
||||
{
|
||||
Buffer = AL_NONE;
|
||||
alBuffer = AL_NONE;
|
||||
|
||||
Pitch = 1.0f;
|
||||
Gain = 1.0f;
|
||||
@ -37,17 +38,17 @@ void CChannel::Reset()
|
||||
void CChannel::Init(bool Is2D)
|
||||
{
|
||||
ASSERT(!HasSource());
|
||||
alGenSources(1, &alChannel);
|
||||
alGenSources(1, &alSource);
|
||||
if ( HasSource() )
|
||||
{
|
||||
alSourcei(alChannel, AL_SOURCE_RELATIVE, AL_TRUE);
|
||||
alSourcei(alSource, AL_SOURCE_RELATIVE, AL_TRUE);
|
||||
if ( IsFXSupported() )
|
||||
alSource3i(alChannel, AL_AUXILIARY_SEND_FILTER, AL_EFFECTSLOT_NULL, 0, AL_FILTER_NULL);
|
||||
alSource3i(alSource, AL_AUXILIARY_SEND_FILTER, AL_EFFECTSLOT_NULL, 0, AL_FILTER_NULL);
|
||||
|
||||
if ( Is2D )
|
||||
{
|
||||
alSource3f(alChannel, AL_POSITION, 0.0f, 0.0f, 0.0f);
|
||||
alSourcef (alChannel, AL_GAIN, 1.0f);
|
||||
alSource3f(alSource, AL_POSITION, 0.0f, 0.0f, 0.0f);
|
||||
alSourcef (alSource, AL_GAIN, 1.0f);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -64,15 +65,15 @@ void CChannel::Term()
|
||||
{
|
||||
if ( IsFXSupported() )
|
||||
{
|
||||
alSource3i(alChannel, AL_AUXILIARY_SEND_FILTER, AL_EFFECTSLOT_NULL, 0, AL_FILTER_NULL);
|
||||
alSource3i(alSource, AL_AUXILIARY_SEND_FILTER, AL_EFFECTSLOT_NULL, 0, AL_FILTER_NULL);
|
||||
|
||||
if(alFilter != AL_FILTER_NULL)
|
||||
alDeleteFilters(1,&alFilter);
|
||||
}
|
||||
|
||||
alDeleteSources(1, &alChannel);
|
||||
alDeleteSources(1, &alSource);
|
||||
}
|
||||
alChannel = AL_NONE;
|
||||
alSource = AL_NONE;
|
||||
alFilter = AL_FILTER_NULL;
|
||||
}
|
||||
|
||||
@ -81,22 +82,22 @@ void CChannel::Start()
|
||||
if ( !HasSource() ) return;
|
||||
|
||||
if ( LoopPoints[0] != 0 && LoopPoints[0] != -1 )
|
||||
alBufferiv(Buffer, AL_LOOP_POINTS_SOFT, LoopPoints);
|
||||
alSourcei (alChannel, AL_BUFFER, Buffer);
|
||||
alSourcePlay(alChannel);
|
||||
alBufferiv(alBuffer, AL_LOOP_POINTS_SOFT, LoopPoints);
|
||||
alSourcei (alSource, AL_BUFFER, alBuffer);
|
||||
alSourcePlay(alSource);
|
||||
}
|
||||
|
||||
void CChannel::Stop()
|
||||
{
|
||||
if ( HasSource() )
|
||||
alSourceStop(alChannel);
|
||||
alSourceStop(alSource);
|
||||
|
||||
Reset();
|
||||
}
|
||||
|
||||
bool CChannel::HasSource()
|
||||
{
|
||||
return alChannel != AL_NONE;
|
||||
return alSource != AL_NONE;
|
||||
}
|
||||
|
||||
bool CChannel::IsUsed()
|
||||
@ -104,7 +105,7 @@ bool CChannel::IsUsed()
|
||||
if ( HasSource() )
|
||||
{
|
||||
ALint sourceState;
|
||||
alGetSourcei(alChannel, AL_SOURCE_STATE, &sourceState);
|
||||
alGetSourcei(alSource, AL_SOURCE_STATE, &sourceState);
|
||||
return sourceState == AL_PLAYING;
|
||||
}
|
||||
return false;
|
||||
@ -113,13 +114,13 @@ bool CChannel::IsUsed()
|
||||
void CChannel::SetPitch(float pitch)
|
||||
{
|
||||
if ( !HasSource() ) return;
|
||||
alSourcef(alChannel, AL_PITCH, pitch);
|
||||
alSourcef(alSource, AL_PITCH, pitch);
|
||||
}
|
||||
|
||||
void CChannel::SetGain(float gain)
|
||||
{
|
||||
if ( !HasSource() ) return;
|
||||
alSourcef(alChannel, AL_GAIN, gain);
|
||||
alSourcef(alSource, AL_GAIN, gain);
|
||||
}
|
||||
|
||||
void CChannel::SetVolume(int32 vol)
|
||||
@ -145,7 +146,7 @@ void CChannel::SetCurrentFreq(uint32 freq)
|
||||
void CChannel::SetLoopCount(int32 loopCount) // fake. TODO:
|
||||
{
|
||||
if ( !HasSource() ) return;
|
||||
alSourcei(alChannel, AL_LOOPING, loopCount == 1 ? AL_FALSE : AL_TRUE);
|
||||
alSourcei(alSource, AL_LOOPING, loopCount == 1 ? AL_FALSE : AL_TRUE);
|
||||
}
|
||||
|
||||
void CChannel::SetLoopPoints(ALint start, ALint end)
|
||||
@ -157,33 +158,33 @@ void CChannel::SetLoopPoints(ALint start, ALint end)
|
||||
void CChannel::SetPosition(float x, float y, float z)
|
||||
{
|
||||
if ( !HasSource() ) return;
|
||||
alSource3f(alChannel, AL_POSITION, x, y, z);
|
||||
alSource3f(alSource, AL_POSITION, x, y, z);
|
||||
}
|
||||
|
||||
void CChannel::SetDistances(float max, float min)
|
||||
{
|
||||
if ( !HasSource() ) return;
|
||||
alSourcef (alChannel, AL_MAX_DISTANCE, max);
|
||||
alSourcef (alChannel, AL_REFERENCE_DISTANCE, min);
|
||||
alSourcef (alChannel, AL_MAX_GAIN, 1.0f);
|
||||
alSourcef (alChannel, AL_ROLLOFF_FACTOR, 1.0f);
|
||||
alSourcef (alSource, AL_MAX_DISTANCE, max);
|
||||
alSourcef (alSource, AL_REFERENCE_DISTANCE, min);
|
||||
alSourcef (alSource, AL_MAX_GAIN, 1.0f);
|
||||
alSourcef (alSource, AL_ROLLOFF_FACTOR, 1.0f);
|
||||
}
|
||||
|
||||
void CChannel::SetPan(uint32 pan)
|
||||
{
|
||||
SetPosition((pan-63)/64.0f, 0.0f, sqrtf(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)
|
||||
{
|
||||
Buffer = buffer;
|
||||
alBuffer = buffer;
|
||||
}
|
||||
|
||||
void CChannel::ClearBuffer()
|
||||
{
|
||||
if ( !HasSource() ) return;
|
||||
SetBuffer(AL_NONE);
|
||||
alSourcei(alChannel, AL_BUFFER, AL_NONE);
|
||||
alSourcei(alSource, AL_BUFFER, AL_NONE);
|
||||
}
|
||||
|
||||
void CChannel::SetReverbMix(ALuint slot, float mix)
|
||||
@ -194,7 +195,7 @@ void CChannel::SetReverbMix(ALuint slot, float mix)
|
||||
|
||||
Mix = mix;
|
||||
EAX3_SetReverbMix(alFilter, mix);
|
||||
alSource3i(alChannel, AL_AUXILIARY_SEND_FILTER, slot, 0, alFilter);
|
||||
alSource3i(alSource, AL_AUXILIARY_SEND_FILTER, slot, 0, alFilter);
|
||||
}
|
||||
|
||||
void CChannel::UpdateReverb(ALuint slot)
|
||||
@ -203,7 +204,7 @@ void CChannel::UpdateReverb(ALuint slot)
|
||||
if ( !HasSource() ) return;
|
||||
if ( alFilter == AL_FILTER_NULL ) return;
|
||||
EAX3_SetReverbMix(alFilter, Mix);
|
||||
alSource3i(alChannel, AL_AUXILIARY_SEND_FILTER, slot, 0, alFilter);
|
||||
alSource3i(alSource, AL_AUXILIARY_SEND_FILTER, slot, 0, alFilter);
|
||||
}
|
||||
|
||||
#endif
|
@ -10,9 +10,9 @@
|
||||
|
||||
class CChannel
|
||||
{
|
||||
ALuint alChannel;
|
||||
ALuint alSource;
|
||||
ALuint alFilter;
|
||||
ALuint Buffer;
|
||||
ALuint alBuffer;
|
||||
float Pitch, Gain;
|
||||
float Mix;
|
||||
int32 Frequency;
|
||||
|
@ -1,48 +1,223 @@
|
||||
#include "stream.h"
|
||||
#include "common.h"
|
||||
|
||||
#ifdef AUDIO_OAL
|
||||
#include "common.h"
|
||||
#include "sampman.h"
|
||||
|
||||
typedef long ssize_t;
|
||||
|
||||
#include <sndfile.h>
|
||||
#include <mpg123.h>
|
||||
|
||||
#pragma comment( lib, "libsndfile-1.lib" )
|
||||
#pragma comment( lib, "libmpg123.lib" )
|
||||
|
||||
class CSndFile : public IDecoder
|
||||
{
|
||||
SNDFILE *m_pfSound;
|
||||
SF_INFO m_soundInfo;
|
||||
public:
|
||||
CSndFile(const char *path) :
|
||||
m_pfSound(nil)
|
||||
{
|
||||
memset(&m_soundInfo, 0, sizeof(m_soundInfo));
|
||||
m_pfSound = sf_open(path, SFM_READ, &m_soundInfo);
|
||||
}
|
||||
|
||||
~CSndFile()
|
||||
{
|
||||
if ( m_pfSound )
|
||||
{
|
||||
sf_close(m_pfSound);
|
||||
m_pfSound = nil;
|
||||
}
|
||||
}
|
||||
|
||||
bool IsOpened()
|
||||
{
|
||||
return m_pfSound != nil;
|
||||
}
|
||||
|
||||
uint32 GetSampleSize()
|
||||
{
|
||||
return sizeof(uint16);
|
||||
}
|
||||
|
||||
uint32 GetSampleCount()
|
||||
{
|
||||
return m_soundInfo.frames;
|
||||
}
|
||||
|
||||
uint32 GetSampleRate()
|
||||
{
|
||||
return m_soundInfo.samplerate;
|
||||
}
|
||||
|
||||
uint32 GetChannels()
|
||||
{
|
||||
return m_soundInfo.channels;
|
||||
}
|
||||
|
||||
void Seek(uint32 milliseconds)
|
||||
{
|
||||
if ( !IsOpened() ) return;
|
||||
sf_seek(m_pfSound, ms2samples(milliseconds), SF_SEEK_SET);
|
||||
}
|
||||
|
||||
uint32 Tell()
|
||||
{
|
||||
if ( !IsOpened() ) return 0;
|
||||
return samples2ms(sf_seek(m_pfSound, 0, SF_SEEK_CUR));
|
||||
}
|
||||
|
||||
uint32 Decode(void *buffer)
|
||||
{
|
||||
if ( !IsOpened() ) return 0;
|
||||
return sf_read_short(m_pfSound, (short *)buffer, GetBufferSamples()) * GetSampleSize();
|
||||
}
|
||||
};
|
||||
|
||||
class CMP3File : public IDecoder
|
||||
{
|
||||
mpg123_handle *m_pMH;
|
||||
bool m_bOpened;
|
||||
uint32 m_nRate;
|
||||
uint32 m_nChannels;
|
||||
public:
|
||||
CMP3File(const char *path) :
|
||||
m_pMH(nil),
|
||||
m_bOpened(false),
|
||||
m_nRate(0),
|
||||
m_nChannels(0)
|
||||
{
|
||||
m_pMH = mpg123_new(nil, nil);
|
||||
if ( m_pMH )
|
||||
{
|
||||
long rate = 0;
|
||||
int channels = 0;
|
||||
int encoding = 0;
|
||||
|
||||
m_bOpened = mpg123_open(m_pMH, path) == MPG123_OK
|
||||
&& mpg123_getformat(m_pMH, &rate, &channels, &encoding) == MPG123_OK;
|
||||
m_nRate = rate;
|
||||
m_nChannels = channels;
|
||||
|
||||
if ( IsOpened() )
|
||||
{
|
||||
mpg123_format_none(m_pMH);
|
||||
mpg123_format(m_pMH, rate, channels, encoding);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
~CMP3File()
|
||||
{
|
||||
if ( m_pMH )
|
||||
{
|
||||
mpg123_close(m_pMH);
|
||||
mpg123_delete(m_pMH);
|
||||
m_pMH = nil;
|
||||
}
|
||||
}
|
||||
|
||||
bool IsOpened()
|
||||
{
|
||||
return m_bOpened;
|
||||
}
|
||||
|
||||
uint32 GetSampleSize()
|
||||
{
|
||||
return sizeof(uint16);
|
||||
}
|
||||
|
||||
uint32 GetSampleCount()
|
||||
{
|
||||
if ( !IsOpened() ) return 0;
|
||||
return mpg123_length(m_pMH);
|
||||
}
|
||||
|
||||
uint32 GetSampleRate()
|
||||
{
|
||||
return m_nRate;
|
||||
}
|
||||
|
||||
uint32 GetChannels()
|
||||
{
|
||||
return m_nChannels;
|
||||
}
|
||||
|
||||
void Seek(uint32 milliseconds)
|
||||
{
|
||||
if ( !IsOpened() ) return;
|
||||
mpg123_seek(m_pMH, ms2samples(milliseconds)*GetSampleSize(), SEEK_SET);
|
||||
}
|
||||
|
||||
uint32 Tell()
|
||||
{
|
||||
if ( !IsOpened() ) return 0;
|
||||
return samples2ms(mpg123_tell(m_pMH)/GetSampleSize());
|
||||
}
|
||||
|
||||
uint32 Decode(void *buffer)
|
||||
{
|
||||
if ( !IsOpened() ) return 0;
|
||||
|
||||
size_t size;
|
||||
int err = mpg123_read(m_pMH, (unsigned char *)buffer, GetBufferSize(), &size);
|
||||
if (err != MPG123_OK && err != MPG123_DONE) return 0;
|
||||
return size;
|
||||
}
|
||||
};
|
||||
|
||||
void CStream::Initialise()
|
||||
{
|
||||
//mpg123_init();
|
||||
mpg123_init();
|
||||
}
|
||||
|
||||
void CStream::Terminate()
|
||||
{
|
||||
//mpg123_exit();
|
||||
mpg123_exit();
|
||||
}
|
||||
|
||||
CStream::CStream(char *filename, ALuint &source, ALuint (&buffers)[NUM_STREAMBUFFERS]) :
|
||||
m_alSource(source),
|
||||
m_alBuffers(buffers),
|
||||
m_nBitRate(0),
|
||||
m_nFormat(0),
|
||||
m_nFreq(0),
|
||||
m_nLength(0),
|
||||
m_nLengthMS(0),
|
||||
m_nBufferSize(0),
|
||||
m_pBuffer(NULL),
|
||||
m_bIsOpened(false),
|
||||
m_bPaused(true)
|
||||
m_pBuffer(nil),
|
||||
m_bPaused(false),
|
||||
m_bActive(false),
|
||||
m_pSoundFile(nil),
|
||||
m_bReset(false),
|
||||
m_nVolume(0),
|
||||
m_nPan(0),
|
||||
m_nPosBeforeReset(0)
|
||||
|
||||
{
|
||||
strcpy(m_aFilename, filename);
|
||||
|
||||
//DEV("Stream %s\n", m_aFilename);
|
||||
DEV("Stream %s\n", m_aFilename);
|
||||
|
||||
/*
|
||||
if ( true )
|
||||
{
|
||||
m_nBitRate = (wBitsPerSample * nChannels * wfex.nSamplesPerSec)/1000;
|
||||
m_nLength = ulDataSize;
|
||||
m_nLengthMS = m_nLength*8 / m_nBitRate;
|
||||
m_nBufferSize = nAvgBytesPerSec >> 2;
|
||||
m_nBufferSize -= (m_nLength % wfex.nBlockAlign);
|
||||
m_pBuffer = malloc(m_nBufferSize);
|
||||
m_bIsOpened = true;
|
||||
if (!strcasecmp(&m_aFilename[strlen(m_aFilename) - strlen(".mp3")], ".mp3"))
|
||||
m_pSoundFile = new CMP3File(m_aFilename);
|
||||
else if (!strcasecmp(&m_aFilename[strlen(m_aFilename) - strlen(".wav")], ".wav"))
|
||||
m_pSoundFile = new CSndFile(m_aFilename);
|
||||
else
|
||||
m_pSoundFile = nil;
|
||||
ASSERT(m_pSoundFile != nil);
|
||||
if (m_pSoundFile && m_pSoundFile->IsOpened() )
|
||||
{
|
||||
m_pBuffer = malloc(m_pSoundFile->GetBufferSize());
|
||||
ASSERT(m_pBuffer!=nil);
|
||||
|
||||
DEV("AvgSamplesPerSec: %d\n", m_pSoundFile->GetAvgSamplesPerSec());
|
||||
DEV("SampleCount: %d\n", m_pSoundFile->GetSampleCount());
|
||||
DEV("SampleRate: %d\n", m_pSoundFile->GetSampleRate());
|
||||
DEV("Channels: %d\n", m_pSoundFile->GetChannels());
|
||||
DEV("Buffer Samples: %d\n", m_pSoundFile->GetBufferSamples());
|
||||
DEV("Buffer sec: %f\n", (float(m_pSoundFile->GetBufferSamples()) / float(m_pSoundFile->GetChannels())/ float(m_pSoundFile->GetSampleRate())));
|
||||
DEV("Length MS: %02d:%02d\n", (m_pSoundFile->GetLength() / 1000) / 60, (m_pSoundFile->GetLength() / 1000) % 60);
|
||||
|
||||
return;
|
||||
}*/
|
||||
}
|
||||
}
|
||||
|
||||
CStream::~CStream()
|
||||
@ -51,68 +226,295 @@ CStream::~CStream()
|
||||
}
|
||||
|
||||
void CStream::Delete()
|
||||
{
|
||||
{
|
||||
Stop();
|
||||
ClearBuffers();
|
||||
|
||||
if ( m_pSoundFile )
|
||||
{
|
||||
delete m_pSoundFile;
|
||||
m_pSoundFile = nil;
|
||||
}
|
||||
|
||||
if ( m_pBuffer )
|
||||
{
|
||||
free(m_pBuffer);
|
||||
m_pBuffer = NULL;
|
||||
m_pBuffer = nil;
|
||||
}
|
||||
}
|
||||
|
||||
bool CStream::HasSource()
|
||||
{
|
||||
return m_alSource != AL_NONE;
|
||||
}
|
||||
|
||||
bool CStream::IsOpened()
|
||||
{
|
||||
return m_bIsOpened;
|
||||
return m_pSoundFile->IsOpened();
|
||||
}
|
||||
|
||||
bool CStream::IsPlaying()
|
||||
{
|
||||
if ( !HasSource() || !IsOpened() ) return false;
|
||||
|
||||
if ( m_pSoundFile->IsOpened() && !m_bPaused )
|
||||
{
|
||||
ALint sourceState;
|
||||
alGetSourcei(m_alSource, AL_SOURCE_STATE, &sourceState);
|
||||
if ( m_bActive || sourceState == AL_PLAYING )
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void CStream::Pause()
|
||||
{
|
||||
if ( !HasSource() ) return;
|
||||
ALint sourceState = AL_PAUSED;
|
||||
alGetSourcei(m_alSource, AL_SOURCE_STATE, &sourceState);
|
||||
if (sourceState != AL_PAUSED )
|
||||
alSourcePause(m_alSource);
|
||||
}
|
||||
|
||||
void CStream::SetPause(bool bPause)
|
||||
{
|
||||
if ( !HasSource() ) return;
|
||||
if ( bPause )
|
||||
{
|
||||
Pause();
|
||||
m_bPaused = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (m_bPaused)
|
||||
SetPlay(true);
|
||||
m_bPaused = false;
|
||||
}
|
||||
}
|
||||
|
||||
void CStream::SetPitch(float pitch)
|
||||
{
|
||||
if ( !HasSource() ) return;
|
||||
alSourcef(m_alSource, AL_PITCH, pitch);
|
||||
}
|
||||
|
||||
void CStream::SetGain(float gain)
|
||||
{
|
||||
if ( !HasSource() ) return;
|
||||
alSourcef(m_alSource, AL_GAIN, gain);
|
||||
}
|
||||
|
||||
void CStream::SetPosition(float x, float y, float z)
|
||||
{
|
||||
if ( !HasSource() ) return;
|
||||
alSource3f(m_alSource, AL_POSITION, x, y, z);
|
||||
}
|
||||
|
||||
void CStream::SetVolume(uint32 nVol)
|
||||
{
|
||||
|
||||
m_nVolume = nVol;
|
||||
SetGain(ALfloat(nVol) / MAX_VOLUME);
|
||||
}
|
||||
|
||||
void CStream::SetPan(uint8 nPan)
|
||||
{
|
||||
m_nPan = nPan;
|
||||
SetPosition((nPan - 63)/64.0f, 0.0f, Sqrt(1.0f-SQR((nPan-63)/64.0f)));
|
||||
}
|
||||
|
||||
void CStream::SetPos(uint32 nPos)
|
||||
void CStream::SetPosMS(uint32 nPos)
|
||||
{
|
||||
if ( !m_pSoundFile->IsOpened() ) return;
|
||||
m_pSoundFile->Seek(nPos);
|
||||
ClearBuffers();
|
||||
}
|
||||
|
||||
uint32 CStream::GetPos()
|
||||
uint32 CStream::GetPosMS()
|
||||
{
|
||||
return 0;
|
||||
if ( !HasSource() ) return 0;
|
||||
if ( !m_pSoundFile->IsOpened() ) return 0;
|
||||
|
||||
ALint offset;
|
||||
//alGetSourcei(m_alSource, AL_SAMPLE_OFFSET, &offset);
|
||||
alGetSourcei(m_alSource, AL_BYTE_OFFSET, &offset);
|
||||
|
||||
return m_pSoundFile->Tell()
|
||||
- m_pSoundFile->samples2ms(m_pSoundFile->GetBufferSamples() * (NUM_STREAMBUFFERS-1))
|
||||
+ m_pSoundFile->samples2ms(offset/m_pSoundFile->GetSampleSize());
|
||||
}
|
||||
|
||||
uint32 CStream::GetLength()
|
||||
uint32 CStream::GetLengthMS()
|
||||
{
|
||||
return m_nLengthMS;
|
||||
if ( !m_pSoundFile->IsOpened() ) return 0;
|
||||
return m_pSoundFile->GetLength();
|
||||
}
|
||||
|
||||
bool CStream::FillBuffer(ALuint alBuffer)
|
||||
{
|
||||
if ( !HasSource() )
|
||||
return false;
|
||||
if ( !m_pSoundFile->IsOpened() )
|
||||
return false;
|
||||
if ( !(alBuffer != AL_NONE && alIsBuffer(alBuffer)) )
|
||||
return false;
|
||||
|
||||
uint32 size = m_pSoundFile->Decode(m_pBuffer);
|
||||
if( size == 0 )
|
||||
return false;
|
||||
|
||||
alBufferData(alBuffer, m_pSoundFile->GetChannels() == 1 ? AL_FORMAT_MONO16 : AL_FORMAT_STEREO16,
|
||||
m_pBuffer, size, m_pSoundFile->GetSampleRate());
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
int32 CStream::FillBuffers()
|
||||
{
|
||||
int32 i = 0;
|
||||
for ( i = 0; i < NUM_STREAMBUFFERS; i++ )
|
||||
{
|
||||
if ( !FillBuffer(m_alBuffers[i]) )
|
||||
break;
|
||||
alSourceQueueBuffers(m_alSource, 1, &m_alBuffers[i]);
|
||||
}
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
void CStream::ClearBuffers()
|
||||
{
|
||||
if ( !HasSource() ) return;
|
||||
|
||||
ALint buffersQueued;
|
||||
alGetSourcei(m_alSource, AL_BUFFERS_QUEUED, &buffersQueued);
|
||||
|
||||
ALuint value;
|
||||
while (buffersQueued--)
|
||||
alSourceUnqueueBuffers(m_alSource, 1, &value);
|
||||
}
|
||||
|
||||
bool CStream::Setup()
|
||||
{
|
||||
if ( !IsOpened() )
|
||||
return false;
|
||||
|
||||
if ( m_pSoundFile->IsOpened() )
|
||||
{
|
||||
m_pSoundFile->Seek(0);
|
||||
alSourcei(m_alSource, AL_SOURCE_RELATIVE, AL_TRUE);
|
||||
//SetPosition(0.0f, 0.0f, 0.0f);
|
||||
SetPitch(1.0f);
|
||||
//SetPan(m_nPan);
|
||||
//SetVolume(100);
|
||||
}
|
||||
|
||||
return IsOpened();
|
||||
}
|
||||
|
||||
void CStream::SetPlay(bool state)
|
||||
{
|
||||
if ( !HasSource() ) return;
|
||||
if ( state )
|
||||
{
|
||||
ALint sourceState = AL_PLAYING;
|
||||
alGetSourcei(m_alSource, AL_SOURCE_STATE, &sourceState);
|
||||
if (sourceState != AL_PLAYING )
|
||||
alSourcePlay(m_alSource);
|
||||
m_bActive = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
ALint sourceState = AL_STOPPED;
|
||||
alGetSourcei(m_alSource, AL_SOURCE_STATE, &sourceState);
|
||||
if (sourceState != AL_STOPPED )
|
||||
alSourceStop(m_alSource);
|
||||
m_bActive = false;
|
||||
}
|
||||
}
|
||||
|
||||
void CStream::Start()
|
||||
{
|
||||
if ( !HasSource() ) return;
|
||||
if ( FillBuffers() != 0 )
|
||||
SetPlay(true);
|
||||
}
|
||||
|
||||
void CStream::Stop()
|
||||
{
|
||||
if ( !HasSource() ) return;
|
||||
SetPlay(false);
|
||||
}
|
||||
|
||||
void CStream::Update()
|
||||
{
|
||||
if ( !IsOpened() )
|
||||
return;
|
||||
|
||||
if ( !HasSource() )
|
||||
return;
|
||||
|
||||
if ( m_bReset )
|
||||
return;
|
||||
|
||||
if ( !m_bPaused )
|
||||
{
|
||||
ALint sourceState;
|
||||
ALint buffersProcessed = 0;
|
||||
|
||||
alGetSourcei(m_alSource, AL_SOURCE_STATE, &sourceState);
|
||||
alGetSourcei(m_alSource, AL_BUFFERS_PROCESSED, &buffersProcessed);
|
||||
|
||||
ALint looping = AL_FALSE;
|
||||
alGetSourcei(m_alSource, AL_LOOPING, &looping);
|
||||
|
||||
if ( looping == AL_TRUE )
|
||||
{
|
||||
TRACE("stream set looping");
|
||||
alSourcei(m_alSource, AL_LOOPING, AL_TRUE);
|
||||
}
|
||||
|
||||
while( buffersProcessed-- )
|
||||
{
|
||||
ALuint buffer;
|
||||
|
||||
alSourceUnqueueBuffers(m_alSource, 1, &buffer);
|
||||
|
||||
if ( m_bActive && FillBuffer(buffer) )
|
||||
alSourceQueueBuffers(m_alSource, 1, &buffer);
|
||||
}
|
||||
|
||||
if ( sourceState != AL_PLAYING )
|
||||
{
|
||||
alGetSourcei(m_alSource, AL_BUFFERS_PROCESSED, &buffersProcessed);
|
||||
SetPlay(buffersProcessed!=0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CStream::ProviderInit()
|
||||
{
|
||||
if ( m_bReset )
|
||||
{
|
||||
if ( Setup() )
|
||||
{
|
||||
SetPan(m_nPan);
|
||||
SetVolume(m_nVolume);
|
||||
SetPosMS(m_nPosBeforeReset);
|
||||
if (m_bActive)
|
||||
FillBuffers();
|
||||
SetPlay(m_bActive);
|
||||
if ( m_bPaused )
|
||||
Pause();
|
||||
}
|
||||
|
||||
m_bReset = false;
|
||||
}
|
||||
}
|
||||
|
||||
void CStream::ProviderTerm()
|
||||
{
|
||||
m_bReset = true;
|
||||
m_nPosBeforeReset = GetPosMS();
|
||||
|
||||
ClearBuffers();
|
||||
}
|
||||
|
||||
#endif
|
@ -4,8 +4,56 @@
|
||||
#ifdef AUDIO_OAL
|
||||
#include <AL/al.h>
|
||||
|
||||
#define NUM_STREAMBUFFERS 5
|
||||
#define STREAMBUFFER_SIZE 0x4000
|
||||
#define NUM_STREAMBUFFERS 4
|
||||
|
||||
class IDecoder
|
||||
{
|
||||
public:
|
||||
virtual ~IDecoder() { }
|
||||
|
||||
virtual bool IsOpened() = 0;
|
||||
|
||||
virtual uint32 GetSampleSize() = 0;
|
||||
virtual uint32 GetSampleCount() = 0;
|
||||
virtual uint32 GetSampleRate() = 0;
|
||||
virtual uint32 GetChannels() = 0;
|
||||
|
||||
uint32 GetAvgSamplesPerSec()
|
||||
{
|
||||
return GetChannels() * GetSampleRate();
|
||||
}
|
||||
|
||||
uint32 ms2samples(uint32 ms)
|
||||
{
|
||||
return float(ms) / 1000.0f * float(GetChannels()) * float(GetSampleRate());
|
||||
}
|
||||
|
||||
uint32 samples2ms(uint32 sm)
|
||||
{
|
||||
return float(sm) * 1000.0f / float(GetChannels()) / float(GetSampleRate());
|
||||
}
|
||||
|
||||
uint32 GetBufferSamples()
|
||||
{
|
||||
//return (GetAvgSamplesPerSec() >> 2) - (GetSampleCount() % GetChannels());
|
||||
return (GetAvgSamplesPerSec() / 4); // 250ms
|
||||
}
|
||||
|
||||
uint32 GetBufferSize()
|
||||
{
|
||||
return GetBufferSamples() * GetSampleSize();
|
||||
}
|
||||
|
||||
virtual void Seek(uint32 milliseconds) = 0;
|
||||
virtual uint32 Tell() = 0;
|
||||
|
||||
uint32 GetLength()
|
||||
{
|
||||
return float(GetSampleCount()) * 1000.0f / float(GetSampleRate());
|
||||
}
|
||||
|
||||
virtual uint32 Decode(void *buffer) = 0;
|
||||
};
|
||||
|
||||
class CStream
|
||||
{
|
||||
@ -13,30 +61,34 @@ class CStream
|
||||
ALuint &m_alSource;
|
||||
ALuint (&m_alBuffers)[NUM_STREAMBUFFERS];
|
||||
|
||||
bool m_bIsOpened;
|
||||
bool m_bPaused;
|
||||
|
||||
uint32 m_nLength;
|
||||
uint32 m_nLengthMS;
|
||||
uint32 m_nBitRate;
|
||||
bool m_bActive;
|
||||
|
||||
unsigned long m_nFormat;
|
||||
unsigned long m_nFreq;
|
||||
|
||||
uint32 m_nBufferSize;
|
||||
void *m_pBuffer;
|
||||
|
||||
ALint iTotalBuffersProcessed;
|
||||
bool m_bReset;
|
||||
uint32 m_nVolume;
|
||||
uint8 m_nPan;
|
||||
uint32 m_nPosBeforeReset;
|
||||
|
||||
IDecoder *m_pSoundFile;
|
||||
|
||||
bool HasSource();
|
||||
void SetPosition(float x, float y, float z);
|
||||
void SetPitch(float pitch);
|
||||
void SetGain(float gain);
|
||||
void Pause();
|
||||
void SetPlay(bool state);
|
||||
|
||||
bool FillBuffer(ALuint alBuffer);
|
||||
int32 FillBuffers();
|
||||
void ClearBuffers();
|
||||
public:
|
||||
static void Initialise();
|
||||
static void Terminate();
|
||||
|
||||
CStream(char *filename, ALuint &source, ALuint (&buffers)[NUM_STREAMBUFFERS]);
|
||||
~CStream();
|
||||
|
||||
void Delete();
|
||||
|
||||
bool IsOpened();
|
||||
@ -44,14 +96,17 @@ public:
|
||||
void SetPause (bool bPause);
|
||||
void SetVolume(uint32 nVol);
|
||||
void SetPan (uint8 nPan);
|
||||
void SetPos (uint32 nPos);
|
||||
|
||||
uint32 GetPos();
|
||||
uint32 GetLength();
|
||||
void SetPosMS (uint32 nPos);
|
||||
uint32 GetPosMS();
|
||||
uint32 GetLengthMS();
|
||||
|
||||
bool Setup();
|
||||
void Start();
|
||||
void Stop();
|
||||
void Update(void);
|
||||
|
||||
void ProviderInit();
|
||||
void ProviderTerm();
|
||||
};
|
||||
|
||||
#endif
|
@ -29,7 +29,6 @@
|
||||
//TODO: fix eax3 reverb
|
||||
//TODO: max channals
|
||||
//TODO: loop count
|
||||
//TODO: mp3/wav stream
|
||||
//TODO: mp3 player
|
||||
|
||||
#pragma comment( lib, "OpenAL32.lib" )
|
||||
@ -179,9 +178,9 @@ add_providers()
|
||||
defaultProvider = pDeviceList->GetDefaultDevice();
|
||||
if ( defaultProvider > MAXPROVIDERS )
|
||||
defaultProvider = 0;
|
||||
|
||||
delete pDeviceList;
|
||||
}
|
||||
|
||||
delete pDeviceList;
|
||||
}
|
||||
|
||||
static void
|
||||
@ -211,6 +210,10 @@ release_existing()
|
||||
|
||||
for ( int32 i = 0; i < MAX_STREAMS; i++ )
|
||||
{
|
||||
CStream *stream = aStream[i];
|
||||
if (stream)
|
||||
stream->ProviderTerm();
|
||||
|
||||
alDeleteSources(1, &ALStreamSources[i]);
|
||||
alDeleteBuffers(NUM_STREAMBUFFERS, ALStreamBuffers[i]);
|
||||
}
|
||||
@ -298,6 +301,10 @@ set_new_provider(int index)
|
||||
{
|
||||
alGenSources(1, &ALStreamSources[i]);
|
||||
alGenBuffers(NUM_STREAMBUFFERS, ALStreamBuffers[i]);
|
||||
|
||||
CStream *stream = aStream[i];
|
||||
if (stream)
|
||||
stream->ProviderInit();
|
||||
}
|
||||
|
||||
for ( int32 i = 0; i < SAMPLEBANK_MAX; i++ )
|
||||
@ -523,6 +530,18 @@ cSampleManager::Initialise(void)
|
||||
nChannelVolume[i] = 0;
|
||||
}
|
||||
|
||||
{
|
||||
for ( int32 i = 0; i < MAX_STREAMS; i++ )
|
||||
{
|
||||
aStream[i] = NULL;
|
||||
nStreamVolume[i] = 100;
|
||||
nStreamPan[i] = 63;
|
||||
}
|
||||
|
||||
for ( int32 i = 0; i < TOTAL_STREAMED_SOUNDS; i++ )
|
||||
nStreamLength[i] = 0;
|
||||
}
|
||||
|
||||
{
|
||||
add_providers();
|
||||
|
||||
@ -545,17 +564,6 @@ cSampleManager::Initialise(void)
|
||||
ASSERT(nSampleBankMemoryStartAddress[SAMPLEBANK_PED] != NULL);
|
||||
}
|
||||
|
||||
{
|
||||
for ( int32 i = 0; i < MAX_STREAMS; i++ )
|
||||
{
|
||||
aStream[i] = NULL;
|
||||
nStreamVolume[i] = 100;
|
||||
nStreamPan[i] = 63;
|
||||
}
|
||||
|
||||
for ( int32 i = 0; i < TOTAL_STREAMED_SOUNDS; i++ )
|
||||
nStreamLength[i] = 3600000;
|
||||
}
|
||||
|
||||
{
|
||||
_bSampmanInitialised = true;
|
||||
@ -571,6 +579,25 @@ cSampleManager::Initialise(void)
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
|
||||
for ( int32 i = 0; i < TOTAL_STREAMED_SOUNDS; i++ )
|
||||
{
|
||||
aStream[0] = new CStream(StreamedNameTable[i], ALStreamSources[0], ALStreamBuffers[0]);
|
||||
|
||||
if ( aStream[0] && aStream[0]->IsOpened() )
|
||||
{
|
||||
uint32 tatalms = aStream[0]->GetLengthMS();
|
||||
delete aStream[0];
|
||||
aStream[0] = NULL;
|
||||
|
||||
nStreamLength[i] = tatalms;
|
||||
}
|
||||
else
|
||||
USERERROR("Can't open '%s'\n", StreamedNameTable[i]);
|
||||
}
|
||||
}
|
||||
|
||||
LoadSampleBank(SAMPLEBANK_MAIN);
|
||||
|
||||
return true;
|
||||
@ -653,7 +680,7 @@ cSampleManager::UpdateEffectsVolume(void)
|
||||
if ( GetChannelUsedFlag(i) )
|
||||
{
|
||||
if ( nChannelVolume[i] != 0 )
|
||||
aChannel[i].SetVolume(m_nEffectsFadeVolume * nChannelVolume[i] * m_nEffectsVolume >> 14);
|
||||
aChannel[i].SetVolume(m_nEffectsFadeVolume*nChannelVolume[i]*m_nEffectsVolume >> 14);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -853,7 +880,7 @@ uint32
|
||||
cSampleManager::GetSampleLength(uint32 nSample)
|
||||
{
|
||||
ASSERT( nSample < TOTAL_AUDIO_SAMPLES );
|
||||
return m_aSamples[nSample].nSize >> 1;
|
||||
return m_aSamples[nSample].nSize / sizeof(uint16);
|
||||
}
|
||||
|
||||
bool cSampleManager::UpdateReverb(void)
|
||||
@ -1018,7 +1045,7 @@ cSampleManager::SetChannelEmittingVolume(uint32 nChannel, uint32 nVolume)
|
||||
&& MusicManager.GetCurrentTrack() != STREAMED_SOUND_NEWS_INTRO
|
||||
&& MusicManager.GetCurrentTrack() != STREAMED_SOUND_CUTSCENE_SAL4_BDBD )
|
||||
{
|
||||
nChannelVolume[nChannel] >>= 2;
|
||||
nChannelVolume[nChannel] = vol / 4;
|
||||
}
|
||||
|
||||
// no idea, does this one looks like a bug or it's SetChannelVolume ?
|
||||
@ -1060,7 +1087,7 @@ cSampleManager::SetChannelVolume(uint32 nChannel, uint32 nVolume)
|
||||
&& MusicManager.GetCurrentTrack() != STREAMED_SOUND_NEWS_INTRO
|
||||
&& MusicManager.GetCurrentTrack() != STREAMED_SOUND_CUTSCENE_SAL4_BDBD )
|
||||
{
|
||||
nChannelVolume[nChannel] >>= 2;
|
||||
nChannelVolume[nChannel] = vol / 4;
|
||||
}
|
||||
|
||||
aChannel[nChannel].SetVolume(m_nEffectsFadeVolume*vol*m_nEffectsVolume >> 14);
|
||||
@ -1209,11 +1236,11 @@ cSampleManager::StartStreamedFile(uint8 nFile, uint32 nPos, uint8 nStream)
|
||||
|
||||
if ( stream->IsOpened() )
|
||||
{
|
||||
nStreamLength[nFile] = stream->GetLength();
|
||||
nStreamLength[nFile] = stream->GetLengthMS();
|
||||
if ( stream->Setup() )
|
||||
{
|
||||
if ( nPos != 0 )
|
||||
stream->SetPos(nPos);
|
||||
stream->SetPosMS(nPos);
|
||||
|
||||
stream->Start();
|
||||
}
|
||||
@ -1253,7 +1280,7 @@ cSampleManager::GetStreamedFilePosition(uint8 nStream)
|
||||
|
||||
if ( stream )
|
||||
{
|
||||
return stream->GetPos();
|
||||
return stream->GetPosMS();
|
||||
}
|
||||
|
||||
return 0;
|
||||
@ -1270,7 +1297,7 @@ cSampleManager::SetStreamedVolumeAndPan(uint8 nVolume, uint8 nPan, uint8 nEffect
|
||||
if ( nPan > MAX_VOLUME )
|
||||
nPan = MAX_VOLUME;
|
||||
|
||||
nStreamVolume[nStream] = m_nMusicFadeVolume * nVolume;
|
||||
nStreamVolume[nStream] = nVolume;
|
||||
nStreamPan [nStream] = nPan;
|
||||
|
||||
CStream *stream = aStream[nStream];
|
||||
|
@ -209,6 +209,7 @@ void mysrand(unsigned int seed);
|
||||
void re3_debug(const char *format, ...);
|
||||
void re3_trace(const char *filename, unsigned int lineno, const char *func, const char *format, ...);
|
||||
void re3_assert(const char *expr, const char *filename, unsigned int lineno, const char *func);
|
||||
void re3_usererror(const char *format, ...);
|
||||
|
||||
#define DEBUGBREAK() __debugbreak();
|
||||
|
||||
@ -216,6 +217,7 @@ void re3_assert(const char *expr, const char *filename, unsigned int lineno, con
|
||||
#define DEV(f, ...) re3_debug("[DEV]: " f, ## __VA_ARGS__)
|
||||
#define TRACE(f, ...) re3_trace(__FILE__, __LINE__, __FUNCTION__, f, ## __VA_ARGS__)
|
||||
#define Error(f, ...) re3_debug("[ERROR]: " f, ## __VA_ARGS__)
|
||||
#define USERERROR(f, ...) re3_usererror(f, ## __VA_ARGS__)
|
||||
|
||||
#define assert(_Expression) (void)( (!!(_Expression)) || (re3_assert(#_Expression, __FILE__, __LINE__, __FUNCTION__), 0) )
|
||||
#define ASSERT assert
|
||||
|
@ -456,6 +456,20 @@ void re3_trace(const char *filename, unsigned int lineno, const char *func, cons
|
||||
OutputDebugStringA(buff);
|
||||
}
|
||||
|
||||
void re3_usererror(const char *format, ...)
|
||||
{
|
||||
va_list va;
|
||||
va_start(va, format);
|
||||
vsprintf_s(re3_buff, re3_buffsize, format, va);
|
||||
va_end(va);
|
||||
|
||||
::MessageBoxA(nil, re3_buff, "RE3 Error!",
|
||||
MB_OK|MB_ICONHAND|MB_SETFOREGROUND|MB_TASKMODAL);
|
||||
|
||||
raise(SIGABRT);
|
||||
_exit(3);
|
||||
}
|
||||
|
||||
#ifdef VALIDATE_SAVE_SIZE
|
||||
int32 _saveBufCount;
|
||||
#endif
|
||||
|
Reference in New Issue
Block a user