Spec-Zone .ru
спецификации, руководства, описания, API
Содержание документации

<Содержание

Глава 11: Игра, Запись и Редактирование Последовательностей MIDI

 

Отметить

С этими 5.0 выпусками есть новое в реальном времени Sequencer (реализация), которая работает со всеми устройствами Midi и через getTransmitter() метод, неограниченное количество передатчиков может быть получено. До этого выпуска не было возможно получить a Transmitter от a Sequencer.


В мире 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 class по существу, который препятствует этому содержать соединение MidiEvents на различных каналах MIDI. Например, весь многоканальный состав MIDI может быть смешан и записан на одного Track. Кроме того, стандартные файлы MIDI Типа 0 (в противоположность Типу 1 и Типу 2) содержат по определению только одну дорожку; так a Sequence это читается из такого файла, будет обязательно иметь сингл Track объект.

MidiEvents и Галочки

Как обсуждено в Главе 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. Размер галочки дается в одном из двух типов модулей:

Если модуль является PPQ, размер галочки выражается как часть четвертной ноты, которая является родственником, не абсолютным, временная стоимость. Четвертная нота является музыкальным значением продолжительности, которое часто соответствует одному удару музыки (четверть меры в 4/4 время). Продолжительность четвертной ноты зависит от темпа, который может измениться в течение музыки, если последовательность содержит события изменения темпа. Так, если синхронизация последовательности постепенно увеличивается (отсчитывает), происходят, говорят 96 раз на четвертную ноту, меры по значению синхронизации каждого события что позиция события в музыкальных терминах, не как абсолютная временная стоимость.

С другой стороны, в случае 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;

и эта формула в случае SMPTE:

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 интерфейс обеспечивает методы в нескольких категориях:

Независимо от которого 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."

Загрузка Последовательности

Получив секвенсер из системы и зарезервированный это, Вы тогда должны загрузить данные, которые должен играть секвенсер. Есть три типичных способа выполнить это:

Мы будем теперь смотреть на первый из этих способов получить данные последовательности. (Другие два пути описываются позже при "Записи и Сохранении Последовательностей" и "Редактировании Последовательности," соответственно.) Этот первый путь фактически охватывает два немного отличающихся подхода. Один подход должен подать данные файла MIDI к 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:

  1. Использовать MidiSystem.getSequencer заставить новый секвенсер использовать для того, чтобы записать, как выше.
  2. Установите "проводное соединение" соединений MIDI. Объект, который передает данные MIDI, которые будут записаны, должен быть сконфигурирован через setReceiver метод, чтобы отправить данные a Receiver связанный с записью Sequencer.
  3. Создайте новое 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; они могут быть добавлены позже как необходимый.
  4. Создайте пустое Track в Sequence, с Sequence.createTrack. Этот шаг является ненужным если Sequence создавался с начальной буквой Tracks.
  5. Используя Sequencer.setSequence, выберите наше новое Sequence получить запись. setSequence метод связывает существующее Sequence с Sequencer, который несколько походит на загрузку ленты на магнитофон.
  6. Вызвать Sequencer.recordEnable для каждого Track быть записанным. В случае необходимости получите ссылку на доступное Tracks в Sequence вызывая Sequence.getTracks.
  7. Вызвать startRecording на Sequencer.
  8. Когда сделано записывая, вызвать Sequencer.stop или Sequencer.stopRecording.
  9. Сохраните записанный 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 class. 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 class.

Перемещение в Произвольную Позицию в Последовательности

Есть два 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.

Отключение звука или Отдельные Дорожки Soloing в Последовательности

Часто удобно для пользователей секвенсеров быть в состоянии выключить определенные дорожки, услышать более ясно точно, что происходит в музыке. Полнофункциональная программа секвенсера позволяет пользователю выбирать, какие дорожки должны звучать во время воспроизведения. (Говорящий более точно, так как секвенсеры фактически не создают, звучат как себя, пользователь выбирает, какие дорожки будут способствовать потоку сообщений 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.

Синхронизация с Другими MIDI-устройствами

Sequencer вызывали внутренний class 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 интерфейс используется. Давайте предполагать, что Вы разработали class, который реализует ControllerEventListener интерфейс, означая, что Ваш class содержит следующий метод:

    void controlChange(ShortMessage msg)
Также давайте предполагать, что Вы создали экземпляр своего class и присвоили его вызванной переменной myListener. Если Вы включаете следующие операторы где-нибудь в пределах Вашей программы:
    int[] controllersOfInterest = { 1, 2, 4 };
    sequencer.addControllerEventListener(myListener,
        controllersOfInterest);
тогда Ваш class controlChange метод будет вызван каждый раз, когда секвенсер обрабатывает сообщение изменения управления для MIDI-контроллера номера 1, 2, или 4. Другими словами, когда Sequencer обрабатывает запрос, чтобы установить значение любого из зарегистрированных контроллеров, Sequencer вызовет Ваш class controlChange метод. (Отметьте, что присвоения чисел MIDI-контроллера к определенным управляющим устройствам детализируются в MIDI 1.0 Спецификации.)

controlChange метод передают a ShortMessage содержа число контроллера, на которое влияют, и новое значение, в которое был установлен контроллер. Можно получить число контроллера, используя ShortMessage.getData1 метод, и новая установка значения контроллера, используя ShortMessage.getData2 метод.

Другой вид слушателя специального мероприятия определяется MetaEventListener интерфейс. Сообщения Меты, согласно Стандартным Файлам MIDI 1.0 спецификации, являются сообщениями, которые не присутствуют в протоколе провода MIDI, но это может быть встроено в файл MIDI. Они не значимы для синтезатора, но могут быть интерпретированы секвенсером. Сообщения Меты включают инструкции (такие как команды изменения темпа), лирика или другой текст, и другие индикаторы (такие как конец дорожки).

MetaEventListener механизм походит ControllerEventListener. Реализуйте MetaEventListener интерфейс в любом class, экземпляры которого должны быть уведомлены когда a MetaMessage обрабатывается секвенсером. Это включает добавление следующего метода к class:

void meta(MetaMessage msg)

Вы регистрируете экземпляр этого class, передавая это как параметр Sequencer addMetaEventListener метод:

boolean b = sequencer.addMetaEventListener
        (myMetaListener);
Это немного отличается от подхода, проявленного ControllerEventListener интерфейс, потому что необходимо зарегистрироваться, чтобы получить все MetaMessages, не только выбранные интереса. Если секвенсер встречается с a MetaMessage в его последовательности это вызовет myMetaListener.meta, передача этого MetaMessage встреченный. meta метод может вызвать getType на MetaMessage параметр, чтобы получить целое число от 0 до 127, который указывает на тип сообщения, как определено Стандартными Файлами MIDI 1.0 спецификации.

 


Oracle и/или его филиалы Авторское право © 1993, 2012, Oracle и/или его филиалы. Все права защищены.
Свяжитесь с Нами