249 lines
7.0 KiB
C++
Executable File
249 lines
7.0 KiB
C++
Executable File
|
|
#include "cAudioSource.h"
|
|
|
|
namespace cAudio
|
|
{
|
|
class cAudioBuffer : public IAudioBuffer
|
|
{
|
|
ALuint Buffer;
|
|
bool Valid;
|
|
float TotalTime;
|
|
|
|
public:
|
|
|
|
cAudioBuffer(IAudioDecoder *decoder)
|
|
{
|
|
Buffer = 0;
|
|
Valid = false;
|
|
TotalTime = decoder->getTotalTime();
|
|
|
|
decoder->setPosition(0, false);
|
|
|
|
const int totalSize = decoder->getTotalSize()&~1;
|
|
if (totalSize > 0)
|
|
{
|
|
cAudioVector<char>::Type data(totalSize, 0);
|
|
|
|
int totalread = 0;
|
|
unsigned errorcount = 0;
|
|
while (totalread < totalSize)
|
|
{
|
|
const int actualread = decoder->readAudioData(&data[totalread], totalSize - totalread);
|
|
if (actualread > 0) {
|
|
totalread += actualread;
|
|
} else if (actualread < 0) {
|
|
++errorcount;
|
|
getLogger()->logDebug("Audio Buffer", "Decoder returned an error: %i (%i of 3)", actualread, errorcount);
|
|
if(errorcount >= 3) {
|
|
break;
|
|
}
|
|
} else {
|
|
break;
|
|
}
|
|
}
|
|
if (totalread != totalSize) {
|
|
getLogger()->logError("Audio Buffer", "Stopped short");
|
|
}
|
|
|
|
alGenBuffers(1, &Buffer);
|
|
checkALError();
|
|
const ALsizei freq = decoder->getFrequency();
|
|
const ALenum format = convertAudioFormatEnum(decoder->getFormat());
|
|
getLogger()->logDebug("Audio Buffer", "Buffered %d bytes of data into buffer %d at %d hz.", totalread, (int)Buffer, (int)freq);
|
|
alBufferData(Buffer, format, &data[0], data.size(), freq);
|
|
checkALError();
|
|
Valid = true;
|
|
}
|
|
}
|
|
|
|
~cAudioBuffer()
|
|
{
|
|
if (Valid)
|
|
{
|
|
alDeleteBuffers(1, &Buffer);
|
|
}
|
|
}
|
|
|
|
bool isValid() const { return Valid; }
|
|
unsigned getBuffer() const { return Buffer; }
|
|
|
|
int getChannels() const
|
|
{
|
|
ALint channels = 0;
|
|
alGetBufferi(Buffer, AL_CHANNELS, &channels);
|
|
return channels;
|
|
}
|
|
|
|
int getTotalAudioSize() const
|
|
{
|
|
ALint size = -1;
|
|
alGetBufferi(Buffer, AL_SIZE, &size);
|
|
return size;
|
|
}
|
|
|
|
float getTotalAudioTime() const { return TotalTime; }
|
|
};
|
|
|
|
|
|
class cAudioStaticSource : public cAudioSourceBase
|
|
{
|
|
IAudioBuffer* Buffer;
|
|
|
|
public:
|
|
cAudioStaticSource(IAudioBuffer* buffer, IAudioDeviceContext* context)
|
|
: cAudioSourceBase(context), Buffer(NULL)
|
|
{
|
|
setBuffer(buffer);
|
|
}
|
|
|
|
~cAudioStaticSource()
|
|
{
|
|
if (Buffer)
|
|
Buffer->drop();
|
|
}
|
|
|
|
bool setBuffer(IAudioBuffer* buffer)
|
|
{
|
|
if (isPlaying())
|
|
stop();
|
|
|
|
if (Buffer)
|
|
Buffer->drop();
|
|
|
|
Buffer = buffer;
|
|
|
|
if (Buffer) {
|
|
Buffer->grab();
|
|
alSourcei(Source, AL_BUFFER, Buffer->getBuffer());
|
|
checkALError();
|
|
}
|
|
return true;
|
|
}
|
|
|
|
IAudioBuffer *getBuffer()
|
|
{
|
|
return Buffer;
|
|
}
|
|
|
|
bool play()
|
|
{
|
|
alSourcePlay(Source);
|
|
checkALError();
|
|
getLogger()->logDebug("Audio Static Source", "Source playing.");
|
|
signalEvent(ON_PLAY);
|
|
oldState = AL_PLAYING;
|
|
return true;
|
|
}
|
|
|
|
bool play2d(const bool& toLoop)
|
|
{
|
|
alSourcei(Source, AL_SOURCE_RELATIVE, true);
|
|
alSourcei(Source, AL_LOOPING, toLoop);
|
|
checkALError();
|
|
return play();
|
|
}
|
|
|
|
bool play3d(const cVector3& position, const float& soundstr, const bool& toLoop)
|
|
{
|
|
alSourcei(Source, AL_SOURCE_RELATIVE, false);
|
|
alSourcei(Source, AL_LOOPING, toLoop);
|
|
checkALError();
|
|
setPosition(position);
|
|
setStrength(soundstr);
|
|
return play();
|
|
}
|
|
|
|
void pause()
|
|
{
|
|
alSourcePause(Source);
|
|
checkALError();
|
|
getLogger()->logDebug("Audio Static Source", "Source paused.");
|
|
signalEvent(ON_PAUSE);
|
|
oldState = AL_PAUSED;
|
|
}
|
|
|
|
void stop()
|
|
{
|
|
alSourceStop(Source);
|
|
alSourceRewind(Source);
|
|
checkALError();
|
|
getLogger()->logDebug("Audio Static Source", "Source stopped.");
|
|
signalEvent(ON_STOP);
|
|
oldState = AL_STOPPED;
|
|
}
|
|
|
|
void loop(const bool& toLoop)
|
|
{
|
|
alSourcei(Source, AL_LOOPING, toLoop);
|
|
checkALError();
|
|
}
|
|
|
|
bool seek(const float& seconds, bool relative)
|
|
{
|
|
float start = relative ? getCurrentAudioTime() : 0.f;
|
|
alSourcef(Source, AL_SEC_OFFSET, start + seconds);
|
|
checkALError();
|
|
return true;
|
|
}
|
|
|
|
float getTotalAudioTime() { return Buffer ? Buffer->getTotalAudioTime() : 0.f; }
|
|
int getTotalAudioSize() { return Buffer ? Buffer->getTotalAudioSize() : 0; }
|
|
|
|
int getCompressedAudioSize() { return -1; }
|
|
|
|
float getCurrentAudioTime()
|
|
{
|
|
float time = -1;
|
|
alGetSourcef(Source, AL_SEC_OFFSET, &time);
|
|
return time;
|
|
}
|
|
|
|
int getCurrentAudioPosition()
|
|
{
|
|
int offset = -1;
|
|
alGetSourcei(Source, AL_BYTE_OFFSET, &offset);
|
|
return offset;
|
|
}
|
|
|
|
int getCurrentCompressedAudioPosition() { return -1; }
|
|
|
|
bool update()
|
|
{
|
|
if(isValid() || isPlaying()) {
|
|
signalEvent(ON_UPDATE);
|
|
}
|
|
|
|
ALenum state;
|
|
alGetSourcei(Source, AL_SOURCE_STATE, &state);
|
|
checkALError();
|
|
if(state == AL_STOPPED && oldState != state)
|
|
{
|
|
getLogger()->logDebug("Audio Static Source", "Source stopped.");
|
|
signalEvent(ON_STOP);
|
|
oldState = state;
|
|
}
|
|
return state != AL_STOPPED;
|
|
}
|
|
|
|
bool isValid() const
|
|
{
|
|
return Buffer ? Buffer->isValid() : false;
|
|
}
|
|
|
|
bool isLooping() const
|
|
{
|
|
ALint looping = false;
|
|
alGetSourcei(Source, AL_LOOPING, &looping);
|
|
return looping == AL_TRUE;
|
|
}
|
|
|
|
#if CAUDIO_EFX_ENABLED == 1
|
|
virtual unsigned int getNumEffectSlotsAvailable() const { return 0; }
|
|
virtual bool attachEffect(unsigned int slot, IEffect* effect) { return false; }
|
|
virtual void removeEffect(unsigned int slot) {}
|
|
virtual bool attachFilter(IFilter* filter) { return false; }
|
|
virtual void removeFilter() {}
|
|
#endif
|
|
};
|
|
}
|