|
Содержание
Раздел первый. Редактор нотного текстаЧто такое Midim?Midim - это секвенсер, который из нотного текста (в формате нотной системы Брайля (НСБ)) генерирует и воспроизводит Midi файл. Нотный текст в формате НСБ, как вы, смею надеяться, знаете, есть ни что иное как обычный текст, то есть набор букв, цифр, скобок и так далее. Этим мы обязаны шести точкам, коими и ограничены наши возможности письма. Но в случае с компьютерными технологиями почему бы этот недостаток не обратить в достоинство? Конечно, в нотной записи есть символы, которые трудно изобразить текстом. Например, нота фа целая, то есть шеститочие, в буквенной записи вообще ни чего не обозначает и используется для зачёркивания или рисования. Также сложно отыскать буквенный аналог для диеза, цифири, обозначения октав и некоторых других элементов. Надеюсь, мне удалось найти наиболее рациональное решение этой проблемы, по крайней мере, правила набора нотного текста в моей программе просты и доступны для понимания любого человека, знакомого с НСБ. Необходимо лишь немного тренировки и вы без особого труда будете набирать и редактировать музыкальные произведения любой сложности и структуры. Шесть основных правил нотописиЗдесь я следовал принципу, по которому одному нотному символу по системе Брайля должен соответствовать только один буквенный символ, а между ними должна быть логическая связь, поэтому вам не придётся их заучивать, достаточно будет внимательно прочитать и осознать шесть основных правил нотописи, приведённые ниже:
Редактор нотного текстаМузыкальное произведение, будем называть его сонгом, в этом секвенсере, впрочем как и в большинстве других секвенсерах, представлено в виде отдельных дорожек или треков, расположенных друг под другом. Каждый трек имеет своё имя и свой номер MIDI-канала, которые задаются в окне свойств трека. Треки могут быть разбиты на отдельные голоса. Это осуществляется посредством большого объединителя. Для облегчения работы и более наглядного представления нотного текста я ввёл возможность неявного использования этого элемента. В общем же случае нотный текст хранится в стандартном для НСБ виде со всеми описанными в правилах символами. Нотный редактор в программе Midim является текстовым и однострочным, то есть максимальное количество символов, которое можно набрать в нём за один промежуток времени не превышает 255. Именно этим числом ограничивается общая длина одного такта, включая все его голоса и по два символа на каждый объединитель между ними. Есть такие понятия, как текущий трек, текущий голос и текущий такт. Вот когда вы с помощью определённых сочетаний клавиш изменяете хотя бы один из этих параметров, тогда в редактор загружается именно та часть нотного текста, которую они описывают, а так как эта часть по понятным причинам не может содержать пробелов или больших объединителей, то эти символы в описываемом редакторе считаются запрещёнными. Именно поэтому, написав, скажем, первый такт, для того чтобы начать писать второй, вы должны нажать не на пробел, а на ту клавишу, которая изменит значение соответствующего параметра, то есть текущего такта. Процесс Набора нотного текста в программе MIDIM похож на заполнение ячеек таблицы. В программном меню можно отыскать и многострочный нотный редактор, позволяющий набирать, редактировать или просто просматривать нотный текст как он есть, то есть с пробелами и объединителями, но работа в нём хотя и бывает необходимой, но, на мой взгляд, не слишком удобна. Здесь же используя клавиши изменения значений текущих трека, такта и голоса, мы легко можем перемещаться по структуре сонга, какой бы сложной она не была. При каждом таком шаге джавс должен озвучить изменившийся параметр. Например, путешествовать внутри трека можно с помощью сочетаний альта с клавишами перемещения курсора. Все операции и соответствующие им горячие клавиши, которые вам доступны в программе, в том числе и навигационные, отражены в меню, поэтому не будем заострять на них особого внимания. Таким образом, вы набираете нотный текст в полном соответствии со всеми основными правилами НСБ. Исключением является только то, что вы не используете пробелов для разделения тактов и объединителей для разделения голосов , причём все голоса как бы отделены друг от друга, словно треки, и имеют гораздо большую свободу, нежели это предусмотрено в НСБ. Выражается это тем, что ровно как каждый трек может иметь свой отличный ото всех остальных треков тактовый размер, так и каждый голос трека имеет такую же независимость от своих собратьев. Другими словами, на одном треке могут находиться несколько голосов с абсолютно разными размерами такта. Все голоса и треки синхронизуются между собой, поэтому в программе существует определённая временная единица, в течение которой и только в течение которой будет звучать один такт, какого бы размера он ни был, и повлиять на эту единицу способен только темп произведения. Вы, должно быть, знаете, что время в MIDI измеряется в тиках. Так вот здесь такт всегда содержит 1920 тиков. Эта величина фиксированная и повлиять на неё не возможно ничем. В обязанность программы входит бдительно следить за тем, чтобы длительности такта не выходили за пределы тактового размера. При возникновении спорных ситуаций вам будет предложено расставить так называемые уточнители. Количество треков ограничено числом 255, причём один трек является общим для всех остальных и называется нулевым. Этот трек нельзя удалить или присвоить ему MIDI-канал. Имя этого трека есть ни что иное как имя всего сонга. Для чего он нужен вы поймёте дальше. Особенности обозначений тактового размера и тональностиБазовые размер и тональность задаются в первом такте нулевого трека. Затем эти параметры могут меняться в любом месте как по вертикали, так и по горизонтали сонга на любом треке, в любом голосе и в начале любого такта. Правила определения тактового размера и тональности такие же как и в нотной системе Брайля. Сначала проставляются ключевые знаки и после "цифири", то есть большой латинской V, количество долей в такте и длительность одной доли. При смене тональности необходимо сначала с помощью бекаров отменить старые ключевые знаки, и лишь затем задать новые. Например, если при начальной тональности в три диеза мы зададим новую тональность, указав перед цифирью один диез, то результатом будет тональность в четыре диеза. Ниже приведу примеры: Vd4 - четыре четверти - без знаков , MVc4 - три четверти - с одним диезом, ((Vb2 - две вторых - с двумя бемолями, \\\Vf8 - шесть восьмых - с тремя бекарами, \MMMMVab16 - двенадцать шестнадцатых - с бекаром и четырьмя диезами и так далее. Нужно помнить, что если сразу после указанного размера следует нота, то её необходимо писать со знаком октавы, даже в случае когда по логике голосоведения этого делать не надо, ведь, например, до восьмую программа может принять за цифру четыре и отнести её к тактовому размеру. Также октава должна быть обязательно проставлена перед самой первой нотой в голосе, но это всё элементарные правила НСБ, поэтому мы перейдём к следующим особенностям. К каждой ноте можно привязать метку или блок. Метка - это именованная константа, значение которой можно использовать в обработчике. Записывается по общим правилам для переменных и констант (смотрите описание обработчика). Присоединить метку к ноте можно записав перед этой нотой имя метки, заключённое в угловые скобки. Внимание! У одной ноты может быть только одна метка! Также метку нельзя присоединять к интервалам. Ниже приведу отрывок из нотного текста, содержащий метку Label, и ноту ми второй октавы целой длительности: <Label>KY Блок - это программа-обработчик, активизирующийся одновременно с началом звучания ноты, к которой он привязан. За продолжительность обработки отвечает сам блок. Его действие распространяется на весь канал. Присоединить блок к ноте можно указав перед ней имя этого блока, а перед именем, в свою очередь, необходимо поставить знак слова (то есть правую круглую скобку). Заканчиваться описание имени блока должно точкой. Например: )Cresh. Если необходимо передать в блок параметры, то после его имени, но до точки можно поставить двоеточие и перечислить их через точку с запятой. Надеюсь, не запутаетесь... Параметрами здесь могут быть числовые и символьные константы, переменные, а также арифметические и логические выражения (смотрите описание обработчика). Использовать или не использовать параметры решает вызываемый блок-обработчик, поэтому желательно знать их предназначение. Можно почитать описание к модулям, если оно есть, или просто изучить программный текст требуемого блока. Например, в комплект программы входит модуль Factures4x4, написанный мной. Если мы присоединим его к нашему сонгу, а в нотном тексте, в одном из тактов, перед каким-нибудь аккордом напишем следующее: )Guitor1:480;10;60. программа не просто воспроизведёт этот и все следующие за ним аккорды, а сыграет его одним из гитарных приёмов. Здесь мы передали блоку Guitor1 три параметра: 480, 10 и 60. Первый означает длительность одного удара, второй промежуток между двумя соседними звуками в ударе, а третий силу удара. Если вы передадите лишние параметры, то они будут просто проигнорированы, а в случае отсутствия оных блок придаст им значения по умолчанию. Блок Guitor2 из того же модуля заставляет звучать аккорды уже в другой, более сложной, ритмической окраске. Аналогичным образом работают и остальные блоки-обработчики, только с тем отличием, что не всем им требуются параметры. Внимание! К одной ноте может быть привязан только один блок-обработчик! К интервалу их привязывать нельзя. На первый раз эти строки могут показаться вам не понятными, но если вы изучите описание обработчика во втором разделе и что-то там поймёте, то вернитесь сюда и перечитайте о метках и блоках-обработчиках снова. Пустые такты вовсе не обязательно забивать паузами, но при желании делайте это маленькой латинской m независимо от тактового размера. К тому же иногда программа делает это автоматически. Использование симиле и прочих приёмов сокращения в этой версии не поддерживается. При желании это легко можно осуществить в обработчике. Аппликатуру пока тоже использовать нельзя. Все мелизмы и штрихи необходимо описывать самостоятельно по нотам или программировать их. На этом первый раздел, думаю, можно завершить. Если вы поняли о чём я разглагольствовал всё это время, то уже сейчас можете приступать к попыткам что-нибудь извлечь из моей программы. Учтите, что для свободного набора и редактирования нотного текста по описанным здесь правилам необходим навык, который обязательно придёт со временем, если, конечно, вы этого захотите... Раздел второй. ОбработчикДля того чтобы легче понять устройство обработчика, рекомендую прочитать главу MIDI это просто из книги Алексея Паркова. Обработчик - это встроенный язык программирования, позволяющий управлять всеми параметрами MIDI во времени, разве что кроме двух, ведь тональность и тактовый размер прочно привязаны к нотному тексту и оторвать их от туда просто не возможно. В остальном, обработчик может "дотянуться" куда угодно, будь то пространственная локализация или динамика, агогика или сама клавиатура инструмента. Перечислю конкретно все доступные ему параметры:
За каждым треком закреплён свой обработчик, который влияет только на параметры MIDI-канала этого трека. Есть обработчик общий для всего сонга, он закреплён за нулевым треком. Здесь описываются команды, влияющие на такие характеристики как, например, темп, или любые другие единые для всего сонга. Иными словами, этот обработчик перед компиляцией будет присоединён к обработчикам остальных треков. Вообще, все они представляют собой последовательность команд, описанных в текстовом виде, где каждая команда должна занимать одну строку Редактор для них находится, как и нотный редактор, в главном окне программы, но в отличие от того является многострочным Переход между этими редакторами осуществляется клавишей табуляции. Содержимое редактора обработчика изменяется при каждой смене текущего трека. Принцип работы обработчикаДля начала опишем состав языка обработчика. Он состоит из команд, выполняющих те или иные операции с данными во времени. Данными в обработчике могут быть: числовые и символьные константы, переменные, массивы, функции и выражения. Все они имеют один общий вещественный тип Extended. Имена символьных констант, переменных, массивов и функций состоят из букв латинского алфавита или цифр, причём первым символом в имени должна быть обязательно буква. Массивы могут быть только одномерными, с постоянным индексным диапазоном от 0 до 127. Индекс массива указывается в квадратных скобках после его имени. Функция внешне отличается от массива тем, что параметр, передаваемый ей указывается в круглых скобках, впрочем, есть функции и без параметров. Выражение может состоять из любых констант, переменных, функций и их сочетаний. Ниже перечислю все доступные операции, в порядке увеличения их значимости, которые можно производить над данными в выражениях:
Таким образом выражение 3 + Tempo выдаст результат сложения значения переменной Tempo с числовой константой 3. Как вы обратили внимания, помимо обычных арифметических операций, в выражениях можно использовать и логические. Здесь не делается отличия между этими операциями, просто принято считать, что ложь - это 0, а истина - 127. Есть встроенные символьные константы, хранящие в себе именно эти значения: False и True. Например, результатом выражения 100 == 100 будет 127 или True, а 127 < 100 выдаст в результате 0 или False. Исходя из этого можно утверждать, что True == 100 + 27 False == 20 - 20 True And False == False True Or False == True False Or False == False True + False == True True * False == False и так далее... Также в выражениях допускается применение круглых скобок с любым уровнем вложенности. Например: ((True Or False) And(100 == 100)) == (True and (True > False)) Главное, чтобы длина одной строки с оператором или выражением не привышала всё тех же 255 символов! В обработчике можно использовать условный оператор If. Общий синтаксис его таков: If <выражение1> Then <инструкции, выполняемые если выражение 1 истинно> Else If <выражение2> Then <инструкции, выполняемые если выражение2 истинно> Else If ... ... Else <инструкции, выполняемые если все выражения не верны> EndIf При этом части, содержащие Else могут и отсутствовать. Оператор If может быть вложенным сам в себя: If <выражение1> Then If <выражение2> Then <инструкции, выполняемые если оба выражения истинны> EndIf EndIf Конечно, это было бы правильней записать по-другому, в одном операторе If, но я просто привёл пример вложенности. Теперь поговорим о командах, выполняющих операции над данными. Разнообразия тут особого нет, поскольку в вашем распоряжении на самом деле всего лишь одна команда присваивания Let. Вид она имеет такой: Let <имя > <выражение>> Так, следующая строка присвоит переменной Tempo значение 120: Let Tempo = 120 В обработчик Для каждого параметра MIDI, встроена своя переменная или массив, изменяя значение которых вы измените значение соответствующего параметра. Так, переменная Tempo, как не трудно догадаться, связана с темпом. Время в обработчикеЯ уже писал ранее, такт в программе MIDIM, не зависимо от его размера, содержит ровно 1920 тиков. В процессе обработки программа такт за тактом, тик за тиком берёт сначала информацию из нотного текста, передаёт её в обработчик и лишь затем подаёт на выход. В связи с этим, чтобы обработать скажем один такт нотного текста одного трека, обработчику придётся выполниться 1920 раз. Это конечно несколько замедляет процесс генерации MIDI-файла, но зато появляется возможность более гибко, точно и наглядно отслеживать музыкальные процессы. Другими словами, если мы запишем опять ту же строку Let Tempo = 120, то значит она будет выполняться по 1920 раз в каждом такте, что отразится на скорости генерации MIDI-файла (хотя и весьма не существенно), но не на его размере, так как в итоговом файле фиксируются только изменения параметров, а не факт присвоения им значений. Конечно, если Записать Let Tempo = Rnd(128), где RND - генератор случайных чисел (смотрите описание встроенных функций), то, это заметно увеличит размер полученного файла, так как на каждом тике будет зафиксировано очередное изменение темпа. Теперь мы подошли к самой важной встроенной переменной, отвечающей за течение времени в обработчике. Это переменная PositionSong. В начале обработки её значение равно нулю, и с каждым тиком оно увеличивается самой программой на единицу. Благодаря именно этой переменной обработчик всегда знает, где он находится. Рассмотрим переменную PositionSong на примере условного оператора If. If PositionSong == 0 Then Let Tempo = 120 Else If PositionSong == 1920 Then Let Tempo = 240 EndIf Так вот, в самом начале обработки, когда значение PositionSong равно нулю, обработчик установит темп равным 120 и целый такт будет звучать именно в этом темпе. В начале второго такта, когда переменная PositionSong дойдёт до значения 1920, темп увеличится в два раза и будет таковым уже до конца произведения. На основе переменной PositionSong строятся два макро оператора: частотный оператор Evry и "временной заголовок". "Временной заголовок" - это простая константа, переменная, функция или выражение, занимающая целую строку. Чтобы понять для чего он нужен, запишем рассмотренный выше пример с условным оператором If, но уже с помощью "временного заголовка": 0 Let Tempo = 120 1920 Let Tempo = 240 "Временной заголовок" введён только для упрощения и наглядности программного текста. Ведь можно, например, записать следующее: 0..1920 Лet Tempo = 100 + Rnd(28) Здесь "временной заголовок" записан в виде отрезка, на протяжении которого переменной Tempo каждый тик будет присваиваться случайное значение от 120 до 127. С помощью оператора If это запишется так: If ((PositionSong>=0) and (PositionSong<=1920)) Then Лet Tempo = 100 + Rnd(28) EndIf Думаю, вы согласитесь, что первая запись всё же попроще. Ещё одно отличие "временного заголовка" от оператора If заключается в том, что последний не может быть вложенным сам в себя. Каждый последующий "временной заголовок" отменяет предыдущий. Другими словами, действие "временного заголовка" распространяется с момента появления его в тексте, вплоть до конца или до появления другого "временного заголовка". В них, как я уже сказал, можно использовать не только числовые, а и любые другие символьные константы, переменные, функции и даже целые выражения. "Временной заголовок" PositionSong отменит все предыдущие заголовки. Частотный оператор EvryСинтаксис его таков: Evry <частота> Do <инструкции...> EndEvry Смысл этого оператора заключается в том, что <инструкции>, находящиеся внутри его тела будут выполняться не каждый тик, а согласно указанной частоте (в тиках). Так, строки: Evry 1920 Do Let Tempo = Tempo + 1 EndEvry приведут к тому, что в начале каждого такта произведения темп будет увеличиваться на единицу. Опять же, для сравнения запишем это с помощью переменной PositionSong и оператора If: If Positionsong Mod 1920 == 0 Then Let Tempo = Tempo + 1 EndIf Здесь Mod - это остаток от деления. Оператор Evry также не может быть вложенным сам в себя и его действие распространяется либо до появления другого такого оператора, либо до строки EndEvry. Приведённый пример увеличивает темп в начале каждого такта, но как быть, если нам потребуется делать это, скажем, в его середине? Для этого в операторе Evry нужно указать частотное смещение OffSet. Приведу следующий пример: Evry 1920 Do Let Tempo = Tempo + 10 Evry 1920 OffSet 960 Do Let Tempo = Tempo - 10 EndEvry Здесь в начале каждого такта темп будет увеличен на 10 единиц, а в середине его вернётся в исходное значение. Понятно, что значение смещения не должно превышать значения частоты. Операторы циклаОператор For имеет следующий синтаксис: For <переменная> = <выражение1> To <выражение2> Do <список операторов> EndFor Здесь <выражение2> должно быть обязательно больше или равно <выражению1>, иначе список операторов в теле цикла не выполнится ни разу. Присвоим, например, всем контроллерам значение 0: For c = 0 To 127 Do Let controller[c] = 0 EndFor Цикл While имеет следующий синтаксис: While <выражение> Do <список операторов> EndWhile Здесь <список операторов> в теле цикла будет выполняться только в том случае и до тех пор пока указанное <выражение> истинно. Будьте осторожны с ним , так как при неграмотной записи <выражения> он может просто зациклиться и вам придётся прибегнуть к аварийной остановке программы. Учтите, что обработчику итак приходится не сладко, поэтому большое нагромождение циклов может значительно увеличить время генерации MIDI-файла. Используйте их только там, где это действительно необходимо. Примеры толкового использования цикловДля этих примеров мне понадобятся два встроенных в обработчик массива KeyLength[] и KeyPosition[], а также две встроенные функции KeyCount и Sounding(). Функция без параметра KeyCount возвращает количество нажатых клавиш в тот момент, когда к ней обращаются, а функция с параметром Sounding() возвращает номера этих клавиш (от 1 до 127). Здесь передаваемый ей параметр должен быть в диапазоне от 1 до KeyCount, в противном случае результатом выполнения этой функции будет 0. Упомянутые массивы хранят в себе информацию о сто двадцать семи клавишах инструмента. Если в какой-то момент значение элемента массива KeyLength[x] стало отличным от нуля, это означает, что именно в этот момент была нажата клавиша x. Тогда элемент массива KeyPosition[x] с каждым последующим тиком, начиная с нуля, увеличивается на единицу и, когда KeyPosition[x] станет равной KeyLength[x], это будет означать, что клавиша x отпущена и значения элементов упомянутых массивов снова сбросятся в нуль. Исходя из этого напишем фрагмент программы, который должен отслеживать нажатия клавиш, заданные в нотном тексте, и уменьшать их длительности в два раза. For i = 1 To KeyCount Do Let key = Sounding(i) If KeyLength[key] > 0 and KeyPosition[key] == 0 Then Let KeyLength[key] = KeyLength[key] / 2 EndIf EndFor Учтите, что KeyCount считает и паузы, которые также воспринимаются как ноты, но sounding() для них возвращает 0. Таким образом, циклы используются в основном для анализа и обработки нотного текста, поскольку только нотный текст способен повлиять на значение описанных здесь двух функций. Не думаю, что возникнет необходимость, скажем, использовать цикл с массивом Controller[]... Добавлю, что если вы в какой-либо момент присвоите элементу массива KeyLength[x] значение y, то клавиша x зазвучит с того самого момента, как вы это сделаете и затихнет ровно через y тиков. Вообще, значения всех встроенных переменных можно изменять, в том числе и PositionSong. Если мы запишем: 1920 Let PositionSong = 0 то воспроизведение первого такта зациклится до бесконечности. Конечно, так писать нельзя, но если завести счётчик повторений и вовремя выйти, то, всё будет нормально. Оператор BreakНе трудно догадаться, что оператор Breakиспользуется для досрочного выхода из циклов For и While, но это не единственное его предназначение, О чём будет сказано ниже в описании блоков-обработчиков. Константы, переменные и функции, определяемые пользователемВ некоторых своих примерах я использовал переменные не только встроенные в обработчик. Вы тоже можете пользоваться любым количеством собственных констант, переменных и массивов. Для этого только нужно их объявить. Оператор объявления переменной: Variable <имя> Оператор объявления массива: Array <имя> (здесь квадратные скобки не ставятся!) Оператор Объявления символьной константы: Constant <имя> = <значение> Эти операторы могут располагаться в любом месте программы и выполняются только один раз. Главное, чтобы объявление всегда предшествовало использованию. Один оператор объявления может объявить только одну константу, переменную или массив. Запись: Let i = 100 Variable i является не верной и в ней следует строки поменять местами. Объявлять ненужно только константы из нотного текста, то есть метки (см. первый раздел). Значение таких констант есть ни что иное, как время в тиках, то есть когда зазвучит нота, имеющая константу, тогда переменная PositionSong станет равна этой константе. Блок-обработчикСинтаксис: Block <ИмяБлока> <список операторов> EndBlock Имя блока задаётся по таким же правилам, как и имена констант или переменных. Список операторов в теле блока не будет исполняться обычным образом. Для того чтобы запустить этот блок, его имя нужно привязать к какой-нибудь ноте в нотном тексте. Как это сделать было описано выше (см. первый раздел). Когда наступит время зазвучать ноте, к которой мы привязали блок, именно тогда он и начнёт свою работу. Приведу простейший пример блока TempoSinus: Block TempoSinus Evry 240 Do {выполнять каждые 240 тиков} Let Tempo = 120 - Sin(PositionSong)*10 EndEvry EndBlock Если теперь в нотном тексте Перед какой-либо нотой написать )TempoSinus. с того места темп начнёт периодически ускоряться и замедляться. В этом примере я использовал встроенную функцию Sin, а в качестве её аргумента - переменную PositionSong. Оператор Evry необходим, чтобы не слишком частить с изменением темпа, а значит избежать перегрузки MIDI. Блок работает до тех пор, пока он сам себя не выгрузит, а достигается это с помощью упомянутого выше оператора Break. Напишем блок, который изменит темп и выгрузится. Block ChangeTempo Let Tempo= Parameter(1) Break EndBlock Здесь новой для вас является встроенная функция Parameter(). Как было описано в первом разделе, привязывая какой-либо блок к ноте, мы можем передавать ему любое количество параметров. Именно извлечением этих параметров из нотного текста и занимается функция Parameter(x), где x - это его порядковый номер. Таким образом, следующая запись в нотном тексте: )ChangeTempo:200. приведёт к тому, что с того места где она обозначена блок сделает темп равным 200 и сразу после этого выгрузится. Что делать, когда необходимо заставить блок работать какое-то определённое время? Для этого можно использовать функцию StartBlock, возвращающую время начала блока в тиках и, известный нам "временной заголовок". Напишем блок который будет работать ровно один такт после своего вызова. Block ChangeTempo StartBlock..StartBlock+1920 {это временной заголовок} Evry 240 Do Let Tempo = Tempo + 1 EndEvry EndBlock Этому блоку не требуются параметры. Благодаря временному заголовку, он после вызова на протяжении 1920 тиков каждые 240 тиков будет увеличивать темп на единицу. Желательно позаботиться о том, чтобы после окончания работы этот блок выгрузился из памяти. Block ChangeTempo StartBlock..StartBlock+1920 Evry 240 Do Let Tempo = Tempo + 1 EndEvry StartBlock + 1920 Break EndBlock Это лишь основные рекомендации по программированию блоков-обработчиков. Добавлю лишь, что они не могут быть вложенными сами в себя, аналогично оператору Evry, и заканчиваться должны либо началом другого блока-обработчика, либо словом EndBlock. Размещать же в тексте их можно где угодно, хоть вначале, хоть в конце, хоть в середине. Ещё блоки-обработчики разрешается выносить в отдельные файлы, называемые модулями,которые имеют расширение BLK. Чтобы использовать такой блок в нотном тексте, нужно модуль, содержащий его, присоединить к основному обработчику. Для этого в тексте этого обработчика пишем Module <имя> где <имя> - имя файла модуля без пути и расширения. Все файлы модулей хранятся в одном месте, в каталоге Modules. Пока создание их необходимо производить вручную, с помощью какого-либо текстового редактора. В модуле запрещено размещать что-то кроме блоков-обработчиков, исключением являются только операторы объявления констант, переменных и массивов, которые могут находиться вне этих блоков. ШтрихиВ нотном тексте разрешено использование штрихов NonLegatto, Legatto, Stakatto и Stakattisimo. Штрих NonLegatto исполняется по умолчанию. Остальные необходимо указывать перед нотами. Также можно использовать удвоенные штрихи, что позволяет несколько сократить запись. Учтите, что штрихи - это единственное, что можно удваивать в MIDIM. Одинарный штрих здесь, как и в НСБ, отменяет удвоенный. В обработчике доступны три переменные для управления упомянутыми штрихами:
Придавая этим переменным различные значения, вы можете управлять используемыми штрихами. Раздел третий. Встроенные константы, переменные, массивы и функцииНастало время перечислить весь инструментарий, с помощью которого и можно вытворять с нотным текстом всё, что вам заблагорассудится, но, разумеется, в рамках возможностей MIDI. Встроенные константыTrue = 127 False = 0 Pi = 3,1415926 Встроенные переменныеInstrument - инструмент MIDI-канала (по умолчанию - 0, т.е. Piano), Tempo - темп сонга (по умолчанию - 120), Pich - изменение высоты звучания (по умолчанию - 64), PositionSong - текущая позиция обработки (в тиках), LengSong - длина сонга (в тиках), PositionRND - допустимая погрешность смещения нот (в тиках, по умолчанию - 0), употребляется для гуманизации, Transpose - транспонирование нот по полутонам (по умолчанию - 0). NonLegatto - коофицент длительности при соответствующем штрихе (по умолчанию 0,99), Stakatto - коофицент длительности при соответствующем штрихе (по умолчанию 0,25), Stakattisimo - длительность ноты в тиках, при соответствующем штрихе (по умолчанию 10), Kanal - содержит номер MIDI-канала трека. Встроенные массивыController[] - контроллеры, KeyOn[] - скорость нажатия клавиши (задаётся для каждой клавиши отдельно), KeyOff[] - скорость отпускания клавиши (аналогично), KeyLength[] - длительность звучащей клавиши (в тиках), KeyPosition[] - счётчик звучания клавиши(аналогично), Встроенные функцииsin(x) - синус аргумента x, cos(x)- косинус аргумента x, arctan(x) - арктангенс, rnd(x) - генератор случайного числа от 0 до (x-1), exp(x) - экспонента, ln(x)- натуральный логарифм, abs(x) - абсолютное значение x, int(x) - целая часть вещественного x, round(x) - округление по известным правилам вещественного x, not(x) - преобразует true в false и наоборот, sqr(x) - квадрат x, sqrt(x) - корень x, parameter(x) - извлекает параметр №x, переданный блоку-обработчику, KeyCount - количество нажатых клавиш, Sounding(x) - возвращает номер нажатой клавиши (x может быть от 1 до KeyCount), StartBlock - в блоке-обработчике возвращает время его начала (в тиках), SegmentCount - возвращает числитель тактового размера. На этом крадкое руководство можно завершить. Надеюсь, вы сможете извлечь максимум пользы из этой программы. Ссылки по теме
Метки
|
|||||||||
Распространение материалов сайта означает, что распространитель принял условия лицензионного соглашения. Идея и реализация: © Владимир Довыденков и Анатолий Камынин, 2004-2024 |
Социальные сети