Загляните в библу latin percussion от brio, если есть доступ. Сразу станет ясно.
Смысл в том, чтоб константами определить положение рядов и колонок для верстки. И при необходимости не переписывать все значения кнопок и пр, а просто поменять положение колонки или ряда целиком
[DOUBLEPOST=1445020340,1445020295][/DOUBLEPOST]в конкретном примере, они добиваются равномерного расположения фейдеров друг меж другом, изменяя одно число
оу....... Это, я не знаю о таком. А контакт какой? Мне еще лень было обновляться на 0.6, а в мануале по 0.4 я такого не нахожу)) Думаю, быстрее будет спросить в NI User Forums
а... не использовал))) я б все-таки в ручную делал, с занесением в протокол, какая абракадабра чем является...
Еще полезно использовать версии. Даня Беличенко вообще на каждый чих новый txt создает, и к релизу в рабочем обиходе получается какая-нибудь версия 3.98
Да и самое ли ценное в библиотеке - скрипт? KSP не настолько обширный язык, чтоб в нем имелись сотни вариантов решения проблемы, т.ч. те, кто им владеет, мне кажется, прекрасно представляют как повторить тот или иной момент в коде, а те кто не владеет не разберутся и с исходниками.... А вот иделя - да, ценна, но она всех на виду
if (in_range (<поискать число, отвечающее за играемую ноту арпеджиатором. Должна быть команда play_note или set_midi>,<нижняя граница кейсвитчей>,<верхняя граница кействитчей>))
exit
end if
вставить в on note в самое начало (в скрипт арпеджиатора естессно)
[DOUBLEPOST=1446838266,1446837885][/DOUBLEPOST]Или чуть элегантнее будет так:
Код:
if (in_range (<переменная используемая в этой команде>,<нижняя граница кейсвитчей>,<верхняя граница кействитчей>))
<команда, в которой первый слот (для ноты) заменен на 0>
else
<команда>
{это может быть так же что-то вроде
new_id:=play_note($new_note,<velocity>,0,1000)}
end if
Оказалось, все работает, но требует небольшой калибровки. Лучше всего, конечно, было бы все реализовывать через поиск продолжительности каждого конкретного сэмпла транзиции, но для этого, надо создавать отдельную строчку для каждого сэмпла, и получится жуткая портянка, с которой и я-то не факт, что разберусь. По этому используем упрощенный алгоритм настройки:
Код:
on init
declare $firstnote := (0)
declare $lastnote
declare $interval
declare $firstnote_id
declare %posintervalgrp [2] := (1,2) {создаем отдельные группы для каждого восходящего интервала для легато, и прописываем их ID в порядке возрастания интервала (от малой секунды).
ID можно посмотреть если открыть вкладку monitor/groups там где у вас иконки билиотек}
declare %negintervalgrp [2] := (3,4) {То же самое для нисходящих транзиций}
end on
on note
ignore_event ($EVENT_ID)
disallow_group ($ALL_GROUPS)
$lastnote := $EVENT_NOTE
if ($firstnote # 0)
$interval := $lastnote - $firstnote
end if
if ($interval >0)
note_off ($firstnote_id)
allow_group (%posintervalgrp [$interval-1])
play_note ($EVENT_NOTE,$EVENT_VELOCITY,0,0)
disallow_group ($ALL_GROUPS)
wait (50000) {Экспериментально-подбираемое число, отвечающее за задержку сустейн-сэмпла для проигрывания сэмпла транзиции.
Надо калибровать вместе с параметрами атаки\релиза в ADSR-envelope группы для достижения максимально реалистичного звучания}
allow_group (0) {Здесь прописываем ID группы сустейна}
play_note ($EVENT_NOTE,$EVENT_VELOCITY,0,-1)
end if
if ($interval <0)
note_off ($firstnote_id)
allow_group (%negintervalgrp [-$interval -1])
play_note ($EVENT_NOTE,$EVENT_VELOCITY,0,-1)
disallow_group ($ALL_GROUPS)
wait (50000)
{Экспериментально-подбираемое число, отвечающее за задержку сустейн-сэмпла для проигрывания сэмпла транзиции.
Надо калибровать вместе с параметрами атаки\релиза в ADSR-envelope группы для достижения максимально реалистичного звучания}
allow_group (0) {ID группы сустейна}
play_note ($EVENT_NOTE,$EVENT_VELOCITY,0,-1)
end if
if ($interval = 0)
allow_group (0) {ID группы сустейна}
play_note ($EVENT_NOTE,$EVENT_VELOCITY,0,-1)
end if
$interval :=0
$firstnote := $EVENT_NOTE
$firstnote_id := $EVENT_ID
end on
on release
$firstnote :=0
disallow_group ($ALL_GROUPS)
if ($interval = 0)
allow_group (5) {прописываем ID группы релиза}
play_note ($EVENT_NOTE,$EVENT_VELOCITY,0,0)
end if
end on
@PianoIst, я все равно не понимаю. я загрузил ваш файл, в Контакте появляется 3 играбельных ноты, как его связать с голосом? как сэмпл заменить в нем? и как играть больше нот?
@stl, Прочитайте русский текст внутри {скобок}
Создаете по отдельной группы для каждого интервала. То-есть, создаете группу m2_up, b2_up, m3_up и т.д. То же самое для перехода вниз. m2_dwn, b2_down, m3_down, b3_down.
Открываете вкладку monitoring там, где у вас файловый браузер и список библиотек и пр. и, вписываете в массивы
%posintervalgrp и %negintervalgrp ID групп через запятую. ID находится в правой колонке со списком групп. Попутно меняете значение в [скобках] возле массива на кол-во групп с интервалами.
И вписываете нужные числа по инструкции в коде.
все. Добавляете свои сэмплы в нужные группы на нужные ноты
[DOUBLEPOST=1447388138,1447349345][/DOUBLEPOST]
Не могу понять почему выскакивает варнинг типа "object ENV_AHDSR not found - index will be invalid" огибающие работают, скрипт эдитор ошибок не находит. В чём загвоздка?
без кода сказать сложно.... Первая мысль - что это не совсем энжин параметр. Группа-то у него есть, а слота нет
[DOUBLEPOST=1447856464,1447856399][/DOUBLEPOST]можно попробовать покурить на тему команды find-target
[DOUBLEPOST=1447870346][/DOUBLEPOST]Понадобились они мне тут, и нашел в сети. Пусть будут здесь
А вот такой вопрос - если мы имеем несколько групп, записанных разной громкостью (например, 7 слоёв громкости скрипок), и хочется переключаться между ними колесом модуляции, а не за счёт велосити, да ещё чтобы кроссфейд был между этими слоями - это в контакте скриптом решается или так можно, малой кровью накрутить?
малой кровью
редактируете 1-ю группу, чтобы никаких управлялок громкостью не было (вкладка mod посередине где-то)
создаете 6 групп для разных слоев.
Ставите галку edit all groups
И добавляете параметр модуляции по CC. В окошке lag поставить значение около 50
Дальше каждую группу редактируете по отдельности, рисуя огибающие в выпадающем окошке, вуаля.
[DOUBLEPOST=1450303148,1450303052][/DOUBLEPOST]вот так
Но при этом по-прежнему слои переключаются, только если я заново нажму клавишу, а без нажатия не хотят - в халионе это решается переключением New note на Held note, а в контакте как?
@V_ad_im, параметр модуляции на CC поправили?
если скрипта нет - то все должно работать. Если есть скрипт - непонятно на кой он в такой ситуации нужен))))
группы должны быть все желтенькими при взятии ноты, если все правильно.
Если не так - проверить макимальное кол-во голосов для инструмента (вверху там где название), проверить вкладку group sstart options, чтоб стояло always
и проверить, чтоб во всех группах сэмплы были растянуты на весь диапазон велосити. можно нажать кнопку selected groups only в mapping editor
Велосити у всех звуков стоят от 1 до 127, каждая нота покрывет весь диапазон.
А вот кривые для СС где правильней рисовать? потому как вкладка Mod есть в секции Amplifier, а есть ещё и в секции volume
сейчас @Ostap Fender поднял достаточно насущную проблему. Хотелось бы влыожить рассуждение по ее поводу сюда:
Расположение и работа слайдеров - не та часть, которую надо копипастить.
Надо оставить ровно столько слайдеров, сколько их будет в максимальной комплектации (експрессия, атака, релиз, сустейн, LFO, и т.д.) По одному на параметр.
Не для каждой группы собственные, а в принципе, мы ж типа аналог моделируем? Аналог не будет ручкой вращать от нажатия кнопки.
То-есть для каждого слайдера заведем мини-секцию, отделенную пропусками строк в on init, примерно так:
Код:
on init
declare ui_slider $Attack (0,127,1)
set_control_par(get_ui_id ($Attack),$CONTROL_PAR_MOUSE_BEHAVIOUR,подобрать)
set_control_par(get_ui_id ($Attack),$CONTROL_PAR_DEFAULT_VALUE,0)
set_control_par_str(get_ui_id ($Attack),$CONTROL_PAR_PICTURE,"картинка")
declare ui_slider $Release (0,127,1)
set_control_par(get_ui_id ($Release),$CONTROL_PAR_MOUSE_BEHAVIOUR,подобрать)
set_control_par(get_ui_id ($Release),$CONTROL_PAR_DEFAULT_VALUE,0)
set_control_par_str(get_ui_id ($Release),$CONTROL_PAR_PICTURE,"картинка")
end on
и т.д.
Потом в этой же мини-секции добавить по текстовой переменной, которая будет отвечать за надпись
Потом создать сетку расположения:
условно:
есть базовый х и базовый у. Из этого делается ряд переменных для расположения элементов:
$x_base (изначальное смещение по х)
$x_step (смещение каждого следующего элемента по х)
$x_width (размер кнопки\слайдера по х)
то же самое для у
$y_base
$y_step
$y_height
как минимум по три параметра, иногда надо больше.
А дальше при расположении самих элементов занимается элементарной процедурой сложения-умножения:
move_control_px ($Attack,$x_base+$x_step*3+$x_width*4, $y_base)
этой строчкой ты расположишь элемент в третью ячейку той таблицы, которую организуешь сам.
Таким образом впоследствии мы сможем изменением одной цифры менять все интервалы между контроллерами.
Потом, как и говорил во всех группах за одни и те же параметры должны отвечать одни и те же контроллеры:
во всех группах атака, скажем, будет подчиняться контроллеру 50, а релиз 51
потом в каллбеке on ui_control (переменная слайдера) добавляем команду
set_controller (номер контроллера, переменная слайдера)
Таким образом мы установим атаку во всех группах на уровень слайдера.
С текстом придется повозиться больше всего.
Нужен будет строковый массив (к примеру !Attack_indicator[128]), в котором будет храниться значение для каждого положение контроллера приравненное к ms
Легче всего это сделать так:
Код:
$i := 0
while ($i<128)
!Attack[$i] := максимальное значение атаки в ms \ на 128 * $i
inc ($i)
end while
Далее нужно придумать каким способом у нас будет выводиться текст на виртуальный дисплей.
Самый простой - сделать его в виде ui_label
и простым суммированием текстовых переменных добавлять все надписи. Будет возможно, некрасиво, но просто
При чем, это нужно будет прописать в каллбеке каждого контролера, а так же в каллбеке on init
Более сложный способ - добавление самого окошка в кач-ве картинки и расположение отдельных ui_label со скрытым фоном (hide_part (&Attack_indicator, $HIDE_PART_BG)) как нам хочется. Даст больше гибкости в настройке, но добавит геморроя.
Ну и в довершение работы над слайдерами - прописать все hide_part для тех кнопок на которых они не нужны отдельной функцией, вызываемой из всех каллбеков, или в каждом каллбеке по отдельности. Речь идет о ui-каллбеках кнопок и возможно каллбеке on note
Вообще работа над качественным интерфейсом - самая изнурительная, после нарезки сэмплов.
Искать новые алгоритмы для реализации никем не придуманных функций интересно и здорово; заниматься же постоянным копипастингом собственных формулировок с заменой одной-двух букв, в коде на 3000 строк - уныние.
[DOUBLEPOST=1457590637,1453663022][/DOUBLEPOST]еще одна концепция программирования сегодня всплыла в обсуждении:
Чтобы, скажем, одной ручкой контролировать и dry и wet сигнал конволюции в противофазе, надо сделать так:
Код:
on init
declare $i_invert
declare $i
$i_invert = 127
$i = 0
declare %invert_velocity[128]
while ($i_invert >= 0)
%invert_velocity[$i]:=$i_invert
inc ($i)
dec ($i_invert)
end while
end on
on ui_control ($drywet_slider)
set_engine_par ($ENGINE_PAR_SEND_EFFECT_DRY_LEVEL,%invert_velocity[$drywet_slider]*7874,-1,0,1)
set_engine_par ($ENGINE_PAR_SEND_EFFECT_OUTPUT_GAIN,$drywet_slider*7874,-1,0,1)
end on
при этом то, что я обозвал $drywet_slider должно быть со шкалой 127.
При этом: я добавил коэфицент умножения *7874. Это число получается, если максимальную шкалу engine-параметра разделить на 127. Но, нам же не нужно wet и dry сигналы разгонять до абсурдных значений.
Соответственно, это число должно быть меньше, выводить надо экспериментальным путем, чтобы в положении 0 слайдер выдавал 100% dry сигнала, а в положении 127 - 100% wet-сигнала. Возможно, как раз 1000 подойдет
Вообще очень полезно иметь при себе инвертированную шкалу миди-параметров, я ее использую довольно часто. К примеру, если нужно организовать какой-нибудь специфический кроссфейд. Так же можно создать несколько разных шкал, которые будут расположены по всему диапазону. В общем, стоит подумать о миди-маппинге.
сегодня открыл отвратительнейшую особенность контакта... Envelope AHDSR применяется к зоне во время ее активации. То-есть. Взяли ноту при показателе release 20ms, держим, двигаем release в значение 200ms, и отпускаем. Играет релиз 20ms. В то же время, мы спокойно можем менять частоту envelope sine, как так...
Друзья помогите пожалуйста создать мульти скрипт(multiscript ) что бы отфильтровать #CC 7 контроллер на все каналы контакта. Проблема в следующем используем контакт на живых выступлениях а на контроллерах (Гитарах) невозможно отключить этот volume -7 CC и часто гитаристы задевают его тем самым меняя баланс инструментов. Пробовал стандартным фактори миди фильтром он отрубает все контроллеры а мне нужны c #CC 1 и до #CC 6 Буду очень благодарен!
Друзья, совсем недавно начал изучать KSP и появился вопрос. Сразу прошу простить, если вопрос банален или уже обсуждался.
Делаю ручки (knob) управления громкостью групп инструмента. Нашел вот такой код (выдержки, чтобы было понятнее):
Код:
on init
declare ui_knob $Vol1 (0,631000,1)
set_knob_unit($Vol1,$KNOB_UNIT_DB)
set_knob_defval($Vol1,500000)
set_knob_label($Vol1,get_engine_par_disp($ENGINE_PAR_VOLUME,0,-1,-1))
$Vol1 := get_engine_par($ENGINE_PAR_VOLUME,0,-1,-1)
make_persistent($Vol1)
message("")
end on
Все прекрасно, все работает. Появляется ручка (knob), рядом с ней поле, в котором отображается значение в Дб уровня громкости. Из примера выше видно, что значение по-умолчанию для данной ручки 500000(или -6.0dB). Но захотелось изменить этот параметр, например на -8.0dB или на -2.0dB, к примеру. Но как узнать значение этой величины в тех единица, которые нужны скрипту?
Покрутил, повертел методом научного тыка, но закономерности не понял, вспомнил лишь, что dB - логарифмическая величина и отправился в гугл. Нашел на форумах формулу расчета уровня (dB): dB = 20 * log (V1/V2) , подставил цифирки в формулу, преобразовал выражение, но что-то не сходилось.
Выражение для расчета получалось следующее (выражаясь языком Excel):
Код:
=СТЕПЕНЬ(10;LOG10(631000) - (ABS(A)/20))
, т.е. 10 в степени LOG10(631000) - (ABS(A)/20)
, где А - уровень громкость к которому нужно прийти, например -8.0 или -5.0 или какой захочется.
И так как получаемые значение не соответствовали задумке, начал подгонять)). Экспериментально пришел к заключению, что вместо "20" в формуле, должно быть "60" и тогда все работает!
Собственно и вопрос! Почему именно "60"? Может кто-то знает физику работы этого элемента?
Наверное, можно все было сделать как-то проще, но в программировании на KSP я совсем новичок.
@Dr.NORFOLK, Чувак, ты сломал систему)
Никогда не слышал, чтоб кто-то разобрался, как оно работает)
Навскидку: дело в том, что норм шкала dB - до нуля, и от -60. (а скорее, от -63.1). А в контакте этих шкал как минимум, 4: от -12 до +12. От -120 до +12 от -120 до +6 и еще что-то.
Я просто сделал массивы, в которых записаны значения каждой из них от 0 до 127 соответственно (исходя из автоматизации в миди).
Если что - вот они.
Вообще, даже те значения, которые должны получаться простым делением - не получаются аналогичными тому, что показывает внутренний интерфейс. И это раздражает)
Подскажите, пожалуйста, какой параметр отвечает за поведение слайдеров.
Т.е., допустим, в тех скриптах, которые используются в определённых библиотеках, за движение (горизонтального!) слайдера отвечает вертикальное движение мыши, а меня интересует, как сделать, чтобы отвечало горизонтальное движение мыши.
@arkaine, set_control_par (get_ui_id(<slider>),$CONTROL_PAR_MOUSE_BEHAVIOUR,<value>)
если value положительный - движется горизонтально, если отрицательный - вертикально. Чем он больше - тем быстрее движется.