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  {
26  }
27 
28  void cAudioCapture::run()
29  {
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 
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 
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 
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 
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 
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 
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 
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 
287  {
288  if(handler)
289  {
290  eventHandlerList.push_back(handler);
291  }
292  }
293 
295  {
296  if(handler)
297  {
298  eventHandlerList.remove(handler);
299  }
300  }
301 
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 
virtual void logError(const char *sender, const char *msg,...)=0
Used to log an error message to the logging system.
virtual bool setInternalBufferSize(unsigned int internalBufferSize)
Sets the internal buffer size that OpenAL will use to store captured audio between calls to getCaptur...
IThread * AudioThread
Our update thread.
Definition: cAudioCapture.h:71
virtual bool setFormat(AudioFormats format)
Sets the format that the captured audio will be at. Will cause the capture device to be reinitialized...
virtual unsigned int getCurrentCapturedAudioSize()
Returns the current size of the internal audio buffer in bytes.
virtual void updateCaptureBuffer(bool force=false)
Grabs samples from the OpenAL buffer into the capture buffer if the OpenAL buffer has reached half fu...
virtual void logDebug(const char *sender, const char *msg,...)=0
Used to log a debug message to the logging system.
Interface for recieving Capture Manager Events.
virtual void stopCapture()
Stops capturing audio data to an internal buffer.
virtual void unRegisterAllEventHandlers()
Removes all event handlers attached to this manager.
virtual AudioCaptureBuffer * getCapturedAudioBuffer()
this method is the same as getCapturedAudio but it returns an managed CaptureBuffer ...
virtual bool setFrequency(unsigned int frequency)
Sets the frequency that the captured audio will be at. Will cause the capture device to be reinitiali...
virtual bool setDevice(const char *deviceName)
Sets the audio device . Will cause the capture device to be reinitialized. Calling while in use will ...
virtual unsigned int getCapturedAudio(void *outputBuffer, unsigned int outputBufferSize)
Allows access to the audio data in the internal capture buffer.
virtual bool beginCapture()
Starts capturing audio data to an internal buffer. Will clear any old data in the buffer...
virtual bool initialize(const char *deviceName=0x0, unsigned int frequency=22050, AudioFormats format=EAF_16BIT_MONO, unsigned int internalBufferSize=8192)
Initializes the capture device to the selected settings.
virtual void shutdown()
Shuts down the capture device, clearing the internal buffer and setting the audio capture into an uni...
virtual void unRegisterEventHandler(ICaptureEventHandler *handler)
Removes the specified event handler from this manager.
CAUDIO_API ILogger * getLogger()
Gets the interface to the logger.
Definition: cAudio.cpp:45
CAUDIO_API void cAudioSleep(unsigned int ms)
Causes the current thread to give up control for a certain duration.
Definition: cAudioSleep.cpp:17
AudioFormats
Enumeration of audio formats supported by the engine.
Definition: EAudioFormats.h:10
virtual void registerEventHandler(ICaptureEventHandler *handler)
Registers a new event handler to this manager.
Main namespace for the entire cAudio library.
Definition: cAudioCapture.h:15