Java声音 - 在软噪声之前的初始巨响

时间:2012-02-20 20:35:59

标签: java audio

我正在尝试制作一个程序,根据参数生成具有指定响度的声音一秒钟。我已经包含了以下代码。在setUpSound()函数中,有一行“control.setValue(integer)”来控制volumne。例如,如果值为-30,则会有一秒钟的非常柔和的蜂鸣声。如果值为20,则会在一秒钟内产生非常大的噪音。

在噪音较弱的情况下(当参数在-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 个答案:

答案 0 :(得分:1)

  

..如何解决?

单独保留主音量并使用getByteValue()方法的其他参数调整音量(返回较小的软音色字节值)。


  

..使用其他参数..

即。
- 将getByteValue()更改为getByteValue(float scale) - throw IllegalArgumentException如果范围超出0.0f - 1.0f。 - 将当时信号的值乘以scale值。

如果为scale提供了0.5f的值,则声音的声音将小于数字为1.0f的声音。