examples/ForumNokia/AudioStreamExample/src/AudioStreamEngine.cpp

00001 /*
00002  * Copyright (c) 2008-2010 Nokia Corporation and/or its subsidiary(-ies). All rights reserved.
00003  *    
00004  * Redistribution and use in source and binary forms, with or without
00005  * modification, are permitted provided that the following conditions are met:
00006  *    
00007  *  * Redistributions of source code must retain the above copyright notice, this
00008  *    list of conditions and the following disclaimer.
00009  *  * Redistributions in binary form must reproduce the above copyright notice,
00010  *    this list of conditions and the following disclaimer in the documentation
00011  *    and/or other materials provided with the distribution.
00012  *  * Neither the name of Nokia Corporation nor the names of its contributors
00013  *    may be used to endorse or promote products derived from this software
00014  *    without specific prior written permission.
00015  *    
00016  *    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
00017  *    AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00018  *    IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
00019  *    DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
00020  *    FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
00021  *    DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
00022  *    SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
00023  *    CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
00024  *    OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
00025  *    OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00026  *    
00027  *    Description:  
00028  */
00029 
00030 #include <mda/common/audio.h>
00031 #include <mmf/common/mmfutilities.h>
00032 #include <MdaAudioInputStream.h>    // audio input stream
00033 #include <MdaAudioOutputStream.h>   // audio output stream
00034 #include <s32file.h>                // RFileWriteStream and RFileReadStream
00035 
00036 #include "AudioStreamEngine.h"
00037 #include "audiostream.pan"
00038 
00039 // Audio data buffer size.
00040 // In both 3rd Edition and 2nd Edition the total buffer (iStreamBuffer) size is 
00041 // KFrameSizePCM * KFrameCountPCM = 40960 bytes. This will contain 2560 ms 
00042 // of 16-bit audio data. 
00043 // In 3rd Edition the KFrameSizePCM is 4096 bytes, because CMdaAudioInputStream::ReadL() 
00044 // returns audio data in 4096-byte chunks. In 2nd Edition, ReadL() returns data in 320-byte
00045 // chunks.
00046 const TInt KFrameSizePCM = 4096;
00047 const TInt KFrameCountPCM = 100;
00048 
00049 // Audio data buffer size for AMR encoding. For AMR, the buffer size is the same in
00050 // both 2nd and 3rd Edition devices (20 ms per frame, a total of 2560 ms in 128 frames).
00051 const TInt KFrameSizeAMR = 14;
00052 const TInt KFrameCountAMR = 128;
00053 // Header data for an AMR-encoded audio file
00054 const TInt KAMRHeaderLength=6;
00055 const TUint8 KAMRNBHeader[KAMRHeaderLength] = { 0x23, 0x21, 0x41, 0x4d, 0x52, 0x0a };
00056 
00057 // Files to store the sample audio clips
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 // Standard EPOC 2nd phase constructor
00078 void CAudioStreamEngine::ConstructL()
00079     {
00080     // Construct streams. We need to construct these here, so that at least the input stream
00081     // exists if SetEncodingL() is called before any recording has taken place 
00082     iInputStream = CMdaAudioInputStream::NewL(*this);
00083     iOutputStream = CMdaAudioOutputStream::NewL(*this);
00084 
00085     // Get a handle to the RFs session to be used (owned by CEikonEnv, NOT to be closed
00086     // when this application exits!)        
00087     iFs = CEikonEnv::Static()->FsSession();
00088 
00089     // Save the default encoding for later reference (the encoding is the same for
00090     // both input and output streams).
00091     iDefaultEncoding = iInputStream->DataType();
00092     // At first we are using the default encoding.
00093     iCurrentEncoding = iDefaultEncoding;
00094 
00095     // Stream buffer allocation (by default for PCM)
00096     iStreamBuffer = HBufC8::NewMaxL(iFrameSize * iFrameCount);
00097     iStreamStart=0;
00098     iStreamEnd=iFrameCount - 1;
00099     
00100     // The sample.aud/amr can be found in \private<UID3>\ folder
00101     User::LeaveIfError( iFs.CreatePrivatePath( EDriveC ) );
00102     User::LeaveIfError( iFs.SetSessionToPrivate( EDriveC ) );
00103     
00104     iStop = CIdle::NewL( CActive::EPriorityIdle );
00105     }
00106 
00107 // ----------------------------------------------------------------------------
00108 // CAudioStreamEngine::CAudioStreamEngine(
00109 //     CAudioStreamAppUi* aAppUi)
00110 //
00111 // onstructor
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     // By default we use PCM and initialise the instance variables accordingly above.
00118         
00119     // Initial audio stream properties for input and output, 8KHz mono. 
00120     // These settings could also be set/changed using method SetAudioPropertiesL() of
00121     // the input and output streams.
00122     iStreamSettings.iChannels=TMdaAudioDataSettings::EChannelsMono;
00123     iStreamSettings.iSampleRate=TMdaAudioDataSettings::ESampleRate8000Hz;
00124     }
00125 
00126 // ----------------------------------------------------------------------------
00127 // CAudioStreamEngine::~CAudioStreamEngine()
00128 //
00129 // destructor
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 // CAudioStreamEngine::Play()
00165 //
00166 // plays the audio data contained in the buffer
00167 // ----------------------------------------------------------------------------
00168 void CAudioStreamEngine::Play()
00169     {
00170     ShowMessage(_L("Play "), ETrue);
00171     // if either stream is active, return
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     // Open output stream.
00185     // Upon completion will receive callback in 
00186     // MMdaAudioOutputStreamCallback::MaoscOpenComplete().
00187     iOutputStream->Open(&iStreamSettings);
00188     }
00189 
00190 
00191 // ----------------------------------------------------------------------------
00192 // CAudioStreamEngine::Record()
00193 //
00194 // records audio data into the buffer
00195 // ----------------------------------------------------------------------------
00196 void CAudioStreamEngine::Record()
00197     {
00198     // If either stream is active, return
00199     if (iInputStatus!=ENotReady || iOutputStatus!=ENotReady) 
00200     {
00201         ShowMessage(_L("Stream in use, \ncannot record audio."), ETrue);
00202         return;
00203     }
00204 
00205     // Open input stream.
00206     // Upon completion will receive callback in 
00207     // MMdaAudioInputStreamCallback::MaiscOpenComplete().
00208     iInputStream->Open(&iStreamSettings);
00209     }
00210 
00211 // ----------------------------------------------------------------------------
00212 // CAudioStreamEngine::Stop()
00213 //
00214 // stops playing/recording
00215 // ----------------------------------------------------------------------------
00216 void CAudioStreamEngine::Stop()
00217     {
00218     // if input or output streams are active, close them
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 // CAudioStreamEngine::LoadAudioFileL()
00237 //
00238 // loads the audio data from a file into the buffer
00239 // ----------------------------------------------------------------------------
00240 void CAudioStreamEngine::LoadAudioFileL()
00241     {
00242     RFileReadStream audiofile;
00243 
00244     // open file
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);  // Empty the stream buffer
00251     if (err==KErrNone) 
00252         {
00253         // file opened ok, proceed reading
00254         if (iUseAMR)
00255             {
00256             // Read the AMR header (the first 6 bytes). We don't need to save/use the header,
00257             // since while playback we already know it's an AMR-NB encoded stream.
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         // failed to open file
00278         ShowMessage(_L("Error loading \naudio sample!"), ETrue); 
00279         iBufferOK = EFalse;
00280         }
00281     audiofile.Close();
00282     }
00283 
00284 
00285 // ----------------------------------------------------------------------------
00286 // CAudioStreamEngine::SaveAudioFileL()
00287 //
00288 // saves the audio data in the buffer into a file
00289 // ----------------------------------------------------------------------------
00290 void CAudioStreamEngine::SaveAudioFileL()
00291     {
00292     if (!iBufferOK)
00293     {
00294         // In case the encoding was changed between recording and trying to save the file
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     // Check for free space for saving the sample
00302     TVolumeInfo volinfo;
00303     TInt err=iFs.Volume(volinfo,EDriveC);
00304     if ( volinfo.iFree<(iFrameCount*iFrameSize))
00305         {
00306         // Not enough free space on drive for saving, report and exit
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                 // Write the six-byte AMR header, so that the file can be used by other
00320                 // applications as well.
00321                 for (int i = 0; i < KAMRHeaderLength; i++)
00322                     audiofile.WriteUint8L(KAMRNBHeader[i]);
00323             }
00324             
00325         // File opened ok, proceed writing.
00326         // Write audio data directly from iStreamBuffer
00327         for (TUint idx=iStreamStart; idx<=iStreamEnd; idx++)//iFrameCount; idx++)
00328             {
00329             audiofile.WriteL(GetFrame(idx));
00330             }
00331         ShowMessage(_L("Saving complete!"), ETrue); 
00332         }   
00333     else 
00334         {
00335         // failed to open file
00336         ShowMessage(_L("Error saving \naudio sample!"), ETrue); 
00337         }
00338     audiofile.Close();
00339     }
00340 
00341 // ----------------------------------------------------------------------------
00342 // CAudioStreamEngine::SetEncodingL(TBool aAmr)
00343 //
00344 // If argument is ETrue, AMR-NB encoding will be used in audio input/output.
00345 // If EFalse, the default PCM is used. If the platform does not support AMR-NB,
00346 // PCM will be used no matter what the argument's value is.
00347 // ----------------------------------------------------------------------------
00348 void CAudioStreamEngine::SetEncodingL(TBool aAmr)
00349     {
00350     // Act only if the new encoding differs from the current one
00351     if (iUseAMR != aAmr)
00352         {
00353         iUseAMR = aAmr;
00354         if (iUseAMR)
00355             {
00356             // Try to set AMR-NB encoding, this will indicate whether it is supported
00357             // by the platform or not.
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                 // We do not need to invalidate the buffer or change buffer settings, 
00365                 // since the encoding was not changed -> just return.
00366                 return;  
00367                 }
00368             else
00369                 {
00370                 iCurrentEncoding = KMMFFourCCCodeAMR;
00371                 iAudioFile.Zero();  // Empty the audio file name                
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             // If we get here, the encoding has previously been changed to AMR. Switch back to
00381             // PCM.
00382             iCurrentEncoding = iDefaultEncoding;
00383             iAudioFile.Zero();  // Empty the audio file name                
00384             iAudioFile.Append(KAudioFilePCM);
00385             iFrameCount = KFrameCountPCM;
00386             iFrameSize = KFrameSizePCM;
00387             ShowMessage(_L("Encoding set to PCM."), ETrue); 
00388             }
00389 
00390         // Make sure the user re-records or reloads the audio file, so that we do not 
00391         // accidentally try to play PCM data using AMR or vice versa.
00392         iBufferOK = EFalse; 
00393         if (iStreamBuffer) delete iStreamBuffer;
00394         iStreamBuffer = NULL; // In case the following NewL leaves
00395         iStreamBuffer = HBufC8::NewMaxL(iFrameSize * iFrameCount);
00396         iStreamStart=0;
00397         iStreamEnd=iFrameCount - 1;
00398         }   
00399     }
00400 
00401 // ----------------------------------------------------------------------------
00402 // CAudioStreamEngine::ShowMessage(
00403 //     const TDesC& aMsg, TBool aReset=EFalse)
00404 //
00405 // displays text referenced by aMsg in the label, will append the aMsg in the 
00406 // existing text in label if aReset is EFalse, otherwise will reset the label 
00407 // text.
00408 // ----------------------------------------------------------------------------
00409 void CAudioStreamEngine::ShowMessage(const TDesC& aMsg, TBool aReset=EFalse)
00410     {
00411     if (aReset)     // if ETrue, clear the message on the label prior to output
00412         iMsg.Zero();
00413     iMsg.Append(aMsg);
00414     TRAPD(error, iAppUi->GetView()->ShowMessageL(iMsg));
00415     PanicIfError(error);
00416     }
00417 
00418 // ----------------------------------------------------------------------------
00419 // TPtr8& CAudioStreamEngine::GetFrame(TUint aFrameIdx)
00420 //
00421 // Returns a modifiable pointer to a single frame inside the audio buffer 
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 // TPtr8& CAudioStreamEngine::GetPlaybackFrames(TUint aLastFrame)
00436 //
00437 // Returns a modifiable pointer to the requested frames inside the audio buffer
00438 // (from the first frame to aLastFrame). 
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 // MMdaAudioInputStream callbacks (MMdaAudioInputStreamCallback)
00454 //
00455 // ----------------------------------------------------------------------------
00456 // CAudioStreamEngine::MaiscOpenComplete(
00457 //     TInt aError)
00458 //
00459 // called upon completion of CMdaAudioInputStream::Open(),
00460 // if the stream was opened succesfully (aError==KErrNone), it's ready for use.
00461 // upon succesful open, the first audio data block will be read from the input
00462 // stream.
00463 // ----------------------------------------------------------------------------
00464 void CAudioStreamEngine::MaiscOpenComplete(TInt aError)
00465     {
00466     if (aError==KErrNone) 
00467         {
00468         // Input stream opened succesfully, set status
00469         iInputStatus = EOpen;
00470         // Set the data type (encoding)
00471         TRAPD(error, iInputStream->SetDataTypeL(iCurrentEncoding));
00472         PanicIfError(error);
00473 
00474         // set stream input gain to maximum
00475         iInputStream->SetGain(iInputStream->MaxGain()); 
00476         // set stream priority to normal and time sensitive
00477         iInputStream->SetPriority(EPriorityNormal, EMdaPriorityPreferenceTime);             
00478         ShowMessage(_L("Recording..."), ETrue);
00479         
00480         // Emtpy the buffer and issue ReadL() to read the first audio data block, 
00481         // subsequent calls to ReadL() will be issued 
00482         // in MMdaAudioInputStreamCallback::MaiscBufferCopied()
00483         iStreamBuffer->Des().FillZ(iFrameCount * iFrameSize);
00484         iStreamIdx=0;
00485         TRAPD(error2, iInputStream->ReadL(GetFrame(iStreamIdx)));
00486         PanicIfError(error2);
00487         } 
00488     else 
00489         {
00490         // input stream open failed
00491         iInputStatus = ENotReady;
00492         ShowMessage(_L("Recording failed!"), ETrue);
00493         }
00494     }
00495 
00496 // ----------------------------------------------------------------------------
00497 // CAudioStreamEngine::MaiscBufferCopied(
00498 //     TInt aError, const TDesC8& aBuffer)
00499 //
00500 // called when a block of audio data has been read and is available at the 
00501 // buffer reference *aBuffer.  calls to ReadL() will be issued until all blocks
00502 // in the audio data buffer (iStreamBuffer) are filled.
00503 // ----------------------------------------------------------------------------
00504 void CAudioStreamEngine::MaiscBufferCopied(TInt aError, const TDesC8& /*aBuffer*/)
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(); // message
00513         message = NULL;
00514         }
00515     
00516     if (aError==KErrNone) 
00517         {
00518         // stop recording if at the end of the buffer
00519         iStreamIdx++;
00520         if (iStreamIdx == iFrameCount)
00521             {
00522             ShowMessage(_L("\nRecording complete!"), ETrue);
00523             iStreamEnd = iStreamIdx - 1;
00524             iBufferOK = ETrue;
00525 
00526             // Playback is complete:
00527             // Start the active object that will stop the stream
00528             iStop->Start( TCallBack(BackgroundStop, this) );            
00529             return;
00530             }       
00531         
00532         // issue ReadL() for next frame     
00533         TRAPD(error, iInputStream->ReadL(GetFrame(iStreamIdx)));
00534         PanicIfError(error);
00535         }
00536     else if (aError==KErrAbort) 
00537         {
00538         // Recording was aborted, due to call to CMdaAudioInputStream::Stop()
00539         // This KErrAbort will occur each time the Stop() method in this class is executed.
00540         // Also, MaiscRecordComplete() will be called after exiting this method.
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 )  // static member function
00554     {
00555     ((CAudioStreamEngine*)aStream)->Stop();
00556     return EFalse;
00557     }
00558 
00559 
00560 // ----------------------------------------------------------------------------
00561 // CAudioStreamEngine::MaiscRecordComplete(
00562 //     TInt aError)
00563 //
00564 // called when input stream is closed by CMdaAudioInputStream::Stop()
00565 // ----------------------------------------------------------------------------
00566 void CAudioStreamEngine::MaiscRecordComplete(TInt aError)
00567     {   
00568     iInputStatus = ENotReady;
00569     if (aError==KErrNone) 
00570         {
00571         // normal stream closure
00572         }
00573     else 
00574         {
00575         // completed with error(s)
00576         }
00577     }
00578 
00579 
00580 // MMdaAudioOutputStream callbacks (MMdaAudioOutputStreamCallback)
00581 
00582 // ----------------------------------------------------------------------------
00583 // CAudioStreamEngine::MaoscOpenComplete(
00584 //     TInt aError)
00585 //
00586 // called upon completion of CMdaAudioOutputStream::Open(),
00587 // if the stream was opened succesfully (aError==KErrNone), it's ready for use.
00588 // upon succesful open, the first audio data block will be written to the 
00589 // output stream.
00590 // ----------------------------------------------------------------------------
00591 void CAudioStreamEngine::MaoscOpenComplete(TInt aError)
00592     {
00593     if (aError==KErrNone) 
00594         {
00595         // output stream opened succesfully, set status
00596         iOutputStatus = EOpen;
00597         // Set the data type (encoding). Should not fail, since we already
00598         // have tested support for this encoding in SetEncodingL with the 
00599         // corresponding input stream!
00600         TRAPD(error, iOutputStream->SetDataTypeL(iCurrentEncoding));
00601         PanicIfError(error);
00602         
00603         // set volume to 1/4th of stream max volume
00604         iOutputStream->SetVolume(iOutputStream->MaxVolume()/2);
00605         // set stream priority to normal and time sensitive
00606         iOutputStream->SetPriority(EPriorityNormal, 
00607             EMdaPriorityPreferenceTime);                
00608         ShowMessage(_L("Playing "), ETrue);
00609 
00610         if (iUseAMR)
00611             {
00612             // In case of AMR, the whole recorded/loaded buffer is played back at once, not frame by frame. 
00613             // The buffer might not be fully recorded, so we will only play back the part
00614             // that is filled with data.
00615             iStreamIdx = iStreamEnd;
00616             TRAPD(error2, iOutputStream->WriteL(GetPlaybackFrames(iStreamEnd)));
00617             PanicIfError(error2);
00618             }
00619         else
00620             {
00621             // PCM needs to be played back frame by frame, otherwise some older devices might
00622             // run into buffer overflow situations.
00623             iStreamIdx = 0;
00624             TRAPD(error3, iOutputStream->WriteL(GetFrame(iStreamIdx)));
00625             PanicIfError(error3);
00626             }
00627         }
00628     else 
00629         {
00630         // output stream open failed
00631         iOutputStatus = ENotReady;
00632         ShowMessage(_L("Playback failed!"), ETrue);
00633         }       
00634     }
00635 
00636 // ----------------------------------------------------------------------------
00637 // CAudioStreamEngine::MaoscBufferCopied(
00638 //     TInt aError, const TDesC8& aBuffer)
00639 //
00640 // called when a block of audio data has been written to MMF. calls to WriteL() 
00641 // will be issued until all blocks in the audio data buffer (iStreamBuffer) are 
00642 // written.
00643 // ----------------------------------------------------------------------------
00644 void CAudioStreamEngine::MaoscBufferCopied(TInt aError, const TDesC8& /*aBuffer*/)
00645     {   
00646     if (aError==KErrNone) 
00647         {
00648         if (iStreamIdx==iStreamEnd)
00649             {
00650             ShowMessage(_L("\nPlayback complete!"), EFalse);
00651             // Playback is complete:
00652             // Start the active object that will stop the stream
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         // Playing was aborted, due to call to CMdaAudioOutputStream::Stop().
00665         // MaoscRecordComplete() will be called after exiting this method.
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 // CAudioStreamEngine::MaoscPlayComplete(
00678 //     TInt aError)
00679 //
00680 // called when output stream is closed by CMdaAudioOutputStream::Stop() or if 
00681 // end of audio data has been reached, in this case KErrUnderflow will be 
00682 // returned.
00683 // ----------------------------------------------------------------------------
00684 void CAudioStreamEngine::MaoscPlayComplete(TInt aError)
00685     {
00686     iOutputStatus = ENotReady;
00687     if (aError==KErrNone) 
00688         {
00689         // normal stream closure
00690         }   
00691     else if (aError==KErrUnderflow) 
00692         {
00693         // end of audio data stream was reached because of stream underflow,
00694         }
00695     else 
00696         {
00697         // completed with error(s)
00698         }   
00699     }
00700 
00701 // END OF FILE
00702 

Generated by  doxygen 1.6.2