Spec-Zone .ru
спецификации, руководства, описания, API
|
ОтметитьС этими 5.0 выпусками есть новое в реальном времени |
В мире MIDI секвенсер является любыми аппаратными средствами или устройством программного обеспечения, которое может точно играть или записать последовательность сообщений MIDI с меткой времени. Точно так же в API Звука Java, Sequencer
абстрактный интерфейс определяет свойства объекта, который может играть и записать Sequences
из MidiEvent
объекты. A Sequencer
обычно загрузки они MidiEvent
последовательности от стандартного файла MIDI или сохраняют их к такому файлу. Последовательности могут также быть отредактированы. Эта глава объясняет, как использовать Sequencer
объекты, наряду со связанными классами и интерфейсами, чтобы выполнить такие задачи.
Разработать интуитивное понимание какой a Sequencer
думайте об этом по аналогии с магнитофоном, который секвенсер напоминает во многих отношениях. Принимая во внимание, что магнитофон играет аудио, секвенсер играет данные MIDI. Последовательность является многодорожечной, линейной, упорядоченной временем записью MIDI музыкальные данные, которые секвенсер может играть на различных скоростях, перемотке, шаттле к определенным точкам, записи в, или скопировать в файл для хранения.
Глава 10, "Передавая и Получая сообщения MIDI," объяснил, что устройства обычно имеют Receiver
объекты, Transmitter
объекты, или оба. Чтобы играть музыку, устройство обычно получает MidiMessages
через a Receiver
, который поочередно обычно получал их от a Transmitter
это принадлежит a Sequencer
. Устройство, которому принадлежит это Receiver
мог бы быть a Synthesizer
, который генерирует аудио непосредственно, или это мог бы быть выходной порт MIDI, который передает данные MIDI через физический кабель к некоторому внешнему элементу оборудования. Точно так же записывать музыку, серию с меткой времени MidiMessages
обычно отправляются a Receiver
принадлежавший a Sequencer
, который размещает их в a Sequence
объект. Обычно объект, отправляющий сообщения, является a Transmitter
связанный с аппаратным входным портом, и данными MIDI реле порта, которые это получает от внешнего инструмента. Однако, устройство, ответственное за отправку сообщений, могло бы вместо этого быть некоторым другим Sequencer
, или любое другое устройство, у которого есть a Transmitter
. Кроме того, как упомянуто в Главе 10, программа может отправить сообщения, не используя никого Transmitter
вообще.
A Sequencer
непосредственно имеет обоих Receivers
и Transmitters
. Когда это записывает, это фактически получает MidiMessages
через Receivers
. Во время воспроизведения это использует Transmitters
передаться MidiMessages
это сохранено в Sequence
то, что это записало (или загрузилось от файла).
Один способ думать о роли a Sequencer
в Java API Звука как агрегатор и "де-агрегатор" MidiMessages
. Серия отдельных MidiMessages
, каждый из которых независим, отправляется Sequencer
наряду с его собственной меткой времени, которая отмечает синхронизацию музыкального события. Они MidiMessages
инкапсулируются в MidiEvent
объекты и собранный в Sequence
объекты посредством действия Sequencer.record
метод. A Sequence
структура данных, содержащая, агрегируется MidiEvents
, и это обычно представляет серию музыкальных нот, часто вся песня или состав. На воспроизведении, Sequencer
снова извлечения MidiMessages
от MidiEvent
объекты в Sequence
и затем передает их к одному или более устройствам, которые или представят их в звуке, сохранят их, изменят их, или передадут их на некоторое другое устройство.
У некоторых секвенсеров не могло бы быть ни передатчиков, ни получателей. Например, они могли бы создать MidiEvents
с нуля в результате клавиатуры или событий от нажатия мыши, вместо получения MidiMessages
через Receivers
. Точно так же они могли бы играть музыку, связываясь непосредственно с внутренним синтезатором (который мог фактически быть тем же самым объектом как секвенсер) вместо отправки MidiMessages
к a Receiver
связанный с отдельным объектом. Однако, остальная часть этой главы принимает нормальный случай секвенсера, который использует Receivers
и Transmitters
.
Для прикладной программы возможно отправить сообщения MIDI непосредственно устройству, не используя секвенсер, как был описан в Главе 10, "Передавая и Получая сообщения MIDI." Программа просто вызывает Receiver.send
метод каждый раз это хочет отправить сообщение. Это - прямой подход, это полезно, когда сама программа создает сообщения в режиме реального времени. Например, рассмотрите программу, которая позволяет пользователю играть примечания, щелкая по экранной клавиатуре фортепьяно. Когда программа получает событие мыши вниз, она сразу отправляет соответствующее Сообщение На сообщении к синтезатору.
Как упомянуто в Главе 10, программа может включать метку времени с каждым сообщением MIDI, которое это отправляет получателю устройства. Однако, такие метки времени используются только для того, чтобы подстроить синхронизацию, исправить для того, чтобы обработать задержку. Вызывающая сторона не может обычно установить произвольные метки времени; временная стоимость, к которой передают Receiver.send
должен быть близко к настоящему времени, или устройство получения не могло бы быть в состоянии запланировать сообщение правильно. Это означает, что, если прикладная программа, требуемая, чтобы создать очередь MIDI, обменивается сообщениями для всей музыкальной пьесы загодя (вместо того, чтобы создать каждое сообщение в ответ на событие в реальном времени), это должно было бы очень делать все возможное запланировать каждый вызов Receiver.send
в течение почти правильного времени.
К счастью, большинство прикладных программ не должно касаться такого планирования. Вместо вызова Receiver.send
непосредственно, программа может использовать a Sequencer
объект управлять очередью MIDI обменивается сообщениями для этого. Секвенсер заботится о планировании и отправке сообщений — другими словами, играя музыку с корректной синхронизацией. Обычно, выгодно использовать секвенсер всякий раз, когда Вы должны преобразовать ряд нев реальном времени сообщений MIDI к ряду в реальном времени (как в воспроизведении), или наоборот (как в записи). Секвенсеры обычно используются для того, чтобы играть данные от файлов MIDI и для того, чтобы записать данные от входного порта MIDI.
Прежде, чем исследовать Sequencer
API, это помогает понять вид данных, это сохранено в последовательности.
В API Звука Java секвенсеры близко следуют за Стандартной спецификацией Файлов MIDI в способе, которым они организуют записанные данные MIDI. Как упомянуто выше, a Sequence
агрегация MidiEvents
, организованный вовремя. Но есть больше структуры к a Sequence
чем только линейная последовательность MidiEvents
: a Sequence
фактически содержит глобальную информацию о синхронизации плюс набор Tracks
, и это Tracks
непосредственно то хранение MidiEvent
данные. Таким образом, данные, играемые секвенсером, состоят из трехуровневой иерархии объектов: Sequencer
, Track
, и MidiEvent
.
В стандартном использовании этих объектов, Sequence
представляет полный музыкальный состав или раздел состава, с каждым Track
соответствие речи или проигрывателю в ансамбле. В этой модели, всех данных на детали Track
был бы также поэтому закодирован в определенный канал MIDI, зарезервированный для той речи или проигрывателя.
Этот способ организовать данные удобен в целях отредактировать последовательности, но отметьте, что это - только стандартный способ использовать Tracks
. Нет ничего в определении Track
класс по существу, который препятствует этому содержать соединение MidiEvents
на различных каналах MIDI. Например, весь многоканальный состав MIDI может быть смешан и записан на одного Track
. Кроме того, стандартные файлы MIDI Типа 0 (в противоположность Типу 1 и Типу 2) содержат по определению только одну дорожку; так a Sequence
это читается из такого файла, будет обязательно иметь сингл Track
объект.
Как обсуждено в Главе 8, "Краткий обзор Пакета MIDI," API Звука Java включает MidiMessage
объекты, которые соответствуют сырым данным два - или трехбайтовые последовательности, которые составляют большинство стандартных сообщений MIDI. A MidiEvent
просто упаковка a MidiMessage
наряду с сопроводительным значением синхронизации, которое определяет, когда событие имеет место. (Мы могли бы тогда сказать, что последовательность действительно состоит из четырех - или пятиуровневая иерархия данных, а не трехуровневый, потому что очевидный самый низкий уровень, MidiEvent
, фактически содержит низшего уровня MidiMessage
, и аналогично MidiMessage
объект содержит массив байтов, который включает стандартное сообщение MIDI.)
В API Звука Java есть два различных пути в который MidiMessages
может быть связан со значениями синхронизации. Каждый - путь, упомянутый выше под, "Когда Использовать Секвенсер." Этот метод описывается подробно при "Отправке сообщения к Получателю без Использования Передатчика" и "Понимания Меток времени" в Главе 10, "Передача и Получение сообщений MIDI." Там, мы видели что send
метод Receiver
берет a MidiMessage
параметр и параметр метки времени. В микросекундах может только быть выражена такая метка времени.
Другой путь тот, в который a MidiMessage
могли определить его синхронизацию, будучи инкапсулировавшимся в a MidiEvent
. В этом случае синхронизация выражается в немного более абстрактных модулях, названных галочками.
Какова продолжительность галочки? Это может измениться между последовательностями (но не в пределах последовательности), и ее значение сохранено в заголовке стандартного файла MIDI. Размер галочки дается в одном из двух типов модулей:
С другой стороны, в случае SMPTE, модули измеряют абсолютное время, и понятие темпа является неподходящим. Есть фактически четыре различных доступные соглашения SMPTE, которые обращаются к числу кадров в секунду кинофильма. Число кадров в секунду может быть 24, 25, 29.97, или 30. С временным кодом SMPTE размер галочки выражается как часть фрейма.
В API Звука Java можно вызвать Sequence.getDivisionType
учиться, какой тип модуля — а именно, PPQ или один из модулей SMPTE — используется в определенной последовательности. Можно тогда вычислить размер галочки после вызова Sequence.getResolution
. Последний метод возвращает число галочек на четвертную ноту, если тип подразделения является PPQ, или на фрейм SMPTE, если тип подразделения является одним из соглашений SMPTE. Можно получить размер галочки, используя эту формулу в случае PPQ:
ticksPerSecond = resolution * (currentTempoInBeatsPerMinute / 60.0); tickSize = 1.0 / ticksPerSecond;
framesPerSecond = (divisionType == Sequence.SMPTE_24 ? 24 : (divisionType == Sequence.SMPTE_25 ? 25 : (divisionType == Sequence.SMPTE_30 ? 30 : (divisionType == Sequence.SMPTE_30DROP ?
29.97)))); ticksPerSecond = resolution * framesPerSecond; tickSize = 1.0 / ticksPerSecond;
Определение API Звука Java синхронизации в последовательности зеркально отражает определение Стандартной спецификации Файлов MIDI. Однако, есть одно важное различие. Значения галочки, содержавшиеся в MidiEvents
измерьте совокупное время, а не время дельты. В стандартном файле MIDI информация о синхронизации каждого события измеряет количество времени, законченное начиная с начала предыдущего события в последовательности. Это вызывают временем дельты. Но в API Звука Java, галочки не являются значениями дельты; они - временная стоимость предыдущего события плюс значение дельты. Другими словами в API Звука Java значение синхронизации для каждого события всегда больше чем то из предыдущего события в последовательности (или равно, если события, как предполагается, одновременны). Значение синхронизации каждого события измеряет время, законченное с начала последовательности.
Чтобы подвести итог, API Звука Java выражает информацию о синхронизации или в галочках MIDI или в микросекунды. MidiEvents
храните информацию синхронизации с точки зрения галочек MIDI. Продолжительность галочки может быть вычислена от Sequence's
глобальная информация о синхронизации и, если последовательность использует основанную на темпе синхронизацию, текущий музыкальный темп. Метка времени связалась с a MidiMessage
отправленный a Receiver
, с другой стороны, всегда выражается в микросекундах.
Одна цель этого проекта состоит в том, чтобы избежать конфликтных понятий времени. Это - задание a Sequencer
интерпретировать единицы измерения времени в MidiEvents
, который мог бы иметь модули PPQ, и преобразовать их в абсолютное время в микросекундах, принимая текущий темп во внимание. Секвенсер должен также выразить микросекунды относительно времени, когда устройство, получающее сообщение, было открыто. Отметьте, что у секвенсера могут быть многократные передатчики, каждый передающий сообщения к различному получателю, который мог бы быть связан с абсолютно различным устройством. Можно видеть, тогда, что секвенсер должен быть в состоянии выполнить многократные преобразования одновременно, удостоверяясь, что каждое устройство получает метки времени, подходящие для его понятия времени.
Чтобы сделать вопросы, более сложные, различные устройства могли бы обновить свои понятия времени, основанного на различных источниках (таких как часы операционной системы, или часы, сохраняемые звуковой платой). Это означает, что их синхронизации могут дрейфовать относительно секвенсера. Чтобы сохранить в синхронизации с секвенсером, некоторые устройства разрешают себе быть "ведомыми устройствами" понятия секвенсера времени. Установка ведущих устройств и ведомых устройств обсуждается позже при "использовании Усовершенствованных Функций Секвенсера."
Sequencer
интерфейс обеспечивает методы в нескольких категориях:
Sequence
объект, и сохранять в настоящий момент загруженные данные последовательности к файлу MIDI. Sequence
. Sequencer
может играть в различных темпах, с некоторыми Tracks
с отключенным звуком, и в различной синхронизации утверждает с другими объектами. Sequencer
определенные виды процессов событий MIDI.
Sequencer
методы, которые Вы вызовете, первый шаг, должны получить a Sequencer
устройство от системы и резерва это для использования Вашей программы.
Прикладная программа не инстанцирует a Sequencer
; в конце концов, Sequencer
только интерфейс. Вместо этого как все устройства в пакете MIDI API Звука Java, a Sequencer
получается доступ через помехи MidiSystem
объект. Как упомянуто в Главе 9, "Получая доступ к Системным ресурсам MIDI," следующий MidiSystem
метод может использоваться, чтобы получить значение по умолчанию Sequencer
:
static Sequencer getSequencer()
Следующий фрагмент кода получает значение по умолчанию Sequencer
, получает любые системные ресурсы, в которых это нуждается, и делает это операционным:
Sequencer sequencer; // Get default sequencer. sequencer = MidiSystem.getSequencer(); if (sequencer == null) { // Error -- sequencer device is not supported. // Inform user and return... } else { // Acquire resources and make operational. sequencer.open(); }
Вызов open
резервирует устройство секвенсера для использования Вашей программы. Не имеет большого количества смысла предполагать совместно использовать секвенсер, потому что это может играть только одну последовательность за один раз. Когда Вы делаетесь, используя секвенсер, можно сделать его доступным для других программ, вызывая close
.
Секвенсеры не по умолчанию могут быть получены как описано в Главе 9, "Получая доступ к Системным ресурсам MIDI."
Получив секвенсер из системы и зарезервированный это, Вы тогда должны загрузить данные, которые должен играть секвенсер. Есть три типичных способа выполнить это:
MidiEvent
объекты к тем дорожкам
InputStream
то, что Вы тогда читаете непосредственно в секвенсер посредством Sequencer.setSequence(InputStream)
. С этим подходом Вы явно не создаете a Sequence
объект. Фактически, Sequencer
реализация не могла бы даже создать a Sequence
негласно, потому что у некоторых секвенсеров есть встроенный механизм для того, чтобы обработать данные непосредственно от файла. Другой подход должен создать a Sequence
явно. Вы должны будете использовать этот подход, если Вы соберетесь отредактировать данные последовательности прежде, чем играть его. С этим подходом Вы вызываете MidiSystem's
перегруженный метод getSequence
. Метод в состоянии получить последовательность от InputStream
, a File
, или a URL
. Метод возвращает a Sequence
объект, который может тогда быть загружен в a Sequencer
для воспроизведения. Подробно останавливаясь на предыдущей выборке кода, вот пример получения a Sequence
объект от a File
и загрузка этого в наш sequencer
:
try { File myMidiFile = new File("seq1.mid"); // Construct a Sequence object, and // load it into my sequencer. Sequence mySeq = MidiSystem.getSequence(myMidiFile); sequencer.setSequence(mySeq); } catch (Exception e) { // Handle error and/or return }
Как MidiSystem's
getSequence
метод, setSequence
может бросить InvalidMidiDataException
— и, в случае InputStream
разновидность, IOException
— если это сталкивается с проблемой.
Запуск и остановка a Sequencer
выполняется, используя следующие методы:
void start()
void stop()
Sequencer.start
метод начинает воспроизведение последовательности. Отметьте, что воспроизведение запускается в текущей позиции в последовательности. Загрузка существующей последовательности, используя setSequence
метод, описанный выше, инициализирует текущую позицию секвенсера к самому началу последовательности. stop
метод останавливает секвенсер, но это автоматически не перематывает ток Sequence
. Запуск остановленного Sequence
не сбрасывая позицию просто возобновляет воспроизведение последовательности от текущей позиции. В этом случае, stop
метод служил работой паузы. Однако, там являются различными Sequencer
методы для того, чтобы установить текущую позицию последовательности в произвольное значение перед воспроизведением запускаются. (Мы обсудим эти методы ниже.)
Как отмечалось ранее, a Sequencer
обычно имеет один или больше Transmitter
объекты, через которые это передается MidiMessages
к a Receiver
. Это через них Transmitters
это a Sequencer
игры Sequence
, испуская соответственно синхронизированный MidiMessages
это соответствует MidiEvents
содержавшийся в токе Sequence
. Поэтому, часть процедуры установки для того, чтобы воспроизвести a Sequence
должен вызвать setReceiver
метод на Sequencer's
Transmitter
объект, в действительности соединяя его вывод проводом к устройству, которое использует назад играемые данные. Для получения дополнительной информации на Transmitters
и Receivers
, см. Главу 10, "Передавая и Получая сообщения MIDI."
Получать данные MIDI к a Sequence
, и впоследствии к файлу, Вы должны выполнить некоторые дополнительные шаги вне описанных выше. Следующая схема показывает шаги, необходимые, чтобы установить для того, чтобы записать к a Track
в a Sequence
:
MidiSystem.getSequencer
заставить новый секвенсер использовать для того, чтобы записать, как выше. setReceiver
метод, чтобы отправить данные a Receiver
связанный с записью Sequencer
. Sequence
объект, который будет хранить записанные данные. Когда Вы создаете Sequence
объект, следует определить глобальную информацию о синхронизации для последовательности. Например: Sequence mySeq; try{ mySeq = new Sequence(Sequence.PPQ, 10); } catch (Exception ex) { ex.printStackTrace(); }Конструктор для
Sequence
берет в качестве параметров a divisionType
и разрешение синхронизации. divisionType
параметр определяет модули параметра разрешения. В этом случае мы определили что разрешение синхронизации Sequence
мы создаем, будут 10 импульсов на четвертную ноту. Дополнительный дополнительный параметр Sequence
конструктор является многим параметром дорожек, который заставил бы начальную последовательность начинаться с конкретного количества (первоначально пустой) Tracks
. Иначе Sequence
будет создаваться без начальной буквы Tracks
; они могут быть добавлены позже как необходимый. Track
в Sequence
, с Sequence.createTrack
. Этот шаг является ненужным если Sequence
создавался с начальной буквой Tracks
. Sequencer.setSequence
, выберите наше новое Sequence
получить запись. setSequence
метод связывает существующее Sequence
с Sequencer
, который несколько походит на загрузку ленты на магнитофон. Sequencer.recordEnable
для каждого Track
быть записанным. В случае необходимости получите ссылку на доступное Tracks
в Sequence
вызывая Sequence.getTracks
. startRecording
на Sequencer
. Sequencer.stop
или Sequencer.stopRecording
. Sequence
к файлу MIDI с MidiSystem.write
. write
метод MidiSystem
берет a Sequence
как один из его параметров, и запишет это Sequence
к потоку или файлу.Много прикладных программ позволяют последовательности создаваться, загружая это из файла, и довольно многие также позволяют последовательности создаваться, получая это от живого ввода MIDI (то есть, записывая). Некоторые программы, однако, должны будут создать последовательности MIDI с нуля, или программно или в ответ на ввод данных пользователем. Полнофункциональные программы секвенсера разрешают пользователю вручную создавать новые последовательности, так же как редактировать существующие.
Эти редактирующие данные операции достигаются в API Звука Java не Sequencer
методы, но методами объектов данных непосредственно: Sequence
, Track
, и MidiEvent
. Можно создать пустую последовательность, используя один из Sequence
конструкторы, и затем добавляют дорожки к этому, вызывая следующий Sequence
метод:
Track createTrack()Если Ваша программа позволит пользователю редактировать последовательности, то Вы будете нуждаться в этом
Sequence
метод, чтобы удалить дорожки: boolean deleteTrack(Track track)
Как только последовательность содержит дорожки, можно изменить содержание дорожек, вызывая методы Track
класс. MidiEvents
содержавшийся в Track
сохранены как a java.util.Vector
в Track
объект, и Track
обеспечивает ряд методов для того, чтобы он получил доступ, добавил, и удалил события в списке. Методы add
и remove
довольно очевидны, добавляя или удаляя указанное MidiEvent
от a Track
. A get
метод обеспечивается, который берет индекс в Track's
список событий и возвраты MidiEvent
сохраненный там. Кроме того, есть size
и tick
методы, которые соответственно возвращают число MidiEvents
в дорожке, и продолжительности дорожки, выраженной как общее количество Ticks
.
Чтобы создать новое событие прежде, чем добавить это к дорожке, Вы будете, конечно, использовать MidiEvent
конструктор. Чтобы определить или изменить сообщение MIDI, встроенное в конечном счете, можно вызвать setMessage
метод соответствующего MidiMessage
подкласс (ShortMessage
, SysexMessage
, или MetaMessage
). Чтобы изменить время, когда событие должно иметь место, вызвать MidiEvent.setTick
.
В комбинации эти низкоуровневые методы обеспечивают основание для функциональности редактирования, необходимой полнофункциональной программе секвенсера.
До сих пор эта глава сосредоточилась на простом воспроизведении и записи данных MIDI. Этот раздел кратко опишет некоторые большего количества расширенных функций, доступных через методы Sequencer
взаимодействуйте через интерфейс и Sequence
класс.
Есть два Sequencer
методы, которые получают текущую позицию секвенсера в последовательности. Первый из них:
long getTickPosition()
возвращает позицию, измеренную в галочках MIDI с начала последовательности. Второй метод:
long getMicrosecondPosition()
возвращает текущую позицию в микросекундах. Этот метод предполагает, что последовательность играется на уровне по умолчанию как сохраненный в файле MIDI или в Sequence
. Это не возвращает различное значение, если Вы изменили скорость воспроизведения как описано ниже.
Можно так же установить текущую позицию секвенсера согласно одному модулю или другому:
void setTickPosition(long tick)
void setMicrosecondPosition(long microsecond)
Как обозначено ранее, скорость последовательности обозначается ее темпом, который может измениться в течение последовательности. Последовательность может содержать события, которые инкапсулируют стандартные сообщения изменения темпа MIDI. Когда секвенсер обрабатывает такое событие, он изменяет скорость воспроизведения, чтобы отразить обозначенный темп. Кроме того, можно программно изменить темп, вызывая любой из них Sequencer
методы:
public void setTempoInBPM(float bpm) public void setTempoInMPQ(float mpq) public void setTempoFactor(float factor)Первые два из этих методов набор темп в ударах в минуту или микросекунды на четвертную ноту, соответственно. Темп останется в указанном значении, пока один из этих методов не будет вызван снова, или пока с событием изменения темпа встречаются в последовательности, в которой точке текущий темп переопределяется недавно указанным.
Третий метод, setTempoFactor
, отличается в природе. Это масштабируется, любой темп устанавливается для секвенсера (ли событиями изменения темпа или одним из первых двух методов выше). Скаляр по умолчанию 1.0 (никакое изменение). Хотя этот метод заставляет воспроизведение или записывающий быть быстрее или медленнее чем номинальный темп (если фактор не 1.0), это не изменяет номинальный темп. Другими словами, значения темпа, возвращенные getTempoInBPM
и getTempoInMPQ
незатронуты фактором темпа, даже при том, что фактор темпа действительно влияет на фактический уровень воспроизведения или записи. Кроме того, если темп изменяется событием изменения темпа или на один из первых двух методов, это все еще масштабируется любым фактором темпа, был последний набор. Если Вы загружаете новую последовательность, однако, фактор темпа сбрасывается к 1.0.
Отметьте, что все эти директивы изменения темпа неэффективны, когда тип подразделения последовательности является одним из типов SMPTE вместо PPQ.
Часто удобно для пользователей секвенсеров быть в состоянии выключить определенные дорожки, услышать более ясно точно, что происходит в музыке. Полнофункциональная программа секвенсера позволяет пользователю выбирать, какие дорожки должны звучать во время воспроизведения. (Говорящий более точно, так как секвенсеры фактически не создают, звучат как себя, пользователь выбирает, какие дорожки будут способствовать потоку сообщений MIDI, что секвенсер производит.) Как правило, есть два типа графических средств управления на каждой дорожке: бесшумная кнопка и сольная кнопка. Если бесшумная кнопка будет активирована, то та дорожка не будет звучать ни при каких обстоятельствах, пока бесшумная кнопка не будет деактивирована. Soloing является менее известной функцией. Это - примерно противоположность отключения звука. Если сольная кнопка на какой-либо дорожке будет активирована, то только дорожки, сольные кнопки которых активируются, будут звучать. Эта функция позволяет пользователю быстро прослушивать небольшое количество дорожек, не имея необходимость отключать звук всех других дорожек. Бесшумная кнопка обычно берет приоритет над сольной кнопкой: если оба активируются, дорожка не звучит.
Используя Sequencer
методы, дорожки отключения звука или soloing (так же как запросы бесшумного тока дорожки или сольное состояние) легко выполняются. Давайте предполагать, что мы получили значение по умолчанию Sequencer
и это мы загрузили данные последовательности в это. Отключение звука пятой дорожки в последовательности было бы выполнено следующим образом:
sequencer.setTrackMute(4, true); boolean muted = sequencer.getTrackMute(4); if (!muted) { return; // muting failed }Есть несколько вещей отметить о вышеупомянутом фрагменте кода. Во-первых, дорожки последовательности нумеруются, запускаясь с 0 и заканчиваясь общим количеством дорожек минус 1. Кроме того, второй параметр
setTrackMute
булевская переменная. Если это - истина, запрос должен отключить звук дорожки; иначе запрос должен неотключить звук указанной дорожки. Наконец, чтобы протестировать это, отключение звука вступило в силу, мы вызываем Sequencer getTrackMute
метод, передавая это число дорожки мы запрашиваем. Если это возвращается true
, поскольку мы ожидали бы в этом случае, тогда бесшумный работавший запрос. Если это возвращается false
, тогда это перестало работать. Бесшумные запросы могут перестать работать по различным причинам. Например, число дорожки, определенное в setTrackMute
вызов мог бы превысить общее количество дорожек, или секвенсер не мог бы поддерживать отключение звука. Вызывая getTrackMute
, мы можем определить если наш запрос, за которым следуют или отказавший.
Как в стороне, булевская переменная это возвращается getTrackMute
может, действительно, сказать нам, если отказ произошел, но он не может сказать нам, почему он произошел. Мы могли протестировать, чтобы видеть, был ли отказ вызван, передавая недопустимое число дорожки к setTrackMute
метод. Чтобы сделать это, мы вызвали бы getTracks
метод Sequence
, который возвращает массив, содержащий все дорожки в последовательности. Если число дорожки, определенное в setTrackMute
вызов превышает длину этого массива, тогда мы знаем, что определили недопустимое число дорожки.
Если бесшумный запрос успешно выполнялся, то в нашем примере, пятая дорожка не будет звучать, когда последовательность будет играть, ни будут любые другие дорожки, которые в настоящий момент отключаются звук.
Метод и методы для soloing дорожка очень подобны тем для того, чтобы отключить звук. К соло дорожка вызовите setTrackSolo
метод Sequence:
void setTrackSolo(int track, boolean bSolo)Как в
setTrackMute
, первый параметр определяет основанное на нуле число дорожки, и второй параметр, если true
, определяет, что дорожка должна быть в сольном режиме; иначе дорожка не должна быть soloed. По умолчанию дорожка ни не отключается звук, ни soloed.
Sequencer
вызывали внутренний класс Sequencer.SyncMode
. A SyncMode
объект представляет один из путей, которыми понятие секвенсера MIDI времени может синхронизироваться с основным или ведомым устройством. Если секвенсер синхронизируется с ведущим устройством, секвенсер пересматривает свое текущее время в ответ на определенные сообщения MIDI от ведущего устройства. Если у секвенсера есть ведомое устройство, секвенсер так же отправляет сообщения MIDI, чтобы управлять синхронизацией ведомого устройства.
Есть три предопределенных режима, которые определяют возможные ведущие устройства для секвенсера: INTERNAL_CLOCK
, MIDI_SYNC
, и MIDI_TIME_CODE
. Последние два работают, если секвенсер получает сообщения MIDI от другого устройства. В этих двух режимах время секвенсера сбрасывается основанное на системе сообщения часов синхронизации в реальном времени или временной код MIDI (MTC) сообщения, соответственно. (См. спецификацию MIDI для получения дополнительной информации об этих типах сообщения.) Эти два режима могут также использоваться в качестве ведомых режимов, когда секвенсер отправляет соответствующие типы сообщений MIDI к его получателю. Четвертый режим, NO_SYNC
, используется, чтобы указать, что секвенсер не должен отправить информацию о синхронизации своим получателям.
Вызывая setMasterSyncMode
метод с поддерживаемым SyncMode
возразите как параметр, можно определить, как синхронизацией секвенсера управляют. Аналогично, setSlaveSyncMode
метод определяет, какую информацию о синхронизации секвенсер отправит его получателям. Эта информация управляет синхронизацией устройств, которые используют секвенсер в качестве основного источника синхронизации.
Каждая дорожка последовательности может содержать много различных видов MidiEvents
. Такие события включают Примечание По и Примечание От сообщений, изменений программы, управляют изменениями, и метасобытиями. API Звука Java определяет интерфейсы "слушателя" для последних двух из этих типов события (события изменения управления и метасобытия). Можно использовать эти интерфейсы, чтобы получить уведомления, когда такие события имеют место во время воспроизведения последовательности.
Объекты, которые поддерживают ControllerEventListener
интерфейс может получить уведомление когда a Sequencer
процессы определенные сообщения изменения управления. Сообщение изменения управления является стандартным типом сообщения MIDI, которое представляет изменение в значении контроллера MIDI, такого как колесо изгиба подачи или ползунок данных. (См. спецификацию MIDI для полного списка сообщений изменения управления.), Когда такое сообщение обрабатывается во время воспроизведения последовательности, сообщение сообщает любому устройству (вероятно, синтезатор), это получает данные от секвенсера, чтобы обновить значение некоторого параметра. Параметр обычно управляет некоторым аспектом синтеза звука, такого как подача в настоящий момент звучащих примечаний, если контроллер был колесом изгиба подачи. Когда последовательность записывается, сообщение изменения управления означает, что контроллер на внешнем физическом устройстве, которое создало сообщение, был перемещен, или что такое перемещение было моделировано в программном обеспечении.
Вот то, как ControllerEventListener
интерфейс используется. Давайте предполагать, что Вы разработали класс, который реализует ControllerEventListener
интерфейс, означая, что Ваш класс содержит следующий метод:
void controlChange(ShortMessage msg)Также давайте предполагать, что Вы создали экземпляр своего класса и присвоили его вызванной переменной
myListener
. Если Вы включаете следующие операторы где-нибудь в пределах Вашей программы: int[] controllersOfInterest = { 1, 2, 4 }; sequencer.addControllerEventListener(myListener, controllersOfInterest);тогда Ваш класс
controlChange
метод будет вызван каждый раз, когда секвенсер обрабатывает сообщение изменения управления для контроллера MIDI номера 1, 2, или 4. Другими словами, когда Sequencer
обрабатывает запрос, чтобы установить значение любого из зарегистрированных контроллеров, Sequencer
вызовет Ваш класс controlChange
метод. (Отметьте, что присвоения чисел контроллера MIDI к определенным управляющим устройствам детализируются в MIDI 1.0 Спецификации.) controlChange
метод передают a ShortMessage
содержа число контроллера, на которое влияют, и новое значение, в которое был установлен контроллер. Можно получить число контроллера, используя ShortMessage.getData1
метод, и новая установка значения контроллера, используя ShortMessage.getData2
метод.
Другой вид слушателя специального мероприятия определяется MetaEventListener
интерфейс. Сообщения Меты, согласно Стандартным Файлам MIDI 1.0 спецификации, являются сообщениями, которые не присутствуют в протоколе провода MIDI, но это может быть встроено в файл MIDI. Они не значимы для синтезатора, но могут быть интерпретированы секвенсером. Сообщения Меты включают инструкции (такие как команды изменения темпа), лирика или другой текст, и другие индикаторы (такие как конец дорожки).
MetaEventListener
механизм походит ControllerEventListener
. Реализуйте MetaEventListener
интерфейс в любом классе, экземпляры которого должны быть уведомлены когда a MetaMessage
обрабатывается секвенсером. Это включает добавление следующего метода к классу:
void meta(MetaMessage msg)
Вы регистрируете экземпляр этого класса, передавая это как параметр Sequencer addMetaEventListener
метод:
boolean b = sequencer.addMetaEventListener (myMetaListener);Это немного отличается от подхода, проявленного
ControllerEventListener
интерфейс, потому что необходимо зарегистрироваться, чтобы получить все MetaMessages,
не только выбранные интереса. Если секвенсер встречается с a MetaMessage
в его последовательности это вызовет myMetaListener.meta
, передача этого MetaMessage
встреченный. meta
метод может вызвать getType
на MetaMessage
параметр, чтобы получить целое число от 0 до 127, который указывает на тип сообщения, как определено Стандартными Файлами MIDI 1.0 спецификации.