с микрофона, линейного входа, синтезатора,
Синтез и запись звука в Java 2
Синтез звука заключается в создании MIDI-последовательности — объекта класса sequence — каким-либо способом: с микрофона, линейного входа, синтезатора, из файла, или просто создать в программе, как это делается в листинге 15.18.
Сначала создается пустая последовательность одним из двух конструкторов:
Sequence(float divisionType, int resolution)
Sequence(float divisionType, int resolution, int numTracks)
Первый аргумент divisionType определяет способ отсчета моментов (ticks) MIDI-событий — это одна из констант:
-
PPQ
(Pulses Per Quarter note) — отсчеты замеряются в долях от длительности звука в четверть;
-
SMPTE_24, SMPTE_25, SMPTE_so, SMPTE_30DROP
(Society of Motion Picture and Television Engineers) — отсчеты в долях одного кадра, при указанном числе кадров в секунду.
Второй аргумент resolution задает количество отсчетов в указанную единицу, например,
Sequence seq = new Sequence)Sequence.PPQ, 10);
задает 10 отсчетов в звуке длительностью в четверть.
Третий аргумент numTracks определяет количество дорожек в MIDI-после-довательности.
Потом, если применялся первый конструктор, в последовательности создается одна или несколько дорожек:
Track tr = seq.createTrack()
;
Если применялся второй конструктор, то надб получить уже созданные конструктором дорожки:
Track[] trs = seq.getTracks();
Затем дорожки заполняются MIDI-событиями с помощью MIDl-сообще-ний. Есть несколько типов сообщений для разных типов событий. Наиболее часто встречаются сообщения типа shortMessage, которые создаются конструктором по умолчанию и потом заполняются методом setMessageo:
ShortMessage msg = new ShortMessage();
rasg.setMessage(ShortMessage.NOTEJDN, 60, 93);
Первый аргумент указывает тип сообщения:
NOTE_ON
— начать звучание,
NOTE_OFF
— прекратить звучание и т. д. Второй аргумент для типа
NOTE_ОN
показывает высоту звука, в стандарте MIDI это числа от 0 до 127, 60 — нота "до" первой октавы. Третий аргумент означает "скорость" нажатия клавиши MIDI-инструмента и по-разному понимается различными устройствами.
Далее создается MIDI-событие:
MidiEvent me = new MidiEvent{msg, ticks);
Первый аргумент конструктора msg — это сообщение, второй аргумент ticks — время наступления события (в нашем примере проигрывания ноты "до") в единицах последовательности seq (в нашем примере в десятых долях четверти). Время отсчитывается от начала проигрывания последовательности.
Наконец, событие заносится на дорожку:
tr.add(me);
Указанные действия продолжаются, пока все дорожки не будут заполнены всеми событиями. В листинге 15.18 это делается в цикле, но обычно MIDI-события создаются в методах обработки нажатия клавиш на обычной или специальной MIDI-клавиатуре. Еще один способ — вывести на экран изображение клавиатуры и создавать MIDI-собьгшя в методах обработки нажатий кнопки мыши на этой клавиатуре.
После создания последовательности ее можно проиграть, как в листинге 15.17, или записать в файл или выходной поток. Для этого вместо метода start() надо применить метод startRecording (), который одновременно и проигрывает последовательность, и подготавливает ее к записи, которую осуществляют статические методы:
write(Sequence in, int type, File out)
write(Sequence in, int type, OutputStream out)
Второй аргумент type задает тип MIDI-файла, который лучше всего определить для заданной последовательности seq статическим методом getMidiFiieTypes(seq). Данный метод возвращает массив возможных типов. Надо воспользоваться нулевым элементом массива, ,Все это. показало в листинге 15.18.
Содержание раздела