Added audio capture capabilities. The user can now get an interface for audio capture from cAudioManager and record audio from the default recording device.

Added a raw audio decoder, allowing raw audio to be played if the format and frequency is known.  Will also load from .raw files on disk, but will assume the format is 16 bit mono and the frequency is 22050 hz
Added a tutorial to show how recording and playback can be done.
Added the ability for the user to unregister audio codecs that they will not be using.  Also added methods to test for the existance of a decoder and get the decoder factory back.
Moved cVector3.h to include instead of Headers to make using it in user projects easier (one less include path)
Moved the audio format enum to its own header file.
Small fix in the wav decoder to prevent the file header from being played as audio data.
This commit is contained in:
Joshua Jones 2009-08-11 17:57:20 +00:00
parent 9933eee54c
commit 0c3df1d430
21 changed files with 989 additions and 113 deletions

View File

@ -0,0 +1,186 @@
<?xml version="1.0" encoding="Windows-1252"?>
<VisualStudioProject
ProjectType="Visual C++"
Version="9.00"
Name="Tutorial4_AudioCapture"
ProjectGUID="{F04BE31E-E8CC-40C8-9C63-EEAE1BF84EB7}"
RootNamespace="Tutorial4_AudioCapture"
TargetFrameworkVersion="196613"
>
<Platforms>
<Platform
Name="Win32"
/>
</Platforms>
<ToolFiles>
</ToolFiles>
<Configurations>
<Configuration
Name="Debug|Win32"
OutputDirectory="../../bin/$(ConfigurationName)"
IntermediateDirectory="$(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;..\..\bin\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="$(SolutionDir)$(ConfigurationName)"
IntermediateDirectory="$(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"
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,103 @@
#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"
using namespace std;
#define CAPTURE_FREQUENCY 22050
#define CAPTURE_DURATION 10
#define CAPTURE_FORMAT cAudio::EAF_16BIT_MONO
int main(int argc, char* argv[])
{
//To make visual studio happy
cAudio::IAudio* mysound = NULL;
//Some fancy text
cout << "cAudio 1.7.1 Tutorial 4: Capturing Audio \n \n";
std::string formatName;
if(CAPTURE_FORMAT == cAudio::EAF_8BIT_MONO)
formatName = "8 Bit Mono";
else if(CAPTURE_FORMAT == cAudio::EAF_8BIT_STEREO)
formatName = "8 Bit Stereo";
else if(CAPTURE_FORMAT == cAudio::EAF_16BIT_MONO)
formatName = "16 Bit Mono";
else
formatName = "16 Bit Stereo";
//Grap the cAudioManager
cAudio::IAudioManager* manager = cAudio::getAudioManager();
//Init the cAudio Engine
manager->init(argc,argv);
//! The capture interface should be grabbed after the manager has been initialized
cAudio::IAudioCapture* capture = manager->getAudioCapture();
bool captureReady = false;
cout << "Capturing Supported: " << std::boolalpha << capture->isSupported() << "\n";
if(capture->isSupported())
{
captureReady = capture->initialize(CAPTURE_FREQUENCY, CAPTURE_FORMAT);
cout << "Ready to capture audio: " << std::boolalpha << captureReady << "\n \n";
//Quick math to figure out how large our data should be for the duration of the record time
const int targetRecordSize = CAPTURE_FREQUENCY * CAPTURE_DURATION * capture->getSampleSize();
cout << "Capture Frequency: " << CAPTURE_FREQUENCY << "\n";
cout << "Capture Duration: " << CAPTURE_DURATION << "\n";
cout << "Capture Format: " << formatName << "\n";
cout << "Sample Size: " << capture->getSampleSize() << "\n";
cout << "Total size of audio: " << targetRecordSize << "\n";
cout << std::endl;
int currentsize = 0;
cout << "Starting capture... \n";
if(capture->beginCapture())
{
while(currentsize < targetRecordSize)
{
currentsize = capture->getCurrentCapturedAudioSize();
//Run the main update loop to keep audio data flowing in
manager->update();
}
}
capture->stopCapture();
cout << "Capture stopped... \n \n";
char* buffer = new char[currentsize];
capture->getCapturedAudio(buffer, currentsize);
//Create a IAudio object and load a sound from a file
mysound = manager->createFromRaw("sound1", buffer, currentsize, CAPTURE_FREQUENCY, CAPTURE_FORMAT);
delete buffer;
if(mysound)
{
cout << "Playing back captured audio... \n \n";
mysound->setVolume(1.0);
//Set the IAudio Sound to play2d and loop
mysound->play2d(false);
while(mysound->playing())
{
//Playback sound
manager->update();
}
}
}
//Delete all IAudio sounds
manager->release();
//Shutdown cAudio
manager->shutDown();
std::cout << "Press any key to quit \n";
std::cin.get();
return 0;
}

View File

@ -19,11 +19,12 @@ namespace cAudio
void play2d(bool loop = false);
//!plays the audio file and sets it to 3d
void play3d(bool loop = false, float x = 0.0, float y = 0.0, float z = 0.0, float soundstr = 1.0);
//!allows us to set the position or reset the position
void setPosition(float posx,float posy,float posz);
//!allows you to set the audio objects velocity
void setVelocity(float velx,float vely,float velz);
//!allows us to set the direction the audio should play in / move
//!allows us to set the direction the audio should play in
void setDirection(float dirx,float diry,float dirz);
//! Sets the audios pitch level
void setPitch(float pitch);
@ -35,6 +36,7 @@ namespace cAudio
void setDopplerStrength(float doop);
//!Set doppler velocity
void setDopplerVelocity(float doopx,float doopy,float doopz);
//!Seek the audio stream
void seek(float secs);
//!release the file handle

93
Headers/cAudioCapture.h Normal file
View File

@ -0,0 +1,93 @@
#ifndef CAUDIOCAPTURE_H
#define CAUDIOCAPTURE_H
#include "../include/IAudioCapture.h"
#include <vector>
#include <AL/al.h>
#include <AL/alc.h>
namespace cAudio
{
class cAudioCapture : public IAudioCapture
{
public:
cAudioCapture();
~cAudioCapture();
//! Checks to see if capturing audio is supported by OpenAL
//! Normally run automatically by cAudioManager::init()
bool checkCaptureExtension();
//! Grabs samples from the OpenAL buffer into the capture buffer. Should be run once every audio frame.
//! Normally run automatically by cAudioManager::update()
void updateCaptureBuffer(bool force = false);
//! Shuts down the capture device
//! Normally run automatically by cAudioManager::shutDown()
void shutdown();
//! Initializes the capture device to the selected settings
/** Note that calling this will cause the capture device to be reinitialized. Calling while in use may lead to a loss of audio data.
\param frequency: Frequency that the captured audio will be at
\param format: Format of the captured audio
\param internalBufferSize: Size of the internal OpenAL buffer used to store the captured audio until the next IAudioManager::update() in bytes
\return True on success, False if the capture device failed to initialize.
*/
virtual bool initialize(unsigned int frequency = 22050, AudioFormats format = EAF_16BIT_MONO, unsigned int internalBufferSize = 8192);
//! Returns true if the current OpenAL implementation supports capturing audio
virtual bool isSupported() { return Supported; }
//! Returns true if the capture device is ready to be used. False may indicate an error with the current settings.
virtual bool isReady() { return Ready; }
//! Returns the frequency that the captured audio will be at
virtual unsigned int getFrequency() { return Frequency; }
//! Returns the format of the captured audio
virtual AudioFormats getFormat() { return Format; }
//! Returns the internal OpenAL buffer size in bytes
virtual unsigned int getInternalBufferSize() { return InternalBufferSize; }
//! Returns the size of a "sample" of audio data. Useful for making sure you grab audio data at sample boundaries
virtual unsigned int getSampleSize() { return SampleSize; }
//! Sets the frequency that the captured audio will be at. Will cause the capture device to be reinitialized. Calling while in use may lead to a loss of audio data.
/** \return True on success, False if the capture device failed to initialize. */
virtual bool setFrequency(unsigned int frequency);
//! Sets the format that the captured audio will be at. Will cause the capture device to be reinitialized. Calling while in use may lead to a loss of audio data.
/** \return True on success, False if the capture device failed to initialize. */
virtual bool setFormat(AudioFormats format);
//! Sets the internal buffer size that OpenAL will use to store captured audio between calls to IAudioManager::update() in bytes. Will cause the capture device to be reinitialized. Calling while in use may lead to a loss of audio data.
/** \return True on success, False if the capture device failed to initialize. */
virtual bool setInternalBufferSize(unsigned int internalBufferSize);
//! Starts capturing audio data to an internal buffer. Will clear any old data in the buffer.
/** \return True if capture was successfully started. */
virtual bool beginCapture();
//! Stops capturing audio data to an internal buffer. Will copy any remaining audio data to the capture buffer.
virtual void stopCapture();
//! Allows access to the audio data in the internal capture buffer
/** Can be called at any time to retrieve recorded audio. It is recommended that you call it every so often to prevent the internal buffer from growing too large.
Once successfully retrieved, the captured audio will be deleted from the internal buffer.
\param outputBuffer: Pointer to an output array to copy audio data to.
\param outputBufferSize: Size of the output array in bytes
*/
virtual void getCapturedAudio(void* outputBuffer, unsigned int outputBufferSize);
//! Returns the current size of the internal audio buffer in bytes
virtual unsigned int getCurrentCapturedAudioSize();
protected:
bool initOpenALDevice();
void shutdownOpenALDevice();
unsigned int Frequency;
AudioFormats Format;
unsigned int InternalBufferSize;
std::vector<char> CaptureBuffer;
bool Supported;
bool Ready;
bool Capturing;
int SampleSize;
ALCdevice* CaptureDevice;
};
};
#endif //! CAUDIOCAPTURE_H

View File

@ -6,6 +6,7 @@
#include "cAudio.h"
#include "../include/IAudioDecoderFactory.h"
#include "cListener.h"
#include "cAudioCapture.h"
#include "../include/IAudioManager.h"
namespace cAudio
@ -16,27 +17,40 @@ namespace cAudio
{
public:
//!Inits the audio manager calling the alut/etc start ups
void init(int argc,char* argv[]);
virtual void init(int argc,char* argv[]);
//!Shuts everything down
void shutDown();
virtual void shutDown();
//!Creates the cAudio object
IAudio* createFromFile(const std::string& identifier,const std::string& file,bool stream = false);
virtual IAudio* createFromFile(const std::string& identifier,const std::string& file,bool stream = false);
//!Loads ogg from memory or virtual file system
IAudio* createFromMemory(const std::string& identifier, const char* data, size_t length, std::string ext);
virtual IAudio* createFromMemory(const std::string& identifier, const char* data, size_t length, std::string ext);
//!Loads raw audio from memory.
virtual IAudio* createFromRaw(const std::string& identifier,const char* data, size_t length, unsigned int frequency, AudioFormats format);
//!Register Audio Codec
void registerAudioDecoder(IAudioDecoderFactory* factory, std::string extension);
virtual bool registerAudioDecoder(IAudioDecoderFactory* factory, std::string extension);
//!Unregister Audio Codec (allows you to prevent an file type from being playable with new sound sources)
//!Note that all current sound sources will still continue to use any currently allocated decoders.
//!Will delete the factory instance
virtual void unRegisterAudioDecoder(std::string extension);
//!Returns whether an audio decoder is currently registered for this file type
virtual bool isAudioDecoderRegistered(std::string extension);
//!Returns a registered audio decoder factory
virtual IAudioDecoderFactory* getAudioDecoderFactory(std::string extension);
//!Allows you to set the listener position (DEPRECIATED! USE getListener() INSTEAD!)
void setListenerPos(float x,float y,float z);
virtual void setListenerPos(float x,float y,float z);
//!Set Listener Orientation (DEPRECIATED! USE getListener() INSTEAD!)
void setListenerOrientation(float ux,float uy,float uz);
virtual void setListenerOrientation(float ux,float uy,float uz);
//!Updates the cAudio playback
void update();
virtual void update();
//!Gets you the cAudio object you want
IAudio *getSound(std::string identifier);
virtual IAudio *getSound(std::string identifier);
//!Releases "ALL" cAudio objects
void release();
virtual void release();
virtual IListener* getListener() { return &initlistener; }
virtual IAudioCapture* getAudioCapture() { return &initCapture; }
static cAudioManager* Instance()
{
@ -55,6 +69,8 @@ namespace cAudio
std::map<std::string, IAudioDecoderFactory*> decodermap;
//!The listener object
cListener initlistener;
//!The audio capture instance
cAudioCapture initCapture;
};
}

View File

@ -0,0 +1,32 @@
#ifndef CRAWAUDIODECODERFACOTRY_H_INCLUDED
#define CRAWAUDIODECODERFACOTRY_H_INCLUDED
#include "../include/IAudioDecoderFactory.h"
#include "cRawDecoder.h"
namespace cAudio
{
class cRawAudioDecoderFactory : public IAudioDecoderFactory
{
public:
cRawAudioDecoderFactory() {}
~cRawAudioDecoderFactory() {}
IAudioDecoder* CreateAudioDecoder(IDataSource* stream)
{
return new cRawDecoder(stream, 22050, EAF_16BIT_MONO);
}
IAudioDecoder* CreateAudioDecoder(IDataSource* stream, unsigned int frequency = 22050, AudioFormats format = EAF_16BIT_MONO)
{
return new cRawDecoder(stream, frequency, format);
}
protected:
private:
};
};
#endif //! CRAWAUDIODECODERFACOTRY_H_INCLUDED

41
Headers/cRawDecoder.h Normal file
View File

@ -0,0 +1,41 @@
#ifndef CRAWDECODER_H_INCLUDED
#define CRAWDECODER_H_INCLUDED
#include "../include/IAudioDecoder.h"
namespace cAudio
{
class cRawDecoder : public IAudioDecoder
{
public:
cRawDecoder(IDataSource* stream, unsigned int frequency, AudioFormats format);
~cRawDecoder();
//!Retruns the format of the audio data
virtual AudioFormats getFormat();
//!Returns the frequency of the audio data
virtual int getFrequency();
//!Returns whether seeking is supported
virtual bool isSeekingSupported();
//!Reads a section of data out of the audio stream
virtual int readAudioData(void* output, int amount);
//!Sets the position to read data out of
virtual bool setPosition(int position, bool relative);
//!If seeking is supported, will seek the stream to seconds
virtual bool seek(float seconds,bool relative);
private:
unsigned int Frequency;
AudioFormats Format;
};
}
#endif //! CRAWDECODER_H_INCLUDED

View File

@ -27,13 +27,13 @@ namespace cAudio
//!Stops all playing sound sources and deletes the sources and buffers
void cAudio::release()
{
//Stops the audio source
alSourceStop(source);
empty();
//Deletes the source
alDeleteSources(1, &source);
//deletes the last filled buffer
alDeleteBuffers(3, buffers);
//Stops the audio source
alSourceStop(source);
empty();
//Deletes the source
alDeleteSources(1, &source);
//deletes the last filled buffer
alDeleteBuffers(3, buffers);
}
//!Plays back sound source
@ -69,10 +69,10 @@ namespace cAudio
int processed = 0;
bool active = true;
//gets the sound source processed buffers/
//gets the sound source processed buffers/
alGetSourcei(source, AL_BUFFERS_PROCESSED, &processed);
//while there is more data refill buffers with audio data.
while (processed--)
//while there is more data refill buffers with audio data.
while (processed--)
{
ALuint buffer;
@ -80,13 +80,11 @@ namespace cAudio
active = stream(buffer);
//if more in stream continue playing.
//if more in stream continue playing.
if(active)
alSourceQueueBuffers(source, 1, &buffer);
}
return active;
return active;
}
//!The streaming function
@ -95,58 +93,56 @@ namespace cAudio
if(Decoder)
{
//stores the caculated data into buffer that is passed to output.
size_t totalread = 0;
size_t totalread = 0;
char tempbuffer[BUFFER_SIZE];
while( totalread < BUFFER_SIZE )
{
char tempbuffer2[BUFFER_SIZE];
int actualread = Decoder->readAudioData(tempbuffer2, BUFFER_SIZE-totalread);
if(actualread > 0)
while( totalread < BUFFER_SIZE )
{
memcpy(tempbuffer+totalread,tempbuffer2,actualread);
totalread += actualread;
}
if(actualread < 0)
{
break;
}
if(actualread == 0)
{
if(toloop)
char tempbuffer2[BUFFER_SIZE];
int actualread = Decoder->readAudioData(tempbuffer2, BUFFER_SIZE-totalread);
if(actualread > 0)
{
//If we are to loop, set to the beginning and reload from the start
Decoder->setPosition(0,false);
memcpy(tempbuffer+totalread,tempbuffer2,actualread);
totalread += actualread;
}
else
if(actualread < 0)
{
break;
}
}
if(actualread == 0)
{
if(toloop)
{
//If we are to loop, set to the beginning and reload from the start
Decoder->setPosition(0,false);
}
else
break;
}
}
//Second check, in case looping is not enabled, we will return false for end of stream
if(totalread == 0)
{
return false;
}
//Second check, in case looping is not enabled, we will return false for end of stream
if(totalread == 0)
{
return false;
}
//std::cout << buffer << std::endl;
alBufferData(buffer, Decoder->getFormat(), tempbuffer, totalread, Decoder->getFrequency());
return true;
}
return false;
alBufferData(buffer, Decoder->getFormat(), tempbuffer, totalread, Decoder->getFrequency());
return true;
}
return false;
}
//!clears the sound sources buffers and makes them free to be used by other sound sources.
void cAudio::empty()
{
int queued = 0;
//grabs allt he sources buffers.
//grabs allt he sources buffers.
alGetSourcei(source, AL_BUFFERS_QUEUED, &queued);
while (queued--)
{
ALuint buffer;
//unqueues sources buffers to be used for others.
//unqueues sources buffers to be used for others.
alSourceUnqueueBuffers(source, 1, &buffer);
}
}
@ -158,16 +154,14 @@ namespace cAudio
if (error != AL_NO_ERROR)
{
std::cout<<"OpenAL error was Raised.";
std::cout<< "OpenAL error was Raised.";
}
}
//!checks to see if the given ogg file is valid
bool cAudio::isvalid()
{
return (Decoder != 0);
}
//!Sets the sound source relativity to follow the listener to give the illusion of stereo 2d sound
@ -176,14 +170,14 @@ namespace cAudio
alSourcei (source, AL_SOURCE_RELATIVE, true);
toloop = loop;
play();
alSourcePlay(source);
alSourcePlay(source);
}
//!Plays the given audio file with 3d position
void cAudio::play3d(bool loop, float x, float y, float z,float soundstr)
{
alSourcei (source, AL_SOURCE_RELATIVE, false);
alSource3f(source, AL_POSITION,x, y, z);
alSource3f(source, AL_POSITION, x, y, z);
alSourcef (source, AL_ROLLOFF_FACTOR, soundstr);
toloop = loop;
play();
@ -199,49 +193,49 @@ namespace cAudio
//!Used to move the audio sources position after the initial creation
void cAudio::setPosition(float posx,float posy,float posz)
{
alSource3f(source, AL_POSITION,posx, posy, posz);
alSource3f(source, AL_POSITION, posx, posy, posz);
}
//!Used to set the velocity of the audio source.
void cAudio::setVelocity(float velx,float vely, float velz)
{
alSource3f(source, AL_VELOCITY,velx, vely, velz);
alSource3f(source, AL_VELOCITY, velx, vely, velz);
}
//!Used to set the direction of the audio source
void cAudio::setDirection(float dirx,float diry,float dirz)
{
alSource3f(source, AL_DIRECTION,dirx, diry, dirz);
alSource3f(source, AL_DIRECTION, dirx, diry, dirz);
}
//!Used to set the sound strength or roll off factor
void cAudio::setStrength(float soundstrength)
{
alSourcef (source, AL_ROLLOFF_FACTOR, soundstrength);
alSourcef(source, AL_ROLLOFF_FACTOR, soundstrength);
}
//!Used to set the pitch of the audio file
void cAudio::setPitch(float pitch)
{
alSourcef (source, AL_PITCH,pitch);
alSourcef (source, AL_PITCH, pitch);
}
//!Used to set the volume of the audio source
void cAudio::setVolume(float volume)
{
alSourcef(source,AL_GAIN,volume);
alSourcef(source, AL_GAIN, volume);
}
//!Used to set the doppler strength of the audio sources doppler effect
void cAudio::setDopplerStrength(float doop)
{
alSourcef(source,AL_DOPPLER_FACTOR,doop);
alSourcef(source, AL_DOPPLER_FACTOR, doop);
}
//!Used to set the doppler velocity of the audio source
void cAudio::setDopplerVelocity(float doopx,float doopy,float doopz)
{
alSource3f(source,AL_DOPPLER_VELOCITY,doopx,doopy,doopz);
alSource3f(source, AL_DOPPLER_VELOCITY, doopx, doopy, doopz);
}
//!Allows us to seek through a stream
@ -257,13 +251,12 @@ namespace cAudio
bool cAudio::play()
{
playaudio = true;
if (!this->paused())
if (!paused())
{
int queueSize = 0;
for(int u = 0; u < 3; u++)
{
int val = this->stream(buffers[u]);
int val = stream(buffers[u]);
if(val < 0)
{
@ -272,17 +265,13 @@ namespace cAudio
else if(val > 0)
++queueSize;
}
//Stores the sources 3 buffers to be used in the queue
alSourceQueueBuffers(source, queueSize, buffers);
}
}
alSourcePlay(source);
return true;
}
//!Used to stop the audio source
void cAudio::stop()
{

177
Source/cAudioCapture.cpp Normal file
View File

@ -0,0 +1,177 @@
#include "../Headers/cAudioCapture.h"
#include <string.h>
namespace cAudio
{
cAudioCapture::cAudioCapture() : Frequency(22050), Format(EAF_16BIT_MONO), InternalBufferSize(8192),
Supported(false), Ready(false), Capturing(false), SampleSize(2), CaptureDevice(NULL)
{
}
cAudioCapture::~cAudioCapture()
{
}
bool cAudioCapture::checkCaptureExtension()
{
// Check for Capture Extension support
ALCdevice* pDevice;
ALCcontext* pContext;
pContext = alcGetCurrentContext();
pDevice = alcGetContextsDevice(pContext);
Supported = ( alcIsExtensionPresent(pDevice, "ALC_EXT_CAPTURE") == AL_TRUE );
return Supported;
}
bool cAudioCapture::initOpenALDevice()
{
if(Supported)
{
if(CaptureDevice)
shutdownOpenALDevice();
CaptureDevice = alcCaptureOpenDevice(NULL, Frequency, Format, InternalBufferSize / SampleSize);
if(CaptureDevice)
{
Ready = true;
return true;
}
}
return false;
}
void cAudioCapture::shutdownOpenALDevice()
{
if(Supported)
{
if(Capturing)
stopCapture();
if(CaptureDevice)
{
alcCaptureCloseDevice(CaptureDevice);
CaptureDevice = NULL;
Ready = false;
}
}
}
void cAudioCapture::shutdown()
{
shutdownOpenALDevice();
}
void cAudioCapture::updateCaptureBuffer(bool force)
{
if(Capturing && CaptureDevice && Ready)
{
int AvailableSamples = 0;
alcGetIntegerv(CaptureDevice, ALC_CAPTURE_SAMPLES, 1, &AvailableSamples);
const unsigned int availbuffersize = AvailableSamples * SampleSize;
//If the samples in the OpenAL buffer are more than half of its max size, grab them
if(availbuffersize > InternalBufferSize / 2 || force)
{
//Fixes a bug with the capture being forced, but no data being available
if(availbuffersize > 0)
{
const int oldBufferSize = CaptureBuffer.size();
CaptureBuffer.resize(oldBufferSize + availbuffersize, 0);
alcCaptureSamples(CaptureDevice, &CaptureBuffer[oldBufferSize], AvailableSamples);
}
}
}
}
bool cAudioCapture::beginCapture()
{
if(!Capturing)
{
CaptureBuffer.clear();
if(CaptureDevice && Ready)
{
alcCaptureStart(CaptureDevice);
Capturing = true;
}
return Capturing;
}
else
return false;
}
void cAudioCapture::stopCapture()
{
if(CaptureDevice && Ready)
{
alcCaptureStop(CaptureDevice);
updateCaptureBuffer(true);
}
Capturing = false;
}
void cAudioCapture::getCapturedAudio(void* outputBuffer, unsigned int outputBufferSize)
{
if(outputBuffer && outputBufferSize > 0)
{
int sizeToCopy = (outputBufferSize >= CaptureBuffer.size()) ? CaptureBuffer.size() : outputBufferSize;
memcpy(outputBuffer, &CaptureBuffer[0], sizeToCopy);
CaptureBuffer.erase(CaptureBuffer.begin(), CaptureBuffer.begin()+sizeToCopy);
}
}
unsigned int cAudioCapture::getCurrentCapturedAudioSize()
{
return CaptureBuffer.size();
}
bool cAudioCapture::setFrequency(unsigned int frequency)
{
Frequency = frequency;
shutdownOpenALDevice();
return initOpenALDevice();
}
bool cAudioCapture::setFormat(AudioFormats format)
{
Format = format;
if(Format == EAF_8BIT_MONO)
SampleSize = 1;
else if(Format == EAF_8BIT_STEREO)
SampleSize = 2;
else if(Format == EAF_16BIT_MONO)
SampleSize = 2;
else
SampleSize = 4;
shutdownOpenALDevice();
return initOpenALDevice();
}
bool cAudioCapture::setInternalBufferSize(unsigned int internalBufferSize)
{
InternalBufferSize = internalBufferSize;
shutdownOpenALDevice();
return initOpenALDevice();
}
bool cAudioCapture::initialize(unsigned int frequency, AudioFormats format, unsigned int internalBufferSize)
{
Frequency = frequency;
InternalBufferSize = internalBufferSize;
Format = format;
if(Format == EAF_8BIT_MONO)
SampleSize = 1;
else if(Format == EAF_8BIT_STEREO)
SampleSize = 2;
else if(Format == EAF_16BIT_MONO)
SampleSize = 2;
else
SampleSize = 4;
shutdownOpenALDevice();
return initOpenALDevice();
}
};

View File

@ -4,8 +4,10 @@
#include "../Headers/cUtils.h"
#include "../Headers/cOggAudioDecoderFactory.h"
#include "../Headers/cWavAudioDecoderFacotry.h"
#include "../Headers/cRawAudioDecoderFactory.h"
#include <AL/al.h>
#include <AL/alc.h>
#include <AL/alut.h>
//!#include <AL/alext.h>
//!#include <AL/efx.h>
@ -24,6 +26,7 @@ namespace cAudio
void cAudioManager::init(int argc,char* argv[])
{
alutInit(&argc,argv);
/*
ALCcontext *Context;
ALCdevice *Device;
@ -64,8 +67,12 @@ namespace cAudio
LOAD_AL_FUNC(alIsEffect);
*/
initCapture.checkCaptureExtension();
initCapture.initialize();
registerAudioDecoder(new cOggAudioDecoderFactory, "ogg");
registerAudioDecoder(new cWavAudioDecoderFactory, "wav");
registerAudioDecoder(new cRawAudioDecoderFactory, "raw");
}
//!create a sound source
@ -76,13 +83,13 @@ namespace cAudio
if(source->isValid())
{
std::string ext = getExt(file);
std::map<std::string, IAudioDecoderFactory*>::iterator it = decodermap.find(ext);
if(it == decodermap.end())
{
IAudioDecoderFactory* factory = getAudioDecoderFactory(ext);
if(!factory)
{
delete source;
return NULL;
}
IAudioDecoder* decoder = it->second->CreateAudioDecoder(source);
IAudioDecoder* decoder = factory->CreateAudioDecoder(source);
IAudio* audio = new cAudio(decoder);
audiomap[identifier] = audio;
return audio;
@ -113,13 +120,13 @@ namespace cAudio
cMemorySource* source = new cMemorySource(data,length,true);
if(source->isValid())
{
std::map<std::string, IAudioDecoderFactory*>::iterator it = decodermap.find(ext);
if(it == decodermap.end())
IAudioDecoderFactory* factory = getAudioDecoderFactory(ext);
if(!factory)
{
delete source;
return NULL;
}
IAudioDecoder* decoder = it->second->CreateAudioDecoder(source);
IAudioDecoder* decoder = factory->CreateAudioDecoder(source);
IAudio* audio = new cAudio(decoder);
audiomap[identifier] = audio;
return audio;
@ -131,11 +138,61 @@ namespace cAudio
}
}
void cAudioManager::registerAudioDecoder(IAudioDecoderFactory* factory, std::string extension)
IAudio* cAudioManager::createFromRaw(const std::string& identifier,const char* data, size_t length, unsigned int frequency, AudioFormats format)
{
cMemorySource* source = new cMemorySource(data,length,true);
if(source->isValid())
{
IAudioDecoderFactory* factory = getAudioDecoderFactory("raw");
if(!factory)
{
delete source;
return NULL;
}
IAudioDecoder* decoder = ((cRawAudioDecoderFactory*)factory)->CreateAudioDecoder(source, frequency, format);
IAudio* audio = new cAudio(decoder);
audiomap[identifier] = audio;
return audio;
}
else
{
delete source;
return NULL;
}
}
bool cAudioManager::registerAudioDecoder(IAudioDecoderFactory* factory, std::string extension)
{
decodermap[extension] = factory;
return true;
}
void cAudioManager::unRegisterAudioDecoder(std::string extension)
{
std::map<std::string, IAudioDecoderFactory*>::iterator it = decodermap.find(extension);
if(it != decodermap.end())
{
delete it->second;
decodermap.erase(it);
}
}
bool cAudioManager::isAudioDecoderRegistered(std::string extension)
{
std::map<std::string, IAudioDecoderFactory*>::iterator it = decodermap.find(extension);
return (it != decodermap.end());
}
IAudioDecoderFactory* cAudioManager::getAudioDecoderFactory(std::string extension)
{
std::map<std::string, IAudioDecoderFactory*>::iterator it = decodermap.find(extension);
if(it != decodermap.end())
{
return it->second;
}
return NULL;
}
//!grabs the selected audio file via the identifier
IAudio *cAudioManager::getSound(std::string identifier)
{
@ -177,17 +234,19 @@ namespace cAudio
{
}
if (i->second->playback())
/*if (i->second->playback())
{
}
}*/
}
}
initCapture.updateCaptureBuffer();
}
//!Shuts down cAudio. Deletes all audio sources in process
void cAudioManager::shutDown()
{
initCapture.shutdown();
alutExit();
}

53
Source/cRawDecoder.cpp Normal file
View File

@ -0,0 +1,53 @@
#include "../Headers/cRawDecoder.h"
namespace cAudio{
cRawDecoder::cRawDecoder(IDataSource* stream, unsigned int frequency, AudioFormats format) : IAudioDecoder(stream), Frequency(frequency), Format(format)
{
}
cRawDecoder::~cRawDecoder()
{
}
//!Returns wav channel format
AudioFormats cRawDecoder::getFormat()
{
return Format;
}
//!Returns wav data frequency
int cRawDecoder::getFrequency()
{
return Frequency;
}
//!Returns if seeking is supported
bool cRawDecoder::isSeekingSupported()
{
return false;
}
//!Reads wav data
int cRawDecoder::readAudioData(void* output, int amount)
{
return Stream->read(output,amount);
}
//!Sets data reader position
bool cRawDecoder::setPosition(int position, bool relative)
{
Stream->seek(position,relative);
return true;
}
//!Seeks wav data
bool cRawDecoder::seek(float seconds,bool relative)
{
return false;
}
}

View File

@ -67,6 +67,10 @@ namespace cAudio{
//!Sets data reader position
bool cWavDecoder::setPosition(int position, bool relative)
{
//Safety to avoid reading the header as audio data
if(!relative && position < 44)
position = 44;
Stream->seek(position,relative);
return true;
}

View File

@ -9,6 +9,8 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Tutorial2_3DSound", "Exampl
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Tutorial3_MemoryPlayback", "Examples\Tutorial3_MemoryPlayback\Tutorial3_MemoryPlayback.vcproj", "{FEA3B340-BBB2-4AFB-AF31-3962A0F3F2C6}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Tutorial4_AudioCapture", "Examples\Tutorial4_AudioCapture\Tutorial4_AudioCapture.vcproj", "{F04BE31E-E8CC-40C8-9C63-EEAE1BF84EB7}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Win32 = Debug|Win32
@ -31,6 +33,10 @@ Global
{FEA3B340-BBB2-4AFB-AF31-3962A0F3F2C6}.Debug|Win32.Build.0 = Debug|Win32
{FEA3B340-BBB2-4AFB-AF31-3962A0F3F2C6}.Release|Win32.ActiveCfg = Release|Win32
{FEA3B340-BBB2-4AFB-AF31-3962A0F3F2C6}.Release|Win32.Build.0 = Release|Win32
{F04BE31E-E8CC-40C8-9C63-EEAE1BF84EB7}.Debug|Win32.ActiveCfg = Debug|Win32
{F04BE31E-E8CC-40C8-9C63-EEAE1BF84EB7}.Debug|Win32.Build.0 = Debug|Win32
{F04BE31E-E8CC-40C8-9C63-EEAE1BF84EB7}.Release|Win32.ActiveCfg = Release|Win32
{F04BE31E-E8CC-40C8-9C63-EEAE1BF84EB7}.Release|Win32.Build.0 = Release|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE

View File

@ -178,6 +178,10 @@
RelativePath=".\Headers\cAudio.h"
>
</File>
<File
RelativePath=".\Headers\cAudioCapture.h"
>
</File>
<File
RelativePath=".\Headers\cAudioManager.h"
>
@ -202,12 +206,20 @@
RelativePath=".\Headers\cOggDecoder.h"
>
</File>
<File
RelativePath=".\Headers\cRawAudioDecoderFactory.h"
>
</File>
<File
RelativePath=".\Headers\cRawDecoder.h"
>
</File>
<File
RelativePath=".\Headers\cUtils.h"
>
</File>
<File
RelativePath=".\Headers\cVector3.h"
RelativePath=".\include\cVector3.h"
>
</File>
<File
@ -218,10 +230,18 @@
RelativePath=".\Headers\cWavDecoder.h"
>
</File>
<File
RelativePath=".\include\eAudioFormats.h"
>
</File>
<File
RelativePath=".\include\IAudio.h"
>
</File>
<File
RelativePath=".\include\IAudioCapture.h"
>
</File>
<File
RelativePath=".\include\IAudioDecoder.h"
>
@ -258,6 +278,10 @@
RelativePath=".\Source\cAudio.cpp"
>
</File>
<File
RelativePath=".\Source\cAudioCapture.cpp"
>
</File>
<File
RelativePath=".\Source\cAudioManager.cpp"
>
@ -282,6 +306,10 @@
RelativePath=".\Source\cOggDecoder.cpp"
>
</File>
<File
RelativePath=".\Source\cRawDecoder.cpp"
>
</File>
<File
RelativePath=".\Source\cWavAudioDecoderFactory.cpp"
>

View File

@ -21,7 +21,7 @@ namespace cAudio
virtual void setPosition(float posx,float posy,float posz) = 0;
//!allows you to set the audio objects velocity
virtual void setVelocity(float velx,float vely,float velz) = 0;
//!allows us to set the direction the audio should play in / move
//!allows us to set the direction the audio should play in
virtual void setDirection(float dirx,float diry,float dirz) = 0;
//! Sets the audios pitch level
virtual void setPitch(float pitch) = 0;

62
include/IAudioCapture.h Normal file
View File

@ -0,0 +1,62 @@
#ifndef IAUDIOCAPTURE_H
#define IAUDIOCAPTURE_H
#include "eAudioFormats.h"
namespace cAudio
{
class IAudioCapture
{
public:
//! Initializes the capture device to the selected settings
/** Note that calling this will cause the capture device to be reinitialized. Calling while in use may lead to a loss of audio data.
\param frequency: Frequency that the captured audio will be at
\param format: Format of the captured audio
\param internalBufferSize: Size of the internal OpenAL buffer used to store the captured audio until the next IAudioManager::update() in bytes
\return True on success, False if the capture device failed to initialize.
*/
virtual bool initialize(unsigned int frequency = 22050, AudioFormats format = EAF_16BIT_MONO, unsigned int internalBufferSize = 8192) = 0;
//! Returns true if the current OpenAL implementation supports capturing audio
virtual bool isSupported() = 0;
//! Returns true if the capture device is ready to be used. False may indicate an error with the current settings.
virtual bool isReady() = 0;
//! Returns the frequency that the captured audio will be at
virtual unsigned int getFrequency() = 0;
//! Returns the format of the captured audio
virtual AudioFormats getFormat() = 0;
//! Returns the internal OpenAL buffer size in bytes
virtual unsigned int getInternalBufferSize() = 0;
//! Returns the size of a "sample" of audio data. Useful for making sure you grab audio data at sample boundaries
virtual unsigned int getSampleSize() = 0;
//! Sets the frequency that the captured audio will be at. Will cause the capture device to be reinitialized. Calling while in use may lead to a loss of audio data.
/** \return True on success, False if the capture device failed to initialize. */
virtual bool setFrequency(unsigned int frequency) = 0;
//! Sets the format that the captured audio will be at. Will cause the capture device to be reinitialized. Calling while in use may lead to a loss of audio data.
/** \return True on success, False if the capture device failed to initialize. */
virtual bool setFormat(AudioFormats format) = 0;
//! Sets the internal buffer size that OpenAL will use to store captured audio between calls to IAudioManager::update() in bytes. Will cause the capture device to be reinitialized. Calling while in use may lead to a loss of audio data.
/** \return True on success, False if the capture device failed to initialize. */
virtual bool setInternalBufferSize(unsigned int internalBufferSize) = 0;
//! Starts capturing audio data to an internal buffer. Will clear any old data in the buffer.
/** \return True if capture was successfully started. */
virtual bool beginCapture() = 0;
//! Stops capturing audio data to an internal buffer.
virtual void stopCapture() = 0;
//! Allows access to the audio data in the internal capture buffer
/** Can be called at any time to retrieve recorded audio. It is recommended that you call it every so often to prevent the internal buffer from growing too large.
Once successfully retrieved, the captured audio will be deleted from the internal buffer.
\param outputBuffer: Pointer to an output array to copy audio data to.
\param outputBufferSize: Size of the output array in bytes
*/
virtual void getCapturedAudio(void* outputBuffer, unsigned int outputBufferSize) = 0;
//! Returns the current size of the internal audio buffer in bytes
virtual unsigned int getCurrentCapturedAudioSize() = 0;
protected:
};
};
#endif //! IAUDIOCAPTURE_H

View File

@ -2,19 +2,11 @@
#define IAUDIODECODER_H
#include "IDataSource.h"
#include "eAudioFormats.h"
namespace cAudio
{
enum AudioFormats
{
EAF_8BIT_MONO = 0x1100,
EAF_8BIT_STEREO = 0x1102,
EAF_16BIT_MONO = 0x1101,
EAF_16BIT_STEREO = 0x1103,
EAF_COUNT
};
class IAudioDecoder
{
public:

View File

@ -3,6 +3,7 @@
#define IAUDIOMANAGER_H
#include <string>
#include "IListener.h"
#include "IAudioCapture.h"
#ifndef CAUDIO_STATIC_LIB
@ -28,24 +29,39 @@ namespace cAudio
virtual void init(int argc,char* argv[]) = 0;
//!Shuts everything down
virtual void shutDown() = 0;
//!Updates the cAudio playback
virtual void update() = 0;
//!Returns an IAudio object by its "name" and 0 if the name is not found
virtual IAudio *getSound(std::string identifier) = 0;
//!Releases "ALL" cAudio objects (but does not shutdown the manager)
virtual void release() = 0;
//!Creates the cAudio object
virtual IAudio* createFromFile(const std::string& identifier,const std::string& file,bool stream = false) = 0;
//!Loads audio from memory or virtual file system
virtual IAudio* createFromMemory(const std::string& identifier,const char* data, size_t length, std::string ext) = 0;
//!Register Audio Codec
virtual void registerAudioDecoder(IAudioDecoderFactory* factory, std::string extension) = 0;
//!Allows you to set the listener position
virtual void setListenerPos(float x,float y,float z) = 0;
//!set the listeners orientation
virtual void setListenerOrientation(float ux,float uy,float uz) = 0;
//!Updates the cAudio playback
virtual void update() = 0;
//!Gets you the cAudio object you want
virtual IAudio *getSound(std::string identifier) = 0;
//!Releases "ALL" cAudio objects
virtual void release() = 0;
//!Loads raw audio from memory.
virtual IAudio* createFromRaw(const std::string& identifier,const char* data, size_t length, unsigned int frequency, AudioFormats format) = 0;
//!Register Audio Codec
virtual bool registerAudioDecoder(IAudioDecoderFactory* factory, std::string extension) = 0;
//!Unregister Audio Codec (allows you to prevent an file type from being playable with new sound sources)
//!Note that all current sound sources will still continue to use any currently allocated decoders.
virtual void unRegisterAudioDecoder(std::string extension) = 0;
//!Returns whether an audio decoder is currently registered for this file type
virtual bool isAudioDecoderRegistered(std::string extension) = 0;
//!Returns a registered audio decoder factory
virtual IAudioDecoderFactory* getAudioDecoderFactory(std::string extension) = 0;
//!Allows you to set the listener position (DEPRECIATED! USE getListener() INSTEAD!)
virtual void setListenerPos(float x,float y,float z) = 0;
//!set the listeners orientation (DEPRECIATED! USE getListener() INSTEAD!)
virtual void setListenerOrientation(float ux,float uy,float uz) = 0;
//!Returns an interface for the listener
virtual IListener* getListener() = 0;
//!Returns an interface for audio capture
virtual IAudioCapture* getAudioCapture() = 0;
virtual ~IAudioManager() {}
protected:

View File

@ -2,7 +2,7 @@
#ifndef ILISTENER_H
#define ILISTENER_H
#include "../Headers/cVector3.h"
#include "cVector3.h"
namespace cAudio
{

17
include/eAudioFormats.h Normal file
View File

@ -0,0 +1,17 @@
#ifndef EAUDIOFORMATS_H
#define EAUDIOFORMATS_H
namespace cAudio
{
enum AudioFormats
{
EAF_8BIT_MONO = 0x1100,
EAF_8BIT_STEREO = 0x1102,
EAF_16BIT_MONO = 0x1101,
EAF_16BIT_STEREO = 0x1103
};
};
#endif //! EAUDIOFORMATS_H