2012-02-20 10 views
1

パラメータに基づいて、指定されたラウドネスで1秒間サウンドを生成するプログラムを作成しようとしています。私は以下のコードを含んでいます。 setUpSound()機能では、列を制御する行「control.setValue(integer)」があります。たとえば、値が-30の場合、実際に1秒間ビープ音が鳴ります。値が20の場合、1秒間は本当に大きなノイズが発生します。Javaサウンド - ソフトノイズの前の最初の大きなノイズ

ノイズが柔らかい場合(パラメーターが-30〜-10の範囲にある場合)、約100ミリ秒間続く初期の大きなノイズがあり、その後ソフトな正規の音が鳴ります。通常の通常の音を再生する前に、数秒間コンピュータの存在が驚いたサウンドカードのように聞こえます。それは理にかなっていますか?あなたもあなたのマシンでそれを試すことができます。私はLionを実行しているMacBook Proを使用しています。

私はJavaがこれを行う理由と解決方法を理解しようとしていますか?

import java.io.ByteArrayInputStream; 

import javax.sound.sampled.AudioFormat; 
import javax.sound.sampled.AudioInputStream; 
import javax.sound.sampled.AudioSystem; 
import javax.sound.sampled.Clip; 
import javax.sound.sampled.FloatControl; 
import javax.sound.sampled.LineUnavailableException; 
import javax.swing.JSlider; 
import javax.swing.event.ChangeEvent; 
import javax.swing.event.ChangeListener; 

public class Test { 

    FloatControl control; 

    public static void main(String[] args) { 
     Test test = new Test(); 
     test.setUpSound(); 
     test.loopSound(true); 

     try { 
      Thread.sleep(1000); 
     } catch(Exception e) { 

     } 
     test.loopSound(false); 
    } 
    Clip clip; 

    public void setUpSound() { 

     /** Volume */ 

      try { 

       generateTone(); 

       control = (FloatControl) 
         clip.getControl(FloatControl.Type.MASTER_GAIN); 

      System.out.println("min volume: " + control.getMinimum()); 
      System.out.println("max volume " + control.getMaximum()); 
      System.out.println("end of sounds"); 

      control.setValue(-40); 



      } catch(Exception e) { 
       e.printStackTrace(); 
      } 
     } 

    public void loopSound(boolean commence) { 
     if (commence) { 
      clip.setFramePosition(0); 
      clip.loop(Clip.LOOP_CONTINUOUSLY); 
     } else { 
      clip.stop(); 
     } 
    } 

    /** Generates a tone, and assigns it to the Clip. */ 
    public void generateTone() 
     throws LineUnavailableException { 
     if (clip!=null) { 
      clip.stop(); 
      clip.close(); 
     } else { 
      clip = AudioSystem.getClip(); 
     } 
     boolean addHarmonic = true; 

     int intSR = 10025; 
     int intFPW = 20; 
     System.out.println("sampleRate = " + intSR); 
     System.out.println("framesPerWavelength = " + intFPW); 

     float sampleRate = (float)intSR; 

     // oddly, the sound does not loop well for less than 
     // around 5 or so, wavelengths 
     int wavelengths = 5; 
     byte[] buf = new byte[2*intFPW*wavelengths]; 
     AudioFormat af = new AudioFormat(
      sampleRate, 
      8, // sample size in bits 
      2, // channels 
      true, // signed 
      false // bigendian 
      ); 

     for(int i=0; i<intFPW*wavelengths; i++){ 
      double angle = ((float)(i*2)/((float)intFPW))*(Math.PI); 
      buf[i*2]=getByteValue(angle); 
      if(addHarmonic) { 
       buf[(i*2)+1]=getByteValue(2*angle); 
      } else { 
       buf[(i*2)+1] = buf[i*2]; 
      } 
     } 

     try { 
      byte[] b = buf; 
      AudioInputStream ais = new AudioInputStream(
       new ByteArrayInputStream(b), 
       af, 
       buf.length/2); 

      clip.open(ais); 
     } catch(Exception e) { 
      e.printStackTrace(); 
     } 
    } 

    /** Provides the byte value for this point in the sinusoidal wave. */ 
    private static byte getByteValue(double angle) { 
     int maxVol = 127; 
     return (new Integer(
      (int)Math.round(
      Math.sin(angle)*maxVol))). 
      byteValue(); 
    } 
} 

答えて

1

..howそれを解決するには?

getByteValue()メソッドの別のパラメータを使用して、音量を調整します(ソフト音のバイト値は小さくしてください)。別のパラメータ..use


..

すなわち、
- getByteValue()getByteValue(float scale)に変更してください。
- throwIllegalArgumentException範囲外の場合は、0.0f - 1.0fです。 - その瞬間の信号の値にscaleの値を掛けます。

scaleに0.5fの値を指定すると、1.0fの場合よりも音が小さくなります。

+0

申し訳ありませんが、私はそれを完全に理解していませんでした。もう少し説明できますか?あなたは別のパラメータを使用すると述べましたか?あなたはこれを拡大できますか?ありがとう! – CodeGuy

+0

回答を編集するを参照してください。 –

+0

getByteValue(double angle)関数を変更しようとしていますか?私はまだ少し混乱しています、申し訳ありません。新しい機能はどうすべきですか? – CodeGuy