Главная » Статьи » Java - интересные решения

Как воспроизвести звук в Java

Воспроизведение звука в Java

Введение


Нормальной русскоязычной информации по теме просто нет. Java-tutorials тоже оставляют желать лучшего. А архитектура javax.sound.sampled хоть и проста, но далеко не тривиальна. Поэтому свой первый пост на Хабре я решил посвятить именно этой теме. Приступим:

Воспроизведение звука


Тут всё более-менее просто. Импортируем javax.sound.sampled и поехали:
try {
 File soundFile = new File("snd.wav"); //Звуковой файл
 
 //Получаем AudioInputStream
 //Вот тут могут полететь IOException и UnsupportedAudioFileException
 AudioInputStream ais = AudioSystem.getAudioInputStream(soundFile);
 
 //Получаем реализацию интерфейса Clip
 //Может выкинуть LineUnavailableException
 Clip clip = AudioSystem.getClip();
 
 //Загружаем наш звуковой поток в Clip
 //Может выкинуть IOException и LineUnavailableException
 clip.open(ais);
 
 clip.setFramePosition(0); //устанавливаем указатель на старт
 clip.start(); //Поехали!!!

 //Если не запущено других потоков, то стоит подождать, пока клип не закончится
 //В GUI-приложениях следующие 3 строчки не понадобятся
 Thread.sleep(clip.getMicrosecondLength()/1000);
 clip.stop(); //Останавливаем
 clip.close(); //Закрываем
} catch (IOException | UnsupportedAudioFileException | LineUnavailableException exc) {
 exc.printStackTrace();
} catch (InterruptedException exc) {}
 
Регулятор громкости

Поигравшись со звуками, вы наверняка захотите иметь возможность программно изменять громкость звука. Java Sound API предоставляет такую возможность с фирменной кривотой.
//Получаем контроллер громкости
FloatControl vc = (FloatControl) clip.getControl(FloatControl.Type.MASTER_GAIN);
//Устанавливаем значение
//Оно должно быть в пределах от vc.getMinimum() до vc.getMaximum()
vc.setValue(5); //Громче обычного

Этот код нужно поместить между строчками clip.open(ais) и clip.setFramePosition(0).
 

Упрощаем процесс


Ну и наконец, чтобы вы не мучились, выкладываю класс для проигрывания звуков
import java.io.File;
import java.io.IOException;

import javax.sound.sampled.AudioInputStream;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.Clip;
import javax.sound.sampled.FloatControl;
import javax.sound.sampled.LineEvent;
import javax.sound.sampled.LineListener;
import javax.sound.sampled.LineUnavailableException;
import javax.sound.sampled.UnsupportedAudioFileException;

public class Sound {
 private boolean released = false;
 private Clip clip = null;
 private FloatControl volumeC = null;
 private boolean playing = false;
 
 public Sound(File f) {
 try {
 AudioInputStream stream = AudioSystem.getAudioInputStream(f);
 clip = AudioSystem.getClip();
 clip.open(stream);
 clip.addLineListener(new Listener());
 volumeC = (FloatControl) clip.getControl(FloatControl.Type.MASTER_GAIN);
 released = true;
 } catch (IOException | UnsupportedAudioFileException | LineUnavailableException exc) {
 exc.printStackTrace();
 released = false;
 }
 }

 //true если звук успешно загружен, false если произошла ошибка
 public boolean isReleased() {
 return released;
 }
 
 //проигрывается ли звук в данный момент
 public boolean isPlaying() {
 return playing;
 }

 //Запуск
 /*
 breakOld определяет поведение, если звук уже играется
 Если reakOld==true, о звук будет прерван и запущен заново
 Иначе ничего не произойдёт
 */
 public void play(boolean breakOld) {
 if (released) {
 if (breakOld) {
 clip.stop();
 clip.setFramePosition(0);
 clip.start();
 playing = true;
 } else if (!isPlaying()) {
 clip.setFramePosition(0);
 clip.start();
 playing = true;
 }
 }
 }
 
 //То же самое, что и play(true)
 public void play() {
 play(true);
 }
 
 //Останавливает воспроизведение
 public void stop() {
 if (playing) {
 clip.stop();
 }
 }

 //Установка громкости
 /*
 x долже быть в пределах от 0 до 1 (от самого тихого к самому громкому)
 */
 public void setVolume(float x) {
 if (x<0) x = 0;
 if (x>1) x = 1;
 float min = volumeC.getMinimum();
 float max = volumeC.getMaximum();
 volumeC.setValue((max-min)*x+min);
 }
 
 //Возвращает текущую громкость (число от 0 до 1)
 public float getVolume() {
 float v = volumeC.getValue();
 float min = volumeC.getMinimum();
 float max = volumeC.getMaximum();
 return (v-min)/(max-min);
 }

 //Дожидается окончания проигрывания звука
 public void join() {
 if (!released) return;
 synchronized(clip) {
 try {
 while (playing) clip.wait();
 } catch (InterruptedException exc) {}
 }
 }
 
 //Статический метод, для удобства
 public static Sound playSound(String s) {
 File f = new File(s);
 Sound snd = new Sound(f);
 snd.play();
 return snd;
 }

 private class Listener implements LineListener {
 public void update(LineEvent ev) {
 if (ev.getType() == LineEvent.Type.STOP) {
 playing = false;
 synchronized(clip) {
 clip.notify();
 }
 }
 }
 }
}



Пользоваться очень просто, например:

// запускает звук и остановит все остальные потоки

Sound.playSound("sounds/hello.wav").join();

// запускает звук не останавливая потоки и смешивая звуки

Sound.playSound("sounds/hello.wav");

// запускает звук с заданной громкостью( от 0 до 1)_

Sound.playSound("res/boom1.wav").setVolume((float) 0.7);

 

 

 

 

 

Категория: Java - интересные решения | Добавил: kuzma (04.04.2017)
Просмотров: 767 | Рейтинг: 0.0/0
Всего комментариев: 0
avatar

Программирование игр на Python

Django - создание сайтов с нуля

Javascript - просто используем готовые решения