symba (779893), страница 46
Текст из файла (страница 46)
For example, if you save to a filename ‘C:\temp.wav’, youget a WAV format file without having to give any further parameters. Thatsaves you having to try to select the format via the controller and worksin most situations.8.9 Set Controller Thread Priorities Before Playingor RecordingEach controller runs in its own thread. For largely historical reasons,the thread priority is that of a normal thread. Experience suggests thatin many, if not most, scenarios this is too low. Even though most ofthe processing time is spent at the lower codec level, there are timeconstraints at the controller level where, once asked to handle data, itmust do so in a reasonably short time.If the player controller layer runs too slowly, in the best-case scenario,the output device may be ‘starved’ of data and the end user will perceiveunpleasant gaps in the audio; in the worst case, a KErrUnderflow errorwill occur and play will stop.
The effect will depend on the particulardevice.The opposite problem can occur for recording – too much data isread at the device and is not pushed into the file fast enough. Againthe effect depends on the device, but recorded sound may be lost ora KErrOverflow error may be generated. Some controllers carry outsome of the codec operation too; potentially this just makes thingsworse.The solution is to raise the thread priority of the controllers. To acertain extent this requires balance and depends on what else is goingon both inside the application at hand and in the wider system.
Set thecontroller priority too high and something else will be ‘starved’. Set it toolow and the controller won’t run fast enough.There are basically two approaches:• permanently set the controller priority• set the priority just before playing or recording and reset it after.218BEST PRACTICEMost of the time this does not make any difference, although thesecond option is perhaps better if your application tends to open in onestage and play in another (an application where the file is opened andthen the user has to call play, for example) and supports querying ofmetadata and so on.Note: this is partly about being a good smartphone citizen, but alsoabout ensuring that end users see your application as well-behaved.8.10Recognize that Behavior Varies when Several ClientsAre ActiveThis is one of those things to watch if you only have one test device: ifyour application tries to use several multimedia client objects at the sametime, the effect varies from one device to another.
To a certain extent,this is no different from memory usage. Multimedia implementationsoften have special memory and other resources, and your program canrun out of them on one device and work on another, just like withnormal memory. However, for audio in particular, things are morecomplex.Essentially, a request to play is merely that – a request.
Even if yourprogram is running in the foreground, it is not its choice as to what runs.Whether several audio components are played is up to the ‘audio policy’.The rule sets that constitute this policy vary from one smartphone modelto another. If you request things to happen, don’t be totally surprised ifthey are stopped by the audio system – your application needs to handlethis. It may decide to ignore the rejection, because the sounds are notthat important or it may decide to reflect this to the end user. This usuallydepends on the type of application: for example, key clicks can usuallybe skipped but a music player should show ‘stopped’ if the clip is stoppedby the underlying system.An additional issue is the underlying hardware – this is reflected partlyin the policy, but not totally. If more than one client plays simultaneouslythrough the same device, then this requires use of an audio mixer.
Audiomixing is effectively a trade-off between quality and performance andpower usage – on some devices, the resultant mixed audio will soundbetter than on others.If you want to play several things at once – say background musiccoupled with key clicks – consider making this optional for the user. Thequality of the mixed effect on some devices may be good, in others lessso. End users may prefer to run the application without the backgroundmusic but with other sound effects – give them the option.UNDERSTAND THAT THE SYSTEM IS BASED ON PLUG-INS2198.11 Understand that the System is Based on Plug-insA commonly asked question is ‘what codecs and formats are supportedby Symbian OS?’ There is no easy answer to this: at heart, all the keymultimedia libraries are based on plug-ins – there are frameworks thatload plug-ins as appropriate.
The answer to what is supported dependsalmost totally on what plug-ins are provided, and thus is a changing storysince they can be added to by downloads, etc.In fact, there is no single story on an individual device either becauseof platform security rules (see Section 2.2). The usable plug-ins may varyfrom one application to another – an application cannot directly exploitplug-ins with fewer capabilities than it has.The conclusion from this is that you should not write software that hasa fixed notion of what features are available. A more subtle conclusion isthat you should be very careful about caching the list of available plug-ins(it might change) or creating it globally – what is valid for one applicationmight not be the correct list for another.So what should you do? In general it is better to avoid code that tries tosecond guess what ICL, MMF etc.
does – just try it instead and deal withthe failure! For example, assume you have a collection of images andwant to display them. Rather than trying to write code with this algorithm:if (we support the file)open and display using ICLelsedisplay default imageYou should try something along the lines of this pseudo-code:error = Open file in ICLif (!error)error = convert file in ICLif (!error)display ICL outputelsedisplay default imageOK, the real code will be more complex than this, as the conversionstage, at least, is asynchronous. However, it does show the underlyingapproach.
It is quite normal in applications to show a default image, e.g.a question mark, should there be an error. This pseudo-code suggestsshowing the same default image in any case of error. This is probablythe best thing to do – most users won’t be interested in the distinction220BEST PRACTICEbetween errors. You could possibly distinguish between ‘transient’ errors,such as out-of-memory, where you might sometimes be able to decode animage (especially a big image) depending on which other applications arerunning.
However, even that is probably best just treated as yet anothererror.So much for images. For audio and video, you will probably wantto distinguish between a failure to open and a failure to play, givingappropriate error messages. What you do depends on your applicationdomain, what the sound is and the interface. For example, if you’reusing ‘beeps’ to signal that something has finished, you can probably justignore problems – an end user would generally be confused by an errorreport.
However, if your application is a music player that is supposedto be playing a music clip, then you need to say that something wentwrong. Quite what you say should depend on how the error is passed toyou – KErrNotSupported or KErrCorrupt during the opening andinitialization step usually says there is no suitable plug-in or that the fileis not really an audio clip; during play, they suggest the file is corrupt andthe plug-ins could not recover.For recording, there is a temptation to want to list as options only thoseformats available.
With some inside knowledge this is possible:• You may be able to use ECOM to search the actual formats and this isthe neatest solution. However, even then it may not be portable – justbecause the frameworks currently use controllers and formats doesnot mean they always will – a future version could easily start toexploit a different type of plug-in. This has changed in the past andwill almost certainly change at some time in the future.• Let the user select from a known list and handle the failure. This isguaranteed to be portable but at the cost of reduced usability, and itis not recommended.• Before options are presented, quickly try to see what can be set up.There is no need to actually record – the requirement is to see whatsuffixes can be opened and then, if required, the supported rawformats can be listed.
This is both portable and usable but it incurs aperformance penalty over querying the supported formats via ECOM,since the relevant controllers each have to be found and loaded bythe framework and several files created and deleted.If none of the above options are suitable, any implementation shouldsupport PCM16 WAV and IMA ADPCM WAV for both play and record.However, they do not give the best tradeoff between compression andquality – PCM gives high quality and no compression, whereas ADPCMgives average compression and low quality. Having said that, they aresupported by virtually any audio platform, one way or another, and areUSE RFile AND TMMSource INSTEAD OF PASSING A FILE NAME221thus also safe for sending emails and similar communication.
OtherwiseAMR is commonly, if not universally, supported and is a good format touse for other audio.8.12 Use RFile and TMMSource Instead of Passinga File NameWhen using CMdaAudioPlayerUtility, there are a number of waysof stating which file to play. These include:static CMdaAudioPlayerUtility* NewFilePlayerL(const TDesC& aFileName,MMdaAudioPlayerCallback& aCallback,TInt aPriority = EMdaPriorityNormal,TMdaPriorityPreference aPref = EMdaPriorityPreferenceTimeAndQuality,CMdaServer* aServer = NULL);or the following:static CMdaAudioPlayerUtility* NewL(MMdaAudioPlayerCallback& aCallback,TInt aPriority = EMdaPriorityNormal,TMdaPriorityPreference aPref = EMdaPriorityPreferenceTimeAndQuality);Followed by one of:IMPORT_C void OpenFileL(const TDesC& aFileName);IMPORT_C void OpenFileL(const RFile& aFile);IMPORT_C void OpenFileL(const TMMSource& aSource);The question is: which sequence to use?The reason for the large number of similar calls is historical.