1

この質問を投稿する前に、問題を理解しました。それでも、これは他の誰かを助けるかもしれないと思うので、とにかく投稿します。これを行うためのより良い方法またはよりエレガントな方法を誰かが知っている場合は、回答を投稿してください。私が同意する場合は、もちろんあなたの回答を受け入れます。これが私の元の問題です:

私はJSynで動作するように以下を取得しようとしています:

2 つのチャネルで 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() メソッドは、エンジンによって直接実行されるユニットのリストにユニットを追加します。LineOut などのチェーンの終わりを start() します。ユニットが実行されると、その入力に接続されているユニットからデータを要求します。これらのユニットは、接続されているユニットからのデータを要求します。これにより、レイテンシを最小限に抑える順序でユニットが実行されることが保証されます。JSyn は循環接続をチェックして、無限ループを防ぎます。

SineOscillators を stop()ped しても、LineOut はまだ SineOscillators を引っ張っていました。それで彼らは音を立てました。

オシレーターで 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 つの方法は、1 つのオシレーターを使用し、Multiply ユニットを介して LineOut の各チャンネルに接続することです。次に、1.0 または 0.0 を掛けることで、そのチャネルのサインをオンまたはオフにできます。これにより、スカラーを掛けることができます。半分にしたい場合は0.5。

    sineOsc ---> Multiply1 ---> lineOut(0) // 左チャンネル
            `-->multiply2 ---> lineOut(1) // 右チャンネル

setEnabled() および start() メソッドが十分に文書化されていないことに気付きました。今すぐ修正します。

于 2013-02-25T16:25:06.993 に答える
0

解決策は、正弦波をオン/オフしようとせず、単に two を使用すること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 に答える