1
Java 소스 데이터 라인에 문제가 있습니다. 톤을 연주해야하기 때문에 톤을 나타내는 톤 클래스를 만들었습니다. 사운드를 재생할 때 스피커가 사운드의 시작 부분에 튀는 것을 제외하고는 모든 것이 잘 작동합니다. 이 문제를 해결할 방법이 있습니까? 그것은 연구 프로젝트를위한 것이며 결과에 영향을 미칠 수 있으므로 딱딱 거리지 않고 실행해야합니다. 아래 소스 코드. 감사!오디오에 Java 소스 데이터 라인을 사용할 때 튀어 오름/크래킹
package edu.jhu.halberda.audiopanamath;
import javax.sound.sampled.AudioFormat;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.FloatControl;
import javax.sound.sampled.LineUnavailableException;
import javax.sound.sampled.SourceDataLine;
import javax.swing.JOptionPane;
public class Tone {
public enum Channel {
LEFT, RIGHT, STEREO
};
public static final float SAMPLE_RATE = 44104; // Should be a multiple of 8
protected byte[] buf;
protected int hz, msecs;
protected double vol;
protected Channel channel;
Tone() {
} // necessary so that subclasses don't complain
public Tone(int hz, int msecs, double vol, Tone.Channel channel) {
if (hz <= 0)
throw new IllegalArgumentException("Frequency <= 0 hz");
if (msecs <= 0)
throw new IllegalArgumentException("Duration <= 0 msecs");
if (vol > 1.0 || vol < 0.0)
throw new IllegalArgumentException("Volume out of range 0.0 - 1.0");
this.channel = channel;
this.hz = hz;
this.vol = vol;
this.msecs = msecs;
generateTone();
}
private void generateTone() {
int len = (int)Math.ceil((2 * SAMPLE_RATE * msecs/1000.0d));
if (len % 2 == 1)
len = len + 1;
buf = new byte[len];
for (int i = 0; i < buf.length /2; i++) {
double angle = (i * hz/SAMPLE_RATE) * 2.0 * Math.PI;
buf[2*i + 1] = buf[2*i] = (byte) Math.round(Math.sin(angle) * 127.0 * vol);
}
}
public void play(SourceDataLine sdl) { // takes an opened SourceDataLine
FloatControl panControl = (FloatControl) sdl
.getControl(FloatControl.Type.PAN);
if (panControl != null) { // Preferred method using built in sound
// control, but not guaranteed to be
// available
if (channel == Channel.LEFT) {
panControl.setValue(-1);
} else if (channel == Channel.RIGHT) {
panControl.setValue(1);
} else {
panControl.setValue(0);
}
} else { // fallback method is directly manipulates the buffer
if (channel != Channel.STEREO) {
int nSilenceOffset;
byte nSilenceValue = 0;
if (channel == Channel.LEFT) {
nSilenceOffset = 1;
} else {
nSilenceOffset = 0;
}
for (int i = 0; i < buf.length; i += 2) {
buf[i + nSilenceOffset] = nSilenceValue;
}
}
}
sdl.write(buf, 0, buf.length);
sdl.drain();
}
public static void main(String[] args) {
AudioFormat af = new AudioFormat(Tone.SAMPLE_RATE, 8, 2, true, false);
SourceDataLine sdl;
try {
sdl = AudioSystem.getSourceDataLine(af);
} catch (LineUnavailableException e) {
JOptionPane.showMessageDialog(null, "Couldn't get sound line");
return;
}
try {
sdl.open(af);
} catch (LineUnavailableException e) {
JOptionPane.showMessageDialog(null, "Couldn't open sound line");
return;
}
sdl.start();
Tone left = new Tone(400, 2000, .5, Tone.Channel.LEFT);
System.out.println("Playing left");
long t = System.currentTimeMillis();
left.play(sdl);
System.out.println(System.currentTimeMillis()-t);
System.out.println("Finished left");
Tone right = new Tone(400, 2000, .5, Tone.Channel.RIGHT);
System.out.println("Playing right");
right.play(sdl);
System.out.println("Finished right");
sdl.stop();
sdl.close();
}
}