📄 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 <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 + -