- Класс SoundPool
- Конструктор класса SoundPool
- Методы
- Пример
- SoundPool.Builder (API 21)
- Воспроизведение звуковых эффектов в Android с помощью SoundPool
- View more Tutorials:
- 1- SoundPool & AudioManager
- 2- Пример с SoundPool
- View more Tutorials:
- Полный список
- Параметры метода play
- Приоритет
- Пауза
- Меняем уже играющий звук
- Выгрузка
Класс SoundPool
Основное отличие класса SoundPool от класса MediaPlayer — поддержка одновременного проигрывания нескольких аудиопотоков, что широко используется в играх.
Обычно SoundPool используют для проигрывания маленьких аудиоклипов. SoundPool может играть несколько звуков одновременно. Звуки также можно повторять (зациклить). В этом случае для остановки проигрывания нужно явно вызывать метод остановки. Размер файла, который может проиграть SoundPool не должен превышать 1 мегабайт.
Поддерживаются файлы практически всех популярных форматов: mp3, ogg, wav, aac, 3gp, flac. После загрузки файлы перекодируются (в 16-bit PCM моно или стерео) для упрощения воспроизведения.
Можно управлять скоростью воспроизведения аудио файла. Скорость 1,0 означает воспроизведение звука в исходном виде, 2,0 — воспроизведение в два раза быстрее, а 0,5 в два раза медленнее. Диапазон скорости воспроизведения составляет от 0,5 до 2,0.
Можно программно задать количество аудио потоков, проигрываемых одновременно. Если максимальное число потоков будет превышено, автоматически остановится поток с самым низкий приоритетом. При наличии нескольких потоков с тем же низким приоритетом, будет выбран старейший из них. В случае, если приоритет нового потока ниже, чем все активные потоки, новый звук не будет проигран. Ограничение максимального числа потоков помогает снизить загрузку процессора.
Конструктор класса SoundPool
- maxStreams — максимальное количество потоков, который могут воспроизводится одновременно
- streamType — тип аудиопотока, это константа из класса AudioManager. Здесь чаще всего используется AudioManager.STREAM_MUSIC.
- srcQuality — качество кодирования. Сейчас этот параметр не используется, поэтому всегда будем передавать 0.
В API 21 конструктор считается устаревшим. Смотри ниже.
Методы
Загрузить аудио файлы в SoundPool можно с помощью четырёх методов:
Загрузка из папки assets. Нужно знать путь к файлу. AssetManager — класс, предоставляющий доступ к файлам в директории assets. Получить экземпляр класса для данного приложения можно методом getAssets(). AssetFileDescriptor — файловый дескриптор для файла из директории assets.
Загрузка файла по идентификатору ресурса. Звуковые файлы могут находиться в каталоге res/raw, и соответственно идентификатор будет R.raw.sound.
Загрузка файла из указанного пути.
Загрузка файла из файловой системы устройства. Этот вариант полезен, если вы храните несколько звуков в одном двоичном файле. Параметр offset определяет смещение от начала файла, а length определяет длину звука.
В каждом методе мы передаём priority — приоритет файла. Методы возвращают идентификатор загруженного звука, который позже используется для воспроизведения.
Загрузка файлов происходит асинхронно, то есть после вызова метода load() файл не сразу будет доступен для воспроизведения, так как необходимо время для его загрузки и перекодирования. Для того чтобы отследить окончание загрузки нужно обработать событие OnLoadCompleteListener. Для этого устанавливаем обработчик события с помощью метода void setOnLoadCompleteListener(SoundPool.OnLoadCompleteListener listener), где SoundPool.OnLoadCompleteListener — это интерфейс с единственным методом void onLoadComplete(SoundPool soundPool, int sampleId, int status), который вызывается когда файл загружен. Здесь sampleId — идентификатор загруженного файла (то есть то, что вернул метод load()), а status — статус загрузки (значение 0 обозначает успешную загрузку).
Метод для проигрывания звука
- soundID — идентификатор звука (который вернул load())
- leftVolume — уровень громкости для левого канала (от 0.0 до 1.0)
- rightVolume — уровень громкости для правого канала (от 0.0 до 1.0)
- priority — приоритет потока (0 — самый низкий)
- loop — количество повторов (0 — без повторов, (-1) — зациклен)
- rate — скорость воспроизведения (от 0.5 до 2.0)
Метод возвращает целое число int, которое используется в других методах в качестве параметра streamID.
Возобновить приостановленный поток (если поток был не на паузе, то метод не даст никакого результата)
Установка количество повторов для потока
Установка приоритета для потока
Установка скорости для потока
Установка громкости для потока
Приостановить все активные потоки
Возобновить все потоки
Удаляет звук из SoundPool. Метод возвращает true, если операция прошла успешно, и false, если такого SoundID не существует
Удаляет все загруженные звуки из SoundPool и освобождает память. После вызова этого метода экземпляр класса SoundPool уже нельзя использовать. Метод используется при выходе из программы, чтобы освободить ресурсы.
Пример
Добавим на форму две кнопки, а также звуковой файл в папку ресурсов res/raw. Образцы бесплатных звуков можно взять в разделе Звуки.
Кнопку управления громкостью телефона можно настроить для управления громкости звуков:
SoundPool.Builder (API 21)
В Android 5.0 (API 21) вызов конструктора считается устаревшим. На смену ему пришёл класс SoundPool.Builder. Ниже приводится код из одного проекта.
Пример использования старого и нового способа показан в примере Кто сказал Мяу? — работаем со звуками Му, Мяу, Гав
Источник
Воспроизведение звуковых эффектов в Android с помощью SoundPool
View more Tutorials:
1- SoundPool & AudioManager
Для начала, я создам ситуацию, вы создаете игру, игра проигрывает такие звуки как выстрелы, бомбы, это звуковые эффекты в игре. Android предоставляет вам класс SoundPool, похожий на хранилице звуков и готовый проигрывать их при запросе.
SoundPool содержит набор музыки, звуков из файла музыки в приложении или из файла в системе. SoundPool помогает проигрывать разные звуки одновременно.
SourcePool использует сервис MediaPlayer, чтобы сделать звуки.
Вид потока звуков | Описание |
AudioManager.STREAM_ALARM | Аудио звуков сирены |
AudioManager.STREAM DTMF | Аудио DTMF тонов |
AudioManager.STREAM_MUSIC | Аудио для перепроигрывания звуков |
AudioManager.STREAM_NOTIFICATION | Аудио звука уведомления |
AudioManager.STREAM_RING | Аудио звука звона телефона |
AudioManager.STREAM_SYSTEM | Аудио системных звуков |
AudioManager.STREAM_VOICE_CALL | Аудио телефонного вызова |
Другой вопрос это какое устройство производит звук.
Используя STREAM_MUSIC звук будет произведен через одно звуковое устройтсво (телефонный динамик, наушники, динамик bluetooth и др.) соединенные с телефоном.
Используя STREAM_RING звук будет произведен через все звуковые устройтсва соединенные с телефоном. Это поведение может отличаться на каждом устройстве.
Метод | Описание |
int play(int soundID, float leftVolume, float rightVolume, int priority, int loop, float rate) | Воспроизведение источника звука, с возвращением ID нового воспроизведенного потока (streamID). |
void pause(int streamID) | Пауза звукового потока с ID streamID. |
void stop(int streamID) | Остановка звукового потока с streamID. |
void setVolume(int streamID, float leftVolume, float rightVolume) | Установка громкости звукового потока с ID streamID |
void setLoop(int streamID, int loop) | Установка номер цикла для звукового потока с ID streamID. |
2- Пример с SoundPool
- Name: SoundPoolDemo
- Package name: org.o7planning.soundpooldemo
View more Tutorials:
Это онлайн курс вне вебсайта o7planning, который мы представляем, он включает бесплатные курсы или курсы со скидкой.
Источник
Полный список
— работаем с SoundPool
На прошлом уроке мы рассмотрели MediaPlayer, который подходит для проигрывания продолжительных треков. SoundPool же подходит для случая, когда вам необходимо многократное воспроизведение небольших файлов. Самый простой пример – игры. Когда есть короткий звук какого-либо действия (прыжка, выстрела и т.п.) и этот звук достаточно часто необходимо воспроизводить. SoundPool один раз загружает этот звук в память и оттуда его воспроизводит, что, конечно, неплохо в плане производительности.
Класс SoundPool несложен. Позволяет загрузить звук в память, проиграть его, ставить паузу, регулировать громкость (левый и правый каналы), менять скорость воспроизведения, ограничивать кол-во одновременно воспроизводимых звуков, использовать приоритеты.
Напишем простое приложение, в котором рассмотрим все эти возможности.
Project name: P1271_SoundPool
Build Target: Android 2.3.3
Application name: SoundPool
Package name: ru.startandroid.develop.p1271soundpool
Create Activity: MainActivity
Добавим строки в strings.xml:
Только кнопка для запуска воспроизведения.
Для тестов нам понадобится пара звуков. Я буду использовать explosion.ogg (взрыв) и shot.ogg (выстрел). Поместим explosion.ogg в папку assets, а shot.ogg в папку res/raw.
Сначала создаем SoundPool. На вход ему передаем:
— максимальное кол-во одновременно воспроизводимых файлов
— аудио-поток, который будет использоваться
— некий параметр качества, который пока что игнорируется системой. Рекомендуется передавать туда 0
Методом setOnLoadCompleteListener мы устанавливаем слушателя загрузки. Загрузка аудио-файлов происходит асинхронно, и по ее окончании срабатывает метод onLoadComplete этого слушателя.
Далее загружаем файлы. Для этого используются различные варианты метода load. Чтобы загрузить файл из raw, необходимо указать Context, ID raw-файла и приоритет. Приоритет пока что также игнорируется системой, рекомендуется передавать туда 1.
Чтобы загрузить файл из assets используем другую реализацию метода load, которая на вход требует AssetFileDescriptor и приоритет. AssetFileDescriptor можно получить, используя метод openFd класса AssetManager, указав имя файла. Приоритет снова никакой роли не играет, передаем 1.
У метода load есть несколько реализаций, я специально показал две разных для наглядности. В хелпе вы можете найти ту, которая вам более подходит.
Метод load возвращает нам ID загруженного файла. Используя этот ID, мы будем проигрывать файл.
В методе onClick запускаем воспроизведение файлов. Для этого используется метод play. На вход он требует ряд параметров:
— ID файла. Тот самый, который мы получили от метода load.
— громкость левого канала (от 0.0 до 1.0)
— громкость правого канала (от 0.0 до 1.0)
— приоритет. Этот приоритет уже не декоративный, а вполне себе используемый. Далее увидим, где он нужен.
— количество повторов. Т.е. файл будет воспроизведен один раз точно + то количество раз, которое вы здесь укажете
— скорость воспроизведения. Можно задать от половины нормальной скорости до двойной (0.5 — 2).
Метод play возвращает ID потока, используемого для проигрывания файла. Этот ID можно использовать для дальнейшего изменения настроек в процессе проигрывания файла, а также для паузы.
Метод onLoadComplete слушателя OnLoadCompleteListener выполняется, когда SoundPool загружает файл. На вход вы получаете сам SoundPool, ID файла (тот же, что и load возвращал) и статус (0, если успешно)
Все сохраним и запустим приложение.
08:38:12.726: D/myLogs(333): soundIdShot = 1
08:38:12.726: D/myLogs(333): soundIdExplosion = 2
08:38:12.855: D/myLogs(333): onLoadComplete, sampleId = 1, status = 0
08:38:12.976: D/myLogs(333): onLoadComplete, sampleId = 2, status = 0
Видно, что загрузка звуков заняла определенное время. Жмем Play и слышим, как приложение играет оба звука одновременно.
Параметры метода play
Давайте поменяем громкость. Перепишем onClick:
Теперь один звук более слышен слева, а другой справа.
Поменяем кол-во повторов:
Теперь звук выстрела воспроизведен 6 раз (1 + 5 повторов), а звук взрыва – 3 раза (1 + 2 повтора).
Звук выстрела стал в два раза медленнее, а звук взрыва – в два раза быстрее.
Приоритет
Теперь давайте разберемся с приоритетом и кол-вом одновременно проигрываемых звуков. Хелп гласит:
«Priority runs low to high, i.e. higher numbers are higher priority. Priority is used when a call to play() would cause the number of active streams to exceed the value established by the maxStreams parameter when the SoundPool was created. In this case, the stream allocator will stop the lowest priority stream. If there are multiple streams with the same low priority, it will choose the oldest stream to stop. In the case where the priority of the new stream is lower than all the active streams, the new sound will not play and the play() function will return a streamID of zero.«
Т.е. приоритет используется, когда кол-во звуков, которое необходимо воспроизводить в данный момент, превышает максимально допустимое кол-во (мы его указывали при создании SoundPool, константа MAX_STREAMS). В этом случае звуки с низким приоритетом будут остановлены. Если есть несколько звуков с одинаково низким приоритетом, то останавливаются более старые. Если максимальное количество звуков уже достигнуто, и вы пытаетесь воспроизвести звук с низким приоритетом, то он не будет проигран, а метод play вернет 0 вместо ID потока.
Давайте проведем тесты и понаблюдаем все это в действии.
Звука у нас всего два. Поэтому, чтобы добиться конфликта, давайте для нашего SoundPool поставим кол-во одновременно воспроизводимых звуков равное одному:
onClick перепишем так:
Я, конечно, понимаю, что ставить паузу в основном потоке это #непофэншуюивообщенекомильфо, но в данном уроке я считаю это допустимым, чтобы не городить лишний код. Так что не обращайте на это внимание )
Мы начнем проигрывать звук выстрела 11 раз, а спустя пару секунд запустим звук взрыва. Выстрелы к тому моменту еще не успеют отзвучать, поэтому поглядим, как поведет себя система в данной ситуации. Напоминаю, что у нас сейчас установлен лимит на кол-во звуков = 1.
Заодно будем выводить в лог ID потоков, которые возвращает нам метод play.
Все сохраняем, запускаем, жмем Play. Я слышу 4 выстрела, потом взрыв. Т.е. при попытке воспроизвести взрыв система видит, что надо одновременно играть два звука: уже звучащий — выстрел и новый — взрыв. А лимит позволяет в один момент времени играть только один звук. Приоритеты у звуков одинаковые. Следовательно, система останавливает более старый звук, в нашем случае это выстрелы.
09:24:35.035: D/myLogs(754): streamIDShot = 1
09:24:37.092: D/myLogs(754): streamIDExplosion = 2
Разница в две секунды. ID потоков получены по обоим звукам.
Попробуем выставить для выстрелов приоритет более высокий, чем у взрыва.
Нарисуем у выстрела приоритет = 1, а у взрыва остался 0.
Сохраняем, запускаем, жмем Play.
Прога воспроизводит все выстрелы. Звук взрыва вообще не воспроизводится. Как и в прошлый раз у системы был выбор, но в этот раз она отменила взрыв и продолжила играть выстрелы, т.к. приоритеты выстрелов выше.
09:28:32.906: D/myLogs(788): streamIDShot = 1
09:28:34.934: D/myLogs(788): streamIDExplosion = 0
Видим, что для взрыва метод play вернул 0 вместо ID потока. Это значит, что звук не воспроизводился.
Пауза
Давайте посмотрим на возможности паузы. Мы можем приостановить какие-то определенные звуки, а можем все сразу.
Увеличим снова лимит звуков:
Мы запускаем проигрывание 10 выстрелов и 6 взрывов. Через 2 секунды приостанавливаем выстрелы, а еще через 3 секунды возобновляем. Для этого используются методы pause и resume, на вход которым даем ID потока из play.
Сохраняем, запускаем, жмем Play. Слышим выстрелы и взрывы. Затем выстрелы стихают, остаются только взрывы. Затем выстрелы снова возобновляются и все стихает. Counter-terrorist win )
Попробуем приостановить все звуки.
Для этого используем методы autoPause и autoResume. При проигрывании у нас будет пауза в три секунды, потом все возобновится.
Меняем уже играющий звук
Пока звук воспроизводится, вы можете повлиять на его характеристики, которые были заданы в методе play:
На вход методам идет ID потока (который вернул play) и необходимое вам значение параметра.
Например, поработаем с громкостью:
Выстрелы начнут играть в одном канале, взрывы — в другом. А через две секунды они поменяются каналами.
Выгрузка
Осталось упомянуть про еще два метода.
unload – выгрузит указанный звук из памяти. На вход требует ID звука, который возвращал метод load.
release – освобождает все ресурсы SoundPool, более он не сможет быть используемым и ссылку на него необходимо об-null-ить.
На следующем уроке:
— используем Audio Focus
Присоединяйтесь к нам в Telegram:
— в канале StartAndroid публикуются ссылки на новые статьи с сайта startandroid.ru и интересные материалы с хабра, medium.com и т.п.
— в чатах решаем возникающие вопросы и проблемы по различным темам: Android, Kotlin, RxJava, Dagger, Тестирование
— ну и если просто хочется поговорить с коллегами по разработке, то есть чат Флудильня
— новый чат Performance для обсуждения проблем производительности и для ваших пожеланий по содержанию курса по этой теме
Источник