2013-02-23 66 views
1

在發佈此問題之前,我已經計算出問題了。不過,我認爲這可能會幫助其他人,所以我仍然發佈它。如果有人知道更好或更優雅的方式來做到這一點,請發表一個答案。如果我同意,我當然會接受你的回答。這是我原來的問題:JSyn:兩個通道上的正弦波

我試圖讓下面用JSyn工作:

我想在兩個通道發揮800Hz的正弦波,開啓或關閉時,我想單獨的通道。所以,舉例來說,我想下面的順序:

time 0s 0.3s  0.8s 1s   1s 1.1s 1.5s 
left |--------------------|    |-----------| 
right |----|   |------------------------|   

我可以生成在任何一個正弦波,或兩個通道,但我還沒有想出如何將它們開/關。下面是一些代碼:

import com.jsyn.JSyn; 
import com.jsyn.Synthesizer; 
import com.jsyn.unitgen.LineOut; 
import com.jsyn.unitgen.SineOscillator; 

public class MusicTest { 
    public static void main(String[] args) { 
     playSound(); 
    } 

    public static void playSound() { 
     Synthesizer synth = JSyn.createSynthesizer(); 
     try { 
      synth.start(); 
      SineOscillator sineOsc1 = new SineOscillator(500, 0.2); 
      SineOscillator sineOsc2 = new SineOscillator(500, 0.2); 
      LineOut lineOut= new LineOut(); 

      synth.add(lineOut); 
      synth.add(sineOsc1); 
      synth.add(sineOsc2); 

      sineOsc1.output.connect(0, lineOut.input, 0); // left channel 
      sineOsc2.output.connect(0, lineOut.input, 1); // right channel 

      lineOut.start(); 

      sineOsc1.start(); // start left 
      sleep(1000); 
      sineOsc2.start(); // after 1s, start right 
      sleep(1000); 
      sineOsc1.stop(); // after 1s, stop left 
      sleep(1000); 
      sineOsc2.stop(); // after 1s, stop 

      lineOut.stop(); 
     } finally { 
      synth.stop(); 
     } 
    } 

    private static void sleep(int ms) { 
     try { 
      Thread.sleep(ms); 
     } catch (InterruptedException e) {} 
    } 
} 

不幸的是,這並不工作...

回答

2

第一個例子不起作用的原因是JSyn通過連接的單元生成器「拉」數據。

start()方法將一個單位添加到引擎直接執行的單元列表中。你開始()一個鏈的結尾,例如LineOut。當一個單元執行時,它要求連接到其輸入的任何單元的數據。這些單位反過來要求與他們有關的任何單位的數據。這保證了單元以最小化延遲的順序執行。 JSyn檢查循環連接以防止無限循環。

即使您停止()蹬SineOscillators,LineOut仍然在拉他們。所以他們發出聲音。

而不是調用振盪器上的start()或stop(),調用setEnabled(f)。這將阻止數據的提取。嘗試此代碼段中的第一個例子:

sineOsc1.setEnabled(false); // begin disabled 
sineOsc2.setEnabled(false); 
lineOut.start(); 

sineOsc1.setEnabled(true); // start left 
sleep(1000); 
sineOsc2.setEnabled(true); // after 1s, start right 
sleep(1000); 
sineOsc1.setEnabled(false); // after 1s, stop left 
sleep(1000); 
sineOsc2.setEnabled(false); // after 1s, stop 

另一種方法是使用一個振盪器和連接它通過一個乘法單元,用於將線路輸出的每個信道。然後,您可以通過乘以1.0或0.0打開或關閉該通道上的正弦。這可以讓你乘以一個標量,例如。 0.5,如果你想成爲一半。

 
    sineOsc ---> multiply1 ---> lineOut(0) // left channel 
      `--> multiply2 ---> lineOut(1) // right channel 

我意識到setEnabled()和start()方法沒有很好的記錄。我現在會解決這個問題。

+0

非常感謝philburk的解釋。你的解決方案肯定比我的看起來更清潔今晚我會嘗試一下。 – brimborium 2013-02-25 16:42:52

+0

好的,我能夠測試它,並且您的解決方案完美無缺。 (其實,我沒有期望從JSyn的創建者那裏獲得^^)再次感謝您的幫助。 – brimborium 2013-02-27 13:42:27

0

解決的辦法是不要試圖打開/關閉正弦波,但只使用兩個LineOut。像這樣:

public static void playSound() { 
    Synthesizer synth = JSyn.createSynthesizer(); 
    try { 
     synth.start(); 
     SineOscillator sineOsc1 = new SineOscillator(500, 0.2); 
     LineOut lineOut1 = new LineOut(); 
     LineOut lineOut2 = new LineOut(); 

     synth.add(lineOut1); 
     synth.add(lineOut2); 
     synth.add(sineOsc1); 

     sineOsc1.output.connect(0, lineOut1.input, 0); // connect to left channel 
     sineOsc1.output.connect(0, lineOut2.input, 1); // connect to right channel 

     lineOut1.start(); // start left 
     sleep(1000); 
     lineOut2.start(); // after 1s, start right 
     sleep(1000); 
     lineOut1.stop(); // after 1s, stop left 
     sleep(1000); 
     lineOut2.stop(); // after 1s, stop 
    } finally { 
     synth.stop(); 
    } 
} 

我不知道這是否是最優雅的解決方案,但它的工作真的很棒。我希望這對別人有幫助。