Added support for all OpenAL Audio Effects. Access can be gotten through the main audio manager using the AudioEffects interface. IEffect provides access to effect parameters and allows for binding to cAudio sources. IFilter provides access to filters that can be attached to sources and effects.

Added conversion functions from our audio format enum to OpenAL's in preparation for supporting more formats.
Reorganized cAudio defines, made it easier to access some compile time parameters.
Fixed a bug where a source could not be played again after it reached the end of its audio stream.
Added better checking for sources.  IsValid() should provide a more useful indication of whether a source is usable.
Added error checking and logging to cAudioCapture.
Prevented initializing of cAudioManager until shutdown() has been called.
Added a tutorial for Audio Effects.
Added a footsteps sound for showing off Audio Effects.
Moved the default compile location for the main library to lib/.  The msvc project will copy the cAudio.dll to bin/win32-visual/
This commit is contained in:
Joshua Jones 2010-01-11 00:39:08 +00:00
parent 2132eea8bf
commit 30e5b4a99e
36 changed files with 3040 additions and 203 deletions

View File

@ -58,7 +58,7 @@
<Tool
Name="VCLinkerTool"
AdditionalDependencies="cAudio.lib"
AdditionalLibraryDirectories="&quot;..\..\bin\win32-visual&quot;"
AdditionalLibraryDirectories="&quot;..\..\lib\win32-visual&quot;"
GenerateDebugInformation="true"
TargetMachine="1"
/>
@ -128,7 +128,7 @@
<Tool
Name="VCLinkerTool"
AdditionalDependencies="cAudio.lib"
AdditionalLibraryDirectories="&quot;..\..\bin\win32-visual&quot;"
AdditionalLibraryDirectories="&quot;..\..\lib\win32-visual&quot;"
GenerateDebugInformation="false"
OptimizeReferences="2"
EnableCOMDATFolding="2"

View File

@ -58,7 +58,7 @@
<Tool
Name="VCLinkerTool"
AdditionalDependencies="cAudio.lib"
AdditionalLibraryDirectories="&quot;..\..\bin\win32-visual&quot;"
AdditionalLibraryDirectories="&quot;..\..\lib\win32-visual&quot;"
GenerateDebugInformation="true"
TargetMachine="1"
/>
@ -128,7 +128,7 @@
<Tool
Name="VCLinkerTool"
AdditionalDependencies="cAudio.lib"
AdditionalLibraryDirectories="&quot;..\..\bin\win32-visual&quot;"
AdditionalLibraryDirectories="&quot;..\..\lib\win32-visual&quot;"
GenerateDebugInformation="false"
OptimizeReferences="2"
EnableCOMDATFolding="2"

View File

@ -58,7 +58,7 @@
<Tool
Name="VCLinkerTool"
AdditionalDependencies="cAudio.lib"
AdditionalLibraryDirectories="&quot;..\..\bin\win32-visual&quot;"
AdditionalLibraryDirectories="&quot;..\..\lib\win32-visual&quot;"
GenerateDebugInformation="true"
TargetMachine="1"
/>
@ -128,7 +128,7 @@
<Tool
Name="VCLinkerTool"
AdditionalDependencies="cAudio.lib"
AdditionalLibraryDirectories="&quot;..\..\bin\win32-visual&quot;"
AdditionalLibraryDirectories="&quot;..\..\lib\win32-visual&quot;"
GenerateDebugInformation="false"
OptimizeReferences="2"
EnableCOMDATFolding="2"

View File

@ -58,7 +58,7 @@
<Tool
Name="VCLinkerTool"
AdditionalDependencies="cAudio.lib"
AdditionalLibraryDirectories="&quot;..\..\bin\win32-visual&quot;"
AdditionalLibraryDirectories="&quot;..\..\lib\win32-visual&quot;"
GenerateDebugInformation="true"
TargetMachine="1"
/>
@ -128,7 +128,7 @@
<Tool
Name="VCLinkerTool"
AdditionalDependencies="cAudio.lib"
AdditionalLibraryDirectories="&quot;..\..\bin\win32-visual&quot;"
AdditionalLibraryDirectories="&quot;..\..\lib\win32-visual&quot;"
GenerateDebugInformation="false"
OptimizeReferences="2"
EnableCOMDATFolding="2"

View File

@ -9,6 +9,8 @@
//Include our version of Sleep to free CPU usage
#include "../../include/cAudioSleep.h"
#include "../../include/ILogger.h"
using namespace std;
const unsigned int CAPTURE_FREQUENCY = 22050;

View File

@ -0,0 +1,188 @@
<?xml version="1.0" encoding="Windows-1252"?>
<VisualStudioProject
ProjectType="Visual C++"
Version="9.00"
Name="Tutorial5_AudioEffects"
ProjectGUID="{EA03D1BB-6D71-4960-958A-670480A8259A}"
RootNamespace="Tutorial5_AudioEffects"
TargetFrameworkVersion="196613"
>
<Platforms>
<Platform
Name="Win32"
/>
</Platforms>
<ToolFiles>
</ToolFiles>
<Configurations>
<Configuration
Name="Debug|Win32"
OutputDirectory="../../bin/win32-visual"
IntermediateDirectory="obj/$(ConfigurationName)"
ConfigurationType="1"
CharacterSet="2"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
/>
<Tool
Name="VCCLCompilerTool"
Optimization="0"
MinimalRebuild="true"
BasicRuntimeChecks="3"
RuntimeLibrary="3"
WarningLevel="3"
DebugInformationFormat="4"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
AdditionalDependencies="cAudio.lib"
AdditionalLibraryDirectories="&quot;..\..\lib\win32-visual&quot;"
GenerateDebugInformation="true"
TargetMachine="1"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
<Configuration
Name="Release|Win32"
OutputDirectory="../../bin/win32-visual"
IntermediateDirectory="obj/$(ConfigurationName)"
ConfigurationType="1"
CharacterSet="2"
WholeProgramOptimization="1"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
/>
<Tool
Name="VCCLCompilerTool"
Optimization="2"
EnableIntrinsicFunctions="true"
RuntimeLibrary="2"
EnableFunctionLevelLinking="true"
WarningLevel="3"
DebugInformationFormat="3"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
AdditionalDependencies="cAudio.lib"
AdditionalLibraryDirectories="&quot;..\..\lib\win32-visual&quot;"
GenerateDebugInformation="true"
OptimizeReferences="2"
EnableCOMDATFolding="2"
TargetMachine="1"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
</Configurations>
<References>
</References>
<Files>
<Filter
Name="Source Files"
Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
>
<File
RelativePath=".\main.cpp"
>
</File>
</Filter>
<Filter
Name="Header Files"
Filter="h;hpp;hxx;hm;inl;inc;xsd"
UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
>
</Filter>
<Filter
Name="Resource Files"
Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav"
UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}"
>
</Filter>
</Files>
<Globals>
</Globals>
</VisualStudioProject>

View File

@ -0,0 +1,361 @@
#include <iostream>
#include <string>
//Include IAudioManager so we can easily work with cAudio
#include "../../include/IAudioManager.h"
//Include IAudio so we can create cAudio objects
#include "../../include/IAudio.h"
//Include our version of Sleep to free CPU usage
#include "../../include/cAudioSleep.h"
using namespace std;
int main(int argc, char* argv[])
{
//Some fancy text
cout << "cAudio 1.7.1 Tutorial 5: Audio Effects \n \n";
//Create an uninitialized Audio Manager
cAudio::IAudioManager* manager = cAudio::createAudioManager(false);
if(manager)
{
//Allow the user to choose a playback device
cout << "Available Playback Devices: \n";
unsigned int deviceCount = manager->getAvailableDeviceCount();
std::string defaultDeviceName = manager->getDefaultDeviceName();
for(unsigned int i=0; i<deviceCount; ++i)
{
std::string deviceName = manager->getAvailableDeviceName(i);
if(deviceName.compare(defaultDeviceName) == 0)
cout << i << "): " << deviceName << " [DEFAULT] \n";
else
cout << i << "): " << deviceName << " \n";
}
cout << std::endl;
cout << "Choose a device by number: ";
unsigned int deviceSelection = 0;
cin >> deviceSelection;
cout << std::endl;
//Initialize the manager with the user settings
manager->initialize(manager->getAvailableDeviceName(deviceSelection));
cAudio::IAudioEffects* effects = manager->getEffects();
if(effects)
{
cAudio::IEffect* effect = effects->createEffect();
cAudio::IFilter* filter = effects->createFilter();
if(effect && effect->isValid() && filter && filter->isValid())
{
filter->setHighFrequencyVolume(0.1f);
filter->setLowFrequencyVolume(0.1f);
//Create a IAudio object and load a sound from a file
cAudio::IAudio* mysound = manager->createFromFile("bling","../../media/Footsteps.wav",false);
if(mysound)
{
mysound->setVolume(1.0f);
mysound->attachFilter(filter);
mysound->attachEffect(0, effect);
std::cout << std::endl;
std::cout << "Simultaneous Effects Supported: " << effects->getMaxEffectsSupported() << ". \n";
std::cout << std::endl;
{
std::cout << "Playing sound with no effect or filter. \n";
filter->setType(cAudio::EFT_NULL);
effect->setType(cAudio::EET_NULL);
mysound->play2d(false);
while(mysound->isPlaying())
cAudio::cAudioSleep(10);
}
if(effects->isFilterSupported(cAudio::EFT_LOWPASS))
{
std::cout << "Playing sound with lowpass filter. \n";
filter->setType(cAudio::EFT_LOWPASS);
mysound->play2d(false);
while(mysound->isPlaying())
cAudio::cAudioSleep(10);
}
else
{
std::cout << "Lowpass filter not supported by this OpenAL device. \n";
}
if(effects->isFilterSupported(cAudio::EFT_HIGHPASS))
{
std::cout << "Playing sound with highpass filter. \n";
filter->setType(cAudio::EFT_HIGHPASS);
mysound->play2d(false);
while(mysound->isPlaying())
cAudio::cAudioSleep(10);
}
else
{
std::cout << "Highpass filter not supported by this OpenAL device. \n";
}
if(effects->isFilterSupported(cAudio::EFT_BANDPASS))
{
std::cout << "Playing sound with bandpass filter. \n";
filter->setType(cAudio::EFT_BANDPASS);
mysound->play2d(false);
while(mysound->isPlaying())
cAudio::cAudioSleep(10);
}
else
{
std::cout << "Bandpass filter not supported by this OpenAL device. \n";
}
filter->setType(cAudio::EFT_NULL);
if(effects->isEffectSupported(cAudio::EET_EAX_REVERB))
{
std::cout << "Playing sound with EAX Reverb effect. \n";
//Set the effect to a setting that distinctly shows off the effect (EAX_BATHROOM)
effect->setType(cAudio::EET_EAX_REVERB);
cAudio::sEAXReverbParameters param;
param.Gain = 0.316f;
param.GainHF = 0.251f;
param.GainLF = 1.0f;
param.Density = 0.17f;
param.DecayHFRatio = 0.54f;
param.ReflectionsGain = 0.653f;
param.ReflectionsDelay = 0.01f;
param.LateReverbDelay = 0.01f;
param.LateReverbGain = 3.273f;
effect->setEAXReverbParameters(param);
mysound->play2d(false);
while(mysound->isPlaying())
cAudio::cAudioSleep(10);
}
else
{
std::cout << "EAX Reverb effect not supported by this OpenAL device. \n";
}
if(effects->isEffectSupported(cAudio::EET_REVERB))
{
std::cout << "Playing sound with Reverb effect. \n";
//Set the effect to a setting that distinctly shows off the effect (EAX_BATHROOM)
effect->setType(cAudio::EET_REVERB);
cAudio::sReverbParameters param;
param.Gain = 0.316f;
param.GainHF = 0.251f;
param.Density = 0.17f;
param.DecayHFRatio = 0.54f;
param.ReflectionsGain = 0.653f;
param.ReflectionsDelay = 0.01f;
param.LateReverbDelay = 0.01f;
param.LateReverbGain = 3.273f;
effect->setReverbParameters(param);
mysound->play2d(false);
while(mysound->isPlaying())
cAudio::cAudioSleep(10);
}
else
{
std::cout << "Reverb effect not supported by this OpenAL device. \n";
}
if(effects->isEffectSupported(cAudio::EET_CHORUS))
{
std::cout << "Playing sound with Chorus effect. \n";
//Default settings
effect->setType(cAudio::EET_CHORUS);
mysound->play2d(false);
while(mysound->isPlaying())
cAudio::cAudioSleep(10);
}
else
{
std::cout << "Chorus effect not supported by this OpenAL device. \n";
}
if(effects->isEffectSupported(cAudio::EET_DISTORTION))
{
std::cout << "Playing sound with Distortion effect. \n";
//Default settings
effect->setType(cAudio::EET_DISTORTION);
mysound->play2d(false);
while(mysound->isPlaying())
cAudio::cAudioSleep(10);
}
else
{
std::cout << "Distortion effect not supported by this OpenAL device. \n";
}
if(effects->isEffectSupported(cAudio::EET_ECHO))
{
std::cout << "Playing sound with Echo effect. \n";
//Default settings
effect->setType(cAudio::EET_ECHO);
mysound->play2d(false);
while(mysound->isPlaying())
cAudio::cAudioSleep(10);
}
else
{
std::cout << "Echo effect not supported by this OpenAL device. \n";
}
if(effects->isEffectSupported(cAudio::EET_FLANGER))
{
std::cout << "Playing sound with Flanger effect. \n";
//Default settings
effect->setType(cAudio::EET_FLANGER);
mysound->play2d(false);
while(mysound->isPlaying())
cAudio::cAudioSleep(10);
}
else
{
std::cout << "Flanger effect not supported by this OpenAL device. \n";
}
if(effects->isEffectSupported(cAudio::EET_FREQUENCY_SHIFTER))
{
std::cout << "Playing sound with Frequency Shifter effect. \n";
//Default settings
effect->setType(cAudio::EET_FREQUENCY_SHIFTER);
mysound->play2d(false);
while(mysound->isPlaying())
cAudio::cAudioSleep(10);
}
else
{
std::cout << "Frequency Shifter effect not supported by this OpenAL device. \n";
}
if(effects->isEffectSupported(cAudio::EET_VOCAL_MORPHER))
{
std::cout << "Playing sound with Vocal Morpher effect. \n";
//Default settings
effect->setType(cAudio::EET_VOCAL_MORPHER);
mysound->play2d(false);
while(mysound->isPlaying())
cAudio::cAudioSleep(10);
}
else
{
std::cout << "Vocal Morpher effect not supported by this OpenAL device. \n";
}
if(effects->isEffectSupported(cAudio::EET_PITCH_SHIFTER))
{
std::cout << "Playing sound with Pitch Shifter effect. \n";
//Default settings
effect->setType(cAudio::EET_PITCH_SHIFTER);
mysound->play2d(false);
while(mysound->isPlaying())
cAudio::cAudioSleep(10);
}
else
{
std::cout << "Pitch Shifter effect not supported by this OpenAL device. \n";
}
if(effects->isEffectSupported(cAudio::EET_RING_MODULATOR))
{
std::cout << "Playing sound with Ring Modulator effect. \n";
//Default settings
effect->setType(cAudio::EET_RING_MODULATOR);
mysound->play2d(false);
while(mysound->isPlaying())
cAudio::cAudioSleep(10);
}
else
{
std::cout << "Ring Modulator effect not supported by this OpenAL device. \n";
}
if(effects->isEffectSupported(cAudio::EET_AUTOWAH))
{
std::cout << "Playing sound with Autowah effect. \n";
//Default settings
effect->setType(cAudio::EET_AUTOWAH);
mysound->play2d(false);
while(mysound->isPlaying())
cAudio::cAudioSleep(10);
}
else
{
std::cout << "Autowah effect not supported by this OpenAL device. \n";
}
if(effects->isEffectSupported(cAudio::EET_COMPRESSOR))
{
std::cout << "Playing sound with Compressor effect. \n";
//Default settings
effect->setType(cAudio::EET_COMPRESSOR);
mysound->play2d(false);
while(mysound->isPlaying())
cAudio::cAudioSleep(10);
}
else
{
std::cout << "Compressor effect not supported by this OpenAL device. \n";
}
if(effects->isEffectSupported(cAudio::EET_EQUALIZER))
{
std::cout << "Playing sound with Equalizer effect. \n";
//Default settings
effect->setType(cAudio::EET_EQUALIZER);
mysound->play2d(false);
while(mysound->isPlaying())
cAudio::cAudioSleep(10);
}
else
{
std::cout << "Equalizer effect not supported by this OpenAL device. \n";
}
}
filter->drop();
effect->drop();
}
}
//Delete all IAudio sounds
manager->release();
//Shutdown cAudio
manager->shutDown();
cAudio::destroyAudioManager(manager);
}
else
{
std::cout << "Failed to create audio playback manager. \n";
}
std::cout << "Press any key to quit \n";
std::cin.get();
std::cin.get();
return 0;
}

View File

@ -9,18 +9,18 @@
#include "../Include/cVector3.h"
#include "../Headers/cMutex.h"
#include "../include/ILogger.h"
//! Size of each internal buffer for sound (total amount buffered is BUFFER_SIZE * NUM_BUFFERS)
#define BUFFER_SIZE ( 1024 * 64 )
//! Number of internal buffers to cycle through (Note: using only 1 leads to choppy sound or premature ending of sources)
#define NUM_BUFFERS 3
#include "../Headers/cEFXFunctions.h"
namespace cAudio
{
class cAudio : public IAudio
{
public:
cAudio(IAudioDecoder* decoder);
#ifdef CAUDIO_EFX_ENABLED
cAudio(IAudioDecoder* decoder, ALCcontext* context, cEFXFunctions* oALFunctions);
#else
cAudio(IAudioDecoder* decoder, ALCcontext* context);
#endif
~cAudio();
//! Plays the source with the default or last set values
@ -38,7 +38,8 @@ namespace cAudio
virtual void loop(const bool& toLoop);
//! Seeks through the audio stream to a specific spot
/** Note: May not be supported by all codecs
\param seconds: Number of seconds from the start of the audio stream to seek to
\param seconds: Number of seconds to seek
\param relative: Whether to seek from the current position or the start of the stream
\return True on success, False if the codec does not support seeking. */
virtual bool seek(const float& seconds, bool relative = false);
@ -153,6 +154,22 @@ namespace cAudio
//!Returns the override for the doppler velocity vector
virtual const cVector3 getDopplerVelocity() const;
#ifdef CAUDIO_EFX_ENABLED
//! Returns the number of effects at one time this source can support
virtual unsigned int getNumEffectSlotsAvailable() const;
//! Attaches an EFX audio effect to this sound source to a specific slot
//! Range (slot): 0 to getNumEffectSlotsAvailable()
virtual bool attachEffect(unsigned int slot, IEffect* effect);
//! Removes an EFX audio effect from this sound source
//! Range (slot): 0 to getNumEffectSlotsAvailable()
virtual void removeEffect(unsigned int slot);
//! Attaches an audio filter to this sound source that will operate on the direct feed, seperate from any effects
virtual bool attachFilter(IFilter* filter);
//! Removes the previously attached filter
virtual void removeFilter();
#endif
protected:
private:
//Mutex for thread syncronization
@ -161,11 +178,16 @@ namespace cAudio
void empty();
//Checks for OpenAL errors and reports them
bool checkError();
//Steams audio data from the decoder into a buffer
//Streams audio data from the decoder into a buffer
bool stream(ALuint buffer);
//Converts our audio format enum to OpenAL's
ALenum convertAudioFormatEnum(AudioFormats format);
//The context that owns this source
ALCcontext* Context;
//Internal audio buffers
ALuint Buffers[NUM_BUFFERS];
ALuint Buffers[CAUDIO_SOURCE_NUM_BUFFERS];
//OpenAL source
ALuint Source;
//cAudio decoder being used to stream data
@ -175,6 +197,26 @@ namespace cAudio
bool Loop;
//Stores whether the source is ready to be used
bool Valid;
#ifdef CAUDIO_EFX_ENABLED
//Holds pointers to all the EFX related functions
cEFXFunctions* EFX;
//Updates the attached filter
void updateFilter(bool remove = false);
//Updates the effect attached to a specific slot
void updateEffect(unsigned int slot, bool remove = false);
//Stores the effects attached to this source
IEffect* Effects[CAUDIO_SOURCE_MAX_EFFECT_SLOTS];
unsigned int LastEffectTimeStamp[CAUDIO_SOURCE_MAX_EFFECT_SLOTS];
//Stores the attached direct feed filter
IFilter* Filter;
unsigned int LastFilterTimeStamp;
//Number of effects supported by the OpenAL Context
unsigned int EffectSlotsAvailable;
#endif
};
}
};
#endif //! CAUDIO_H_INCLUDED

View File

@ -109,6 +109,11 @@ namespace cAudio
std::string DeviceName;
ALCdevice* CaptureDevice;
//! Check for OpenAL errors
bool checkError();
//Converts our audio format enum to OpenAL's
ALenum convertAudioFormatEnum(AudioFormats format);
};
};

35
Headers/cAudioEffects.h Normal file
View File

@ -0,0 +1,35 @@
#ifndef CAUDIOEFFECTS_H
#define CAUDIOEFFECTS_H
#include "../include/IAudioEffects.h"
#include "../Headers/cMutex.h"
#include "../Headers/cEFXFunctions.h"
namespace cAudio
{
class cAudioEffects : public IAudioEffects
{
public:
cAudioEffects();
virtual ~cAudioEffects();
virtual IEffect* createEffect();
virtual IFilter* createFilter();
virtual unsigned int getMaxEffectsSupported() const;
virtual bool isEffectSupported(const EffectTypes& type) const;
virtual bool isFilterSupported(const FilterTypes& type) const;
cEFXFunctions* getEFXInterface();
void checkEFXSupportDetails();
private:
cAudioMutex Mutex;
cEFXFunctions EFXInterface;
unsigned int MaxEffectsSupported;
bool SupportedEffects[EET_COUNT];
bool SupportedFilters[EFT_COUNT];
};
};
#endif //! CAUDIOEFFECTS_H

View File

@ -10,6 +10,7 @@
#include "cListener.h"
#include "../include/IAudioManager.h"
#include "../Headers/cMutex.h"
#include "../Headers/cAudioEffects.h"
#include <AL/al.h>
#include <AL/alc.h>
@ -65,6 +66,7 @@ namespace cAudio
void getAvailableDevices();
virtual IListener* getListener() { return &initlistener; }
virtual IAudioEffects* getEffects() { return &initEffects; }
private:
//Mutex for thread syncronization
@ -89,8 +91,10 @@ namespace cAudio
std::map<std::string, IAudioDecoderFactory*> decodermap;
//! The listener object
cListener initlistener;
//! Interface for audio effects
cAudioEffects initEffects;
//! Check for OpenAL errors
void checkError();
bool checkError();
std::vector<std::string> AvailableDevices;
std::string DefaultDevice;

156
Headers/cEFXFunctions.h Normal file
View File

@ -0,0 +1,156 @@
#ifndef CEFXFUNCTIONS_H
#define CEFXFUNCTIONS_H
#include <AL/al.h>
#include <AL/alc.h>
#include <AL/efx.h>
#include <AL/efx-creative.h>
#include "../Headers/cMutex.h"
// EFX Extension function pointer variables
namespace cAudio
{
struct cEFXFunctions
{
cEFXFunctions::cEFXFunctions()
{
alGenEffects = NULL;
alDeleteEffects = NULL;
alIsEffect = NULL;
alEffecti = NULL;
alEffectiv = NULL;
alEffectf = NULL;
alEffectfv = NULL;
alGetEffecti = NULL;
alGetEffectiv = NULL;
alGetEffectf = NULL;
alGetEffectfv = NULL;
alGenFilters = NULL;
alDeleteFilters = NULL;
alIsFilter = NULL;
alFilteri = NULL;
alFilteriv = NULL;
alFilterf = NULL;
alFilterfv = NULL;
alGetFilteri = NULL;
alGetFilteriv = NULL;
alGetFilterf = NULL;
alGetFilterfv = NULL;
alGenAuxiliaryEffectSlots = NULL;
alDeleteAuxiliaryEffectSlots = NULL;
alIsAuxiliaryEffectSlot = NULL;
alAuxiliaryEffectSloti = NULL;
alAuxiliaryEffectSlotiv = NULL;
alAuxiliaryEffectSlotf = NULL;
alAuxiliaryEffectSlotfv = NULL;
alGetAuxiliaryEffectSloti = NULL;
alGetAuxiliaryEffectSlotiv = NULL;
alGetAuxiliaryEffectSlotf = NULL;
alGetAuxiliaryEffectSlotfv = NULL;
Supported = false;
}
// Effect objects
LPALGENEFFECTS alGenEffects;
LPALDELETEEFFECTS alDeleteEffects;
LPALISEFFECT alIsEffect;
LPALEFFECTI alEffecti;
LPALEFFECTIV alEffectiv;
LPALEFFECTF alEffectf;
LPALEFFECTFV alEffectfv;
LPALGETEFFECTI alGetEffecti;
LPALGETEFFECTIV alGetEffectiv;
LPALGETEFFECTF alGetEffectf;
LPALGETEFFECTFV alGetEffectfv;
// Filter objects
LPALGENFILTERS alGenFilters;
LPALDELETEFILTERS alDeleteFilters;
LPALISFILTER alIsFilter;
LPALFILTERI alFilteri;
LPALFILTERIV alFilteriv;
LPALFILTERF alFilterf;
LPALFILTERFV alFilterfv;
LPALGETFILTERI alGetFilteri;
LPALGETFILTERIV alGetFilteriv;
LPALGETFILTERF alGetFilterf;
LPALGETFILTERFV alGetFilterfv;
// Auxiliary slot object
LPALGENAUXILIARYEFFECTSLOTS alGenAuxiliaryEffectSlots;
LPALDELETEAUXILIARYEFFECTSLOTS alDeleteAuxiliaryEffectSlots;
LPALISAUXILIARYEFFECTSLOT alIsAuxiliaryEffectSlot;
LPALAUXILIARYEFFECTSLOTI alAuxiliaryEffectSloti;
LPALAUXILIARYEFFECTSLOTIV alAuxiliaryEffectSlotiv;
LPALAUXILIARYEFFECTSLOTF alAuxiliaryEffectSlotf;
LPALAUXILIARYEFFECTSLOTFV alAuxiliaryEffectSlotfv;
LPALGETAUXILIARYEFFECTSLOTI alGetAuxiliaryEffectSloti;
LPALGETAUXILIARYEFFECTSLOTIV alGetAuxiliaryEffectSlotiv;
LPALGETAUXILIARYEFFECTSLOTF alGetAuxiliaryEffectSlotf;
LPALGETAUXILIARYEFFECTSLOTFV alGetAuxiliaryEffectSlotfv;
cAudioMutex Mutex;
bool Supported;
bool CheckEFXSupport(ALCdevice* device)
{
Supported = false;
if (alcIsExtensionPresent(device, "ALC_EXT_EFX"))
{
// Get function pointers
alGenEffects = (LPALGENEFFECTS)alGetProcAddress("alGenEffects");
alDeleteEffects = (LPALDELETEEFFECTS )alGetProcAddress("alDeleteEffects");
alIsEffect = (LPALISEFFECT )alGetProcAddress("alIsEffect");
alEffecti = (LPALEFFECTI)alGetProcAddress("alEffecti");
alEffectiv = (LPALEFFECTIV)alGetProcAddress("alEffectiv");
alEffectf = (LPALEFFECTF)alGetProcAddress("alEffectf");
alEffectfv = (LPALEFFECTFV)alGetProcAddress("alEffectfv");
alGetEffecti = (LPALGETEFFECTI)alGetProcAddress("alGetEffecti");
alGetEffectiv = (LPALGETEFFECTIV)alGetProcAddress("alGetEffectiv");
alGetEffectf = (LPALGETEFFECTF)alGetProcAddress("alGetEffectf");
alGetEffectfv = (LPALGETEFFECTFV)alGetProcAddress("alGetEffectfv");
alGenFilters = (LPALGENFILTERS)alGetProcAddress("alGenFilters");
alDeleteFilters = (LPALDELETEFILTERS)alGetProcAddress("alDeleteFilters");
alIsFilter = (LPALISFILTER)alGetProcAddress("alIsFilter");
alFilteri = (LPALFILTERI)alGetProcAddress("alFilteri");
alFilteriv = (LPALFILTERIV)alGetProcAddress("alFilteriv");
alFilterf = (LPALFILTERF)alGetProcAddress("alFilterf");
alFilterfv = (LPALFILTERFV)alGetProcAddress("alFilterfv");
alGetFilteri = (LPALGETFILTERI )alGetProcAddress("alGetFilteri");
alGetFilteriv= (LPALGETFILTERIV )alGetProcAddress("alGetFilteriv");
alGetFilterf = (LPALGETFILTERF )alGetProcAddress("alGetFilterf");
alGetFilterfv= (LPALGETFILTERFV )alGetProcAddress("alGetFilterfv");
alGenAuxiliaryEffectSlots = (LPALGENAUXILIARYEFFECTSLOTS)alGetProcAddress("alGenAuxiliaryEffectSlots");
alDeleteAuxiliaryEffectSlots = (LPALDELETEAUXILIARYEFFECTSLOTS)alGetProcAddress("alDeleteAuxiliaryEffectSlots");
alIsAuxiliaryEffectSlot = (LPALISAUXILIARYEFFECTSLOT)alGetProcAddress("alIsAuxiliaryEffectSlot");
alAuxiliaryEffectSloti = (LPALAUXILIARYEFFECTSLOTI)alGetProcAddress("alAuxiliaryEffectSloti");
alAuxiliaryEffectSlotiv = (LPALAUXILIARYEFFECTSLOTIV)alGetProcAddress("alAuxiliaryEffectSlotiv");
alAuxiliaryEffectSlotf = (LPALAUXILIARYEFFECTSLOTF)alGetProcAddress("alAuxiliaryEffectSlotf");
alAuxiliaryEffectSlotfv = (LPALAUXILIARYEFFECTSLOTFV)alGetProcAddress("alAuxiliaryEffectSlotfv");
alGetAuxiliaryEffectSloti = (LPALGETAUXILIARYEFFECTSLOTI)alGetProcAddress("alGetAuxiliaryEffectSloti");
alGetAuxiliaryEffectSlotiv = (LPALGETAUXILIARYEFFECTSLOTIV)alGetProcAddress("alGetAuxiliaryEffectSlotiv");
alGetAuxiliaryEffectSlotf = (LPALGETAUXILIARYEFFECTSLOTF)alGetProcAddress("alGetAuxiliaryEffectSlotf");
alGetAuxiliaryEffectSlotfv = (LPALGETAUXILIARYEFFECTSLOTFV)alGetProcAddress("alGetAuxiliaryEffectSlotfv");
if (alGenEffects && alDeleteEffects && alIsEffect && alEffecti && alEffectiv && alEffectf &&
alEffectfv && alGetEffecti && alGetEffectiv && alGetEffectf && alGetEffectfv && alGenFilters &&
alDeleteFilters && alIsFilter && alFilteri && alFilteriv && alFilterf && alFilterfv &&
alGetFilteri && alGetFilteriv && alGetFilterf && alGetFilterfv && alGenAuxiliaryEffectSlots &&
alDeleteAuxiliaryEffectSlots && alIsAuxiliaryEffectSlot && alAuxiliaryEffectSloti &&
alAuxiliaryEffectSlotiv && alAuxiliaryEffectSlotf && alAuxiliaryEffectSlotfv &&
alGetAuxiliaryEffectSloti && alGetAuxiliaryEffectSlotiv && alGetAuxiliaryEffectSlotf &&
alGetAuxiliaryEffectSlotfv)
Supported = true;
}
return Supported;
}
};
};
#endif //! CEFXFUNCTIONS_H

117
Headers/cEffect.h Normal file
View File

@ -0,0 +1,117 @@
#ifndef CEFFECT_H
#define CEFFECT_H
#include "../include/IEffect.h"
#include "../Headers/cMutex.h"
#include "../Headers/cEFXFunctions.h"
#include <AL/al.h>
#include <AL/alc.h>
namespace cAudio
{
class cEffect : public IEffect
{
public:
cEffect(cEFXFunctions* oALFunctions);
virtual ~cEffect();
virtual const EffectTypes& getType() const;
virtual void setType(const EffectTypes& type);
virtual const sEAXReverbParameters& getEAXReverbParameters() const;
virtual void setEAXReverbParameters(const sEAXReverbParameters& param);
virtual const sReverbParameters& getReverbParameters() const;
virtual void setReverbParameters(const sReverbParameters& param);
virtual const sChorusParameters& getChorusParameters() const;
virtual void setChorusParameters(const sChorusParameters& param);
virtual const sDistortionParameters& getDistortionParameters() const;
virtual void setDistortionParameters(const sDistortionParameters& param);
virtual const sEchoParameters& getEchoParameters() const;
virtual void setEchoParameters(const sEchoParameters& param);
virtual const sFlangerParameters& getFlangerParameters() const;
virtual void setFlangerParameters(const sFlangerParameters& param);
virtual const sFrequencyShiftParameters& getFrequencyShiftParameters() const;
virtual void setFrequencyShiftParameters(const sFrequencyShiftParameters& param);
virtual const sVocalMorpherParameters& getVocalMorpherParameters() const;
virtual void setVocalMorpherParameters(const sVocalMorpherParameters& param);
virtual const sPitchShifterParameters& getPitchShifterParameters() const;
virtual void setPitchShifterParameters(const sPitchShifterParameters& param);
virtual const sRingModulatorParameters& getRingModulatorParameters() const;
virtual void setRingModulatorParameters(const sRingModulatorParameters& param);
virtual const sAutowahParameters& getAutowahParameters() const;
virtual void setAutowahParameters(const sAutowahParameters& param);
virtual const sCompressorParameters& getCompressorParameters() const;
virtual void setCompressorParameters(const sCompressorParameters& param);
virtual const sEqualizerParameters& getEqualizerParameters() const;
virtual void setEqualizerParameters(const sEqualizerParameters& param);
virtual float getMasterVolume() const;
virtual void setMasterVolume(const float& volume);
virtual bool isIgnoringAttenuation() const;
virtual void ignoreAttenuation(const bool& ignore);
virtual IFilter* getFilter() const;
virtual void attachFilter(IFilter* filter);
virtual void removeFilter();
virtual unsigned int getLastUpdated() const;
virtual bool isValid() const;
ALuint getOpenALEffect() const;
ALuint getOpenALEffectSlot() const;
private:
cEFXFunctions* EFX;
//Mutex for thread syncronization
cAudioMutex Mutex;
EffectTypes Type;
float Volume;
bool IgnoreAttenuation;
unsigned int LastUpdated;
bool Valid;
IFilter* Filter;
ALuint Effect;
ALuint EffectSlot;
bool UpdateEffect();
bool CheckError();
ALenum ConvertEffectEnum(EffectTypes type);
ALenum ConvertFrequencyShiftEnum(sFrequencyShiftParameters::ShiftDirection shift);
ALenum ConvertVocalMorphPhonemeEnum(sVocalMorpherParameters::MorpherPhoneme phoneme);
//Storage for all the possible settings for effects
sEAXReverbParameters EAXReverbParam;
sReverbParameters ReverbParam;
sChorusParameters ChorusParam;
sDistortionParameters DistortionParam;
sEchoParameters EchoParam;
sFlangerParameters FlangerParam;
sFrequencyShiftParameters FrequencyShiftParam;
sVocalMorpherParameters VocalMorpherParam;
sPitchShifterParameters PitchShifterParam;
sRingModulatorParameters RingModulatorParam;
sAutowahParameters AutowahParam;
sCompressorParameters CompressorParam;
sEqualizerParameters EqualizerParam;
};
};
#endif //! CEFFECT_H

58
Headers/cFilter.h Normal file
View File

@ -0,0 +1,58 @@
#ifndef CFILTER_H
#define CFILTER_H
#include "../include/IFilter.h"
#include "../Headers/cMutex.h"
#include "../Headers/cEFXFunctions.h"
#include <AL/al.h>
#include <AL/alc.h>
namespace cAudio
{
class cFilter : public IFilter
{
public:
cFilter(cEFXFunctions* oALFunctions);
~cFilter();
virtual const FilterTypes& getType() const;
virtual void setType(const FilterTypes& type);
virtual float getVolume() const;
virtual void setVolume(const float& volume);
virtual float getLowFrequencyVolume() const;
virtual void setLowFrequencyVolume(const float& volumeLF);
virtual float getHighFrequencyVolume() const;
virtual void setHighFrequencyVolume(const float& volumeHF);
virtual unsigned int getLastUpdated() const;
virtual bool isValid() const;
ALuint getOpenALFilter() const;
protected:
cEFXFunctions* EFX;
//Mutex for thread syncronization
cAudioMutex Mutex;
FilterTypes Type;
float Volume;
float LowFreqVolume;
float HighFreqVolume;
unsigned int LastUpdated;
bool Valid;
ALuint Filter;
bool UpdateFilter();
bool CheckError();
ALenum ConvertFilterEnum(FilterTypes type);
};
};
#endif //! CFILTER_H

View File

@ -41,6 +41,14 @@ namespace cAudio
virtual cVector3 getVelocity(void) const { return Velocity; }
//!Returns the global volume modifier for all sources
virtual float getMasterVolume(void) const { return MasterGain; }
#ifdef CAUDIO_EFX_ENABLED
//!Sets the meters per user world unit for use with sound effects
virtual void setMetersPerUnit(const float& meters);
//!Returns the meters per user world unit for use with sound effects
virtual float getMetersPerUnit(void) const;
#endif
protected:
cAudioMutex Mutex;

View File

@ -48,7 +48,6 @@ namespace cAudio
};
#endif
#ifdef CAUDIO_MAKE_THREAD_SAFE
class cAudioMutexBasicLock
{
public:
@ -63,7 +62,6 @@ namespace cAudio
protected:
cAudioMutex* Mutex;
};
#endif
};
#endif //! CAUDIOMUTEX_H

View File

@ -1,39 +1,91 @@
#include "../Headers/cAudio.h"
#include "../Headers/cLogger.h"
#include "../Headers/cFilter.h"
#include "../Headers/cEffect.h"
namespace cAudio
{
cAudio::cAudio(IAudioDecoder* decoder) : Decoder(decoder), Loop(false), Valid(false)
#ifdef CAUDIO_EFX_ENABLED
cAudio::cAudio(IAudioDecoder* decoder, ALCcontext* context, cEFXFunctions* oALFunctions)
: Context(context), Source(0), Decoder(decoder), Loop(false), Valid(false),
EFX(oALFunctions), Filter(NULL), EffectSlotsAvailable(0), LastFilterTimeStamp(0)
#else
cAudio::cAudio(IAudioDecoder* decoder, ALCcontext* context)
: Context(context), Source(0), Decoder(decoder), Loop(false), Valid(false)
#endif
{
Mutex.lock();
cAudioMutexBasicLock lock(Mutex);
for(int i=0; i<CAUDIO_SOURCE_NUM_BUFFERS; ++i)
Buffers[i] = 0;
#ifdef CAUDIO_EFX_ENABLED
for(int i=0; i<CAUDIO_SOURCE_MAX_EFFECT_SLOTS; ++i)
Effects[i] = NULL;
for(int i=0; i<CAUDIO_SOURCE_MAX_EFFECT_SLOTS; ++i)
LastEffectTimeStamp[i] = 0;
#endif
if(Decoder)
Decoder->grab();
//Generates 3 buffers for the ogg file
alGenBuffers(NUM_BUFFERS, Buffers);
//Creates one source to be stored.
alGenSources(1, &Source);
alGenBuffers(CAUDIO_SOURCE_NUM_BUFFERS, Buffers);
bool state = !checkError();
Valid = state && (Decoder != NULL);
Mutex.unlock();
if(state)
{
//Creates one source to be stored.
alGenSources(1, &Source);
state = !checkError();
}
#ifdef CAUDIO_EFX_ENABLED
Valid = state && (Decoder != NULL) && (Context != NULL) && (EFX != NULL);
#else
Valid = state && (Decoder != NULL) && (Context != NULL);
#endif
#ifdef CAUDIO_EFX_ENABLED
int numSlots = 0;
ALCdevice* device = alcGetContextsDevice(Context);
alcGetIntegerv(device, ALC_MAX_AUXILIARY_SENDS, 1, &numSlots);
EffectSlotsAvailable = (numSlots <= CAUDIO_SOURCE_MAX_EFFECT_SLOTS) ? numSlots : CAUDIO_SOURCE_MAX_EFFECT_SLOTS;
#endif
}
cAudio::~cAudio()
{
Mutex.lock();
cAudioMutexBasicLock lock(Mutex);
if(Decoder)
Decoder->drop();
Mutex.unlock();
#ifdef CAUDIO_EFX_ENABLED
for(int i=0; i<CAUDIO_SOURCE_MAX_EFFECT_SLOTS; ++i)
{
if(Effects[i])
Effects[i]->drop();
Effects[i] = NULL;
}
if(Filter)
Filter->drop();
Filter = NULL;
#endif
}
bool cAudio::play()
{
Mutex.lock();
cAudioMutexBasicLock lock(Mutex);
if (!isPaused())
{
int queueSize = 0;
for(int u = 0; u < NUM_BUFFERS; u++)
int queueSize = 0;
//Resets the audio to the beginning
Decoder->setPosition(0, false);
//Purges all buffers from the source
alSourcei(Source, AL_BUFFER, 0);
checkError();
for(int u = 0; u < CAUDIO_SOURCE_NUM_BUFFERS; u++)
{
int val = stream(Buffers[u]);
@ -48,76 +100,75 @@ namespace cAudio
alSourceQueueBuffers(Source, queueSize, Buffers);
checkError();
}
#ifdef CAUDIO_EFX_ENABLED
updateFilter();
for(unsigned int i=0; i<CAUDIO_SOURCE_MAX_EFFECT_SLOTS; ++i)
updateEffect(i);
#endif
alSourcePlay(Source);
checkError();
Mutex.unlock();
getLogger()->logDebug("Audio Source", "Source playing.");
return true;
}
bool cAudio::play2d(const bool& toLoop)
{
Mutex.lock();
cAudioMutexBasicLock lock(Mutex);
alSourcei(Source, AL_SOURCE_RELATIVE, true);
loop(toLoop);
bool state = play();
checkError();
Mutex.unlock();
return state;
}
bool cAudio::play3d(const cVector3& position, const float& soundstr, const bool& toLoop)
{
Mutex.lock();
cAudioMutexBasicLock lock(Mutex);
alSourcei(Source, AL_SOURCE_RELATIVE, false);
setPosition(position);
setStrength(soundstr);
loop(toLoop);
bool state = play();
checkError();
Mutex.unlock();
return state;
}
void cAudio::pause()
{
Mutex.lock();
cAudioMutexBasicLock lock(Mutex);
alSourcePause(Source);
checkError();
Mutex.unlock();
getLogger()->logDebug("Audio Source", "Source paused.");
}
void cAudio::stop()
{
Mutex.lock();
cAudioMutexBasicLock lock(Mutex);
alSourceStop(Source);
checkError();
Mutex.unlock();
getLogger()->logDebug("Audio Source", "Source stopped.");
}
void cAudio::loop(const bool& loop)
{
Mutex.lock();
cAudioMutexBasicLock lock(Mutex);
Loop = loop;
Mutex.unlock();
}
bool cAudio::seek(const float& seconds, bool relative)
{
bool state = false;
Mutex.lock();
cAudioMutexBasicLock lock(Mutex);
if(Decoder->isSeekingSupported())
{
state = Decoder->seek(seconds, relative);
}
Mutex.unlock();
return state;
}
bool cAudio::update()
{
cAudioMutexBasicLock lock(Mutex);
if(!isValid() || !isPlaying())
{
return false;
@ -125,7 +176,12 @@ namespace cAudio
int processed = 0;
bool active = true;
Mutex.lock();
#ifdef CAUDIO_EFX_ENABLED
updateFilter();
for(unsigned int i=0; i<CAUDIO_SOURCE_MAX_EFFECT_SLOTS; ++i)
updateEffect(i);
#endif
//gets the sound source processed buffers
alGetSourcei(Source, AL_BUFFERS_PROCESSED, &processed);
//while there is more data refill buffers with audio data.
@ -141,22 +197,20 @@ namespace cAudio
checkError();
}
Mutex.unlock();
return active;
}
void cAudio::release()
{
Mutex.lock();
cAudioMutexBasicLock lock(Mutex);
//Stops the audio Source
alSourceStop(Source);
empty();
//Deletes the source
alDeleteSources(1, &Source);
//deletes the last filled buffer
alDeleteBuffers(NUM_BUFFERS, Buffers);
alDeleteBuffers(CAUDIO_SOURCE_NUM_BUFFERS, Buffers);
checkError();
Mutex.unlock();
getLogger()->logDebug("Audio Source", "Audio source released.");
}
@ -193,34 +247,30 @@ namespace cAudio
void cAudio::setPosition(const cVector3& position)
{
Mutex.lock();
cAudioMutexBasicLock lock(Mutex);
alSource3f(Source, AL_POSITION, position.x, position.y, position.z);
checkError();
Mutex.unlock();
}
void cAudio::setVelocity(const cVector3& velocity)
{
Mutex.lock();
cAudioMutexBasicLock lock(Mutex);
alSource3f(Source, AL_VELOCITY, velocity.x, velocity.y, velocity.z);
checkError();
Mutex.unlock();
}
void cAudio::setDirection(const cVector3& direction)
{
Mutex.lock();
cAudioMutexBasicLock lock(Mutex);
alSource3f(Source, AL_DIRECTION, direction.x, direction.y, direction.z);
checkError();
Mutex.unlock();
}
void cAudio::setRolloffFactor(const float& rolloff)
{
Mutex.lock();
cAudioMutexBasicLock lock(Mutex);
alSourcef(Source, AL_ROLLOFF_FACTOR, rolloff);
checkError();
Mutex.unlock();
}
void cAudio::setStrength(const float& soundstrength)
@ -229,110 +279,97 @@ namespace cAudio
if(soundstrength > 0.0f)
inverseStrength = 1.0f / soundstrength;
Mutex.lock();
cAudioMutexBasicLock lock(Mutex);
alSourcef(Source, AL_ROLLOFF_FACTOR, inverseStrength);
checkError();
Mutex.unlock();
}
void cAudio::setMinDistance(const float& minDistance)
{
Mutex.lock();
cAudioMutexBasicLock lock(Mutex);
alSourcef(Source, AL_REFERENCE_DISTANCE, minDistance);
checkError();
Mutex.unlock();
}
void cAudio::setMaxDistance(const float& maxDistance)
{
Mutex.lock();
cAudioMutexBasicLock lock(Mutex);
alSourcef(Source, AL_MAX_DISTANCE, maxDistance);
checkError();
Mutex.unlock();
}
void cAudio::setPitch(const float& pitch)
{
Mutex.lock();
cAudioMutexBasicLock lock(Mutex);
alSourcef (Source, AL_PITCH, pitch);
checkError();
Mutex.unlock();
}
void cAudio::setVolume(const float& volume)
{
Mutex.lock();
cAudioMutexBasicLock lock(Mutex);
alSourcef(Source, AL_GAIN, volume);
checkError();
Mutex.unlock();
}
void cAudio::setMinVolume(const float& minVolume)
{
Mutex.lock();
cAudioMutexBasicLock lock(Mutex);
alSourcef(Source, AL_MIN_GAIN, minVolume);
checkError();
Mutex.unlock();
}
void cAudio::setMaxVolume(const float& maxVolume)
{
Mutex.lock();
cAudioMutexBasicLock lock(Mutex);
alSourcef(Source, AL_MAX_GAIN, maxVolume);
checkError();
Mutex.unlock();
}
void cAudio::setInnerConeAngle(const float& innerAngle)
{
Mutex.lock();
cAudioMutexBasicLock lock(Mutex);
alSourcef(Source, AL_CONE_INNER_ANGLE, innerAngle);
checkError();
Mutex.unlock();
}
void cAudio::setOuterConeAngle(const float& outerAngle)
{
Mutex.lock();
cAudioMutexBasicLock lock(Mutex);
alSourcef(Source, AL_CONE_OUTER_ANGLE, outerAngle);
checkError();
Mutex.unlock();
}
void cAudio::setOuterConeVolume(const float& outerVolume)
{
Mutex.lock();
cAudioMutexBasicLock lock(Mutex);
alSourcef(Source, AL_CONE_OUTER_GAIN, outerVolume);
checkError();
Mutex.unlock();
}
void cAudio::setDopplerStrength(const float& dstrength)
{
Mutex.lock();
cAudioMutexBasicLock lock(Mutex);
alSourcef(Source, AL_DOPPLER_FACTOR, dstrength);
checkError();
Mutex.unlock();
}
void cAudio::setDopplerVelocity(const cVector3& dvelocity)
{
Mutex.lock();
cAudioMutexBasicLock lock(Mutex);
alSource3f(Source, AL_DOPPLER_VELOCITY, dvelocity.x, dvelocity.y, dvelocity.z);
checkError();
Mutex.unlock();
}
void cAudio::move(const cVector3& position)
{
Mutex.lock();
cAudioMutexBasicLock lock(Mutex);
cVector3 oldPos = getPosition();
cVector3 velocity = position - oldPos;
alSource3f(Source, AL_VELOCITY, velocity.x, velocity.y, velocity.z);
alSource3f(Source, AL_POSITION, position.x, position.y, position.z);
checkError();
Mutex.unlock();
}
const cVector3 cAudio::getPosition() const
@ -452,6 +489,65 @@ namespace cAudio
return velocity;
}
#ifdef CAUDIO_EFX_ENABLED
unsigned int cAudio::getNumEffectSlotsAvailable() const
{
return EffectSlotsAvailable;
}
bool cAudio::attachEffect(unsigned int slot, IEffect* effect)
{
cAudioMutexBasicLock lock(Mutex);
if(slot < EffectSlotsAvailable)
{
Effects[slot] = effect;
if(Effects[slot])
Effects[slot]->grab();
updateEffect(slot);
return true;
}
return false;
}
void cAudio::removeEffect(unsigned int slot)
{
cAudioMutexBasicLock lock(Mutex);
if(slot < EffectSlotsAvailable)
{
if(Effects[slot])
Effects[slot]->drop();
Effects[slot] = NULL;
LastEffectTimeStamp[slot] = 0;
updateEffect(slot, true);
}
}
bool cAudio::attachFilter(IFilter* filter)
{
cAudioMutexBasicLock lock(Mutex);
Filter = filter;
if(Filter)
Filter->grab();
updateFilter();
return true;
}
void cAudio::removeFilter()
{
cAudioMutexBasicLock lock(Mutex);
if(Filter)
Filter->drop();
Filter = NULL;
LastFilterTimeStamp = 0;
updateFilter(true);
}
#endif
void cAudio::empty()
{
int queued = 0;
@ -489,11 +585,11 @@ namespace cAudio
//stores the caculated data into buffer that is passed to output.
size_t totalread = 0;
unsigned int errorcount = 0;
char tempbuffer[BUFFER_SIZE];
while( totalread < BUFFER_SIZE )
char tempbuffer[CAUDIO_SOURCE_BUFFER_SIZE];
while( totalread < CAUDIO_SOURCE_BUFFER_SIZE )
{
char tempbuffer2[BUFFER_SIZE];
int actualread = Decoder->readAudioData(tempbuffer2, BUFFER_SIZE-totalread);
char tempbuffer2[CAUDIO_SOURCE_BUFFER_SIZE];
int actualread = Decoder->readAudioData(tempbuffer2, CAUDIO_SOURCE_BUFFER_SIZE-totalread);
if(actualread > 0)
{
memcpy(tempbuffer+totalread,tempbuffer2,actualread);
@ -525,10 +621,86 @@ namespace cAudio
return false;
}
getLogger()->logDebug("Audio Source", "Buffered %i bytes of data into buffer %i at %i hz.", totalread, buffer, Decoder->getFrequency());
alBufferData(buffer, Decoder->getFormat(), tempbuffer, totalread, Decoder->getFrequency());
alBufferData(buffer, convertAudioFormatEnum(Decoder->getFormat()), tempbuffer, totalread, Decoder->getFrequency());
checkError();
return true;
}
return false;
}
ALenum cAudio::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;
};
}
#ifdef CAUDIO_EFX_ENABLED
void cAudio::updateFilter(bool remove)
{
if(!remove)
{
if(Filter && Filter->isValid())
{
if(LastFilterTimeStamp != Filter->getLastUpdated())
{
LastFilterTimeStamp = Filter->getLastUpdated();
cFilter* theFilter = static_cast<cFilter*>(Filter);
if(theFilter)
{
alSourcei(Source, AL_DIRECT_FILTER, theFilter->getOpenALFilter());
checkError();
return;
}
}
return;
}
}
alSourcei(Source, AL_DIRECT_FILTER, AL_FILTER_NULL);
checkError();
}
void cAudio::updateEffect(unsigned int slot, bool remove)
{
if(slot < EffectSlotsAvailable)
{
if(!remove)
{
if(Effects[slot] && Effects[slot]->isValid())
{
if(LastEffectTimeStamp[slot] != Effects[slot]->getLastUpdated())
{
LastEffectTimeStamp[slot] = Effects[slot]->getLastUpdated();
cEffect* theEffect = static_cast<cEffect*>(Effects[slot]);
if(theEffect)
{
ALuint filterID = AL_FILTER_NULL;
cFilter* theFilter = static_cast<cFilter*>(theEffect->getFilter());
if(theFilter)
{
filterID = theFilter->getOpenALFilter();
}
alSource3i(Source, AL_AUXILIARY_SEND_FILTER, theEffect->getOpenALEffectSlot(), slot, filterID);
checkError();
return;
}
}
return;
}
}
alSource3i(Source, AL_AUXILIARY_SEND_FILTER, AL_EFFECTSLOT_NULL, slot, AL_FILTER_NULL);
checkError();
}
}
#endif
}

View File

@ -2,6 +2,7 @@
#include "../Headers/cUtils.h"
#include "../Headers/cThread.h"
#include "../include/cAudioSleep.h"
#include "../Headers/cLogger.h"
#include <string.h>
#include <set>
@ -46,39 +47,39 @@ namespace cAudio
bool cAudioCapture::checkCaptureExtension()
{
Mutex.lock();
cAudioMutexBasicLock lock(Mutex);
// Check for Capture Extension support
Supported = ( alcIsExtensionPresent(NULL, "ALC_EXT_CAPTURE") == AL_TRUE );
Mutex.unlock();
return Supported;
}
bool cAudioCapture::initOpenALDevice()
{
Mutex.lock();
cAudioMutexBasicLock lock(Mutex);
if(Supported)
{
if(CaptureDevice)
shutdownOpenALDevice();
if(DeviceName.empty())
CaptureDevice = alcCaptureOpenDevice(NULL, Frequency, Format, InternalBufferSize / SampleSize);
CaptureDevice = alcCaptureOpenDevice(NULL, Frequency, convertAudioFormatEnum(Format), InternalBufferSize / SampleSize);
else
CaptureDevice = alcCaptureOpenDevice(DeviceName.c_str(), Frequency, Format, InternalBufferSize / SampleSize);
CaptureDevice = alcCaptureOpenDevice(DeviceName.c_str(), Frequency, convertAudioFormatEnum(Format), InternalBufferSize / SampleSize);
if(CaptureDevice)
{
DeviceName = alcGetString(CaptureDevice, ALC_CAPTURE_DEVICE_SPECIFIER);
Ready = true;
Mutex.unlock();
checkError();
getLogger()->logDebug("AudioCapture", "OpenAL Capture Device Opened.");
return true;
}
}
Mutex.unlock();
checkError();
return false;
}
void cAudioCapture::shutdownOpenALDevice()
{
Mutex.lock();
cAudioMutexBasicLock lock(Mutex);
if(Supported)
{
if(Capturing)
@ -89,23 +90,23 @@ namespace cAudio
alcCaptureCloseDevice(CaptureDevice);
CaptureDevice = NULL;
Ready = false;
getLogger()->logDebug("AudioCapture", "OpenAL Capture Device Closed.");
}
checkError();
CaptureBuffer.clear();
}
Mutex.unlock();
}
void cAudioCapture::shutdown()
{
Mutex.lock();
cAudioMutexBasicLock lock(Mutex);
shutdownOpenALDevice();
Mutex.unlock();
}
void cAudioCapture::getAvailableDevices()
{
// Get list of available Capture Devices
Mutex.lock();
cAudioMutexBasicLock lock(Mutex);
if( alcIsExtensionPresent(NULL, "ALC_ENUMERATION_EXT") == AL_TRUE )
{
const char* deviceList = alcGetString(NULL, ALC_CAPTURE_DEVICE_SPECIFIER);
@ -122,43 +123,36 @@ namespace cAudio
// Get the name of the 'default' capture device
DefaultDevice = alcGetString(NULL, ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER);
}
Mutex.unlock();
}
const char* cAudioCapture::getAvailableDeviceName(unsigned int index)
{
Mutex.lock();
cAudioMutexBasicLock lock(Mutex);
if(!AvailableDevices.empty())
{
//Bounds check
if( index > (AvailableDevices.size()-1) ) index = (AvailableDevices.size()-1);
const char* deviceName = AvailableDevices[index].c_str();
Mutex.unlock();
return deviceName;
}
Mutex.unlock();
return "";
}
unsigned int cAudioCapture::getAvailableDeviceCount()
{
Mutex.lock();
unsigned int size = AvailableDevices.size();
Mutex.unlock();
return size;
cAudioMutexBasicLock lock(Mutex);
return AvailableDevices.size();
}
const char* cAudioCapture::getDefaultDeviceName()
{
Mutex.lock();
const char* deviceName = DefaultDevice.empty() ? "" : DefaultDevice.c_str();
Mutex.unlock();
return deviceName;
cAudioMutexBasicLock lock(Mutex);
return DefaultDevice.empty() ? "" : DefaultDevice.c_str();
}
void cAudioCapture::updateCaptureBuffer(bool force)
{
Mutex.lock();
cAudioMutexBasicLock lock(Mutex);
if(Capturing && CaptureDevice && Ready)
{
int AvailableSamples = 0;
@ -174,15 +168,16 @@ namespace cAudio
const unsigned int oldBufferSize = CaptureBuffer.size();
CaptureBuffer.resize(oldBufferSize + availbuffersize, 0);
alcCaptureSamples(CaptureDevice, &CaptureBuffer[oldBufferSize], AvailableSamples);
checkError();
getLogger()->logDebug("AudioCapture", "Captured %i bytes of audio data.", availbuffersize);
}
}
}
Mutex.unlock();
}
bool cAudioCapture::beginCapture()
{
Mutex.lock();
cAudioMutexBasicLock lock(Mutex);
if(!Capturing)
{
CaptureBuffer.clear();
@ -190,32 +185,31 @@ namespace cAudio
{
alcCaptureStart(CaptureDevice);
Capturing = true;
getLogger()->logDebug("AudioCapture", "OpenAL Capture Started.");
}
Mutex.unlock();
checkError();
return Capturing;
}
else
{
Mutex.unlock();
return false;
}
checkError();
return false;
}
void cAudioCapture::stopCapture()
{
Mutex.lock();
cAudioMutexBasicLock lock(Mutex);
if(CaptureDevice && Ready)
{
alcCaptureStop(CaptureDevice);
updateCaptureBuffer(true);
checkError();
getLogger()->logDebug("AudioCapture", "OpenAL Capture Stopped.");
}
Capturing = false;
Mutex.unlock();
}
unsigned int cAudioCapture::getCapturedAudio(void* outputBuffer, unsigned int outputBufferSize)
{
Mutex.lock();
cAudioMutexBasicLock lock(Mutex);
unsigned int internalBufferSize = CaptureBuffer.size();
if(outputBuffer && outputBufferSize > 0 && internalBufferSize > 0)
{
@ -223,34 +217,30 @@ namespace cAudio
memcpy(outputBuffer, &CaptureBuffer[0], sizeToCopy);
CaptureBuffer.erase(CaptureBuffer.begin(), CaptureBuffer.begin()+sizeToCopy);
Mutex.unlock();
getLogger()->logDebug("AudioCapture", "Copied out %i bytes of data out of %i bytes in the buffer at user request.", sizeToCopy, internalBufferSize);
return sizeToCopy;
}
Mutex.unlock();
return 0;
}
unsigned int cAudioCapture::getCurrentCapturedAudioSize()
{
Mutex.lock();
unsigned int size = CaptureBuffer.size();
Mutex.unlock();
return size;
cAudioMutexBasicLock lock(Mutex);
return CaptureBuffer.size();
}
bool cAudioCapture::setFrequency(unsigned int frequency)
{
Mutex.lock();
cAudioMutexBasicLock lock(Mutex);
Frequency = frequency;
shutdownOpenALDevice();
bool state = initOpenALDevice();
Mutex.unlock();
return state;
return initOpenALDevice();
}
bool cAudioCapture::setFormat(AudioFormats format)
{
Mutex.lock();
cAudioMutexBasicLock lock(Mutex);
Format = format;
if(Format == EAF_8BIT_MONO)
SampleSize = 1;
@ -262,36 +252,30 @@ namespace cAudio
SampleSize = 4;
shutdownOpenALDevice();
bool state = initOpenALDevice();
Mutex.unlock();
return state;
return initOpenALDevice();
}
bool cAudioCapture::setInternalBufferSize(unsigned int internalBufferSize)
{
Mutex.lock();
cAudioMutexBasicLock lock(Mutex);
InternalBufferSize = internalBufferSize;
shutdownOpenALDevice();
bool state = initOpenALDevice();
Mutex.unlock();
return state;
return initOpenALDevice();
}
bool cAudioCapture::setDevice(const char* deviceName)
{
Mutex.lock();
cAudioMutexBasicLock lock(Mutex);
DeviceName = safeCStr(deviceName);
shutdownOpenALDevice();
bool state = initOpenALDevice();
Mutex.unlock();
return state;
return initOpenALDevice();
}
bool cAudioCapture::initialize(const char* deviceName, unsigned int frequency, AudioFormats format, unsigned int internalBufferSize)
{
Mutex.lock();
cAudioMutexBasicLock lock(Mutex);
DeviceName = safeCStr(deviceName);
Frequency = frequency;
InternalBufferSize = internalBufferSize;
@ -307,9 +291,39 @@ namespace cAudio
SampleSize = 4;
shutdownOpenALDevice();
bool state = initOpenALDevice();
Mutex.unlock();
return state;
return initOpenALDevice();
}
bool cAudioCapture::checkError()
{
if(CaptureDevice)
{
int error = alcGetError(CaptureDevice);
if (error != AL_NO_ERROR)
{
const char* errorString = alGetString(error);
getLogger()->logError("AudioCapture", "OpenAL Error: %s.", errorString);
return true;
}
}
return false;
}
ALenum cAudioCapture::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;
};
}
CAUDIO_API IAudioCapture* createAudioCapture(bool initializeDefault)

166
Source/cAudioEffects.cpp Normal file
View File

@ -0,0 +1,166 @@
#include "../Headers/cAudioEffects.h"
#include "../Headers/cFilter.h"
#include "../Headers/cEffect.h"
//Number of effect slots to try to create
#define EFFECT_SLOTS_TO_TEST 256
namespace cAudio
{
cAudioEffects::cAudioEffects() : MaxEffectsSupported(0)
{
for(int i=0; i<EET_COUNT; ++i)
SupportedEffects[i] = false;
for(int i=0; i<EFT_COUNT; ++i)
SupportedFilters[i] = false;
}
cAudioEffects::~cAudioEffects()
{
}
IEffect* cAudioEffects::createEffect()
{
cAudioMutexBasicLock lock(Mutex);
IEffect* effect = new cEffect(&EFXInterface);
if(effect && effect->isValid())
return effect;
return NULL;
}
IFilter* cAudioEffects::createFilter()
{
cAudioMutexBasicLock lock(Mutex);
IFilter* filter = new cFilter(&EFXInterface);
if(filter && filter->isValid())
return filter;
return NULL;
}
unsigned int cAudioEffects::getMaxEffectsSupported() const
{
return MaxEffectsSupported;
}
bool cAudioEffects::isEffectSupported(const EffectTypes& type) const
{
return SupportedEffects[type];
}
bool cAudioEffects::isFilterSupported(const FilterTypes& type) const
{
return SupportedFilters[type];
}
cEFXFunctions* cAudioEffects::getEFXInterface()
{
return &EFXInterface;
}
void cAudioEffects::checkEFXSupportDetails()
{
cAudioMutexBasicLock lock(Mutex);
if(EFXInterface.Supported)
{
cAudioMutexBasicLock lock(EFXInterface.Mutex);
//Count the number of effect slots this device supports (limits the max number of effects available)
unsigned int count = 0;
ALuint effectSlots[EFFECT_SLOTS_TO_TEST];
for(count=0; count<EFFECT_SLOTS_TO_TEST; ++count)
{
EFXInterface.alGenAuxiliaryEffectSlots(1, &effectSlots[count]);
if(alGetError() != AL_NO_ERROR)
break;
}
MaxEffectsSupported = count;
//Check what effects are supported
ALuint Effect;
EFXInterface.alGenEffects(1, &Effect);
if (alGetError() == AL_NO_ERROR)
{
SupportedEffects[EET_NULL] = true;
// Try setting Effect Type to known Effects
EFXInterface.alEffecti(Effect, AL_EFFECT_TYPE, AL_EFFECT_REVERB);
SupportedEffects[EET_REVERB] = (alGetError() == AL_NO_ERROR);
EFXInterface.alEffecti(Effect, AL_EFFECT_TYPE, AL_EFFECT_EAXREVERB);
SupportedEffects[EET_EAX_REVERB] = (alGetError() == AL_NO_ERROR);
EFXInterface.alEffecti(Effect, AL_EFFECT_TYPE, AL_EFFECT_CHORUS);
SupportedEffects[EET_CHORUS] = (alGetError() == AL_NO_ERROR);
EFXInterface.alEffecti(Effect, AL_EFFECT_TYPE, AL_EFFECT_DISTORTION);
SupportedEffects[EET_DISTORTION] = (alGetError() == AL_NO_ERROR);
EFXInterface.alEffecti(Effect, AL_EFFECT_TYPE, AL_EFFECT_ECHO);
SupportedEffects[EET_ECHO] = (alGetError() == AL_NO_ERROR);
EFXInterface.alEffecti(Effect, AL_EFFECT_TYPE, AL_EFFECT_FLANGER);
SupportedEffects[EET_FLANGER] = (alGetError() == AL_NO_ERROR);
EFXInterface.alEffecti(Effect, AL_EFFECT_TYPE, AL_EFFECT_FREQUENCY_SHIFTER);
SupportedEffects[EET_FREQUENCY_SHIFTER] = (alGetError() == AL_NO_ERROR);
EFXInterface.alEffecti(Effect, AL_EFFECT_TYPE, AL_EFFECT_VOCAL_MORPHER);
SupportedEffects[EET_VOCAL_MORPHER] = (alGetError() == AL_NO_ERROR);
EFXInterface.alEffecti(Effect, AL_EFFECT_TYPE, AL_EFFECT_PITCH_SHIFTER);
SupportedEffects[EET_PITCH_SHIFTER] = (alGetError() == AL_NO_ERROR);
EFXInterface.alEffecti(Effect, AL_EFFECT_TYPE, AL_EFFECT_RING_MODULATOR);
SupportedEffects[EET_RING_MODULATOR] = (alGetError() == AL_NO_ERROR);
EFXInterface.alEffecti(Effect, AL_EFFECT_TYPE, AL_EFFECT_AUTOWAH);
SupportedEffects[EET_AUTOWAH] = (alGetError() == AL_NO_ERROR);
EFXInterface.alEffecti(Effect, AL_EFFECT_TYPE, AL_EFFECT_COMPRESSOR);
SupportedEffects[EET_COMPRESSOR] = (alGetError() == AL_NO_ERROR);
EFXInterface.alEffecti(Effect, AL_EFFECT_TYPE, AL_EFFECT_EQUALIZER);
SupportedEffects[EET_EQUALIZER] = (alGetError() == AL_NO_ERROR);
}
// Delete Effect
EFXInterface.alDeleteEffects(1, &Effect);
// Generate a Filter to use to determine what Filter Types are supported
ALuint Filter;
EFXInterface.alGenFilters(1, &Filter);
if (alGetError() == AL_NO_ERROR)
{
SupportedFilters[EFT_NULL] = true;
// Try setting the Filter type to known Filters
EFXInterface.alFilteri(Filter, AL_FILTER_TYPE, AL_FILTER_LOWPASS);
SupportedFilters[EFT_LOWPASS] = (alGetError() == AL_NO_ERROR);
EFXInterface.alFilteri(Filter, AL_FILTER_TYPE, AL_FILTER_HIGHPASS);
SupportedFilters[EFT_HIGHPASS] = (alGetError() == AL_NO_ERROR);
EFXInterface.alFilteri(Filter, AL_FILTER_TYPE, AL_FILTER_BANDPASS);
SupportedFilters[EFT_BANDPASS] = (alGetError() == AL_NO_ERROR);
}
// Delete Filter
EFXInterface.alDeleteFilters(1, &Filter);
//Cleanup the slots we created
while(count > 0)
{
EFXInterface.alDeleteAuxiliaryEffectSlots(1, &effectSlots[--count]);
}
}
}
};

View File

@ -11,10 +11,6 @@
#include <set>
#include <AL/efx.h>
#include <AL/efx-creative.h>
#include <AL/xram.h>
#define LOAD_AL_FUNC(x) (x = (typeof(x))alGetProcAddress(#x))
namespace cAudio
@ -59,7 +55,7 @@ namespace cAudio
cAudioMutexBasicLock lock(Mutex);
if(Initialized)
shutDown();
return false;
//Stores the context attributes (MAX of 4, with 2 zeros to terminate)
ALint attribs[6] = { 0 };
@ -86,10 +82,6 @@ namespace cAudio
return false;
}
#ifdef CAUDIO_EAX_ENABLED
EFXSupported = (alcIsExtensionPresent(Device, "ALC_EXT_EFX") == AL_TRUE);
#endif
Context = alcCreateContext(Device, attribs);
if (Context == NULL)
{
@ -111,10 +103,17 @@ namespace cAudio
return false;
}
#ifdef CAUDIO_EFX_ENABLED
initEffects.getEFXInterface()->Mutex.lock();
EFXSupported = initEffects.getEFXInterface()->CheckEFXSupport(Device);
initEffects.getEFXInterface()->Mutex.unlock();
initEffects.checkEFXSupportDetails();
#endif
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));
#ifdef CAUDIO_EAX_ENABLED
#ifdef CAUDIO_EFX_ENABLED
if(EFXSupported)
{
int EFXMajorVersion = 0;
@ -170,7 +169,7 @@ namespace cAudio
{
if(decoder->isValid())
{
IAudio* audio = new cAudio(decoder);
IAudio* audio = new cAudio(decoder, Context, initEffects.getEFXInterface());
decoder->drop();
if(audio)
@ -262,7 +261,7 @@ namespace cAudio
{
if(decoder->isValid())
{
IAudio* audio = new cAudio(decoder);
IAudio* audio = new cAudio(decoder, Context, initEffects.getEFXInterface());
decoder->drop();
if(audio)
@ -322,7 +321,7 @@ namespace cAudio
{
if(decoder->isValid())
{
IAudio* audio = new cAudio(decoder);
IAudio* audio = new cAudio(decoder, Context, initEffects.getEFXInterface());
decoder->drop();
if(audio)
@ -469,7 +468,7 @@ namespace cAudio
}
}
void cAudioManager::checkError()
bool cAudioManager::checkError()
{
int error = alGetError();
const char* errorString;
@ -478,6 +477,7 @@ namespace cAudio
{
errorString = alGetString(error);
getLogger()->logError("AudioManager", "OpenAL Error: %s.", errorString);
return true;
}
if(Device)
@ -487,8 +487,10 @@ namespace cAudio
{
errorString = alGetString(error);
getLogger()->logError("AudioManager", "OpenAL Error: %s.", errorString);
return true;
}
}
return false;
}
void cAudioManager::getAvailableDevices()

697
Source/cEffect.cpp Normal file
View File

@ -0,0 +1,697 @@
#include "../Headers/cEffect.h"
#include "../Headers/cLogger.h"
#include "../Headers/cUtils.h"
namespace cAudio
{
cEffect::cEffect(cEFXFunctions* oALFunctions) : EFX(oALFunctions), Type(EET_NULL),
Volume(1.0f), IgnoreAttenuation(false), LastUpdated(0), Valid(false), Filter(NULL),
Effect(0), EffectSlot(0)
{
cAudioMutexBasicLock lock(Mutex);
if(EFX)
{
if(EFX->Supported)
{
cAudioMutexBasicLock lock(EFX->Mutex);
//Create Effect Slot
EFX->alGenAuxiliaryEffectSlots(1, &EffectSlot);
bool error = CheckError();
if(error)
{
EffectSlot = 0;
return;
}
//Create the effect object
EFX->alGenEffects(1, &Effect);
error = CheckError();
if(error)
{
EFX->alDeleteAuxiliaryEffectSlots(1, &EffectSlot);
EffectSlot = 0;
Effect = 0;
return;
}
//Bind the effect to the effect slot
EFX->alAuxiliaryEffectSloti(EffectSlot, AL_EFFECTSLOT_EFFECT, Effect);
error = CheckError();
if(error)
{
EFX->alDeleteEffects(1, &Effect);
EFX->alDeleteAuxiliaryEffectSlots(1, &EffectSlot);
EffectSlot = 0;
Effect = 0;
return;
}
//Everything worked, effect is ready to use
Valid = true;
}
}
}
cEffect::~cEffect()
{
cAudioMutexBasicLock lock(Mutex);
if(EFX && EFX->Supported)
{
cAudioMutexBasicLock lock(EFX->Mutex);
EFX->alAuxiliaryEffectSloti(EffectSlot, AL_EFFECTSLOT_EFFECT, AL_EFFECT_NULL);
if(Effect)
{
EFX->alDeleteEffects(1, &Effect);
}
if(EffectSlot)
{
EFX->alDeleteAuxiliaryEffectSlots(1, &EffectSlot);
}
}
}
const EffectTypes& cEffect::getType() const
{
return Type;
}
void cEffect::setType(const EffectTypes& type)
{
cAudioMutexBasicLock lock(Mutex);
Type = type;
UpdateEffect();
}
const sEAXReverbParameters& cEffect::getEAXReverbParameters() const
{
return EAXReverbParam;
}
void cEffect::setEAXReverbParameters(const sEAXReverbParameters& param)
{
cAudioMutexBasicLock lock(Mutex);
EAXReverbParam = param;
UpdateEffect();
}
const sReverbParameters& cEffect::getReverbParameters() const
{
return ReverbParam;
}
void cEffect::setReverbParameters(const sReverbParameters& param)
{
cAudioMutexBasicLock lock(Mutex);
ReverbParam = param;
UpdateEffect();
}
const sChorusParameters& cEffect::getChorusParameters() const
{
return ChorusParam;
}
void cEffect::setChorusParameters(const sChorusParameters& param)
{
cAudioMutexBasicLock lock(Mutex);
ChorusParam = param;
UpdateEffect();
}
const sDistortionParameters& cEffect::getDistortionParameters() const
{
return DistortionParam;
}
void cEffect::setDistortionParameters(const sDistortionParameters& param)
{
cAudioMutexBasicLock lock(Mutex);
DistortionParam = param;
UpdateEffect();
}
const sEchoParameters& cEffect::getEchoParameters() const
{
return EchoParam;
}
void cEffect::setEchoParameters(const sEchoParameters& param)
{
cAudioMutexBasicLock lock(Mutex);
EchoParam = param;
UpdateEffect();
}
const sFlangerParameters& cEffect::getFlangerParameters() const
{
return FlangerParam;
}
void cEffect::setFlangerParameters(const sFlangerParameters& param)
{
cAudioMutexBasicLock lock(Mutex);
FlangerParam = param;
UpdateEffect();
}
const sFrequencyShiftParameters& cEffect::getFrequencyShiftParameters() const
{
return FrequencyShiftParam;
}
void cEffect::setFrequencyShiftParameters(const sFrequencyShiftParameters& param)
{
cAudioMutexBasicLock lock(Mutex);
FrequencyShiftParam = param;
UpdateEffect();
}
const sVocalMorpherParameters& cEffect::getVocalMorpherParameters() const
{
return VocalMorpherParam;
}
void cEffect::setVocalMorpherParameters(const sVocalMorpherParameters& param)
{
cAudioMutexBasicLock lock(Mutex);
VocalMorpherParam = param;
UpdateEffect();
}
const sPitchShifterParameters& cEffect::getPitchShifterParameters() const
{
return PitchShifterParam;
}
void cEffect::setPitchShifterParameters(const sPitchShifterParameters& param)
{
cAudioMutexBasicLock lock(Mutex);
PitchShifterParam = param;
UpdateEffect();
}
const sRingModulatorParameters& cEffect::getRingModulatorParameters() const
{
return RingModulatorParam;
}
void cEffect::setRingModulatorParameters(const sRingModulatorParameters& param)
{
cAudioMutexBasicLock lock(Mutex);
RingModulatorParam = param;
UpdateEffect();
}
const sAutowahParameters& cEffect::getAutowahParameters() const
{
return AutowahParam;
}
void cEffect::setAutowahParameters(const sAutowahParameters& param)
{
cAudioMutexBasicLock lock(Mutex);
AutowahParam = param;
UpdateEffect();
}
const sCompressorParameters& cEffect::getCompressorParameters() const
{
return CompressorParam;
}
void cEffect::setCompressorParameters(const sCompressorParameters& param)
{
cAudioMutexBasicLock lock(Mutex);
CompressorParam = param;
UpdateEffect();
}
const sEqualizerParameters& cEffect::getEqualizerParameters() const
{
return EqualizerParam;
}
void cEffect::setEqualizerParameters(const sEqualizerParameters& param)
{
cAudioMutexBasicLock lock(Mutex);
EqualizerParam = param;
UpdateEffect();
}
float cEffect::getMasterVolume() const
{
return Volume;
}
void cEffect::setMasterVolume(const float& volume)
{
cAudioMutexBasicLock lock(Mutex);
Volume = volume;
UpdateEffect();
}
bool cEffect::isIgnoringAttenuation() const
{
return IgnoreAttenuation;
}
void cEffect::ignoreAttenuation(const bool& ignore)
{
cAudioMutexBasicLock lock(Mutex);
IgnoreAttenuation = ignore;
UpdateEffect();
}
IFilter* cEffect::getFilter() const
{
return Filter;
}
void cEffect::attachFilter(IFilter* filter)
{
cAudioMutexBasicLock lock(Mutex);
Filter = filter;
if(Filter)
Filter->grab();
UpdateEffect();
}
void cEffect::removeFilter()
{
cAudioMutexBasicLock lock(Mutex);
if(Filter)
Filter->drop();
Filter = NULL;
}
unsigned int cEffect::getLastUpdated() const
{
return LastUpdated;
}
bool cEffect::isValid() const
{
return Valid;
}
ALuint cEffect::getOpenALEffect() const
{
return Effect;
}
ALuint cEffect::getOpenALEffectSlot() const
{
return EffectSlot;
}
bool cEffect::UpdateEffect()
{
++LastUpdated;
ALenum alEffectType = ConvertEffectEnum(Type);
if(EFX && EFX->Supported && EffectSlot && Effect)
{
cAudioMutexBasicLock lock(EFX->Mutex);
EFX->alEffecti(Effect, AL_EFFECT_TYPE, alEffectType);
Valid = !CheckError();
if(!Valid)
return false;
EFX->alAuxiliaryEffectSlotf(EffectSlot, AL_EFFECTSLOT_GAIN, Volume);
Valid = !CheckError();
if(!Valid)
return false;
EFX->alAuxiliaryEffectSloti(EffectSlot, AL_EFFECTSLOT_AUXILIARY_SEND_AUTO, IgnoreAttenuation ? AL_TRUE : AL_FALSE);
Valid = !CheckError();
if(!Valid)
return false;
if(Type == EET_EAX_REVERB)
{
EFX->alEffectf(Effect, AL_EAXREVERB_DENSITY, EAXReverbParam.Density);
EFX->alEffectf(Effect, AL_EAXREVERB_DIFFUSION, EAXReverbParam.Diffusion);
EFX->alEffectf(Effect, AL_EAXREVERB_GAIN, EAXReverbParam.Gain);
EFX->alEffectf(Effect, AL_EAXREVERB_GAINHF, EAXReverbParam.GainHF);
EFX->alEffectf(Effect, AL_EAXREVERB_GAINLF, EAXReverbParam.GainLF);
EFX->alEffectf(Effect, AL_EAXREVERB_DECAY_TIME, EAXReverbParam.DecayTime);
EFX->alEffectf(Effect, AL_EAXREVERB_DECAY_HFRATIO, EAXReverbParam.DecayHFRatio);
EFX->alEffectf(Effect, AL_EAXREVERB_DECAY_LFRATIO, EAXReverbParam.DecayLFRatio);
EFX->alEffectf(Effect, AL_EAXREVERB_REFLECTIONS_GAIN, EAXReverbParam.ReflectionsGain);
EFX->alEffectf(Effect, AL_EAXREVERB_REFLECTIONS_DELAY, EAXReverbParam.ReflectionsDelay);
EFX->alEffectfv(Effect, AL_EAXREVERB_REFLECTIONS_PAN, &EAXReverbParam.ReflectionsPan.x);
EFX->alEffectf(Effect, AL_EAXREVERB_LATE_REVERB_GAIN, EAXReverbParam.LateReverbGain);
EFX->alEffectf(Effect, AL_EAXREVERB_LATE_REVERB_DELAY, EAXReverbParam.LateReverbDelay);
EFX->alEffectfv(Effect, AL_EAXREVERB_LATE_REVERB_PAN, &EAXReverbParam.LateReverbPan.x);
EFX->alEffectf(Effect, AL_EAXREVERB_ECHO_TIME, EAXReverbParam.EchoTime);
EFX->alEffectf(Effect, AL_EAXREVERB_ECHO_DEPTH, EAXReverbParam.EchoDepth);
EFX->alEffectf(Effect, AL_EAXREVERB_MODULATION_TIME, EAXReverbParam.ModulationTime);
EFX->alEffectf(Effect, AL_EAXREVERB_MODULATION_DEPTH, EAXReverbParam.ModulationDepth);
EFX->alEffectf(Effect, AL_EAXREVERB_HFREFERENCE, EAXReverbParam.HFReference);
EFX->alEffectf(Effect, AL_EAXREVERB_LFREFERENCE, EAXReverbParam.LFReference);
EFX->alEffectf(Effect, AL_EAXREVERB_ROOM_ROLLOFF_FACTOR, EAXReverbParam.RoomRolloffFactor);
EFX->alEffectf(Effect, AL_EAXREVERB_AIR_ABSORPTION_GAINHF, EAXReverbParam.AirAbsorptionGainHF);
EFX->alEffecti(Effect, AL_EAXREVERB_DECAY_HFLIMIT, EAXReverbParam.DecayHFLimit ? AL_TRUE : AL_FALSE);
Valid = !CheckError();
return Valid;
}
else if(Type == EET_REVERB)
{
EFX->alEffectf(Effect, AL_REVERB_DENSITY, ReverbParam.Density);
EFX->alEffectf(Effect, AL_REVERB_DIFFUSION, ReverbParam.Diffusion);
EFX->alEffectf(Effect, AL_REVERB_GAIN, ReverbParam.Gain);
EFX->alEffectf(Effect, AL_REVERB_GAINHF, ReverbParam.GainHF);
EFX->alEffectf(Effect, AL_REVERB_DECAY_TIME, ReverbParam.DecayTime);
EFX->alEffectf(Effect, AL_REVERB_DECAY_HFRATIO, ReverbParam.DecayHFRatio);
EFX->alEffectf(Effect, AL_REVERB_REFLECTIONS_GAIN, ReverbParam.ReflectionsGain);
EFX->alEffectf(Effect, AL_REVERB_REFLECTIONS_DELAY, ReverbParam.ReflectionsDelay);
EFX->alEffectf(Effect, AL_REVERB_LATE_REVERB_GAIN, ReverbParam.LateReverbGain);
EFX->alEffectf(Effect, AL_REVERB_LATE_REVERB_DELAY, ReverbParam.LateReverbDelay);
EFX->alEffectf(Effect, AL_REVERB_ROOM_ROLLOFF_FACTOR, ReverbParam.RoomRolloffFactor);
EFX->alEffectf(Effect, AL_REVERB_AIR_ABSORPTION_GAINHF, ReverbParam.AirAbsorptionGainHF);
EFX->alEffecti(Effect, AL_REVERB_DECAY_HFLIMIT, ReverbParam.DecayHFLimit ? AL_TRUE : AL_FALSE);
Valid = !CheckError();
return Valid;
}
else if(Type == EET_CHORUS)
{
ALenum waveform = AL_CHORUS_DEFAULT_WAVEFORM;
switch(ChorusParam.Waveform)
{
case sChorusParameters::ECW_SINUSOID:
waveform = AL_CHORUS_WAVEFORM_SINUSOID;
break;
case sChorusParameters::ECW_TRIANGLE:
waveform = AL_CHORUS_WAVEFORM_TRIANGLE;
break;
default:
waveform = AL_CHORUS_DEFAULT_WAVEFORM;
break;
};
EFX->alEffecti(Effect, AL_CHORUS_WAVEFORM, waveform);
EFX->alEffecti(Effect, AL_CHORUS_PHASE, ChorusParam.Phase);
EFX->alEffectf(Effect, AL_CHORUS_RATE, ChorusParam.Rate);
EFX->alEffectf(Effect, AL_CHORUS_DEPTH, ChorusParam.Depth);
EFX->alEffectf(Effect, AL_CHORUS_FEEDBACK, ChorusParam.Feedback);
EFX->alEffectf(Effect, AL_CHORUS_DELAY, ChorusParam.Delay);
Valid = !CheckError();
return Valid;
}
else if(Type == EET_DISTORTION)
{
EFX->alEffectf(Effect, AL_DISTORTION_EDGE, DistortionParam.Edge);
EFX->alEffectf(Effect, AL_DISTORTION_GAIN, DistortionParam.Gain);
EFX->alEffectf(Effect, AL_DISTORTION_LOWPASS_CUTOFF, DistortionParam.LowpassCutoff);
EFX->alEffectf(Effect, AL_DISTORTION_EQCENTER, DistortionParam.EqCenter);
EFX->alEffectf(Effect, AL_DISTORTION_EQBANDWIDTH, DistortionParam.EqBandwidth);
Valid = !CheckError();
return Valid;
}
else if(Type == EET_ECHO)
{
EFX->alEffectf(Effect, AL_ECHO_DELAY, EchoParam.Delay);
EFX->alEffectf(Effect, AL_ECHO_LRDELAY, EchoParam.LRDelay);
EFX->alEffectf(Effect, AL_ECHO_DAMPING, EchoParam.Damping);
EFX->alEffectf(Effect, AL_ECHO_FEEDBACK, EchoParam.Feedback);
EFX->alEffectf(Effect, AL_ECHO_SPREAD, EchoParam.Spread);
Valid = !CheckError();
return Valid;
}
else if(Type == EET_FLANGER)
{
ALenum waveform = AL_FLANGER_DEFAULT_WAVEFORM;
switch(FlangerParam.Waveform)
{
case sFlangerParameters::EFW_SINUSOID:
waveform = AL_FLANGER_WAVEFORM_SINUSOID;
break;
case sFlangerParameters::EFW_TRIANGLE:
waveform = AL_FLANGER_WAVEFORM_SINUSOID;
break;
default:
waveform = AL_FLANGER_DEFAULT_WAVEFORM;
break;
};
EFX->alEffecti(Effect, AL_FLANGER_WAVEFORM, waveform);
EFX->alEffecti(Effect, AL_FLANGER_PHASE, FlangerParam.Phase);
EFX->alEffectf(Effect, AL_FLANGER_RATE, FlangerParam.Rate);
EFX->alEffectf(Effect, AL_FLANGER_DEPTH, FlangerParam.Depth);
EFX->alEffectf(Effect, AL_FLANGER_FEEDBACK, FlangerParam.Feedback);
EFX->alEffectf(Effect, AL_FLANGER_DELAY, FlangerParam.Delay);
Valid = !CheckError();
return Valid;
}
else if(Type == EET_FREQUENCY_SHIFTER)
{
ALenum shiftleft = ConvertFrequencyShiftEnum(FrequencyShiftParam.Left);
ALenum shiftright = ConvertFrequencyShiftEnum(FrequencyShiftParam.Right);
EFX->alEffectf(Effect, AL_FREQUENCY_SHIFTER_FREQUENCY, FrequencyShiftParam.Frequency);
EFX->alEffecti(Effect, AL_FREQUENCY_SHIFTER_LEFT_DIRECTION, shiftleft);
EFX->alEffecti(Effect, AL_FREQUENCY_SHIFTER_RIGHT_DIRECTION, shiftright);
Valid = !CheckError();
return Valid;
}
else if(Type == EET_VOCAL_MORPHER)
{
ALenum pA = ConvertVocalMorphPhonemeEnum(VocalMorpherParam.PhonemeA);
ALenum pB = ConvertVocalMorphPhonemeEnum(VocalMorpherParam.PhonemeB);
ALenum waveform = AL_VOCAL_MORPHER_DEFAULT_WAVEFORM;
switch(VocalMorpherParam.Waveform)
{
case sVocalMorpherParameters::EMW_SINUSOID:
waveform = AL_VOCAL_MORPHER_WAVEFORM_SINUSOID;
break;
case sVocalMorpherParameters::EMW_TRIANGLE:
waveform = AL_VOCAL_MORPHER_WAVEFORM_TRIANGLE;
break;
case sVocalMorpherParameters::EMW_SAW:
waveform = AL_VOCAL_MORPHER_WAVEFORM_SAWTOOTH;
break;
default:
waveform = AL_VOCAL_MORPHER_DEFAULT_WAVEFORM;
break;
};
EFX->alEffecti(Effect, AL_VOCAL_MORPHER_PHONEMEA, pA);
EFX->alEffecti(Effect, AL_VOCAL_MORPHER_PHONEMEB, pB);
EFX->alEffecti(Effect, AL_VOCAL_MORPHER_PHONEMEA_COARSE_TUNING, VocalMorpherParam.PhonemeACoarseTune);
EFX->alEffecti(Effect, AL_VOCAL_MORPHER_PHONEMEB_COARSE_TUNING, VocalMorpherParam.PhonemeBCoarseTune);
EFX->alEffecti(Effect, AL_VOCAL_MORPHER_WAVEFORM, waveform);
EFX->alEffectf(Effect, AL_VOCAL_MORPHER_RATE, VocalMorpherParam.Rate);
Valid = !CheckError();
return Valid;
}
else if(Type == EET_PITCH_SHIFTER)
{
EFX->alEffecti(Effect, AL_PITCH_SHIFTER_COARSE_TUNE, PitchShifterParam.CoarseTune);
EFX->alEffecti(Effect, AL_PITCH_SHIFTER_FINE_TUNE, PitchShifterParam.FineTune);
Valid = !CheckError();
return Valid;
}
else if(Type == EET_RING_MODULATOR)
{
ALenum waveform = AL_RING_MODULATOR_DEFAULT_WAVEFORM;
switch(RingModulatorParam.Waveform)
{
case sRingModulatorParameters::EMW_SINUSOID:
waveform = AL_RING_MODULATOR_SINUSOID;
break;
case sRingModulatorParameters::EMW_SAW:
waveform = AL_RING_MODULATOR_SAWTOOTH;
break;
case sRingModulatorParameters::EMW_SQUARE:
waveform = AL_RING_MODULATOR_SQUARE;
break;
default:
waveform = AL_RING_MODULATOR_DEFAULT_WAVEFORM;
break;
};
EFX->alEffectf(Effect, AL_RING_MODULATOR_FREQUENCY, RingModulatorParam.Frequency);
EFX->alEffectf(Effect, AL_RING_MODULATOR_HIGHPASS_CUTOFF, RingModulatorParam.HighPassCutoff);
EFX->alEffecti(Effect, AL_RING_MODULATOR_WAVEFORM, waveform);
Valid = !CheckError();
return Valid;
}
else if(Type == EET_AUTOWAH)
{
EFX->alEffectf(Effect, AL_AUTOWAH_ATTACK_TIME, AutowahParam.AttackTime);
EFX->alEffectf(Effect, AL_AUTOWAH_RELEASE_TIME, AutowahParam.ReleaseTime);
EFX->alEffectf(Effect, AL_AUTOWAH_RESONANCE, AutowahParam.Resonance);
EFX->alEffectf(Effect, AL_AUTOWAH_PEAK_GAIN, AutowahParam.PeakGain);
Valid = !CheckError();
return Valid;
}
else if(Type == EET_COMPRESSOR)
{
EFX->alEffecti(Effect, AL_COMPRESSOR_ONOFF, CompressorParam.Active ? AL_TRUE : AL_FALSE);
Valid = !CheckError();
return Valid;
}
else if(Type == EET_EQUALIZER)
{
EFX->alEffectf(Effect, AL_EQUALIZER_LOW_GAIN, EqualizerParam.LowGain);
EFX->alEffectf(Effect, AL_EQUALIZER_LOW_CUTOFF, EqualizerParam.LowCutoff);
EFX->alEffectf(Effect, AL_EQUALIZER_MID1_GAIN, EqualizerParam.Mid1Gain);
EFX->alEffectf(Effect, AL_EQUALIZER_MID1_CENTER, EqualizerParam.Mid1Center);
EFX->alEffectf(Effect, AL_EQUALIZER_MID1_WIDTH, EqualizerParam.Mid1Width);
EFX->alEffectf(Effect, AL_EQUALIZER_MID2_GAIN, EqualizerParam.Mid2Gain);
EFX->alEffectf(Effect, AL_EQUALIZER_MID2_CENTER, EqualizerParam.Mid2Center);
EFX->alEffectf(Effect, AL_EQUALIZER_MID2_WIDTH, EqualizerParam.Mid2Width);
EFX->alEffectf(Effect, AL_EQUALIZER_HIGH_GAIN, EqualizerParam.HighGain);
EFX->alEffectf(Effect, AL_EQUALIZER_HIGH_CUTOFF, EqualizerParam.HighCutoff);
Valid = !CheckError();
return Valid;
}
else
{
return true;
}
}
return false;
}
bool cEffect::CheckError()
{
int error = alGetError();
const char* errorString;
if (error != AL_NO_ERROR)
{
errorString = alGetString(error);
if(error == AL_OUT_OF_MEMORY)
getLogger()->logCritical("Audio Effect", "OpenAL Error: %s.", errorString);
else
getLogger()->logError("Audio Effect", "OpenAL Error: %s.", errorString);
return true;
}
return false;
}
ALenum cEffect::ConvertEffectEnum(EffectTypes type)
{
switch(type)
{
case EET_NULL:
return AL_EFFECT_NULL;
case EET_EAX_REVERB:
return AL_EFFECT_EAXREVERB;
case EET_REVERB:
return AL_EFFECT_REVERB;
case EET_CHORUS:
return AL_EFFECT_CHORUS;
case EET_DISTORTION:
return AL_EFFECT_DISTORTION;
case EET_ECHO:
return AL_EFFECT_ECHO;
case EET_FLANGER:
return AL_EFFECT_FLANGER;
case EET_FREQUENCY_SHIFTER:
return AL_EFFECT_FREQUENCY_SHIFTER;
case EET_VOCAL_MORPHER:
return AL_EFFECT_VOCAL_MORPHER;
case EET_PITCH_SHIFTER:
return AL_EFFECT_PITCH_SHIFTER;
case EET_RING_MODULATOR:
return AL_EFFECT_RING_MODULATOR;
case EET_AUTOWAH:
return AL_EFFECT_AUTOWAH;
case EET_COMPRESSOR:
return AL_EFFECT_COMPRESSOR;
case EET_EQUALIZER:
return AL_EFFECT_EQUALIZER;
default:
return AL_EFFECT_NULL;
};
}
ALenum cEffect::ConvertFrequencyShiftEnum(sFrequencyShiftParameters::ShiftDirection shift)
{
switch(shift)
{
case sFrequencyShiftParameters::ESD_DOWN:
return AL_FREQUENCY_SHIFTER_DIRECTION_DOWN;
case sFrequencyShiftParameters::ESD_UP:
return AL_FREQUENCY_SHIFTER_DIRECTION_UP;
case sFrequencyShiftParameters::ESD_OFF:
return AL_FREQUENCY_SHIFTER_DIRECTION_OFF;
default:
return AL_FREQUENCY_SHIFTER_DIRECTION_DOWN;
};
}
ALenum cEffect::ConvertVocalMorphPhonemeEnum(sVocalMorpherParameters::MorpherPhoneme phoneme)
{
switch(phoneme)
{
case sVocalMorpherParameters::EMP_A:
return AL_VOCAL_MORPHER_PHONEME_A;
case sVocalMorpherParameters::EMP_E:
return AL_VOCAL_MORPHER_PHONEME_E;
case sVocalMorpherParameters::EMP_I:
return AL_VOCAL_MORPHER_PHONEME_I;
case sVocalMorpherParameters::EMP_O:
return AL_VOCAL_MORPHER_PHONEME_O;
case sVocalMorpherParameters::EMP_U:
return AL_VOCAL_MORPHER_PHONEME_U;
case sVocalMorpherParameters::EMP_AA:
return AL_VOCAL_MORPHER_PHONEME_AA;
case sVocalMorpherParameters::EMP_AE:
return AL_VOCAL_MORPHER_PHONEME_AE;
case sVocalMorpherParameters::EMP_AH:
return AL_VOCAL_MORPHER_PHONEME_AH;
case sVocalMorpherParameters::EMP_AO:
return AL_VOCAL_MORPHER_PHONEME_AO;
case sVocalMorpherParameters::EMP_EH:
return AL_VOCAL_MORPHER_PHONEME_EH;
case sVocalMorpherParameters::EMP_ER:
return AL_VOCAL_MORPHER_PHONEME_ER;
case sVocalMorpherParameters::EMP_IH:
return AL_VOCAL_MORPHER_PHONEME_IH;
case sVocalMorpherParameters::EMP_IY:
return AL_VOCAL_MORPHER_PHONEME_IY;
case sVocalMorpherParameters::EMP_UH:
return AL_VOCAL_MORPHER_PHONEME_UH;
case sVocalMorpherParameters::EMP_UW:
return AL_VOCAL_MORPHER_PHONEME_UW;
case sVocalMorpherParameters::EMP_B:
return AL_VOCAL_MORPHER_PHONEME_B;
case sVocalMorpherParameters::EMP_D:
return AL_VOCAL_MORPHER_PHONEME_D;
case sVocalMorpherParameters::EMP_F:
return AL_VOCAL_MORPHER_PHONEME_F;
case sVocalMorpherParameters::EMP_G:
return AL_VOCAL_MORPHER_PHONEME_G;
case sVocalMorpherParameters::EMP_J:
return AL_VOCAL_MORPHER_PHONEME_J;
case sVocalMorpherParameters::EMP_K:
return AL_VOCAL_MORPHER_PHONEME_K;
case sVocalMorpherParameters::EMP_L:
return AL_VOCAL_MORPHER_PHONEME_L;
case sVocalMorpherParameters::EMP_M:
return AL_VOCAL_MORPHER_PHONEME_M;
case sVocalMorpherParameters::EMP_N:
return AL_VOCAL_MORPHER_PHONEME_N;
case sVocalMorpherParameters::EMP_P:
return AL_VOCAL_MORPHER_PHONEME_P;
case sVocalMorpherParameters::EMP_R:
return AL_VOCAL_MORPHER_PHONEME_R;
case sVocalMorpherParameters::EMP_S:
return AL_VOCAL_MORPHER_PHONEME_S;
case sVocalMorpherParameters::EMP_T:
return AL_VOCAL_MORPHER_PHONEME_T;
case sVocalMorpherParameters::EMP_V:
return AL_VOCAL_MORPHER_PHONEME_V;
case sVocalMorpherParameters::EMP_Z:
return AL_VOCAL_MORPHER_PHONEME_Z;
default:
return AL_VOCAL_MORPHER_DEFAULT_PHONEMEA;
};
}
};

175
Source/cFilter.cpp Normal file
View File

@ -0,0 +1,175 @@
#include "../Headers/cFilter.h"
#include "../Headers/cLogger.h"
#include "../Headers/cUtils.h"
namespace cAudio
{
cFilter::cFilter(cEFXFunctions* oALFunctions) : EFX(oALFunctions), Type(EFT_NULL),
Volume(1.0f), LowFreqVolume(1.0f), HighFreqVolume(1.0f), LastUpdated(0),
Valid(false), Filter(0)
{
cAudioMutexBasicLock lock(Mutex);
if(EFX)
Valid = EFX->Supported;
if(Valid)
{
cAudioMutexBasicLock lock(EFX->Mutex);
EFX->alGenFilters(1, &Filter);
Valid = !CheckError();
if(!Valid)
Filter = 0;
}
}
cFilter::~cFilter()
{
cAudioMutexBasicLock lock(Mutex);
if(Filter && EFX && EFX->Supported)
{
cAudioMutexBasicLock lock(EFX->Mutex);
EFX->alDeleteFilters(1, &Filter);
}
}
const FilterTypes& cFilter::getType() const
{
return Type;
}
void cFilter::setType(const FilterTypes& type)
{
cAudioMutexBasicLock lock(Mutex);
Type = type;
UpdateFilter();
}
float cFilter::getVolume() const
{
return Volume;
}
void cFilter::setVolume(const float& volume)
{
cAudioMutexBasicLock lock(Mutex);
Volume = volume;
UpdateFilter();
}
float cFilter::getLowFrequencyVolume() const
{
return LowFreqVolume;
}
void cFilter::setLowFrequencyVolume(const float& volumeLF)
{
cAudioMutexBasicLock lock(Mutex);
LowFreqVolume = volumeLF;
UpdateFilter();
}
float cFilter::getHighFrequencyVolume() const
{
return HighFreqVolume;
}
void cFilter::setHighFrequencyVolume(const float& volumeHF)
{
cAudioMutexBasicLock lock(Mutex);
HighFreqVolume = volumeHF;
UpdateFilter();
}
unsigned int cFilter::getLastUpdated() const
{
return LastUpdated;
}
bool cFilter::isValid() const
{
return Valid;
}
ALuint cFilter::getOpenALFilter() const
{
return Filter;
}
bool cFilter::UpdateFilter()
{
++LastUpdated;
ALenum alFilterType = ConvertFilterEnum(Type);
if(Filter && EFX && EFX->Supported)
{
cAudioMutexBasicLock lock(EFX->Mutex);
EFX->alFilteri(Filter, AL_FILTER_TYPE, alFilterType);
Valid = !CheckError();
if(!Valid)
return false;
if(Type == EFT_LOWPASS)
{
EFX->alFilterf(Filter, AL_LOWPASS_GAIN, Volume);
EFX->alFilterf(Filter, AL_LOWPASS_GAINHF, HighFreqVolume);
Valid = !CheckError();
return Valid;
}
else if(Type == EFT_HIGHPASS)
{
EFX->alFilterf(Filter, AL_HIGHPASS_GAIN, Volume);
EFX->alFilterf(Filter, AL_HIGHPASS_GAINLF, LowFreqVolume);
Valid = !CheckError();
return Valid;
}
else if(Type == EFT_BANDPASS)
{
EFX->alFilterf(Filter, AL_BANDPASS_GAIN, Volume);
EFX->alFilterf(Filter, AL_BANDPASS_GAINLF, LowFreqVolume);
EFX->alFilterf(Filter, AL_BANDPASS_GAINHF, HighFreqVolume);
Valid = !CheckError();
return Valid;
}
else
{
return true;
}
}
return false;
}
bool cFilter::CheckError()
{
int error = alGetError();
const char* errorString;
if (error != AL_NO_ERROR)
{
errorString = alGetString(error);
if(error == AL_OUT_OF_MEMORY)
getLogger()->logCritical("Audio Filter", "OpenAL Error: %s.", errorString);
else
getLogger()->logError("Audio Filter", "OpenAL Error: %s.", errorString);
return true;
}
return false;
}
ALenum cFilter::ConvertFilterEnum(FilterTypes type)
{
switch(type)
{
case EFT_NULL:
return AL_FILTER_NULL;
case EFT_LOWPASS:
return AL_FILTER_LOWPASS;
case EFT_HIGHPASS:
return AL_FILTER_HIGHPASS;
case EFT_BANDPASS:
return AL_FILTER_BANDPASS;
default:
return AL_FILTER_NULL;
};
}
};

View File

@ -1,53 +1,64 @@
#include "../Headers/cListener.h"
#include <AL/al.h>
#include "../Headers/cEFXFunctions.h"
namespace cAudio
{
void cListener::setPosition(const cVector3 pos)
{
Mutex.lock();
cAudioMutexBasicLock lock(Mutex);
Position = pos;
alListener3f(AL_POSITION, Position.x, Position.y, Position.z);
Mutex.unlock();
}
void cListener::setDirection(const cVector3 dir)
{
Mutex.lock();
cAudioMutexBasicLock lock(Mutex);
Direction = dir;
float orient[6] = {Direction[0], Direction[1], Direction[2], UpVector[0], UpVector[1], UpVector[2]};
alListenerfv(AL_ORIENTATION, orient);
Mutex.unlock();
}
void cListener::setUpVector(const cVector3 up)
{
Mutex.lock();
cAudioMutexBasicLock lock(Mutex);
UpVector = up;
float orient[6] = {Direction[0], Direction[1], Direction[2], UpVector[0], UpVector[1], UpVector[2]};
alListenerfv(AL_ORIENTATION, orient);
Mutex.unlock();
}
void cListener::setVelocity(const cVector3 vel)
{
Mutex.lock();
cAudioMutexBasicLock lock(Mutex);
Velocity = vel;
alListener3f(AL_VELOCITY, Velocity.x, Velocity.y, Velocity.z);
Mutex.unlock();
}
void cListener::setMasterVolume(const float volume)
{
Mutex.lock();
cAudioMutexBasicLock lock(Mutex);
MasterGain = volume;
alListenerf(AL_GAIN, MasterGain);
Mutex.unlock();
}
void cListener::move(const cVector3 pos)
{
Mutex.lock();
cAudioMutexBasicLock lock(Mutex);
Velocity = pos - Position;
Position = pos;
alListener3f(AL_POSITION, Position.x, Position.y, Position.z);
alListener3f(AL_VELOCITY, Velocity.x, Velocity.y, Velocity.z);
Mutex.unlock();
}
#ifdef CAUDIO_EFX_ENABLED
//!Sets the meters per user world unit for use with sound effects
void cListener::setMetersPerUnit(const float& meters)
{
cAudioMutexBasicLock lock(Mutex);
alListenerf(AL_METERS_PER_UNIT, meters);
}
//!Returns the meters per user world unit for use with sound effects
float cListener::getMetersPerUnit(void) const
{
float value = 1.0f;
alGetListenerf(AL_METERS_PER_UNIT, &value);
return value;
}
#endif
};

View File

@ -24,8 +24,14 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Tutorial4_AudioCapture", "E
EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Stress_Test", "tests\Stress_Test\Stress_Test.vcproj", "{0E491D8E-6B9E-4107-B50B-EC48CBA3203D}"
ProjectSection(ProjectDependencies) = postProject
{ACD6C202-85D4-44F5-83BF-6577A074F655} = {ACD6C202-85D4-44F5-83BF-6577A074F655}
EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "mp3Decoder", "plugins\mp3Decoder\mp3Decoder.vcproj", "{F1741962-FBBB-4BA2-AC74-A97E2DDF6B2E}"
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Tutorial5_AudioEffects", "Examples\Tutorial5_AudioEffects\Tutorial5_AudioEffects.vcproj", "{EA03D1BB-6D71-4960-958A-670480A8259A}"
ProjectSection(ProjectDependencies) = postProject
{ACD6C202-85D4-44F5-83BF-6577A074F655} = {ACD6C202-85D4-44F5-83BF-6577A074F655}
EndProjectSection
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
@ -57,10 +63,10 @@ Global
{0E491D8E-6B9E-4107-B50B-EC48CBA3203D}.Debug|Win32.Build.0 = Debug|Win32
{0E491D8E-6B9E-4107-B50B-EC48CBA3203D}.Release|Win32.ActiveCfg = Release|Win32
{0E491D8E-6B9E-4107-B50B-EC48CBA3203D}.Release|Win32.Build.0 = Release|Win32
{F1741962-FBBB-4BA2-AC74-A97E2DDF6B2E}.Debug|Win32.ActiveCfg = Debug|Win32
{F1741962-FBBB-4BA2-AC74-A97E2DDF6B2E}.Debug|Win32.Build.0 = Debug|Win32
{F1741962-FBBB-4BA2-AC74-A97E2DDF6B2E}.Release|Win32.ActiveCfg = Release|Win32
{F1741962-FBBB-4BA2-AC74-A97E2DDF6B2E}.Release|Win32.Build.0 = Release|Win32
{EA03D1BB-6D71-4960-958A-670480A8259A}.Debug|Win32.ActiveCfg = Debug|Win32
{EA03D1BB-6D71-4960-958A-670480A8259A}.Debug|Win32.Build.0 = Debug|Win32
{EA03D1BB-6D71-4960-958A-670480A8259A}.Release|Win32.ActiveCfg = Release|Win32
{EA03D1BB-6D71-4960-958A-670480A8259A}.Release|Win32.Build.0 = Release|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE

View File

@ -18,7 +18,7 @@
<Configurations>
<Configuration
Name="Debug|Win32"
OutputDirectory="bin/win32-visual"
OutputDirectory="lib/win32-visual"
IntermediateDirectory="obj/$(ConfigurationName)"
ConfigurationType="2"
UseOfMFC="0"
@ -90,11 +90,12 @@
/>
<Tool
Name="VCPostBuildEventTool"
CommandLine="xcopy &quot;$(TargetPath)&quot; &quot;$(SolutionDir)\bin\win32-visual\&quot; /y"
/>
</Configuration>
<Configuration
Name="Release|Win32"
OutputDirectory="bin/win32-visual"
OutputDirectory="lib/win32-visual"
IntermediateDirectory="obj/$(ConfigurationName)"
ConfigurationType="2"
UseOfMFC="0"
@ -166,6 +167,7 @@
/>
<Tool
Name="VCPostBuildEventTool"
CommandLine="xcopy &quot;$(TargetPath)&quot; &quot;$(SolutionDir)\bin\win32-visual\&quot; /y"
/>
</Configuration>
</Configurations>
@ -185,6 +187,10 @@
RelativePath=".\Headers\cAudioCapture.h"
>
</File>
<File
RelativePath=".\Headers\cAudioEffects.h"
>
</File>
<File
RelativePath=".\Headers\cAudioManager.h"
>
@ -193,10 +199,22 @@
RelativePath=".\Headers\cConsoleLogReceiver.h"
>
</File>
<File
RelativePath=".\Headers\cEffect.h"
>
</File>
<File
RelativePath=".\Headers\cEFXFunctions.h"
>
</File>
<File
RelativePath=".\Headers\cFileSource.h"
>
</File>
<File
RelativePath=".\Headers\cFilter.h"
>
</File>
<File
RelativePath=".\Headers\cListener.h"
>
@ -265,6 +283,10 @@
RelativePath=".\Source\cAudioCapture.cpp"
>
</File>
<File
RelativePath=".\Source\cAudioEffects.cpp"
>
</File>
<File
RelativePath=".\Source\cAudioManager.cpp"
>
@ -277,10 +299,18 @@
RelativePath=".\Source\cConsoleLogReceiver.cpp"
>
</File>
<File
RelativePath=".\Source\cEffect.cpp"
>
</File>
<File
RelativePath=".\Source\cFileSource.cpp"
>
</File>
<File
RelativePath=".\Source\cFilter.cpp"
>
</File>
<File
RelativePath=".\Source\cListener.cpp"
>
@ -357,6 +387,10 @@
RelativePath=".\include\IAudioDecoderFactory.h"
>
</File>
<File
RelativePath=".\include\IAudioEffects.h"
>
</File>
<File
RelativePath=".\include\IAudioManager.h"
>
@ -365,6 +399,18 @@
RelativePath=".\include\IDataSource.h"
>
</File>
<File
RelativePath=".\include\IEffect.h"
>
</File>
<File
RelativePath=".\include\IEffectParameters.h"
>
</File>
<File
RelativePath=".\include\IFilter.h"
>
</File>
<File
RelativePath=".\include\IListener.h"
>

View File

@ -6,10 +6,10 @@ namespace cAudio
enum AudioFormats
{
EAF_8BIT_MONO = 0x1100,
EAF_8BIT_STEREO = 0x1102,
EAF_16BIT_MONO = 0x1101,
EAF_16BIT_STEREO = 0x1103
EAF_8BIT_MONO,
EAF_8BIT_STEREO,
EAF_16BIT_MONO,
EAF_16BIT_STEREO
};
};

View File

@ -1,9 +1,12 @@
#ifndef IAUDIO_H
#define IAUDIO_H
#include "cAudioDefines.h"
#include "IRefCounted.h"
#include "IAudioDecoder.h"
#include "cVector3.h"
#include "IEffect.h"
#include "IFilter.h"
namespace cAudio
{
@ -28,7 +31,8 @@ namespace cAudio
virtual void loop(const bool& toLoop) = 0;
//! Seeks through the audio stream to a specific spot
/** Note: May not be supported by all codecs
\param seconds: Number of seconds from the start of the audio stream to seek to
\param seconds: Number of seconds to seek
\param relative: Whether to seek from the current position or the start of the stream
\return True on success, False if the codec does not support seeking. */
virtual bool seek(const float& seconds, bool relative = false) = 0;
@ -143,6 +147,22 @@ namespace cAudio
//! Returns the override for the doppler velocity vector
virtual const cVector3 getDopplerVelocity() const = 0;
#ifdef CAUDIO_EFX_ENABLED
//! Returns the number of effects at one time this source can support
virtual unsigned int getNumEffectSlotsAvailable() const = 0;
//! Attaches an EFX audio effect to this sound source to a specific slot
//! Range (slot): 0 to getNumEffectSlotsAvailable()
virtual bool attachEffect(unsigned int slot, IEffect* effect) = 0;
//! Removes an EFX audio effect from this sound source
//! Range (slot): 0 to getNumEffectSlotsAvailable()
virtual void removeEffect(unsigned int slot) = 0;
//! Attaches an audio filter to this sound source that will operate on the direct feed, seperate from any effects
virtual bool attachFilter(IFilter* filter) = 0;
//! Removes the previously attached filter
virtual void removeFilter() = 0;
#endif
protected:
private:
};

28
include/IAudioEffects.h Normal file
View File

@ -0,0 +1,28 @@
#ifndef IAUDIOEFFECTS_H
#define IAUDIOEFFECTS_H
#include "IEffect.h"
#include "IFilter.h"
#include "cAudioDefines.h"
namespace cAudio
{
class IAudioEffects
{
public:
IAudioEffects() {}
virtual ~IAudioEffects() {}
virtual IEffect* createEffect() = 0;
virtual IFilter* createFilter() = 0;
virtual unsigned int getMaxEffectsSupported() const = 0;
virtual bool isEffectSupported(const EffectTypes& type) const = 0;
virtual bool isFilterSupported(const FilterTypes& type) const = 0;
protected:
private:
};
};
#endif //! IAUDIOEFFECTS_H

View File

@ -4,6 +4,7 @@
#include "IListener.h"
#include "cAudioDefines.h"
#include "eAudioFormats.h"
#include "IAudioEffects.h"
namespace cAudio
{
@ -55,6 +56,7 @@ namespace cAudio
//!Returns an interface for the listener
virtual IListener* getListener() = 0;
virtual IAudioEffects* getEffects() = 0;
protected:
private:

92
include/IEffect.h Normal file
View File

@ -0,0 +1,92 @@
#ifndef IEFFECT_H
#define IEFFECT_H
#include "IRefCounted.h"
#include "IFilter.h"
#include "IEffectParameters.h"
namespace cAudio
{
enum EffectTypes
{
EET_NULL,
EET_EAX_REVERB,
EET_REVERB,
EET_CHORUS,
EET_DISTORTION,
EET_ECHO,
EET_FLANGER,
EET_FREQUENCY_SHIFTER,
EET_VOCAL_MORPHER,
EET_PITCH_SHIFTER,
EET_RING_MODULATOR,
EET_AUTOWAH,
EET_COMPRESSOR,
EET_EQUALIZER,
EET_COUNT
};
class IEffect : public IRefCounted
{
public:
IEffect() { }
virtual ~IEffect() { }
virtual const EffectTypes& getType() const = 0;
virtual void setType(const EffectTypes& type) = 0;
virtual const sEAXReverbParameters& getEAXReverbParameters() const = 0;
virtual void setEAXReverbParameters(const sEAXReverbParameters& param) = 0;
virtual const sReverbParameters& getReverbParameters() const = 0;
virtual void setReverbParameters(const sReverbParameters& param) = 0;
virtual const sChorusParameters& getChorusParameters() const = 0;
virtual void setChorusParameters(const sChorusParameters& param) = 0;
virtual const sDistortionParameters& getDistortionParameters() const = 0;
virtual void setDistortionParameters(const sDistortionParameters& param) = 0;
virtual const sEchoParameters& getEchoParameters() const = 0;
virtual void setEchoParameters(const sEchoParameters& param) = 0;
virtual const sFlangerParameters& getFlangerParameters() const = 0;
virtual void setFlangerParameters(const sFlangerParameters& param) = 0;
virtual const sFrequencyShiftParameters& getFrequencyShiftParameters() const = 0;
virtual void setFrequencyShiftParameters(const sFrequencyShiftParameters& param) = 0;
virtual const sVocalMorpherParameters& getVocalMorpherParameters() const = 0;
virtual void setVocalMorpherParameters(const sVocalMorpherParameters& param) = 0;
virtual const sPitchShifterParameters& getPitchShifterParameters() const = 0;
virtual void setPitchShifterParameters(const sPitchShifterParameters& param) = 0;
virtual const sRingModulatorParameters& getRingModulatorParameters() const = 0;
virtual void setRingModulatorParameters(const sRingModulatorParameters& param) = 0;
virtual const sAutowahParameters& getAutowahParameters() const = 0;
virtual void setAutowahParameters(const sAutowahParameters& param) = 0;
virtual const sCompressorParameters& getCompressorParameters() const = 0;
virtual void setCompressorParameters(const sCompressorParameters& param) = 0;
virtual const sEqualizerParameters& getEqualizerParameters() const = 0;
virtual void setEqualizerParameters(const sEqualizerParameters& param) = 0;
virtual float getMasterVolume() const = 0;
virtual void setMasterVolume(const float& volume) = 0;
virtual bool isIgnoringAttenuation() const = 0;
virtual void ignoreAttenuation(const bool& ignore) = 0;
virtual IFilter* getFilter() const = 0;
virtual void attachFilter(IFilter* filter) = 0;
virtual void removeFilter() = 0;
virtual unsigned int getLastUpdated() const = 0;
virtual bool isValid() const = 0;
};
};
#endif //! IEFFECT_H

364
include/IEffectParameters.h Normal file
View File

@ -0,0 +1,364 @@
#ifndef IEFFECTPARAMETERS_H
#define IEFFECTPARAMETERS_H
#include "cVector3.h"
namespace cAudio
{
struct sEAXReverbParameters
{
sEAXReverbParameters(
float density = 1.0f,
float diffusion = 1.0f,
float gain = 0.32f,
float gainHF = 0.89f,
float gainLF = 0.0f,
float decayTime = 1.49f,
float decayHFRatio = 0.83f,
float decayLFRatio = 1.0f,
float reflectionsGain = 0.05f,
float reflectionsDelay = 0.007f,
cVector3 reflectionsPan = cVector3(0.0f, 0.0f, 0.0f),
float lateReverbGain = 1.26f,
float lateReverbDelay = 0.011f,
cVector3 lateReverbPan = cVector3(0.0f, 0.0f, 0.0f),
float echoTime = 0.25f,
float echoDepth = 0.0f,
float modulationTime = 0.25f,
float modulationDepth = 0.0f,
float airAbsorptionGainHF = 0.994f,
float hFReference = 5000.0f,
float lFReference = 250.0f,
float roomRolloffFactor = 0.0f,
bool decayHFLimit = true) :
Density(density), Diffusion(diffusion), Gain(gain), GainHF(gainHF), GainLF(gainLF),
DecayTime(decayTime), DecayHFRatio(decayHFRatio), DecayLFRatio(decayLFRatio),
ReflectionsGain(reflectionsGain), ReflectionsDelay(reflectionsDelay),
ReflectionsPan(reflectionsPan), LateReverbGain(lateReverbGain),
LateReverbDelay(lateReverbDelay), LateReverbPan(lateReverbPan),
EchoTime(echoTime), EchoDepth(echoDepth),ModulationTime(modulationTime),
ModulationDepth(modulationDepth), AirAbsorptionGainHF(airAbsorptionGainHF),
HFReference(hFReference), LFReference(lFReference),
RoomRolloffFactor(roomRolloffFactor), DecayHFLimit(decayHFLimit) { }
float Density;
float Diffusion;
float Gain;
float GainHF;
float GainLF;
float DecayTime;
float DecayHFRatio;
float DecayLFRatio;
float ReflectionsGain;
float ReflectionsDelay;
cVector3 ReflectionsPan;
float LateReverbGain;
float LateReverbDelay;
cVector3 LateReverbPan;
float EchoTime;
float EchoDepth;
float ModulationTime;
float ModulationDepth;
float AirAbsorptionGainHF;
float HFReference;
float LFReference;
float RoomRolloffFactor;
bool DecayHFLimit;
};
struct sReverbParameters
{
sReverbParameters(
float density = 1.0f,
float diffusion = 1.0f,
float gain = 0.32f,
float gainHF = 0.89f,
float decayTime = 1.49f,
float decayHFRatio = 0.83f,
float reflectionsGain = 0.05f,
float reflectionsDelay = 0.007f,
float lateReverbGain = 1.26f,
float lateReverbDelay = 0.011f,
float airAbsorptionGainHF = 0.994f,
float roomRolloffFactor = 0.0f,
bool decayHFLimit = true) :
Density(density), Diffusion(diffusion), Gain(gain), GainHF(gainHF),
DecayTime(decayTime), DecayHFRatio(decayHFRatio),
ReflectionsGain(reflectionsGain), ReflectionsDelay(reflectionsDelay),
LateReverbGain(lateReverbGain), LateReverbDelay(lateReverbDelay),
AirAbsorptionGainHF(airAbsorptionGainHF), RoomRolloffFactor(roomRolloffFactor),
DecayHFLimit(decayHFLimit) { }
float Density;
float Diffusion;
float Gain;
float GainHF;
float DecayTime;
float DecayHFRatio;
float ReflectionsGain;
float ReflectionsDelay;
float LateReverbGain;
float LateReverbDelay;
float AirAbsorptionGainHF;
float RoomRolloffFactor;
bool DecayHFLimit;
};
struct sChorusParameters
{
enum ChorusWaveform
{
ECW_SINUSOID,
ECW_TRIANGLE,
ECW_COUNT
};
sChorusParameters(
ChorusWaveform waveform = ECW_TRIANGLE,
int phase = 90,
float rate = 1.1f,
float depth = 0.1f,
float feedback = 0.25f,
float delay = 0.016f) :
Waveform(waveform), Phase(phase), Rate(rate), Depth(depth), Feedback(feedback),
Delay(delay) { }
ChorusWaveform Waveform;
int Phase;
float Rate;
float Depth;
float Feedback;
float Delay;
};
struct sDistortionParameters
{
sDistortionParameters(
float edge = 0.2f,
float gain = 0.05f,
float lowpassCutoff = 8000.0f,
float eqCenter = 3600.0f,
float eqBandwidth = 3600.0f) :
Edge(edge), Gain(gain), LowpassCutoff(lowpassCutoff), EqCenter(eqCenter),
EqBandwidth(eqBandwidth) { }
float Edge;
float Gain;
float LowpassCutoff;
float EqCenter;
float EqBandwidth;
};
struct sEchoParameters
{
sEchoParameters(
float delay = 0.1f,
float lRDelay = 0.1f,
float damping = 0.5f,
float feedback = 0.5f,
float spread = -1.0f) :
Delay(delay), LRDelay(lRDelay), Damping(damping), Feedback(feedback),
Spread(spread) { }
float Delay;
float LRDelay;
float Damping;
float Feedback;
float Spread;
};
struct sFlangerParameters
{
enum FlangerWaveform
{
EFW_SINUSOID,
EFW_TRIANGLE,
EFW_COUNT
};
sFlangerParameters(
FlangerWaveform waveform = EFW_TRIANGLE,
int phase = 0,
float rate = 0.27f,
float depth = 1.0f,
float feedback = -0.5f,
float delay = 0.002f) :
Waveform(waveform), Phase(phase), Rate(rate), Depth(depth), Feedback(feedback),
Delay(delay) { }
FlangerWaveform Waveform;
int Phase;
float Rate;
float Depth;
float Feedback;
float Delay;
};
struct sFrequencyShiftParameters
{
enum ShiftDirection
{
ESD_DOWN,
ESD_UP,
ESD_OFF,
ESD_COUNT
};
sFrequencyShiftParameters(
float frequency = 0.0f,
ShiftDirection left = ESD_DOWN,
ShiftDirection right = ESD_DOWN) :
Frequency(frequency), Left(left), Right(right) { }
float Frequency;
ShiftDirection Left;
ShiftDirection Right;
};
struct sVocalMorpherParameters
{
enum MorpherPhoneme
{
EMP_A,
EMP_E,
EMP_I,
EMP_O,
EMP_U,
EMP_AA,
EMP_AE,
EMP_AH,
EMP_AO,
EMP_EH,
EMP_ER,
EMP_IH,
EMP_IY,
EMP_UH,
EMP_UW,
EMP_B,
EMP_D,
EMP_F,
EMP_G,
EMP_J,
EMP_K,
EMP_L,
EMP_M,
EMP_N,
EMP_P,
EMP_R,
EMP_S,
EMP_T,
EMP_V,
EMP_Z,
ESD_COUNT
};
enum MorpherWaveform
{
EMW_SINUSOID,
EMW_TRIANGLE,
EMW_SAW,
EMW_COUNT
};
sVocalMorpherParameters(
MorpherPhoneme phonemeA = EMP_A,
MorpherPhoneme phonemeB = EMP_ER,
int phonemeACoarseTune = 0,
int phonemeBCoarseTune = 0,
MorpherWaveform waveform = EMW_SINUSOID,
float rate = 1.41f) :
PhonemeA(phonemeA), PhonemeB(phonemeB), PhonemeACoarseTune(phonemeACoarseTune),
PhonemeBCoarseTune(phonemeBCoarseTune), Waveform(waveform), Rate(rate) { }
MorpherPhoneme PhonemeA;
MorpherPhoneme PhonemeB;
int PhonemeACoarseTune;
int PhonemeBCoarseTune;
MorpherWaveform Waveform;
float Rate;
};
struct sPitchShifterParameters
{
sPitchShifterParameters(
int coarseTune = 12,
int fineTune = 0) :
CoarseTune(coarseTune), FineTune(fineTune) { }
int CoarseTune;
int FineTune;
};
struct sRingModulatorParameters
{
enum ModulatorWaveform
{
EMW_SINUSOID,
EMW_SAW,
EMW_SQUARE,
EMW_COUNT
};
sRingModulatorParameters(
float frequency = 440.0f,
float highPassCutoff = 800.0f,
ModulatorWaveform waveform = EMW_SINUSOID) :
Frequency(frequency), HighPassCutoff(highPassCutoff), Waveform(waveform) { }
float Frequency;
float HighPassCutoff;
ModulatorWaveform Waveform;
};
struct sAutowahParameters
{
sAutowahParameters(
float attackTime = 0.06f,
float releaseTime = 0.06f,
float resonance = 1000.0f,
float peakGain = 11.22f) :
AttackTime(attackTime), ReleaseTime(releaseTime), Resonance(resonance),
PeakGain(peakGain) { }
float AttackTime;
float ReleaseTime;
float Resonance;
float PeakGain;
};
struct sCompressorParameters
{
sCompressorParameters(
bool active = true) :
Active(active) { }
bool Active;
};
struct sEqualizerParameters
{
sEqualizerParameters(
float lowGain = 1.0f,
float lowCutoff = 200.0f,
float mid1Gain = 1.0f,
float mid1Center = 500.0f,
float mid1Width = 1.0f,
float mid2Gain = 1.0f,
float mid2Center = 3000.0f,
float mid2Width = 1.0f,
float highGain = 1.0f,
float highCutoff = 6000.0f) :
LowGain(lowGain), LowCutoff(lowCutoff), Mid1Gain(mid1Gain),
Mid1Center(mid1Center), Mid1Width(mid1Width), Mid2Gain(mid2Gain),
Mid2Center(mid2Center), Mid2Width(mid2Width), HighGain(highGain),
HighCutoff(highCutoff) { }
float LowGain;
float LowCutoff;
float Mid1Gain;
float Mid1Center;
float Mid1Width;
float Mid2Gain;
float Mid2Center;
float Mid2Width;
float HighGain;
float HighCutoff;
};
};
#endif //! IEFFECTPARAMETERS_H

40
include/IFilter.h Normal file
View File

@ -0,0 +1,40 @@
#ifndef IFILTER_H
#define IFILTER_H
#include "IRefCounted.h"
namespace cAudio
{
enum FilterTypes
{
EFT_NULL,
EFT_LOWPASS,
EFT_HIGHPASS,
EFT_BANDPASS,
EFT_COUNT
};
class IFilter : public IRefCounted
{
public:
IFilter() { }
virtual ~IFilter() { }
virtual const FilterTypes& getType() const = 0;
virtual void setType(const FilterTypes& type) = 0;
virtual float getVolume() const = 0;
virtual void setVolume(const float& volume) = 0;
virtual float getLowFrequencyVolume() const = 0;
virtual void setLowFrequencyVolume(const float& volumeLF) = 0;
virtual float getHighFrequencyVolume() const = 0;
virtual void setHighFrequencyVolume(const float& volumeHF) = 0;
virtual unsigned int getLastUpdated() const = 0;
virtual bool isValid() const = 0;
};
};
#endif //! IFILTER_H

View File

@ -1,8 +1,8 @@
#ifndef ILISTENER_H
#define ILISTENER_H
#include "cVector3.h"
#include "cAudioDefines.h"
namespace cAudio
{
@ -40,6 +40,13 @@ namespace cAudio
//!Returns the global volume modifier for all sources
virtual float getMasterVolume(void) const = 0;
#ifdef CAUDIO_EFX_ENABLED
//!Sets the meters per user world unit for use with sound effects
virtual void setMetersPerUnit(const float& meters) = 0;
//!Returns the meters per user world unit for use with sound effects
virtual float getMetersPerUnit(void) const = 0;
#endif
protected:
private:
};

View File

@ -5,27 +5,27 @@
#ifndef CAUDIO_STATIC_LIB
#ifdef CAUDIO_EXPORTS
#define CAUDIO_API __declspec(dllexport)
#define CAUDIO_API __declspec(dllexport)
#else
#define CAUDIO_API//! __declspec(dllimport)
#define CAUDIO_API//! __declspec(dllimport)
#endif // CAUDIO_EXPORTS
#else
#define CAUDIO_API
#define CAUDIO_API
#endif // CAUDIO_STATIC_LIB
//////////////////////////
//Global Library Settings
//////////////////////////
//Define for making the entire library Thread Safe, comment out to disable
//Will also disable internal threading by the library
#define CAUDIO_MAKE_THREAD_SAFE
//Define for compiling with EAX
#define CAUDIO_EAX_ENABLED
#ifdef CAUDIO_MAKE_THREAD_SAFE
//Define enables threading for the main update loop. Disable to run the internal update loop yourself
//NOTE: Internal threading should NOT be used if the library is not thread safe!
#define CAUDIO_USE_INTERNAL_THREAD
//Define enables threading for the main update loop. Disable to run the internal update loop yourself
//NOTE: Internal threading should NOT be used if the library is not thread safe!
#define CAUDIO_USE_INTERNAL_THREAD
#endif
//These defines control which of the default audio codecs are compiled into the library
@ -33,4 +33,25 @@
#define CAUDIO_COMPILE_WITH_WAV_DECODER
#define CAUDIO_COMPILE_WITH_RAW_DECODER
////////////////////////
//Audio Source Settings
////////////////////////
//Size of the internal buffer per source for audio data (total amount buffered is CAUDIO_SOURCE_BUFFER_SIZE * CAUDIO_SOURCE_NUM_BUFFERS)
#define CAUDIO_SOURCE_BUFFER_SIZE ( 1024 * 64 )
//Number of internal buffers to cycle through per source (Note: using only 1 leads to choppy sound or premature ending of sources)
#define CAUDIO_SOURCE_NUM_BUFFERS 3
/////////////////////////
//Audio Effects Settings
/////////////////////////
//Comment out to remove all EFX support from the library
#define CAUDIO_EFX_ENABLED
#ifdef CAUDIO_EFX_ENABLED
//Max number of effects that can be attached to a single sound source
#define CAUDIO_SOURCE_MAX_EFFECT_SLOTS 4
#endif
#endif //! CAUDIODEFINES_H

BIN
media/Footsteps.wav Normal file

Binary file not shown.

View File

@ -58,7 +58,7 @@
<Tool
Name="VCLinkerTool"
AdditionalDependencies="cAudio.lib"
AdditionalLibraryDirectories="&quot;..\..\bin\win32-visual&quot;"
AdditionalLibraryDirectories="&quot;..\..\lib\win32-visual&quot;"
GenerateDebugInformation="true"
TargetMachine="1"
/>
@ -128,7 +128,7 @@
<Tool
Name="VCLinkerTool"
AdditionalDependencies="cAudio.lib"
AdditionalLibraryDirectories="&quot;..\..\bin\win32-visual&quot;"
AdditionalLibraryDirectories="&quot;..\..\lib\win32-visual&quot;"
GenerateDebugInformation="true"
OptimizeReferences="2"
EnableCOMDATFolding="2"