środa, 10 października 2012

Dźwięki w aplikacji na Windows Phone?

Jeśli chcemy mieć dźwięk przy zwykłej aplikacji, która nie jest pisana w XNA (czyli wg marketu nie jest grą) możemy go zdobyć na kilka sposobów... ale i tak koniec końców najlepiej użyć frameworku XNA :D

No, może nie wprost :] Ale o tym za chwilę.
Generalnie zapewne pierwszym sposobem, z którego większość by skorzystała jest natywna kontrolka "MediaElement", która fakt faktem udostępnia możliwość odtwarzania filmów i dźwięków niejako z marszu. Ot wrzucamy do XAML, dodajemy źródło naszej "zawartości medialnej" i mamy słyszalną zawartość. Czyli w skrócie wystarczy zrobić tak:
<MediaElement Height="100" Width="100" Name="media" Source="sound.mp3" AutoPlay="True" />
Prawda, że pięknie i prosto? No właśnie, nie do końca. Bo o ile jest to bardzo łatwe, to nadaje się de facto jedynie do odtwarzania zawartości na aktualnej stronie - wszak kontrolka jest sztywno przypisana do Page i po zmianie aktywnej strony po prostu przestanie wytwarzać jakiekolwiek dźwięki (co można obchodzić zmiennymi globalnymi, ale takie podejście jest po prostu marnowaniem zasobów telefonu). Z drugiej strony w przypadku wrzucenia apki używającej MediaElement do samo wyzwalającego się materiału (np. po pacnięciu w guzik) na market możemy spotkać się z odrzuceniem podczas certyfikacji, które to wynika z guidelines i domyślnego działania tej kontrolki:
  • When the user is already playing music on the phone when the application is launched, the application must not pause, resume, or stop the active music in the phone
    If the application plays its own background music or adjusts background music volume, it must ask the user for consent to stop playing/adjust the background music (e.g. message dialog or settings menu). This prompt must occur each time the application launches, unless there is an opt-in setting provided to the user and the user has used this setting to opt-in.
Czyli generalnie MediaElement jest super jeśli chcemy odtwarzać muzykę tła na pojedynczej stronie (lub wyświetlić filmik). Oczywiście nie możemy wtedy zapomnieć, że jeśli użytkownik słucha jakiejś muzyki to musimy się go zapytać czy wyraża zgodę na puszczenie muzyki z naszej aplikacji oraz zapewnić konfigurację dla naszego muzycznego tła:
  • If an application plays background music, the application must provide the user with configurable settings for both the background music, and the background music volume.
 Pewnym rozsądnym rozwiązaniem jest użycie BackgroundAudioPlayer, który pozwala nie tylko na puszczanie muzyki w tle wewnątrz całej aplikacji, ale również dzięki agentom wewnątrz innych aplikacji naszego telefonu (czyli możemy stworzyć odtwarzacz muzyki). Klasa ta jest bardzo przydatna, bo nie dość, że pozwala nam na wspomniane odtwarzanie tła, to również umożliwia przewijanie piosenek i wybór miejsca, od którego chcemy utwór odtworzyć (pod tym względem jest to nawet lepsze rozwiązanie od MediaPlayera z XNA). Rozwiązanie to ma jednak tą małą wadę, że plik z dźwiękiem albo musi być dostarczony z IsolatedStorage albo z zewnętrznego adresu URI (poradnik od MS dotyczący BackgroundAudioPlayer).

Jednak jeśli chcemy mieć dźwięki efektów, czyli np. odgłos gdaczącej kury po kliknięciu na guzik, to już tak MediaElement jak i BackgroundAudioPlayer się nie nadaje (bo m.in. wstrzymuje obecnie odgrywany dźwięk). Natomiast do tego celu nadaje się coś innego - klasa SoundEffect pochodząca z XNA :D
            using (var stream = TitleContainer.OpenStream("sound.wav"))
            {
                var effect = SoundEffect.FromStream(stream);
                FrameworkDispatcher.Update();
                effect.Play();
            }
Aż chciałoby się wykorzystać SoundEffect do odtwarzania muzyki w tle (zwłaszcza, że po stworzeniu instancji efektu możemy bez trudu odtwarzanie muzyki zapętlić)... niestety guideline jest bardzo stanowczy pod tym względem:
  • The SoundEffect class must not be used to play a continuous background music track in an application.
Ach Ci źli ludzie z Microsoftu! Na szczęście XNA daje nam dużo, dużo więcej możliwości, z których chyba najprzyjemniejszą jest połączenie klas Song i MediaPlayer:
            Song song = Song.FromUri("Nasze audio", new Uri("sound.mp3", UriKind.Relative));
            if (MediaPlayer.GameHasControl)
            {
                MediaPlayer.Play(song);
            }
Klasa ta jak widać nie tylko z gracją rozwiązuje problem nakładania się naszego muzycznego tła na muzykę odtwarzaną przez użytkownika dzięki polu GameHasControl i pozwala na odtwarzanie pojedynczych piosenek (Song), ale również umożliwia tworzenie ich całych kolekcji (SongCollection) oraz łatwe nawigowanie pomiędzy nimi. Tak więc myśląc o dźwięku w aplikacjach na Windows Phone bazujących na silverlight i tak prędzej czy później wykorzystamy biblioteki XNA, bo po prostu dają one ogromną swobodę i wbrew pozorom są bardzo łatwe w wykorzystaniu.

Brak komentarzy:

Publikowanie komentarza