1

我已经阅读了一些教程,但在我看来,它们似乎都没有理解什么是明智的架构:

  1. 有一个或多个Instrument实例,
  2. 有一个Score定义了一组 Note对象,
  3. 将实例从乐谱路由到乐器的Player类(可能是函数),Note以便产生音乐。

我在这个模式中看到的,但在我到目前为止读过的例子中没有看到的是(a)乐谱和乐器之间的总分离和(b)明确的定义(以类的形式和/或 API)Note告诉仪器做什么的对象。

他们的内置实用程序是否支持这种类型的操作模式?

这是思考问题的一种不重要的方式吗?

4

2 回答 2

2

鉴于您已经查看了示例,我不确定您到底想要什么。奇数位是“完全分离”的要求;通常,分数需要对哪些参数与哪些乐器相关做出一些假设——尽管 SynthDef 中有足够的内省方法,程序可以做出有根据的猜测。

但基本原理图是相当标准的:SynthDef 定义乐器,Collection 及其子类存储数据,Routine 和其他类可以在预定的时间内解释数据结构以制作音乐。

在底部,我粘贴了一些样板代码,用于使用 SynthDef、Routine 和 Array 对这种结构进行非常简单的类似 c 的方法。使用哪种乐器是在音符生成时任意选择的,“分数”与乐器无关。

但是,SC 中的惯用方法是使用模式和事件,尤其是 Pbind 类。我个人觉得这些有点限制和冗长,但他们肯定会按照你的要求做。查看“Streams-Patterns-Events”系列帮助文件。

并且许多人已经编写了第三方扩展,例如 Instr 和 Voicer,以适应他们自己风格的乐谱乐器模型。查看 Quarks 列表或考虑推出自己的列表?

s = Server.local.boot;
s.waitForBoot{ Routine {
/// in a "real" patch, i'd make these local variables,
/// but in testing its convenient to use environment variables.
// var inst, tclock, score, playr, switchr;

// the current instrument
~inst = \ding;
// a fast TempoClock
~tclock = TempoClock.new(8);

// two instruments that take the same arguments
SynthDef.new(\ding, {
    arg dur=0.2, hz=880, out=0, level=0.25, pan=0.0;
    var snd;
    var amp = EnvGen.ar(Env.perc, doneAction:2, timeScale:dur);
    snd = SinOsc.ar(hz) * amp * level;
    Out.ar(out, Pan2.ar(snd, pan));
}).send(s);

SynthDef.new(\tick, {
    arg dur=0.1, hz=880, out=0, level=0.25, pan=0.0;
    var snd;
    var amp = EnvGen.ar(Env.perc, doneAction:2, timeScale:dur);
    snd = LPF.ar(WhiteNoise.ar, hz) * amp * level;
    Out.ar(out, Pan2.ar(snd, pan));
}).send(s);

s.sync;

// the "score" is just a nested array of argument values
// there are also many kinds of associative collections in SC if you prefer
~score = [
    // each entry:
    // midi note offset, note duration in seconds, wait time in beats
    [0, 0.4, 2],
    [0, 0.4, 1],
    [7, 0.2, 1],
    [0, 0.2, 1],
    [7, 0.15, 1],
    [10, 0.5, 2],
    [7, 0.1, 1],
    [2, 0.3, 1]

];

// a routine that plays the score, not knowing which instrument is the target
~playr = Routine { var note, hz; inf.do({ arg i;
    // get the next note
    note = ~score.wrapAt(i);
    // interpret scale degree as MIDI note plus offset
    hz = (note[0] + 60).midicps;
    // play the note
    Synth.new(~inst, [\hz, hz, \dur, note[1] ], s);
    // wait
    note[2].wait;
}); }.play(~tclock);


// a routine that randomly switches instruments
~switchr = Routine { var note, hz; inf.do({ arg i;
    if(0.2.coin, {
        if(~inst == \ding, {
            ~inst = \tick;
        }, {
            ~inst = \ding;
        });
        ~inst.postln;
    });
    // wait
    1.wait;
}); }.play(~tclock);

}.play; };
于 2012-08-16T01:26:03.373 回答
0

我还要补充一点,有一组名为 Ctk 的扩展(一个“夸克”)它包装了 SynthDef(到 CtkSynthDef)、音符的概念(到 CtkNote)和乐谱(到 CtkScore)促进工作在两个真实时间和非实时。我觉得其帮助文件提供的示例(大部分)遵循 OP 建议的架构。要安装它,请Quarks.install("Ctk")在 SuperCollider 中运行。

于 2018-06-06T22:59:10.470 回答