1

私はいくつかのチュートリアルを経験しましたが、私の意見では、賢明なアーキテクチャとは何かに到達しているようには見えません。

  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などのサードパーティの拡張機能を作成しています。クォークのリストをチェックするか、自分でローリングすることを検討しますか?

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 に答える