www.pudn.com > Audio_Streaming_Example_v1_0.zip > AudioStreamEngine.cpp
/* * ============================================================================ * Name : CAudioStreamEngine from AudioStreamEngine.cpp * Part of : AudioStream * Created : 24.11.2003 by Nokia Forum * Implementation notes: * Initial content was generated by Series 60 AppWizard. * Version : * Copyright: Nokia Corporation * ============================================================================ */ #include#include // audio input stream #include // audio output stream #include "AudioStreamEngine.h" // audio data buffer size // 11200 bytes will contain 700ms of 16bit audio data const TInt KStreamBufferSize = 11200; // number of audio data buffers const TInt KStreamBufferCount = 3; // file to store the sample _LIT(KAudioFile, "c:\\system\\apps\\audiostream\\sample.aud"); CAudioStreamEngine* CAudioStreamEngine::NewL(CAudioStreamAppUi* aAppUi) { CAudioStreamEngine* self = CAudioStreamEngine::NewLC(aAppUi); CleanupStack::Pop(self); return self; } CAudioStreamEngine* CAudioStreamEngine::NewLC(CAudioStreamAppUi* aAppUi) { CAudioStreamEngine* self = new (ELeave) CAudioStreamEngine(aAppUi); CleanupStack::PushL(self); self->ConstructL(); return self; } // Standard EPOC 2nd phase constructor void CAudioStreamEngine::ConstructL() { // Construct input stream iInputStream = CMdaAudioInputStream::NewL(*this); // Construct output stream iOutputStream = CMdaAudioOutputStream::NewL(*this); // Stream buffer allocation TDes8* buffer; for (TInt idx=0; idx ; CleanupStack::PushL(buffer); buffer->SetMax(); User::LeaveIfError(iStreamBuffer.Append(buffer)); CleanupStack::Pop(buffer); } iStreamStart=0; iStreamEnd=iStreamBuffer.Count()-1; } // ---------------------------------------------------------------------------- // CAudioStreamEngine::CAudioStreamEngine( // CAudioStreamAppUi* aAppUi) // // constructor // ---------------------------------------------------------------------------- CAudioStreamEngine::CAudioStreamEngine(CAudioStreamAppUi* aAppUi) { iAppUi=aAppUi; // initial audio stream properties, 8KHz mono iStreamSettings.iChannels=TMdaAudioDataSettings::EChannelsMono; iStreamSettings.iSampleRate=TMdaAudioDataSettings::ESampleRate8000Hz; } // ---------------------------------------------------------------------------- // CAudioStreamEngine::~CAudioStreamEngine() // // destructor // ---------------------------------------------------------------------------- CAudioStreamEngine::~CAudioStreamEngine() { // close and delete streams if (iInputStatus!=ENotReady) iInputStream->Stop(); if (iOutputStatus!=ENotReady) iOutputStream->Stop(); delete iInputStream; iInputStream=NULL; delete iOutputStream; iOutputStream=NULL; // empties and deletes stream buffer iStreamBuffer.ResetAndDestroy(); } // ---------------------------------------------------------------------------- // CAudioStreamEngine::Play() // // plays the audio data contained in the buffer // ---------------------------------------------------------------------------- void CAudioStreamEngine::Play() { // if either stream is active, return if (iInputStatus!=ENotReady || iOutputStatus!=ENotReady) return; // open output stream // upon completion will receive callback in // MMdaAudioInputStreamCallback::MaoscOpenComplete() iOutputStream->Open(&iStreamSettings); } // ---------------------------------------------------------------------------- // CAudioStreamEngine::Record() // // records audio data into the buffer // ---------------------------------------------------------------------------- void CAudioStreamEngine::Record() { // If either stream is active, return if (iInputStatus!=ENotReady || iOutputStatus!=ENotReady) return; // open input stream // upon completion will receive callback in // MMdaAudioInputStreamCallback::MaiscOpenComplete() iInputStream->Open(&iStreamSettings); } // ---------------------------------------------------------------------------- // CAudioStreamEngine::Stop() // // stops playing/recording // ---------------------------------------------------------------------------- void CAudioStreamEngine::Stop() { // if input or output streams are active, close them if (iInputStatus!=ENotReady) { iInputStream->Stop(); ShowMessageL(_L("Recording stopped!"), true); // get stream start (first block of audio) and end index iStreamEnd = iStreamIdx; iStreamStart = iStreamIdx+1; if (iStreamStart==iStreamBuffer.Count()) iStreamStart=0; } if (iOutputStatus!=ENotReady) { iOutputStream->Stop(); ShowMessageL(_L("Playback stopped!"), true); } } // ---------------------------------------------------------------------------- // CAudioStreamEngine::LoadAudioFileL() // // loads the audio data from a file into the buffer // ---------------------------------------------------------------------------- void CAudioStreamEngine::LoadAudioFileL() { RFs fs; // file server instance RFile audiofile; // open fileserver session and file User::LeaveIfError(fs.Connect()); // push into cleanup stack CleanupClosePushL(fs); // open file TInt err = audiofile.Open(fs, KAudioFile, EFileRead|EFileStream); if (err==KErrNone) { // file opened ok, proceed reading TInt idx=0; while (idx MaxSize()); if (fstatus!=KErrNone) break; idx++; } ShowMessageL(_L("Loading complete!"), true); } else { // failed to open file ShowMessageL(_L("Error loading audio sample!"), true); } iStreamStart=0; iStreamEnd=iStreamBuffer.Count()-1; audiofile.Close(); // pop and destroy resources pushed into stack CleanupStack::PopAndDestroy(); } // ---------------------------------------------------------------------------- // CAudioStreamEngine::SaveAudioFileL() // // saves the audio data in the buffer into a file // ---------------------------------------------------------------------------- void CAudioStreamEngine::SaveAudioFileL() { RFs fs; // file server instance RFile audiofile; TInt writeidx=iStreamStart; // open fileserver session and file User::LeaveIfError(fs.Connect()); // push into cleanup stack CleanupClosePushL(fs); // check for free space for saving the sample TVolumeInfo volinfo; TInt err=fs.Volume(volinfo,EDriveC); if ( volinfo.iFree<(iStreamBuffer.Count()*KStreamBufferSize) ) { // not enough free space on drive for saving, report and exit CleanupStack::PopAndDestroy(); ShowMessageL(_L("Cannot save file:\nnot enough space!"), true); return; } err = audiofile.Open(fs, KAudioFile, EFileWrite|EFileStream); if (err==KErrNone) { // file opened ok, proceed writing // read audio data directly into iStreamBuffer for (TInt idx=0; idx GetView()->ShowMessageL(iMsg); } // // MMdaAudioInputStream callbacks (MMdaAudioInputStreamCallback) // // ---------------------------------------------------------------------------- // CAudioStreamEngine::MaiscOpenComplete( // TInt aError) // // called upon completion of CMdaAudioInputStream::Open(), // if the stream was opened succesfully (aError==KErrNone), it's ready for use. // upon succesful open, the first audio data block will be read from the input // stream. // ---------------------------------------------------------------------------- void CAudioStreamEngine::MaiscOpenComplete(TInt aError) { if (aError==KErrNone) { // input stream opened succesfully, set status iInputStatus = EOpen; // set stream properties, 16bit 8KHz mono iInputStream->SetAudioPropertiesL(iStreamSettings.iSampleRate, iStreamSettings.iChannels); // set stream input gain to maximum iInputStream->SetGain(iInputStream->MaxGain()); // set stream priority to normal and time sensitive iInputStream->SetPriority(EPriorityNormal, EMdaPriorityPreferenceTime); ShowMessageL(_L("Recording ..."), true); // issue ReadL() to read the first audio data block, // subsequent calls to ReadL() will be issued // in MMdaAudioInputStreamCallback::MaiscBufferCopied() iStreamIdx=0; iInputStream->ReadL(*iStreamBuffer[iStreamIdx]); } else { // input stream open failed iInputStatus = ENotReady; ShowMessageL(_L("Recording failed!"), true); } } // ---------------------------------------------------------------------------- // CAudioStreamEngine::MaiscBufferCopied( // TInt aError, const TDesC8& aBuffer) // // called when a block of audio data has been read and is available at the // buffer reference *aBuffer. calls to ReadL() will be issued until all blocks // in the audio data buffer (iStreamBuffer) are filled. // ---------------------------------------------------------------------------- void CAudioStreamEngine::MaiscBufferCopied(TInt aError, const TDesC8& aBuffer) { if (aError==KErrNone) { // see if end of buffer, if so, rotate buffer if (&aBuffer==iStreamBuffer[iStreamBuffer.Count()-1]) iStreamIdx=0; else iStreamIdx++; // issue ReadL() for next audio data block iInputStream->ReadL(*iStreamBuffer[iStreamIdx]); } else if (aError==KErrAbort) { // recording was aborted, due to call to CMdaAudioInputStream::Stop() // this KErrAbort will occur each time the Stop() above is executed. iInputStatus = ENotReady; } else { // error reading data from input iInputStatus = ENotReady; } } // ---------------------------------------------------------------------------- // CAudioStreamEngine::MaiscRecordComplete( // TInt aError) // // called when input stream is closed by CMdaAudioInputStream::Stop() // ---------------------------------------------------------------------------- void CAudioStreamEngine::MaiscRecordComplete(TInt aError) { iInputStatus = ENotReady; if (aError==KErrNone) { // normal stream closure } else { // completed with error(s) } } // MMdaAudioOutputStream callbacks (MMdaAudioOutputStreamCallback) // ---------------------------------------------------------------------------- // CAudioStreamEngine::MaoscOpenComplete( // TInt aError) // // called upon completion of CMdaAudioOutputStream::Open(), // if the stream was opened succesfully (aError==KErrNone), it's ready for use. // upon succesful open, the first audio data block will be written to the // output stream. // ---------------------------------------------------------------------------- void CAudioStreamEngine::MaoscOpenComplete(TInt aError) { if (aError==KErrNone) { // output stream opened succesfully, set status iOutputStatus = EOpen; // set stream properties, 16bit 8KHz mono iOutputStream->SetAudioPropertiesL(iStreamSettings.iSampleRate, iStreamSettings.iChannels); // set volume to 1/4th of stream max volume iOutputStream->SetVolume(iOutputStream->MaxVolume()/4); // set stream priority to normal and time sensitive iOutputStream->SetPriority(EPriorityNormal, EMdaPriorityPreferenceTime); ShowMessageL(_L("Playing "), true); // issue WriteL() to write the first audio data block, // subsequent calls to WriteL() will be issued in // MMdaAudioOutputStreamCallback::MaoscBufferCopied() // until whole data buffer is written. iStreamIdx=iStreamStart; iOutputStream->WriteL(*iStreamBuffer[iStreamIdx]); } else { // output stream open failed iOutputStatus = ENotReady; ShowMessageL(_L("Playback failed!"), true); } } // ---------------------------------------------------------------------------- // CAudioStreamEngine::MaiscBufferCopied( // TInt aError, const TDesC8& aBuffer) // // called when a block of audio data has been written to MMF. calls to WriteL() // will be issued until all blocks in the audio data buffer (iStreamBuffer) are // written. // ---------------------------------------------------------------------------- void CAudioStreamEngine::MaoscBufferCopied(TInt aError, const TDesC8& aBuffer) { if (aError==KErrNone) { ShowMessageL(_L(".")); // indicate buffer was written if (&aBuffer==iStreamBuffer[iStreamEnd]) { ShowMessageL(_L("\nPlayback complete!"), false); iOutputStatus = ENotReady; } else { iStreamIdx++; // rotate stream if necessary if (iStreamIdx==iStreamBuffer.Count()) iStreamIdx=0; // issue WriteL() for next audio data block iOutputStream->WriteL(*iStreamBuffer[iStreamIdx]); } } else if (aError==KErrAbort) { // playing was aborted, due to call to CMdaAudioOutputStream::Stop() } else { // error writing data to output iOutputStatus = ENotReady; } } // ---------------------------------------------------------------------------- // CAudioStreamEngine::MaoscPlayComplete( // TInt aError) // // called when output stream is closed by CMdaAudioOutputStream::Stop() or if // end of audio data has been reached, in this case KErrUnderflow will be // returned. // ---------------------------------------------------------------------------- void CAudioStreamEngine::MaoscPlayComplete(TInt aError) { iOutputStatus = ENotReady; if (aError==KErrNone) { // normal stream closure } else if (aError==KErrUnderflow) { // end of audio data stream was reached because of stream underflow, } else { // completed with error(s) } } // END OF FILE