Audio Clip Recording

Recording of audio clips is achieved using class CMdaAudioRecorder-Utility which is defined in MdaAudioSampleEditor.h. You can use this class to record audio in any format for which a suitable controller plug-in exists. The class contains a superset of the functionality of CMdaAudioPlayerUtility and so is often used for playback of clips. Note however that the class does not contain a Pause() method, unlike the player utility.

To perform audio recording, you need the UserEnvironment capability. High audio priorities are policed in the same way as with the player utility, using the MultimediaDD capability.

To use the audio recorder utility, you must derive from mixin class MMdaObjectStateChangeObserver which defines a single method:

class MMdaObjectStateChangeObserver {

public:

virtual void MoscoStateChangeEvent(CBase* aObject,

Tint aPreviousState, Tint aCurrentState, Tint aErrorCode) = 0;

MoscoStateChangeEvent is called every time the utility changes state; the aPreviousState and aCurrentState parameters have values corresponding to CMdaAudioClipUtility::TState:

enum TState {

ENotReady = 0,

EOpen,

EPlaying,

ERecording };

When using the utility for audio playback, the usage is very similar to the player utility so it is not discussed again here. One point worth mentioning however is that you receive a callback to MoscoStateChange event following a call to PlayL() indicating that playback has started; no equivalent callback exists when using the player utility.

To perform audio recording, a controller is opened by the recorder utility. You can record to a descriptor or to a file; it is usual to record to a file due to the memory requirements of using a descriptor.

When you open the recorder utility, you must indicate which controller to use for the recording. You can do this either by specifying explicitly the UID of the controller to use or by letting the controller framework select the controller automatically based on the extension of the filename given. For example, if you open a file with the extension .wav, the Symbian audio controller is selected automatically.

Selecting a controller by UID

As stated earlier, all controller plug-ins are ECOM plug-ins. Hence we can use ECOM to query the controllers present on a phone and the formats that they support. Symbian provides some helper classes to make this job easier:

• CMMFControllerlmplementationlnformation

• CMMFFormatlmplementationlnformation

• CMMFControllerPluginSelectionParameters

• CMMFFormatSelectionParameters.

You can use these classes to query the controllers present on a phone and find out what media formats they support. They are all defined in the header file mmf\common\mmfcontrollerpluginresolver.h.

The mmfcontrollerframework.lib library that you need to link against when using these classes is not present in the S60 3rd Edition SDK from Nokia. You must download an SDK extension plug-in separately before you can use the classes discussed here.

First, create an instance of CMMFControllerPluginSelection-Parameters and indicate what sort of controller you are interested in. Here, we specify that we are only interested in controllers that support audio:

CMMFControllerPluginSelectionParameters* controllerSelection = CMMFControllerPluginSelectionParameters::NewLC();

RArray<TUid> medialds; CleanupClosePushL(medialds);

medialds.AppendL(KUidMediaTypeAudio); controllerSelection->SetMediaIdsL(mediaIds,

CMMFPluginSelectionParameters::EAllowOnlySuppliedMediaIds);

If we wanted to find out about video controllers, we could have specified KUidMediaTypeVideo instead of KUidMediaTypeAudio. In this example, we have specified that we are interested in controllers that support only audio, by giving the value EAllowOnlySuppliedMediaIds. Other options here are:

• ENoMediaIdMatch - do not perform matching on media ID

• EAllowOtherMediaIds - allow controllers that support the specified media ID in addition to others. This would show controllers supporting audio and video.

The next step is to specify the media formats we are interested in:

CMMFFormatSelectionParameters* formatSelect = CMMFFormatSelectionParameters::NewLC();

controllerSelection-> SetRequiredRecordFormatSupportL(*formatSelect);

We could have chosen a specific format at this point by calling SetMatchToMimeTypeL() and giving the MIME type of the audio format we are interested in. In this example, we list all controllers that support audio recording.

The final step is to retrieve the list of controllers that meet the criteria we have specified.

RMMFControllerImplInfoArray iControllers;

controllerSelection->ListImplementationsL(iControllers);

The array iControllers now contains a list of controllers that support audio recording, each one represented by an instance of cmmf-ControllerImplementationInformation.

Each controller can support any number of audio playback or recording formats. The list of formats supported can be accessed using the Record-Formats() and PlayFormats() methods. Each format is represented by an instance of CMMFFormatImplementationInformation.

Recording the sound

Once we have chosen the format we wish to record in, the controller can be opened by the utility. If we want to let the MMF choose a controller and format based on the extension of the filename we give, simply pass in this filename.

iRecorder->OpenFileL(fileName);

If we are specifying a format to record in by controller and format UID, we pass these in to the OpenFileL() method.

void CAudioRecordEngine::OpenL(const TDesC& aRecordFileName, TRecordFormatParameters aParameters)

// in case it has previously been used:

iRecorder->Close();

iState = ENotReady;

// Append a suitable extension to the filename we are given, const CDesC8Array& extensions =

aParameters.iFormat->SupportedFileExtensions();

if (extensions.Count()>0)

// just use the first one

InitializeFileNameL(aRecordFileName, extensions[0]); }

iRecorder->OpenFileL(iFileName, aParameters.iController->Uid(), // controller UID

KNullUid, // play controller UID (unused here)

aParameters.iFormat->Uid() // record format UID );

In this example, we are appending a suitable file extension to the filename given. This step is not necessary but adds completeness.

As with the player utility, we expect a callback after we have called OpenFileL().

void CAudioRecordEngine::MoscoStateChangeEvent(CBase* /*aObject*/,

Tint /*aPreviousState*/, Tint aCurrentState, Tint aErrorCode)

switch (iState)

case ENotReady:

// The OpenFileL call is complete if (aErrorCode == KErrNone)

iState = ERecordReady; // notify the UI

iObserver.MareoStateChanged(); }

else

// notify the Ui iObserver.MareoError(aErrorCode);

break;

The aObject parameter to this method indicates which object the state change relates to; in this example, since we only use a single recorder utility, we know that aObject == iRecorder.

If we want to set the parameters for the recording, now is the time to do it. The recorder utilities provides a number of methods allowing you to change the number of channels, bitrate and other settings. You should query which values are supported before setting them, for example by using the GetSupportedBitRatesL() method before calling SetDestinationBitRateL().

Now the recorder is ready to begin recording.

void CAudioRecordEngine::RecordL()

__ASSERT_ALWAYS(iState == ERecordReady,

Panic(EAudioRecorderEngineWrongState));

iRecorder->RecordL();

We receive another callback to MoscoStateChangeEvent() when the recording starts successfully; at this point, we move the engine into state ERecording. The recording continues until we stop it or an error occurs, such as if we run out of disk space or the descriptor we are recording into becomes full. If we call Stop(), we do not receive a callback notifying us of the state change.

Playing back the recording

The recorder utility is capable of playing audio clips as well as recording them. Once the clip is recorded, we can play it back. This can be done simply by making a call to PlayL() after the call to Stop(); however this requires that the same controller supports recording and playback of the format in use, since only one controller is used at a time. While this is true for the Symbian audio controller, it is often not the case for controllers that record in compressed formats.

So, to play the clip reliably, we need to close and reopen the controller. This gives the MMF the chance to load a new controller if required. In this example, we do it immediately after the recording finishes.

void CAudioRecordEngine::Stop()

__ASSERT_ALWAYS(iState ! = ENotReady,

Panic(EAudioRecorderEngineWrongState));

iRecorder->Stop();

switch (iState) {

case ERecording:

OpenControllerForPlay();

break;

iObserver.MareoStateChanged();

void CAudioRecordEngine::OpenControllerForPlay()

iRecorder->Close();

TRAPD(err, iRecorder->OpenFileL(iFileName));

iState = EPlayReady;

// don't notify our observer yet - wait until we get another // state change event notifying us that the player is now

iState = ENotReady;

iObserver.MareoError(err); }

We then receive a callback to MoscoStateChangeEvent(), indicating that the utility is ready to begin playback.

0 0

Post a comment

  • Receive news updates via email from this site