我进行了搜索和搜索,但没有找到问题的原因。
设置:我试图无限期地按顺序播放剪辑列表,直到程序的GUI告诉停止。此外,用户可以在播放剪辑时调节音量。 让我们说我有片段A,B和C.播放顺序是ABCABCABCABC .....
问题:问题是第一次剪辑A,B和C开始 - 有POP - 在GUI之后告诉停止,没有POP。
代码:在线程的run()方法中,获取剪辑的所有文件名,创建所有剪辑并将其保存在LinkedHashSet中。接下来,循环播放这些片段,为每个片段创建音量控制对象。
我的观察:对违规行进行评论(使用// TODO:UNCOMMENT ME !!!!!)使用注释行,没有POP,但音量控制已被禁用。取消注释这些行后,POP将返回。
问题:我哪里错了?我头上没有任何头发可以拉出来! :)
private LinkedHashSet<Clip> clips = new LinkedHashSet<Clip>();
private FloatControl volControl = null;
.
.
.
.
@Override
public void run() {
List<String> fileNames = smd.getFiles();
if ( !(numFiles.isEmpty()) ) {
try {
// Create all clips and save in LinkedHashSet
//
for (String s: fileNames) {
clips.add(CreateClip(s));
}
// Play each clip till GUI says to stop
//
while (smd.getStopPlayStatus()) {
for (Clip c: clips) {
// Calculate and set the clip volume to what GUI says
//
float dB = (float) (Math.log(smd.getSwarMVolume()/100f) / Math.log(10.0) * 80.0);
System.out.println(" vol = " + volumeLevel/100f + " || dB = " + dB);
Control[ ] ctls = c.getControls();
for (Control ctl : ctls) {
if (ctl.toString().toLowerCase().contains("master gain")) {
volControl = (FloatControl) ctl;
break;
}
}
// volControl.setValue(dB); // TODO: UNCOMMENT ME!!!!!!!!
// Play the clip
//
loop(c, 0);
}
}
} catch (ConcurrentModificationException ex) {
}
}
}
void loop(Clip clip, int times){
if (times == -1) {
clip.loop(Clip.LOOP_CONTINUOUSLY);
} else {
clip.loop(times);
}
while (clip.isRunning()) {
float dB = (float) (Math.log(smd.getVolume()/100f) / Math.log(10.0) * 80.0);
// volControl.setValue(dB); // TODO: UNCOMMENT ME!!!!!!!!
try {
Thread.sleep(50);
} catch (InterruptedException e) {
}
}
clip.drain();
}
private Clip CreateClip(String fileName) {
Clip c = null;
try {
File file = new File(fileName);
AudioInputStream sound = AudioSystem.getAudioInputStream(file);
AudioFormat format = sound.getFormat();
DataLine.Info info = new DataLine.Info(Clip.class, format);
c = (Clip) AudioSystem.getLine(info);
c.addLineListener(this);
c.open(sound);
} catch (MalformedURLException ex) {
} catch (UnsupportedAudioFileException ex) {
} catch (IOException ex) {
} catch (LineUnavailableException ex) {
}
return c;
}
答案 0 :(得分:1)
提供的音量控制非常粗糙。设置新卷时,整个更改会立即发生。这可能会在声音中产生不连续,导致弹出。
为了消除这种情况,可以尝试逐渐改变音量。有时这很有效。您将不得不修补它以找到转换和平滑所需时间的最佳权衡。
有几个问题。 (1)根据使用的缩放比例,可以在没有弹出的单个音量变化中行进的“距离”在低端与高端可以不同。 (2)在一段时间内可以进行的更改次数受缓冲区大小的限制。每个缓冲区只能进行一次更改。因此,减小缓冲区大小将允许更大的粒度变化,但会增加辍学的风险。
坦率地说,我只是举起手来放弃使用提供的音量线。相反,我将更改编程为基于每帧的转换。这可以通过获取每个缓冲区并将字节转换为PCM,对各个帧进行体积倍增并转换回字节来完成。处理成本非常小。