2012-02-20 97 views
1

我正在嘗試製作一個程序,該程序將根據參數生成具有指定響度一秒的聲音。我已經包含下面的代碼。在setUpSound()功能中,有一行「control.setValue(integer)」來控制體積。例如,如果該值爲-30,則會有一秒鐘的真正輕微蜂鳴聲。如果數值是20,那麼一秒鐘內會有很大的噪音。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另一參數..

I.E.
- 將getByteValue()更改爲getByteValue(float scale)
- throw an IllegalArgumentException如果範圍在0.0f-1.0f之外。 - 將此時的信號值乘以scale的值。

如果爲scale提供的值爲0.5f,則聲音將比數字爲1.0f時的聲音更小。

+0

對不起,我沒有完全理解。你能多解釋一下嗎?你聲明使用另一個參數?你能擴充這個嗎?謝謝! – CodeGuy 2012-02-21 20:52:44

+0

查看要編輯的答案。 – 2012-02-21 21:01:35

+0

你的意思是改變我的getByteValue(雙角度)函數?我仍然有點困惑,對不起。新功能應該是什麼? – CodeGuy 2012-02-22 02:08:40