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