cAudioCapture.cpp
00001
00002
00003
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
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
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
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
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
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
00171 if(availbuffersize > InternalBufferSize / 2 || force)
00172 {
00173
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
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
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