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 (idxMaxSize()); 
			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; idxGetView()->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