我正在尝试制作一个程序,该程序将根据参数生成一秒钟指定响度的声音。我已经包含了下面的代码。在setUpSound()
函数中,有一行“control.setValue(integer)
”控制音量。例如,如果该值为 -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();
}
}
最佳答案
..how to resolve it?
保留主音量,并使用 getByteValue()
方法的另一个参数调整音量(对于柔和的声音,返回较小的字节值)。
..use another parameter..
即
- 将 getByteValue()
更改为 getByteValue(float scale)
。
- 如果范围超出 0.0f
- 1.0f
,则抛出
IllegalArgumentException
。
- 将当时的信号值乘以scale
值。
如果为 scale
提供了 0.5f 的值,则声音将比该数字为 1.0f 时的声音小。
关于Java 声音 - 先是响亮的噪音,然后是轻柔的噪音,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9368051/