11 #if defined(AD_BACKEND_S60)
20 #include <e32msgqueue.h>
22 #include <MdaAudioInputStream.h>
23 #include <mda/common/audio.h>
58 const TInt KQueueLength = 10;
63 const TInt KBytesPerSample = 2;
68 const TInt KSampleRate = 16000;
75 const TInt KTemporaryBufferTime = 150;
80 const TInt KTemporaryBufferSize = (KTemporaryBufferTime * KSampleRate * KBytesPerSample) / 1000;
85 _LIT(KHelperThreadName,
"HelperThread");
90 enum THelperThreadState {EPaused = 0, ERecording, EClosing};
97 class CHelperThreadHost :
public MMdaAudioInputStreamCallback {
99 CHelperThreadHost(CBufSeg*, RFastLock*, RMsgQueue<TInt>*, RMsgQueue<TInt>*);
100 virtual ~CHelperThreadHost();
101 static TInt ThreadFunction(TAny*);
105 virtual void MaiscOpenComplete(TInt);
106 virtual void MaiscBufferCopied(TInt,
const TDesC8&);
107 virtual void MaiscRecordComplete(TInt);
110 CMdaAudioInputStream* iStream;
111 TMdaAudioDataSettings iStreamSettings;
112 THelperThreadState iState;
114 RBuf8 iTemporaryBuffer;
117 RFastLock* iBufferLock;
119 RMsgQueue<TInt>* iCommandQueue;
120 RMsgQueue<TInt>* iNotificationQueue;
130 static CAudioDevice* NewL();
131 virtual ~CAudioDevice();
133 void ResumeRecording();
134 void PauseRecording();
135 TInt ReadSamples(TAny*, TInt);
139 CHelperThreadHost* iThreadHost;
142 RFastLock iBufferLock;
144 RMsgQueue<TInt> iCommandQueue;
145 RMsgQueue<TInt> iNotificationQueue;
148 CAudioDevice::CAudioDevice(){
149 iCommandQueue.CreateLocal(KQueueLength);
150 iNotificationQueue.CreateLocal(KQueueLength);
153 void CAudioDevice::ConstructL(){
154 iBuffer = CBufSeg::NewL(KTemporaryBufferSize);
155 iBufferLock.CreateLocal();
157 iThreadHost =
new (ELeave) CHelperThreadHost(iBuffer, &(iBufferLock), &(iCommandQueue), &(iNotificationQueue));
158 iThread.Create(KHelperThreadName, CHelperThreadHost::ThreadFunction, KDefaultStackSize, NULL, iThreadHost);
162 TInt message = ENullMessage;
163 iNotificationQueue.ReceiveBlocking(message);
164 if(message != EInited){
165 RDebug::Print(_L(
"expecting %d, got %d"), EInited, message);
169 CAudioDevice* CAudioDevice::NewL(){
170 CAudioDevice*
self =
new (ELeave) CAudioDevice();
171 CleanupStack::PushL(
self);
173 CleanupStack::Pop(
self);
180 void CAudioDevice::ResumeRecording(){
181 iCommandQueue.SendBlocking(EStartRecording);
183 TInt message = ENullMessage;
184 iNotificationQueue.ReceiveBlocking(message);
185 if(message != ERecordingStarted){
186 RDebug::Print(_L(
"expecting %d, got %d"), ERecordingStarted, message);
194 void CAudioDevice::PauseRecording(){
195 iCommandQueue.SendBlocking(EStopRecording);
197 TInt message = ENullMessage;
198 iNotificationQueue.ReceiveBlocking(message);
199 if(message != ERecordingStopped){
200 RDebug::Print(_L(
"expecting %d, got %d"), ERecordingStopped, message);
208 TInt CAudioDevice::ReadSamples(TAny* aDestinationBuffer, TInt aMaxSamples){
210 TInt availableSamples = iBuffer->Size() / KBytesPerSample;
211 TInt samplesToCopy = aMaxSamples;
212 if (availableSamples < aMaxSamples){
213 samplesToCopy = availableSamples;
215 TInt bytesToCopy = samplesToCopy * KBytesPerSample;
216 iBuffer->Read(0, aDestinationBuffer, bytesToCopy);
217 iBuffer->Delete(0, bytesToCopy);
218 iBufferLock.Signal();
220 return samplesToCopy;
223 CAudioDevice::~CAudioDevice(){
225 iCommandQueue.SendBlocking(EClose);
227 TInt message = ENullMessage;
228 iNotificationQueue.ReceiveBlocking(message);
229 if(message != EClosed){
230 RDebug::Print(_L(
"expecting %d, got %d"), EClosed, message);
234 TRequestStatus status;
235 iThread.Logon(status);
236 User::WaitForRequest(status);
243 iNotificationQueue.Close();
244 iCommandQueue.Close();
247 CHelperThreadHost::CHelperThreadHost(CBufSeg* aBuffer, RFastLock* aBufferLock, RMsgQueue<TInt>* aCommandQueue, RMsgQueue<TInt>* aNotificationQueue){
249 iBufferLock = aBufferLock;
250 iCommandQueue = aCommandQueue;
251 iNotificationQueue = aNotificationQueue;
255 TInt CHelperThreadHost::ThreadFunction(TAny* aParam){
256 CHelperThreadHost* host = (CHelperThreadHost*) aParam;
259 CTrapCleanup* cleanupStack = CTrapCleanup::New();
263 CActiveScheduler* activeScheduler =
new (ELeave) CActiveScheduler;
264 CleanupStack::PushL(activeScheduler);
265 CActiveScheduler::Install(activeScheduler);
271 CActiveScheduler::Start();
274 CleanupStack::PopAndDestroy(activeScheduler);
276 if(error != KErrNone){
277 RDebug::Print(_L(
"thread error: %d"), error);
287 void CHelperThreadHost::InitializeL(){
288 iStream = CMdaAudioInputStream::NewL(*
this, EMdaPriorityMax, EMdaPriorityPreferenceTime);
289 iStream->Open(&(iStreamSettings));
290 iTemporaryBuffer.CreateL(KTemporaryBufferSize);
296 void CHelperThreadHost::DestroyL(){
297 iTemporaryBuffer.Close();
298 #if defined(__WINSCW__)
300 CMdaAudioInputStream::Delete(iStream);
309 void CHelperThreadHost::MaiscOpenComplete(TInt aError){
310 if (aError == KErrNone){
311 iNotificationQueue->SendBlocking(EInited);
313 iStream->SetAudioPropertiesL(TMdaAudioDataSettings::ESampleRate16000Hz, TMdaAudioDataSettings::EChannelsMono);
314 iStream->SetGain(iStream->MaxGain());
316 iStream->ReadL(iTemporaryBuffer);
319 RDebug::Print(_L(
"error %d in MaiscOpenComplete"), aError);
326 void CHelperThreadHost::MaiscBufferCopied(TInt aError,
const TDesC8 &aBuffer){
327 if (aError == KErrNone){
329 if(iState == ERecording){
330 TInt availableBytes = aBuffer.Size();
332 TInt bufferSize = iBuffer->Size();
333 iBuffer->ExpandL(bufferSize, availableBytes);
334 iBuffer->Write(bufferSize, aBuffer, availableBytes);
335 iBufferLock->Signal();
339 iTemporaryBuffer.Zero();
342 TInt message = ENullMessage;
343 TInt result = iCommandQueue->Receive(message);
344 if (result == KErrNone){
345 if(message == EStartRecording){
347 iNotificationQueue->SendBlocking(ERecordingStarted);
349 else if(message == EStopRecording){
351 iNotificationQueue->SendBlocking(ERecordingStopped);
353 else if(message == EClose){
357 iNotificationQueue->SendBlocking(EClosed);
361 RDebug::Print(_L(
"received unexpected %d"), message);
366 if (iState != EClosing){
367 iStream->ReadL(iTemporaryBuffer);
370 else if (aError == KErrAbort){
374 RDebug::Print(_L(
"error %d in MaiscBufferCopied"), aError);
383 void CHelperThreadHost::MaiscRecordComplete(TInt aError){
387 CHelperThreadHost::~CHelperThreadHost(){
395 result->recorder = CAudioDevice::NewL();
396 result->recording = FALSE;
397 result->
sps = KSampleRate;
398 result->
bps = KBytesPerSample;
412 ad_rec_t* ad_open_sps_bufsize(int32 sps, int32 bufsize_msec){
418 ((CAudioDevice*)r->recorder)->ResumeRecording();
423 int32 ad_read(
ad_rec_t* r, int16* buf, int32 max){
424 int32 result = (int32) ((CAudioDevice*)r->recorder)->ReadSamples((TAny*) buf, (TInt)max);
425 if(result == 0 && r->recording == FALSE){
432 ((CAudioDevice*)r->recorder)->PauseRecording();
433 r->recording = FALSE;
438 delete ((CAudioDevice*)r->recorder);
443 #endif //defined(AD_BACKEND_S60)
SPHINXBASE_EXPORT ad_rec_t * ad_open(void)
Open the default audio device.
generic live audio interface for recording and playback
SPHINXBASE_EXPORT ad_rec_t * ad_open_dev(const char *dev, int32 samples_per_sec)
Open a specific audio device for recording.
SPHINXBASE_EXPORT ad_rec_t * ad_open_sps(int32 samples_per_sec)
Open the default audio device with a given sampling rate.