Зацикливание буферного массива в суперколлайдере

Я пытаюсь перебрать массив буферов, каждый из которых содержит образец звука, считанный с диска, но у меня возникают проблемы с получением SynthDef для сброса указателя на буферы.

Я сделал следующее:

  1. Предположим, у меня есть папка со звуковыми файлами, и я прочитал их все в массиве буферов, называемых «~ буферами».

  2. Я просто хочу пройтись по массиву по порядку, воспроизведя образцы подряд и остановившись после последнего.

  3. Я определяю простой SynthDef, а затем помещаю Synth, который вызывает его, в процедуру:

    (
     SynthDef(\playBuffer,{arg out = 0, buf;
             var sig;
             sig = PlayBuf.ar(2, buf, doneAction: Done.freeSelf); 
             Out.ar(out, sig);
             }).add
    
     ~routine = Routine({
                ~buffers.do({
                    arg item;
                    var synth;
                    synth = Synth(\playBuffer, [\buf, item]);
                    item.duration.wait;
                    synth.free;
                 });
               });
    ~routine.play;   
    )    
    

Это не работает должным образом --- синтезаторы всегда воспроизводят один и тот же звук, первый, хотя длительность соответствует разным семплам.

Я думаю, проблема может заключаться в том, что функция внутри моего \playbuffer SynthDef (по крайней мере, согласно файлам справки) не переоценивается с другим аргументом bufnum внутри цикла.

На самом деле я могу перебирать буферы, если использую Buffer.play, который создает synthDef и Synth на лету. Замена моей процедуры этим кодом работает:

       (
        ~routine2 = Routine({
                     ~buffers.do({
                      arg item;
                      item.play;
                      item.duration.wait;
                    });
                 });
         ~routine2.play;
        )

НО: это очень грубо, так как теперь я не могу манипулировать выводом буфера, кроме изменения амплитуды через параметр mul в Buffer.play. Что я хотел бы сделать, так это воспроизвести поведение Buffer.play --- создание SynthDef и Synth на лету --- в моем собственном коде. Но мне с этим не везет. На самом деле я не уверен, с чего начать, возможно, потому, что я не полностью понимаю, как сервер SuperCollider обрабатывает функции. Должен ли я сделать функцию создания синтезатора и использовать ее внутри цикла подпрограммы? Или я должен переместить определение SynthDef внутрь цикла (что кажется эквивалентным)? Я пробовал последний, но все равно играл тот же звук.

Возможно, я иду по неправильному пути --- я очень новичок в SuperCollider.


person stefano    schedule 22.02.2018    source источник


Ответы (2)


Код в вашем первом примере правильный. Если я заполняю буферы следующим образом:

(
s.makeBundle(nil, {
    ~buffers = [1, 2, 3, 4, 5].collect {
        |i|
        var b;
        b = Buffer.alloc(s, 44100, 1);
        b.sine3([100, 150, 175] * i, 0.25);
    };
})
)

а затем воспроизведите их с помощью примера кода:

(
SynthDef(\playBuffer,{arg out = 0, buf;
    var sig;
    sig = PlayBuf.ar(1, buf, doneAction: Done.freeSelf); 
    Out.ar(out, sig);
}).add;

~routine = Routine({
    ~buffers.do({
        arg item;
        Synth(\playBuffer, [\buf, item]);
        item.duration.wait;
    });
});
~routine.play;   
) 

Это работает нормально, я слышу восходящие тона. (Я изменил ваш пример на одноканальные буферы и удалил .free, как вы уже делали Done.freeSelf). Если вы каждый раз слышите один и тот же звук, проблема, скорее всего, в коде, где вы загружаете свои буферы, а не в воспроизведении.

Одна загвоздка: свойство duration буфера недоступно сразу после их загрузки — чтение аудиофайла происходит асинхронно, и SC не знает продолжительность, пока он не загружен. Если вы делаете Buffer.read непосредственно перед игрой, есть шанс, что ваша продолжительность может быть, например, 0 или nil, что может привести к неожиданным результатам.

person scztt    schedule 22.02.2018
comment
Удивительно, но когда я вернулся к своему файлу и снова попробовал первое решение, чтобы доказать, что вы ошибаетесь, оно сработало. Должно быть, я сделал что-то не так не столько при чтении звуков в буферы (иначе вторые решения не сработали бы), сколько при их извлечении (буферы на самом деле являются частью более сложной структуры данных, Dic of Dic) . Спасибо за прояснение вопроса! - person stefano; 23.02.2018

я попробовал это в задаче, но я думаю, что это полностью похоже на то, что вы будете делать в рутине. вы должны поместить буферы в массив. например, buffer=[1,2,3,4,5], но кодировать лучше так. \buffer=[a.bufnum,b.bufnum,c.bufnum,d.bufnum] и установите переменную буфера во втором аргументе PlayBuf в SynthDef. потому что вы можете загрузить чужой буфер на свой сервер, и если вы поместите номер буфера в массив, он обычно будет воспроизводить неправильный буфер, который вы не хотите воспроизводить.

person soelz    schedule 19.07.2021