Прежде, чем перейти к сути, я немного расскажу вам о компьютерном звуке.
Существует два основных формата воспроизведения звуков компьютером:
цифровой (WAV-формат) и синтезированный (MIDI).
Цифровой звук является основным стандартом компьютерного звука сегодня. Именно оцифрованный звук вы слышите, проигрывая композиции в mp3 формате или прослушивая компакт-диски, просматривая фильм или играя в комьютерные игры.
Оцифрованный звук представляет собой набор битов, который последовательно описывает значение уровня амплитуды звуковой волны в каждый момент времени звучания. При его воспроизведении звуковая карта лишь переводит «цифровой» звук в привычную нам «аналоговую» форму.
Но существует и другой вид компьютерного звука — синтезированный (MIDI)
Звуковая карта может служить музыкальным синтезатором, способном воспроизводить звучания до 128-ми различных музыкальных инструментов. Качество и принцип имитации инструментов зависит от вашей звуковой карты. Она может пытаться смоделировать звучание инструмента совокупностью нескольких FM (частотных) генераторов простых частот, для каждой из которых задана амплитуда, частота, фаза и куча других параметров. Но чаще она обращается к хранящимся в ней «банкам данных» образцов звучания инструментов.
В настоящий момент существует множество звуковых карт, которые могут работать с SoundFont. Это просто wav сэмплы, которые можно загрузить в звуковую карту и звучанием этих инструментов можно управлять в миди-секвенсоре. SoundFont обычно имеет расширение .sf2, их могут также называть патчами (patch) или программами (program). Несколько SoundFont объединяют в звуковые банки (SoundFont Banks), которые могут содержать до 128 инструментов и одного набора ударных.
В сети вы без труда сможете найти профессиональные библиотеки банков инструментов в формате SF2.
Чтобы синтезатор воспроизвел нужный звук, необходимо передать ему специальную команду. Совокупность таких команд описана стандартом MIDI.
MIDI это акроним от Musical Instruments Digital Interface, что в буквальном переводе — цифровой интерфейс музыкальных инструментов.
При помощи этих команд мы можем «сказать» синтезатору звуковой платы каким инструментом ту или иную ноту мы хотим чтобы он воспроизвел. Например Фа-диез на рояле или любом другом из 128-ми инструментов.
Допустим для каких-то целей вам понадобилось из java научиться воспроизводить ноты. И вы решили узнать, как заставить синтезатор вашей звуковой платы это делать. Окунувшись поисковиком в информационное море интернета, вы неожиданно поймете, что толковой информации по этому вопросу найти непросто.
Скажу, что существует достаточное количество библиотек для работы с midi. И все они обещают, что с их помощью процес программирования музыки будет проще. Я столкнулся с двумя такими: jfugue и jMusic. В Ютубе есть наглядные руководства о их применении. В каждой из подобных библиотек были выдуманы свои способы и правила. Чем более экзотическая библиотека, тем меньше информации и примеров. Так же придется довериться правильности и точности их работы.
Из многих соображений полагаю, что лучше начать изучение и научиться применять в начале стандартную библиотеку: javax/sound/midi
Тем, кто впервые сталкивается с этой темой, моя статья призвана помочь сделать первые шаги. Я научу вас самым базовым навыкам работы с midi звуком. А дальше вы уже сами сможете расширить их применение и, если потребуется, легко дополните информацию из описания библиотеки и примерами из интернета.
Итак, все что вам для начала нужно — научиться воспроизводить ноты.
Ваше желание включает некоторую дополнительную информацию — название ноты (номер) и длительность звучания. А так же инструмент, который вы хотите чтобы её сыграл.
Желание совершенно просто и ясно сформулировано: «Хочу, чтобы прозвучала такая-то нота, определенное время и выбранным инструментом.» Однако сходу найти соответствующую информацию, как это сделать, вам будет сложно. Вот по этому эта статья и написана — чтобы вы не тратили свое время а сразу получили то, что нужно. И начали применять.
Номера нот вы можете определить по данной таблице:

А номера инструментов можно посмотреть здесь
Перед непосредственным программированием воспроизведения потребуется некоторая подготовка. А именно, вам понадобится получить объект синтезатора (Synthesizer) и отрыть его. Затем получить доступ к его каналам.
Звучит, возможно, не совсем понятно, но на практике всё просто:
Канал можно представить как универсального музыканта, который способен играть на любом из 128-ми инструментов. Вы располагаете 16-тью такими каналами.
Вот в принципе и вся подготовка. Далее необходимо научиться давать команды музыкантам.
Допустим вы хотите, чтоб звучала нота Фа первой октавы. Для этого, посмотрев таблицу с номерами нот, выясняете, что её номер 65. Выбираем одного из 16-ти музыкантов. Допустим под номером 0 (channels[0]). Воспроизведение происходит по команде noteOn.
Она принимает 2 параметра: MIDI номер ноты (от 0 до 127) и громкость звучания (так же до 127)
Выглядеть это будет так:
По этой команде музыкант под номером «ноль» начнет воспроизведение ноты Фа первой октавы. 80 — это громкость. Это можно представить, что музыкант нажал клавишу синтезатора и льется звук.
Думаю, вы догадались, что для прекращения звучания так же потребуется дать команду. Т.е. чтобы конкретно этот музыкант отпустил нажатую клавишу — выполняем команду noteOff.
Таким образом:
Между этими командами следует сделать паузу, от которой и будет зависеть длительность звучания.
Вот, собственно, и всё. И не нужны никакие сторонние библиотеки. Всё необходимое теперь вы сможете удобным способом написать под себя сами. Осталось открыть вам последний секрет — научить волшебным словам, которые заставят «музыкантов» взять другой муз. инструмент.
Напомню, что выбрать инструмент можно здесь. Любому из 16-ти каналов вы можете назначить один из 128-ми инструментов. По умолчанию почти все каналы используют фортепиано.
Так производится назначение «нулевому» каналу инструмент «скрипка»:
Понадобится импортировать следующие стандартные пакеты:
Итак, код воспроизводящий звук будет выглядеть следующим образом:
Далее, как уже было сказано, возможности по программированию извлечения звука ограничены только вашей фантазией.
Для примитивной демонстрации создадим свой метод воспроизведения звуков, который нажатие, паузу и отпускание будет выполнять одной командой. Отведем для этих целей отдельный класс, структура и функционал которого не нуждаются в пояснении:
В конструкторе класса создается и открывается синтезатор. Получаем массив каналов и первому (нулевому) назначаем инструмент «скрипка».
Метод playSound получает на вход номер канала, длительность звучания, громкость и последовательность нот, которые прозвучат одновременно. Реализация предельно проста — воспроизводятся все входящие ноты, удерживается интервал длительности и затем все выключаются.
Вот пример использования данного класса — воспроизводятся четыре аккорда:
Ну и в заключении, давайте для эксперимента запрограммируем какую-нибудь известную красивую мелодию.
Просто скопируйте себе код и, запустив, услышите «Jasper Forks — River Flows In You»:
В массиве пары чисел содержат величину длительности звучания и номер ноты. Паузу, для отличия, запишем «минус единицей». Канал и громкость оставим для всех нот одинаковые — 0 и 80 соответственно.
Что ж, полагаю у вас не возникло сложностей с пониманием изложенного материала. Буду рад, если эта статья сэкономит ваше время и силы, позволив с легкостью приступить к программированию воспроизведения MIDI звука на JAVA.
Существует два основных формата воспроизведения звуков компьютером:
цифровой (WAV-формат) и синтезированный (MIDI).
Цифровой звук является основным стандартом компьютерного звука сегодня. Именно оцифрованный звук вы слышите, проигрывая композиции в mp3 формате или прослушивая компакт-диски, просматривая фильм или играя в комьютерные игры.
Оцифрованный звук представляет собой набор битов, который последовательно описывает значение уровня амплитуды звуковой волны в каждый момент времени звучания. При его воспроизведении звуковая карта лишь переводит «цифровой» звук в привычную нам «аналоговую» форму.
Но существует и другой вид компьютерного звука — синтезированный (MIDI)
Звуковая карта может служить музыкальным синтезатором, способном воспроизводить звучания до 128-ми различных музыкальных инструментов. Качество и принцип имитации инструментов зависит от вашей звуковой карты. Она может пытаться смоделировать звучание инструмента совокупностью нескольких FM (частотных) генераторов простых частот, для каждой из которых задана амплитуда, частота, фаза и куча других параметров. Но чаще она обращается к хранящимся в ней «банкам данных» образцов звучания инструментов.
В настоящий момент существует множество звуковых карт, которые могут работать с SoundFont. Это просто wav сэмплы, которые можно загрузить в звуковую карту и звучанием этих инструментов можно управлять в миди-секвенсоре. SoundFont обычно имеет расширение .sf2, их могут также называть патчами (patch) или программами (program). Несколько SoundFont объединяют в звуковые банки (SoundFont Banks), которые могут содержать до 128 инструментов и одного набора ударных.
В сети вы без труда сможете найти профессиональные библиотеки банков инструментов в формате SF2.
Чтобы синтезатор воспроизвел нужный звук, необходимо передать ему специальную команду. Совокупность таких команд описана стандартом MIDI.
MIDI это акроним от Musical Instruments Digital Interface, что в буквальном переводе — цифровой интерфейс музыкальных инструментов.
При помощи этих команд мы можем «сказать» синтезатору звуковой платы каким инструментом ту или иную ноту мы хотим чтобы он воспроизвел. Например Фа-диез на рояле или любом другом из 128-ми инструментов.
Допустим для каких-то целей вам понадобилось из java научиться воспроизводить ноты. И вы решили узнать, как заставить синтезатор вашей звуковой платы это делать. Окунувшись поисковиком в информационное море интернета, вы неожиданно поймете, что толковой информации по этому вопросу найти непросто.
Скажу, что существует достаточное количество библиотек для работы с midi. И все они обещают, что с их помощью процес программирования музыки будет проще. Я столкнулся с двумя такими: jfugue и jMusic. В Ютубе есть наглядные руководства о их применении. В каждой из подобных библиотек были выдуманы свои способы и правила. Чем более экзотическая библиотека, тем меньше информации и примеров. Так же придется довериться правильности и точности их работы.
Из многих соображений полагаю, что лучше начать изучение и научиться применять в начале стандартную библиотеку: javax/sound/midi
Тем, кто впервые сталкивается с этой темой, моя статья призвана помочь сделать первые шаги. Я научу вас самым базовым навыкам работы с midi звуком. А дальше вы уже сами сможете расширить их применение и, если потребуется, легко дополните информацию из описания библиотеки и примерами из интернета.
Итак, все что вам для начала нужно — научиться воспроизводить ноты.
Ваше желание включает некоторую дополнительную информацию — название ноты (номер) и длительность звучания. А так же инструмент, который вы хотите чтобы её сыграл.
Желание совершенно просто и ясно сформулировано: «Хочу, чтобы прозвучала такая-то нота, определенное время и выбранным инструментом.» Однако сходу найти соответствующую информацию, как это сделать, вам будет сложно. Вот по этому эта статья и написана — чтобы вы не тратили свое время а сразу получили то, что нужно. И начали применять.
Номера нот вы можете определить по данной таблице:

А номера инструментов можно посмотреть здесь
Перед непосредственным программированием воспроизведения потребуется некоторая подготовка. А именно, вам понадобится получить объект синтезатора (Synthesizer) и отрыть его. Затем получить доступ к его каналам.
Звучит, возможно, не совсем понятно, но на практике всё просто:
Synthesizer synth = MidiSystem.getSynthesizer();
synth.open();
MidiChannel[] channels = synth.getChannels();
Канал можно представить как универсального музыканта, который способен играть на любом из 128-ми инструментов. Вы располагаете 16-тью такими каналами.
Вот в принципе и вся подготовка. Далее необходимо научиться давать команды музыкантам.
Допустим вы хотите, чтоб звучала нота Фа первой октавы. Для этого, посмотрев таблицу с номерами нот, выясняете, что её номер 65. Выбираем одного из 16-ти музыкантов. Допустим под номером 0 (channels[0]). Воспроизведение происходит по команде noteOn.
Она принимает 2 параметра: MIDI номер ноты (от 0 до 127) и громкость звучания (так же до 127)
Выглядеть это будет так:
channels[0].noteOn(65, 80);
По этой команде музыкант под номером «ноль» начнет воспроизведение ноты Фа первой октавы. 80 — это громкость. Это можно представить, что музыкант нажал клавишу синтезатора и льется звук.
Думаю, вы догадались, что для прекращения звучания так же потребуется дать команду. Т.е. чтобы конкретно этот музыкант отпустил нажатую клавишу — выполняем команду noteOff.
Таким образом:
channels[0].noteOff(65);
Между этими командами следует сделать паузу, от которой и будет зависеть длительность звучания.
Вот, собственно, и всё. И не нужны никакие сторонние библиотеки. Всё необходимое теперь вы сможете удобным способом написать под себя сами. Осталось открыть вам последний секрет — научить волшебным словам, которые заставят «музыкантов» взять другой муз. инструмент.
Напомню, что выбрать инструмент можно здесь. Любому из 16-ти каналов вы можете назначить один из 128-ми инструментов. По умолчанию почти все каналы используют фортепиано.
Так производится назначение «нулевому» каналу инструмент «скрипка»:
channels[0].programChange(41);
Понадобится импортировать следующие стандартные пакеты:
import javax.sound.midi.MidiChannel;
import javax.sound.midi.MidiSystem;
import javax.sound.midi.Synthesizer;
Итак, код воспроизводящий звук будет выглядеть следующим образом:
try {
Synthesizer synth = MidiSystem.getSynthesizer();
synth.open();
MidiChannel[] channels = synth.getChannels();
channels[0].programChange(41);
channels[0].noteOn(65, 80);
Thread.sleep(1000); // in milliseconds
channels[0].noteOff(65);
synth.close();
} catch (Exception e) {
e.printStackTrace();
}
Далее, как уже было сказано, возможности по программированию извлечения звука ограничены только вашей фантазией.
Для примитивной демонстрации создадим свой метод воспроизведения звуков, который нажатие, паузу и отпускание будет выполнять одной командой. Отведем для этих целей отдельный класс, структура и функционал которого не нуждаются в пояснении:
package music.player;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.sound.midi.MidiChannel;
import javax.sound.midi.MidiSystem;
import javax.sound.midi.MidiUnavailableException;
import javax.sound.midi.Synthesizer;
public class Player {
private MidiChannel[] channels = null;
private Synthesizer synth = null;
public Player() {
try {
synth = MidiSystem.getSynthesizer();
synth.open();
channels = synth.getChannels();
channels[0].programChange(41);
} catch (MidiUnavailableException ex) {
Logger.getLogger(Player.class.getName()).log(Level.SEVERE, null, ex);
}
}
public void close() {
synth.close();
}
public void playSound(int channel, int duration, int volume, int... notes) {
for (int note : notes) {
channels[channel].noteOn(note, volume);
}
try {
Thread.sleep(duration);
} catch (InterruptedException ex) {
Logger.getLogger(Player.class.getName()).log(Level.SEVERE, null, ex);
}
for (int note : notes) {
channels[channel].noteOff(note);
}
}
}
В конструкторе класса создается и открывается синтезатор. Получаем массив каналов и первому (нулевому) назначаем инструмент «скрипка».
Метод playSound получает на вход номер канала, длительность звучания, громкость и последовательность нот, которые прозвучат одновременно. Реализация предельно проста — воспроизводятся все входящие ноты, удерживается интервал длительности и затем все выключаются.
Вот пример использования данного класса — воспроизводятся четыре аккорда:
Player player = new Player();
player.playSound(0, 1000, 80, 69, 72, 76);
player.playSound(0, 1000, 80, 69, 74, 77);
player.playSound(0, 1000, 80, 67, 71, 74);
player.playSound(0, 1000, 80, 67, 72, 76);
player.close();
Ну и в заключении, давайте для эксперимента запрограммируем какую-нибудь известную красивую мелодию.
Просто скопируйте себе код и, запустив, услышите «Jasper Forks — River Flows In You»:
int notes[][] = {{470, 81}, {230, 80}, {470, 81}, {250, -1}, {230, 80}, {470, 81}, {230, 69}, {230, 76}, {470, 81}, {230, 69}, {470, 74}, {470, 73}, {470, 74}, {470, 76}, {470, 73}, {470, 71}, {970, -1}, {230, 69}, {230, 68}, {470, 69}, {730, -1}, {230, 64}, {230, 69}, {230, 71}, {470, 73}, {970, -1}, {230, 73}, {230, 74}, {470, 76}, {730, -1}, {230, 69}, {230, 74}, {230, 73}, {470, 71}, {1450, -1}, {470, 81}, {230, 80}, {470, 81}, {250, -1}, {230, 80}, {470, 81}, {230, 69}, {230, 76}, {470, 81}, {230, 69}, {470, 74}, {470, 73}, {470, 74}, {470, 76}, {470, 73}, {470, 71}, {970, -1}, {230, 69}, {230, 68}, {470, 69}, {730, -1}, {230, 64}, {230, 69}, {230, 71}, {470, 73}, {970, -1}, {230, 73}, {230, 74}, {470, 76}, {730, -1}, {230, 69}, {230, 74}, {230, 73}, {470, 71}, {250, -1}};
Player player = new Player();
for (int[] note : notes) {
if (note[1] != -1) {
player.playSound(0, note[0], 80, note[1]);
} else {
try {
Thread.sleep(note[0]);
} catch (InterruptedException ex) {
Logger.getLogger(Music.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
player.close();
В массиве пары чисел содержат величину длительности звучания и номер ноты. Паузу, для отличия, запишем «минус единицей». Канал и громкость оставим для всех нот одинаковые — 0 и 80 соответственно.
Что ж, полагаю у вас не возникло сложностей с пониманием изложенного материала. Буду рад, если эта статья сэкономит ваше время и силы, позволив с легкостью приступить к программированию воспроизведения MIDI звука на JAVA.