Как преобразовать переменную скорости управления в скалярное значение?

В SuperCollider: как преобразовать переменную скорости управления в скалярное значение?

Например, у меня есть скалярная глобальная переменная с именем ~delay, и несколько функций заботятся об этом значении. Они предполагают, что это скаляр. Я хотел установить генератор огибающей для этой переменной, чтобы изменить ее с помощью переменной скорости управления. Или используйте MouseX.kr, если бы я мог преобразовать одно значение MouseX.kr в скалярное значение, я был бы счастлив.

Предположим, что я не могу реорганизовать код, чтобы разрешить глобальную k-скорость, и поэтому мне нужно выбрать или уменьшить выборку одного значения из переменной скорости управления.

Я не могу сделать это:

    MouseX.kr(1, 4, 1).rand.wait;

Но я был бы рад этому:

    downSample(MouseX.kr(1, 4, 1)).rand.wait;

Or

    ~mousex = MouseX.kr(1, 4, 1)
    ...
    downSample(~mousex).rand.wait

person Hapus    schedule 14.04.2013    source источник


Ответы (2)


Это классическая проблема SuperCollider язык-против-сервера. Вы хотите использовать MouseX (который представляет информацию сервера о положении мыши) в расчетах на стороне языка. («Почему разделение? Почему язык не может узнать это, используя один и тот же объект?» — ну, представьте, что два процесса выполняются на разных машинах — разных мышах...)

Чтобы получить положение мыши в языке, лучше использовать один из:

 Platform.getMouseCoords  // SC up to 3.6
 GUI.cursorPosition // SC recent versions

Если вы уверены, что хотите использовать данные сервера на языке, то ваш собственный ответ об отправке через Автобус — один из способов сделать это. В последних версиях SuperCollider есть методы

 Bus.getSynchronous
 Bus.setSynchronous

которые полагаются на новый «интерфейс общей памяти» между языком и сервером. Если они находятся на одном компьютере, то это может быть хорошим способом сделать это, чтобы избежать задержки асинхронного запроса информации.

person Dan Stowell    schedule 15.04.2013

После долгих исследований я нашел одно решение: использовать управляющую шину для захвата значений. Мы берем функцию в качестве входных данных (f) и затем воспроизводим ее на шине.

Затем мы читаем из этой шины, вызывая метод get на шине и предоставляя функцию, которая позволяет нам извлечь значение из введенной функции.

    ~mkscalarfun = {
        arg f={ 0 };
        var last = 0.0;
        var mbus = Bus.control(s, 1);   
        var pf = f.play(s,mbus);
        var scalarf = {
            mbus.get({|v| last = v;});
            last;
        };
        scalarf; // This is a function
    };
    // Create a closure that includes the bus
    ~mousescalarf = ~mkscalarfun.({ MouseX.kr(1,  4, 1); });
    ~mousescalarf.();
    ~mousescalarf.().rand.wait;

Я не уверен, насколько идиоматично это решение, подходит ли оно или насколько хорошо оно работает.

Одна проблема с этим решением заключается в том, что pf скрыт, и поэтому вы не можете его остановить.

Одной из альтернатив является использование объектно-ориентированного решения, в котором вы создаете класс в своем каталоге расширений:

    MakeScalarKR {
        var last;
        var mbus;
        var pf;
        var f;
        *new { arg sbase,f;
            ^super.new.init(sbase,f)
        }
        init { 
            arg sbase,myf;
            f = myf;
            last = 0.0;
            mbus = Bus.control(sbase, 1);   
            pf = f.play(sbase, mbus);
        }
        v {
            mbus.get({|x| last=x;});
            ^last
        }
        free {
            pf.free
        }
    }

Затем вы можете вызвать этот класс следующим образом:

    ~mkr = MakeScalarKR(s,{ MouseX.kr(10,400,1) });
    ~mkr.v()
person Hapus    schedule 15.04.2013