⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 audiostreamengine.cpp

📁 symbian Audio_Streaming_Example_v1_0 series60第二版线程编程
💻 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 <mda\common\audio.h>
#include <MdaAudioInputStream.h>	// audio input stream
#include <MdaAudioOutputStream.h>	// 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<KStreamBufferCount; idx++)
		{
		buffer = new(ELeave) TBuf8<KStreamBufferSize>;
		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<iStreamBuffer.Count())
			{
			TInt fstatus=audiofile.Read(*iStreamBuffer[idx], 
				(iStreamBuffer[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<iStreamBuffer.Count(); idx++)	
			{
			audiofile.Write(*iStreamBuffer[writeidx]);
			writeidx++;
			// write buffers in correct order, rotate if necessary
			if (writeidx==iStreamBuffer.Count()) writeidx=0;
			}
		ShowMessageL(_L("Saving complete!"), true);	
		}	
	else 
		{
		// failed to open file
		ShowMessageL(_L("Error saving audio sample!"), true);	
		}
	audiofile.Close();
	// pop and destroy resources pushed into stack
	CleanupStack::PopAndDestroy();
	}


// ----------------------------------------------------------------------------
// CAudioStreamEngine::ShowMessageL(
//     const TDesC& aMsg, TBool aReset=false)
//
// displays text referenced by aMsg in the label, will append the aMsg in the 
// existing text in label if aReset is false, otherwise will reset the label 
// text.
// ----------------------------------------------------------------------------
void CAudioStreamEngine::ShowMessageL(const TDesC& aMsg, TBool aReset=false)
	{
	if (aReset) 	// if true, clear the message on the label prior to output
		iMsg.Zero();
	iMsg.Append(aMsg);
	iAppUi->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

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -