00001
00002
00003
00004
00005 #include <mda\common\audio.h>
00006 #include <mmf\common\mmfutilities.h>
00007 #include <MdaAudioInputStream.h>
00008 #include <MdaAudioOutputStream.h>
00009 #include <s32file.h>
00010
00011 #include "AudioStreamEngine.h"
00012 #include "audiostream.pan"
00013
00014
00015
00016
00017
00018
00019
00020
00021 const TInt KFrameSizePCM = 4096;
00022 const TInt KFrameCountPCM = 100;
00023
00024
00025
00026 const TInt KFrameSizeAMR = 14;
00027 const TInt KFrameCountAMR = 128;
00028
00029 const TInt KAMRHeaderLength=6;
00030 const TUint8 KAMRNBHeader[KAMRHeaderLength] = { 0x23, 0x21, 0x41, 0x4d, 0x52, 0x0a };
00031
00032
00033 _LIT(KAudioFilePCM, "sample.aud");
00034 _LIT(KAudioFileAMR, "sample.amr");
00035
00036
00037 CAudioStreamEngine* CAudioStreamEngine::NewL(CAudioStreamAppUi* aAppUi)
00038 {
00039 CAudioStreamEngine* self = CAudioStreamEngine::NewLC(aAppUi);
00040 CleanupStack::Pop(self);
00041 return self;
00042 }
00043
00044 CAudioStreamEngine* CAudioStreamEngine::NewLC(CAudioStreamAppUi* aAppUi)
00045 {
00046 CAudioStreamEngine* self = new (ELeave) CAudioStreamEngine(aAppUi);
00047 CleanupStack::PushL(self);
00048 self->ConstructL();
00049 return self;
00050 }
00051
00052
00053 void CAudioStreamEngine::ConstructL()
00054 {
00055
00056
00057 iInputStream = CMdaAudioInputStream::NewL(*this);
00058 iOutputStream = CMdaAudioOutputStream::NewL(*this);
00059
00060
00061
00062 iFs = CEikonEnv::Static()->FsSession();
00063
00064
00065
00066 iDefaultEncoding = iInputStream->DataType();
00067
00068 iCurrentEncoding = iDefaultEncoding;
00069
00070
00071 iStreamBuffer = HBufC8::NewMaxL(iFrameSize * iFrameCount);
00072 iStreamStart=0;
00073 iStreamEnd=iFrameCount - 1;
00074
00075
00076 User::LeaveIfError( iFs.CreatePrivatePath( EDriveC ) );
00077 User::LeaveIfError( iFs.SetSessionToPrivate( EDriveC ) );
00078
00079 iStop = CIdle::NewL( CActive::EPriorityIdle );
00080 }
00081
00082
00083
00084
00085
00086
00087
00088 CAudioStreamEngine::CAudioStreamEngine(CAudioStreamAppUi* aAppUi)
00089 : iAppUi(aAppUi), iUseAMR(EFalse), iAudioFile(KAudioFilePCM), iFrameSize(KFrameSizePCM),
00090 iFrameCount(KFrameCountPCM), iStreamBuffer(0), iFramePtr(0,0), iBufferOK(EFalse)
00091 {
00092
00093
00094
00095
00096
00097 iStreamSettings.iChannels=TMdaAudioDataSettings::EChannelsMono;
00098 iStreamSettings.iSampleRate=TMdaAudioDataSettings::ESampleRate8000Hz;
00099 }
00100
00101
00102
00103
00104
00105
00106 CAudioStreamEngine::~CAudioStreamEngine()
00107 {
00108 if (iInputStream)
00109 {
00110 if (iInputStatus!=ENotReady)
00111 {
00112 iInputStream->Stop();
00113 }
00114 delete iInputStream;
00115 }
00116
00117 if (iOutputStream)
00118 {
00119 if (iOutputStatus!=ENotReady)
00120 {
00121 iOutputStream->Stop();
00122 }
00123 delete iOutputStream;
00124 }
00125
00126 if (iStreamBuffer)
00127 {
00128 delete iStreamBuffer;
00129 }
00130 if (iStop)
00131 {
00132 iStop->Cancel();
00133 }
00134 delete iStop;
00135 }
00136
00137
00138
00139
00140
00141
00142
00143 void CAudioStreamEngine::Play()
00144 {
00145 ShowMessage(_L("Play "), ETrue);
00146
00147 if (iInputStatus!=ENotReady || iOutputStatus!=ENotReady)
00148 {
00149 ShowMessage(_L("Stream in use, \ncannot play audio."), ETrue);
00150 return;
00151 }
00152
00153 if(!iBufferOK)
00154 {
00155 ShowMessage(_L("Nothing to play - \nrecord or load \na file first."), ETrue);
00156 return;
00157 }
00158
00159
00160
00161
00162 iOutputStream->Open(&iStreamSettings);
00163 }
00164
00165
00166
00167
00168
00169
00170
00171 void CAudioStreamEngine::Record()
00172 {
00173
00174 if (iInputStatus!=ENotReady || iOutputStatus!=ENotReady)
00175 {
00176 ShowMessage(_L("Stream in use, \ncannot record audio."), ETrue);
00177 return;
00178 }
00179
00180
00181
00182
00183 iInputStream->Open(&iStreamSettings);
00184 }
00185
00186
00187
00188
00189
00190
00191 void CAudioStreamEngine::Stop()
00192 {
00193
00194 if (iInputStatus!=ENotReady)
00195 {
00196 iInputStream->Stop();
00197 ShowMessage(_L("\nRecording stopped!"), ETrue);
00198 iBufferOK = ETrue;
00199 iInputStatus = ENotReady;
00200 }
00201 if (iOutputStatus!=ENotReady)
00202 {
00203 iOutputStream->Stop();
00204 iOutputStatus = ENotReady;
00205 ShowMessage(_L("\nPlayback stopped!"), ETrue);
00206 }
00207 }
00208
00209
00210
00211
00212
00213
00214
00215 void CAudioStreamEngine::LoadAudioFileL()
00216 {
00217 RFileReadStream audiofile;
00218
00219
00220 TFileName fileName;
00221 fileName.Copy(iAudioFilePath);
00222 fileName.Append(iAudioFile);
00223
00224 TInt err = audiofile.Open(iFs, fileName, EFileRead|EFileStream);
00225 iStreamBuffer->Des().FillZ(iFrameCount * iFrameSize);
00226 if (err==KErrNone)
00227 {
00228
00229 if (iUseAMR)
00230 {
00231
00232
00233 TBuf8<KAMRHeaderLength> temp;
00234 audiofile.ReadL(temp, KAMRHeaderLength);
00235 }
00236
00237 TUint idx=0;
00238 while (idx < iFrameCount)
00239 {
00240 TRAPD(fstatus, audiofile.ReadL(GetFrame(idx), iFrameSize));
00241 if (fstatus!=KErrNone)
00242 break;
00243 idx++;
00244 }
00245 iStreamStart=0;
00246 iStreamEnd=idx-1;
00247 ShowMessage(_L("Loading complete!"), ETrue);
00248 iBufferOK = ETrue;
00249 }
00250 else
00251 {
00252
00253 ShowMessage(_L("Error loading \naudio sample!"), ETrue);
00254 iBufferOK = EFalse;
00255 }
00256 audiofile.Close();
00257 }
00258
00259
00260
00261
00262
00263
00264
00265 void CAudioStreamEngine::SaveAudioFileL()
00266 {
00267 if (!iBufferOK)
00268 {
00269
00270 ShowMessage(_L("Recorded buffer does not \nmatch current encoding."), ETrue);
00271 ShowMessage(_L("\nPlease re-record and \ntry again."), EFalse);
00272 return;
00273 }
00274 RFileWriteStream audiofile;
00275
00276
00277 TVolumeInfo volinfo;
00278 TInt err=iFs.Volume(volinfo,EDriveC);
00279 if ( volinfo.iFree<(iFrameCount*iFrameSize))
00280 {
00281
00282 ShowMessage(_L("Cannot save file:\nnot enough space!"), ETrue);
00283 return;
00284 }
00285
00286 TFileName fileName;
00287 fileName.Copy(iAudioFilePath);
00288 fileName.Append(iAudioFile);
00289 err = audiofile.Replace(iFs, fileName, EFileWrite|EFileStream);
00290 if (err==KErrNone)
00291 {
00292 if (iUseAMR)
00293 {
00294
00295
00296 for (int i = 0; i < KAMRHeaderLength; i++)
00297 audiofile.WriteUint8L(KAMRNBHeader[i]);
00298 }
00299
00300
00301
00302 for (TUint idx=iStreamStart; idx<=iStreamEnd; idx++)
00303 {
00304 audiofile.WriteL(GetFrame(idx));
00305 }
00306 ShowMessage(_L("Saving complete!"), ETrue);
00307 }
00308 else
00309 {
00310
00311 ShowMessage(_L("Error saving \naudio sample!"), ETrue);
00312 }
00313 audiofile.Close();
00314 }
00315
00316
00317
00318
00319
00320
00321
00322
00323 void CAudioStreamEngine::SetEncodingL(TBool aAmr)
00324 {
00325
00326 if (iUseAMR != aAmr)
00327 {
00328 iUseAMR = aAmr;
00329 if (iUseAMR)
00330 {
00331
00332
00333 TRAPD(err, iInputStream->SetDataTypeL(KMMFFourCCCodeAMR));
00334 if (err != KErrNone)
00335 {
00336 ShowMessage(_L("AMR-NB not supported,\nusing PCM."), ETrue);
00337 iCurrentEncoding = iDefaultEncoding;
00338 iUseAMR = EFalse;
00339
00340
00341 return;
00342 }
00343 else
00344 {
00345 iCurrentEncoding = KMMFFourCCCodeAMR;
00346 iAudioFile.Zero();
00347 iAudioFile.Append(KAudioFileAMR);
00348 iFrameCount = KFrameCountAMR;
00349 iFrameSize = KFrameSizeAMR;
00350 ShowMessage(_L("Encoding set to AMR-NB."), ETrue);
00351 }
00352 }
00353 else
00354 {
00355
00356
00357 iCurrentEncoding = iDefaultEncoding;
00358 iAudioFile.Zero();
00359 iAudioFile.Append(KAudioFilePCM);
00360 iFrameCount = KFrameCountPCM;
00361 iFrameSize = KFrameSizePCM;
00362 ShowMessage(_L("Encoding set to PCM."), ETrue);
00363 }
00364
00365
00366
00367 iBufferOK = EFalse;
00368 if (iStreamBuffer) delete iStreamBuffer;
00369 iStreamBuffer = NULL;
00370 iStreamBuffer = HBufC8::NewMaxL(iFrameSize * iFrameCount);
00371 iStreamStart=0;
00372 iStreamEnd=iFrameCount - 1;
00373 }
00374 }
00375
00376
00377
00378
00379
00380
00381
00382
00383
00384 void CAudioStreamEngine::ShowMessage(const TDesC& aMsg, TBool aReset=EFalse)
00385 {
00386 if (aReset)
00387 iMsg.Zero();
00388 iMsg.Append(aMsg);
00389 TRAPD(error, iAppUi->GetView()->ShowMessageL(iMsg));
00390 PanicIfError(error);
00391 }
00392
00393
00394
00395
00396
00397
00398 TPtr8& CAudioStreamEngine::GetFrame(TUint aFrameIdx)
00399 {
00400 __ASSERT_ALWAYS(aFrameIdx < iFrameCount,
00401 User::Panic(_L("AudioStreamEx"), 1));
00402
00403 iFramePtr.Set((TUint8*)(iStreamBuffer->Ptr() + (aFrameIdx * iFrameSize)),
00404 iFrameSize,
00405 iFrameSize);
00406 return iFramePtr;
00407 }
00408
00409
00410
00411
00412
00413
00414
00415 TPtr8& CAudioStreamEngine::GetPlaybackFrames(TUint aLastFrame)
00416 {
00417 __ASSERT_ALWAYS(aLastFrame < iFrameCount,
00418 User::Panic(_L("AudioStreamEx"), 2));
00419
00420 iFramePtr.Set((TUint8*)(iStreamBuffer->Ptr()),
00421 (aLastFrame + 1) * iFrameSize,
00422 (aLastFrame + 1) * iFrameSize);
00423 return iFramePtr;
00424 }
00425
00426
00427
00428
00429
00430
00431
00432
00433
00434
00435
00436
00437
00438
00439 void CAudioStreamEngine::MaiscOpenComplete(TInt aError)
00440 {
00441 if (aError==KErrNone)
00442 {
00443
00444 iInputStatus = EOpen;
00445
00446 TRAPD(error, iInputStream->SetDataTypeL(iCurrentEncoding));
00447 PanicIfError(error);
00448
00449
00450 iInputStream->SetGain(iInputStream->MaxGain());
00451
00452 iInputStream->SetPriority(EPriorityNormal, EMdaPriorityPreferenceTime);
00453 ShowMessage(_L("Recording..."), ETrue);
00454
00455
00456
00457
00458 iStreamBuffer->Des().FillZ(iFrameCount * iFrameSize);
00459 iStreamIdx=0;
00460 TRAPD(error2, iInputStream->ReadL(GetFrame(iStreamIdx)));
00461 PanicIfError(error2);
00462 }
00463 else
00464 {
00465
00466 iInputStatus = ENotReady;
00467 ShowMessage(_L("Recording failed!"), ETrue);
00468 }
00469 }
00470
00471
00472
00473
00474
00475
00476
00477
00478
00479 void CAudioStreamEngine::MaiscBufferCopied(TInt aError, const TDesC8& )
00480 {
00481 if (aError!=KErrNone)
00482 {
00483 _LIT(KMessage,"Recording error: %d");
00484 HBufC16* message = HBufC16::NewLC(KMessage().Length()+10);
00485 message->Des().AppendFormat(KMessage,aError);
00486 ShowMessage(*message, ETrue);
00487 CleanupStack::PopAndDestroy();
00488 message = NULL;
00489 }
00490
00491 if (aError==KErrNone)
00492 {
00493
00494 iStreamIdx++;
00495 if (iStreamIdx == iFrameCount)
00496 {
00497 ShowMessage(_L("\nRecording complete!"), ETrue);
00498 iStreamEnd = iStreamIdx - 1;
00499 iBufferOK = ETrue;
00500
00501
00502
00503 iStop->Start( TCallBack(BackgroundStop, this) );
00504 return;
00505 }
00506
00507
00508 TRAPD(error, iInputStream->ReadL(GetFrame(iStreamIdx)));
00509 PanicIfError(error);
00510 }
00511 else if (aError==KErrAbort)
00512 {
00513
00514
00515
00516 iStreamEnd = iStreamIdx - 1;
00517 iBufferOK = ETrue;
00518 iInputStatus = ENotReady;
00519 }
00520 else
00521 {
00522 ShowMessage(_L("\nError reading data \nfrom input"), ETrue);
00523 iInputStatus = ENotReady;
00524 }
00525 }
00526
00527
00528 TInt CAudioStreamEngine::BackgroundStop( TAny *aStream )
00529 {
00530 ((CAudioStreamEngine*)aStream)->Stop();
00531 return EFalse;
00532 }
00533
00534
00535
00536
00537
00538
00539
00540
00541 void CAudioStreamEngine::MaiscRecordComplete(TInt aError)
00542 {
00543 iInputStatus = ENotReady;
00544 if (aError==KErrNone)
00545 {
00546
00547 }
00548 else
00549 {
00550
00551 }
00552 }
00553
00554
00555
00556
00557
00558
00559
00560
00561
00562
00563
00564
00565
00566 void CAudioStreamEngine::MaoscOpenComplete(TInt aError)
00567 {
00568 if (aError==KErrNone)
00569 {
00570
00571 iOutputStatus = EOpen;
00572
00573
00574
00575 TRAPD(error, iOutputStream->SetDataTypeL(iCurrentEncoding));
00576 PanicIfError(error);
00577
00578
00579 iOutputStream->SetVolume(iOutputStream->MaxVolume()/2);
00580
00581 iOutputStream->SetPriority(EPriorityNormal,
00582 EMdaPriorityPreferenceTime);
00583 ShowMessage(_L("Playing "), ETrue);
00584
00585 if (iUseAMR)
00586 {
00587
00588
00589
00590 iStreamIdx = iStreamEnd;
00591 TRAPD(error2, iOutputStream->WriteL(GetPlaybackFrames(iStreamEnd)));
00592 PanicIfError(error2);
00593 }
00594 else
00595 {
00596
00597
00598 iStreamIdx = 0;
00599 TRAPD(error3, iOutputStream->WriteL(GetFrame(iStreamIdx)));
00600 PanicIfError(error3);
00601 }
00602 }
00603 else
00604 {
00605
00606 iOutputStatus = ENotReady;
00607 ShowMessage(_L("Playback failed!"), ETrue);
00608 }
00609 }
00610
00611
00612
00613
00614
00615
00616
00617
00618
00619 void CAudioStreamEngine::MaoscBufferCopied(TInt aError, const TDesC8& )
00620 {
00621 if (aError==KErrNone)
00622 {
00623 if (iStreamIdx==iStreamEnd)
00624 {
00625 ShowMessage(_L("\nPlayback complete!"), EFalse);
00626
00627
00628 iStop->Start( TCallBack(BackgroundStop, this) );
00629 }
00630 else
00631 {
00632 iStreamIdx++;
00633 TRAPD(error, iOutputStream->WriteL(GetFrame(iStreamIdx)));
00634 PanicIfError(error);
00635 }
00636 }
00637 else if (aError==KErrAbort)
00638 {
00639
00640
00641 iOutputStatus = ENotReady;
00642 }
00643 else
00644 {
00645 ShowMessage(_L("\nError writing data \nto output"), EFalse);
00646 iOutputStatus = ENotReady;
00647 }
00648 }
00649
00650
00651
00652
00653
00654
00655
00656
00657
00658
00659 void CAudioStreamEngine::MaoscPlayComplete(TInt aError)
00660 {
00661 iOutputStatus = ENotReady;
00662 if (aError==KErrNone)
00663 {
00664
00665 }
00666 else if (aError==KErrUnderflow)
00667 {
00668
00669 }
00670 else
00671 {
00672
00673 }
00674 }
00675
00676
00677