1

我遇到的问题是音频文件的分贝数仅从 programVolume (变量)的初始值更改,但我有一个 JSlider 可以更改变量的值;但是,它不会更改文件的分贝数。我要添加/更改什么以确保基于从 JSlider 设置为变量的值更改分贝数。

  File fileSong = new File (filePath); 
  AudioInputStream input = AudioSystem.getAudioInputStream(fileSong); 
  clip = AudioSystem.getClip(); 
  clip.open(input); 
  FloatControl gainControl = (FloatControl) clip.getControl(FloatControl.Type.MASTER_GAIN);
  gainControl.setValue(programVolume);
  clip.start();

编辑:

我添加了以下代码:

  File fileSong = new File (filePath); 
  AudioInputStream input = AudioSystem.getAudioInputStream(fileSong);
  clip = AudioSystem.getClip(); 
  clip.open(input); 

  FloatControl gainControl = (FloatControl) clip.getControl(FloatControl.Type.MASTER_GAIN);
  float range = gainControl.getMaximum() - gainControl.getMinimum();
  float gain = (range * programVolume) + gainControl.getMinimum();
  gainControl.setValue(gain);

对于我的 JSlider(在 ChangeEvent e 方法中)

    programVolume =  (float)volume.getValue() / 100; 

我仍然面临同样的问题。从 JSlider 收到的新值不会改变音量。只有 programVolume 的初始值会改变声音。

4

2 回答 2

2

@gthanop 对 ShaleeQureshi 的回答的第一个建议非常重要。重新加载 aClip是非常低效的。整个Clip必须重新加载才能重新启动。

控件经常存在问题,因为它们依赖于与不同系统交互的本机代码。由于该 PC 上缺少功能,在一台 PC 上实现的控件可能无法在另一台 PC 上实现。

出现的另一个问题是控件引起的更改与缓冲区边界相关联。例如,如果缓冲区是半秒长,那么新值将需要半秒才能生效。

音频文件本身没有“分贝”控制。相反,音量来自形成信号的数据值的动态范围。一个安静的文件可能只有 -0.05 到 0.05 的范围,而一个响亮的文件可能更像是 -0.5 到 0.5。音频文件可能有部分响亮而其他部分柔和,但整体仍直接编码为信号值。.wav 文件没有“音量”控制。

由于不能依赖 Java 提供的控件,您可能需要查看 github 资源AudioCue。它基本上是增强的Clip,具有实时音量控制。该代码具有许可许可证,可以免费使用或检查想法。基本原则是将数据存储在 afloat[]而不是 aClip中,并通过 a 播放它,SourceDataLine同时不断参考与流式传输的信号值相乘的音量因子。

于 2020-01-02T05:52:52.873 回答
0

我想到了!每当使用 JSlider 更改变量时,都必须停止剪辑,并将其停止的点存储到变量中。我选择了一个很长的片段,然后必须重新启动剪辑,当它重新启动时,它使用用户选择的新音量,同时它开始给用户一种错觉,即音量被改变,而音频-文件在停止、更改音量和恢复时正在播放。这些Math.Log东西用于计算/将分贝转换为我们知道的音量系统(0%-100%),我认为是这样。

  File fileSong = new File (filePath);
  AudioInputStream input = AudioSystem.getAudioInputStream(fileSong); 
  clip = AudioSystem.getClip(); 
  clip.open(input); 
  clip.setMicrosecondPosition(position); 

  FloatControl gainControl = (FloatControl) clip.getControl(FloatControl.Type.MASTER_GAIN); 
  float range = (float) (Math.log(userInput) / Math.log(10) * 20); 
  gainControl.setValue(range); 
  clip.start(); 
于 2020-01-01T09:31:58.333 回答