Wiley.Games.on.Symbian.OS.A.Handbook.for.Mobile.Development.Apr.2008 (779888), страница 32
Текст из файла (страница 32)
This behavior is again audiopolicy dependent, so it will be different on different devices. The callbackmight not be called depending on what sort of audio interrupts playingof the clip.void CAudioDemo::MarncResourceAvailable(TUid aNotificationEventId,const TDesC8& aNotificationData){if ((aNotificationEventId == KMMFEventCategoryAudioResourceAvailable)&& (aNotificationData.Size() >= sizeof(TInt64))){// get the position from the notification dataTPckgBuf<TInt64> position;position.Copy(aNotificationData);// move the current position in the clipiPlayerUtil->SetPosition(position());// resume playingiPlayerUtil->Play();}}Unfortunately, Symbian OS does not support mixing of audio fromthe same application.
However, audio output from different clients mightbe mixed under certain circumstances on some devices, if the audiopolicy allows.2 The MMF does not have the concept of ‘audio channels,’so simultaneous playing of different audio clips is not supported. Audiopriorities and audio policies also have strict requirements from the systemaudio engine that complicates things.2A notable exception to this rule is Motorola’s MOTORIZR Z8 smartphone, whichhas an 8-channel DSP mixer that will mix multiple streams from any process/threadindiscriminately. This is more of a feature of the hardware and the audio policy server onthis device than Symbian OS, so game developers should not depend on this feature in theirgame designs, for the time being, for portability.SOUND EFFECTS133Of course, in a modern game engine, it is not sufficient to play onlyone sound effect at a time.
When background music is also considered,this limitation becomes even more severe. Symbian is aware of these limitations and is working to address them in a future release of Symbian OS.In the meanwhile, there are still some other options. A game developercan consider two different alternative designs for implementing a multipleeffect engine with only one output channel.One option is to implement an interrupting model where the audioengine will allow the first sound effect to play and if a second effectneeds to play prior to the first one’s ending, the first effect is interrupted(stopped) and the second one starts playing. The effects can have gameengine-defined priorities, so the effects with higher priorities will preemptlower priority ones, but not be interrupted by them. Developers canimplement such a design by using audio clip player APIs because theseAPIs are asynchronous and support notifications.To store multiple effects in memory to use in such a design, multipleCMdaAudioPlayerUtility objects can be instantiated, and differentaudio clips can be loaded.
The game audio engine will decide which oneto play at run time. The main advantage will be having pre-initializedobjects ready to be played, which will reduce latency when played inreaction to game events. The drawback of such a method is that it wastesprecious MMF server and system resources (one thread will be started andsome extra memory will be allocated for each player). To minimize thememory usage, UseSharedHeap() can be used to share the resourcesamong multiple clients.Another way is to load up the effects from files in descriptors and usethe OpenDesL() method to prime them prior to playing. Because theeffects will be preloaded in memory, the file load lag will not occur. Stillthe requirement to initialize each effect prior to playing will still introducesome lag that might not be acceptable for some types of action games.Calling SetThreadPriority() with a higher priority value, whichcan increase the priority of the sub thread MMF creates for processing theclient requests, can minimize this lag.A third alternative is to create audio clips that contain multiple effects.An accompanying data file contains the time-based indexes and durationsof individual effects in the clip.
The engine loads the clip file once but,prior to playing an effect, it will calculate a play window correspondingto the effect’s data in the file using the time and duration data from theindex file. This will cause Play() to play only the portion of the file thatcontains the desired effect.A much better option for a multi-effect audio engine is to implementa software mixer and mix the sounds in real time prior to playing themon the only available channel. However, this requires more processingpower and a continuous streaming API.
Section 4.3.3 explains this optionin more detail.134ADDING AUDIO TO GAMES ON SYMBIAN OS4.3.2 Audio Tone PlayerFor certain types of simple games, such as a card game or a Tetris clone,all the game developer wants is to provide some kind of audio feedback tothe user. Therefore, realistic sound effects or full-blown audio tracks mightnot be required for these types of games. Sometimes, the game developermight not have the resources to spend on specialized audio content.In these cases, just creating the simplest of effects using the synthesizercan be the best option. Granted, it does not sound great (think offirst generation ringtones), but will do the job of creating the requiredfeedback.Symbian OS supports synthesized sound through the CMdaAudioToneUtility class, defined in MdaAudioTonePlayer.h.
The usageof this class is very similar to CMdaAudioPlayerUtility. This classsupports the playing of single or dual tones. The observer mixin class toimplement is MMdaAudioToneObserver.class CAudioDemo : public CActive , MMdaAudioToneObserver{public:virtual void MatoPrepareComplete(TInt aError);virtual void MatoPlayComplete(TInt aError);private:CMdaAudioToneUtility* iToneUtil;};Construction is simple and requires no setup:void CAudioDemo::ConstructL(){iToneUtil = CMdaAudioToneUtility::NewL(*this);}Playing a tone requires a prepare function to be called first. For asingle tone, the PrepareToPlayTone() function requires a frequencyand duration.
For a dual tone (which is comprised of two sine waves ofdifferent frequencies), the same parameters, plus an extra frequency, arerequired for the PrepareToPlayDualTone() function.void CAudioDemo::PlayTone(){// for single tone of frequency 640iToneUtil->PrepareToPlayTone(640,TTimeIntervalMicroSeconds(1000000));// for dual tones of frequencies 697 and 1209iToneUtil->PrepareToPlayDualTone(697, 1209,TTimeIntervalMicroSeconds(1000000));...}SOUND EFFECTS135The prepare functions are asynchronous as well, eventually callingMatoPrepareComplete(). After the callback is complete, calling thePlay() method plays the tone.
When the tone playing finishes, the MMFwill call MatoPlayComplete() to signal the end of tone playing. Theerror conditions described for audio clip playing apply to tone playing aswell.Although clip and tone playing use different classes, they share acommon system resource, so the multi-channel limitation still applies. Itis not possible to play a clip and a tone at the same time from the sameapplication, except when running code on Motorola’s MOTORIZR Z8smartphone, which has an 8-channel DSP mixer that will mix multiplestreams from any process/thread. Since this is a feature of that particularphone hardware, game developers should not depend on the availabilityof this feature on other hardware.4.3.3 Audio Output Streaming and Creating Multi-channelSound EffectsThe way to accomplish reduced latency and multi-channel audio supportfor a complex audio engine is by implementing a software mixer runningin a dedicated high-priority thread.
Audio streaming APIs are the mostsuitable APIs for this purpose.Audio streaming APIs interface directly with the hardware through theDevSound interface, bypassing the MMF. Audio data will be processeddirectly in the applications thread when the audio streaming API orDevSound API (see section 4.3.4) is used for streaming. This is becausethe sub-threads created internally by the MMF for other audio operationswill not be created for these cases. Therefore, games requiring highperformance must create separate threads for streaming to ensure smoothaudio output.Symbian OS supports audio output streaming through the CMdaAudioOutputStream class, defined in MdaAudioOutputStream.h.This API builds upon the same MMF architecture as other MMF APIsbut has extra methods to support streaming.