00001 /* 00002 * Copyright © 2008 Nokia Corporation. 00003 */ 00004 00005 #include <mda\common\audio.h> 00006 #include <mmf\common\mmfutilities.h> 00007 #include <MdaAudioInputStream.h> // audio input stream 00008 #include <MdaAudioOutputStream.h> // audio output stream 00009 #include <s32file.h> // RFileWriteStream and RFileReadStream 00010 00011 #include "AudioStreamEngine.h" 00012 #include "audiostream.pan" 00013 00014 // Audio data buffer size. 00015 // In both 3rd Edition and 2nd Edition the total buffer (iStreamBuffer) size is 00016 // KFrameSizePCM * KFrameCountPCM = 40960 bytes. This will contain 2560 ms 00017 // of 16-bit audio data. 00018 // In 3rd Edition the KFrameSizePCM is 4096 bytes, because CMdaAudioInputStream::ReadL() 00019 // returns audio data in 4096-byte chunks. In 2nd Edition, ReadL() returns data in 320-byte 00020 // chunks. 00021 const TInt KFrameSizePCM = 4096; 00022 const TInt KFrameCountPCM = 100; 00023 00024 // Audio data buffer size for AMR encoding. For AMR, the buffer size is the same in 00025 // both 2nd and 3rd Edition devices (20 ms per frame, a total of 2560 ms in 128 frames). 00026 const TInt KFrameSizeAMR = 14; 00027 const TInt KFrameCountAMR = 128; 00028 // Header data for an AMR-encoded audio file 00029 const TInt KAMRHeaderLength=6; 00030 const TUint8 KAMRNBHeader[KAMRHeaderLength] = { 0x23, 0x21, 0x41, 0x4d, 0x52, 0x0a }; 00031 00032 // Files to store the sample audio clips 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 // Standard EPOC 2nd phase constructor 00053 void CAudioStreamEngine::ConstructL() 00054 { 00055 // Construct streams. We need to construct these here, so that at least the input stream 00056 // exists if SetEncodingL() is called before any recording has taken place 00057 iInputStream = CMdaAudioInputStream::NewL(*this); 00058 iOutputStream = CMdaAudioOutputStream::NewL(*this); 00059 00060 // Get a handle to the RFs session to be used (owned by CEikonEnv, NOT to be closed 00061 // when this application exits!) 00062 iFs = CEikonEnv::Static()->FsSession(); 00063 00064 // Save the default encoding for later reference (the encoding is the same for 00065 // both input and output streams). 00066 iDefaultEncoding = iInputStream->DataType(); 00067 // At first we are using the default encoding. 00068 iCurrentEncoding = iDefaultEncoding; 00069 00070 // Stream buffer allocation (by default for PCM) 00071 iStreamBuffer = HBufC8::NewMaxL(iFrameSize * iFrameCount); 00072 iStreamStart=0; 00073 iStreamEnd=iFrameCount - 1; 00074 00075 // The sample.aud/amr can be found in \private<UID3>\ folder 00076 User::LeaveIfError( iFs.CreatePrivatePath( EDriveC ) ); 00077 User::LeaveIfError( iFs.SetSessionToPrivate( EDriveC ) ); 00078 00079 iStop = CIdle::NewL( CActive::EPriorityIdle ); 00080 } 00081 00082 // ---------------------------------------------------------------------------- 00083 // CAudioStreamEngine::CAudioStreamEngine( 00084 // CAudioStreamAppUi* aAppUi) 00085 // 00086 // onstructor 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 // By default we use PCM and initialise the instance variables accordingly above. 00093 00094 // Initial audio stream properties for input and output, 8KHz mono. 00095 // These settings could also be set/changed using method SetAudioPropertiesL() of 00096 // the input and output streams. 00097 iStreamSettings.iChannels=TMdaAudioDataSettings::EChannelsMono; 00098 iStreamSettings.iSampleRate=TMdaAudioDataSettings::ESampleRate8000Hz; 00099 } 00100 00101 // ---------------------------------------------------------------------------- 00102 // CAudioStreamEngine::~CAudioStreamEngine() 00103 // 00104 // destructor 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 // CAudioStreamEngine::Play() 00140 // 00141 // plays the audio data contained in the buffer 00142 // ---------------------------------------------------------------------------- 00143 void CAudioStreamEngine::Play() 00144 { 00145 ShowMessage(_L("Play "), ETrue); 00146 // if either stream is active, return 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 // Open output stream. 00160 // Upon completion will receive callback in 00161 // MMdaAudioOutputStreamCallback::MaoscOpenComplete(). 00162 iOutputStream->Open(&iStreamSettings); 00163 } 00164 00165 00166 // ---------------------------------------------------------------------------- 00167 // CAudioStreamEngine::Record() 00168 // 00169 // records audio data into the buffer 00170 // ---------------------------------------------------------------------------- 00171 void CAudioStreamEngine::Record() 00172 { 00173 // If either stream is active, return 00174 if (iInputStatus!=ENotReady || iOutputStatus!=ENotReady) 00175 { 00176 ShowMessage(_L("Stream in use, \ncannot record audio."), ETrue); 00177 return; 00178 } 00179 00180 // Open input stream. 00181 // Upon completion will receive callback in 00182 // MMdaAudioInputStreamCallback::MaiscOpenComplete(). 00183 iInputStream->Open(&iStreamSettings); 00184 } 00185 00186 // ---------------------------------------------------------------------------- 00187 // CAudioStreamEngine::Stop() 00188 // 00189 // stops playing/recording 00190 // ---------------------------------------------------------------------------- 00191 void CAudioStreamEngine::Stop() 00192 { 00193 // if input or output streams are active, close them 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 // CAudioStreamEngine::LoadAudioFileL() 00212 // 00213 // loads the audio data from a file into the buffer 00214 // ---------------------------------------------------------------------------- 00215 void CAudioStreamEngine::LoadAudioFileL() 00216 { 00217 RFileReadStream audiofile; 00218 00219 // open file 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); // Empty the stream buffer 00226 if (err==KErrNone) 00227 { 00228 // file opened ok, proceed reading 00229 if (iUseAMR) 00230 { 00231 // Read the AMR header (the first 6 bytes). We don't need to save/use the header, 00232 // since while playback we already know it's an AMR-NB encoded stream. 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 // failed to open file 00253 ShowMessage(_L("Error loading \naudio sample!"), ETrue); 00254 iBufferOK = EFalse; 00255 } 00256 audiofile.Close(); 00257 } 00258 00259 00260 // ---------------------------------------------------------------------------- 00261 // CAudioStreamEngine::SaveAudioFileL() 00262 // 00263 // saves the audio data in the buffer into a file 00264 // ---------------------------------------------------------------------------- 00265 void CAudioStreamEngine::SaveAudioFileL() 00266 { 00267 if (!iBufferOK) 00268 { 00269 // In case the encoding was changed between recording and trying to save the file 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 // Check for free space for saving the sample 00277 TVolumeInfo volinfo; 00278 TInt err=iFs.Volume(volinfo,EDriveC); 00279 if ( volinfo.iFree<(iFrameCount*iFrameSize)) 00280 { 00281 // Not enough free space on drive for saving, report and exit 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 // Write the six-byte AMR header, so that the file can be used by other 00295 // applications as well. 00296 for (int i = 0; i < KAMRHeaderLength; i++) 00297 audiofile.WriteUint8L(KAMRNBHeader[i]); 00298 } 00299 00300 // File opened ok, proceed writing. 00301 // Write audio data directly from iStreamBuffer 00302 for (TUint idx=iStreamStart; idx<=iStreamEnd; idx++)//iFrameCount; idx++) 00303 { 00304 audiofile.WriteL(GetFrame(idx)); 00305 } 00306 ShowMessage(_L("Saving complete!"), ETrue); 00307 } 00308 else 00309 { 00310 // failed to open file 00311 ShowMessage(_L("Error saving \naudio sample!"), ETrue); 00312 } 00313 audiofile.Close(); 00314 } 00315 00316 // ---------------------------------------------------------------------------- 00317 // CAudioStreamEngine::SetEncodingL(TBool aAmr) 00318 // 00319 // If argument is ETrue, AMR-NB encoding will be used in audio input/output. 00320 // If EFalse, the default PCM is used. If the platform does not support AMR-NB, 00321 // PCM will be used no matter what the argument's value is. 00322 // ---------------------------------------------------------------------------- 00323 void CAudioStreamEngine::SetEncodingL(TBool aAmr) 00324 { 00325 // Act only if the new encoding differs from the current one 00326 if (iUseAMR != aAmr) 00327 { 00328 iUseAMR = aAmr; 00329 if (iUseAMR) 00330 { 00331 // Try to set AMR-NB encoding, this will indicate whether it is supported 00332 // by the platform or not. 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 // We do not need to invalidate the buffer or change buffer settings, 00340 // since the encoding was not changed -> just return. 00341 return; 00342 } 00343 else 00344 { 00345 iCurrentEncoding = KMMFFourCCCodeAMR; 00346 iAudioFile.Zero(); // Empty the audio file name 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 // If we get here, the encoding has previously been changed to AMR. Switch back to 00356 // PCM. 00357 iCurrentEncoding = iDefaultEncoding; 00358 iAudioFile.Zero(); // Empty the audio file name 00359 iAudioFile.Append(KAudioFilePCM); 00360 iFrameCount = KFrameCountPCM; 00361 iFrameSize = KFrameSizePCM; 00362 ShowMessage(_L("Encoding set to PCM."), ETrue); 00363 } 00364 00365 // Make sure the user re-records or reloads the audio file, so that we do not 00366 // accidentally try to play PCM data using AMR or vice versa. 00367 iBufferOK = EFalse; 00368 if (iStreamBuffer) delete iStreamBuffer; 00369 iStreamBuffer = NULL; // In case the following NewL leaves 00370 iStreamBuffer = HBufC8::NewMaxL(iFrameSize * iFrameCount); 00371 iStreamStart=0; 00372 iStreamEnd=iFrameCount - 1; 00373 } 00374 } 00375 00376 // ---------------------------------------------------------------------------- 00377 // CAudioStreamEngine::ShowMessage( 00378 // const TDesC& aMsg, TBool aReset=EFalse) 00379 // 00380 // displays text referenced by aMsg in the label, will append the aMsg in the 00381 // existing text in label if aReset is EFalse, otherwise will reset the label 00382 // text. 00383 // ---------------------------------------------------------------------------- 00384 void CAudioStreamEngine::ShowMessage(const TDesC& aMsg, TBool aReset=EFalse) 00385 { 00386 if (aReset) // if ETrue, clear the message on the label prior to output 00387 iMsg.Zero(); 00388 iMsg.Append(aMsg); 00389 TRAPD(error, iAppUi->GetView()->ShowMessageL(iMsg)); 00390 PanicIfError(error); 00391 } 00392 00393 // ---------------------------------------------------------------------------- 00394 // TPtr8& CAudioStreamEngine::GetFrame(TUint aFrameIdx) 00395 // 00396 // Returns a modifiable pointer to a single frame inside the audio buffer 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 // TPtr8& CAudioStreamEngine::GetPlaybackFrames(TUint aLastFrame) 00411 // 00412 // Returns a modifiable pointer to the requested frames inside the audio buffer 00413 // (from the first frame to aLastFrame). 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 // MMdaAudioInputStream callbacks (MMdaAudioInputStreamCallback) 00429 // 00430 // ---------------------------------------------------------------------------- 00431 // CAudioStreamEngine::MaiscOpenComplete( 00432 // TInt aError) 00433 // 00434 // called upon completion of CMdaAudioInputStream::Open(), 00435 // if the stream was opened succesfully (aError==KErrNone), it's ready for use. 00436 // upon succesful open, the first audio data block will be read from the input 00437 // stream. 00438 // ---------------------------------------------------------------------------- 00439 void CAudioStreamEngine::MaiscOpenComplete(TInt aError) 00440 { 00441 if (aError==KErrNone) 00442 { 00443 // Input stream opened succesfully, set status 00444 iInputStatus = EOpen; 00445 // Set the data type (encoding) 00446 TRAPD(error, iInputStream->SetDataTypeL(iCurrentEncoding)); 00447 PanicIfError(error); 00448 00449 // set stream input gain to maximum 00450 iInputStream->SetGain(iInputStream->MaxGain()); 00451 // set stream priority to normal and time sensitive 00452 iInputStream->SetPriority(EPriorityNormal, EMdaPriorityPreferenceTime); 00453 ShowMessage(_L("Recording..."), ETrue); 00454 00455 // Emtpy the buffer and issue ReadL() to read the first audio data block, 00456 // subsequent calls to ReadL() will be issued 00457 // in MMdaAudioInputStreamCallback::MaiscBufferCopied() 00458 iStreamBuffer->Des().FillZ(iFrameCount * iFrameSize); 00459 iStreamIdx=0; 00460 TRAPD(error2, iInputStream->ReadL(GetFrame(iStreamIdx))); 00461 PanicIfError(error2); 00462 } 00463 else 00464 { 00465 // input stream open failed 00466 iInputStatus = ENotReady; 00467 ShowMessage(_L("Recording failed!"), ETrue); 00468 } 00469 } 00470 00471 // ---------------------------------------------------------------------------- 00472 // CAudioStreamEngine::MaiscBufferCopied( 00473 // TInt aError, const TDesC8& aBuffer) 00474 // 00475 // called when a block of audio data has been read and is available at the 00476 // buffer reference *aBuffer. calls to ReadL() will be issued until all blocks 00477 // in the audio data buffer (iStreamBuffer) are filled. 00478 // ---------------------------------------------------------------------------- 00479 void CAudioStreamEngine::MaiscBufferCopied(TInt aError, const TDesC8& /*aBuffer*/) 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(); // message 00488 message = NULL; 00489 } 00490 00491 if (aError==KErrNone) 00492 { 00493 // stop recording if at the end of the buffer 00494 iStreamIdx++; 00495 if (iStreamIdx == iFrameCount) 00496 { 00497 ShowMessage(_L("\nRecording complete!"), ETrue); 00498 iStreamEnd = iStreamIdx - 1; 00499 iBufferOK = ETrue; 00500 00501 // Playback is complete: 00502 // Start the active object that will stop the stream 00503 iStop->Start( TCallBack(BackgroundStop, this) ); 00504 return; 00505 } 00506 00507 // issue ReadL() for next frame 00508 TRAPD(error, iInputStream->ReadL(GetFrame(iStreamIdx))); 00509 PanicIfError(error); 00510 } 00511 else if (aError==KErrAbort) 00512 { 00513 // Recording was aborted, due to call to CMdaAudioInputStream::Stop() 00514 // This KErrAbort will occur each time the Stop() method in this class is executed. 00515 // Also, MaiscRecordComplete() will be called after exiting this method. 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 ) // static member function 00529 { 00530 ((CAudioStreamEngine*)aStream)->Stop(); 00531 return EFalse; 00532 } 00533 00534 00535 // ---------------------------------------------------------------------------- 00536 // CAudioStreamEngine::MaiscRecordComplete( 00537 // TInt aError) 00538 // 00539 // called when input stream is closed by CMdaAudioInputStream::Stop() 00540 // ---------------------------------------------------------------------------- 00541 void CAudioStreamEngine::MaiscRecordComplete(TInt aError) 00542 { 00543 iInputStatus = ENotReady; 00544 if (aError==KErrNone) 00545 { 00546 // normal stream closure 00547 } 00548 else 00549 { 00550 // completed with error(s) 00551 } 00552 } 00553 00554 00555 // MMdaAudioOutputStream callbacks (MMdaAudioOutputStreamCallback) 00556 00557 // ---------------------------------------------------------------------------- 00558 // CAudioStreamEngine::MaoscOpenComplete( 00559 // TInt aError) 00560 // 00561 // called upon completion of CMdaAudioOutputStream::Open(), 00562 // if the stream was opened succesfully (aError==KErrNone), it's ready for use. 00563 // upon succesful open, the first audio data block will be written to the 00564 // output stream. 00565 // ---------------------------------------------------------------------------- 00566 void CAudioStreamEngine::MaoscOpenComplete(TInt aError) 00567 { 00568 if (aError==KErrNone) 00569 { 00570 // output stream opened succesfully, set status 00571 iOutputStatus = EOpen; 00572 // Set the data type (encoding). Should not fail, since we already 00573 // have tested support for this encoding in SetEncodingL with the 00574 // corresponding input stream! 00575 TRAPD(error, iOutputStream->SetDataTypeL(iCurrentEncoding)); 00576 PanicIfError(error); 00577 00578 // set volume to 1/4th of stream max volume 00579 iOutputStream->SetVolume(iOutputStream->MaxVolume()/2); 00580 // set stream priority to normal and time sensitive 00581 iOutputStream->SetPriority(EPriorityNormal, 00582 EMdaPriorityPreferenceTime); 00583 ShowMessage(_L("Playing "), ETrue); 00584 00585 if (iUseAMR) 00586 { 00587 // In case of AMR, the whole recorded/loaded buffer is played back at once, not frame by frame. 00588 // The buffer might not be fully recorded, so we will only play back the part 00589 // that is filled with data. 00590 iStreamIdx = iStreamEnd; 00591 TRAPD(error2, iOutputStream->WriteL(GetPlaybackFrames(iStreamEnd))); 00592 PanicIfError(error2); 00593 } 00594 else 00595 { 00596 // PCM needs to be played back frame by frame, otherwise some older devices might 00597 // run into buffer overflow situations. 00598 iStreamIdx = 0; 00599 TRAPD(error3, iOutputStream->WriteL(GetFrame(iStreamIdx))); 00600 PanicIfError(error3); 00601 } 00602 } 00603 else 00604 { 00605 // output stream open failed 00606 iOutputStatus = ENotReady; 00607 ShowMessage(_L("Playback failed!"), ETrue); 00608 } 00609 } 00610 00611 // ---------------------------------------------------------------------------- 00612 // CAudioStreamEngine::MaoscBufferCopied( 00613 // TInt aError, const TDesC8& aBuffer) 00614 // 00615 // called when a block of audio data has been written to MMF. calls to WriteL() 00616 // will be issued until all blocks in the audio data buffer (iStreamBuffer) are 00617 // written. 00618 // ---------------------------------------------------------------------------- 00619 void CAudioStreamEngine::MaoscBufferCopied(TInt aError, const TDesC8& /*aBuffer*/) 00620 { 00621 if (aError==KErrNone) 00622 { 00623 if (iStreamIdx==iStreamEnd) 00624 { 00625 ShowMessage(_L("\nPlayback complete!"), EFalse); 00626 // Playback is complete: 00627 // Start the active object that will stop the stream 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 // Playing was aborted, due to call to CMdaAudioOutputStream::Stop(). 00640 // MaoscRecordComplete() will be called after exiting this method. 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 // CAudioStreamEngine::MaoscPlayComplete( 00653 // TInt aError) 00654 // 00655 // called when output stream is closed by CMdaAudioOutputStream::Stop() or if 00656 // end of audio data has been reached, in this case KErrUnderflow will be 00657 // returned. 00658 // ---------------------------------------------------------------------------- 00659 void CAudioStreamEngine::MaoscPlayComplete(TInt aError) 00660 { 00661 iOutputStatus = ENotReady; 00662 if (aError==KErrNone) 00663 { 00664 // normal stream closure 00665 } 00666 else if (aError==KErrUnderflow) 00667 { 00668 // end of audio data stream was reached because of stream underflow, 00669 } 00670 else 00671 { 00672 // completed with error(s) 00673 } 00674 } 00675 00676 // END OF FILE 00677
Copyright ©2010 Nokia Corporation and/or its subsidiary(-ies).
All rights
reserved. Unless otherwise stated, these materials are provided under the terms of the Eclipse Public License
v1.0.