This tutorial describes how to use Audio Input Streaming.
The purpose of this tutorial is to show you how to open, read and then close an audio input stream.
Required Background
The Audio Input Streaming Overview provides an introduction to Audio Input Streaming.
Introduction
The audio input stream interface class, CMdaAudioInputStream, enables MMF client applications to:
stream audio data from the low level audio controller (which has collected it from a hardware device, such as a microphone) to specified buffers (record audio).
specify the priority of the audio stream relative to other clients trying to use the same audio hardware
set the sample rate and the number of channels to use for recording.
change the gain and channel balance of the input stream.
The low level audio controller stores the audio data in buffers. CMdaAudioInputStream reads these buffers incrementally and does not have to wait until capture is complete.
Typically, using an audio input stream involves the following steps as shown in the sequence diagram below:
The following tasks will be covered in this tutorial:
Basic Procedure to Construct an Audio Input Stream
The high level step to construct an audio input stream is shown here:
The client application creates an audio input stream object using the static function CMdaAudioInputStream::NewL(). The input stream class provides two versions of the constructor: one with the default priority and preferences, and another with specified priority and preferences. The client application must also implement the observer class MMdaAudioInputStreamCallback to notify it about audio input streaming progress.
The following code constructs an audio input stream:
CMdaAudioInputStream* aInputStream; aInputStream = CMdaAudioInputStream::NewL(aCallback, EMdaPriorityNormal, EMdaPriorityPreferenceTimeAndQuality);
where, aCallback is an MMdaAudioInputStreamCallback object.
Basic Procedure to Open an Audio Input Stream
The high level steps to open an audio input stream are shown here:
To open an input stream, use the Open() member function, which provides a pointer to the TMdaPackage object with the required audio settings. You can also open the stream without the audio settings. For example:
aInputStream->Open(NULL);
Once the stream is open, a MMdaAudioInputStreamCallback::MaiscOpenComplete() is issued to indicate that the stream is ready for use.
void CIOStreamAudio::MaiscOpenComplete(TInt aError) { ASSERT(iState==EStateOpeningInput); if (aError!=KErrNone) { Complete(aError); } else { iMainBuffer.Zero(); iState = EStateReading; ReadNextBlock(KNullDesC8); // kick off a new read - KNullDesC8 for first buffer } }
Basic Procedure to Get and Set Stream Properties
The high level steps to get and set stream properties are shown here:
To set the sampling rate and number of audio channels, use the SetAudioPropertiesL() member function. You can do this only if the stream is open and if data is not being streamed. Values must be specified as enum values. For example, TMdaAudioDataSettings::ESampleRate8000Hz and not 8000 (Hz). The following code sets the sampling rate to 8000Hz and audio channel to mono:
aInputStream->SetAudioPropertiesL(TMdaAudioDataSettings::ESampleRate8000Hz,TMdaAudioDataSettings::EChannelsMono));
The Gain() and GetBalanceL() member functions let you determine the current gain and balance settings.
The SetGain() and SetBalanceL() member functions let you set the gain and balance respectively. You can use them while the stream is open, with the new settings taking immediate effect.
Basic Procedure to Read an Audio Input Stream
The high level steps to read an audio input stream are shown here:
To record the audio stream, use the ReadL() member function, specifying the buffer to use. The first ReadL() after a successful Open(), starts audio recording. Once the buffer is successfully recorded, a pointer to it is returned by MMdaAudioInputStreamCallback::MaiscBufferCopied() callback.
void CIOStreamAudio::MaiscBufferCopied(TInt aError, const TDesC8& aBuffer) { ASSERT(iState==EStateReading); if (aError!=KErrNone) { if (aError!=KErrAbort) // aborts happen on Stop as buffers are recovered, need to ignore { Complete(aError); } } else { ReadNextBlock(aBuffer); } }
The following code reads the next audio block into the buffer in an array of descriptors:
void CIOStreamAudio::ReadNextBlock(const TDesC8& aBuffer) { ASSERT(iState==EStateReading); // buffer will be tail of iMainBuffer. Shift latter's length and get the next bit TInt lengthRecorded = iMainBuffer.Length()+aBuffer.Length(); iMainBuffer.SetLength(lengthRecorded); iBufferPtr.Set(const_cast<TUint8*>(iMainBuffer.Ptr())+lengthRecorded, 0, iMainBuffer.MaxLength()-lengthRecorded); TRAPD(error, iInputStream->ReadL(iBufferPtr)); if (error!=KErrNone) { Complete(error); } }
Basic Procedure to Stop an Audio Input Stream
The high level steps to stop an audio input stream are shown here:
To stop recording the audio stream, use the Stop() member function. Two callbacks are issued after a Stop().
An MMdaAudioInputStreamCallback::MaiscBufferCopied() pointing to a buffer that contains the last of the recorded audio data (and an aError value of KErrAbort).
An MMdaAudioInputStreamCallback::MaiscRecordComplete(), indicating successful closure of the audio stream.
void CIOStreamAudio::MaiscRecordComplete(TInt aError) { ASSERT(iState==EStateReading && aError!=KErrNone); Complete(aError); }