cAudio  2.3.0
3d Audio Engine
cAudioCapture.cpp
1 // Copyright (c) 2008-2011 Raynaldo (Wildicv) Rivera, Joshua (Dark_Kilauea) Jones, Murat (wolfmanfx) Sari
2 // This file is part of the "cAudio Engine"
3 // For conditions of distribution and use, see copyright notice in cAudio.h
4 
5 #include "cAudio.h"
6 #include "cAudioCapture.h"
7 #include "cUtils.h"
8 #include "cThread.h"
9 #include "cAudioSleep.h"
10 #include "cLogger.h"
11 #include "cPluginManager.h"
12 
13 #include <string.h>
14 
15 namespace cAudio
16 {
17  cAudioCapture::cAudioCapture() : AudioThread(NULL), Frequency(22050), Format(EAF_16BIT_MONO),
18  InternalBufferSize(8192), SampleSize(2), Ready(false),
19  Capturing(false), CaptureDevice(NULL)
20  {
21 
22  }
23  cAudioCapture::~cAudioCapture()
24  {
25  cAudioCapture::shutdown();
26  }
27 
28  void cAudioCapture::run()
29  {
30  updateCaptureBuffer();
31  cAudioSleep(1);
32  }
33 
34  bool cAudioCapture::initOpenALDevice()
35  {
36  cAudioMutexBasicLock lock(Mutex);
37  if(CaptureDevice)
38  shutdownOpenALDevice();
39  if(DeviceName.empty())
40  CaptureDevice = alcCaptureOpenDevice(NULL, Frequency, convertAudioFormatEnum(Format), InternalBufferSize / SampleSize);
41  else
42  CaptureDevice = alcCaptureOpenDevice(toUTF8(DeviceName), Frequency, convertAudioFormatEnum(Format), InternalBufferSize / SampleSize);
43  if(CaptureDevice)
44  {
45  DeviceName = fromUTF8(alcGetString(CaptureDevice, ALC_CAPTURE_DEVICE_SPECIFIER));
46  Ready = true;
47  checkError();
48  getLogger()->logDebug("AudioCapture", "OpenAL Capture Device Opened.");
49 
50  return true;
51  }
52  checkError();
53 
54  return false;
55  }
56 
57  void cAudioCapture::shutdownOpenALDevice()
58  {
59  cAudioMutexBasicLock lock(Mutex);
60  if(Capturing)
61  stopCapture();
62 
63  if(CaptureDevice)
64  {
65  alcCaptureCloseDevice(CaptureDevice);
66  CaptureDevice = NULL;
67  Ready = false;
68  getLogger()->logDebug("AudioCapture", "OpenAL Capture Device Closed.");
69  signalEvent(ON_RELEASE);
70  }
71  checkError();
72  CaptureBuffer.clear();
73  }
74 
75  void cAudioCapture::shutdown()
76  {
77  cAudioMutexBasicLock lock(Mutex);
78 
79  if (AudioThread)
80  {
81  AudioThread->join();
82  delete AudioThread;
83  AudioThread = NULL;
84  }
85 
86  shutdownOpenALDevice();
87  signalEvent(ON_RELEASE);
88  }
89 
90  void cAudioCapture::updateCaptureBuffer(bool force)
91  {
92  cAudioMutexBasicLock lock(Mutex);
93  if(Capturing && CaptureDevice && Ready)
94  {
95  int AvailableSamples = 0;
96  alcGetIntegerv(CaptureDevice, ALC_CAPTURE_SAMPLES, 1, &AvailableSamples);
97  const unsigned int availbuffersize = AvailableSamples * SampleSize;
98 
99  //If the samples in the OpenAL buffer are more than half of its max size, grab them
100  if(availbuffersize > InternalBufferSize / 2 || force)
101  {
102  //Fixes a bug with the capture being forced, but no data being available
103  if(availbuffersize > 0)
104  {
105  const unsigned int oldBufferSize = CaptureBuffer.size();
106  CaptureBuffer.resize(oldBufferSize + availbuffersize, 0);
107  alcCaptureSamples(CaptureDevice, &CaptureBuffer[oldBufferSize], AvailableSamples);
108  checkError();
109  getLogger()->logDebug("AudioCapture", "Captured %i bytes of audio data.", availbuffersize);
110  signalEvent(ON_UPDATE);
111  }
112  }
113  }
114  }
115 
116  bool cAudioCapture::beginCapture()
117  {
118  cAudioMutexBasicLock lock(Mutex);
119  if(!Capturing)
120  {
121  CaptureBuffer.clear();
122  if(CaptureDevice && Ready)
123  {
124  alcCaptureStart(CaptureDevice);
125  Capturing = true;
126  getLogger()->logDebug("AudioCapture", "OpenAL Capture Started.");
127  signalEvent(ON_BEGINCAPTURE);
128  }
129  checkError();
130  return Capturing;
131  }
132  checkError();
133  return false;
134  }
135 
136  void cAudioCapture::stopCapture()
137  {
138  cAudioMutexBasicLock lock(Mutex);
139  if(CaptureDevice && Ready)
140  {
141  alcCaptureStop(CaptureDevice);
142  updateCaptureBuffer(true);
143  checkError();
144  getLogger()->logDebug("AudioCapture", "OpenAL Capture Stopped.");
145  signalEvent(ON_ENDCAPTURE);
146  }
147  Capturing = false;
148  }
149 
150  AudioCaptureBuffer* cAudioCapture::getCapturedAudioBuffer()
151  {
152  AudioCaptureBuffer* buffer = new AudioCaptureBuffer(CaptureBuffer.size());
153  getCapturedAudio(buffer->getWriteBuffer(), buffer->getLength());
154  return buffer;
155  }
156 
157  unsigned int cAudioCapture::getCapturedAudio(void* outputBuffer, unsigned int outputBufferSize)
158  {
159  cAudioMutexBasicLock lock(Mutex);
160  unsigned int internalBufferSize = CaptureBuffer.size();
161  if(outputBuffer && outputBufferSize > 0 && internalBufferSize > 0)
162  {
163  int sizeToCopy = (outputBufferSize >= internalBufferSize) ? internalBufferSize : outputBufferSize;
164  memcpy(outputBuffer, &CaptureBuffer[0], sizeToCopy);
165  CaptureBuffer.erase(CaptureBuffer.begin(), CaptureBuffer.begin()+sizeToCopy);
166 
167  getLogger()->logDebug("AudioCapture", "Copied out %i bytes of data out of %i bytes in the buffer at user request.", sizeToCopy, internalBufferSize);
168  signalEvent(ON_USERREQUESTEDBUFFER);
169  return sizeToCopy;
170  }
171  return 0;
172  }
173 
174  unsigned int cAudioCapture::getCurrentCapturedAudioSize()
175  {
176  cAudioMutexBasicLock lock(Mutex);
177  return CaptureBuffer.size();
178  }
179 
180  bool cAudioCapture::setFrequency(unsigned int frequency)
181  {
182  cAudioMutexBasicLock lock(Mutex);
183  Frequency = frequency;
184  shutdownOpenALDevice();
185  return initOpenALDevice();
186  }
187 
188  bool cAudioCapture::setFormat(AudioFormats format)
189  {
190  cAudioMutexBasicLock lock(Mutex);
191  Format = format;
192  if(Format == EAF_8BIT_MONO)
193  SampleSize = 1;
194  else if(Format == EAF_8BIT_STEREO)
195  SampleSize = 2;
196  else if(Format == EAF_16BIT_MONO)
197  SampleSize = 2;
198  else
199  SampleSize = 4;
200 
201  shutdownOpenALDevice();
202  return initOpenALDevice();
203  }
204 
205  bool cAudioCapture::setInternalBufferSize(unsigned int internalBufferSize)
206  {
207  cAudioMutexBasicLock lock(Mutex);
208  InternalBufferSize = internalBufferSize;
209 
210  shutdownOpenALDevice();
211  return initOpenALDevice();
212  }
213 
214  bool cAudioCapture::setDevice(const char* deviceName)
215  {
216  cAudioMutexBasicLock lock(Mutex);
217  DeviceName = fromUTF8(deviceName);
218 
219  shutdownOpenALDevice();
220  return initOpenALDevice();
221  }
222 
223  bool cAudioCapture::initialize(const char* deviceName, unsigned int frequency, AudioFormats format, unsigned int internalBufferSize)
224  {
225  cAudioMutexBasicLock lock(Mutex);
226  DeviceName = fromUTF8(deviceName);
227  Frequency = frequency;
228  InternalBufferSize = internalBufferSize;
229 
230  Format = format;
231  if(Format == EAF_8BIT_MONO)
232  SampleSize = 1;
233  else if(Format == EAF_8BIT_STEREO)
234  SampleSize = 2;
235  else if(Format == EAF_16BIT_MONO)
236  SampleSize = 2;
237  else
238  SampleSize = 4;
239 
240  shutdownOpenALDevice();
241  signalEvent(ON_INIT);
242  bool isInit = initOpenALDevice();
243 
244 #ifdef CAUDIO_USE_INTERNAL_THREAD
245  if (!AudioThread)
246  {
247  AudioThread = new cAudioThread(this);
248  }
249  AudioThread->start();
250 #endif
251  return isInit;
252  }
253 
254  bool cAudioCapture::checkError()
255  {
256  if(CaptureDevice)
257  {
258  int error = alcGetError(CaptureDevice);
259  if (error != AL_NO_ERROR)
260  {
261  const char* errorString = alGetString(error);
262  getLogger()->logError("AudioCapture", "OpenAL Error: %s.", errorString);
263  return true;
264  }
265  }
266  return false;
267  }
268 
269  ALenum cAudioCapture::convertAudioFormatEnum(AudioFormats format)
270  {
271  switch(format)
272  {
273  case EAF_8BIT_MONO:
274  return AL_FORMAT_MONO8;
275  case EAF_16BIT_MONO:
276  return AL_FORMAT_MONO16;
277  case EAF_8BIT_STEREO:
278  return AL_FORMAT_STEREO8;
279  case EAF_16BIT_STEREO:
280  return AL_FORMAT_STEREO16;
281  default:
282  return AL_FORMAT_MONO8;
283  };
284  }
285 
286  void cAudioCapture::registerEventHandler(ICaptureEventHandler* handler)
287  {
288  if(handler)
289  {
290  eventHandlerList.push_back(handler);
291  }
292  }
293 
294  void cAudioCapture::unRegisterEventHandler(ICaptureEventHandler* handler)
295  {
296  if(handler)
297  {
298  eventHandlerList.remove(handler);
299  }
300  }
301 
302  void cAudioCapture::unRegisterAllEventHandlers()
303  {
304  eventHandlerList.clear();
305  }
306 
307  void cAudioCapture::signalEvent(Events sevent)
308  {
309  cAudioMutexBasicLock lock(Mutex);
310  cAudioList<ICaptureEventHandler*>::Type::iterator it = eventHandlerList.begin();
311 
312  if(it != eventHandlerList.end()){
313 
314  switch(sevent){
315 
316  case ON_INIT:
317 
318  for(; it != eventHandlerList.end(); it++){
319  (*it)->onInit();
320  }
321 
322  break;
323 
324  case ON_UPDATE:
325 
326  for(; it != eventHandlerList.end(); it++){
327  (*it)->onUpdate();
328  }
329 
330  break;
331 
332  case ON_RELEASE:
333 
334  for(; it != eventHandlerList.end(); it++){
335  (*it)->onRelease();
336  }
337 
338  break;
339 
340  case ON_BEGINCAPTURE:
341 
342  for(; it != eventHandlerList.end(); it++){
343  (*it)->onBeginCapture();
344  }
345 
346 
347  break;
348 
349  case ON_ENDCAPTURE:
350 
351  for(; it != eventHandlerList.end(); it++){
352  (*it)->onEndCapture();
353  }
354 
355  break;
356 
357  case ON_USERREQUESTEDBUFFER:
358 
359  for(; it != eventHandlerList.end(); it++){
360  (*it)->onUserRequestBuffer();
361  }
362 
363  break;
364  }
365  }
366  }
367 };
368 
cAudio::ILogger::logError
virtual void logError(const char *sender, const char *msg,...)=0
Used to log an error message to the logging system.
cAudio::AudioFormats
AudioFormats
Enumeration of audio formats supported by the engine.
Definition: EAudioFormats.h:11
cAudio::cAudioMutexBasicLock
Definition: cMutex.h:49
cAudio::cAudioSleep
CAUDIO_API void cAudioSleep(unsigned int ms)
Causes the current thread to give up control for a certain duration.
Definition: cAudioSleep.cpp:17
cAudio::ILogger::logDebug
virtual void logDebug(const char *sender, const char *msg,...)=0
Used to log a debug message to the logging system.
cAudio
Main namespace for the entire cAudio library.
Definition: cAudioCapture.h:16
cAudio::ICaptureEventHandler
Interface for recieving Capture Manager Events.
Definition: ICaptureEventHandler.h:11
cAudio::AudioCaptureBuffer
Definition: IAudioCapture.h:114
cAudio::cAudioThread
Definition: cThread.h:20
cAudio::cAudioList
Definition: cSTLAllocator.h:132
cAudio::convertAudioFormatEnum
ALenum convertAudioFormatEnum(AudioFormats format)
Converts our audio format enum to OpenAL's.
Definition: cOpenALUtil.h:48
cAudio::getLogger
CAUDIO_API ILogger * getLogger()
Gets the interface to the logger.
Definition: cAudio.cpp:45