Музыкальная студия "La Bella Classic" композитора Алексея Паркова
ГЛАВА 12
Программирование музыки
Практически все рассмотренные выше музыкальные программы (кроме программ набора и верстки) представляют собой, по сути, набор алгоритмов синтеза звука, его обработки, а также работы со звуковыми последовательностями (то же можно сказать о некомпьютерных электронно-музыкальных модулях — синтезаторах, сэмплерах, драм-машинах и т. п.)- Каждая программа имеет ограниченный набор перечисленных выше алгоритмов, а в них для редакции открыто, как правило, лишь небольшое количество параметров. У многих музыкантов, работавших с этими программами, возникало желание редактировать все параметры алгоритмов и вообще создавать свои собственные. И начинались сетования на ограниченность средств данной программы или системы.
На самом деле все эти ограничения — лишь плата за удобство и красоту пользовательского интерфейса. Интерфейс сковывает свободу действий — иначе и быть не может (сравните, например, пользовательский интерфейс профессионального фотоаппарата, имеющий кучу настроек, и обычной мыльницы с едва ли не одной кнопкой щелканья).
Однако есть программный продукт, позволяющий легко редактировать музыкальные алгоритмы и создавать новые, тонко регулировать мельчайшие параметры каждого звука — просто мечта музыканта. Кроме всего прочего, он еще и совершенно бесплатный! Речь идет об универсальной системе программирования музыки — программе C-Sound.
И пусть людей, далеких от компьютеров и не знающих языков программирования, не пугает вынесенное в заголовок слово программирование. Вспомните, что и современную стиральную машину нужно немножко программировать. Программу C-Sound можно, в принципе, назвать и языком программирования, однако, поскольку программируются здесь музыкальные явления, а не какиенибудь там ядра и интерфейсы, C-Sound не просто легок для понимания музыкантов — более того, его легче понять музыканту, не знакомому с программированием, чем программисту, не знакомому с музыкой.
Итак, рассмотрим вкратце основы работы с C-Sound. Ниже будет рассмотрен классический вариант этой программы, не рассчитанный на воспроизведение в реальном времени и вполне сносно работающий даже на медленных компьютерах (например, 486-х с тактовой частотой 33 МГц).
Классическая схема работы в C-Sound такова. Вы создаете два текстовых файла (в любом текстовом редакторе, например в стандартном Windows-блокноте Notepad). Первый из них описывает свойства ваших инструментов, а второй — последовательность звуков, играемых этими инструментами, и их параметры. Грубо говоря, можно сказать, что первый файл — это описание оркестра (он должен иметь расширение .ore, и в дальнейшем мы будем называть его ore-файлом), а второй файл — это партитура (расширение .sco, будем называть его sco-файлом). Собственно говоря, программа C-Sound занимается тем, что превращает эти два файла в обычный звуковой файл, который можно прослушать любой воспроизводящей программой.
В своем базовом варианте C-Sound запускается из командной строки, в которой указываются имена входных файлов, формат и имя выходного файла и еще некоторые параметры. В Windows-варианте имеется небольшая оболочка, которая, однако, принципиально ничем не отличается от командной строки.
Построение простейшего инструмента
Рассмотрим вкратце, что же представляют собой текстовые файлы-источники .ore и .sco и как они превращаются в нечто звучащее.
Как уже говорилось, ore-файл представляет собой описание инструментария для вашей музыки. Он может содержать описание одного или нескольких инструментов, ссылки на которые будут появляться у каждой ноты в sco-файле.
Описание каждого инструмента должно начинаться о ключевого слова instr и заканчиваться словом endi п. После слова i nstr обязательно должен быть указан идентификационный номер этого инструмента. Описание каждого инструмента должно быть завершено словом endin до начала описания следующего инструмента. Описания инструментов не могут быть вложены друг в друга: instr 1 ... (описание) endin instr 2 ... (описание) endin instr 3 ... (описание) endin и т. д.
Однако еще до начала описания первого инструмента в ore-файле необходимо поместить так называемый заголовок, в котором указываются ключевые параметры для данной композиции. Этих параметров четыре:
Вот, например, типичный заголовок ore-файла (для Windows-окружения):
Si-44100
kr=3675
ksmps=12
nchnls-2
... (и т. д. )
После заголовка следуют собственно описания инструментов. Ключевым в описании инструмента является оператор out (для двух каналов — cuts). В качестве его операнда нужно указать объект, который вы как бы присоединяете к звуковому выходу — другими словами, то, что звучит. Этим объектом обычно является ссылка на строку с соответствующим оператором. Рассмотрим такой элементарный пример:
sr=44100
kr=3675
ksmps=12
nchnls-1 instr 1
asndoscil 15000,220.1 out asnd endin
Этот ore-файл описывает простейший инструмент, который умеет играть только одну ноту (ля малой октавы) на одной громкости, одним тембром (каким — указывается в sco-файле). Здесь строка out asnd означает, что выходным результатом данного инструмента является сигнал, который генерируется в строке, помеченной asnd. В этой строке вы можете видеть оператор oscil, один из важнейших в C-Sound, — он генерирует периодический сигнал. Оператор oscil требует трех операндов: первый определяет амплитуду сигнала, второй — его частоту и третий — номер волновой таблицы, находящейся в sco-файле. В данном примере амплитуда сигнала равна 15 000 единиц, а частота — 220 герцам. Тембр определяется волновой таблицей № 1 (должна быть в sco-файле).
Теперь приведем пример sco-файла для описанного выше простейшего инструмента:
f1 0 512 10 1
i1 0 1
i1 1 1
i1 3 10
е
Если скомпилировать два этих файла, получим в результате звук ля малой октавы, исполняемый синусоидальным тембром три раза: два раза по одной секунде и затем, после секундной паузы — 10 секунд.
Первая строка этого sco-файла содержит волновую таблицу, на что указывает буква f в начале строки. Ее цифровые параметры объясняются следующим образом:
Каждая строка sco-файла, начинающаяся с буквы i, — это нота, исполняемая инструментом. В этой строке должно быть три обязательных параметра:
В строке i могут быть еще и другие параметры, если они необходимы для инструмента. Однако для приведенного выше простейшего инструмента они не нужны.
Sco-файл должен заканчиваться строкой, содержащей единственную букву е. Кстати, обратите внимание, что в начале каждой строки sco-файла обязательно стоит буква, а больше букв в этом файле нет, есть только цифры1.
Буква, стоящая в начале строки, определяет тип этой строки:
Разобравшись с простейшим инструментом, попробуем его усложнить. Например, не очень удобно, что инструмент может сыграть только ноту одной высоты. Сделаем так, чтобы высота ноты регулировалась из sco-файла:
огс-файл sco-файл
sr=44100 fl 0 512 10 1
kr=3675 il 0 1 110
ksmps=12 il 1 1 220
nchnls=l il 2 1 330
instr 1 il 3 1 440
asnd oscil 15000,p4.1 e
out asnd
endin
В этом инструменте в операторе oscil также указана постоянная амплитуда, однако вместо постоянной частоты стоит указание р4, то есть parameter 4. Оно означает, что значение частоты в герцах будет таким, каким оно указано в четвертом параметре i-строки в sco-файле. Таким образом, теперь мы можем указывать в sco-файле частоту исполняемого звука. В приведенном выше примере наш инструмент сыграет четыре ноты, каждая длиной в 1 секунду: ля большой октавы, ля малой октавы, чуть повышенное ми первой октавы и ля первой октавы.
Однако трудно не согласиться, что указывать ноты в виде частоты основного тона не всегда удобно. Поэтому в C-Sound предусмотрена функция cpspch, преобразующая ноту из более привычного формата октава.пич-класс в частоту. При этом октавы нумеруются снизу вверх, а первая октава имеет здесь номер 8. Пич-класс ноты обозначается обычным образом: 00 — до, 01 — до-диез, 02 — ре и т. д., до И — си. Таким образом, до первой октавы будет обозначаться как 8.00, соль малой октавы — как 7.07 и т. д. В следующем примере наш простой инструмент играет первую фразу мелодии песни Подмосковные вечера.
Ore-файл sco-файл
Sr=44100 fl 0 512 10 1
kr=3675 il 0 1 8.00
ksmps=12 il 1 1 8.03
nchnls=l il 2 1 8.07
instr 1 il 3 1 8.03
asnd oscil 15000,cpspch(p4).1 il 4 2 8.05
out asnd il 6 1 8.03
endin il 7 1 8.02
il 8 2 8.07
il 10 2 8.05
il 12 4 8.00
e
Точно таким же образом вы можете указывать амплитуду сигнала в децибелах, используя функцию ampdb, как будет показано в следующем примере.
Настало время сказать несколько слов о переменных. Переменные существуют, грубо говоря, для того, чтобы можно было ссылаться на строки операторов в ore-файле. Например, в приведенных выше примерах строка оператора oscil была помечена как asnd, а оператор out содержал ссылку на эту строку.
Имена переменных в C-Sound могут состоять из практически любого набора букв и цифр (исключая зарезервированные слова). Однако первой буквой любого имени переменной должна быть либо буква а (как в примерах выше), либо k, либо i. Значения всех элементов, имя которых начинается с буквы i, вычисляются один раз для каждого звука. Если имя элемента начинается с k, то его значение обновляется с контрольной частотой (control rate), указанной в заголовке ore-файла (kr). Такие имена используются для сигналов, которые изменяются в течение времени звучания одной ноты, но для которых не критична скорость обновления (огибающие, LFO и пр.). И наконец, если имя элемента начинается с а, то его значение обновляется с частотой сэмплирования, указанной в заголовке как sr. Эти имена используются для тех сигналов, для которых частота обновления играет ключевую роль — в основном, это аудиосигналы. Пример использования i-переменных приведен ниже (для разнообразия в sco-файле здесь записано начало мелодии Легко на сердце от песни веселой). Заметьте, что каждая i-строка sco-файла здесь содержит уже пять параметров — три стандартных, четвертый — громкость и пятый — высота.
Ore-файл sco-файл
Sr=44100 fl 0 512 10 1
kr=3675 il 0. .5 60 8.03
ksmps=12 il .5 .5 65 8.07
nchnls=l il 1 .5 70 8.10
instr 1 il 1.5 1 80 9.03
ivlm=ampdb(p4) il 2.5 .75 75 9.02
ipch=cpspch(p5) il 3.25 .25 65 8.10
asnd oscil ivlm.ipch.l il 3.5 1 75 9.02
out asnd il 4.5 .75 70 9.00
endin il 5.25 .25 65 8.08
il 5.5 1 70 9.00
il 6.5 2 60 8.10
e
Все это, разумеется, хорошо, но в реальной музыке, как правило, громкость и высота звука не являются постоянными на протяжении всей ноты. Заставить параметры звука изменяться во время звучания оного можно, применив к осцилля"тору (oscil) постоянно меняющиеся значения:
Оrс-файл sco-файл
Sr=44100 fl 0 512 10 1
kr=3675 il 0 .5 60 8.03 .05
ksmps=12 .1
nchnls=l i1 . 5 .5 65 8.07 . 05
instr 1 . .1
ivlm=ampdb(p4) il 1 .5 70 8.10 .05
ipch=cpspch(p5) .1
kenv linen ivim.p6.p3.p7 il 1.5 1 80 9.03 .08
asnd oscil kenv.ipch.l .2
out asnd il 2.5 .75 75 9.02 .08
endin .2
il 3.25 .25 65 8.10 .02
.1
il 3.5 1 75 9.02 .06
.2
il 4.5 .75 70 9.00 .06
.2
il 5.25 .25 65 8.08 .02
.1
il 5.5 1 70 9.00 .06
.2
il 6.5 2 60 8.10 .09
.3
e
В этом примере в качестве амплитуды в операторе oscil.указана не постоянная величина ivlm, а динамически изменяющаяся kenv (начинается с k!). Данной меткой обозначена строка оператора linen, строящего огибающую для нашего звука. Оператор linen требует наличия четырех операндов: максимальной амплитуды, времени атаки, общей продолжительности звука и времени затухания. В качестве значения максимальной амплитуды мы берем ivlm, а общая продолжительность звука всегда находится в параметре рЗ (помните — это обязательный для всех i-строк стандартный параметр). Что касается времени атаки и времени затухания для них мы здесь определили специальные параметры рб и р7, это и отразилось в соответствующем sco-файле.
Дополним картину динамически изменяющихся параметров добавлением легкого вибрато в песню. Для этого к постоянной базовой высоте ноты ipch в операторе oscil добавим медленно изменяющийся синусоидальный сигнал kvbr. При этом предоставим возможность выбирать в sco-файле частоту и глубину вибрато, а также время его задержки. Задержку вибрато осуществим с помощью постепенно возрастающей амплитудной огибающей на генераторе медленной синусоиды:
ore-файл sco-файл
sr=44100 F1 0 512 10 3 2 1
kn-3675 f2 0 512 10 1
ksmps=12 il 0 .5 60 8.03 .05 .15.15
nchnls-1 11 .5 .5 65 8.07 .05 .16.17
irrstr 1 il 1 .5 70 8.10 .05 .1 5 .1 7
ivlm=ampdb(p4) il 1.5 1 80 9.03 .08 .2 7 .3 11
ipch=cpspch(p5) il 2.5 .75 75 9.02 .08 .2 5 .2 7
kenvlinen ivlra,p6.p3.p7 il 3.25 .25 65 8.10 .02 .1 5 .1 7
kvdel linseg il 3.5 1 75 9.02 .06 .2 6 .25 11
O.p9.0..I.pl0.p3-p9-.l.pl0
kvbroscil kvdel.p8.2 il 4.5 .75 70 9.00 .06 .2 6 .2 7
asndoscil kenv,ipch+kvbr,1 il 4.5 .75 70 9.00 .06 .2 6.27
out asnd il 5.25 .25 65 8.08 .02 .1 5 .1 7
endin il 5.5 1 70 9.00 .06 .2 5 .2 7
il 6.5 2 60 8.10 .09 .3 6 .4 8
e
Для амплитудной огибающей на медленной синусоиде был использован генератор непериодического сигнала, состоящего из линейных сегментов linseg. При этом операторе может находиться любое нечетное число операндов. Все операнды, стоящие на нечетных позициях, обозначают уровень сигнала, а стоящие на четных позициях — время перехода между уровнями. В нашем примере (linseg 0,р9,0,.1,р10,рЗ-р9-.1,р10): 0 — уровень, р9 — время перехода, 0 — уровень, .1 — время перехода, р!0 — уровень, рЗ-р9-.1 — оставшееся время и р!0 — последний уровень (если ваш сигнал будет состоять всего из одного сегмента, вместо оператора linseg используйте оператор line, это намного ускорит процесс компиляции).
Теперь в качестве иллюстрации возможных улучшений алгоритма добавим к нашему инструменту небольшой хорус:
огс-файл sco-файл
sr-44100 fl 0 512 10 3 2 1
kr-3675 f2 0 512 10 1
ksmps-12 il 0 .5 60 8.03 .05 .15.15
nchnls-1 il .5 .5 65 8.07 .05 .16.17
instr 1 il 1 .5 70 8.10 .05 .15.17
ivlm-ampdb(p4)/5 il 1.5 1 80 9.03 .08 .2 7 .3 11
ipch-cpspch(pS) il 2.5 .75 75 9.02 .08 .2 5 .2 7
kenvlinen ivlm.p6.p3.p7 il 3.25 .25 65 8.10 .02 .15.17
kvdel linseg il 3.5 1 75 9.02 .06 .2 6 .25 11
O.p9.0..I.pl0.p3-p9-.l.pl0
kvbroscil kvdel.p8.2 il 4.5 .75 70 9.00 .06 .2 6 .2 7
asndl oscil kenv.ipch+kvbr.1 il 5.25 .25 65 8.08 .02 .15.17
asnd2 oscil kenv,ipch*1.002+kvbr, 1 il 5.5 1 70 9.00 .06 .2 5 .2 7
asndS oscil kenv.ipch*1.004+kvbr. 1 il 6.5 2 60 8.10 .09 .3 6 .4 8
asnd4 oscil kenv,ipch*.998+kvbr, 1 e
asnd5 oscil kenv.ipch*.996+kvbr. 1
asnd=asndl+asnd2+asnd3+asnd4+asnd5
out asnd
endin
Для получения этого хоруса мы использовали пять почти одинаковых сигналов, только чуть-чуть различающихся частотой. Обратите внимание, что, поскольку перед выходом эти сигналы складываются, указанная амплитуда при инициалиа-зии уменьшается в пять раз.
Состав операторов и возможности C-Sound
Если вы дочитали до этого места и поняли смысл приведенных выше простых файлов C-Sound, то вы легко сможете строить алгоритмы и дальше, вооружившись собственной фантазией. Поэтому теперь я лишь кратко перечислю основные операторы C-Sound, а также некоторые другие его возможности.
Итак, начнем. В C-Sound можно определить глобальные переменные, имена которых должны начинаться с буквы д. После буквы д должна следовать бука a, k или i, а потом — любой набор символов. Глобальная переменная отличается от локальной тем, что область ее действия распространяется на весь огстфайл (область действия обычных, локальных переменных — один инструмент, то есть ограничивается пространством между instr и endin). Глобальные переменные полезны для создания инструментов, обрабатывающих сигнал, — ревербераторов, эквалайзеров и т. п.
В C-Sound можно использовать арифметические операции сложения (+), вычитания (-), умножения (* ) и деления (/). Возможны также логическое И (&&) и логическое ИЛИ (||), но они не применимы к а-параметрам, обновляемым с частотой сэмпли1 рования (sr). Порядок действий при этом обычный: сначала умножение и деление, потом сложение и вычитание, а затем логические операции. Для указания иного порядка действий можно использовать скобки.
Можно применять также условные функции, которые возвращают то или иное значение в зависимости от выполнения условия. Например, выражение a>b?c:d возвращает значение с, если а действительно больше, чем Ь; в противном случае возвращается значение d. В качестве операций сравнения могут использоваться: больше (>), меньше (<), больше или равно (>=), меньше или равно (<-), равно (—) и не равно (!=). Существует небольшой набор встроенных функций:
В C-Sound можно применять операции ветвления (перехода). Для безусловного ветвления можно использовать оператор goto, после которого должна стоять метка. Операторы igoto и kgoto используются для ветвления, соответственно, только во время инициализации звука или только во время обновления значений. Для условного ветвленеия можно использовать оператор if... goto, где после оператора if должна быть операция сравнения, например: if k2>p4 goto next. Здесь сравниваются значения k2 и р4, и если значение k2 больше, то происходит ветвление на метку next.
Для условного ветвления можно использовать также оператор timout. Это ветвление в зависимости от времени, прошедшего с момента начала звука. Оператор требует трех операндов: времени начала ветвления, продолжительности временного интервала ветвления и метки. Например: timout 1, 2, next Здесь ветвление происходит в том случае, если от начала звука прошло более 1 и менее 3 секунд (точнее, долей). Во всех приведенных выше примерах для генерации периодических сигналов использовался оператор oscil Однако C-Sound содержит еще целый набор генераторов периодических (и непериодических) сигналов. Рассмотрим некоторые из них.
Оператор foscil предназначен для FM-синтеза. Он требует шести операндов: амплитуда, базовая частота, коэффициент несущей частоты1, коэффициент модулирующей частоты, индекс модуляции, номер таблицы. Амплитуда и номер таблицы здесь по значению идентичны соответствующим операндам оператора oscil. Несущая и модулирующая частоты получаются от умножения коэффициентов на базовую частоту. Например, если базовая частота равна 220 Гц, а коэффициенты — 1 и 2, то в результате при FM-синтезе несущая частота будет равна 220 Гц, а модулирующая — 440 Гц.
Оператор loscil предназначен для WT-синтеза, то есть использования C-Sound в качестве сэмплера. Он требует наличия трех обязательных операндов, после которых могут следовать семь или менее необязательных. Обязательными являются амплитуда, частота и номер волновой таблицы (имеет смысл выбирать таблицу, заполненную волновой формой сэмплированного звука). Затем могут следовать: основная частота оригинального сэмпла (если этот операнд равен 0 или отсутствует, то данное значение берется из заголовка звукового файла-источника), режим петли (0 — нет петли, 1 — обычная петля, 2 — двустороння петля), точка начала петли, точка конца петли. Потом могут следовать те же параметры для второй петли.
А каким же образом сэмплированный звук из файла-источника попадает в таблицу? Для этого существует несколько способов. Один из них — воспользоваться подпрограммой GEN01, например, вот так: fl 0 8192 1 piano_c3.aiff 0 4 0. Как вы уже, вероятно, догадались по первым четырем параметрам этой f-строки, здесь вызывается подпрограмма генерации сигнала GENO1. После номера подпрограммы должны быть указаны следующие параметры: имя файла-источника в двойных кавычках, точка (время) начала чтения в звуковом файле, формат звукового файла (4 означает обычный 16-битный формат) и номер канала, который следует прочитать из файла (для стерео- или квадрофайлов; 0 означает чтение всех каналов).
Оператор pluck используется при синтезе методом Карплуса — Стронга для получения звука щипка струны или ударных звуков. Напомню, что в основе этого метода лежит периодическое повторение первоначального (обычно шумового) посыла с частотой, лежащей в звуковом диапазоне. Этот оператор требует наличия пяти обязательных операндов: амплитуда, частота повторения посыла, базовая частота самого посыла, номер волновой таблицы (для инициализации посыла) и номер метода синтеза. Номер метода может принимать значения от 1 до 6, при этом для использования алгоритма Карплуса — Стронга в чистом виде нужно применить метод № 1. Применение других методов (кроме № 6) требует ввода дополнительных параметров. Например, при выборе метода № 3 (звуки ударного характера) следует ввести еще коэффициент жесткости звучания, лежащий в диапазоне от 0 до 1. Поскольку в классическом варианте алгоритма Карплуса — Стронга используется шумовой посыл, в качестве номера волновой таблицы можно указать 0, и в этом случае для посыла будет использована случайная последовательность. Базовая частота посыла обычно должна равняться частоте повторения и соответствовать желаемой высоте звука.
Оператор rand предназначен для генерации случайных последовательностей, которые могут использоваться, например, для создания шумовых сигналов. Этот оператор требует единственный операнд — амплитуду генерируемых значений. Новые значения последовательности генерируются с частотой sr или kr. В некоторых случаях может потребоваться генерировать случайные значения с меньшей частотой. Для этого предназначен оператор randh, которому необходим второй операнд — частота генерации случайных значений. Можно использовать также оператор randi, который действует так же, как и randh, однако осуществляет линейную интерполяцию между сгенерированными значениями.
Оператор fof предназначен для формантного синтеза. Он воспроизводит основные алгоритмы знаменитой IRCAM' овской программы CHANT. Детально его объяснять довольно долго, поэтому приведу лишь список обязательных операндов этого оператора:
Оператор grain применяется для гранулярного синтеза. Как и в предыдущем случае, ограничусь перечислением его обязательных операндов:
Оператор vdelay применяется для обработки сигнала с помощью задержки. Он требует трех операндов: исходного сигнала, текущего времени задержки и максимального значения времени задержки. Обратите внимание, что текущее время задержки лучше всего контролировать с частотой sr, иначе могут появиться непредвиденные щелчки.
Оператор reverb применяется для реверберации исходного сигнала. Он требует наличия двух обязательных операндов — исходного сигнала и времени реверберации. Для использования других типов реверберации существуют операторы comb и alpass, которые требуют наличия еще одного дополнительного операнда — размера временной петли, практически означающего плотность эха.
Оператор multitap применяется для обработки сигнала с помощью мультизадержки. В качестве первого операнда здесь должен быть указан исходный сигнал, а затем могут следовать несколько пар операндов. В каждой паре первый из операндов определяет время задержки, а второй — уровень задержанного сигнала.
Существует и множество других операторов C-Sound, позволяющих осуществить самые фантастические звуковые мечты, но подробно их перечислять не буду. Если вы научитесь эффективно применять рассмотренные выше возможности C-Sound (а рассмотрены все основные операторы и функции), то остальные операторы и подпрограммы генерации сможете изучить самостоятельно, заглянув в описание C-Sound, свободно лежащее в Сети (на английском языке), или просто в файл csound.hlp, присутствующий практически во всех версиях и вариантах программы. Ну и напоследок замечу, что все, что относится к программе C-Sound (и саму программу), можно найти в Интернете на The Csound Front Page no адресу http://www.leeds.ac.uk/music/Man/c_front.html
Главная страничка Архив midi Обработка звука Видео школа Архив звуковых эфектов Почта Ссылки