Spec-Zone .ru
спецификации, руководства, описания, API
|
Большинство программ, которые пользуются пакетом MIDI API Звука Java, делает так, чтобы синтезировать звук. У всего аппарата файлов MIDI, событий, последовательностей, и секвенсеров, который был обсужден в других главах, почти всегда есть цель в конечном счете отправки музыкальных данных к синтезатору, чтобы преобразовать в аудио. (Возможные исключения включают программы, которые преобразовывают MIDI в музыкальную нотацию, которая может быть считана музыкантом, и программами, которые отправляют сообщения внешним УПРАВЛЯЕМЫМ MIDI устройствам, таким как смешивающиеся консоли.)
Synthesizer
интерфейс является поэтому основным принципом к пакету MIDI. Эта глава показывает, как управлять синтезатором, чтобы играть звук. Много программ будут просто использовать секвенсер, чтобы отправить данные файла MIDI синтезатору, и не должны будут вызвать многих Synthesizer
методы непосредственно. Однако, возможно управлять синтезатором непосредственно, не используя секвенсеры или даже MidiMessage
объекты, как объяснено около конца этой главы.
Архитектура синтеза могла бы казаться сложной для читателей, которые незнакомы с MIDI. Его API включает три интерфейса:
и четыре класса: Как ориентация для всего этого API, следующий раздел объясняет некоторые из основ синтеза MIDI и как они отражаются в API Звука Java. (Также см. краткий раздел "Синтезаторы" под "Представлением API Звука Java Устройств MIDI" в Главе 8, "Краткий обзор Пакета MIDI."), Последующие разделы дают более подробный взгляд на API.Как синтезатор генерирует звук? В зависимости от его реализации это может использовать один или методы более синтеза звука. Например, много синтезаторов используют wavetable синтез. wavetable синтезатор читает сохраненные отрывки аудио из памяти, играя их на различных демонстрационных уровнях и цикличном выполнении их, чтобы создать примечания различных передач и продолжительностей. Например, чтобы синтезировать звук саксофона, играя примечание C#4 (примечание MIDI номер 61), синтезатор мог бы получить доступ к очень короткому отрывку от записи саксофона, играя Середину примечания C (примечание MIDI номер 60), и затем цикл неоднократно через этот отрывок на немного более быстром демонстрационном уровне, чем это было записано в, который создает длинное примечание немного более высокой подачи. Другие синтезаторы используют методы, такие как модуляция частоты (FM), аддитивный синтез, или физическое моделирование, которое не использует сохраненное аудио, но вместо этого генерирует аудио, с нуля используя различные алгоритмы.
Что имеют все методы синтеза, вместе возможность создать много видов звуков. Различные алгоритмы, или различные настройки параметров в пределах того же самого алгоритма, создают различно звучащие результаты. Инструмент является спецификацией для того, чтобы синтезировать определенный тип звука. Тот звук может эмулировать традиционный музыкальный инструмент, такой как фортепьяно или скрипка; это может эмулировать некоторый другой вид звукового источника, например, телефона или вертолета; или это не может эмулировать "реальный" звук вообще. Спецификация под названием Общий MIDI определяет стандартный список 128 инструментов, но большинство синтезаторов позволяет другие инструменты также. Много синтезаторов обеспечивают набор встроенных инструментов, которые всегда доступны для использования; некоторые синтезаторы также поддерживают механизмы для того, чтобы загрузить дополнительные инструменты.
Инструмент может быть специфичным для поставщика — другими словами, применимым только к одному синтезатору или нескольким моделям от того же самого поставщика. Эта несовместимость заканчивается, когда два различных синтезатора используют различные методы синтеза звука, или различные внутренние алгоритмы и параметры, даже если фундаментальный метод является тем же самым. Поскольку детали метода синтеза являются часто собственными, несовместимость распространена. API Звука Java включает способы обнаружить, поддерживает ли данный синтезатор данный инструмент.
Инструмент можно обычно считать предварительной установкой; Вы ничего не должны знать о деталях метода синтеза, который производит его звук. Однако, можно все еще изменить аспекты его звука. Каждое Примечание По сообщению определяет подачу и объем отдельного примечания. Можно также изменить звук посредством других команд MIDI, таких как сообщения контроллера или монопольные системой сообщения.
Много синтезаторов являются multimbral (иногда названный политембральным), означая, что они могут играть примечания различных инструментов одновременно. (Тембр является характерным качеством звука, которое позволяет слушателю отличить один вид музыкального инструмента от других видов.) Синтезаторы Multimbral могут эмулировать весь ансамбль реальных инструментов вместо только одного инструмента за один раз. Синтезаторы MIDI обычно реализуют эту опцию, используя в своих интересах различные каналы MIDI, на которых спецификация MIDI позволяет данным быть переданными. В этом случае синтезатор является фактически набором звуковых электростанций, каждый эмулирующий различный инструмент и отвечающий независимо обменивается сообщениями, которые получаются на различном канале MIDI. Так как спецификация MIDI обеспечивает только 16 каналов, типичный синтезатор MIDI может играть до 16 различных инструментов сразу. Синтезатор получает поток команд MIDI, многие из которых являются командами канала. (Команды канала предназначаются к определенному каналу MIDI; для получения дополнительной информации см. спецификацию MIDI.) Если синтезатор является мультитембральным, он направляет каждую команду канала к корректной звуковой электростанции согласно номеру канала, обозначенному в команде.
В API Звука Java эти звуковые электростанции являются экземплярами классов, которые реализуют MidiChannel
интерфейс. A synthesizer
у объекта есть по крайней мере один MidiChannel
объект. Если синтезатор является multimbral, у него есть больше чем один, обычно 16. Каждый MidiChannel
представляет независимую звуковую электростанцию.
Поскольку синтезатор MidiChannel
объекты более или менее независимы, присвоение инструментов к каналам не должно быть уникальным. Например, все 16 каналов могли играть тембр фортепьяно, как если бы был ансамбль 16 фортепьяно. Любая группировка возможна — например, каналы 1, 5, и 8 могли играть звуки гитары, в то время как у каналов, 2 и 3 удара игры и образовывают канал 12, есть басовый тембр. Инструмент, играемый на данном канале MIDI, может быть изменен динамически; это известно как изменение программы.
Даже при том, что большинство синтезаторов позволяет только 16 или меньшему количеству инструментов быть активным в установленный срок, эти инструменты могут обычно быть выбраны из намного большего выбора и присвоены определенным каналам как требуется.
Инструменты организуются иерархически в синтезаторе. Как был упомянут в Главе 8, "Краткий обзор Пакета MIDI," инструменты располагаются числом банка и числом программы. Банки и программы могут считаться строками и столбцами в двумерной таблице инструментов. Банк является набором программ. Спецификация MIDI позволяет до 128 программ в банке, и до 128 банков. Однако, определенный синтезатор мог бы поддерживать только один банк, или несколько банков, и мог бы поддерживать меньше чем 128 программ на банк.
В API Звука Java есть более высокий уровень к иерархии: soundbank. Soundbanks может содержать до 128 банков, каждый содержащий до 128 инструментов. Некоторые синтезаторы могут загрузить весь soundbank в память.
Чтобы выбрать инструмент из тока soundbank, Вы определяете число банка и число программы. Спецификация MIDI выполняет это с двумя командами MIDI: выбор банка и изменение программы. В API Звука Java комбинация числа банка и числа программы инкапсулируется в a Patch
объект. Вы изменяете текущий инструмент канала MIDI, определяя новый патч. Патч можно считать двумерным индексом инструментов в токе soundbank.
Вы могли бы задаваться вопросом, индексируются ли soundbanks, также, в цифровой форме. Ответ нет; спецификация MIDI не предусматривает это. В API Звука Java, a Soundbank
объект может быть получен, читая soundbank файл. Если soundbank поддерживается синтезатором, его инструменты могут быть загружены в синтезатор индивидуально как требующийся, или внезапно. У многих синтезаторов есть встроенный или soundbank по умолчанию; инструменты, содержавшиеся в этом soundbank, всегда доступны синтезатору.
Важно различить число тембров, которые синтезатор может играть одновременно и число примечаний, которые это может играть одновременно. Прежний был описан выше под "Каналами". Возможность играть многократные примечания сразу упоминается как полифония. Даже синтезатор, который не является мультитембральным, может обычно играть больше чем одно примечание за один раз (все имеющие тот же самый тембр, но различные передачи). Например, играя любой аккорд, такой как соль-мажорная триада или си-минорный седьмой аккорд, требует полифонии. У любого синтезатора, который генерирует звук в режиме реального времени, есть ограничение на число примечаний, которые это может синтезировать сразу. В API Звука Java синтезатор сообщает об этом ограничении через getMaxPolyphony
метод.
Речь является последовательностью единственных примечаний, таких как мелодия, которую может спеть человек. Полифония состоит из многократной речи, такой как части, спетые хором. Синтезатор с 32 речью, например, может играть 32 примечания одновременно. (Однако, немного литературы MIDI использует слово "речь" в различном смысле, подобном значению "инструмента" или "тембра.")
Процесс присвоения входящих примечаний MIDI к определенной речи известен как речевое выделение. Синтезатор поддерживает список речи, отслеживание того, которые являются активными (подразумевать, что у них в настоящий момент есть звучание примечаний). Когда примечание прекращает звучать, речь становится неактивной, означая, что это теперь свободно принять следующее примечание - по запросу, который получает синтезатор. Входящий поток команд MIDI может легко запросить больше одновременных примечаний, чем синтезатор способен к генерированию. Когда речь всего синтезатора является активной, как следующее должно Отметить По запросу быть обработанным? Синтезаторы могут реализовать различные стратегии: последний раз требуемое примечание может быть проигнорировано; или это может играться, прекращая другое примечание, такое как наименее недавно запущенный.
Хотя спецификация MIDI не требует этого, синтезатор может обнародовать содержание каждой его речи. API Звука Java включает a VoiceStatus
класс с этой целью.
A VoiceStatus
отчеты относительно текущего активного или неактивного состояния речи, канала MIDI, банка и числа программы, числа примечания MIDI, и объема MIDI.
С этим фоном давайте исследуем специфические особенности API Звука Java для синтеза.
Во многих случаях программа может использовать a Synthesizer
объект, явно не вызывая почти ни одного API синтеза. Например, предположите, что Вы играете стандартный файл MIDI. Вы загружаете это в a Sequence
объект, который Вы играете при наличии секвенсера, отправляет данные синтезатору по умолчанию. Данные в управлении последовательностью синтезатор как предназначено, играя все правильные примечания в правильные времена.
Однако, есть случаи, когда этот простой сценарий является несоответствующим. Последовательность содержит правильную музыку, но инструменты звучат неправильными! Эта неудачная ситуация, вероятно, возникла, потому что создатель файла MIDI имевшие различные инструменты в виду чем те, которые в настоящий момент загружаются в синтезатор.
MIDI 1.0 Спецификации предусматривают выбор банка и команды изменения программы, которые влияют, какой инструмент в настоящий момент играет на каждом канале MIDI. Однако, спецификация не определяет, какой инструмент должен находиться в каждом расположении патча (банк и число программы). Более свежая Общая спецификация MIDI рассматривает эту проблему, определяя банк, содержащий 128 программ, которые соответствуют определенным инструментальным звукам. Общий синтезатор MIDI использует 128 инструментов, которые соответствуют этот указанный набор. Различные Общие синтезаторы MIDI могут звучать очень отличающимися, играя, что, как предполагается, является тем же самым инструментом. Однако, файл MIDI должен по большей части звучать подобным (даже если не идентичный), независимо от того какой Общий синтезатор MIDI играет его.
Тем не менее, не все создатели файлов MIDI хотят быть ограниченными набором 128 тембров, определенных Общим MIDI. Этот раздел показывает, как изменить инструменты от набора по умолчанию, с которым идет синтезатор. (Если нет никакого значения по умолчанию, означая, что никакие инструменты не загружаются, когда Вы получаете доступ к синтезатору, необходимо использовать этот API, чтобы запустить с в любом случае.)
Чтобы учиться, являются ли инструменты, в настоящий момент загруженные в синтезатор, теми, Вы хотите, можно вызвать это Synthesizer
метод:
Instrument[] getLoadedInstruments()и выполните итерации по возвращенному массиву, чтобы видеть точно, какие инструменты в настоящий момент загружаются. Наиболее вероятно Вы вывели бы на экран имена инструментов в пользовательском интерфейсе (использующий
getName
метод Instrument
), и позвольте пользователю решать, использовать ли те инструменты или загрузить других. Instrument
API включает метод, который сообщает, какому soundbank инструмент принадлежит. Имя soundbank могло бы помочь Вашей программе, или пользователь устанавливают точно, каков инструмент.
Soundbank getDefaultSoundbank()дает Вам значение по умолчанию soundbank.
Soundbank
API включает методы, чтобы получить имя soundbank, поставщика, и номер версии, которым программа или пользователь могут проверить идентификационные данные банка. Однако, невозможно принять, когда Вы сначала получаете синтезатор, что инструменты от значения по умолчанию soundbank были загружены в синтезатор. Например, синтезатор мог бы иметь большой выбор в наличии встроенных инструментов для использования, но из-за его ограниченной памяти это не могло бы загрузить их автоматически.
Пользователь мог бы решить загрузить инструменты, которые отличаются от текущих (или Вы могли бы принять то решение программно). Следующий метод говорит Вам который инструменты, с которыми идут синтезатор (против необходимости быть загруженным из soundbank файлов):
Instrument[] getAvailableInstruments()Можно загрузить любой из этих инструментов, вызывая:
boolean loadInstrument(Instrument instrument)Инструмент загружается в синтезатор в расположении, определенном инструментом
Patch
объект (который может быть получен, используя getPatch
метод Instrument
). Чтобы загрузить инструменты из другого soundbanks, сначала вызовите Synthesizer's
isSupportedSoundbank
метод, чтобы удостовериться, что soundbank является совместимым с этим синтезатором (если это не, можно выполнить итерации по синтезаторам системы, чтобы попытаться найти тот, который поддерживает soundbank). Можно тогда вызвать один из этих методов, чтобы загрузить инструменты из soundbank:
boolean loadAllInstruments(Soundbank soundbank) boolean loadInstruments(Soundbank soundbank, Patch[] patchList)Поскольку имена предлагают, первая из этих загрузок весь набор инструментов от данного soundbank, и вторые загрузки выбранные инструменты от soundbank. Вы могли также использовать
Soundbank's
getInstruments
метод, чтобы получить доступ ко всем инструментам, затем выполните итерации по ним и загрузке выбранных инструментов, по одному используя loadInstrument
. Это не необходимо для всех инструментов, которые Вы загружаете, чтобы быть от того же самого soundbank. Вы могли использовать loadInstrument
или loadInstruments
загрузить определенные инструменты из одного soundbank, другой набор от различного soundbank, и так далее.
У каждого инструмента есть свое собственное Patch
объект, который определяет расположение на синтезаторе, где инструмент должен быть загружен. Расположение определяется числом банка и числом программы. Нет никакого API, чтобы изменить расположение, изменяя банк патча или число программы.
Однако, возможно загрузить инструмент в расположение кроме того, определенного его патчем, используя следующий метод Synthesizer
:
boolean remapInstrument(Instrument from, Instrument to)Этот метод разгружает свой первый параметр от синтезатора, и помещает его второй параметр в любое расположение патча синтезатора, был занят первым параметром.
Загрузка инструмента в расположение программы автоматически разгружается, любой инструмент уже был в том расположении, если любой. Можно также явно разгрузить инструменты, обязательно не заменяя их новыми. Synthesizer
включает три разгружающихся метода, которые соответствуют трем загружающимся методам. Если синтезатор получает сообщение изменения программы, которое выбирает расположение программы, где никакой инструмент в настоящий момент не загружается, не будет никакого звука от канала MIDI, на котором было отправлено сообщение изменения программы.
Некоторые синтезаторы хранят другую информацию помимо инструментов в их soundbanks. Например, wavetable синтезатор хранит аудиосэмплы, к которым могут получить доступ один или более инструментов. Поскольку выборки могли бы быть совместно использованы многократными инструментами, они сохранены в soundbank независимо от любого инструмента. Оба Soundbank
взаимодействуйте через интерфейс и Instrument
класс обеспечивает вызов метода getSoundbankResources
, который возвращает список SoundbankResource
объекты. Детали этих объектов являются определенными для синтезатора, для которого разрабатывается soundbank. В случае wavetable синтеза ресурс мог бы быть объектом, который инкапсулирует серию аудиосэмплов, взятых от одного отрывка звукозаписи. Синтезаторы, которые используют другие методы синтеза, могли бы сохранить другие виды объектов в синтезаторе SoundbankResources
массив.
Synthesizer
интерфейс включает методы, которые возвращают информацию о возможностях синтезатора:
public long getLatency() public int getMaxPolyphony()Задержка измеряет задержку худшего случая между временем, сообщение MIDI передается к синтезатору и время, когда синтезатор фактически приводит к соответствующему результату. Например, синтезатору могли бы потребоваться несколько миллисекунд, чтобы начать генерировать аудио после получения примечания - на событии.
getMaxPolyphony
метод указывает, сколько примечаний синтезатор может звучать одновременно, как обсуждено под "Речью" в разделе "Понимание Синтеза MIDI" ранее в этой главе. Как упомянуто в том же самом обсуждении, синтезатор может предоставить информацию о своей речи. Это выполняется через следующий метод:
public VoiceStatus[] getVoiceStatus()Каждый
VoiceStatus
в возвращенном массиве сообщает о текущем активном или неактивном состоянии речи, канале MIDI, банке и числе программы, числе примечания MIDI, и объеме MIDI. Длина массива должна обычно быть тем же самым числом, возвращенным getMaxPolyphony
. Если синтезатор не играет, все VoiceStatus
объектам установили их активное поле в false
. Можно изучить дополнительную информацию о текущем статусе синтезатора, получая MidiChannel
объекты и запросы их состояния. Это обсуждается больше в следующем разделе.
Иногда это полезно или необходимо получить доступ к синтезатору MidiChannel
объекты непосредственно. Этот раздел обсуждает такие ситуации.
При использовании последовательности, такой как одно чтение от файла MIDI, Вы не должны отправить команды MIDI синтезатору самостоятельно. Вместо этого Вы только загружаете последовательность в секвенсер, соединяете секвенсер с синтезатором, и позволяете этому работать. Секвенсер заботится о планировании событий, и результатом является предсказуемое музыкальное представление. Этот сценарий хорошо работает, когда требуемая музыка известна заранее, который является истиной, когда это читается из файла.
В некоторых ситуациях, однако, музыка сгенерирована на лету, поскольку она играет. Например, пользовательский интерфейс мог бы вывести на экран музыкальную клавиатуру или гитару fretboard и позволить пользователю играть примечания по желанию, щелкая с мышью. Как другой пример, приложение могло бы использовать синтезатор, чтобы не играть музыку по существу, но генерировать звуковые эффекты в ответ на действия пользователя. Этот сценарий типичен для игр. Как заключительный пример, приложение могло бы действительно играть музыку, это читается из файла, но пользовательский интерфейс позволяет пользователю взаимодействовать с музыкой, изменяя это динамически. Во всех этих случаях приложение отправляет команды непосредственно синтезатору, так как сообщения MIDI должны быть сразу переданы, вместо того, чтобы быть запланированными для некоторой определенной точки в будущем.
Есть по крайней мере два способа отправить сообщение MIDI синтезатору, не используя секвенсер. Первое должно создать a MidiMessage
и передайте это к синтезатору, используя отправить метод Receiver
. Например, чтобы произвести Середину C (примечание MIDI номер 60) на MIDI образовывают канал 5 (на основе одно) сразу, Вы могли сделать следующее:
ShortMessage myMsg = new ShortMessage(); // Play the note Middle C (60) moderately loud // (velocity = 93)on channel 4 (zero-based). myMsg.setMessage(ShortMessage.NOTE_ON, 4, 60, 93); Synthesizer synth = MidiSystem.getSynthesizer(); Receiver synthRcvr = synth.getReceiver(); synthRcvr.send(myMsg, -1); // -1 means no time stampВторой путь состоит в том, чтобы обойти уровень передачи сообщений (то есть,
MidiMessage
и Receiver
API), в целом, и взаимодействуют с синтезатором MidiChannel
объекты непосредственно. Вы сначала должны получить синтезатор MidiChannel
объекты, используя следующий Synthesizer
метод: public MidiChannel[] getChannels()после которого можно вызвать требуемый
MidiChannel
методы непосредственно. Это - более непосредственный маршрут чем отправка соответствия MidiMessages
к синтезатору Receiver
и позволяя синтезатору обработать передачу с его собственным MidiChannels
. Например, код, соответствующий предыдущему примеру, был бы: Synthesizer synth = MidiSystem.getSynthesizer(); MidiChannel chan[] = synth.getChannels(); // Check for null; maybe not all 16 channels exist. if (chan[4] != null) { chan[4].noteOn(60, 93); }
MidiChannel
интерфейс обеспечивает методы, которые соответствуют непосредственные каждой "речи канала" или "сообщениям" режима канала, определенным спецификацией MIDI. Мы видели один случай с использованием noteOn метода в предыдущем примере. Однако, в дополнение к этим каноническим методам, API Звука Java MidiChannel
интерфейс добавляет, что некоторые "заставляют" методы получать значение, последний раз установленное соответствующей речью или методами "набора" режима:
int getChannelPressure() int getController(int controller) boolean getMono() boolean getOmni() int getPitchBend() int getPolyPressure(int noteNumber) int getProgram()Эти методы могли бы быть полезными для отображения состояния канала пользователю, или для того, чтобы решить что значения передаться впоследствии к каналу.
API Звука Java добавляет понятия соло на канал и бесшумный, которые не требуются спецификацией MIDI. Они являются подобными соло и бесшумными на дорожках последовательности MIDI. (См. "Отключение звука или Отдельные Дорожки Soloing в Последовательности" в Главе 11, "Игра, Запись, и Редактирование Последовательностей MIDI.)"
Если отключено звук идет, этот канал не будет звучать, но другие каналы незатронуты. Если соло будет идти, то этот канал, и любой другой канал soloed, будут звучать (если это не будет отключено звук), но никакие другие каналы не будут звучать. Канал, который является и soloed и отключенный звук, не будет звучать. MidiChannel
API включает четыре метода:
boolean getMute() boolean getSolo() void setMute(boolean muteState) void setSolo(boolean soloState)
Аудио, произведенное любым установленным синтезатором MIDI, обычно направляется через выбранную аудиосистему. Если у Вашей программы не будет разрешения, чтобы играть аудио, то звук синтезатора не услышат, и исключение безопасности будет выдано. Для получения дополнительной информации по аудио полномочиям см. "Разрешение, чтобы Использовать Аудио Ресурсы" в Главе 3, "Получая доступ к Ресурсам Аудиосистемы."