Главная » Программирование игр под Android » Потоковая музыка – РАЗРАБОТКА ИГР ДЛЯ ОС ANDROID

0

Короткие звуковые эффекты легко помещаются в ограниченной области памяти (куче), которую приложению Android выделяет операционная система. Это не касается более объемных музыкальных файлов. Поэтому нам необходимо осуществлять потоковую передачу музыки на устройство воспроизведение (то есть читать в единицу времени небольшой фрагмент файла, декодировать его в РСМ-данные и передавать его аудиочипу).

Звучит пугающе, правда? К счастью, у нас есть класс Medi a PIayer, делающий за нас всю работу. Все, что нам нужно, – указать ему на аудиофайл и дать команду его воспроизведения. Инициализация класса Medi aPl ауег выполняется проще некуда:

Далее нам необходимо сообщить Medi aPl ауег, какой файл воспроизводить. Это делается (как и в случае со звуковым эффектом) с помощью AssetFi1eOescri ptor:

Однако здесь немного больше кода, чем в случае с SoundPool. Метод Medi aPl ауег. setDataSourceO не принимает AssetDescri ptor напрямую – ему нужен FileDescriptor, получаемый через AssetFileDescriptor.getFileDescriptor. Кроме того, нам необходимо определить сдвиг и длительность воспроизводимого файла. Почему сдвиг? Дело в том, что все ресурсы на самом деле хранятся в одном файле. Чтобы Medi aPl ауег получил позицию начала нашего файла, необходимо предоставить ему величину сдвига внутри файла ресурсы.

Перед началом воспроизведения музыкального файла придется вызвать еще один метод, подготавливающий Medi aPlауег к  воспроизведению:

Это действие на самом деле открывает файл и проверяет, можно ли его читать и воспроизводить экземпляром Medi aPl ауег. Теперь мы можем воспроизводить, приостанавливать, останавливать, зацикливать звуковой файл и менять громкость.

Для начала воспроизведения вызывается следующий метод:

Обратите внимание: его можно вызывать только после успешного вызова MediaPlауег. prepare – иначе возникнет ошибка выполнения.

Поставить воспроизведение на паузу можно с помощью метода pause:

Вызов этого метода также легитимен лишь после успешной подготовки класса Medi aPlауег и начала воспроизведения. Для возобновления воспроизведения мы просто опять вызываем метод Medi аР1ауег. start  без какой-либо предварительной подготовки.

Для остановки воспроизведения используется метод stop:

Обратите внимание – чтобы запустить остановленный Medi aPlауег, необходимо сначала вновь вызвать Medi aPlауег. prepare .

Мы можем заставить Medi aPlауег циклически воспроизводить файл, воспользовавшись следующим методом:

Для регулировки громкости воспроизведения применяется такой метод:

Громкость устанавливается отдельно для левого и правого каналов. В документации не указываются диапазоны для этих значений, но экспериментально было установлено, что они должны помещаться между 0 и 1.

Наконец, нам необходимо знать, закончилось ли воспроизведение. Это можно сделать двумя способами. Можно зарегистрировать OnCompletionLi stener для Medi а PIауег, чтобы он вызывался при окончании воспроизведения файла:

Другой метод – получение состояния Medi aPlауег с помощью еще одного метода:

Понятно, что при установке MediaPlауег в режим циклического воспроизведения ни один из этих способов не сообщит, что MediaPlауег остановил воспроизведение.

Не забудьте – после окончания работы с экземпляром MediaPlауег нужно освободить занятые им ресурсы. Делается это так:

Как уже говорилось, освобождать ресурсы при завершении работы с объектом является хорошей практикой.

Если мы не установили Medi а PIауег в режим циклического воспроизведения, можем перезапустить его вызовом методов MediaPlауег. prepareO и Medi aPl ауег. startO.

Большинство этих методов вызываются асинхронно. Это значит, что даже если вы вызвали Medi aPl ауег. stop, значение MediaPlayer.isPlayingO может еще некоторое время оставаться равным true. Обычно это не повод для беспокойства – в большинстве игр мы устанавливаем Medi а PIауег на воспроизведение по циклу и останавливаем его по мере необходимости (например, при переходе на другой экран, которому соответствует другая музыка).

Напишем небольшую активность, в которой будем циклически воспроизводить звуковой файл из каталога assets/. Этот звуковой эффект будет приостанавливаться и возобновляться в соответствии с жизненным циклом активности – при ее постановке на паузу приостановится и музыка, при продолжении соответствующим образом музыка продолжится с места остановки. Реализация этой функциональности показана в листинге 4.10.

Листинг 4.10. MediaPlayerTest.Java; воспроизведение звуковых потоков package com.bad.ogic.androidgames;

Основы Android API

Мы храним ссылку на MediaPlауег в виде члена нашей активности. В методе OnCreateO мы просто создаем TextView для вывода сообщений об ошибках, как всегда.

Перед тем как пользоваться Medi аРП ауег, необходимо удостовериться, что кнопки управления громкостью привязаны к музыкальному потоку. После этого мы инициализируем объект Medi а PI ауег и получаем дескриптор AssetFi 1 eDescri ptor для файла musi с. ogg (находящегося в каталоге assets/) из AssetManager, а также устанавливаем его в качестве источника данных для Medi aPl ауег. Все, что остается сделать после этого, – подготовить Medi a Player к воспроизведению и установить для него режим циклического воспроизведения. Если что-то пойдет не так, член Medi aPl ауег устанавливается в nul 1, чтобы позже мы могли определить, успешной ли была загрузка. Кроме того, мы выводим сообщения об ошибках в TextView.

В методе onResumeO мы стартуем Medi aPl ауег (если его создание совершилось успешно). OnResumeO – прекрасное для этого место, поскольку он вызывается как после onCreate, так и после onPause. В первом случае мы начинаем воспроизведение впервые, во втором – возобновляем поставленный на паузе Medi aPl ауег.

Метод onPauseC) приостанавливает воспроизведение Medi aPl ауег. Если активность предназначена к уничтожению, мы останавливаем Medi а PI ауег и освобождаем связанные с ним ресурсы.

При тестировании различных операций проверьте также его реакцию на приостановку и возобновление активности, заблокировав экран или временно переключившись на Ноте (Стартовый экран). При возобновлении Medi aPlауег продолжит воспроизведение с того места, на котором он остановился в прошлый раз.

При работе с потоковым звуком есть несколько тонкостей.

Методы Medi aPl ауег. start , Medi aPl ауег. pause nMediaPlayer.resumeO могут вызываться только в определенных ситуациях. Никогда не пытайтесь вызывать их, не подготовив предварительно Medi aPl ауег. Вызывайте Medi a Player, start  только после подготовки Medi a Player или при возобновлении воспроизведения после вызова метода Medi aPlауег .pause.

Экземпляры Medi aPlауег довольно тяжеловесны. Если их много, они могут порядочно загрузить систему. Всегда необходимо стараться использовать только один экземпляр этого объекта для воспроизведения. Звуковые эффекты лучше реализовывать с помощью класса SoundPool.

Не забывайте связывать кнопки управления громкостью с музыкальным потоком, иначе ваши игроки не смогут управлять уровнем звука.

Наша глава почти закончена, но осталась еще одна большая тема – 20-графика.

Источник: Mario Zechner / Марио Цехнер, «Программирование игр под Android», пер. Егор Сидорович, Евгений Зазноба, Издательство «Питер»

По теме:

  • Комментарии