1

在发布此问题之前,我已经解决了问题。不过我认为这可能对其他人有帮助,所以我还是发布了它。如果有人知道更好或更优雅的方法来做到这一点,请发布答案。如果我同意,我当然会接受你的回答。这是我原来的问题:

我正在尝试使以下内容与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) {}
    }
}

不幸的是,这不起作用......

4

2 回答 2

2

第一个示例不起作用的原因是 JSyn 通过连接的单元生成器“拉”数据。

start() 方法将一个单元添加到由引擎直接执行的单元列表中。您 start() 链的末端,例如 LineOut。当一个单元执行时,它会从连接到其输入的任何单元中请求数据。反过来,这些单元从与其连接的任何单元请求数据。这保证了单元以最小化延迟的顺序执行。JSyn 检查循环连接以防止无限循环。

即使您 stop()ped 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

另一种方法是使用一个振荡器并通过乘法单元将其连接到 LineOut 的每个通道。然后,您可以通过乘以 1.0 或 0.0 打开或关闭该通道上的正弦波。这允许您乘以标量,例如。0.5,如果你想半开。

    sineOsc ---> multiply1 ---> lineOut(0) // 左声道
            `--> multiply2 ---> lineOut(1) // 右声道

我意识到 setEnabled() 和 start() 方法没有很好的记录。我现在会解决这个问题。

于 2013-02-25T16:25:06.993 回答
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();
    }
}

我不知道这是否是最优雅的解决方案,但它真的很棒。我希望这对其他人有帮助。

于 2013-02-23T16:05:11.367 回答