mirror of https://git.rip/DMCA_FUCKER/re3.git
1404 lines
29 KiB
C++
1404 lines
29 KiB
C++
#include <al.h>
|
|
#include <alc.h>
|
|
#include <mpg123_pre.h>
|
|
//#include <mpg123.h>
|
|
#include <time.h>
|
|
#include <io.h>
|
|
#include "samp_oal.h"
|
|
#include "AudioManager.h"
|
|
#include "MusicManager.h"
|
|
#include "Frontend.h"
|
|
#include "Timer.h"
|
|
|
|
#pragma comment( lib, "libmpg123.lib" )
|
|
#pragma comment( lib, "OpenAL32.lib" )
|
|
|
|
cSampleManager SampleManager;
|
|
int32 BankStartOffset[MAX_SAMPLEBANKS];
|
|
|
|
|
|
///////////////////////////////////////////////////////////////
|
|
class MP3Stream
|
|
{
|
|
public:
|
|
mpg123_handle *m_pMPG;
|
|
FILE *m_fpFile;
|
|
unsigned char *m_pBuf;
|
|
char m_aFilename[128];
|
|
size_t m_nBufSize;
|
|
size_t m_nLengthInBytes;
|
|
long m_nRate;
|
|
int m_nBitRate;
|
|
int m_nChannels;
|
|
int m_nEncoding;
|
|
int m_nLength;
|
|
int m_nBlockSize;
|
|
int m_nNumBlocks;
|
|
ALuint m_alSource;
|
|
ALuint m_alBuffers[5];
|
|
unsigned char *m_pBlocks;
|
|
bool m_bIsFree;
|
|
bool m_bIsOpened;
|
|
bool m_bIsPaused;
|
|
int m_nVolume;
|
|
|
|
void Initialize(void);
|
|
bool FillBuffer(ALuint alBuffer);
|
|
void Update(void);
|
|
void SetPos(uint32 nPos);
|
|
int32 FillBuffers();
|
|
MP3Stream(char *filename, ALuint source, ALuint *buffers);
|
|
~MP3Stream() { Delete(); }
|
|
void Delete();
|
|
|
|
};
|
|
///////////////////////////////////////////////////////////////
|
|
|
|
char SampleBankDescFilename[] = "AUDIO\\SFX.SDT";
|
|
char SampleBankDataFilename[] = "AUDIO\\SFX.RAW";
|
|
|
|
FILE *fpSampleDescHandle;
|
|
FILE *fpSampleDataHandle;
|
|
bool bSampleBankLoaded [MAX_SAMPLEBANKS];
|
|
int32 nSampleBankDiscStartOffset [MAX_SAMPLEBANKS];
|
|
int32 nSampleBankSize [MAX_SAMPLEBANKS];
|
|
int32 nSampleBankMemoryStartAddress[MAX_SAMPLEBANKS];
|
|
int32 _nSampleDataEndOffset;
|
|
|
|
int32 nPedSlotSfx [MAX_PEDSFX];
|
|
int32 nPedSlotSfxAddr[MAX_PEDSFX];
|
|
uint8 nCurrentPedSlot;
|
|
|
|
|
|
|
|
uint32 nStreamLength[TOTAL_STREAMED_SOUNDS];
|
|
|
|
///////////////////////////////////////////////////////////////
|
|
ALuint alChannel[MAXCHANNELS+MAX2DCHANNELS];
|
|
ALuint ALStreamSources[MAX_STREAMS];
|
|
ALuint ALStreamBuffers[MAX_STREAMS][5];
|
|
struct
|
|
{
|
|
ALuint buffer;
|
|
ALuint timer;
|
|
}ALBuffers[SAMPLEBANK_MAX];
|
|
|
|
ALuint pedBuffers[MAX_PEDSFX];
|
|
//bank0Buffers
|
|
|
|
uint32 nNumMP3s;
|
|
|
|
MP3Stream *mp3Stream[MAX_STREAMS];
|
|
int8 nStreamPan [MAX_STREAMS];
|
|
int8 nStreamVolume[MAX_STREAMS];
|
|
|
|
float ChannelPitch[MAXCHANNELS+MAX2DCHANNELS];
|
|
uint8 nChannelVolume[MAXCHANNELS+MAX2DCHANNELS];
|
|
uint32 ChannelSample[MAXCHANNELS+MAX2DCHANNELS];
|
|
int32 currentChannelMaxFrontDistance[MAXCHANNELS+MAX2DCHANNELS];
|
|
int32 currentChannelFrequency[MAXCHANNELS+MAX2DCHANNELS];
|
|
int32 currentChannelVolume[MAXCHANNELS+MAX2DCHANNELS];
|
|
|
|
|
|
cSampleManager::cSampleManager(void)
|
|
{
|
|
;
|
|
}
|
|
|
|
cSampleManager::~cSampleManager(void)
|
|
{
|
|
ASSERT((void *)nSampleBankMemoryStartAddress[SAMPLEBANK_PED] == NULL);
|
|
free((void *)nSampleBankMemoryStartAddress[SAMPLEBANK_PED]);
|
|
|
|
if ( fpSampleDescHandle != NULL )
|
|
{
|
|
fclose(fpSampleDescHandle);
|
|
fpSampleDescHandle = NULL;
|
|
}
|
|
|
|
if ( fpSampleDataHandle != NULL )
|
|
{
|
|
fclose(fpSampleDataHandle);
|
|
fpSampleDataHandle = NULL;
|
|
}
|
|
}
|
|
|
|
void cSampleManager::SetSpeakerConfig(int32 nConfig)
|
|
{
|
|
|
|
}
|
|
|
|
uint32 cSampleManager::GetMaximumSupportedChannels(void)
|
|
{
|
|
return 20;
|
|
}
|
|
|
|
uint32 cSampleManager::GetNum3DProvidersAvailable()
|
|
{
|
|
return 1;
|
|
}
|
|
|
|
void cSampleManager::SetNum3DProvidersAvailable(uint32 num)
|
|
{
|
|
;
|
|
}
|
|
|
|
char *cSampleManager::Get3DProviderName(uint8 id)
|
|
{
|
|
static char PROVIDER[256] = "OpenAL";
|
|
return PROVIDER;
|
|
}
|
|
|
|
void cSampleManager::Set3DProviderName(uint8 id, char *name)
|
|
{
|
|
;
|
|
}
|
|
|
|
int8 cSampleManager::GetCurrent3DProviderIndex(void)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
int8 cSampleManager::SetCurrent3DProvider(uint8 which)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
bool
|
|
cSampleManager::IsMP3RadioChannelAvailable(void)
|
|
{
|
|
return nNumMP3s != 0;
|
|
}
|
|
|
|
|
|
void cSampleManager::ReleaseDigitalHandle(void)
|
|
{
|
|
|
|
}
|
|
|
|
void cSampleManager::ReacquireDigitalHandle(void)
|
|
{
|
|
|
|
}
|
|
|
|
bool
|
|
cSampleManager::Initialise(void)
|
|
{
|
|
ALCint attr[] = {ALC_FREQUENCY,MAX_FREQ,0};
|
|
|
|
m_pDevice = alcOpenDevice(NULL);
|
|
ASSERT(m_pDevice != NULL);
|
|
|
|
m_pContext = alcCreateContext(m_pDevice, attr);
|
|
ASSERT(m_pContext != NULL);
|
|
|
|
alcMakeContextCurrent(m_pContext);
|
|
|
|
mpg123_init();
|
|
|
|
|
|
|
|
for ( int32 i = 0; i < TOTAL_AUDIO_SAMPLES; i++ )
|
|
{
|
|
m_aSamples[i].nOffset = 0;
|
|
m_aSamples[i].nSize = 0;
|
|
m_aSamples[i].nFrequency = MAX_FREQ;
|
|
m_aSamples[i].nLoopStart = 0;
|
|
m_aSamples[i].nLoopEnd = -1;
|
|
}
|
|
|
|
for ( int32 i = 0; i < TOTAL_STREAMED_SOUNDS; i++ )
|
|
nStreamLength[i] = 3600000;
|
|
|
|
for ( int32 i = 0; i < MAX_STREAMS; i++ )
|
|
{
|
|
mp3Stream[i] = NULL;
|
|
nStreamVolume[i] = 100;
|
|
nStreamPan[i] = 63;
|
|
}
|
|
|
|
alGenSources(MAX_STREAMS, (ALuint *)ALStreamSources);
|
|
alGenBuffers(MAX_STREAMS*5, (ALuint *)ALStreamBuffers);
|
|
|
|
m_nMonoMode = 0;
|
|
|
|
m_nEffectsVolume = MAX_VOLUME;
|
|
m_nMusicVolume = MAX_VOLUME;
|
|
m_nEffectsFadeVolume = MAX_VOLUME;
|
|
m_nMusicFadeVolume = MAX_VOLUME;
|
|
|
|
|
|
memset(alChannel, 0, sizeof(alChannel));
|
|
memset(nChannelVolume, 0, sizeof(nChannelVolume));
|
|
memset(ChannelSample, 0, sizeof(ChannelSample));
|
|
|
|
for ( int32 i = 0; i < ARRAY_SIZE(ChannelPitch); i++ )
|
|
ChannelPitch[i] = 1.0f;
|
|
|
|
|
|
fpSampleDescHandle = NULL;
|
|
fpSampleDataHandle = NULL;
|
|
|
|
for ( int32 i = 0; i < MAX_SAMPLEBANKS; i++ )
|
|
{
|
|
bSampleBankLoaded[i] = false;
|
|
nSampleBankDiscStartOffset[i] = 0;
|
|
nSampleBankSize[i] = 0;
|
|
nSampleBankMemoryStartAddress[i] = 0;
|
|
}
|
|
|
|
alGenBuffers(MAX_PEDSFX, pedBuffers);
|
|
|
|
for ( int32 i = 0; i < MAX_PEDSFX; i++ )
|
|
{
|
|
nPedSlotSfx[i] = NO_SAMPLE;
|
|
nPedSlotSfxAddr[i] = 0;
|
|
}
|
|
|
|
nCurrentPedSlot = 0;
|
|
|
|
for ( int32 i = 0; i < SAMPLEBANK_MAX; i++ )
|
|
{
|
|
ALBuffers[i].buffer = 0;
|
|
ALBuffers[i].timer = 0;
|
|
}
|
|
|
|
alListenerf (AL_GAIN, 1.0f);
|
|
alListener3f(AL_POSITION, 0.0f, 0.0f, 0.0f);
|
|
alListener3f(AL_VELOCITY, 0.0f, 0.0f, 0.0f);
|
|
ALfloat orientation[6] = { 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f };
|
|
alListenerfv(AL_ORIENTATION, orientation);
|
|
|
|
if ( !InitialiseSampleBanks() )
|
|
{
|
|
Terminate();
|
|
return false;
|
|
}
|
|
|
|
nSampleBankMemoryStartAddress[SAMPLEBANK_MAIN] = (int32)malloc(nSampleBankSize[SAMPLEBANK_MAIN]);
|
|
ASSERT(nSampleBankMemoryStartAddress[SAMPLEBANK_MAIN] != NULL);
|
|
|
|
if ( nSampleBankMemoryStartAddress[SAMPLEBANK_MAIN] == NULL )
|
|
{
|
|
Terminate();
|
|
return false;
|
|
}
|
|
|
|
nSampleBankMemoryStartAddress[SAMPLEBANK_PED] = (int32)malloc(PED_BLOCKSIZE*MAX_PEDSFX);
|
|
ASSERT(nSampleBankMemoryStartAddress[SAMPLEBANK_PED] != NULL);
|
|
|
|
alGenSources(MAXCHANNELS, alChannel);
|
|
for ( int32 i = 0; i < MAXCHANNELS; i++ )
|
|
{
|
|
if ( alChannel[i] )
|
|
alSourcei(alChannel[i], AL_SOURCE_RELATIVE, AL_TRUE);
|
|
}
|
|
|
|
alGenSources(MAX2DCHANNELS, &alChannel[CHANNEL2D]);
|
|
if ( alChannel[CHANNEL2D] )
|
|
{
|
|
alSourcei (alChannel[CHANNEL2D], AL_SOURCE_RELATIVE, AL_TRUE);
|
|
alSource3f(alChannel[CHANNEL2D], AL_POSITION, 0.0f, 0.0f, 0.0f);
|
|
alSourcef (alChannel[CHANNEL2D], AL_GAIN, 1.0f);
|
|
}
|
|
|
|
LoadSampleBank(SAMPLEBANK_MAIN);
|
|
|
|
return true;
|
|
}
|
|
|
|
void
|
|
cSampleManager::Terminate(void)
|
|
{
|
|
mpg123_exit();
|
|
alcMakeContextCurrent(NULL);
|
|
alcDestroyContext(m_pContext);
|
|
alcCloseDevice(m_pDevice);
|
|
}
|
|
|
|
void
|
|
cSampleManager::UpdateSoundBuffers(void)
|
|
{
|
|
for ( int32 i = 0; i < SAMPLEBANK_MAX; i++ )
|
|
{
|
|
if ( ALBuffers[i].timer > 0 )
|
|
{
|
|
ALBuffers[i].timer -= ALuint(CTimer::GetTimeStep() * 20.0f);
|
|
|
|
if ( ALBuffers[i].timer <= 0 )
|
|
{
|
|
if ( ALBuffers[i].buffer != 0 && alIsBuffer(ALBuffers[i].buffer) )
|
|
{
|
|
alDeleteBuffers(1, &ALBuffers[i].buffer);
|
|
|
|
if ( alGetError() == AL_NO_ERROR )
|
|
ALBuffers[i].buffer = 0;
|
|
else
|
|
ALBuffers[i].buffer = 120000;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
bool cSampleManager::CheckForAnAudioFileOnCD(void)
|
|
{
|
|
return true;
|
|
}
|
|
|
|
char cSampleManager::GetCDAudioDriveLetter(void)
|
|
{
|
|
return '\0';
|
|
}
|
|
|
|
void
|
|
cSampleManager::SetEffectsMasterVolume(uint8 nVolume)
|
|
{
|
|
m_nEffectsVolume = nVolume;
|
|
}
|
|
|
|
void
|
|
cSampleManager::SetMusicMasterVolume(uint8 nVolume)
|
|
{
|
|
m_nMusicVolume = nVolume;
|
|
}
|
|
|
|
void
|
|
cSampleManager::SetEffectsFadeVolume(uint8 nVolume)
|
|
{
|
|
m_nEffectsFadeVolume = nVolume;
|
|
}
|
|
|
|
void
|
|
cSampleManager::SetMusicFadeVolume(uint8 nVolume)
|
|
{
|
|
m_nMusicFadeVolume = nVolume;
|
|
}
|
|
|
|
void
|
|
cSampleManager::SetMonoMode(uint8 nMode)
|
|
{
|
|
m_nMonoMode = nMode;
|
|
}
|
|
|
|
bool
|
|
cSampleManager::LoadSampleBank(uint8 nBank)
|
|
{
|
|
ASSERT( nBank < MAX_SAMPLEBANKS );
|
|
|
|
if ( CTimer::GetIsCodePaused() )
|
|
return false;
|
|
|
|
if ( MusicManager.IsInitialised()
|
|
&& MusicManager.GetMusicMode() == MUSICMODE_CUTSCENE
|
|
&& nBank != SAMPLEBANK_MAIN )
|
|
{
|
|
return false;
|
|
}
|
|
|
|
if ( fseek(fpSampleDataHandle, nSampleBankDiscStartOffset[nBank], SEEK_SET) != 0 )
|
|
return false;
|
|
|
|
if ( fread((void *)nSampleBankMemoryStartAddress[nBank], 1, nSampleBankSize[nBank], fpSampleDataHandle) != nSampleBankSize[nBank] )
|
|
return false;
|
|
|
|
bSampleBankLoaded[nBank] = true;
|
|
|
|
return true;
|
|
}
|
|
|
|
void
|
|
cSampleManager::UnloadSampleBank(uint8 nBank)
|
|
{
|
|
ASSERT( nBank < MAX_SAMPLEBANKS );
|
|
|
|
; // NOIMP
|
|
}
|
|
|
|
bool
|
|
cSampleManager::IsSampleBankLoaded(uint8 nBank)
|
|
{
|
|
ASSERT( nBank < MAX_SAMPLEBANKS );
|
|
return true;
|
|
}
|
|
|
|
bool
|
|
cSampleManager::IsPedCommentLoaded(uint32 nComment)
|
|
{
|
|
ASSERT( nComment < TOTAL_AUDIO_SAMPLES );
|
|
|
|
uint8 slot;
|
|
|
|
for ( int32 i = 0; i < _TODOCONST(3); i++ )
|
|
{
|
|
slot = nCurrentPedSlot - i - 1;
|
|
if ( nComment == nPedSlotSfx[slot] )
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
|
|
int32
|
|
cSampleManager::_GetPedCommentSlot(uint32 nComment)
|
|
{
|
|
uint8 slot;
|
|
|
|
for (int32 i = 0; i < _TODOCONST(3); i++)
|
|
{
|
|
slot = nCurrentPedSlot - i - 1;
|
|
if (nComment == nPedSlotSfx[slot])
|
|
return slot;
|
|
}
|
|
|
|
return -1;
|
|
}
|
|
|
|
bool
|
|
cSampleManager::LoadPedComment(uint32 nComment)
|
|
{
|
|
ASSERT( nComment < TOTAL_AUDIO_SAMPLES );
|
|
|
|
if ( CTimer::GetIsCodePaused() )
|
|
return false;
|
|
|
|
// no talking peds during cutsenes or the game end
|
|
if ( MusicManager.IsInitialised() )
|
|
{
|
|
switch ( MusicManager.GetMusicMode() )
|
|
{
|
|
case MUSICMODE_CUTSCENE:
|
|
{
|
|
return false;
|
|
|
|
break;
|
|
}
|
|
|
|
case MUSICMODE_FRONTEND:
|
|
{
|
|
if ( MusicManager.GetCurrentTrack() == STREAMED_SOUND_GAME_COMPLETED )
|
|
return false;
|
|
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
if ( fseek(fpSampleDataHandle, m_aSamples[nComment].nOffset, SEEK_SET) != 0 )
|
|
return false;
|
|
|
|
if ( fread((void *)(nSampleBankMemoryStartAddress[SAMPLEBANK_PED] + PED_BLOCKSIZE*nCurrentPedSlot), 1, m_aSamples[nComment].nSize, fpSampleDataHandle) != m_aSamples[nComment].nSize )
|
|
return false;
|
|
|
|
nPedSlotSfx[nCurrentPedSlot] = nComment;
|
|
|
|
alBufferData(pedBuffers[nCurrentPedSlot],
|
|
AL_FORMAT_MONO16,
|
|
(void *)(nSampleBankMemoryStartAddress[SAMPLEBANK_PED] + PED_BLOCKSIZE*nCurrentPedSlot),
|
|
m_aSamples[nComment].nSize,
|
|
MAX_FREQ);
|
|
|
|
if ( ++nCurrentPedSlot >= MAX_PEDSFX )
|
|
nCurrentPedSlot = 0;
|
|
|
|
return true;
|
|
}
|
|
|
|
int32
|
|
cSampleManager::GetBankContainingSound(uint32 offset)
|
|
{
|
|
if ( offset >= BankStartOffset[SAMPLEBANK_PED] )
|
|
return SAMPLEBANK_PED;
|
|
|
|
if ( offset >= BankStartOffset[SAMPLEBANK_MAIN] )
|
|
return SAMPLEBANK_MAIN;
|
|
|
|
return SAMPLEBANK_INVALID;
|
|
}
|
|
|
|
int32
|
|
cSampleManager::GetSampleBaseFrequency(uint32 nSample)
|
|
{
|
|
ASSERT( nSample < TOTAL_AUDIO_SAMPLES );
|
|
return m_aSamples[nSample].nFrequency;
|
|
}
|
|
|
|
int32
|
|
cSampleManager::GetSampleLoopStartOffset(uint32 nSample)
|
|
{
|
|
ASSERT( nSample < TOTAL_AUDIO_SAMPLES );
|
|
return m_aSamples[nSample].nLoopStart;
|
|
}
|
|
|
|
int32
|
|
cSampleManager::GetSampleLoopEndOffset(uint32 nSample)
|
|
{
|
|
ASSERT( nSample < TOTAL_AUDIO_SAMPLES );
|
|
return m_aSamples[nSample].nLoopEnd;
|
|
}
|
|
|
|
uint32
|
|
cSampleManager::GetSampleLength(uint32 nSample)
|
|
{
|
|
ASSERT( nSample < TOTAL_AUDIO_SAMPLES );
|
|
return m_aSamples[nSample].nSize >> 1;
|
|
}
|
|
|
|
bool cSampleManager::UpdateReverb(void)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
void
|
|
cSampleManager::SetChannelReverbFlag(uint32 nChannel, uint8 nReverbFlag)
|
|
{
|
|
; // NOIMP
|
|
}
|
|
|
|
bool
|
|
cSampleManager::InitialiseChannel(uint32 nChannel, uint32 nSfx, uint8 nBank)
|
|
{
|
|
ASSERT( nChannel < MAXCHANNELS+MAX2DCHANNELS );
|
|
|
|
ALuint buffer;
|
|
|
|
if ( nSfx < SAMPLEBANK_MAX )
|
|
{
|
|
int32 offset = (m_aSamples[nSfx].nLoopStart > 0) ? (m_aSamples[nSfx].nOffset - m_aSamples[nSfx].nLoopStart) : m_aSamples[nSfx].nOffset;
|
|
int32 size = (m_aSamples[nSfx].nLoopStart > 0) ? (m_aSamples[nSfx].nLoopEnd - m_aSamples[nSfx].nLoopStart) : m_aSamples[nSfx].nSize;
|
|
|
|
void *data = malloc(size);
|
|
ASSERT(data != NULL);
|
|
|
|
if ( fseek(fpSampleDataHandle, offset + nSampleBankDiscStartOffset[nBank], SEEK_SET) != 0 )
|
|
{
|
|
free(data);
|
|
return false;
|
|
}
|
|
|
|
if ( fread(data, 1, size, fpSampleDataHandle) != size )
|
|
{
|
|
free(data);
|
|
return false;
|
|
}
|
|
|
|
ALuint buf;
|
|
alGenBuffers(1, &buf);
|
|
alBufferData(buf, AL_FORMAT_MONO16, data, size, MAX_FREQ);
|
|
free(data);
|
|
|
|
if ( !IsSampleBankLoaded(nBank) )
|
|
return false;
|
|
|
|
ALBuffers[nSfx].buffer = buf;
|
|
ALBuffers[nSfx].timer = 120000;
|
|
|
|
buffer = ALBuffers[nSfx].buffer;
|
|
|
|
ChannelSample[nChannel] = nSfx;
|
|
}
|
|
else
|
|
{
|
|
if ( !IsPedCommentLoaded(nSfx) )
|
|
return false;
|
|
|
|
int32 slot = _GetPedCommentSlot(nSfx);
|
|
|
|
buffer = pedBuffers[slot];
|
|
}
|
|
|
|
if ( buffer == 0 )
|
|
{
|
|
TRACE("No buffer to play id %d", nSfx);
|
|
return false;
|
|
}
|
|
|
|
if ( GetChannelUsedFlag(nChannel) )
|
|
{
|
|
TRACE("Stopping channel %d - really!!!", nChannel);
|
|
StopChannel(nChannel);
|
|
}
|
|
|
|
alSourcei(alChannel[nChannel], AL_BUFFER, 0);
|
|
currentChannelVolume [nChannel] = -1;
|
|
currentChannelFrequency [nChannel] = -1;
|
|
currentChannelMaxFrontDistance[nChannel] = -1;
|
|
|
|
if ( alChannel[nChannel] )
|
|
{
|
|
alSourcei(alChannel[nChannel], AL_BUFFER, buffer);
|
|
alSourcef(alChannel[nChannel], AL_PITCH, 1.0f);
|
|
ChannelPitch[nChannel] = 1.0f;
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
void
|
|
cSampleManager::SetChannelEmittingVolume(uint32 nChannel, uint32 nVolume)
|
|
{
|
|
ASSERT( nChannel < MAXCHANNELS+MAX2DCHANNELS );
|
|
|
|
uint32 vol = nVolume;
|
|
if ( vol > MAX_VOLUME ) vol = MAX_VOLUME;
|
|
|
|
nChannelVolume[nChannel] = vol;
|
|
|
|
// reduce the volume for JB.MP3 and S4_BDBD.MP3
|
|
if ( MusicManager.GetMusicMode() == MUSICMODE_CUTSCENE
|
|
&& MusicManager.GetCurrentTrack() != STREAMED_SOUND_NEWS_INTRO
|
|
&& MusicManager.GetCurrentTrack() != STREAMED_SOUND_CUTSCENE_SAL4_BDBD )
|
|
{
|
|
nChannelVolume[nChannel] >>= 2;
|
|
}
|
|
|
|
uint32 channelVol = m_nEffectsFadeVolume*nChannelVolume[nChannel]*m_nEffectsVolume >> 14;
|
|
if ( ChannelSample[nChannel] >= SFX_CAR_REV_1 && SFX_CAR_REV_10 >= ChannelSample[nChannel] ) // nice hack
|
|
channelVol >>= 1;
|
|
|
|
if ( alChannel[nChannel] )
|
|
{
|
|
if ( currentChannelVolume[nChannel] != channelVol )
|
|
{
|
|
ALfloat gain = ALfloat(channelVol) / MAX_VOLUME;
|
|
alSourcef(alChannel[nChannel], AL_GAIN, gain);
|
|
currentChannelVolume[nChannel] = channelVol;
|
|
}
|
|
}
|
|
}
|
|
|
|
void
|
|
cSampleManager::SetChannel3DPosition(uint32 nChannel, float fX, float fY, float fZ)
|
|
{
|
|
ASSERT( nChannel < MAXCHANNELS+MAX2DCHANNELS );
|
|
|
|
if ( alChannel[nChannel] )
|
|
{
|
|
alSource3f(alChannel[nChannel], AL_POSITION, -fX, fY, fZ);
|
|
}
|
|
}
|
|
|
|
void
|
|
cSampleManager::SetChannel3DDistances(uint32 nChannel, float fMax, float fMin)
|
|
{
|
|
ASSERT( nChannel < MAXCHANNELS+MAX2DCHANNELS );
|
|
|
|
if ( alChannel[nChannel] )
|
|
{
|
|
if ( float(currentChannelMaxFrontDistance[nChannel]) != fMax )
|
|
{
|
|
alSourcef(alChannel[nChannel], AL_MAX_DISTANCE, fMax);
|
|
alSourcef(alChannel[nChannel], AL_REFERENCE_DISTANCE, 5.0f);
|
|
alSourcef(alChannel[nChannel], AL_MAX_GAIN, 1.0f);
|
|
currentChannelMaxFrontDistance[nChannel] = int32(fMax);
|
|
}
|
|
}
|
|
}
|
|
|
|
void
|
|
cSampleManager::SetChannelVolume(uint32 nChannel, uint32 nVolume)
|
|
{
|
|
ASSERT( nChannel < MAXCHANNELS+MAX2DCHANNELS );
|
|
|
|
if ( nChannel == CHANNEL2D )
|
|
{
|
|
uint32 vol = nVolume;
|
|
if ( vol > MAX_VOLUME ) vol = MAX_VOLUME;
|
|
|
|
nChannelVolume[nChannel] = vol;
|
|
|
|
// increase the volume for JB.MP3 and S4_BDBD.MP3
|
|
if ( MusicManager.GetMusicMode() == MUSICMODE_CUTSCENE
|
|
&& MusicManager.GetCurrentTrack() != STREAMED_SOUND_NEWS_INTRO
|
|
&& MusicManager.GetCurrentTrack() != STREAMED_SOUND_CUTSCENE_SAL4_BDBD )
|
|
{
|
|
nChannelVolume[nChannel] >>= 2;
|
|
}
|
|
|
|
uint32 channelVol = m_nEffectsFadeVolume*nChannelVolume[nChannel]*m_nEffectsVolume >> 14;
|
|
if ( ChannelSample[nChannel] >= SFX_CAR_REV_1 && SFX_CAR_IDLE_10 >= ChannelSample[nChannel] ) // nice hack
|
|
channelVol >>= 1;
|
|
|
|
if ( alChannel[nChannel] )
|
|
{
|
|
if ( currentChannelVolume[nChannel] != channelVol )
|
|
{
|
|
ALfloat gain = ALfloat(channelVol) / MAX_VOLUME;
|
|
alSourcef(alChannel[nChannel], AL_GAIN, gain);
|
|
currentChannelVolume[nChannel] = channelVol;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void
|
|
cSampleManager::SetChannelPan(uint32 nChannel, uint32 nPan)
|
|
{
|
|
ASSERT( nChannel < MAXCHANNELS+MAX2DCHANNELS );
|
|
; // NOIMP
|
|
}
|
|
|
|
void
|
|
cSampleManager::SetChannelFrequency(uint32 nChannel, uint32 nFreq)
|
|
{
|
|
ASSERT( nChannel < MAXCHANNELS+MAX2DCHANNELS );
|
|
|
|
if ( alChannel[nChannel] )
|
|
{
|
|
if ( currentChannelFrequency[nChannel] != nFreq )
|
|
{
|
|
ALfloat pitch = ALfloat(nFreq) / MAX_FREQ;
|
|
alSourcef(alChannel[nChannel], AL_PITCH, pitch);
|
|
currentChannelFrequency[nChannel] = nFreq;
|
|
|
|
if ( Abs(1.0f - pitch) < 0.01f )
|
|
ChannelPitch[nChannel] = 1.0f;
|
|
else
|
|
ChannelPitch[nChannel] = pitch;
|
|
}
|
|
}
|
|
}
|
|
|
|
void
|
|
cSampleManager::SetChannelLoopPoints(uint32 nChannel, uint32 nLoopStart, int32 nLoopEnd)
|
|
{
|
|
ASSERT( nChannel < MAXCHANNELS+MAX2DCHANNELS );
|
|
|
|
; // NOIMP
|
|
}
|
|
|
|
void
|
|
cSampleManager::SetChannelLoopCount(uint32 nChannel, uint32 nLoopCount)
|
|
{
|
|
ASSERT( nChannel < MAXCHANNELS+MAX2DCHANNELS );
|
|
|
|
if ( nLoopCount != 0 )
|
|
alSourcei(alChannel[nChannel], AL_LOOPING, AL_FALSE);
|
|
else
|
|
alSourcei(alChannel[nChannel], AL_LOOPING, AL_TRUE);
|
|
}
|
|
|
|
bool
|
|
cSampleManager::GetChannelUsedFlag(uint32 nChannel)
|
|
{
|
|
ASSERT( nChannel < MAXCHANNELS+MAX2DCHANNELS );
|
|
|
|
if ( alChannel[nChannel] )
|
|
{
|
|
ALint sourceState;
|
|
alGetSourcei(alChannel[nChannel], AL_SOURCE_STATE, &sourceState);
|
|
return sourceState == AL_PLAYING;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
void
|
|
cSampleManager::StartChannel(uint32 nChannel)
|
|
{
|
|
ASSERT( nChannel < MAXCHANNELS+MAX2DCHANNELS );
|
|
|
|
if ( alChannel[nChannel] )
|
|
{
|
|
if ( ChannelSample[nChannel] > SAMPLEBANK_END ) // PED's Bank
|
|
{
|
|
if ( ChannelPitch[nChannel] != 1.0f )
|
|
ChannelPitch[nChannel] = 1.0f;
|
|
}
|
|
|
|
alSourcef (alChannel[nChannel], AL_PITCH, ChannelPitch[nChannel]);
|
|
alSourcePlay(alChannel[nChannel]);
|
|
}
|
|
}
|
|
|
|
void
|
|
cSampleManager::StopChannel(uint32 nChannel)
|
|
{
|
|
ASSERT( nChannel < MAXCHANNELS+MAX2DCHANNELS );
|
|
|
|
if ( alChannel[nChannel] )
|
|
{
|
|
alSourceStop(alChannel[nChannel]);
|
|
|
|
currentChannelVolume [nChannel] = -1;
|
|
currentChannelFrequency [nChannel] = -1;
|
|
currentChannelMaxFrontDistance[nChannel] = -1;
|
|
ChannelPitch [nChannel] = 1.0f;
|
|
}
|
|
}
|
|
|
|
void
|
|
cSampleManager::PreloadStreamedFile(uint8 nFile, uint8 nStream)
|
|
{
|
|
char filename[256];
|
|
|
|
ASSERT( nStream < MAX_STREAMS );
|
|
|
|
if ( nFile < TOTAL_STREAMED_SOUNDS )
|
|
{
|
|
if ( mp3Stream[nStream] )
|
|
{
|
|
delete mp3Stream[nStream];
|
|
mp3Stream[nStream] = NULL;
|
|
}
|
|
|
|
strcpy(filename, StreamedNameTable[nFile]);
|
|
|
|
MP3Stream *stream = new MP3Stream(filename, ALStreamSources[nStream], ALStreamBuffers[nStream]);
|
|
ASSERT(stream != NULL);
|
|
|
|
mp3Stream[nStream] = stream;
|
|
|
|
if ( stream->m_bIsOpened )
|
|
{
|
|
;
|
|
}
|
|
else
|
|
{
|
|
delete stream;
|
|
mp3Stream[nStream] = NULL;
|
|
}
|
|
}
|
|
}
|
|
|
|
void
|
|
cSampleManager::PauseStream(uint8 nPauseFlag, uint8 nStream)
|
|
{
|
|
ASSERT( nStream < MAX_STREAMS );
|
|
|
|
MP3Stream *stream = mp3Stream[nStream];
|
|
|
|
if ( stream )
|
|
{
|
|
if ( nPauseFlag != 0 )
|
|
{
|
|
if ( !stream->m_bIsPaused )
|
|
{
|
|
alSourcePause(stream->m_alSource);
|
|
stream->m_bIsPaused = true;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if ( stream->m_bIsPaused )
|
|
{
|
|
alSourcef(stream->m_alSource, AL_PITCH, 1.0f);
|
|
alSourcePlay(stream->m_alSource);
|
|
stream->m_bIsPaused = false;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void
|
|
cSampleManager::StartPreloadedStreamedFile(uint8 nStream)
|
|
{
|
|
ASSERT( nStream < MAX_STREAMS );
|
|
|
|
MP3Stream *stream = mp3Stream[nStream];
|
|
|
|
if ( stream )
|
|
{
|
|
stream->Initialize();
|
|
if ( stream->m_bIsOpened )
|
|
{
|
|
//NOTE: set pos here on mobile
|
|
|
|
if ( stream->FillBuffers() != 0 )
|
|
{
|
|
alSourcef(stream->m_alSource, AL_PITCH, 1.0f);
|
|
alSourcePlay(stream->m_alSource);
|
|
stream->m_bIsFree = false;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
bool
|
|
cSampleManager::StartStreamedFile(uint8 nFile, uint32 nPos, uint8 nStream)
|
|
{
|
|
char filename[256];
|
|
|
|
ASSERT( nStream < MAX_STREAMS );
|
|
|
|
if ( nFile < TOTAL_STREAMED_SOUNDS )
|
|
{
|
|
if ( mp3Stream[nStream] )
|
|
{
|
|
delete mp3Stream[nStream];
|
|
mp3Stream[nStream] = NULL;
|
|
}
|
|
|
|
strcpy(filename, StreamedNameTable[nFile]);
|
|
|
|
MP3Stream *stream = new MP3Stream(filename, ALStreamSources[nStream], ALStreamBuffers[nStream]);
|
|
ASSERT(stream != NULL);
|
|
|
|
mp3Stream[nStream] = stream;
|
|
|
|
if ( stream->m_bIsOpened )
|
|
{
|
|
stream->Initialize();
|
|
nStreamLength[nFile] = stream->m_nLength;
|
|
//MusicManager.SetTrackInfoLength(nFile, stream->m_nLength);
|
|
|
|
if ( stream->m_bIsOpened )
|
|
{
|
|
if ( nPos != 0 )
|
|
{
|
|
stream->SetPos(nPos);
|
|
}
|
|
|
|
if ( stream->FillBuffers() != 0 )
|
|
{
|
|
alSourcef(stream->m_alSource, AL_PITCH, 1.0f);
|
|
alSourcePlay(stream->m_alSource);
|
|
stream->m_bIsFree = false;
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|
|
else
|
|
{
|
|
delete stream;
|
|
mp3Stream[nStream] = NULL;
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
void
|
|
cSampleManager::StopStreamedFile(uint8 nStream)
|
|
{
|
|
ASSERT( nStream < MAX_STREAMS );
|
|
|
|
MP3Stream *stream = mp3Stream[nStream];
|
|
|
|
if ( stream )
|
|
{
|
|
delete stream;
|
|
mp3Stream[nStream] = NULL;
|
|
}
|
|
}
|
|
|
|
int32
|
|
cSampleManager::GetStreamedFilePosition(uint8 nStream)
|
|
{
|
|
ASSERT( nStream < MAX_STREAMS );
|
|
|
|
MP3Stream *stream = mp3Stream[nStream];
|
|
|
|
if ( stream )
|
|
{
|
|
return (ftell(stream->m_fpFile) * 8) / stream->m_nBitRate;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
void
|
|
cSampleManager::SetStreamedVolumeAndPan(uint8 nVolume, uint8 nPan, uint8 nEffectFlag, uint8 nStream)
|
|
{
|
|
ASSERT( nStream < MAX_STREAMS );
|
|
|
|
if ( nVolume > MAX_VOLUME )
|
|
nVolume = MAX_VOLUME;
|
|
|
|
if ( nPan > MAX_VOLUME )
|
|
nPan = MAX_VOLUME;
|
|
|
|
nStreamVolume[nStream] = m_nMusicFadeVolume * nVolume;
|
|
nStreamPan [nStream] = nPan;
|
|
|
|
MP3Stream *stream = mp3Stream[nStream];
|
|
|
|
if ( stream )
|
|
{
|
|
uint32 vol;
|
|
if ( nEffectFlag )
|
|
vol = m_nEffectsFadeVolume*nVolume*m_nEffectsVolume >> 14;
|
|
else
|
|
vol = m_nMusicFadeVolume*nVolume*m_nMusicVolume >> 14;
|
|
|
|
if ( stream->m_nVolume != vol )
|
|
{
|
|
if ( stream->m_bIsOpened )
|
|
{
|
|
ALuint source = stream->m_alSource;
|
|
if ( source )
|
|
{
|
|
ALfloat gain = ALfloat(vol) / MAX_VOLUME;
|
|
alSourcef(source, AL_GAIN, gain);
|
|
stream = mp3Stream[nStream];
|
|
}
|
|
}
|
|
|
|
stream->m_nVolume = vol;
|
|
}
|
|
}
|
|
}
|
|
|
|
int32
|
|
cSampleManager::GetStreamedFileLength(uint8 nStream)
|
|
{
|
|
ASSERT( nStream < TOTAL_STREAMED_SOUNDS );
|
|
|
|
return nStreamLength[nStream];
|
|
}
|
|
|
|
bool
|
|
cSampleManager::IsStreamPlaying(uint8 nStream)
|
|
{
|
|
ASSERT( nStream < MAX_STREAMS );
|
|
|
|
MP3Stream *stream = mp3Stream[nStream];
|
|
|
|
if ( stream && stream->m_bIsOpened && !stream->m_bIsPaused )
|
|
{
|
|
ALint sourceState;
|
|
alGetSourcei(stream->m_alSource, AL_SOURCE_STATE, &sourceState);
|
|
if ( !stream->m_bIsFree || sourceState == AL_PLAYING )
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
void
|
|
cSampleManager::Service(void)
|
|
{
|
|
for ( int32 i = 0; i < MAX_STREAMS; i++ )
|
|
{
|
|
if ( mp3Stream[i] )
|
|
mp3Stream[i]->Update();
|
|
}
|
|
|
|
UpdateSoundBuffers();
|
|
}
|
|
|
|
bool
|
|
cSampleManager::InitialiseSampleBanks(void)
|
|
{
|
|
int32 nBank = SAMPLEBANK_MAIN;
|
|
|
|
fpSampleDescHandle = fopen(SampleBankDescFilename, "rb");
|
|
if ( fpSampleDescHandle == NULL )
|
|
return false;
|
|
|
|
fpSampleDataHandle = fopen(SampleBankDataFilename, "rb");
|
|
if ( fpSampleDataHandle == NULL )
|
|
{
|
|
fclose(fpSampleDescHandle);
|
|
fpSampleDescHandle = NULL;
|
|
|
|
return false;
|
|
}
|
|
|
|
fseek(fpSampleDataHandle, 0, SEEK_END);
|
|
int32 _nSampleDataEndOffset = ftell(fpSampleDataHandle);
|
|
rewind(fpSampleDataHandle);
|
|
|
|
fread(m_aSamples, sizeof(tSample), TOTAL_AUDIO_SAMPLES, fpSampleDescHandle);
|
|
|
|
fclose(fpSampleDescHandle);
|
|
fpSampleDescHandle = NULL;
|
|
|
|
for ( int32 i = 0; i < TOTAL_AUDIO_SAMPLES; i++ )
|
|
{
|
|
if ( BankStartOffset[nBank] == BankStartOffset[SAMPLEBANK_MAIN] + i )
|
|
{
|
|
nSampleBankDiscStartOffset[nBank] = m_aSamples[i].nOffset;
|
|
nBank++;
|
|
}
|
|
}
|
|
|
|
nSampleBankSize[SAMPLEBANK_MAIN] = nSampleBankDiscStartOffset[SAMPLEBANK_PED] - nSampleBankDiscStartOffset[SAMPLEBANK_MAIN];
|
|
nSampleBankSize[SAMPLEBANK_PED] = _nSampleDataEndOffset - nSampleBankDiscStartOffset[SAMPLEBANK_PED];
|
|
|
|
return true;
|
|
}
|
|
|
|
/*
|
|
sub_1D8D40
|
|
PreloadSoundBank(tSample *,uchar)
|
|
CheckOpenALChannels(void)
|
|
*/
|
|
|
|
void MP3Stream::Initialize(void)
|
|
{
|
|
if ( !m_bIsOpened )
|
|
return;
|
|
|
|
mpg123_format_none(m_pMPG);
|
|
|
|
mpg123_format(m_pMPG, 11000, MPG123_MONO|MPG123_STEREO, MPG123_ENC_SIGNED_16);
|
|
mpg123_format(m_pMPG, 24000, MPG123_MONO|MPG123_STEREO, MPG123_ENC_SIGNED_16);
|
|
mpg123_format(m_pMPG, 32000, MPG123_MONO|MPG123_STEREO, MPG123_ENC_SIGNED_16);
|
|
mpg123_format(m_pMPG, 44100, MPG123_MONO|MPG123_STEREO, MPG123_ENC_SIGNED_16);
|
|
|
|
if ( mpg123_open_feed(m_pMPG) != MPG123_OK )
|
|
return;
|
|
|
|
const uint32 CHUNK_SIZE = 1024*5;
|
|
|
|
if ( fread(m_pBuf, 1, CHUNK_SIZE, m_fpFile) != CHUNK_SIZE )
|
|
{
|
|
Delete();
|
|
return;
|
|
}
|
|
|
|
m_nBufSize -= CHUNK_SIZE;
|
|
|
|
mpg123_feed(m_pMPG, m_pBuf, CHUNK_SIZE);
|
|
|
|
if ( mpg123_getformat(m_pMPG, &m_nRate, &m_nChannels, &m_nEncoding) != MPG123_OK )
|
|
{
|
|
Delete();
|
|
return;
|
|
}
|
|
|
|
mpg123_frameinfo info;
|
|
if ( mpg123_info(m_pMPG, &info) != MPG123_OK )
|
|
{
|
|
Delete();
|
|
return;
|
|
}
|
|
|
|
m_nBitRate = info.bitrate;
|
|
m_nLength = 8 * m_nLengthInBytes / info.bitrate;
|
|
m_nBlockSize = mpg123_outblock(m_pMPG);
|
|
m_nNumBlocks = 5;
|
|
m_pBlocks = (unsigned char *)malloc(m_nNumBlocks * m_nBlockSize);
|
|
}
|
|
|
|
bool MP3Stream::FillBuffer(ALuint alBuffer)
|
|
{
|
|
size_t done;
|
|
|
|
uint8 *pBlockBuff = (uint8 *)m_pBlocks;
|
|
|
|
bool fail = !(m_nBufSize > 1);
|
|
|
|
int err = mpg123_read(m_pMPG, m_pBlocks, m_nBlockSize, &done);
|
|
if ( alBuffer == 0 )
|
|
{
|
|
if ( err == MPG123_OK )
|
|
{
|
|
while ( mpg123_read(m_pMPG, pBlockBuff, m_nBlockSize, &done) == MPG123_OK )
|
|
;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
int32 blocks = 0;
|
|
for ( blocks = 0; blocks < m_nNumBlocks; blocks++ )
|
|
{
|
|
if ( err == MPG123_NEED_MORE )
|
|
{
|
|
if ( fail )
|
|
break;
|
|
|
|
size_t readSize = m_nBufSize;
|
|
if ( readSize > 0x4000 )
|
|
{
|
|
if ( fread(m_pBuf, 1, 0x4000, m_fpFile) != 0x4000 )
|
|
{
|
|
fail = true;
|
|
TRACE("MP3 ************* : MP3 read unsuccessful mid file, stopping queuing");
|
|
break;
|
|
}
|
|
|
|
m_nBufSize -= 0x4000;
|
|
mpg123_feed(m_pMPG, m_pBuf, 0x4000);
|
|
}
|
|
else
|
|
{
|
|
if ( fread(m_pBuf, 1, readSize, m_fpFile) != readSize )
|
|
{
|
|
fail = true;
|
|
break;
|
|
}
|
|
|
|
m_nBufSize -= readSize;
|
|
mpg123_feed(m_pMPG, m_pBuf, readSize);
|
|
}
|
|
}
|
|
else if ( err == MPG123_OK )
|
|
{
|
|
pBlockBuff += m_nBlockSize;
|
|
}
|
|
else
|
|
{
|
|
fail = true;
|
|
break;
|
|
}
|
|
|
|
err = mpg123_read(m_pMPG, pBlockBuff, m_nBlockSize, &done);
|
|
}
|
|
|
|
if ( blocks != 0 )
|
|
{
|
|
if ( m_nChannels == 1 )
|
|
alBufferData(alBuffer, AL_FORMAT_MONO16, m_pBlocks, m_nBlockSize*blocks, m_nRate);
|
|
else
|
|
alBufferData(alBuffer, AL_FORMAT_STEREO16, m_pBlocks, m_nBlockSize*blocks, m_nRate);
|
|
}
|
|
|
|
if ( fail && blocks < m_nNumBlocks )
|
|
m_bIsFree = true;
|
|
|
|
return blocks != 0;
|
|
}
|
|
|
|
void MP3Stream::Update(void)
|
|
{
|
|
if ( !m_bIsOpened )
|
|
return;
|
|
|
|
if ( m_bIsFree )
|
|
return;
|
|
|
|
if ( !m_bIsPaused )
|
|
{
|
|
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_bIsFree && FillBuffer(buffer) )
|
|
alSourceQueueBuffers(m_alSource, 1, &buffer);
|
|
}
|
|
|
|
if ( sourceState != AL_PLAYING )
|
|
{
|
|
alSourcef(m_alSource, AL_PITCH, 1.0f);
|
|
alSourcePlay(m_alSource);
|
|
}
|
|
}
|
|
}
|
|
|
|
void MP3Stream::SetPos(uint32 nPos)
|
|
{
|
|
uint32 pos = nPos;
|
|
if ( nPos > m_nLength )
|
|
pos %= m_nLength;
|
|
|
|
uint32 blockPos = m_nBitRate * pos / 8;
|
|
if ( blockPos > m_nLengthInBytes )
|
|
blockPos %= m_nLengthInBytes;
|
|
|
|
fseek(m_fpFile, blockPos, SEEK_SET);
|
|
|
|
size_t done;
|
|
while ( mpg123_read(m_pMPG, m_pBlocks, m_nBlockSize, &done) == MPG123_OK )
|
|
;
|
|
}
|
|
|
|
int32 MP3Stream::FillBuffers()
|
|
{
|
|
int32 i = 0;
|
|
for ( i = 0; i < ARRAY_SIZE(m_alBuffers); i++ )
|
|
{
|
|
if ( !FillBuffer(m_alBuffers[i]) )
|
|
break;
|
|
alSourceQueueBuffers(m_alSource, 1, &m_alBuffers[i]);
|
|
}
|
|
|
|
return i;
|
|
}
|
|
|
|
MP3Stream::MP3Stream(char *filename, ALuint source, ALuint *buffers)
|
|
{
|
|
strcpy(m_aFilename, filename);
|
|
memset(m_alBuffers, 0, sizeof(m_alBuffers));
|
|
m_alSource = source;
|
|
memcpy(m_alBuffers, buffers, sizeof(m_alBuffers));
|
|
m_nVolume = -1;
|
|
m_pBlocks = NULL;
|
|
m_pBuf = NULL;
|
|
m_pMPG = NULL;
|
|
m_bIsPaused = false;
|
|
m_bIsOpened = true;
|
|
m_bIsFree = true;
|
|
m_fpFile = fopen(m_aFilename, "rb");
|
|
|
|
if ( m_fpFile )
|
|
{
|
|
m_nBufSize = filelength(fileno(m_fpFile));
|
|
m_nLengthInBytes = m_nBufSize;
|
|
m_pMPG = mpg123_new(NULL, NULL);
|
|
m_pBuf = (unsigned char *)malloc(0x4000);
|
|
}
|
|
else
|
|
{
|
|
m_bIsOpened = false;
|
|
Delete();
|
|
}
|
|
}
|
|
|
|
void MP3Stream::Delete()
|
|
{
|
|
if ( m_pMPG )
|
|
{
|
|
mpg123_delete(m_pMPG);
|
|
m_pMPG = NULL;
|
|
}
|
|
|
|
if ( m_fpFile )
|
|
{
|
|
fclose(m_fpFile);
|
|
m_fpFile = NULL;
|
|
}
|
|
|
|
if ( m_alSource )
|
|
{
|
|
ALint sourceState = AL_STOPPED;
|
|
alGetSourcei(m_alSource, AL_SOURCE_STATE, &sourceState);
|
|
if (sourceState != AL_STOPPED )
|
|
alSourceStop(m_alSource);
|
|
|
|
ALint buffersQueued;
|
|
alGetSourcei(m_alSource, AL_BUFFERS_QUEUED, &buffersQueued);
|
|
|
|
ALuint value;
|
|
while (buffersQueued--)
|
|
alSourceUnqueueBuffers(m_alSource, 1, &value);
|
|
|
|
m_alSource = 0;
|
|
}
|
|
|
|
if ( m_pBlocks )
|
|
{
|
|
free(m_pBlocks);
|
|
m_pBlocks = NULL;
|
|
}
|
|
|
|
if ( m_pBuf )
|
|
{
|
|
free(m_pBuf);
|
|
m_pBuf = NULL;
|
|
}
|
|
|
|
m_bIsOpened = false;
|
|
} |