1

我正在尝试遍历缓冲区数组,每个缓冲区都包含从磁盘读取的声音样本,但我在让 SynthDef 将其指针重置为缓冲区时遇到问题。

我做了以下事情:

  1. 假设我有一个声音文件文件夹,并且我已将它们全部读入一个名为“~buffers”的缓冲区数组中

  2. 我只想按顺序浏览数组,背靠背播放样本并在最后一个之后停止。

  3. 我定义了一个简单的 SynthDef,然后把调用它的 Synth 放到一个 Routine 中:

    (
     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;
        )

但是:它非常粗糙,因为现在我无法操纵缓冲区输出,只能通过 Buffer.play 的 mul 参数更改幅度。我想做的是在我自己的代码中复制 Buffer.play 的行为——动态创建 SynthDef 和 Synth。但我没有运气。事实上我不知道从哪里开始,可能是因为我没有完全掌握 SuperCollider 的服务器对功能的处理。我应该制作一个合成器功能并在例程的循环中使用它吗?或者我应该在循环内移动 SynthDef 的定义(这似乎是等价的)?我尝试了后者,但仍然播放相同的声音。

也许我走错了路——我对 SuperCollider 很陌生。

4

2 回答 2

1

您的第一个示例中的代码是正确的。如果我用这样的缓冲区填充:

(
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在演奏前立即进行,则您的持续时间可能是例如0nil,这会导致意外结果。

于 2018-02-22T21:16:04.503 回答
0

我在一个任务中尝试过,但我认为它完全像你在日常工作中所做的那样。您必须将缓冲区放入数组中。像 buffer=[1,2,3,4,5] 但最好以这种方式编码。\buffer=[a.bufnum,b.bufnum,c.bufnum,d.bufnum] 并在 SynthDef 的 PlayBuf 的第二个参数中设置缓冲区变量。因为您可能会在服务器中加载其他缓冲区,并且如果您将缓冲区的编号放入数组中,它通常会播放您不想播放的错误缓冲区。

于 2021-07-19T05:59:28.250 回答