2016-04-26 7 views
0

私はこの小さな信号生成方法を書いています。私の目標は、2つのチャンネル間のわずかな時間遅れ(左右)またはチャンネル間のわずかなゲイン差でビープ音を発生させることです。 現在のところ、1つのチャネルに対して0のバッファを設定し、2番目のチャネルの値をバッファに書き込むことで、遅延を作成します。チャネル間の振る舞いをスワップします(この点についてはヒントやアイデアがあれば分かります)。 次のステージでは、ゲインと同様のことをしています。私は、JavaがFloatControl経由でゲインコントロールを組み込んでいることを見てきました。しかし、各チャンネルのゲインを個別に制御する方法がわかりません。これを行うための方法が組み込まれていますか? チャンネルごとに2つの別々のストリームが必要ですか?もしそうなら、同時にどのようにプレイするのですか? 私はプログラミングを聴くには新しいです、これを行うより良い方法があれば教えてください。どんな助力も非常に感謝しています。個別にJavaを使ったサウンドチャンネルのコントロールゲイン

これは、これまでの私のコードです:

public static void generateTone(int delayR, int delayL, double gainRightDB, double gainLeftDB) 
     throws LineUnavailableException, IOException { 

    // in hz, number of samples in one second 
    int sampleRate = 100000; // let sample rate and frequency be the same 

    // how much to add to each side: 
    double gainLeft = 100;//Math.pow(10.0, gainLeftDB/20.0); 
    double gainRight = 100;// Math.pow(10.0, gainRightDB/20.0);; 

    // click duration = 40 us 
    double duration = 0.08; 
    double durationInSamples = Math.ceil(duration * sampleRate); 

    // single delay window duration = 225 us 
    double baseDelay = 0.000225; 
    double samplesPerDelay = Math.ceil(baseDelay * sampleRate); 

    AudioFormat af; 

    byte buf[] = new byte[sampleRate * 4];     // one second of audio in total 
    af = new AudioFormat(sampleRate, 16, 2, true, true); // 44100 Hz, 16 bit, 2 channels 


    SourceDataLine sdl = AudioSystem.getSourceDataLine(af); 

    sdl.open(af); 

    sdl.start(); 

    // only one should be delayed at a time 
    int delayRight = delayR; 
    int delayLeft = delayL; 

    int freq = 1000; 

    /* 
    * NOTE: 
    * The buffer holds data in groups of 4. Every 4 bytes represent a single sample. The first 2 bytes 
    * are for the left side, the other two are for the right. We take 2 each time because of a 16 bit rate. 
    * 
    * 
    */ 
    for(int i = 0; i < sampleRate * 4; i++){ 
     double time = ((double)i/((double)sampleRate)); 

     // Left side: 
     if (i >= delayLeft * samplesPerDelay * 4    // when the left side plays 
       && i % 4 < 2         // access first two bytes in sample 
       && i <= (delayLeft * 4 * samplesPerDelay) 
       + (4 * durationInSamples))      // make sure to stop after your delay window 

      buf[i] = (byte) ((1+gainLeft) * Math.sin(2*Math.PI*(freq)*time));     // sound in left ear 
     //Right side: 
     else if (i >= delayRight * samplesPerDelay * 4   // time for right side 
       && i % 4 >= 2         // use second 2 bytes 
       && i <= (delayRight * 4 * samplesPerDelay) 
       + (4 * durationInSamples))      // stop after your delay window 


      buf[i] = (byte) ((1+gainRight) * Math.sin(2*Math.PI*(freq)*time));     // sound in right ear 

    } 

    for (byte b : buf) 
     System.out.print(b + " "); 
    System.out.println(); 

    sdl.write(buf,0,buf.length); 
    sdl.drain(); 
    sdl.stop(); 


    sdl.close(); 
} 
+0

* "各チャンネルのゲインを個別に制御する方法が分かりません" * ['FloatControl.Type.BALANCE'](http://docs.oracle.com/javase/8/docs/api/javax /sound/sampled/FloatControl.Type.html#BALANCE).. –

+0

より良いヘルプを早く得るには、[MCVE]または[短く、自己完結型の正しい例](http://www.sscce.org/)を投稿してください。 –

答えて

1

はどのように遠く離れてあなたのビープ音が欲しいのですか?私はサインビープ音を数百フレーム(44100 fps)で発音させるプログラムを書いて、ソースコードhereで掲示しました。あなたはこれを閲覧/コピー/書き直すことを歓迎します。

このような低レベルの分離では、音は知覚的に融合されたままですが、一方の耳または他の耳に移動し始める可能性があります。ボリュームパンと遅延ベースのパンを比較したかったので、これを書きました。柔軟に複数のファイルをテストできるように、コードはあなたが始めたものよりもわずかにモジュラーです。私は、私が書いたものがどんなに優れていると主張するつもりはない。

1つのクラスは、モノラルPCM(範囲は浮動小数点、-1から1まで)の配列を取り、それをチャンネル間で所望のフレーム遅延を持つステレオ配列に変換します。同じクラスでは、モノラルファイルを音量のみのステレオファイルに分割し、モノラルデータをステレオにするときに遅延と音量の違いを組み合わせることもできます。

Monofile:F1、F2、F3、... Stereofile F1L、F1R、F2L、F2R、F3L、F3R、...

いますが、遅延を追加する場合は、右に2つのフレームを言う:

Stereofile F1L、0、F2L、0、F3L、F1R、F4L、F2R、... Fは、オーディオ波を表す(-1と1の間)の正規化浮動小数点である

ビープ音の最初のモノアレイを作成することは、正弦関数を使用することとほぼ同じです。突然始動または停止する不連続点に起因するクリックを最小限に抑えるために、いくつかのフレームのコースにわたって音量を上げることによって、「エッジを丸める」ことができます。

もう一つのクラスは、SourceDataLineを介してステレオフロート配列を出力することを目的としています。音量は、オーディオ出力に0から1までの係数を掛けることによって処理されます。正規化された値に32767を掛けて符号付きショーツに変換し、使用するフォーマット(16ビット、44100 fps、ステレオ、リトルエンディアン)。

アレイ再生オーディオクラスを持つことはきれいです。その配列はクリップとよく似ていますが、データに直接アクセスできます。このクラスを使用すると、多くのサウンド配列を構築して再利用できます。私は、このDIYクリップにwavファイルをロードするコードが含まれていると思います。

このコードの詳細はthis thread at Java-Gaming.orgです。

ここで私がここで学んだことのいくつかを、リアルタイムの3Dサウンドシステムを簡略化するために使用しました。しかし、このようなものを設定する "最良の"方法は、あなたの目標にかかっています。私の3Dでは、例えば、ステレオの左右から別々の読み込みを可能にするディレイツールを書いており、オーディオミキサー&の再生は単純な配列からSourceDataLineのプレイヤーよりも複雑です。

+0

入力いただきありがとうございます。あなたのプログラムは非常に便利なようです。私はそれを調べるでしょう。 元々、音の距離は非常に小さく、40-100μSec程度でした。しかし、現時点では、私は平均的なサウンドカードが私に聞かせてくれるほど低くすることを喜んでしています。 もう少し調べてみると、FloatControlはPANとBALANCEのアクションもサポートしていることがわかりました。これらはあなたがここでやったこととは違うのですか? – TheFooBarWay

+0

私はサウンドカードの限界は、それがサポートする最高のフレームレートと考えることができると思う。標準サウンドカードは44100 fpsをサポートできます。つまり、1フレームは約22.5マイクロ秒ですか?線形補間を使用すると、フレーム1のRが90%のフレーム1 Lと10%のフレーム2 Lを取得するなど、より小さい値になる可能性があります。PANとBALANCEのコントロールが安定しているとは限りません。フレーム。彼らが働くとき、彼らは通常、個々のフレームレベルではなく、データの完全なバッファー上で動作するように結びついているので、それほど細かくはありません。 –

関連する問題