6b3e9c5a9d
Updated logger to allow a user to create callbacks to receive log messages Logger also gives more information, time the message was sent, the source, the importance, and the message itself. User can now query playback devices and specify the device for the audio manager to use. The audio manager is no longer a singleton, although creating multiple managers is not advised. Clean up and optimization of manager initialization code. IAudioCapture can now be told which device to capture audio from. The user can also create multiple IAudioCaptures to capture audio from multiple sources at the same time. Added additional error checking. A seperate thread is used to capture audio now. Defines added to allow a user to remove support for default codecs.
419 lines
9.8 KiB
C++
419 lines
9.8 KiB
C++
#include <iostream>
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
#include "../Headers/cAudio.h"
|
|
#include "../Headers/cLogger.h"
|
|
|
|
namespace cAudio
|
|
{
|
|
cAudio::cAudio(IAudioDecoder* decoder) : Decoder(decoder)
|
|
{
|
|
Mutex.lock();
|
|
streaming = false;
|
|
playaudio = false;
|
|
pauseaudio = false;
|
|
toloop = false;
|
|
|
|
//Generates 3 buffers for the ogg file
|
|
alGenBuffers(3, buffers);
|
|
//Creates one source to be stored.
|
|
alGenSources(1, &source);
|
|
checkError();
|
|
Mutex.unlock();
|
|
}
|
|
|
|
cAudio::~cAudio()
|
|
{
|
|
Mutex.lock();
|
|
delete Decoder;
|
|
Mutex.unlock();
|
|
}
|
|
|
|
//!Stops all playing sound sources and deletes the sources and buffers
|
|
void cAudio::release()
|
|
{
|
|
Mutex.lock();
|
|
//Stops the audio source
|
|
alSourceStop(source);
|
|
empty();
|
|
//Deletes the source
|
|
alDeleteSources(1, &source);
|
|
//deletes the last filled buffer
|
|
alDeleteBuffers(3, buffers);
|
|
checkError();
|
|
Mutex.unlock();
|
|
}
|
|
|
|
//!Plays back sound source
|
|
bool cAudio::playback()
|
|
{
|
|
Mutex.lock();
|
|
bool play = playing();
|
|
Mutex.unlock();
|
|
return play;
|
|
}
|
|
|
|
bool cAudio::paused()
|
|
{
|
|
Mutex.lock();
|
|
ALenum state = 0;
|
|
|
|
alGetSourcei(source, AL_SOURCE_STATE, &state);
|
|
|
|
Mutex.unlock();
|
|
return (state == AL_PAUSED);
|
|
}
|
|
|
|
//!checks to see if audio source is playing if it is returns true
|
|
bool cAudio::playing()
|
|
{
|
|
Mutex.lock();
|
|
ALenum state = 0;
|
|
|
|
alGetSourcei(source, AL_SOURCE_STATE, &state);
|
|
|
|
Mutex.unlock();
|
|
return (state == AL_PLAYING);
|
|
}
|
|
|
|
//!updates the sound source by refilling the buffers with ogg data.
|
|
bool cAudio::update()
|
|
{
|
|
Mutex.lock();
|
|
if(!isvalid() || !playing())
|
|
{
|
|
Mutex.unlock();
|
|
return false;
|
|
}
|
|
|
|
int processed = 0;
|
|
bool active = true;
|
|
//gets the sound source processed buffers/
|
|
alGetSourcei(source, AL_BUFFERS_PROCESSED, &processed);
|
|
//while there is more data refill buffers with audio data.
|
|
while (processed--)
|
|
{
|
|
ALuint buffer;
|
|
|
|
alSourceUnqueueBuffers(source, 1, &buffer);
|
|
|
|
active = stream(buffer);
|
|
|
|
//if more in stream continue playing.
|
|
if(active)
|
|
alSourceQueueBuffers(source, 1, &buffer);
|
|
|
|
checkError();
|
|
}
|
|
Mutex.unlock();
|
|
return active;
|
|
}
|
|
|
|
//!The streaming function
|
|
bool cAudio::stream(ALuint buffer)
|
|
{
|
|
if(Decoder)
|
|
{
|
|
//stores the caculated data into buffer that is passed to output.
|
|
size_t totalread = 0;
|
|
char tempbuffer[BUFFER_SIZE];
|
|
while( totalread < BUFFER_SIZE )
|
|
{
|
|
char tempbuffer2[BUFFER_SIZE];
|
|
int actualread = Decoder->readAudioData(tempbuffer2, BUFFER_SIZE-totalread);
|
|
if(actualread > 0)
|
|
{
|
|
memcpy(tempbuffer+totalread,tempbuffer2,actualread);
|
|
totalread += actualread;
|
|
}
|
|
if(actualread < 0)
|
|
{
|
|
break;
|
|
}
|
|
if(actualread == 0)
|
|
{
|
|
if(toloop)
|
|
{
|
|
//If we are to loop, set to the beginning and reload from the start
|
|
Decoder->setPosition(0,false);
|
|
}
|
|
else
|
|
break;
|
|
}
|
|
}
|
|
|
|
//Second check, in case looping is not enabled, we will return false for end of stream
|
|
if(totalread == 0)
|
|
{
|
|
return false;
|
|
}
|
|
//std::cout << buffer << std::endl;
|
|
alBufferData(buffer, Decoder->getFormat(), tempbuffer, totalread, Decoder->getFrequency());
|
|
checkError();
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
//!clears the sound sources buffers and makes them free to be used by other sound sources.
|
|
void cAudio::empty()
|
|
{
|
|
int queued = 0;
|
|
//grabs allt he sources buffers.
|
|
alGetSourcei(source, AL_BUFFERS_QUEUED, &queued);
|
|
|
|
while (queued--)
|
|
{
|
|
ALuint buffer;
|
|
//unqueues sources buffers to be used for others.
|
|
alSourceUnqueueBuffers(source, 1, &buffer);
|
|
checkError();
|
|
}
|
|
}
|
|
|
|
//!Checks the given functions
|
|
void cAudio::checkError()
|
|
{
|
|
int error = alGetError();
|
|
const char* errorString;
|
|
|
|
if (error != AL_NO_ERROR)
|
|
{
|
|
errorString = alGetString(error);
|
|
if(error == AL_OUT_OF_MEMORY)
|
|
getLogger()->logCritical("Audio Source", "OpenAL Error: %s.", errorString);
|
|
else
|
|
getLogger()->logError("Audio Source", "OpenAL Error: %s.", errorString);
|
|
}
|
|
}
|
|
|
|
//!checks to see if the given ogg file is valid
|
|
bool cAudio::isvalid()
|
|
{
|
|
Mutex.lock();
|
|
bool state = (Decoder != 0);
|
|
Mutex.unlock();
|
|
return state;
|
|
}
|
|
|
|
//!Sets the sound source relativity to follow the listener to give the illusion of stereo 2d sound
|
|
void cAudio::play2d(bool loop)
|
|
{
|
|
Mutex.lock();
|
|
alSourcei (source, AL_SOURCE_RELATIVE, true);
|
|
toloop = loop;
|
|
play();
|
|
alSourcePlay(source);
|
|
checkError();
|
|
Mutex.unlock();
|
|
}
|
|
|
|
//!Plays the given audio file with 3d position
|
|
void cAudio::play3d(cVector3 position, float soundstr, bool loop)
|
|
{
|
|
Mutex.lock();
|
|
this->position = position;
|
|
this->strength = soundstr;
|
|
alSourcei (source, AL_SOURCE_RELATIVE, false);
|
|
alSource3f(source, AL_POSITION, position.x, position.y, position.z);
|
|
alSourcef (source, AL_ROLLOFF_FACTOR, soundstr);
|
|
toloop = loop;
|
|
play();
|
|
alSourcePlay(source);
|
|
checkError();
|
|
Mutex.unlock();
|
|
}
|
|
|
|
//!Used to tell the soundsource to loop or not
|
|
void cAudio::loop(bool loop)
|
|
{
|
|
Mutex.lock();
|
|
toloop = loop;
|
|
Mutex.unlock();
|
|
}
|
|
|
|
//!Used to move the audio sources position after the initial creation
|
|
void cAudio::setPosition(const cVector3 position)
|
|
{
|
|
Mutex.lock();
|
|
this->position = position;
|
|
alSource3f(source, AL_POSITION, position.x, position.y, position.z);
|
|
checkError();
|
|
Mutex.unlock();
|
|
}
|
|
|
|
//!Used to set the velocity of the audio source.
|
|
void cAudio::setVelocity(const cVector3 velocity)
|
|
{
|
|
Mutex.lock();
|
|
this->velocity = velocity;
|
|
alSource3f(source, AL_VELOCITY, velocity.x, velocity.y, velocity.z);
|
|
checkError();
|
|
Mutex.unlock();
|
|
}
|
|
|
|
//!Used to set the direction of the audio source
|
|
void cAudio::setDirection(const cVector3 direction)
|
|
{
|
|
Mutex.lock();
|
|
this->direction = direction;
|
|
alSource3f(source, AL_DIRECTION, direction.x, direction.y, direction.z);
|
|
checkError();
|
|
Mutex.unlock();
|
|
}
|
|
|
|
//!Used to set the sound strength or roll off factor
|
|
void cAudio::setStrength(const float soundstrength)
|
|
{
|
|
Mutex.lock();
|
|
alSourcef(source, AL_ROLLOFF_FACTOR, soundstrength);
|
|
checkError();
|
|
Mutex.unlock();
|
|
}
|
|
|
|
//!Used to set the pitch of the audio file
|
|
void cAudio::setPitch(const float pitch)
|
|
{
|
|
Mutex.lock();
|
|
this->pitch = pitch;
|
|
alSourcef (source, AL_PITCH, pitch);
|
|
checkError();
|
|
Mutex.unlock();
|
|
}
|
|
|
|
//!Used to set the volume of the audio source
|
|
void cAudio::setVolume(const float volume)
|
|
{
|
|
Mutex.lock();
|
|
this->volume = volume;
|
|
alSourcef(source, AL_GAIN, volume);
|
|
checkError();
|
|
Mutex.unlock();
|
|
}
|
|
|
|
//!Used to set the doppler strength of the audio sources doppler effect
|
|
void cAudio::setDopplerStrength(const float dstrength)
|
|
{
|
|
Mutex.lock();
|
|
this->dstrength = dstrength;
|
|
alSourcef(source, AL_DOPPLER_FACTOR, dstrength);
|
|
checkError();
|
|
Mutex.unlock();
|
|
}
|
|
|
|
//!Used to set the doppler velocity of the audio source
|
|
void cAudio::setDopplerVelocity(const cVector3 dvelocity)
|
|
{
|
|
Mutex.lock();
|
|
this->dvelocity = dvelocity;
|
|
alSource3f(source, AL_DOPPLER_VELOCITY, dvelocity.x, dvelocity.y, dvelocity.z);
|
|
checkError();
|
|
Mutex.unlock();
|
|
}
|
|
|
|
const cVector3& cAudio::getPosition()const
|
|
{
|
|
return this->position;
|
|
}
|
|
|
|
const cVector3& cAudio::getVelocity()const
|
|
{
|
|
return this->velocity;
|
|
}
|
|
|
|
const cVector3& cAudio::getDirection()const
|
|
{
|
|
return this->direction;
|
|
}
|
|
|
|
const float& cAudio::getDopplerStrength()const
|
|
{
|
|
return this->dstrength;
|
|
}
|
|
|
|
const float& cAudio::getStrength()const
|
|
{
|
|
return this->strength;
|
|
}
|
|
|
|
const float& cAudio::getVolume()const
|
|
{
|
|
return this->volume;
|
|
}
|
|
|
|
const float& cAudio::getPitch()const
|
|
{
|
|
return this->pitch;
|
|
}
|
|
|
|
const bool& cAudio::isLooping()const
|
|
{
|
|
return this->toloop;
|
|
}
|
|
|
|
//!Allows us to seek through a stream
|
|
void cAudio::seek(float secs)
|
|
{
|
|
Mutex.lock();
|
|
if(Decoder->isSeekingSupported())
|
|
{
|
|
Decoder->seek(secs, false);
|
|
}
|
|
Mutex.unlock();
|
|
}
|
|
|
|
//!Used to play the audio source
|
|
bool cAudio::play()
|
|
{
|
|
Mutex.lock();
|
|
playaudio = true;
|
|
if (!paused())
|
|
{
|
|
int queueSize = 0;
|
|
for(int u = 0; u < 3; u++)
|
|
{
|
|
int val = stream(buffers[u]);
|
|
|
|
if(val < 0)
|
|
{
|
|
return false;
|
|
}
|
|
else if(val > 0)
|
|
++queueSize;
|
|
}
|
|
//Stores the sources 3 buffers to be used in the queue
|
|
alSourceQueueBuffers(source, queueSize, buffers);
|
|
checkError();
|
|
}
|
|
alSourcePlay(source);
|
|
checkError();
|
|
Mutex.unlock();
|
|
return true;
|
|
}
|
|
|
|
//!Used to stop the audio source
|
|
void cAudio::stop()
|
|
{
|
|
Mutex.lock();
|
|
playaudio = false;
|
|
alSourceStop(source);
|
|
checkError();
|
|
Mutex.unlock();
|
|
}
|
|
|
|
//!Used to pause the audio source
|
|
void cAudio::pause()
|
|
{
|
|
Mutex.lock();
|
|
playaudio = false;
|
|
alSourcePause(source);
|
|
checkError();
|
|
Mutex.unlock();
|
|
}
|
|
|
|
const ALuint& cAudio::getSource()const
|
|
{
|
|
return this->source;
|
|
}
|
|
}
|