ReaScripts (скрипты для Reaper) - обсуждение

  • Автор темы Автор темы drzhnn
  • Дата начала Дата начала
@EUGEN27771, не замечал, что чем больше сохранено пресетов у плагина, тем дольше между ними переключаться и дольше открывается плагин (при добавлении на трек и просто при открытии окна)? На всяких спайрах и тд очень хорошо ощущается.
это может означать, что если пресетов много, то лучше использовать свою систему пресетов, которая будет работать через чанки.
А еще лучше было бы наверно иметь возможность сохранять и загружать внутренние пресеты плагина, они вообще моментально загружаются
 
@lil-burn, через чанки, если простыня чанков (они же пресеты) будет аналогичной списку пресетов в ini - будет грузиться также долго.
Грузить пресеты плагина:
А как их туда записывать из Рипера? А что делать с плагинами, у которых система пресетов типпа как в Bias Fx?

Вообще-то, по идее система пресетов Рипера столь же интеллектуальна, как и чанки и не грузит по новой уже загруженный пресет, не тратит на это время - там есть контрольные суммы, которые в начале считываются.
Вот бы сделать что-то аналогичное и с данными изменившихся параметорв в новом пресете - грузить только их, игнорируя не менявшиеся.
 
@Aleksandr Oleynik, сделал для себя минимальную версию системы пресетов: в окне отображается список пресетов для эффекта в фокусе, при клике устанавливается выбранный пресет для эффекта в фокусе, при нажатии на колесо - сохраняется текущий пресет - в виде куска чанка, кот. отвечает за данные эффекта. Достаточно быстро загружается.

@Aleksandr Oleynik, @EUGEN27771,
а контрольные суммы находятся в начале куска base64 или в конце?

для многих vst-эффектов чанк непостоянный - к примеру, тот же контакт - каждую секунду разный чанк, хотя параметры одинаковые. Там по-моему то ли счетчик стоит, то ли еще что-то но чанки разные.
Это одна из вещей (вместе с невозможностью быстрого перемещения треков), которая застопорила создание скрипта, синхронизирующего работу проекта на нескольких компьютерах одновременно (этот скрипт требует однозначного определения, были ли изменены параметры эффекта, т.к. передавать чанки имеет смысл только при изменении эффекта)

вот гляньте - The glue
chunks.gif
видно, что в одном месте как будто счетчик стоит, зачем-то считает время, причем даже не каждую секунду, а еще чаще. в контакте вообще несколько таких "очагов".
Хотя есть и эффекты, где не меняется чанк, например Effectrix. Ну и в js конечно не меняется
 
@EUGEN27771, интересно)
это будет работать, если эффектов нет?
__________
у меня пока
PHP:
function ExtractBrackets(str)
  local s, other, f = '',''
  local count = 1
  for line in str:gmatch('[^\n]+') do
    if not f then
      s = s..'\n'..line
      if line:sub(1,1) == '<' then count = count +1 end
      if line:sub(1,1) == '>' then count = count -1 end
      if count == 0 then f = 1 end
    else other = other..'\n'..line end
  end
  if s:sub(-1) == '>' then s = s:sub(1,-2) other = '>'..other end
  return s, other
end

function get_tr_fx_chain(tr,chunk)
  if chunk:match'\n<FXCHAIN\n' then
    local a,b,c
    a,b = chunk:match'(.-\n<FXCHAIN\n)(.*)'
    b,c = ExtractBrackets(b)
   
   
    return a,b,c
  end
end
 
  • Like
Реакции: RJ Baker
@EUGEN27771,
а для вставки вот такое
PHP:
function add_tr_fx_chain(tr, chunk, new_chain, replace7)
  local fx = r.TrackFX_GetCount(tr)
  local fx_chain

  a,b,c = get_tr_fx_chain(tr,chunk)

  if b then
    if replace7 and replace7~=0 then
      chunk = a..new_chain..'\n'..c
    else
      chunk = a..b..new_chain..'\n'..c
    end
  else
    local a,b,c
    a, c = chunk:match'(.-\nMAINSEND.-\n)(.*)'
    b = '<FXCHAIN\n'..new_chain..'\n>\n'
    chunk = a..b..c
  end

  SetTrackChunk(tr, chunk)

end
new_chain - содержимое файла цепи RfxChain (такая задача сейчас)
replace7 == 1 заменяет цепь на треке, иначе добавляет в конец
 
  • Like
Реакции: RJ Baker
@EUGEN27771, аналог SWS Resources. только при запуске скрипта создает список всех цепей эффектов (из папки FXChains), темплейтов (из папки TrackTemplates), и пресетов (из папки presets). И из этого списка пользователь добавляет в проект все что нужно
 
  • Like
Реакции: EUGEN27771
в SWS resources используется "умный скролл" *. Например при добавлении трек-темплейтов происходит следующее:
- если первый добавленный трек находится в поле видимости (если его видно в данный момент в tcp), то ничего не происходит
- иначе происходит скролл к этому треку.

* "умный" - по сравнению с экшеном Track: Vertical scroll selected tracks into view, который всегда устанавливает первый выделенный трек в середину треклиста

По скроллу в апи нашел пока только такие варианты:
reaper.CSurf_OnScroll( xdir, ydir )
reaper.CSurf_OnArrow( whichdir, wantzoom )
но это скроллы относительно текущего положения

В общем не могу пока добиться такого поведения скролла, как в SWS resources
 
@lil-burn а у вас нет такого скрипта, чтобы выделенные треки попадали в первую выделенную группу ?
 

Вложения

  • Gif.gif
    Gif.gif
    191 KB · Просмотры: 149
@EUGEN27771, на кокосах видел потестил, очень круто.
Теперь будет в разы удобнее работать с чанками.

Кстати, не было еще желания написать свой текстовый редактор скриптов? В риперовском не хватает некоторых вещей, которые бы заметно ускорили написание скриптов:
- комментирование выделенных строк (toggle) одним нажатием
- перемещение строк с помощью например rightdrag - очень часто приходится перемещать куски текста или просто менять местами строки
- темплейты-шаблоны: при создании нового скрипта может к примеру автоматом добавляться шапка и тд
- вкладки скриптов: можно открывать не каждый скрипт в отдельном IDE окне, а в одном окне в нескольких вкладках
- добавление функций и просто кусков кода по названиям и тегам, с фильтром (помнишь, показывал скрипт: список функций с фильтром - вводишь название - щелкаешь по нужной функции - текст функции копируется в буфер обмена, потом его добавляешь в редактор через Ctrl+V)
scripter is back.gif
так вот при частом использовании напрягает немного, что надо переходить из окна IDE в окно скриптера (со списком функций) и жмакать каждый раз Ctrl+V. А если это встроить в свой редактор, будет гораздо удобнее.
А потом можно пойти еще дальше и запилить, чтобы функции добавлялись с учетом уже написанного текста, то есть например было
my_item = r.GetSelectedMediaItem(0,0)
если после этого добавить функцию r.GetMediaItemInfo_Value() то она добавится как it_start = r.GetMediaItemInfo_Value(my_item, 'D_POSITION') именно с переменной my_item
- + удаление неиспользуемых функций в один клик, оптимизация кода (например замена глобальных переменных на локальные) и тд
В общем можно много чего полезного замутить, что будет люто экономить время
 
  • Like
Реакции: stepperian
Подскажите, коллеги, в какую сторону смотреть для решения следующей задачи: миди сообщения SysEx нужно передать по OSC, в сообщениях содержится массив 8ми битных чисел, т.е. это не команды, мне числа и нужны. Все это надо в потоке. Или скриты для этого не подойдут, они все больше по оффлайн операциям?
 
Последнее редактирование:
Подскажите, коллеги, в какую сторону смотреть для решения следующей задачи: миди сообщения SysEx нужно передать по OSC, в сообщениях содержится массив 8ми битных чисел, т.е. это не команды, мне числа и нужны. Все это надо в потоке. Или скриты для этого не подойдут, они все больше по оффлайн операциям?
https://www.cockos.com/oscii-bot/
 
@lil-burn, есть замечательный Эдитор для скриптов с модулем под lua -
https://atom.io/
В нём есть абсолютно всё нужное.
Думаю можно написать и модуль для регистрации изменений в Рипере тоже.
 
  • Like
Реакции: lil-burn
@EUGEN27771,
Смотри разве не удобно?)
script editor.gif
начал в общем на основе твоего скрипта писать редактор
Сохранение и загрузку (save/ load) добавить очень легко, остальное нарастет
Единственное - список переменных как сделать (в правом окне), пока не ясно

есть замечательный Эдитор
посмотрю, спасибо
 
Хочу сделать что-то вроде голосового управления рипером.
Почти все что нужно есть
Нашел
PHP:
import speech_recognition as sr
import os
import datetime

class Speech_AI:

    def __init__(self):
        self._recognizer = sr.Recognizer()
        self._microphone = sr.Microphone()
        now_time = datetime.datetime.now()
        self._mp3_name = now_time.strftime("%d%m%Y%I%M%S")+".mp3"
        self._mp3_nameold='111'

    def work(self):
        with self._microphone as source:
            self._recognizer.adjust_for_ambient_noise(source)

        try:
            while True:
                with self._microphone as source:
                    audio = self._recognizer.listen(source)
                try:
                    statement = self._recognizer.recognize_google(audio, language="ru_RU")
                    statement=statement.lower()
                   
                    print(format(statement))
                   
                except sr.UnknownValueError:
                    a = 1
                except sr.RequestError as e:
                    a = 1
        except KeyboardInterrupt:
            self._clean_up()

    def _clean_up(self):
        def clean_up():
            os.remove(self._mp3_name)

def main():
    ai = Speech_AI()
    ai.work()

main()
и немного упростил его - скрипт выводит текст, который я наговариваю в микрофон.
работает так
voice.gif
но не работает в рипере - зависает. Думаю, что надо куда-то добавить дефер, но пока не ясно, куда именно (пробовал по-разному).
Есть идеи?
 
@vitalker, маловероятно, думаю тогда бы появилась ошибка. есть конфа разработчиков скриптов рипера, там сейчас ответили, что надо создавать отдельный "поток", буду разбираться
 
  • Like
Реакции: vitalker
Доброго времени суток! Ребята, давно мучает меня вопрос , как менять программно в графическом скрипте высоту окна (можно ли сделать при помощи функция gfx.init (не в ручную) заранее спасибо
 
@EUGEN27771,
себе в скриптер добавил только что поддержку ввода кириллицы в строку фильтра, работает как надо.
test kyrillic.gif
У тебя алгоритм другой, но тоже должно работать, надо просто подумать как лучше сделать. могу прислать код
 
@EUGEN27771, кстати вопрос по GUI: можно ли как-то активировать окно скрипта, если фокус не на нем, а например на аранже?
только через gfx.init()?
 
@EUGEN27771, проблема была из-за gfx.setfont()
у меня пару месяцев назад слетела тема. И пошли баги с оформлением на многих программах. Руки пока все не доходят переустановить винду.
вот так работает:
PHP:
--[[
В cp1251 русские буквы А-Яа-я (без буквы Ёё) занимают диапазон ASCII кодов 192-255 (0xC0-0xFF)
а в юникоде - 1040-1104 (0x0410-0x044F).
Разница как раз 848.
--]]
--------------------
str_tb = {}
local c_pos = 0

----------------------------------------
gfx.clear =  0
--gfx.setfont(1,"Tahoma",22)

gfx.init("Test", 500,300,0,200,200)

--------------------
function minmax(x, minv, maxv)
  return math.min(math.max(x, minv),maxv)
end

----------------------------------------
function DrawText(str_tb)
  gfx.set(1)
  gfx.setfont(1, 'Verdana',16)
  ------------------
  gfx.x, gfx.y = 10, 0
  gfx.drawstr("last char: ")
  gfx.drawnumber(last_char, 0)
  ------------------
  local s_x, s_y = 10, 20
  gfx.x, gfx.y = s_x, s_y
  if c_pos == 0 then gfx.line(gfx.x, gfx.y, gfx.x, gfx.y + gfx.texth) end
  ------------------
  for i = 1, #str_tb do
    local c = str_tb[i]
    if c == 13 then
      gfx.x, gfx.y = s_x, gfx.y + gfx.texth -- next line
    else
      gfx.drawchar(c)
    end
    if i == c_pos then gfx.line(gfx.x, gfx.y, gfx.x, gfx.y + gfx.texth) end -- cursor
  end
   
end


----------------------------------------
function mainloop()

  mouse_down = gfx.mouse_cap&1 == 1 and mouse_last_cap&1 == 0
  mouse_last_cap = gfx.mouse_cap

  char = gfx.getchar()

  if char > 0 then last_char = char end -- For Test!
  if char == 13 then table.insert(str_tb, c_pos+1, char); c_pos = c_pos+1 end
  if char > 31 and char < 127 then table.insert(str_tb, c_pos+1, char); c_pos = c_pos+1 end
  if char > 127 and char < 256 then table.insert(str_tb, c_pos+1, 848 + char); c_pos = c_pos+1 end
  ---------------
  if char == 8 and c_pos > 0 then table.remove(str_tb, c_pos); c_pos = c_pos-1 end
  if char == 1818584692 then c_pos = minmax(c_pos-1, 0, #str_tb) end
  if char == 1919379572 then c_pos = minmax(c_pos+1, 0, #str_tb) end
  DrawText(str_tb)
  ---------------

  if char~=-1 then reaper.defer(mainloop) end --defer
  gfx.update();

end

mainloop()
[DOUBLEPOST=1503082808][/DOUBLEPOST]то есть если просто убрать gfx.setfont(1,"Tahoma",22) в начале и поставить ее в функцию DrawText(str_tb) то все ок. Причем от названия шрифта это не зависит
now its ok.gif
 
Последнее редактирование:
@EUGEN27771, а, ну разобрался, получается так
PHP:
  if char > 127 and char < 256 then
    if char == 184 then
      table.insert(str_tb, c_pos+1, 1105)
    elseif char == 168 then
      table.insert(str_tb, c_pos+1, 1025)
    else
      table.insert(str_tb, c_pos+1, 848 + char)
    end
    c_pos = c_pos+1
  end
 

Сейчас просматривают