cAudioCapture.cpp

00001 // Copyright (c) 2008-2010 Raynaldo (Wildicv) Rivera, Joshua (Dark_Kilauea) Jones
00002 // This file is part of the "cAudio Engine"
00003 // For conditions of distribution and use, see copyright notice in cAudio.h
00004 
00005 #include "../Headers/cAudioCapture.h"
00006 #include "../Headers/cUtils.h"
00007 #include "../Headers/cThread.h"
00008 #include "../include/cAudioSleep.h"
00009 #include "../Headers/cLogger.h"
00010 #include "../Headers/cPluginManager.h"
00011 
00012 #include <string.h>
00013 #include <set>
00014 
00015 namespace cAudio
00016 {
00017         static bool RunAudioCaptureThread(false);
00018 
00019         //Note: OpenAL is threadsafe, so a mutex only needs to protect the class state
00020 #ifdef CAUDIO_USE_INTERNAL_THREAD
00021         static cAudioMutex AudioCaptureObjectsMutex;
00022         static std::set<IAudioCapture*> AudioCaptureObjects;
00023 
00024         CAUDIO_DECLARE_THREAD_FUNCTION(AudioCaptureUpdateThread)
00025         {
00026                 while(RunAudioCaptureThread)
00027                 {
00028                         AudioCaptureObjectsMutex.lock();
00029                         std::set<IAudioCapture*>::iterator it;
00030                         for ( it=AudioCaptureObjects.begin() ; it != AudioCaptureObjects.end(); it++ )
00031                         {
00032                                 (*it)->updateCaptureBuffer();
00033                         }
00034                         AudioCaptureObjectsMutex.unlock();
00035                         cAudioSleep(1);
00036                 }
00037                 return 0;
00038         }
00039 #endif
00040 
00041         cAudioCapture::cAudioCapture() : Frequency(22050), Format(EAF_16BIT_MONO), InternalBufferSize(8192),
00042                                                                         SampleSize(2), Supported(false), Ready(false), Capturing(false), 
00043                                                                         CaptureDevice(NULL)
00044         {
00045                 checkCaptureExtension();
00046                 getAvailableDevices();
00047         }
00048         cAudioCapture::~cAudioCapture()
00049         {
00050                 shutdown();
00051         }
00052 
00053         bool cAudioCapture::checkCaptureExtension()
00054         {
00055                 cAudioMutexBasicLock lock(Mutex);
00056                 // Check for Capture Extension support
00057                 Supported = ( alcIsExtensionPresent(NULL, "ALC_EXT_CAPTURE") == AL_TRUE );
00058                 return Supported;
00059         }
00060 
00061         bool cAudioCapture::initOpenALDevice()
00062         {
00063                 cAudioMutexBasicLock lock(Mutex);
00064                 if(Supported)
00065                 {
00066                         if(CaptureDevice)
00067                                 shutdownOpenALDevice();
00068                         if(DeviceName.empty())
00069                                 CaptureDevice = alcCaptureOpenDevice(NULL, Frequency, convertAudioFormatEnum(Format), InternalBufferSize / SampleSize);
00070                         else
00071                                 CaptureDevice = alcCaptureOpenDevice(DeviceName.c_str(), Frequency, convertAudioFormatEnum(Format), InternalBufferSize / SampleSize);
00072                         if(CaptureDevice)
00073                         {
00074                                 DeviceName = alcGetString(CaptureDevice, ALC_CAPTURE_DEVICE_SPECIFIER);
00075                                 Ready = true;
00076                                 checkError();
00077                                 getLogger()->logDebug("AudioCapture", "OpenAL Capture Device Opened.");
00078 
00079                                 return true;
00080                         }
00081                 }
00082                 checkError();
00083                 return false;
00084         }
00085 
00086         void cAudioCapture::shutdownOpenALDevice()
00087         {
00088                 cAudioMutexBasicLock lock(Mutex);
00089                 if(Supported)
00090                 {
00091                         if(Capturing)
00092                                 stopCapture();
00093 
00094                         if(CaptureDevice)
00095                         {
00096                                 alcCaptureCloseDevice(CaptureDevice);
00097                                 CaptureDevice = NULL;
00098                                 Ready = false;
00099                                 getLogger()->logDebug("AudioCapture", "OpenAL Capture Device Closed.");
00100                                 signalEvent(ON_RELEASE);
00101                         }
00102                         checkError();
00103                         CaptureBuffer.clear();
00104                 }
00105         }
00106 
00107         void cAudioCapture::shutdown()
00108         {
00109                 cAudioMutexBasicLock lock(Mutex);
00110                 shutdownOpenALDevice();
00111                 signalEvent(ON_RELEASE);
00112         }
00113 
00114         void cAudioCapture::getAvailableDevices()
00115         {
00116                 // Get list of available Capture Devices
00117                 cAudioMutexBasicLock lock(Mutex);
00118                 if( alcIsExtensionPresent(NULL, "ALC_ENUMERATION_EXT") == AL_TRUE )
00119                 {
00120                         const char* deviceList = alcGetString(NULL, ALC_CAPTURE_DEVICE_SPECIFIER);
00121                         if (deviceList)
00122                         {
00123                                 while(*deviceList)
00124                                 {
00125                                         std::string device(deviceList);
00126                                         AvailableDevices.push_back(device);
00127                                         deviceList += strlen(deviceList) + 1;
00128                                 }
00129                         }
00130 
00131                         // Get the name of the 'default' capture device
00132                         DefaultDevice = alcGetString(NULL, ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER);
00133                 }
00134         }
00135 
00136         const char* cAudioCapture::getAvailableDeviceName(unsigned int index)
00137         {
00138                 cAudioMutexBasicLock lock(Mutex);
00139                 if(!AvailableDevices.empty())
00140                 {
00141                         //Bounds check
00142                         if( index > (AvailableDevices.size()-1) ) index = (AvailableDevices.size()-1);
00143                         const char* deviceName = AvailableDevices[index].c_str();
00144                         return deviceName;
00145                 }
00146                 return "";
00147         }
00148 
00149         unsigned int cAudioCapture::getAvailableDeviceCount()
00150         {
00151                 cAudioMutexBasicLock lock(Mutex);
00152                 return AvailableDevices.size();
00153         }
00154 
00155         const char* cAudioCapture::getDefaultDeviceName()
00156         {
00157                 cAudioMutexBasicLock lock(Mutex);
00158                 return DefaultDevice.empty() ? "" : DefaultDevice.c_str();
00159         }
00160 
00161         void cAudioCapture::updateCaptureBuffer(bool force)
00162         {
00163                 cAudioMutexBasicLock lock(Mutex);
00164                 if(Capturing && CaptureDevice && Ready)
00165                 {
00166                         int AvailableSamples = 0;
00167                         alcGetIntegerv(CaptureDevice, ALC_CAPTURE_SAMPLES, 1, &AvailableSamples);
00168                         const unsigned int availbuffersize = AvailableSamples * SampleSize;
00169 
00170                         //If the samples in the OpenAL buffer are more than half of its max size, grab them
00171                         if(availbuffersize > InternalBufferSize / 2 || force)
00172                         {
00173                                 //Fixes a bug with the capture being forced, but no data being available
00174                                 if(availbuffersize > 0)
00175                                 {
00176                                         const unsigned int oldBufferSize = CaptureBuffer.size();
00177                                         CaptureBuffer.resize(oldBufferSize + availbuffersize, 0);
00178                                         alcCaptureSamples(CaptureDevice, &CaptureBuffer[oldBufferSize], AvailableSamples);
00179                                         checkError();
00180                                         getLogger()->logDebug("AudioCapture", "Captured %i bytes of audio data.", availbuffersize);
00181                                         signalEvent(ON_UPDATE);
00182                                 }
00183                         }
00184                 }
00185         }
00186 
00187         bool cAudioCapture::beginCapture()
00188         {
00189                 cAudioMutexBasicLock lock(Mutex);
00190                 if(!Capturing)
00191                 {
00192                         CaptureBuffer.clear();
00193                         if(CaptureDevice && Ready)
00194                         {
00195                                 alcCaptureStart(CaptureDevice);
00196                                 Capturing = true;
00197                                 getLogger()->logDebug("AudioCapture", "OpenAL Capture Started.");
00198                                 signalEvent(ON_BEGINCAPTURE);
00199                         }
00200                         checkError();
00201                         return Capturing;
00202                 }
00203                 checkError();
00204                 return false;
00205         }
00206 
00207         void cAudioCapture::stopCapture()
00208         {
00209                 cAudioMutexBasicLock lock(Mutex);
00210                 if(CaptureDevice && Ready)
00211                 {
00212                         alcCaptureStop(CaptureDevice);
00213                         updateCaptureBuffer(true);
00214                         checkError();
00215                         getLogger()->logDebug("AudioCapture", "OpenAL Capture Stopped.");
00216                         signalEvent(ON_ENDCAPTURE);
00217                 }
00218                 Capturing = false;
00219         }
00220 
00221         unsigned int cAudioCapture::getCapturedAudio(void* outputBuffer, unsigned int outputBufferSize)
00222         {
00223                 cAudioMutexBasicLock lock(Mutex);
00224                 unsigned int internalBufferSize = CaptureBuffer.size();
00225                 if(outputBuffer && outputBufferSize > 0 && internalBufferSize > 0)
00226                 {
00227                         int sizeToCopy = (outputBufferSize >= internalBufferSize) ? internalBufferSize : outputBufferSize;
00228                         memcpy(outputBuffer, &CaptureBuffer[0], sizeToCopy);
00229                         CaptureBuffer.erase(CaptureBuffer.begin(), CaptureBuffer.begin()+sizeToCopy);
00230 
00231                         getLogger()->logDebug("AudioCapture", "Copied out %i bytes of data out of %i bytes in the buffer at user request.", sizeToCopy, internalBufferSize);
00232                         signalEvent(ON_USERREQUESTEDBUFFER);
00233                         return sizeToCopy;
00234                 }
00235                 return 0;
00236         }
00237 
00238         unsigned int cAudioCapture::getCurrentCapturedAudioSize()
00239         {
00240                 cAudioMutexBasicLock lock(Mutex);
00241                 return CaptureBuffer.size();
00242         }
00243 
00244         bool cAudioCapture::setFrequency(unsigned int frequency)
00245         {
00246                 cAudioMutexBasicLock lock(Mutex);
00247                 Frequency = frequency;
00248                 shutdownOpenALDevice();
00249                 return initOpenALDevice();
00250         }
00251 
00252         bool cAudioCapture::setFormat(AudioFormats format)
00253         {
00254                 cAudioMutexBasicLock lock(Mutex);
00255                 Format = format;
00256                 if(Format == EAF_8BIT_MONO)
00257                         SampleSize = 1;
00258                 else if(Format == EAF_8BIT_STEREO)
00259                         SampleSize = 2;
00260                 else if(Format == EAF_16BIT_MONO)
00261                         SampleSize = 2;
00262                 else
00263                         SampleSize = 4;
00264 
00265                 shutdownOpenALDevice();
00266                 return initOpenALDevice();
00267         }
00268 
00269         bool cAudioCapture::setInternalBufferSize(unsigned int internalBufferSize)
00270         {
00271                 cAudioMutexBasicLock lock(Mutex);
00272                 InternalBufferSize = internalBufferSize;
00273 
00274                 shutdownOpenALDevice();
00275                 return initOpenALDevice();
00276         }
00277 
00278         bool cAudioCapture::setDevice(const char* deviceName)
00279         {
00280                 cAudioMutexBasicLock lock(Mutex);
00281                 DeviceName = safeCStr(deviceName);
00282 
00283                 shutdownOpenALDevice();
00284                 return initOpenALDevice();
00285         }
00286 
00287         bool cAudioCapture::initialize(const char* deviceName, unsigned int frequency, AudioFormats format, unsigned int internalBufferSize)
00288         {
00289                 cAudioMutexBasicLock lock(Mutex);
00290                 DeviceName = safeCStr(deviceName);
00291                 Frequency = frequency;
00292                 InternalBufferSize = internalBufferSize;
00293 
00294                 Format = format;
00295                 if(Format == EAF_8BIT_MONO)
00296                         SampleSize = 1;
00297                 else if(Format == EAF_8BIT_STEREO)
00298                         SampleSize = 2;
00299                 else if(Format == EAF_16BIT_MONO)
00300                         SampleSize = 2;
00301                 else
00302                         SampleSize = 4;
00303 
00304                 shutdownOpenALDevice();
00305                 signalEvent(ON_INIT);
00306                 return initOpenALDevice();
00307         }
00308 
00309         bool cAudioCapture::checkError()
00310         {
00311                 if(CaptureDevice)
00312                 {
00313                         int error = alcGetError(CaptureDevice);
00314                         if (error != AL_NO_ERROR)
00315                         {
00316                                 const char* errorString = alGetString(error);
00317                                 getLogger()->logError("AudioCapture", "OpenAL Error: %s.", errorString);
00318                                 return true;
00319                         }
00320                 }
00321                 return false;
00322         }
00323 
00324         ALenum cAudioCapture::convertAudioFormatEnum(AudioFormats format)
00325         {
00326                 switch(format)
00327                 {
00328                 case EAF_8BIT_MONO:
00329                         return AL_FORMAT_MONO8;
00330                 case EAF_16BIT_MONO:
00331                         return AL_FORMAT_MONO16;
00332                 case EAF_8BIT_STEREO:
00333                         return AL_FORMAT_STEREO8;
00334                 case EAF_16BIT_STEREO:
00335                         return AL_FORMAT_STEREO16;
00336                 default:
00337                         return AL_FORMAT_MONO8;
00338                 };
00339         }
00340 
00341         CAUDIO_API IAudioCapture* createAudioCapture(bool initializeDefault)
00342         {
00343                 cAudioCapture* capture = new cAudioCapture;
00344                 if(capture)
00345                 {
00346                         if(initializeDefault)
00347                                 capture->initialize();
00348 
00349                         std::vector<IAudioPlugin*> plugins = cPluginManager::Instance()->getPluginList();
00350                         for(unsigned int i = 0; i < plugins.size(); ++i)
00351                         {
00352                                 plugins[i]->onCreateAudioCapture(capture);
00353                         }
00354 
00355 #ifdef CAUDIO_USE_INTERNAL_THREAD
00356                         AudioCaptureObjectsMutex.lock();
00357                         AudioCaptureObjects.insert(capture);
00358 
00359                         //First time launch of thread
00360                         if(!RunAudioCaptureThread && AudioCaptureObjects.size() > 0)
00361                                 RunAudioCaptureThread = (cAudioThread::SpawnThread(AudioCaptureUpdateThread, NULL) == 0);
00362                         AudioCaptureObjectsMutex.unlock();
00363 #endif
00364                 }
00365                 return capture;
00366         }
00367 
00368         CAUDIO_API void destroyAudioCapture(IAudioCapture* capture)
00369         {
00370                 if(capture)
00371                 {
00372 #ifdef CAUDIO_USE_INTERNAL_THREAD
00373                         AudioCaptureObjectsMutex.lock();
00374                         AudioCaptureObjects.erase(capture);
00375 
00376                         //Kill the thread if there are no objects to process anymore
00377                         if(RunAudioCaptureThread && AudioCaptureObjects.empty())
00378                                 RunAudioCaptureThread = false;
00379                         AudioCaptureObjectsMutex.unlock();
00380 #endif
00381                         std::vector<IAudioPlugin*> plugins = cPluginManager::Instance()->getPluginList();
00382                         for(unsigned int i = 0; i < plugins.size(); ++i)
00383                         {
00384                                 plugins[i]->onDestoryAudioCapture(capture);
00385                         }
00386 
00387                         delete capture;
00388                         capture = NULL;
00389                 }
00390         }
00391 
00392         CAUDIO_API bool isAudioCaptureThreadRunning()
00393         {
00394                 return RunAudioCaptureThread;
00395         }
00396 
00397 
00398         void cAudioCapture::registerEventHandler(ICaptureEventHandler* handler)
00399         {
00400                 if(handler)
00401                 {
00402                         eventHandlerList.push_back(handler);
00403                 }
00404         }
00405 
00406         void cAudioCapture::unRegisterEventHandler(ICaptureEventHandler* handler)
00407         {
00408                 if(handler)
00409                 {
00410                         eventHandlerList.remove(handler);
00411                 }
00412         }
00413 
00414         void cAudioCapture::unRegisterAllEventHandlers()
00415         {
00416                 eventHandlerList.clear();
00417         }
00418 
00419         void cAudioCapture::signalEvent(Events sevent)
00420         {
00421                 cAudioMutexBasicLock lock(Mutex);
00422                 std::list<ICaptureEventHandler*>::iterator it = eventHandlerList.begin();
00423 
00424                 if(it != eventHandlerList.end()){
00425 
00426                         switch(sevent){
00427 
00428                                 case ON_INIT: 
00429                                         
00430                                         for(it; it != eventHandlerList.end(); it++){
00431                                                 (*it)->onInit();
00432                                         }
00433 
00434                                         break;
00435                                 
00436                                 case ON_UPDATE:
00437 
00438                                         for(it; it != eventHandlerList.end(); it++){
00439                                                 (*it)->onUpdate();
00440                                         }
00441 
00442                                         break;
00443 
00444                                 case ON_RELEASE:
00445 
00446                                         for(it; it != eventHandlerList.end(); it++){
00447                                                 (*it)->onRelease();
00448                                         }
00449 
00450                                         break;
00451 
00452                                 case ON_BEGINCAPTURE:
00453 
00454                                         for(it; it != eventHandlerList.end(); it++){
00455                                                 (*it)->onBeginCapture();
00456                                         }
00457 
00458 
00459                                         break;
00460 
00461                                 case ON_ENDCAPTURE:
00462 
00463                                         for(it; it != eventHandlerList.end(); it++){
00464                                                 (*it)->onEndCapture();
00465                                         }
00466 
00467                                         break;
00468 
00469                                 case ON_USERREQUESTEDBUFFER:
00470 
00471                                         for(it; it != eventHandlerList.end(); it++){
00472                                                 (*it)->onUserRequestBuffer();
00473                                         }
00474 
00475                                         break;
00476                         }
00477                 }
00478         }
00479 };
00480 
 All Classes Namespaces Functions Variables Enumerations

Generated on Sat Feb 20 22:55:08 2010 for cAudio by  doxygen 1.6.2