cAudio 2.3.0
3d Audio Engine
Loading...
Searching...
No Matches
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
15namespace 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
Interface for recieving Capture Manager Events.
virtual void logDebug(const char *sender, const char *msg,...)=0
Used to log a debug message to the logging system.
virtual void logError(const char *sender, const char *msg,...)=0
Used to log an error message to the logging system.
Main namespace for the entire cAudio library.
Definition: cAudioCapture.h:16
ALenum convertAudioFormatEnum(AudioFormats format)
Converts our audio format enum to OpenAL's.
Definition: cOpenALUtil.h:48
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:11