2013-08-08 4 views
1

я построил следующую простую структуру синтезатора, которая создает синтезатор и направляет его выход через эффекты блок:Почему это важно, как я выполняю этот код?

b = Bus.audio(numChannels: 2); 

SynthDef(
    "mySynth", 
    { 
     |freq, amp, gate = 1| 
     var vol = 0.5; 
     var audio = Pulse.ar(freq, 0.5); 
     var env = EnvGen.kr(Env.perc, doneAction:2); 
     audio = Pan2.ar(audio, MouseX.kr(-1, 1)); 
     Out.ar(b, audio * env); 
    } 
).add; 


SynthDef(
    "effects", 
    { 
     var audio = In.ar(b, 2); 
     audio = LPF.ar(audio, MouseY.kr(200, 1000)); 
        //TODO: Implement some crazy, revolutionary effects 
      Out.ar(0, audio); 
    } 
).add; 

// **** Dividing line for executing the code **** 

e = Synth(\effects); 

p = Pbind(*[ 
    instrument: \mySynth, 
    scale: #[0, 2, 4, 5, 7, 9, 11], 
    degree: Pseq([3,  3,  9,  9,  2,  9,  9,  3,  5,  7], inf), 
    dur:  Pseq([0.2, 0.2, 0.2, 0.1, 0.1, 0.2, 0.2, 0.2, 0.1, 0.1], inf), 
    amp:  Pseq([1,  0.6, 0.9, 0.3, 0.4, 0.9, 0.6, 0.85, 0.3, 0.4], inf), 
]); 

p.play; 

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

  • Я могу выполнить каждый блок по отдельности, и я получаю звуковой вывод.
  • Я могу выполнить первые блоки до комментария разделительной линии, а затем следующие блоки, и я получаю слышимый вывод.
  • Если я выполняю весь код вместе, я не получаю слышимый вывод.

Я предполагаю, что там должна быть некоторая задержка между объявляя SynthDef, а затем создать его экземпляр с помощью Synth(), в то время как сервер не установлен настройки материала. Может ли кто-нибудь пролить свет?

ответ

1

Это потому, что вы не можете просто «добавить» SynthDefs на сервер и создать экземпляр указанного синтезатора в том же самом исполнении. Если вы «играете» синтезаторы по мере их запуска, то их экземпляр добавляется на сервер, так что, когда вы вызываете Synth для выполнения, он уже будет загружен. Рабочий код приведен ниже.

(
b = Bus.audio(numChannels: 2); 

SynthDef(
    "mySynth", 
    { 
     |freq, amp, gate = 1| 
     var vol = 0.5; 
     var audio = Pulse.ar(freq, 0.5); 
     var env = EnvGen.kr(Env.perc, doneAction:2); 
     audio = Pan2.ar(audio, MouseX.kr(-1, 1)); 
     Out.ar(b, audio * env); 
    } 
).play; 

SynthDef(
    "effects", 
    { 
     var audio = In.ar(b, 2); 
     audio = LPF.ar(audio, MouseY.kr(200, 1000)); 
        //TODO: Implement some crazy, revolutionary effects 
      Out.ar(0, audio); 
    } 
).play; 



// **** Dividing line for executing the code **** 

e = Synth(\effects); 

p = Pbind(*[ 
    instrument: \mySynth, 
    scale: #[0, 2, 4, 5, 7, 9, 11], 
    degree: Pseq([3,  3,  9,  9,  2,  9,  9,  3,  5,  7], inf), 
    dur:  Pseq([0.2, 0.2, 0.2, 0.1, 0.1, 0.2, 0.2, 0.2, 0.1, 0.1], inf), 
    amp:  Pseq([1,  0.6, 0.9, 0.3, 0.4, 0.9, 0.6, 0.85, 0.3, 0.4], inf), 
]); 

p.play; 
) 
+0

Спасибо, что ответили на исправление моего собственного кода. Всегда полезно. Так что все, что мне нужно было сделать, это вызвать 'play' вместо' add'? Ой! – David

1

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

Я не очень опытный, с sclang, чтобы сразу сказать вам, как вы должны изменить свой код (я обычно использую scsynth через OSC, только используя sclang для записи SynthDefs), но вы можете что-то сделать с помощью факультативно completionMsg аргумент SynthDef.add.

+0

Благодаря Питер, я буду смотреть на это. – David

+0

В качестве альтернативы вы можете прослушивать сообщения OSC/'/ done/d_load' OSC, но я полагаю, что в рамках sclang механизм, о котором я упоминал ранее, вероятно, проще. Удачи! – PeterT

2

Обычно я обхожу это с помощью метода Server.sync(). Он приостанавливает выполнение входящего потока (например, Routine) до тех пор, пока все команды асинхронного сервера не будут завершены. Сюда входит отправка SynthDefs и выделение буферов. Вы можете передать аргумент условия Server.sync() для более явного управления.

так, например, вы можете выполнить этот блок на одном дыхании:

s = Server.local; 
s.boot; 
s.doWhenBooted({ 
    Routine { 
     SynthDef.new(\sine, { 
      arg out=0, hz=220, dur=4.0; 
      var snd, amp; 
      snd = SinOsc.ar(hz); 
      amp = EnvGen.ar(Env.linen(0.1, dur, 0.1), doneAction:2); 
      Out.ar(out, (amp*snd).dup); 
     }).send(s); 
     s.sync; // waits here 
     x = Synth.new(\sine); 
    }.play; 
});