Воспроизведение звука в 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 implements AutoCloseable < private boolean released = false; private AudioInputStream stream = null; private Clip clip = null; private FloatControl volumeControl = null; private boolean playing = false; public Sound(File f) < try < stream = AudioSystem.getAudioInputStream(f); clip = AudioSystem.getClip(); clip.open(stream); clip.addLineListener(new Listener()); volumeControl = (FloatControl) clip.getControl(FloatControl.Type.MASTER_GAIN); released = true; >catch (IOException | UnsupportedAudioFileException | LineUnavailableException exc) < exc.printStackTrace(); released = false; close(); >> // true если звук успешно загружен, false если произошла ошибка public boolean isReleased() < return released; >// проигрывается ли звук в данный момент public boolean isPlaying() < return playing; >// Запуск /* breakOld определяет поведение, если звук уже играется Если breakOld==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(); >> public void close() < if (clip != null) clip.close(); if (stream != null) try < stream.close(); >catch (IOException exc) < exc.printStackTrace(); >> // Установка громкости /* x долже быть в пределах от 0 до 1 (от самого тихого к самому громкому) */ public void setVolume(float x) < if (x<0) x = 0; if (x>1) x = 1; float min = volumeControl.getMinimum(); float max = volumeControl.getMaximum(); volumeControl.setValue((max-min)*x+min); > // Возвращает текущую громкость (число от 0 до 1) public float getVolume() < float v = volumeControl.getValue(); float min = volumeControl.getMinimum(); float max = volumeControl.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 path) < File f = new File(path); 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();
Форматы
Пару слов о поддержке форматов звуковых файлов: забудьте про mp3 и вспомните wav. Также поддерживаются au и aif.
Как воспроизвести звук в java
Для воспроизведения музыки и других аудиоматериалов Android предоставляет класс MediaPlayer .
Чтобы воспроизводить аудио, MediaPlayer должен знать, какой именно ресурс (файл) нужно производить. Установить нужный ресурс для воспроизведения можно тремя способами:
- в метод create() объекта MediaPlayer передается id ресурса, представляющего аудиофайл
- в метод create() объекта MediaPlayer передается объект Uri, представляющего аудиофайл
- в метод setDataSource() объекта MediaPlayer передается полный путь к аудиофайлу
После установки ресурса вызывается метод prepare() или prepareAsync() (асинхронный вариант prepare()). Этот метод подготавливает аудиофайл к воспроизведению, извлекая из него первые секунды. Если мы воспроизводим файл из сети, то лучше использовать prepareAsync().
Для управления воспроизведением в классе MediaPlayer определены следующие методы:
- start() : запускает аудио
- pause() : приостанавливает воспроизведение
- stop() : полностью останавливает воспроизведение
Итак, создадим новый проект. Как и в случае с видео, аудиофайл должен находиться в папке res/raw , поэтому добавим в проект в Android Studio такую папку. Для этого нажмем на папку res правой кнопкой мыши и в появившемся меню выберем New -> Android Resource Directory :

Затем в появившемся окне в качестве типа папки укажем raw (что также будет использоваться в качестве названия папки):

И скопируем в нее какой-нибудь аудио-файл.

Для управления аудиопотоком определим в файле activity_main.xml три кнопки:
И изменим код класса MainActivity :
package com.example.mediaapp; import androidx.appcompat.app.AppCompatActivity; import android.media.MediaPlayer; import android.os.Bundle; import android.view.View; import android.widget.Button; import android.widget.Toast; public class MainActivity extends AppCompatActivity < MediaPlayer mPlayer; Button playButton, pauseButton, stopButton; @Override protected void onCreate(Bundle savedInstanceState) < super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); mPlayer= MediaPlayer.create(this, R.raw.music); mPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() < @Override public void onCompletion(MediaPlayer mp) < stopPlay(); >>); playButton = findViewById(R.id.playButton); pauseButton = findViewById(R.id.pauseButton); stopButton = findViewById(R.id.stopButton); pauseButton.setEnabled(false); stopButton.setEnabled(false); > private void stopPlay() < mPlayer.stop(); pauseButton.setEnabled(false); stopButton.setEnabled(false); try < mPlayer.prepare(); mPlayer.seekTo(0); playButton.setEnabled(true); >catch (Throwable t) < Toast.makeText(this, t.getMessage(), Toast.LENGTH_SHORT).show(); >> public void play(View view) < mPlayer.start(); playButton.setEnabled(false); pauseButton.setEnabled(true); stopButton.setEnabled(true); >public void pause(View view) < mPlayer.pause(); playButton.setEnabled(true); pauseButton.setEnabled(false); stopButton.setEnabled(true); >public void stop(View view) < stopPlay(); >@Override public void onDestroy() < super.onDestroy(); if (mPlayer.isPlaying()) < stopPlay(); >> >
Обработчик каждой кнопки кроме вызова определенного метода у MediaPlayer также переключает доступность кнопок.
И если запуск и приостановка воспроизведения особых сложностей не вызывает, то при обработки полной остановки воспроизведения мы можем столкнуться с рядом трудностей. В частности, когда мы выходим из приложения — полностью закрываем его через диспетчер приложений либо нажимаем на кнопку Назад, то у нас для текущей Activity вызывается метод onDestroy, activity уничтожается, но MediaPlayer продолжает работать. Если мы вернемся к приложению, то activity будет создана заново, но с помощью кнопок мы не сможем управлять воспроизведением. Поэтому в даном случае переопределяем метод onDestroy, в котором завершаем воспроизведение.
Для корректного завершения также определен обработчик естественного завершения воспроизведения OnCompletionListener , действие которого будет аналогично нажатию на кнопку «Стоп».

Добавим к воспроизведению индикатор громкости. Для этого в файле activity_main.xml определим SeekBar :
И далее изменим код класса MainActivity :
package com.example.mediaapp; import androidx.appcompat.app.AppCompatActivity; import android.content.Context; import android.media.AudioManager; import android.media.MediaPlayer; import android.os.Bundle; import android.view.View; import android.widget.Button; import android.widget.SeekBar; import android.widget.Toast; public class MainActivity extends AppCompatActivity < MediaPlayer mPlayer; Button playButton, pauseButton, stopButton; SeekBar volumeControl; AudioManager audioManager; @Override protected void onCreate(Bundle savedInstanceState) < super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); mPlayer=MediaPlayer.create(this, R.raw.music); mPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() < @Override public void onCompletion(MediaPlayer mp) < stopPlay(); >>); playButton = findViewById(R.id.playButton); pauseButton = findViewById(R.id.pauseButton); stopButton = findViewById(R.id.stopButton); audioManager = (AudioManager) getSystemService(Context.AUDIO_SERVICE); int maxVolume = audioManager.getStreamMaxVolume(AudioManager.STREAM_MUSIC); int curValue = audioManager.getStreamVolume(AudioManager.STREAM_MUSIC); volumeControl = findViewById(R.id.volumeControl); volumeControl.setMax(maxVolume); volumeControl.setProgress(curValue); volumeControl.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() < @Override public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) < audioManager.setStreamVolume(AudioManager.STREAM_MUSIC, progress, 0); >@Override public void onStartTrackingTouch(SeekBar seekBar) < >@Override public void onStopTrackingTouch(SeekBar seekBar) < >>); pauseButton.setEnabled(false); stopButton.setEnabled(false); > private void stopPlay() < mPlayer.stop(); pauseButton.setEnabled(false); stopButton.setEnabled(false); try < mPlayer.prepare(); mPlayer.seekTo(0); playButton.setEnabled(true); >catch (Throwable t) < Toast.makeText(this, t.getMessage(), Toast.LENGTH_SHORT).show(); >> public void play(View view) < mPlayer.start(); playButton.setEnabled(false); pauseButton.setEnabled(true); stopButton.setEnabled(true); >public void pause(View view) < mPlayer.pause(); playButton.setEnabled(true); pauseButton.setEnabled(false); stopButton.setEnabled(true); >public void stop(View view) < stopPlay(); >@Override public void onDestroy() < super.onDestroy(); if (mPlayer.isPlaying()) < stopPlay(); >> >
Для управления громкостью звука применяется класс AudioManager . А в с помощью вызова audioManager.setStreamVolume(AudioManager.STREAM_MUSIC, progress, 0); в качестве второго параметра можно передать нужное значение громкости.
Как воспроизвести звук в java
для воспроизведения файла — создать объект согласно конструктора
Audio a_enem = new Audio("res/boom1.wav",0.8);
Для воспроизведения вызвать метод sound для объекта
a_enem.sound();//играть звук
Для задания уровня громкости — вызвать метод setVolume ()
a_enem.setVolume();
Метод play() — воспроизводит муз. файл один раз и позволяет остановить его методом stop().
Полный код класса Audio
/** * звук */ import java.io.File; import java.io.IOException; import javax.sound.sampled.*; public class Audio < private String track; // адрес трека(файла) private Clip clip = null;// ссылка на объект класса private FloatControl volumeC = null;// контролер громкости private double wt; //уровень громкости private boolean pl_audio;// воспроизведение звука private long timer_p = 0;// начальное время для таймера звучания private long timer_f = 0;// конечное время звучания private long timer_d;// (количество миллисекунд) длительность трека //конструктор (адрес файла, уровень громкости) public Audio( String track, double wt)< this.track = track; this.wt =wt; this.pl_audio = false; >
//конструктор (адрес файла, уровень громкости, кол.милсек звук трек) public Audio( String track, double wt,long timer_d)< this.timer_d = timer_d; this.track = track; this.pl_audio = false; this.wt =wt; >
public void sound() < File f = new File(this.track);// передаем звуковой файл в f //поток для записи и считывания AudioInputStream tr = null; // обьект потока AudioInputStream пуст try < tr = AudioSystem.getAudioInputStream(f); // Получаем AudioInputStream (нужный файл) > catch (UnsupportedAudioFileException e) < e.printStackTrace(); >catch (IOException e) < e.printStackTrace(); >try < clip = AudioSystem.getClip();//Получаем реализацию интерфейса Clip clip.open(tr); //Загружаем наш звуковой поток в Clip //Получаем контроллер громкости volumeC = (FloatControl) clip.getControl(FloatControl.Type.MASTER_GAIN); clip.setFramePosition(0); //устанавливаем указатель на старт clip.start(); //Поехали. > catch (LineUnavailableException e) < e.printStackTrace(); >catch (IOException e) < e.printStackTrace(); >> // пероигрывать звук объкта одиночное проигрывание с stop() public void play() < File f = new File(this.track);// передаем звуковой файл в f //поток для записи и считывания AudioInputStream tr = null; // обьект потока AudioInputStream пуст try < tr = AudioSystem.getAudioInputStream(f); // Получаем AudioInputStream (нужный файл) > catch (UnsupportedAudioFileException e) < e.printStackTrace(); >catch (IOException e) < e.printStackTrace(); >try < clip = AudioSystem.getClip();//Получаем реализацию интерфейса Clip clip.open(tr); //Загружаем наш звуковой поток в Clip //Получаем контроллер громкости volumeC = (FloatControl) clip.getControl(FloatControl.Type.MASTER_GAIN); if(!this.pl_audio) < clip.setFramePosition(0); //устанавливаем указатель на старт clip.start(); //Поехали. this.pl_audio = true; // играет > > catch (LineUnavailableException e) < e.printStackTrace(); >catch (IOException e) < e.printStackTrace(); >> //стоп public void stop() < clip.stop(); clip.close(); //Закрываем this.pl_audio = false; > //уровень громкости public void setVolume() < if (wt0) wt = 0; if (wt>1) wt = 1; float min = volumeC.getMinimum(); float max = volumeC.getMaximum(); volumeC.setValue((max-min)*(float)wt+min); > // повтор (работает с треками запущенными методом play()) public void repeat() < if (this.pl_audio) clip.loop(10); //повторить n раз > // таймер звука ( для треков запущ. play() и конструктор с timer_d) public void timer_play ()< if (timer_p == 0) < //если таймер не запущен timer_p = System.currentTimeMillis();// получаем текущее время милсек timer_f = timer_p + timer_d; // конечное время трека > if(timer_fcurrentTimeMillis()) < //если время звучания меньше текущювремени this.stop();//стоп трек timer_p=0;// обнуляем счетчик > > >
Учебники. Программирование для начинающих.
Programm.ws — это сайт, на котором вы можете почитать литературу по языкам программирования , а так-же посмотреть примеры работающих программ на С++, ассемблере, паскале и много другого..
Программирование — в обычном понимании, это процесс создания компьютерных программ.
В узком смысле (так называемое кодирование) под программированием понимается написание инструкций — программ — на конкретном языке программирования (часто по уже имеющемуся алгоритму — плану, методу решения поставленной задачи). Соответственно, люди, которые этим занимаются, называются программистами (на профессиональном жаргоне — кодерами), а те, кто разрабатывает алгоритмы — алгоритмистами, специалистами предметной области, математиками.
В более широком смысле под программированием понимают весь спектр деятельности, связанный с созданием и поддержанием в рабочем состоянии программ — программного обеспечения ЭВМ. Более точен современный термин — «программная инженерия» (также иначе «инженерия ПО»). Сюда входят анализ и постановка задачи, проектирование программы, построение алгоритмов, разработка структур данных, написание текстов программ, отладка и тестирование программы (испытания программы), документирование, настройка (конфигурирование), доработка и сопровождение.
Cамоучитель по Java
Глава 15. Изображения и звук
Проигрывание звука в Java 2
Проигрыватель звука, встроенный в JVM, рассчитан на два способа записи звука: моно и стерео оцифровку (digital audio) с частотой дискретизации (sample rate) от 8 000 до 48 000 Гц и аппроксимацией (quantization) 8 и 16 битов, и MIDI-последовательности (sequences) типа 0 и 1.
Оцифрованный звук должен храниться в файлах типа AU, WAVE и AIFF. Его можно проигрывать двумя способами.
Первый способ описан в интерфейсе clip. Он рассчитан на воспроизведение небольших файлов или неоднократное проигрывание файла и заключается в том, что весь файл целиком загружается в оперативную память, а затем проигрывается.
Второй способ описан в интерфейсе SourceDataLine. Согласно этому способу файл загружается в оперативную память по частям в буфер, размер которого можно задать произвольно.
Перед загрузкой файла надо задать формат записи звука в объекте класса AudioFormat. Конструктор этого класса:
AudioFormat(float sampleRate, int sampleSize, int channels, boolean signed, boolean bigEndian)
требует знания частоты дискретизации sampleRate (по умолчанию 44 100 Гц), аппроксимации sampleSize, заданной в битах (по умолчанию 16), числа каналов channels (1 — моно, по умолчанию 2 — стерео), запись чисел со знаком, signed == true, или без знака, и порядка расположения байтов в числе bigEndian. Такие сведения обычно неизвестны, поэтому их получают косвенным образом из файла. Это осуществляется в два шага.
На первом шаге получаем формат файла статическим методом getAudioFiieFormato класса AudioSystem, на втором — формат записи звука методом getFormato класса AudioFiieFormat. Это описано в листинге 15.15. После того как формат записи определен и занесен в объект класса AudioFormat, в объекте класса DataLine. infо собирается информация о входной линии (line) и способе проигрывания clip или SourceDataLine. Далее следует проверить, сможет ли проигрыватель обслуживать линию с таким форматом. Затем надо связать линию с проигрывателем статическим методом getLine () класса AudioSystem. Потом создаем поток данных из файла — объект класса Audioinputstream. Из этого потока тоже можно извлечь объект класса AudioFormat методом getFormat (). Данный вариант выбран в листинге 15.16. Открываем созданный поток методом орепо.
У-фф! Все готово, теперь можно начать проигрывание методом start (), завершить методом stop(), «перемотать» в начало методом setFramePosition(0) ИЛИ setMillisecondPosition(0).
Можно задать проигрывание п раз подряд методом loop(n) или бесконечное число раз методом loop (Clip.LOOP_CONTINUOUSLY) . Перед этим необходимо установить начальную n и конечную m позиции повторения методом setLoopPoints(n, m).
По окончании проигрывания следует закрыть линию методом close ().
Вся эта последовательность действий показана в листинге 15.15.
Листинг 15.15. Проигрывание аудиоклипа
public void play(String file)
Clip line = null;
// Создаем объект, представляющий файл
File f = new File (file);
// Получаем информацию о способе записи файла
AudioFileFormat aff = AudioSystem.getAudioFileFormat(f);
// Получаем информацию о способе записи звука
AudioFormat af = aff.getFormat();
// Собираем всю информацию вместе,
// добавляя сведения о классе
Class DataLine.Infо info = new DataLine.Info(Clip.class, af) ;
// Проверяем, можно ли проигрывать такой формат
System.err.printlnt»Line is not supported»);
// Получаем линию связи с файлом
// Создаем поток байтов из файла
AudioInputStream ais — AudioSystem.getAudioInputStream(f);
// Здесь надо сделать задержку до окончания проигрывания
// или остановить его следующим методом:
//По окончании проигрывания закрываем линию
public static void main(String[] args)
if (args.length != 1)
System.out.printlnt»Usage: Java PlayAudio filename»);
Как видите, методы Java Sound API выполняют элементарные действия, которые надо повторять из программы в программу. Как говорят, это методы «низкого уровня» (low level).
Второй способ, использующий методы интерфейса SourceDataLine, требует предварительного создания буфера произвольного размера.
Листинг 15.16. Проигрывание аудиофайла
public void play(String file)
SourceDataLine line = null;
AudioInputStream ais = null;
byte[] b = new byte[2048]; // Буфер данных
File f = new File(file);
// Создаем входной поток байтов из файла f
// Извлекаем из потока информацию о способе записи звука
AudioFormat af = ais.getFormat () ;
// Заносим эту информацию в объект info
DataLine.Infо info = new DataLine.Infо(SourceDataLine.class, af);
// Проверяем, приемлем ли такой способ записи звука
System.err.println(«Line is not supported»);
// Получаем входную линию
line.start(); // Ждем появления данных в буфере int num = 0;
// Раз за разом заполняем буфер
while(( num = ais.read(b)) != -1)
line.write(b, 0, num);
// «Сливаем» буфер, проигрывая остаток файла
> catch (Exception e)
System, err.println (e);
public static void main(String[] args)
String s = «mrmba.aif»;
if (args.length > 0) s = args[0];
Управлять проигрыванием файла можно с помощью событий. Событие класса LineEvent происходит при открытии, OPEN, и закрытии, CLOSE, потока, при начале, START, и окончании, STOP, проигрывания. Характер события отмечается указанными константами. Соответствующий интерфейс LineListener описывает только один метод update ().
В MIDI-файлах хранится последовательность (sequence) команд для секвен-сора (sequencer) — устройства для записи, проигрывания и редактирования MlDI-последовательности, которым может быть физическое устройство или программа. Последовательность состоит из нескольких дорожек (tracks), на которых записаны MIDI-события (events). Каждая дорожка загружается в своем канале (channel). Обычно дорожка содержит звучание одного музыкального инструмента или запись голоса одного исполнителя или запись нескольких исполнителей, микшированную синтезатором (synthesizer).
Для проигрывания MIDI-последовательности в простейшем случае надо создать экземпляр секвенсора, открыть его и направить в него последовательность, извлеченную из файла, как показано в листинге 15.17. После этого следует начать проигрывание методом start (). Закончить проигрывание можно методом stop(), «перемотать» последовательность на начало записи или на указанное время проигрывания — методами setMicrosecondPositionflong mcs) или setTickPosition(long tick).
Листинг 15.17. Проигрывание MIDI-последовательности
public void play(String file)
File f = new File(file);
// Получаем секвенсор по умолчанию
Sequencer sequencer = MidiSystem.getSequencerО;
// Проверяем, получен ли секвенсор
if (sequencer = null)
System.err.println(«Sequencer is not supported»);
// Получаем MIDI-последовательность из файла
Sequence seq = MidiSystem.getSequence(f);
// Направляем последовательность в секвенсор
// Здесь надо сделать задержку на время проигрывания,
// а затем остановить:
public static void main(String[] args)
String s = «doom.mid»;
if (args.length > 0) s = args[0];