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

📄 audiostreamengine.cpp

📁 S60_Platform_Audio_Streaming_Example 60平台下
💻 CPP
📖 第 1 页 / 共 2 页
字号:
/*
* ============================================================================
*  Name     : CAudioStreamEngine from AudioStreamEngine.cpp
*  Part of  : AudioStream
*  Created  : April 28, 2006 by Forum Nokia
*  Implementation notes:
*
*     Initial content was generated by S60 AppWizard.
*  Version  : 2.0
*  Copyright: Nokia Corporation
* ============================================================================
*/


#include <mda\common\audio.h>
#include <mmf\common\mmfutilities.h>
#include <MdaAudioInputStream.h>	// audio input stream
#include <MdaAudioOutputStream.h>	// audio output stream
#include <s32file.h>				// RFileWriteStream and RFileReadStream

#include "AudioStreamEngine.h"
#include "audiostream.pan"

// Audio data buffer size.
// In both 3rd Edition and 2nd Edition the total buffer (iStreamBuffer) size is 
// KFrameSizePCM * KFrameCountPCM = 40960 bytes. This will contain 2560 ms 
// of 16-bit audio data. 
// In 3rd Edition the KFrameSizePCM is 4096 bytes, because CMdaAudioInputStream::ReadL() 
// returns audio data in 4096-byte chunks. In 2nd Edition, ReadL() returns data in 320-byte
// chunks.
#ifdef __SERIES60_3X__  // 3rd Edition
const TInt KFrameSizePCM = 4096;
const TInt KFrameCountPCM = 10;
#else // 2nd Edition
const TInt KFrameSizePCM = 320;
const TInt KFrameCountPCM = 128;
#endif

// Audio data buffer size for AMR encoding. For AMR, the buffer size is the same in
// both 2nd and 3rd Edition devices (20 ms per frame, a total of 2560 ms in 128 frames).
const TInt KFrameSizeAMR = 14;
const TInt KFrameCountAMR = 128;
// Header data for an AMR-encoded audio file
const TInt KAMRHeaderLength=6;
const TUint8 KAMRNBHeader[KAMRHeaderLength] = { 0x23, 0x21, 0x41, 0x4d, 0x52, 0x0a };

// Files to store the sample audio clips
_LIT(KAudioFilePCM, "sample.aud");
_LIT(KAudioFileAMR, "sample.amr");

#ifdef __WINS__
// The path to the sample files in 2nd Ed emulator
_LIT(KEmulatorPath, "c:\\system\\apps\\audiostream\\");
#endif

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 streams. We need to construct these here, so that at least the input stream
	// exists if SetEncodingL() is called before any recording has taken place 
	iInputStream = CMdaAudioInputStream::NewL(*this);
	iOutputStream = CMdaAudioOutputStream::NewL(*this);

	// Get a handle to the RFs session to be used (owned by CEikonEnv, NOT to be closed
	// when this application exits!)		
	iFs = CEikonEnv::Static()->FsSession();

	// Save the default encoding for later reference (the encoding is the same for
	// both input and output streams).
	iDefaultEncoding = iInputStream->DataType();
	// At first we are using the default encoding.
	iCurrentEncoding = iDefaultEncoding;

	// Stream buffer allocation (by default for PCM)
	iStreamBuffer = HBufC8::NewMaxL(iFrameSize * iFrameCount);
	iStreamStart=0;
	iStreamEnd=iFrameCount - 1;
	
	#ifdef __SERIES60_3X__    
	// Only in 3rd Edition. The sample.aud/amr can be found in \private\<UID3>\ folder.
    	User::LeaveIfError( iFs.CreatePrivatePath( EDriveC ) );
	User::LeaveIfError( iFs.SetSessionToPrivate( EDriveC ) );
	#else
		#ifndef __WINS__  // don't save settings to z-drive in emulator
			// In 2nd Ed device the sample.aud/amr will be in \system\apps\audiostream\ folder.
    		TFileName appFullName = iAppUi->Application()->AppFullName();
    		TParsePtr appPath(appFullName);
	    	iAudioFilePath = appPath.DriveAndPath();
		#else 
			// For 2nd Ed emulator
			iAudioFilePath.Append(KEmulatorPath);
		#endif //__WINS__
		
	#endif
	}

// ----------------------------------------------------------------------------
// CAudioStreamEngine::CAudioStreamEngine(
//     CAudioStreamAppUi* aAppUi)
//
// onstructor
// ----------------------------------------------------------------------------
CAudioStreamEngine::CAudioStreamEngine(CAudioStreamAppUi* aAppUi)
: iAppUi(aAppUi), iUseAMR(EFalse), iAudioFile(KAudioFilePCM), iFrameSize(KFrameSizePCM), 
iFrameCount(KFrameCountPCM), iStreamBuffer(0), iFramePtr(0,0), iBufferOK(EFalse)
	{
	// By default we use PCM and initialise the instance variables accordingly above.
		
	// Initial audio stream properties for input and output, 8KHz mono. 
	// These settings could also be set/changed using method SetAudioPropertiesL() of
	// the input and output streams.
	iStreamSettings.iChannels=TMdaAudioDataSettings::EChannelsMono;
	iStreamSettings.iSampleRate=TMdaAudioDataSettings::ESampleRate8000Hz;
	}

// ----------------------------------------------------------------------------
// CAudioStreamEngine::~CAudioStreamEngine()
//
// destructor
// ----------------------------------------------------------------------------
CAudioStreamEngine::~CAudioStreamEngine()
	{ 
	// close and delete streams
	if (iInputStream)
		{
		if (iInputStatus!=ENotReady) iInputStream->Stop();
	    delete iInputStream;
    	iInputStream=NULL;
		}
	if (iOutputStream)
		{
		if (iOutputStatus!=ENotReady) iOutputStream->Stop();
	    delete iOutputStream;
    	iOutputStream=NULL;
		}
	if (iStreamBuffer)
		{
		delete iStreamBuffer;
		iStreamBuffer = NULL;
		}
	}


// ----------------------------------------------------------------------------
// CAudioStreamEngine::Play()
//
// plays the audio data contained in the buffer
// ----------------------------------------------------------------------------
void CAudioStreamEngine::Play()
	{
	ShowMessage(_L("Play "), ETrue);
	// if either stream is active, return
	if (iInputStatus!=ENotReady || iOutputStatus!=ENotReady) 
		{
	    ShowMessage(_L("Stream in use, \ncannot play audio."), ETrue);
		return;
		}

	if(!iBufferOK)
	    {
	    ShowMessage(_L("Nothing to play - \nrecord or load \na file first."), ETrue);
	    return;
	    }
		
	// Open output stream.
	// Upon completion will receive callback in 
	// MMdaAudioOutputStreamCallback::MaoscOpenComplete().
	#ifndef __SERIES60_3X__  // Not 3rd Ed
		// Some 2nd Edition, FP2 devices (such as Nokia 6630) require the stream to be
		// reconstructed each time before calling Open() - otherwise the callback
		// never gets called.
		if (iOutputStream) delete iOutputStream;
		iOutputStream = NULL; // In case the following NewL leaves
		TRAPD(err, iOutputStream = CMdaAudioOutputStream::NewL(*this));
		PanicIfError(err);
	#endif
	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) 
	{
	    ShowMessage(_L("Stream in use, \ncannot record audio."), ETrue);
		return;
	}

	// Open input stream.
	// Upon completion will receive callback in 
	// MMdaAudioInputStreamCallback::MaiscOpenComplete().
	#ifndef __SERIES60_3X__  // Not 3rd Ed
		// Some 2nd Edition, FP2 devices (such as Nokia 6630) require the stream to be
		// reconstructed each time before calling Open() - otherwise the callback
		// never gets called.
		if (iInputStream) delete iInputStream;
		iInputStream = NULL; // In case the following NewL leaves
		TRAPD(err, iInputStream = CMdaAudioInputStream::NewL(*this));
		PanicIfError(err);
	#endif
	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();
		ShowMessage(_L("\nRecording stopped!"), EFalse);
		iBufferOK = ETrue;
		}		
	if (iOutputStatus!=ENotReady) 
		{
		iOutputStream->Stop();
		ShowMessage(_L("\nPlayback stopped!"), ETrue);
		}
	}


// ----------------------------------------------------------------------------
// CAudioStreamEngine::LoadAudioFileL()
//
// loads the audio data from a file into the buffer
// ----------------------------------------------------------------------------
void CAudioStreamEngine::LoadAudioFileL()
	{
	RFileReadStream audiofile;

	// open file
	TFileName fileName;
	fileName.Copy(iAudioFilePath);
	fileName.Append(iAudioFile);

	TInt err = audiofile.Open(iFs, fileName, EFileRead|EFileStream);
	iStreamBuffer->Des().FillZ(iFrameCount * iFrameSize);  // Empty the stream buffer
	if (err==KErrNone) 
		{
		// file opened ok, proceed reading
		if (iUseAMR)
			{
			// Read the AMR header (the first 6 bytes). We don't need to save/use the header,
			// since while playback we already know it's an AMR-NB encoded stream.
			TBuf8<KAMRHeaderLength> temp;
			audiofile.ReadL(temp, KAMRHeaderLength);
			}

		TUint idx=0;
		while (idx < iFrameCount)
			{
			TRAPD(fstatus, audiofile.ReadL(GetFrame(idx), iFrameSize));
			if (fstatus!=KErrNone)
				break;
			idx++;
			}
		iStreamStart=0;
		iStreamEnd=idx-1;
		ShowMessage(_L("Loading complete!"), ETrue);
		iBufferOK = ETrue;	
		}	
	else 
		{
		// failed to open file
		ShowMessage(_L("Error loading \naudio sample!"), ETrue); 
		iBufferOK = EFalse;
		}
	audiofile.Close();
	}


// ----------------------------------------------------------------------------
// CAudioStreamEngine::SaveAudioFileL()
//
// saves the audio data in the buffer into a file
// ----------------------------------------------------------------------------
void CAudioStreamEngine::SaveAudioFileL()
	{
	if (!iBufferOK)
	{
		// In case the encoding was changed between recording and trying to save the file
		ShowMessage(_L("Recorded buffer does not \nmatch current encoding."), ETrue);	
		ShowMessage(_L("\nPlease re-record and \ntry again."), EFalse);	
		return;
	}
	RFileWriteStream audiofile;

	// Check for free space for saving the sample
	TVolumeInfo volinfo;
	TInt err=iFs.Volume(volinfo,EDriveC);
	if ( volinfo.iFree<(iFrameCount*iFrameSize))
		{
		// Not enough free space on drive for saving, report and exit
		ShowMessage(_L("Cannot save file:\nnot enough space!"), ETrue);	
		return;
		}

	TFileName fileName;
	fileName.Copy(iAudioFilePath);
	fileName.Append(iAudioFile);
	err = audiofile.Replace(iFs, fileName, EFileWrite|EFileStream);
	if (err==KErrNone) 
		{
		if (iUseAMR)
			{
				// Write the six-byte AMR header, so that the file can be used by other
				// applications as well.
				for (int i = 0; i < KAMRHeaderLength; i++)
					audiofile.WriteUint8L(KAMRNBHeader[i]);
			}
			
		// File opened ok, proceed writing.
		// Write audio data directly from iStreamBuffer
		for (TUint idx=iStreamStart; idx<=iStreamEnd; idx++)//iFrameCount; idx++)
			{
			audiofile.WriteL(GetFrame(idx));
			}
		ShowMessage(_L("Saving complete!"), ETrue);	
		}	
	else 
		{
		// failed to open file
		ShowMessage(_L("Error saving \naudio sample!"), ETrue);	
		}
	audiofile.Close();
	}

// ----------------------------------------------------------------------------
// CAudioStreamEngine::SetEncodingL(TBool aAmr)
//
// If argument is ETrue, AMR-NB encoding will be used in audio input/output.

⌨️ 快捷键说明

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