diff --git a/cAudio/Headers/cAudioCapture.h b/cAudio/Headers/cAudioCapture.h index aaa6404..c92ce6d 100644 --- a/cAudio/Headers/cAudioCapture.h +++ b/cAudio/Headers/cAudioCapture.h @@ -4,8 +4,7 @@ #pragma once -#include -#include +#include "cOpenALUtil.h" #include "cMutex.h" #include "cMemoryOverride.h" #include "IAudioCapture.h" @@ -36,8 +35,8 @@ namespace cAudio virtual void updateCaptureBuffer(bool force = false); virtual void shutdown(); virtual bool isUpdateThreadRunning() - { - return (AudioThread != NULL && AudioThread->isRunning()); + { + return (AudioThread != NULL && AudioThread->isRunning()); } virtual const char* getDeviceName() { return toUTF8(DeviceName); } @@ -68,7 +67,7 @@ namespace cAudio cAudioMutex Mutex; - //! Our update thread + //! Our update thread IThread* AudioThread; bool initOpenALDevice(); @@ -92,4 +91,4 @@ namespace cAudio ALenum convertAudioFormatEnum(AudioFormats format); void signalEvent(Events sevent); }; -}; \ No newline at end of file +}; diff --git a/cAudio/Headers/cAudioManager.h b/cAudio/Headers/cAudioManager.h index 62ad2ef..4e2f440 100644 --- a/cAudio/Headers/cAudioManager.h +++ b/cAudio/Headers/cAudioManager.h @@ -18,6 +18,7 @@ namespace cAudio { class IAudioSource; + class IAudioBuffer; class cAudioManager : public IAudioManager, public cMemoryOverride, public IThreadWorker { @@ -31,11 +32,11 @@ namespace cAudio ON_DATASOURCEREGISTER, }; - cAudioManager() : AudioThread(NULL), AudioContext(NULL), Initialized(false), MasterVolume(1.0f) { } + cAudioManager() : Initialized(false), AudioThread(NULL), AudioContext(NULL), MasterVolume(1.0f) { } virtual ~cAudioManager(); virtual bool initialize(const char* deviceName = 0x0, int outputFrequency = -1, int eaxEffectSlots = 4); - virtual void shutDown(); + virtual void shutDown(); virtual void update(); virtual IAudioSource* getSoundByName(const char* name); virtual void releaseAllSources(); @@ -46,6 +47,10 @@ namespace cAudio virtual void setMasterVolume(float vol); virtual float getMasterVolume() const; + virtual void setSpeedOfSound(float speed); + virtual float getSpeedOfSound() const; + virtual void setDopplerFactor(float factor) const; + virtual float getDopplerFactor() const; virtual void stopAllSounds(); virtual IAudioSource* create(const char* name, const char* filename, bool stream = false); @@ -53,6 +58,9 @@ namespace cAudio virtual IAudioSource* createFromRaw(const char* name, const char* data, size_t length, unsigned int frequency, AudioFormats format); virtual IAudioSource* createFromAudioBuffer(const char* name, AudioCaptureBuffer* pBiffer, unsigned int frequency, AudioFormats format); + virtual IAudioBuffer* createBuffer(const char* filename); + virtual IAudioSource* createStatic(IAudioBuffer* buffer); + virtual bool registerAudioDecoder(IAudioDecoderFactory* factory, const char* extension); virtual void unRegisterAudioDecoder(const char* extension); virtual bool isAudioDecoderRegistered(const char* extension); @@ -77,6 +85,8 @@ namespace cAudio virtual IAudioEffects* getEffects(); #endif + virtual cAudioMutex *getMutex() { return &Mutex; } + protected: virtual void run(); @@ -101,6 +111,7 @@ namespace cAudio typedef cAudioMap::Type::iterator audioIndexIterator; //! Holds all managed audio sources cAudioVector::Type audioSources; + cAudioVector::Type updateSources; //! Holds audio sources which gets deleted from the audioManager cAudioVector::Type managedAudioSources; //! Holds audio sources which gets deleted from the audioManager diff --git a/cAudio/Headers/cAudioSource.h b/cAudio/Headers/cAudioSource.h index 0797142..387b553 100644 --- a/cAudio/Headers/cAudioSource.h +++ b/cAudio/Headers/cAudioSource.h @@ -7,9 +7,8 @@ #include #include #include -#include -#include +#include "cOpenALUtil.h" #include "cMutex.h" #include "cEFXFunctions.h" #include "cMemoryOverride.h" @@ -21,8 +20,8 @@ namespace cAudio { - - class cAudioSource : public IAudioSource, public cMemoryOverride + + class cAudioSourceBase : public IAudioSource, public cMemoryOverride { public: @@ -34,38 +33,13 @@ namespace cAudio ON_STOP, }; -#if CAUDIO_EFX_ENABLED == 1 - cAudioSource(IAudioDecoder* decoder, IAudioDeviceContext* context, cEFXFunctions* oALFunctions); -#else - cAudioSource(IAudioDecoder* decoder, IAudioDeviceContext* context); -#endif - ~cAudioSource(); + cAudioSourceBase(IAudioDeviceContext* context); + virtual ~cAudioSourceBase(); - virtual bool play(); - virtual bool play2d(const bool& toLoop = false); - virtual bool play3d(const cVector3& position, const float& soundstr = 1.0 , const bool& toLoop = false); - - virtual void pause(); - virtual void stop(); - virtual void loop(const bool& toLoop); - virtual bool seek(const float& seconds, bool relative = false); + virtual bool isPlaying() const; + virtual bool isPaused() const; + virtual bool isStopped() const; - virtual float getTotalAudioTime(); - virtual int getTotalAudioSize(); - virtual int getCompressedAudioSize(); - - virtual float getCurrentAudioTime(); - virtual int getCurrentAudioPosition(); - virtual int getCurrentCompressedAudioPosition(); - - virtual bool update(); - - virtual const bool isValid() const; - virtual const bool isPlaying() const; - virtual const bool isPaused() const; - virtual const bool isStopped() const; - virtual const bool isLooping() const; - virtual void setPosition(const cVector3& position); virtual void setVelocity(const cVector3& velocity); virtual void setDirection(const cVector3& direction); @@ -89,31 +63,90 @@ namespace cAudio virtual void move(const cVector3& position); - virtual const cVector3 getPosition() const; - virtual const cVector3 getVelocity() const; - virtual const cVector3 getDirection() const; + virtual cVector3 getPosition() const; + virtual cVector3 getVelocity() const; + virtual cVector3 getDirection() const; - virtual const float getRolloffFactor() const; - virtual const float getStrength() const; - virtual const float getMinDistance() const; - virtual const float getMaxDistance() const; + virtual float getRolloffFactor() const; + virtual float getStrength() const; + virtual float getMinDistance() const; + virtual float getMaxDistance() const; - virtual const float getPitch() const; - virtual const float getVolume() const; - virtual const float getMinVolume() const; - virtual const float getMaxVolume() const; + virtual bool isRelative() const; + virtual float calculateGain() const; - virtual const float getInnerConeAngle() const; - virtual const float getOuterConeAngle() const; - virtual const float getOuterConeVolume() const; + virtual float getPitch() const; + virtual float getVolume() const; + virtual float getMinVolume() const; + virtual float getMaxVolume() const; - virtual const float getDopplerStrength() const; - virtual const cVector3 getDopplerVelocity() const; + virtual float getInnerConeAngle() const; + virtual float getOuterConeAngle() const; + virtual float getOuterConeVolume() const; + + virtual float getDopplerStrength() const; + virtual cVector3 getDopplerVelocity() const; virtual void registerEventHandler(ISourceEventHandler* handler); virtual void unRegisterEventHandler(ISourceEventHandler* handler); virtual void unRegisterAllEventHandlers(); + protected: + //! Mutex for thread synchronization + cAudioMutex Mutex; + + //! Signals a event to all event handlers + void signalEvent(Events sevent); + + //! The context that owns this source + IAudioDeviceContext* Context; + + //! Holds the current volume + float Volume; + + //! OpenAL source + ALuint Source; + + ALenum oldState; + + //! List of registered event handlers + cAudioVector::Type eventHandlerList; + }; + + class cAudioSource : public cAudioSourceBase { + public: +#if CAUDIO_EFX_ENABLED == 1 + cAudioSource(IAudioDecoder* decoder, IAudioDeviceContext* context, cEFXFunctions* oALFunctions); +#else + cAudioSource(IAudioDecoder* decoder, IAudioDeviceContext* context); +#endif + ~cAudioSource(); + + virtual bool play(); + virtual bool play2d(const bool& toLoop = false); + virtual bool play3d(const cVector3& position, const float& soundstr = 1.0 , const bool& toLoop = false); + + virtual void pause(); + virtual void stop(); + virtual void loop(const bool& toLoop); + virtual bool seek(const float& seconds, bool relative = false); + + virtual bool setBuffer(IAudioBuffer* buffer) { return false; } + virtual IAudioBuffer *getBuffer() { return NULL; } + + virtual float getTotalAudioTime(); + virtual int getTotalAudioSize(); + virtual int getCompressedAudioSize(); + + virtual float getCurrentAudioTime(); + virtual int getCurrentAudioPosition(); + virtual int getCurrentCompressedAudioPosition(); + + virtual bool update(); + + virtual bool isValid() const; + virtual bool isLooping() const; + virtual bool drop(); //! Override the default behavior #if CAUDIO_EFX_ENABLED == 1 @@ -126,31 +159,14 @@ namespace cAudio #endif private: - //! Mutex for thread synchronization - cAudioMutex Mutex; //! Empties the current working buffer queue void empty(); - //! Checks for OpenAL errors and reports them - bool checkError() const; //! Streams audio data from the decoder into a buffer bool stream(ALuint buffer); - //! Signals a event to all event handlers - void signalEvent(Events sevent); - //! Converts our audio format enum to OpenAL's - ALenum convertAudioFormatEnum(AudioFormats format); - - //! The context that owns this source - IAudioDeviceContext* Context; - - //! Holds the current volume - float Volume; //! Internal audio buffers ALuint Buffers[CAUDIO_SOURCE_NUM_BUFFERS]; - //! OpenAL source - ALuint Source; - ALenum oldState; //! cAudio decoder being used to stream data IAudioDecoder* Decoder; @@ -159,8 +175,10 @@ namespace cAudio //! Stores whether the source is ready to be used bool Valid; - //! List of registered event handlers - cAudioList::Type eventHandlerList; + //! position of first buffer in seconds + float BufferTime; + //! position of first buffer in bytes + int BufferPosition; #if CAUDIO_EFX_ENABLED == 1 //! Holds pointers to all the EFX related functions diff --git a/cAudio/Headers/cAudioStaticSource.h b/cAudio/Headers/cAudioStaticSource.h new file mode 100755 index 0000000..f985e69 --- /dev/null +++ b/cAudio/Headers/cAudioStaticSource.h @@ -0,0 +1,248 @@ + +#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::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 + }; +} diff --git a/cAudio/Headers/cMutex.h b/cAudio/Headers/cMutex.h index 928704d..0f8ff94 100644 --- a/cAudio/Headers/cMutex.h +++ b/cAudio/Headers/cMutex.h @@ -7,9 +7,7 @@ #include "cAudioDefines.h" #if CAUDIO_MAKE_THREAD_SAFE == 1 - #ifdef CAUDIO_PLATFORM_WIN - #include //Basic windows include - #else + #ifndef CAUDIO_PLATFORM_WIN #include //Assumed linux system #endif #endif @@ -61,4 +59,4 @@ namespace cAudio protected: cAudioMutex* Mutex; }; -}; \ No newline at end of file +}; diff --git a/cAudio/Headers/cOpenALDeviceContext.h b/cAudio/Headers/cOpenALDeviceContext.h index e5237ad..98bd9c8 100644 --- a/cAudio/Headers/cOpenALDeviceContext.h +++ b/cAudio/Headers/cOpenALDeviceContext.h @@ -4,14 +4,13 @@ #pragma once -#include -#include - #include "IAudioDeviceContext.h" #include "cMemoryOverride.h" #include "cMutex.h" #include "cAudioEffects.h" +#include "cOpenALUtil.h" + namespace cAudio { class cOpenALDeviceContext : public IAudioDeviceContext, public cMemoryOverride @@ -26,30 +25,30 @@ namespace cAudio virtual IAudioEffects* getEffects() const; ALCcontext* getOpenALContext() const; - private: - - //! Check for OpenAL errors - bool checkError(); - - //! Mutex for thread synchronization + private: + + //! Check for OpenAL errors + bool checkError(); + + //! Mutex for thread synchronization cAudioMutex Mutex; - //! An OpenAL context pointer - ALCcontext* Context; - - //! An OpenAL device pointer + //! An OpenAL context pointer + ALCcontext* Context; + + //! An OpenAL device pointer ALCdevice* Device; IAudioManager* AudioManager; bool Initialized; - //! Holds whether EFX is supported + //! Holds whether EFX is supported bool EFXSupported; -#if CAUDIO_EFX_ENABLED == 1 - //! Interface for audio effects - cAudioEffects initEffects; +#if CAUDIO_EFX_ENABLED == 1 + //! Interface for audio effects + cAudioEffects initEffects; #endif }; -} \ No newline at end of file +} diff --git a/cAudio/Headers/cOpenALUtil.h b/cAudio/Headers/cOpenALUtil.h new file mode 100755 index 0000000..782ea02 --- /dev/null +++ b/cAudio/Headers/cOpenALUtil.h @@ -0,0 +1,69 @@ + +#ifndef CAUDIO_COPENALUTIL_H +#define CAUDIO_COPENALUTIL_H + +#include "cAudio.h" + +#if !defined(CAUDIO_PLATFORM_LINUX) +#include +#include +#else +#include +#include +#endif + +#if DEBUG +#ifndef __func__ +#define __func__ __FUNCTION__ +#endif +#define checkALError() checkALErrorInternal(__FILE__, __func__, __LINE__) +#else +#define checkALError() (false) +#endif + +namespace cAudio { + + //! Checks for OpenAL errors and reports them + inline bool checkALErrorInternal(const char* file, const char *func, int line) + { + ALenum error = AL_NO_ERROR; + bool anyError = false; + while ((error = alGetError()) != AL_NO_ERROR) + { + const char* errorString = alGetString(error); + if(error == AL_OUT_OF_MEMORY) { + getLogger()->logCritical("Audio Source", "OpenAL Error: %s:%d:%s, %s.", file, line, func, errorString); + } else if (error == -1) { + // this occurs randomly and relatively freqently with Apple's OpenAL and does not seem to cause serious problems. + getLogger()->logWarning("Audio Source", "OpenAL Warning %s:%d:%s, %s.", file, line, func, errorString); + } else { + getLogger()->logError("Audio Source", "OpenAL Error: %s:%d:%s, %s.", file, line, func, errorString); + } + anyError = true; + } + return anyError; + } + + //! Converts our audio format enum to OpenAL's + inline ALenum convertAudioFormatEnum(AudioFormats format) + { + switch(format) + { + case EAF_8BIT_MONO: + return AL_FORMAT_MONO8; + case EAF_16BIT_MONO: + return AL_FORMAT_MONO16; + case EAF_8BIT_STEREO: + return AL_FORMAT_STEREO8; + case EAF_16BIT_STEREO: + return AL_FORMAT_STEREO16; + default: + return AL_FORMAT_MONO8; + }; + } + +} + +#endif + + diff --git a/cAudio/Headers/cPluginManager.h b/cAudio/Headers/cPluginManager.h index 5e60703..35646e2 100644 --- a/cAudio/Headers/cPluginManager.h +++ b/cAudio/Headers/cPluginManager.h @@ -13,8 +13,6 @@ #ifdef CAUDIO_COMPILE_WITH_PLUGIN_SUPPORT #ifdef CAUDIO_PLATFORM_WIN -# define WIN32_LEAN_AND_MEAN -# include struct HINSTANCE__; typedef struct HINSTANCE__* hInstance; diff --git a/cAudio/Headers/cThread.h b/cAudio/Headers/cThread.h index d59c7af..b5df90b 100644 --- a/cAudio/Headers/cThread.h +++ b/cAudio/Headers/cThread.h @@ -8,11 +8,10 @@ #include "cAudioDefines.h" #include "IThread.h" -#ifdef CAUDIO_PLATFORM_WIN -#include //Basic windows includes -#include -#else -#include //Assumed linux system +#ifdef CAUDIO_PLATFORM_WIN +#include +#else +#include //Assumed linux system #endif namespace cAudio @@ -44,4 +43,4 @@ namespace cAudio bool IsInit; bool Loop; }; -}; \ No newline at end of file +}; diff --git a/cAudio/Headers/cUtils.h b/cAudio/Headers/cUtils.h index 282744e..e6d90f7 100644 --- a/cAudio/Headers/cUtils.h +++ b/cAudio/Headers/cUtils.h @@ -9,8 +9,6 @@ #include "cAudioString.h" #ifdef CAUDIO_PLATFORM_WIN -# define WIN32_LEAN_AND_MEAN -# include # include # include #endif @@ -25,14 +23,14 @@ namespace cAudio { //! Grabs the current extention of a given string. -static cAudioString getExt(const cAudioString& filename) +inline cAudioString getExt(const cAudioString& filename) { if(filename.find_last_of(_CTEXT(".")) == cAudioString::npos) return filename; return filename.substr(filename.find_last_of(_CTEXT(".")) + 1, filename.length()-filename.find_last_of(_CTEXT("."))-1); } //! Returns a list of files/directories in the supplied directory. Used internally for auto-installation of plugins. -static cAudioVector::Type getFilesInDirectory(cAudioString path) +inline cAudioVector::Type getFilesInDirectory(cAudioString path) { cAudioVector::Type FileList; #ifdef CAUDIO_PLATFORM_WIN diff --git a/cAudio/include/EAudioFormats.h b/cAudio/include/EAudioFormats.h index 1711d18..c91b197 100644 --- a/cAudio/include/EAudioFormats.h +++ b/cAudio/include/EAudioFormats.h @@ -14,4 +14,4 @@ namespace cAudio EAF_16BIT_MONO, EAF_16BIT_STEREO }; -}; \ No newline at end of file +}; diff --git a/cAudio/include/IAudioCapture.h b/cAudio/include/IAudioCapture.h index aae831a..e46048d 100644 --- a/cAudio/include/IAudioCapture.h +++ b/cAudio/include/IAudioCapture.h @@ -150,4 +150,4 @@ namespace cAudio char* buffer; size_t length; }; -}; \ No newline at end of file +}; diff --git a/cAudio/include/IAudioDeviceContext.h b/cAudio/include/IAudioDeviceContext.h index e8dcb38..dc7af49 100644 --- a/cAudio/include/IAudioDeviceContext.h +++ b/cAudio/include/IAudioDeviceContext.h @@ -17,5 +17,6 @@ namespace cAudio virtual void update() = 0; virtual IAudioManager* getAudioManager() const = 0; virtual IAudioEffects* getEffects() const = 0; + virtual ~IAudioDeviceContext(){} }; } \ No newline at end of file diff --git a/cAudio/include/IAudioDeviceList.h b/cAudio/include/IAudioDeviceList.h index 8e0c35e..b3ae9e6 100644 --- a/cAudio/include/IAudioDeviceList.h +++ b/cAudio/include/IAudioDeviceList.h @@ -24,5 +24,6 @@ namespace cAudio virtual cAudioString getDeviceDescription(unsigned int idx) = 0; virtual cAudioString getDefaultDeviceName() = 0; virtual bool isSupported() = 0; + virtual ~IAudioDeviceList(){} }; } diff --git a/cAudio/include/IAudioEffects.h b/cAudio/include/IAudioEffects.h index ff92621..0fa4714 100644 --- a/cAudio/include/IAudioEffects.h +++ b/cAudio/include/IAudioEffects.h @@ -234,4 +234,4 @@ namespace cAudio }; }; -#endif \ No newline at end of file +#endif diff --git a/cAudio/include/IAudioManager.h b/cAudio/include/IAudioManager.h index 130d52f..7693d83 100644 --- a/cAudio/include/IAudioManager.h +++ b/cAudio/include/IAudioManager.h @@ -15,8 +15,10 @@ namespace cAudio { class IAudioSource; + class IAudioBuffer; class IAudioDecoderFactory; class AudioCaptureBuffer; + class cAudioMutex; //! Interface for the playback capabilities of cAudio. class IAudioManager @@ -89,6 +91,18 @@ namespace cAudio //! Get the master volume. virtual float getMasterVolume() const = 0; + //! Set Speed of Sound (for doppler computations) + virtual void setSpeedOfSound(float speed) = 0; + + //! Get Speed of Sound (for doppler computations) + virtual float getSpeedOfSound() const = 0; + + //! Set Doppler Factor + virtual void setDopplerFactor(float factor) const = 0; + + //! Get Doppler Factor + virtual float getDopplerFactor() const = 0; + //! Stops all playing sounds. virtual void stopAllSounds() = 0; @@ -133,6 +147,20 @@ namespace cAudio */ virtual IAudioSource* createFromAudioBuffer(const char* name, AudioCaptureBuffer* pBiffer, unsigned int frequency, AudioFormats format) = 0; + //! Creates a Audio Sample using the highest priority data source that has the referenced filename + /** + \param filename: Path to the file to load audio data from. + \return A pointer to an Audio Source or NULL if creation failed. + */ + virtual IAudioBuffer* createBuffer(const char* filename) = 0; + + //! Creates an Audio Source from an Audio Buffer object (see createAudioBuffer()) + /** + \param buffer: The buffer to play, or NULL to create an empty static source + \return A pointer to an Audio Source or NULL if creation failed. + */ + virtual IAudioSource* createStatic(IAudioBuffer* buffer) = 0; + //! Register an Audio Decoder. /** \param factory: Pointer to the factory instance to use. @@ -207,6 +235,8 @@ namespace cAudio //! Returns the interface for the listener. virtual IListener* getListener() = 0; + virtual cAudioMutex *getMutex() = 0; + #if CAUDIO_EFX_ENABLED == 1 //! Returns the interface for audio effects. virtual IAudioEffects* getEffects() = 0; diff --git a/cAudio/include/IAudioPlugin.h b/cAudio/include/IAudioPlugin.h index 1c6e14f..76dc0ec 100644 --- a/cAudio/include/IAudioPlugin.h +++ b/cAudio/include/IAudioPlugin.h @@ -52,4 +52,4 @@ namespace cAudio \param capture: Pointer to the soon to be destroyed capture interface. */ virtual void onDestoryAudioCapture(IAudioCapture* capture) { } }; -}; \ No newline at end of file +}; diff --git a/cAudio/include/IAudioSource.h b/cAudio/include/IAudioSource.h index 526cd4a..b4566d7 100644 --- a/cAudio/include/IAudioSource.h +++ b/cAudio/include/IAudioSource.h @@ -14,6 +14,20 @@ namespace cAudio { + //! interface for a sample (audio buffer): completely loaded into memory, shareable across sources + class IAudioBuffer : public IRefCounted + { + public: + virtual ~IAudioBuffer() {} + + virtual bool isValid() const = 0; + virtual unsigned getBuffer() const = 0; + virtual int getChannels() const = 0; + + virtual int getTotalAudioSize() const = 0; + virtual float getTotalAudioTime() const = 0; + }; + //! Interface for a single audio source, which allow you to manipulate sound sources (speakers) in 2D or 3D space. class IAudioSource : public IRefCounted { @@ -39,7 +53,7 @@ namespace cAudio \param toLoop: Whether to loop (restart) the audio when the end is reached. \return True if the source is playing, false if not. */ virtual bool play3d(const cVector3& position, const float& soundstr = 1.0 , const bool& toLoop = false) = 0; - + //! Pauses playback of the sound source. virtual void pause() = 0; @@ -57,6 +71,15 @@ namespace cAudio \return True on success, False if the codec does not support seeking. */ virtual bool seek(const float& seconds, bool relative = false) = 0; + //! Change the audio buffer associated with the source + /** Note: Only supported on sources created with createFromBuffer() or createForBuffer() + \return True on success, False if the sample does not support setting buffers or is currently playing */ + virtual bool setBuffer(IAudioBuffer* buffer) = 0; + + //! Get the audio buffer associated with the source + /** \return buffer on succes, NULL if no buffer or sample is streaming */ + virtual IAudioBuffer *getBuffer() = 0; + //! Returns the total amount of time in the audio stream. See IAudioDecoder for details. virtual float getTotalAudioTime() = 0; @@ -79,19 +102,19 @@ namespace cAudio virtual bool update() = 0; //! Returns if the source is ready to be used. - virtual const bool isValid() const = 0; + virtual bool isValid() const = 0; // //! Returns if the source is playing. - virtual const bool isPlaying() const = 0; + virtual bool isPlaying() const = 0; //! Returns if the source is paused. - virtual const bool isPaused() const = 0; + virtual bool isPaused() const = 0; //! Returns if the source is stopped. - virtual const bool isStopped() const = 0; + virtual bool isStopped() const = 0; //! Returns if the source is looping. - virtual const bool isLooping() const = 0; + virtual bool isLooping() const = 0; //! Sets the position of the source in 3D space. /** @@ -183,52 +206,58 @@ namespace cAudio virtual void move(const cVector3& position) = 0; //! Returns the audio objects position - virtual const cVector3 getPosition() const = 0; + virtual cVector3 getPosition() const = 0; //! Returns the audio objects velocity - virtual const cVector3 getVelocity() const = 0; + virtual cVector3 getVelocity() const = 0; //! Returns the audio objects direction - virtual const cVector3 getDirection() const = 0; + virtual cVector3 getDirection() const = 0; //! Returns the factor used in attenuating the source over distance - virtual const float getRolloffFactor() const = 0; + virtual float getRolloffFactor() const = 0; //! Returns the strength of the source - virtual const float getStrength() const = 0; + virtual float getStrength() const = 0; //! Returns the distance from the source where attenuation will begin - virtual const float getMinDistance() const = 0; + virtual float getMinDistance() const = 0; //! Returns the distance from the source where attenuation will stop - virtual const float getMaxDistance() const = 0; + virtual float getMaxDistance() const = 0; + + //! Return true for 2d sounds, false for 3d sounds + virtual bool isRelative() const = 0; + + //! Return gain, taking into account volume as well as distance attenuation + virtual float calculateGain() const = 0; //! Returns the pitch of the source - virtual const float getPitch() const = 0; + virtual float getPitch() const = 0; //! Returns the source volume before attenuation and other effects - virtual const float getVolume() const = 0; + virtual float getVolume() const = 0; //! Returns the minimum volume that the source can be attenuated to - virtual const float getMinVolume() const = 0; + virtual float getMinVolume() const = 0; //! Returns the maximum volume that the source can achieve - virtual const float getMaxVolume() const = 0; + virtual float getMaxVolume() const = 0; //! Returns the angle of the inner sound cone of the source - virtual const float getInnerConeAngle() const = 0; + virtual float getInnerConeAngle() const = 0; //! Returns the angle of the outer sound cone of the source - virtual const float getOuterConeAngle() const = 0; + virtual float getOuterConeAngle() const = 0; //! Returns how much the volume of the source is scaled in the outer cone - virtual const float getOuterConeVolume() const = 0; + virtual float getOuterConeVolume() const = 0; //! Returns the doppler strength, which enhances or diminishes the doppler effect - virtual const float getDopplerStrength() const = 0; + virtual float getDopplerStrength() const = 0; //! Returns the override for the doppler velocity vector - virtual const cVector3 getDopplerVelocity() const = 0; + virtual cVector3 getDopplerVelocity() const = 0; //! Registers a new event handler to this source /** @@ -272,4 +301,4 @@ namespace cAudio protected: private: }; -}; \ No newline at end of file +}; diff --git a/cAudio/include/ICaptureEventHandler.h b/cAudio/include/ICaptureEventHandler.h index 3faf86b..bb093bc 100644 --- a/cAudio/include/ICaptureEventHandler.h +++ b/cAudio/include/ICaptureEventHandler.h @@ -29,5 +29,6 @@ namespace cAudio //! This function is called whe user requests data from the capture buffer. virtual void onUserRequestBuffer() = 0; + virtual ~ICaptureEventHandler(){} }; }; diff --git a/cAudio/include/ILogReceiver.h b/cAudio/include/ILogReceiver.h index fdba8b7..dcde4ab 100644 --- a/cAudio/include/ILogReceiver.h +++ b/cAudio/include/ILogReceiver.h @@ -33,7 +33,7 @@ namespace cAudio { public: ILogReceiver() { } - ~ILogReceiver() { } + virtual ~ILogReceiver() { } //! Called on every logged message that is greater than or equal to the minimum log level. /** diff --git a/cAudio/include/IManagerEventHandler.h b/cAudio/include/IManagerEventHandler.h index 107864e..ae104c7 100644 --- a/cAudio/include/IManagerEventHandler.h +++ b/cAudio/include/IManagerEventHandler.h @@ -27,6 +27,8 @@ namespace cAudio //! This function is called when a data source is registered. virtual void onDataSourceRegister() = 0; + + virtual ~IManagerEventHandler(){} }; }; diff --git a/cAudio/include/IMemoryProvider.h b/cAudio/include/IMemoryProvider.h index 2929c9c..2718bd7 100644 --- a/cAudio/include/IMemoryProvider.h +++ b/cAudio/include/IMemoryProvider.h @@ -28,5 +28,7 @@ namespace cAudio //! Returns the largest possible single allocation that can be made. virtual size_t getMaxAllocationSize() = 0; + + virtual ~IMemoryProvider() {} }; }; diff --git a/cAudio/include/IPluginManager.h b/cAudio/include/IPluginManager.h index 655c4b6..d9c148f 100644 --- a/cAudio/include/IPluginManager.h +++ b/cAudio/include/IPluginManager.h @@ -15,7 +15,7 @@ namespace cAudio { public: IPluginManager() { } - ~IPluginManager() { } + virtual ~IPluginManager() { } //! Installs a plugin using a statically linked plugin implementation. /** diff --git a/cAudio/include/ISourceEventHandler.h b/cAudio/include/ISourceEventHandler.h index 9866580..dc48d82 100644 --- a/cAudio/include/ISourceEventHandler.h +++ b/cAudio/include/ISourceEventHandler.h @@ -11,19 +11,21 @@ namespace cAudio { public: //! This function is called when a source updates its buffers. - virtual void onUpdate() = 0; + virtual void onUpdate(){} //! This function is called when a source is released and soon to be deleted. - virtual void onRelease() = 0; + virtual void onRelease(){} //! This function is called when a source starts playing. - virtual void onPlay() = 0; + virtual void onPlay(){} //! This function is called when a source stopped playback. - virtual void onStop() = 0; + virtual void onStop(){} //! This function is called when a source is paused. - virtual void onPause() = 0; + virtual void onPause(){} + + virtual ~ISourceEventHandler(){} }; }; diff --git a/cAudio/include/IThread.h b/cAudio/include/IThread.h index dae50b8..47555df 100644 --- a/cAudio/include/IThread.h +++ b/cAudio/include/IThread.h @@ -13,11 +13,13 @@ namespace cAudio virtual void join() = 0; virtual void shutdown() = 0; virtual bool isRunning() = 0; + virtual ~IThread(){} }; class IThreadWorker { public: virtual void run() = 0; + virtual ~IThreadWorker(){} }; -} \ No newline at end of file +} diff --git a/cAudio/include/cAudioMemory.h b/cAudio/include/cAudioMemory.h index 9c5f12a..52143c1 100644 --- a/cAudio/include/cAudioMemory.h +++ b/cAudio/include/cAudioMemory.h @@ -7,7 +7,7 @@ #include "cAudioDefines.h" #include "IMemoryProvider.h" -#ifdef CAUDIO_DEBUG +#if 0 /* defined(CAUDIO_DEBUG) */ #define CAUDIO_NEW new (__FILE__, __LINE__, __FUNCTION__) #define CAUDIO_DELETE delete #define CAUDIO_MALLOC(size) cAudio::getMemoryProvider()->Allocate(size, __FILE__, __LINE__, __FUNCTION__) @@ -25,4 +25,4 @@ namespace cAudio /** Used by cAudio for all allocations of memory \return A pointer to the memory provider */ CAUDIO_API IMemoryProvider* getMemoryProvider(); -}; \ No newline at end of file +}; diff --git a/cAudio/include/cAudioPlatform.h b/cAudio/include/cAudioPlatform.h index 0137fd6..dd5b498 100644 --- a/cAudio/include/cAudioPlatform.h +++ b/cAudio/include/cAudioPlatform.h @@ -47,3 +47,20 @@ # define CAUDIO_COMPILER_MINGW # endif #endif + + +#ifdef CAUDIO_PLATFORM_WIN +#ifndef NOMINMAX +#define NOMINMAX +#endif +#define WIN32_LEAN_AND_MEAN +#define _CRT_SECURE_NO_WARNINGS 1 +#if defined(_DEBUG) && !defined(DEBUG) +#define DEBUG _DEBUG +#endif +#ifndef DEBUG +#define _SECURE_SCL 0 +#define _HAS_ITERATOR_DEBUGGING 0 +#endif +#include //Basic windows includes +#endif diff --git a/cAudio/include/cAudioSleep.h b/cAudio/include/cAudioSleep.h index 9713201..62eb855 100644 --- a/cAudio/include/cAudioSleep.h +++ b/cAudio/include/cAudioSleep.h @@ -11,4 +11,4 @@ namespace cAudio //! Causes the current thread to give up control for a certain duration. /** \param ms: amount of miliseconds to sleep */ CAUDIO_API void cAudioSleep(unsigned int ms); -}; \ No newline at end of file +}; diff --git a/cAudio/include/cAudioString.h b/cAudio/include/cAudioString.h index 40a54cb..f70d2f0 100644 --- a/cAudio/include/cAudioString.h +++ b/cAudio/include/cAudioString.h @@ -13,8 +13,6 @@ #include #ifdef CAUDIO_PLATFORM_WIN -# define WIN32_LEAN_AND_MEAN -# include # include # include #endif @@ -26,12 +24,12 @@ namespace cAudio # define _CTEXT(x) L ## x # define cstrcmp wcscmp # define cAudioChar wchar_t -# define cfopen _wfopen +# define cfopen(N, M) _wfopen((N).c_str(), L ## M) #else # define _CTEXT(x) x # define cstrcmp strcmp # define cAudioChar char -# define cfopen fopen +# define cfopen(N, M) fopen(toUTF8(N), M) #endif #if CAUDIO_REROUTE_STRING_ALLOCATIONS == 1 @@ -46,55 +44,13 @@ namespace cAudio #if defined(CAUDIO_PLATFORM_WIN) - static const TCHAR* toWINSTR(const char* str) - { -#if (defined(UNICODE) || defined(_UNICODE)) - static int id = 0; - static wchar_t buffer[8][1024]; - id = ++id & 0x7; - - int slen = strlen(str); - int buff_size = MultiByteToWideChar(CP_UTF8, 0, str, (int)(slen < 1023 ? slen : 1023), buffer[id], 1023); - buffer[id][buff_size] = 0; - buffer[id][1023] = 0; - return buffer[id]; -#else - return str; -#endif - } - - static const TCHAR* toWINSTR(const wchar_t* str) - { -#if (defined(UNICODE) || defined(_UNICODE)) - return str; -#else - static int id = 0; - static char buffer[8][1024]; - id = ++id & 0x7; - - int slen = wcslen(str); - int buff_size = WideCharToMultiByte(CP_UTF8, 0, str, (int)(slen < 1023 ? slen : 1023), buffer[id], 1023, 0, false); - buffer[id][buff_size] = 0; - buffer[id][1023] = 0; - return buffer[id]; -#endif - } - - static wchar_t* charToWChar(const char* text) - { - size_t size = strlen(text) + 1; - wchar_t* wa = new wchar_t[size]; - mbstowcs(wa, text, size); - return wa; - } - static const char* toUTF8(const cAudioString& str) { static int id = 0; static char buffer[8][1024]; id = ++id & 0x7; - - int buff_size = WideCharToMultiByte(CP_UTF8, 0, charToWChar(str.c_str()), (int)(str.size() < 1023 ? str.size() : 1023), buffer[id], 1023, 0, false); + + int buff_size = WideCharToMultiByte(CP_UTF8, 0, str.c_str(), (int)(str.size() < 1023 ? str.size() : 1023), buffer[id], 1023, 0, false); buffer[id][buff_size] = 0; buffer[id][1023] = 0; return buffer[id]; @@ -102,34 +58,20 @@ namespace cAudio static cAudioString fromUTF8(const char* str) { - wchar_t* buffer = 0; - int buff_size = MultiByteToWideChar(CP_UTF8, 0, str, (int)strlen(str), 0, 0); - if (buff_size == 0) - return cAudioString(); - - buffer = new wchar_t[buff_size + 1]; - - memset((void*)buffer, 0, sizeof(wchar_t) * (buff_size + 1)); - MultiByteToWideChar(CP_UTF8, 0, str, (int)strlen(str), buffer, buff_size); - char* convert = new char[buff_size+1]; - wcstombs(convert, buffer, sizeof(wchar_t) * (buff_size + 1)); - cAudioString s(convert); - delete[] buffer; + int str_len = (int)strlen(str); + int buf_size = MultiByteToWideChar(CP_UTF8, 0, str, str_len, 0, 0); + cAudioString s(buf_size, L'\0'); + MultiByteToWideChar(CP_UTF8, 0, str, str_len, &s[0], buf_size); return s; } #else - static const char* toWINSTR(const char* str) - { - return str; - } - - static const char* toUTF8(const cAudioString& str) + inline const char* toUTF8(const cAudioString& str) { return str.c_str(); } - static cAudioString fromUTF8(const char* str) + inline cAudioString fromUTF8(const char* str) { return cAudioString(str); } diff --git a/cAudio/include/cSTLAllocator.h b/cAudio/include/cSTLAllocator.h index 6454c62..b421384 100644 --- a/cAudio/include/cSTLAllocator.h +++ b/cAudio/include/cSTLAllocator.h @@ -62,7 +62,7 @@ namespace cAudio pointer allocate( size_type count, typename std::allocator::const_pointer ptr = 0 ) { (void)ptr; - register size_type size = count*sizeof( T ); + size_type size = count*sizeof( T ); pointer p = static_cast(CAUDIO_MALLOC(size)); return p; } diff --git a/cAudio/include/cVector3.h b/cAudio/include/cVector3.h index 1c8418d..3a54469 100644 --- a/cAudio/include/cVector3.h +++ b/cAudio/include/cVector3.h @@ -91,7 +91,7 @@ namespace cAudio operator float*() { return &x; } - const float operator[] ( int i ) const { return ( ( float* ) &x ) [i]; } + float operator[] ( int i ) const { return ( ( float* ) &x ) [i]; } float &operator[] ( int i ) { return ( ( float* ) &x ) [i]; } @@ -151,4 +151,4 @@ namespace cAudio output[2] = z; } }; -}; \ No newline at end of file +}; diff --git a/cAudio/src/cAudio.cpp b/cAudio/src/cAudio.cpp index a863c2e..f7d4d62 100644 --- a/cAudio/src/cAudio.cpp +++ b/cAudio/src/cAudio.cpp @@ -91,9 +91,6 @@ namespace cAudio } #endif - manager->unRegisterAllAudioDecoders(); - manager->unRegisterAllDataSources(); - manager->unRegisterAllEventHandlers(); manager->shutDown(); CAUDIO_DELETE manager; @@ -144,9 +141,6 @@ namespace cAudio // Logger section //--------------------------------------------------------------------------------------- - static cLogger Logger; - static bool FirstTimeLogInit(false); - #if CAUDIO_COMPILE_WITH_CONSOLE_LOG_RECEIVER == 1 static cConsoleLogReceiver ConsoleLog; #endif @@ -157,17 +151,19 @@ namespace cAudio CAUDIO_API ILogger* getLogger() { - if(!FirstTimeLogInit) + static cLogger* Logger = NULL; + + if(!Logger) { - FirstTimeLogInit = true; + Logger = new cLogger; #if CAUDIO_COMPILE_WITH_CONSOLE_LOG_RECEIVER == 1 - Logger.registerLogReceiver(&ConsoleLog, "Console"); + Logger->registerLogReceiver(&ConsoleLog, "Console"); #endif #if CAUDIO_COMPILE_WITH_FILE_LOG_RECEIVER == 1 - Logger.registerLogReceiver(&FileLog,"File"); + Logger->registerLogReceiver(&FileLog,"File"); #endif } - return &Logger; + return Logger; } //--------------------------------------------------------------------------------------- diff --git a/cAudio/src/cAudioCapture.cpp b/cAudio/src/cAudioCapture.cpp index 119c6b1..23800f9 100644 --- a/cAudio/src/cAudioCapture.cpp +++ b/cAudio/src/cAudioCapture.cpp @@ -14,15 +14,15 @@ namespace cAudio { - cAudioCapture::cAudioCapture() : Frequency(22050), Format(EAF_16BIT_MONO), InternalBufferSize(8192), - SampleSize(2), Ready(false), Capturing(false), - CaptureDevice(NULL), AudioThread(NULL) + cAudioCapture::cAudioCapture() : AudioThread(NULL), Frequency(22050), Format(EAF_16BIT_MONO), + InternalBufferSize(8192), SampleSize(2), Ready(false), + Capturing(false), CaptureDevice(NULL) { } cAudioCapture::~cAudioCapture() { - shutdown(); + cAudioCapture::shutdown(); } void cAudioCapture::run() @@ -315,7 +315,7 @@ namespace cAudio case ON_INIT: - for(it; it != eventHandlerList.end(); it++){ + for(; it != eventHandlerList.end(); it++){ (*it)->onInit(); } @@ -323,7 +323,7 @@ namespace cAudio case ON_UPDATE: - for(it; it != eventHandlerList.end(); it++){ + for(; it != eventHandlerList.end(); it++){ (*it)->onUpdate(); } @@ -331,7 +331,7 @@ namespace cAudio case ON_RELEASE: - for(it; it != eventHandlerList.end(); it++){ + for(; it != eventHandlerList.end(); it++){ (*it)->onRelease(); } @@ -339,7 +339,7 @@ namespace cAudio case ON_BEGINCAPTURE: - for(it; it != eventHandlerList.end(); it++){ + for(; it != eventHandlerList.end(); it++){ (*it)->onBeginCapture(); } @@ -348,7 +348,7 @@ namespace cAudio case ON_ENDCAPTURE: - for(it; it != eventHandlerList.end(); it++){ + for(; it != eventHandlerList.end(); it++){ (*it)->onEndCapture(); } @@ -356,7 +356,7 @@ namespace cAudio case ON_USERREQUESTEDBUFFER: - for(it; it != eventHandlerList.end(); it++){ + for(; it != eventHandlerList.end(); it++){ (*it)->onUserRequestBuffer(); } diff --git a/cAudio/src/cAudioManager.cpp b/cAudio/src/cAudioManager.cpp index 2ff67c0..68bf596 100644 --- a/cAudio/src/cAudioManager.cpp +++ b/cAudio/src/cAudioManager.cpp @@ -5,6 +5,7 @@ #include "cAudioManager.h" #include "cAudio.h" #include "cAudioSource.h" +#include "cAudioStaticSource.h" #include "cAudioPlatform.h" #include "cAudioSleep.h" #include "cUtils.h" @@ -22,7 +23,7 @@ namespace cAudio { cAudioManager::~cAudioManager() { - shutDown(); + cAudioManager::shutDown(); } bool cAudioManager::initialize(const char* deviceName, int outputFrequency, int eaxEffectSlots) @@ -60,6 +61,10 @@ namespace cAudio } cAudioMutexBasicLock lock(Mutex); + + unRegisterAllAudioDecoders(); + unRegisterAllDataSources(); + unRegisterAllEventHandlers(); releaseAllSources(); @@ -78,20 +83,35 @@ namespace cAudio void cAudioManager::update() { - cAudioMutexBasicLock lock(Mutex); - size_t count = audioSources.size(); - for(size_t i=0; iisValid()) - { - source->update(); - } - } + updateSources.clear(); + { + cAudioMutexBasicLock lock(Mutex); + size_t count = audioSources.size(); + for(size_t i=0; iisValid()) + { + source->grab(); + updateSources.push_back(source); + } + } + } + + // not holding the mutex because this might take a while! + for (int i=0; i != updateSources.size(); i++) + { + IAudioSource *src = updateSources[i]; + src->update(); + src->drop(); + } + + cAudioMutexBasicLock lock(Mutex); + if (!managedAudioSources.empty()) { - count = managedAudioSources.size(); + size_t count = managedAudioSources.size(); for(size_t i=0; iisValid()) + if (!decoder) + return NULL; + + if(decoder->isValid()) { #if CAUDIO_EFX_ENABLED == 1 IAudioSource* audio = CAUDIO_NEW cAudioSource(decoder, AudioContext, ((cAudioEffects*)getEffects())->getEFXInterface()); @@ -248,11 +296,13 @@ namespace cAudio audio->drop(); return NULL; } - getLogger()->logError("AudioManager", "Failed to create Audio Source (%s): Audio data could not be decoded by (.%s) decoder.", toUTF8(audioName), toUTF8(decoder->getType())); + getLogger()->logError("AudioManager", "Failed to create Audio Source (%s): Audio data could not be decoded by (.%s) decoder.", + toUTF8(audioName), toUTF8(decoder->getType())); decoder->drop(); return NULL; } + IAudioSource* cAudioManager::create(const char* name, const char* filename, bool stream) { if(!Initialized) return NULL; @@ -284,8 +334,8 @@ namespace cAudio if(audio != NULL) return audio; - if(source) - source->drop(); + //if(source) + // source->drop(); return NULL; } @@ -358,6 +408,56 @@ namespace cAudio return NULL; } + IAudioBuffer* cAudioManager::createBuffer(const char* filename) + { + if(!Initialized) return NULL; + + cAudioMutexBasicLock lock(Mutex); + cAudioString path = fromUTF8(filename); + cAudioString ext = getExt(path); + IAudioDecoderFactory* factory = getAudioDecoderFactory(toUTF8(ext)); + + if(!factory) { + getLogger()->logError("AudioManager", "Failed to create Audio Buffer: No decoder could be found for (.%s).", toUTF8(ext)); + return NULL; + } + + for(size_t i=0; iCreateDataSource(filename, false); + if(source && source->isValid()) + { + IAudioDecoder* decoder = factory->CreateAudioDecoder(source); + source->drop(); + + IAudioBuffer* buffer = CAUDIO_NEW cAudioBuffer(decoder); + + if(buffer != NULL) + return buffer; + + //if(source) + // source->drop(); + + return NULL; + } + } + } + return NULL; + } + + IAudioSource* cAudioManager::createStatic(IAudioBuffer* buffer) + { + if(!Initialized) return NULL; + + // FIXME save a reference? + IAudioSource *audio = CAUDIO_NEW cAudioStaticSource(buffer, AudioContext); + return audio; + } + bool cAudioManager::registerAudioDecoder(IAudioDecoderFactory* factory, const char* extension) { cAudioMutexBasicLock lock(Mutex); @@ -504,7 +604,7 @@ namespace cAudio { case ON_INIT: - for(it; it != eventHandlerList.end(); it++) + for(; it != eventHandlerList.end(); it++) { (*it)->onInit(); } @@ -513,7 +613,7 @@ namespace cAudio case ON_UPDATE: - for(it; it != eventHandlerList.end(); it++) + for(; it != eventHandlerList.end(); it++) { (*it)->onUpdate(); } @@ -522,7 +622,7 @@ namespace cAudio case ON_RELEASE: - for(it; it != eventHandlerList.end(); it++) + for(; it != eventHandlerList.end(); it++) { (*it)->onRelease(); } @@ -531,7 +631,7 @@ namespace cAudio case ON_SOURCECREATE: - for(it; it != eventHandlerList.end(); it++) + for(; it != eventHandlerList.end(); it++) { (*it)->onSourceCreate(); } @@ -540,7 +640,7 @@ namespace cAudio case ON_DECODERREGISTER: - for(it; it != eventHandlerList.end(); it++) + for(; it != eventHandlerList.end(); it++) { (*it)->onDecoderRegister(); } @@ -549,7 +649,7 @@ namespace cAudio case ON_DATASOURCEREGISTER: - for(it; it != eventHandlerList.end(); it++) + for(; it != eventHandlerList.end(); it++) { (*it)->onDataSourceRegister(); } diff --git a/cAudio/src/cAudioSleep.cpp b/cAudio/src/cAudioSleep.cpp index 2072617..8b7133e 100644 --- a/cAudio/src/cAudioSleep.cpp +++ b/cAudio/src/cAudioSleep.cpp @@ -1,12 +1,10 @@ -// Copyright (c) 2008-2011 Raynaldo (Wildicv) Rivera, Joshua (Dark_Kilauea) Jones, Murat (wolfmanfx) Sari -// This file is part of the "cAudio Engine" +// Copyright (c) 2008-2011 Raynaldo (Wildicv) Rivera, Joshua (Dark_Kilauea) Jones, Murat (wolfmanfx) Sari +// This file is part of the "cAudio Engine" // For conditions of distribution and use, see copyright notice in cAudio.h #include "cAudioPlatform.h" -#ifdef CAUDIO_PLATFORM_WIN -#include //Basic windows include for Sleep(); -#else +#ifndef CAUDIO_PLATFORM_WIN #include //Assumed linux system, include for usleep() #include #endif //If you need to support another platform, simply add a define for it diff --git a/cAudio/src/cAudioSource.cpp b/cAudio/src/cAudioSource.cpp index 25bdefc..e1eaa3d 100644 --- a/cAudio/src/cAudioSource.cpp +++ b/cAudio/src/cAudioSource.cpp @@ -9,26 +9,56 @@ #include "cEffect.h" #include "cAudioSleep.h" #include +#include #if CAUDIO_EFX_ENABLED == 1 #include "cOpenALDeviceContext.h" #endif +namespace +{ + // return buffer length in seconds + ALfloat GetBufferLength(ALuint buffer) + { + ALint size, bits, channels, freq; + + alGetBufferi(buffer, AL_SIZE, &size); + alGetBufferi(buffer, AL_BITS, &bits); + alGetBufferi(buffer, AL_CHANNELS, &channels); + alGetBufferi(buffer, AL_FREQUENCY, &freq); + if(alGetError() != AL_NO_ERROR || !bits || !channels || !freq) + return -1.0f; + + return (ALfloat)((ALuint)size/channels/(bits/8)) / (ALfloat)freq; + } + + ALint GetBufferSize(ALuint buffer) + { + ALint size; + alGetBufferi(buffer, AL_SIZE, &size); + return size; + } +} + namespace cAudio { + #if CAUDIO_EFX_ENABLED == 1 cAudioSource::cAudioSource(IAudioDecoder* decoder, IAudioDeviceContext* context, cEFXFunctions* oALFunctions) - : Context(context), Source(0), Volume(1.0), Decoder(decoder), Loop(false), Valid(false), + : cAudioSourceBase(context), Decoder(decoder), Loop(false), Valid(false), EFX(oALFunctions), Filter(NULL), EffectSlotsAvailable(0), LastFilterTimeStamp(0) #else cAudioSource::cAudioSource(IAudioDecoder* decoder, IAudioDeviceContext* context) - : Context(context), Source(0), Volume(1.0), Decoder(decoder), Loop(false), Valid(false) + : cAudioSourceBase(context), Decoder(decoder), Loop(false), Valid(false) #endif { cAudioMutexBasicLock lock(Mutex); - for(int i=0; igrab(); - //Generates 3 buffers for the ogg file - alGenBuffers(CAUDIO_SOURCE_NUM_BUFFERS, Buffers); - bool state = !checkError(); - if(state) - { - //Creates one source to be stored. - alGenSources(1, &Source); - state = !checkError(); - setVolume(Volume); - } + ALboolean state = alIsSource(Source); + + if (state) + { + //Generates 3 buffers for the ogg file + alGenBuffers(CAUDIO_SOURCE_NUM_BUFFERS, Buffers); + state = !checkALError(); + } #if CAUDIO_EFX_ENABLED == 1 Valid = state && (Decoder != NULL) && (Context != NULL) && (EFX != NULL); @@ -84,19 +112,36 @@ namespace cAudio //Stops the audio Source alSourceStop(Source); + checkALError(); empty(); - //Deletes the source - alDeleteSources(1, &Source); + alSourcei(Source, AL_BUFFER, 0); //deletes the last filled buffer alDeleteBuffers(CAUDIO_SOURCE_NUM_BUFFERS, Buffers); - checkError(); + checkALError(); + + if(Decoder) { + Decoder->drop(); + Decoder = NULL; + } + } + + cAudioSourceBase::cAudioSourceBase(IAudioDeviceContext* context) : + Context(context), Volume(1.f), Source(0) + { + alGenSources(1, &Source); + checkALError(); + setVolume(Volume); + } + + cAudioSourceBase::~cAudioSourceBase() + { + alSourceStop(Source); + checkALError(); + alDeleteSources(1, &Source); + checkALError(); + getLogger()->logDebug("Audio Source", "Audio source released."); signalEvent(ON_RELEASE); - - if(Decoder) - Decoder->drop(); - - unRegisterAllEventHandlers(); } @@ -119,7 +164,9 @@ namespace cAudio int queueSize = 0; //Purges all buffers from the source alSourcei(Source, AL_BUFFER, 0); - checkError(); + BufferPosition = Decoder->getCurrentPosition(); + BufferTime = Decoder->getCurrentTime(); + checkALError(); for(int u = 0; u < CAUDIO_SOURCE_NUM_BUFFERS; u++) { int val = stream(Buffers[u]); @@ -133,7 +180,7 @@ namespace cAudio } //Stores the sources 3 buffers to be used in the queue alSourceQueueBuffers(Source, queueSize, Buffers); - checkError(); + checkALError(); } #if CAUDIO_EFX_ENABLED == 1 updateFilter(); @@ -141,7 +188,7 @@ namespace cAudio updateEffect(i); #endif alSourcePlay(Source); - checkError(); + checkALError(); getLogger()->logDebug("Audio Source", "Source playing."); signalEvent(ON_PLAY); oldState = AL_PLAYING; @@ -154,7 +201,7 @@ namespace cAudio alSourcei(Source, AL_SOURCE_RELATIVE, true); loop(toLoop); bool state = play(); - checkError(); + checkALError(); return state; } @@ -166,7 +213,7 @@ namespace cAudio setStrength(soundstr); loop(toLoop); bool state = play(); - checkError(); + checkALError(); return state; } @@ -174,7 +221,7 @@ namespace cAudio { cAudioMutexBasicLock lock(Mutex); alSourcePause(Source); - checkError(); + checkALError(); getLogger()->logDebug("Audio Source", "Source paused."); signalEvent(ON_PAUSE); oldState = AL_PAUSED; @@ -196,7 +243,7 @@ namespace cAudio //Resets the audio to the beginning Decoder->setPosition(0, false); - checkError(); + checkALError(); getLogger()->logDebug("Audio Source", "Source stopped."); signalEvent(ON_STOP); oldState = AL_STOPPED; @@ -215,6 +262,16 @@ namespace cAudio if(Decoder->isSeekingSupported()) { state = Decoder->seek(seconds, relative); + + BufferPosition = Decoder->getCurrentPosition(); + BufferTime = Decoder->getCurrentTime(); + + int queued = 0; + alGetSourcei(Source, AL_BUFFERS_QUEUED, &queued); + if (queued) { + BufferPosition -= queued * GetBufferSize(Buffers[0]); + BufferTime -= queued * GetBufferLength(Buffers[0]); + } } return state; } @@ -236,12 +293,16 @@ namespace cAudio float cAudioSource::getCurrentAudioTime() { - return Decoder->getCurrentTime(); + float time = -1; + alGetSourcef(Source, AL_SEC_OFFSET, &time); + return BufferTime + time; } int cAudioSource::getCurrentAudioPosition() { - return Decoder->getCurrentPosition(); + int offset = -1; + alGetSourcei(Source, AL_BYTE_OFFSET, &offset); + return BufferPosition + offset; } int cAudioSource::getCurrentCompressedAudioPosition() @@ -265,15 +326,17 @@ namespace cAudio //gets the sound source processed buffers alGetSourcei(Source, AL_BUFFERS_PROCESSED, &processed); - checkError(); + checkALError(); //while there is more data refill buffers with audio data. while (processed--) { ALuint buffer; alSourceUnqueueBuffers(Source, 1, &buffer); + BufferPosition += GetBufferSize(buffer); + BufferTime += GetBufferLength(buffer); - if (checkError()) + if (checkALError()) { processed++; cAudioSleep(1); @@ -288,7 +351,7 @@ namespace cAudio alSourceQueueBuffers(Source, 1, &buffer); } - if (checkError()) + if (checkALError()) { processed++; cAudioSleep(1); @@ -301,7 +364,7 @@ namespace cAudio ALenum state; alGetSourcei(Source, AL_SOURCE_STATE, &state); - checkError(); + checkALError(); if(state == AL_STOPPED && oldState != state) { //Resets the audio to the beginning @@ -314,69 +377,69 @@ namespace cAudio return active; } - const bool cAudioSource::isValid() const + bool cAudioSource::isValid() const { return Valid; } - const bool cAudioSource::isPlaying() const + bool cAudioSourceBase::isPlaying() const { ALenum state = 0; alGetSourcei(Source, AL_SOURCE_STATE, &state); - checkError(); + checkALError(); return (state == AL_PLAYING); } - const bool cAudioSource::isPaused() const + bool cAudioSourceBase::isPaused() const { ALenum state = 0; alGetSourcei(Source, AL_SOURCE_STATE, &state); - checkError(); + checkALError(); return (state == AL_PAUSED); } - const bool cAudioSource::isStopped() const + bool cAudioSourceBase::isStopped() const { ALenum state = 0; alGetSourcei(Source, AL_SOURCE_STATE, &state); - checkError(); + checkALError(); return (state == AL_STOPPED); } - const bool cAudioSource::isLooping() const + bool cAudioSource::isLooping() const { return Loop; } - void cAudioSource::setPosition(const cVector3& position) + void cAudioSourceBase::setPosition(const cVector3& position) { cAudioMutexBasicLock lock(Mutex); alSource3f(Source, AL_POSITION, position.x, position.y, position.z); - checkError(); + checkALError(); } - void cAudioSource::setVelocity(const cVector3& velocity) + void cAudioSourceBase::setVelocity(const cVector3& velocity) { cAudioMutexBasicLock lock(Mutex); alSource3f(Source, AL_VELOCITY, velocity.x, velocity.y, velocity.z); - checkError(); + checkALError(); } - void cAudioSource::setDirection(const cVector3& direction) + void cAudioSourceBase::setDirection(const cVector3& direction) { cAudioMutexBasicLock lock(Mutex); alSource3f(Source, AL_DIRECTION, direction.x, direction.y, direction.z); - checkError(); + checkALError(); } - void cAudioSource::setRolloffFactor(const float& rolloff) + void cAudioSourceBase::setRolloffFactor(const float& rolloff) { cAudioMutexBasicLock lock(Mutex); alSourcef(Source, AL_ROLLOFF_FACTOR, rolloff); - checkError(); + checkALError(); } - void cAudioSource::setStrength(const float& soundstrength) + void cAudioSourceBase::setStrength(const float& soundstrength) { float inverseStrength = 0.0f; if(soundstrength > 0.0f) @@ -384,88 +447,88 @@ namespace cAudio cAudioMutexBasicLock lock(Mutex); alSourcef(Source, AL_ROLLOFF_FACTOR, inverseStrength); - checkError(); + checkALError(); } - void cAudioSource::setMinDistance(const float& minDistance) + void cAudioSourceBase::setMinDistance(const float& minDistance) { cAudioMutexBasicLock lock(Mutex); alSourcef(Source, AL_REFERENCE_DISTANCE, minDistance); - checkError(); + checkALError(); } - void cAudioSource::setMaxAttenuationDistance(const float& maxDistance) + void cAudioSourceBase::setMaxAttenuationDistance(const float& maxDistance) { cAudioMutexBasicLock lock(Mutex); alSourcef(Source, AL_MAX_DISTANCE, maxDistance); - checkError(); + checkALError(); } - void cAudioSource::setPitch(const float& pitch) + void cAudioSourceBase::setPitch(const float& pitch) { cAudioMutexBasicLock lock(Mutex); alSourcef (Source, AL_PITCH, pitch); - checkError(); + checkALError(); } - void cAudioSource::setVolume(const float& volume) + void cAudioSourceBase::setVolume(const float& volume) { cAudioMutexBasicLock lock(Mutex); Volume = volume; alSourcef(Source, AL_GAIN, Volume * Context->getAudioManager()->getMasterVolume()); - checkError(); + checkALError(); } - void cAudioSource::setMinVolume(const float& minVolume) + void cAudioSourceBase::setMinVolume(const float& minVolume) { cAudioMutexBasicLock lock(Mutex); alSourcef(Source, AL_MIN_GAIN, minVolume); - checkError(); + checkALError(); } - void cAudioSource::setMaxVolume(const float& maxVolume) + void cAudioSourceBase::setMaxVolume(const float& maxVolume) { cAudioMutexBasicLock lock(Mutex); alSourcef(Source, AL_MAX_GAIN, maxVolume); - checkError(); + checkALError(); } - void cAudioSource::setInnerConeAngle(const float& innerAngle) + void cAudioSourceBase::setInnerConeAngle(const float& innerAngle) { cAudioMutexBasicLock lock(Mutex); alSourcef(Source, AL_CONE_INNER_ANGLE, innerAngle); - checkError(); + checkALError(); } - void cAudioSource::setOuterConeAngle(const float& outerAngle) + void cAudioSourceBase::setOuterConeAngle(const float& outerAngle) { cAudioMutexBasicLock lock(Mutex); alSourcef(Source, AL_CONE_OUTER_ANGLE, outerAngle); - checkError(); + checkALError(); } - void cAudioSource::setOuterConeVolume(const float& outerVolume) + void cAudioSourceBase::setOuterConeVolume(const float& outerVolume) { cAudioMutexBasicLock lock(Mutex); alSourcef(Source, AL_CONE_OUTER_GAIN, outerVolume); - checkError(); + checkALError(); } - void cAudioSource::setDopplerStrength(const float& dstrength) + void cAudioSourceBase::setDopplerStrength(const float& dstrength) { cAudioMutexBasicLock lock(Mutex); alSourcef(Source, AL_DOPPLER_FACTOR, dstrength); - checkError(); + checkALError(); } - void cAudioSource::setDopplerVelocity(const cVector3& dvelocity) + void cAudioSourceBase::setDopplerVelocity(const cVector3& dvelocity) { cAudioMutexBasicLock lock(Mutex); alSource3f(Source, AL_DOPPLER_VELOCITY, dvelocity.x, dvelocity.y, dvelocity.z); - checkError(); + checkALError(); } - void cAudioSource::move(const cVector3& position) + void cAudioSourceBase::move(const cVector3& position) { cAudioMutexBasicLock lock(Mutex); cVector3 oldPos = getPosition(); @@ -473,45 +536,45 @@ namespace cAudio alSource3f(Source, AL_VELOCITY, velocity.x, velocity.y, velocity.z); alSource3f(Source, AL_POSITION, position.x, position.y, position.z); - checkError(); + checkALError(); } - const cVector3 cAudioSource::getPosition() const + cVector3 cAudioSourceBase::getPosition() const { cVector3 position; alGetSourcefv(Source, AL_POSITION, &position.x); - checkError(); + checkALError(); return position; } - const cVector3 cAudioSource::getVelocity() const + cVector3 cAudioSourceBase::getVelocity() const { cVector3 velocity; alGetSourcefv(Source, AL_VELOCITY, &velocity.x); return velocity; } - const cVector3 cAudioSource::getDirection() const + cVector3 cAudioSourceBase::getDirection() const { cVector3 direction; alGetSourcefv(Source, AL_DIRECTION, &direction.x); - checkError(); + checkALError(); return direction; } - const float cAudioSource::getRolloffFactor() const + float cAudioSourceBase::getRolloffFactor() const { float value = 0.0f; alGetSourcef(Source, AL_ROLLOFF_FACTOR, &value); - checkError(); + checkALError(); return value; } - const float cAudioSource::getStrength() const + float cAudioSourceBase::getStrength() const { float value = 0.0f; alGetSourcef(Source, AL_ROLLOFF_FACTOR, &value); - checkError(); + checkALError(); float inverseStrength = 0.0f; if(value > 0.0f) @@ -520,88 +583,116 @@ namespace cAudio return inverseStrength; } - const float cAudioSource::getMinDistance() const + float cAudioSourceBase::getMinDistance() const { float value = 0.0f; alGetSourcef(Source, AL_REFERENCE_DISTANCE, &value); - checkError(); + checkALError(); return value; } - const float cAudioSource::getMaxDistance() const + float cAudioSourceBase::getMaxDistance() const { float value = 0.0f; alGetSourcef(Source, AL_MAX_DISTANCE, &value); - checkError(); + checkALError(); return value; } - const float cAudioSource::getPitch() const + bool cAudioSourceBase::isRelative() const + { + int relative = 0; + alGetSourcei(Source, AL_SOURCE_RELATIVE, &relative); + return relative; + } + + float cAudioSourceBase::calculateGain() const + { + // OpenAL Inverse Distance Clamped Model + // distance = max(distance,AL_REFERENCE_DISTANCE); + // distance = min(distance,AL_MAX_DISTANCE); + // gain = AL_REFERENCE_DISTANCE / (AL_REFERENCE_DISTANCE + + // AL_ROLLOFF_FACTOR * + // (distance – AL_REFERENCE_DISTANCE)); + + cVector3 lpos = Context->getAudioManager()->getListener()->getPosition(); + cVector3 pos = getPosition(); + + float refDist = getMinDistance(); + float dist = 0.f; + dist = isRelative() ? pos.length() : (pos - lpos).length(); + dist = std::max(dist, refDist); + dist = std::min(dist, getMaxDistance()); + float gain = refDist / (refDist + getRolloffFactor() * (dist - refDist)); + return gain * getVolume(); + } + + float cAudioSourceBase::getPitch() const { float value = 0.0f; alGetSourcef(Source, AL_PITCH, &value); - checkError(); + checkALError(); return value; } - const float cAudioSource::getVolume() const + float cAudioSourceBase::getVolume() const { return Volume; } - const float cAudioSource::getMinVolume() const + float cAudioSourceBase::getMinVolume() const { float value = 0.0f; alGetSourcef(Source, AL_MIN_GAIN, &value); - checkError(); + checkALError(); return value; } - const float cAudioSource::getMaxVolume() const + float cAudioSourceBase::getMaxVolume() const { float value = 0.0f; alGetSourcef(Source, AL_MAX_GAIN, &value); - checkError(); + checkALError(); return value; } - const float cAudioSource::getInnerConeAngle() const + float cAudioSourceBase::getInnerConeAngle() const { float value = 0.0f; alGetSourcef(Source, AL_CONE_INNER_ANGLE, &value); - checkError(); + checkALError(); return value; } - const float cAudioSource::getOuterConeAngle() const + float cAudioSourceBase::getOuterConeAngle() const { float value = 0.0f; alGetSourcef(Source, AL_CONE_OUTER_ANGLE, &value); - checkError(); + checkALError(); return value; } - const float cAudioSource::getOuterConeVolume() const + float cAudioSourceBase::getOuterConeVolume() const { float value = 0.0f; alGetSourcef(Source, AL_CONE_OUTER_GAIN, &value); - checkError(); + checkALError(); return value; } - const float cAudioSource::getDopplerStrength() const + float cAudioSourceBase::getDopplerStrength() const { float value = 0.0f; alGetSourcef(Source, AL_DOPPLER_FACTOR, &value); - checkError(); + checkALError(); return value; } - const cVector3 cAudioSource::getDopplerVelocity() const + cVector3 cAudioSourceBase::getDopplerVelocity() const { cVector3 velocity; alGetSourcefv(Source, AL_DOPPLER_VELOCITY, &velocity.x); - checkError(); + checkALError(); return velocity; } @@ -668,100 +759,70 @@ namespace cAudio { int queued = 0; alGetSourcei(Source, AL_BUFFERS_QUEUED, &queued); - checkError(); + checkALError(); while (queued--) { ALuint buffer; alSourceUnqueueBuffers(Source, 1, &buffer); - checkError(); + checkALError(); } } - bool cAudioSource::checkError() const - { - int error = alGetError(); - if (error != AL_NO_ERROR) - { - const char* 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); - return true; - } - return false; - } - bool cAudioSource::stream(ALuint buffer) { - if(Decoder) + if(!Decoder) + return false; + + //stores the calculated data into buffer that is passed to output. + size_t totalread = 0; + unsigned int errorcount = 0; + char tempbuffer[CAUDIO_SOURCE_BUFFER_SIZE]; + while( totalread < CAUDIO_SOURCE_BUFFER_SIZE ) { - //stores the calculated data into buffer that is passed to output. - size_t totalread = 0; - unsigned int errorcount = 0; - char tempbuffer[CAUDIO_SOURCE_BUFFER_SIZE]; - while( totalread < CAUDIO_SOURCE_BUFFER_SIZE ) - { - char tempbuffer2[CAUDIO_SOURCE_BUFFER_SIZE]; - int actualread = Decoder->readAudioData(tempbuffer2, CAUDIO_SOURCE_BUFFER_SIZE-totalread); - if(actualread > 0) - { - memcpy(tempbuffer+totalread,tempbuffer2,actualread); - totalread += actualread; - } - if(actualread < 0) - { - ++errorcount; - getLogger()->logDebug("Audio Source", "Decoder returned an error: %i (%i of 3)", actualread, errorcount); - if(errorcount >= 3) - { - stop(); - break; - } - } - if(actualread == 0) - { - if(isLooping()) - { - //If we are to loop, set to the beginning and reload from the start - Decoder->setPosition(0, false); - getLogger()->logDebug("Audio Source", "Buffer looping."); - } - else - break; - } - } - - //Second check, in case looping is not enabled, we will return false for end of stream - if(totalread == 0) - { - return false; - } - getLogger()->logDebug("Audio Source", "Buffered %i bytes of data into buffer %i at %i hz.", totalread, buffer, Decoder->getFrequency()); - alBufferData(buffer, convertAudioFormatEnum(Decoder->getFormat()), tempbuffer, totalread, Decoder->getFrequency()); - checkError(); - return true; + char tempbuffer2[CAUDIO_SOURCE_BUFFER_SIZE]; + Mutex.unlock(); // this can take a long time + int actualread = Decoder->readAudioData(tempbuffer2, CAUDIO_SOURCE_BUFFER_SIZE-totalread); + Mutex.lock(); + + if(actualread > 0) + { + memcpy(tempbuffer+totalread,tempbuffer2,actualread); + totalread += actualread; + } + if(actualread < 0) + { + ++errorcount; + getLogger()->logDebug("Audio Source", "Decoder returned an error: %i (%i of 3)", actualread, errorcount); + if(errorcount >= 3) + { + stop(); + break; + } + } + if(actualread == 0) + { + if(isLooping()) + { + //If we are to loop, set to the beginning and reload from the start + Decoder->setPosition(0, false); + getLogger()->logDebug("Audio Source", "Buffer looping."); + } + else + break; + } } - return false; - } - ALenum cAudioSource::convertAudioFormatEnum(AudioFormats format) - { - switch(format) - { - case EAF_8BIT_MONO: - return AL_FORMAT_MONO8; - case EAF_16BIT_MONO: - return AL_FORMAT_MONO16; - case EAF_8BIT_STEREO: - return AL_FORMAT_STEREO8; - case EAF_16BIT_STEREO: - return AL_FORMAT_STEREO16; - default: - return AL_FORMAT_MONO8; - }; - } + //Second check, in case looping is not enabled, we will return false for end of stream + if(totalread == 0) + { + return false; + } + getLogger()->logDebug("Audio Source", "Buffered %i bytes of data into buffer %i at %i hz.", totalread, buffer, Decoder->getFrequency()); + alBufferData(buffer, convertAudioFormatEnum(Decoder->getFormat()), tempbuffer, totalread, Decoder->getFrequency()); + checkALError(); + return true; + } #if CAUDIO_EFX_ENABLED == 1 void cAudioSource::updateFilter(bool remove) @@ -777,7 +838,7 @@ namespace cAudio if(theFilter) { alSourcei(Source, AL_DIRECT_FILTER, theFilter->getOpenALFilter()); - checkError(); + checkALError(); return; } } @@ -785,7 +846,7 @@ namespace cAudio } } alSourcei(Source, AL_DIRECT_FILTER, AL_FILTER_NULL); - checkError(); + checkALError(); } void cAudioSource::updateEffect(unsigned int slot, bool remove) @@ -809,7 +870,7 @@ namespace cAudio filterID = theFilter->getOpenALFilter(); } alSource3i(Source, AL_AUXILIARY_SEND_FILTER, theEffect->getOpenALEffectSlot(), slot, filterID); - checkError(); + checkALError(); return; } } @@ -817,12 +878,12 @@ namespace cAudio } } alSource3i(Source, AL_AUXILIARY_SEND_FILTER, AL_EFFECTSLOT_NULL, slot, AL_FILTER_NULL); - checkError(); + checkALError(); } } #endif - void cAudioSource::registerEventHandler(ISourceEventHandler* handler) + void cAudioSourceBase::registerEventHandler(ISourceEventHandler* handler) { if(handler) { @@ -831,71 +892,51 @@ namespace cAudio } } - void cAudioSource::unRegisterEventHandler(ISourceEventHandler* handler) + void cAudioSourceBase::unRegisterEventHandler(ISourceEventHandler* handler) { if(handler) { cAudioMutexBasicLock lock(Mutex); - eventHandlerList.remove(handler); + for(int i=0; i::Type::iterator it = eventHandlerList.begin(); + if(eventHandlerList.empty()) + return; - if(it != eventHandlerList.end()){ + size_t size = eventHandlerList.size(); - switch(sevent){ + for(int i=0; ionUpdate(); - } - - break; - - case ON_RELEASE: - - for( ; it != eventHandlerList.end(); it++){ - (*it)->onRelease(); - } - - break; - - case ON_PLAY: - - for( ; it != eventHandlerList.end(); it++){ - (*it)->onPlay(); - } - - - break; - - case ON_PAUSE: - - for( ; it != eventHandlerList.end(); it++){ - (*it)->onPause(); - } - - break; - - case ON_STOP: - - for( ; it != eventHandlerList.end(); it++){ - (*it)->onStop(); - } - - break; - } - } - } + switch(sevent) + { + case ON_UPDATE: handler->onUpdate(); break; + case ON_RELEASE: handler->onRelease(); break; + case ON_PLAY: handler->onPlay(); break; + case ON_PAUSE: handler->onPause(); break; + case ON_STOP: handler->onStop(); break; + } + + // handler may have unregistered itself + if(size == eventHandlerList.size()) { + i++; + } else { + size = eventHandlerList.size(); + } + } + } } diff --git a/cAudio/src/cConsoleLogReceiver.cpp b/cAudio/src/cConsoleLogReceiver.cpp index f4491b6..1209255 100644 --- a/cAudio/src/cConsoleLogReceiver.cpp +++ b/cAudio/src/cConsoleLogReceiver.cpp @@ -11,8 +11,8 @@ namespace cAudio { bool cConsoleLogReceiver::OnLogMessage(const char* sender, const char* message, LogLevel level, float time) { - //std::cout << time << " " << sender << ": [" << LogLevelStrings[level] << "] " << message << std::endl; - std::cout << "[" << LogLevelStrings[level] << "] " << message << std::endl; + std::cout << sender << ": " << message << std::endl; + //std::cout << "[" << LogLevelStrings[level] << "] " << message << std::endl; return true; } }; diff --git a/cAudio/src/cFileSource.cpp b/cAudio/src/cFileSource.cpp index dc2b19f..f63372f 100644 --- a/cAudio/src/cFileSource.cpp +++ b/cAudio/src/cFileSource.cpp @@ -17,7 +17,7 @@ cFileSource::cFileSource(const char* filename) : pFile(NULL), Valid(false), File cAudioString safeFilename = fromUTF8(filename); if(safeFilename.length() != 0) { - pFile = fopen(toUTF8(safeFilename),"rb"); + pFile = cfopen(safeFilename, "rb"); if(pFile) Valid = true; } diff --git a/cAudio/src/cListener.cpp b/cAudio/src/cListener.cpp index 4d1f0a6..3ebabd5 100644 --- a/cAudio/src/cListener.cpp +++ b/cAudio/src/cListener.cpp @@ -1,10 +1,10 @@ -// Copyright (c) 2008-2011 Raynaldo (Wildicv) Rivera, Joshua (Dark_Kilauea) Jones, Murat (wolfmanfx) Sari -// This file is part of the "cAudio Engine" +// Copyright (c) 2008-2011 Raynaldo (Wildicv) Rivera, Joshua (Dark_Kilauea) Jones, Murat (wolfmanfx) Sari +// This file is part of the "cAudio Engine" // For conditions of distribution and use, see copyright notice in cAudio.h #include "cListener.h" #include "cEFXFunctions.h" -#include +#include "cOpenALUtil.h" namespace cAudio { @@ -13,6 +13,7 @@ namespace cAudio cAudioMutexBasicLock lock(Mutex); Position = pos; alListener3f(AL_POSITION, Position.x, Position.y, Position.z); + checkALError(); } void cListener::setDirection(const cVector3& dir) { @@ -20,6 +21,7 @@ namespace cAudio Direction = dir; float orient[6] = {Direction[0], Direction[1], Direction[2], UpVector[0], UpVector[1], UpVector[2]}; alListenerfv(AL_ORIENTATION, orient); + checkALError(); } void cListener::setUpVector(const cVector3& up) { @@ -27,18 +29,21 @@ namespace cAudio UpVector = up; float orient[6] = {Direction[0], Direction[1], Direction[2], UpVector[0], UpVector[1], UpVector[2]}; alListenerfv(AL_ORIENTATION, orient); + checkALError(); } void cListener::setVelocity(const cVector3& vel) { cAudioMutexBasicLock lock(Mutex); Velocity = vel; alListener3f(AL_VELOCITY, Velocity.x, Velocity.y, Velocity.z); + checkALError(); } void cListener::setMasterVolume(const float& volume) { cAudioMutexBasicLock lock(Mutex); MasterGain = volume; alListenerf(AL_GAIN, MasterGain); + checkALError(); } void cListener::move(const cVector3& pos) { @@ -48,12 +53,14 @@ namespace cAudio alListener3f(AL_POSITION, Position.x, Position.y, Position.z); alListener3f(AL_VELOCITY, Velocity.x, Velocity.y, Velocity.z); + checkALError(); } #if CAUDIO_EFX_ENABLED == 1 void cListener::setMetersPerUnit(const float& meters) { cAudioMutexBasicLock lock(Mutex); alListenerf(AL_METERS_PER_UNIT, meters); + checkALError(); } float cListener::getMetersPerUnit(void) const @@ -63,4 +70,4 @@ namespace cAudio return value; } #endif -}; \ No newline at end of file +}; diff --git a/cAudio/src/cMutex.cpp b/cAudio/src/cMutex.cpp index b3f138a..161abef 100644 --- a/cAudio/src/cMutex.cpp +++ b/cAudio/src/cMutex.cpp @@ -1,5 +1,5 @@ -// Copyright (c) 2008-2011 Raynaldo (Wildicv) Rivera, Joshua (Dark_Kilauea) Jones, Murat (wolfmanfx) Sari -// This file is part of the "cAudio Engine" +// Copyright (c) 2008-2011 Raynaldo (Wildicv) Rivera, Joshua (Dark_Kilauea) Jones, Murat (wolfmanfx) Sari +// This file is part of the "cAudio Engine" // For conditions of distribution and use, see copyright notice in cAudio.h #include "cMutex.h" @@ -30,7 +30,7 @@ namespace cAudio #ifdef CAUDIO_PLATFORM_WIN EnterCriticalSection(&criticalSection); #else - int error = pthread_mutex_lock(&Mutex); + pthread_mutex_lock(&Mutex); #endif } @@ -41,7 +41,7 @@ namespace cAudio #ifdef CAUDIO_PLATFORM_WIN LeaveCriticalSection(&criticalSection); #else - int error = pthread_mutex_unlock(&Mutex); + pthread_mutex_unlock(&Mutex); #endif } @@ -51,10 +51,10 @@ namespace cAudio InitializeCriticalSection(&criticalSection); #else pthread_mutexattr_t attr; - int error = pthread_mutexattr_init(&attr); - error = pthread_mutexattr_settype(&attr,PTHREAD_MUTEX_RECURSIVE); - error = pthread_mutex_init(&Mutex, &attr); - error = pthread_mutexattr_destroy(&attr); + pthread_mutexattr_init(&attr); + pthread_mutexattr_settype(&attr,PTHREAD_MUTEX_RECURSIVE); + pthread_mutex_init(&Mutex, &attr); + pthread_mutexattr_destroy(&attr); #endif Initialized=true; } diff --git a/cAudio/src/cOggDecoder.cpp b/cAudio/src/cOggDecoder.cpp index 5def886..97e837b 100644 --- a/cAudio/src/cOggDecoder.cpp +++ b/cAudio/src/cOggDecoder.cpp @@ -136,7 +136,7 @@ namespace cAudio { if(relative) { - float curtime = ov_time_tell(&oggStream); + double curtime = ov_time_tell(&oggStream); return (ov_time_seek(&oggStream,curtime+seconds)==0); } else @@ -153,7 +153,8 @@ namespace cAudio int cOggDecoder::getTotalSize() { - return ov_pcm_total(&oggStream, -1) * vorbisInfo->channels; + // ov_pcm_total is in samples + return ov_pcm_total(&oggStream, -1) * vorbisInfo->channels * 2; } int cOggDecoder::getCompressedSize() @@ -168,7 +169,8 @@ namespace cAudio int cOggDecoder::getCurrentPosition() { - return ov_pcm_tell(&oggStream) * vorbisInfo->channels; + // ov_pcm_tell is in samples + return ov_pcm_tell(&oggStream) * vorbisInfo->channels * 2; } int cOggDecoder::getCurrentCompressedPosition() diff --git a/cAudio/src/cOpenALAudioDeviceList.cpp b/cAudio/src/cOpenALAudioDeviceList.cpp index 5cdd3ee..9a1f9b1 100644 --- a/cAudio/src/cOpenALAudioDeviceList.cpp +++ b/cAudio/src/cOpenALAudioDeviceList.cpp @@ -2,11 +2,8 @@ // This file is part of the "cAudio Engine" // For conditions of distribution and use, see copyright notice in cAudio.h -#pragma once - #include "cOpenALAudioDeviceList.h" -#include -#include +#include "cOpenALUtil.h" namespace cAudio { @@ -23,12 +20,15 @@ namespace cAudio } else { +#if ALC_ENUMERATE_ALL_EXT if( alcIsExtensionPresent(NULL, "ALC_ENUMERATE_ALL_EXT") == AL_TRUE ) { specifier = ALC_ALL_DEVICES_SPECIFIER; defaultDevice = ALC_DEFAULT_ALL_DEVICES_SPECIFIER; } - else if( alcIsExtensionPresent(NULL, "ALC_ENUMERATION_EXT") == AL_TRUE ) + else +#endif + if( alcIsExtensionPresent(NULL, "ALC_ENUMERATION_EXT") == AL_TRUE ) { specifier = ALC_DEVICE_SPECIFIER; defaultDevice = ALC_DEFAULT_DEVICE_SPECIFIER; @@ -87,4 +87,4 @@ namespace cAudio } return AvailableDevices.size() > 0; } -} \ No newline at end of file +} diff --git a/cAudio/src/cOpenALDeviceContext.cpp b/cAudio/src/cOpenALDeviceContext.cpp index 0eacf60..734b13b 100644 --- a/cAudio/src/cOpenALDeviceContext.cpp +++ b/cAudio/src/cOpenALDeviceContext.cpp @@ -84,9 +84,9 @@ namespace cAudio return false; } - getLogger()->logInfo("AudioManager", "OpenAL Version: %s", alGetString(AL_VERSION)); - getLogger()->logInfo("AudioManager", "Vendor: %s", alGetString(AL_VENDOR)); - getLogger()->logInfo("AudioManager", "Renderer: %s", alGetString(AL_RENDERER)); + getLogger()->logWarning("AudioManager", "OpenAL Version: %s", alGetString(AL_VERSION)); + getLogger()->logWarning("AudioManager", "Vendor: %s", alGetString(AL_VENDOR)); + getLogger()->logWarning("AudioManager", "Renderer: %s", alGetString(AL_RENDERER)); #if CAUDIO_EFX_ENABLED == 1 initEffects.getEFXInterface()->Mutex.lock(); @@ -108,7 +108,8 @@ namespace cAudio getLogger()->logWarning("AudioManager", "EFX is not supported, EFX disabled."); } #endif - getLogger()->logInfo("AudioManager", "Supported Extensions: %s", alGetString(AL_EXTENSIONS)); + getLogger()->logWarning("AudioManager", "Supported Extensions: %s", alGetString(AL_EXTENSIONS)); + Initialized = true; return true; } @@ -124,8 +125,8 @@ namespace cAudio alcDestroyContext(Context); Context = NULL; //Close the device - alcCloseDevice(Device); - checkError(); + if (!alcCloseDevice(Device)) + getLogger()->logError("AudioManager", "alcCloseDevice failed"); Device = NULL; Initialized = false; @@ -169,16 +170,16 @@ namespace cAudio return true; } - if(Device) + //if(Device) { error = alcGetError(Device); if (error != AL_NO_ERROR) { - errorString = alGetString(error); + errorString = alcGetString(Device, error); getLogger()->logError("AudioManager", "OpenAL Error: %s.", errorString); return true; } } return false; } -} \ No newline at end of file +} diff --git a/cAudio/src/cThread.cpp b/cAudio/src/cThread.cpp index b91c301..ca27639 100644 --- a/cAudio/src/cThread.cpp +++ b/cAudio/src/cThread.cpp @@ -13,8 +13,6 @@ namespace cAudio cAudioThread::~cAudioThread() { - if(IsInit) - shutdown(); } bool cAudioThread::start() @@ -28,8 +26,6 @@ namespace cAudio #ifdef CAUDIO_PLATFORM_WIN ThreadHandle = reinterpret_cast(_beginthreadex(0, 0, threadFunc, this, 0, &ThreadID)); - if(ThreadHandle == 0) - CloseHandle( ThreadHandle ); #else pthread_create( &ThreadHandle, 0, threadFunc, this ); #endif @@ -79,9 +75,43 @@ namespace cAudio } #ifdef CAUDIO_PLATFORM_WIN + + // + // Usage: SetThreadName (-1, "MainThread"); + // + const DWORD MS_VC_EXCEPTION = 0x406D1388; + +#pragma pack(push,8) + typedef struct tagTHREADNAME_INFO + { + DWORD dwType; // Must be 0x1000. + LPCSTR szName; // Pointer to name (in user addr space). + DWORD dwThreadID; // Thread ID (-1=caller thread). + DWORD dwFlags; // Reserved for future use, must be zero. + } THREADNAME_INFO; +#pragma pack(pop) + + inline void SetThreadName(DWORD dwThreadID, const char* threadName) + { + THREADNAME_INFO info; + info.dwType = 0x1000; + info.szName = threadName; + info.dwThreadID = dwThreadID; + info.dwFlags = 0; + + __try + { + RaiseException(MS_VC_EXCEPTION, 0, sizeof(info) / sizeof(ULONG_PTR), (ULONG_PTR*)&info); + } + __except (EXCEPTION_EXECUTE_HANDLER) + { + } + } + unsigned int __stdcall cAudioThread::threadFunc(void *args) { cAudioThread* pThread = reinterpret_cast(args); + SetThreadName(GetCurrentThreadId(), "cAudio"); pThread->updateLoop(); return 0; } @@ -89,8 +119,13 @@ namespace cAudio void* cAudioThread::threadFunc(void* args) { cAudioThread* pThread = reinterpret_cast(args); +#if defined(CAUDIO_PLATFORM_MAC) || defined(CAUDIO_PLATFORM_IPHONE) + pthread_setname_np("cAudio"); +#else + pthread_setname_np(pthread_self(), "cAudio"); +#endif pThread->updateLoop(); return 0; } #endif -}; \ No newline at end of file +}; diff --git a/cAudio/src/cWavDecoder.cpp b/cAudio/src/cWavDecoder.cpp index cd05dbf..2fe8870 100644 --- a/cAudio/src/cWavDecoder.cpp +++ b/cAudio/src/cWavDecoder.cpp @@ -19,7 +19,6 @@ namespace cAudio char ident[4]; int tempint32 = 0; short tempint16 = 0; - char tempint8 = 0; unsigned int startOffset = 0; @@ -192,7 +191,7 @@ namespace cAudio bool cWavDecoder::seek(float seconds,bool relative) { - int amountToSeek = seconds * (float)SampleRate * (float)Channels * (float)(BitsPerSample/8); + int amountToSeek = (int) (seconds * (float)SampleRate * (float)Channels * (float)(BitsPerSample/8)); return setPosition(amountToSeek, relative); }