几天来,我一直在寻找解码MP3的方法,更改samplingRate并将其重新编码为MP3。 现在这是有效的,我把它放在一个循环中因为我需要多次重复这个过程。
"价格"是一个浮动变量,表示我将多少乘以音频文件的速度。
对于上下文,这是我多次调用我的函数的时候:
private void passRates() throws Exception {
for (Float rate : this.rates) {
String audio = "Some file name.mp3"
createAudio(audio, rate);
for (Beatmap beatmap : this.currentBeatmaps) {
createRate(beatmap, audio, rate);
}
}
}
createAudio()函数调用一个类" ConvertMP3"这会创建一个新的音频文件,并在其中发生nullPointerException。
这里的小车部分:
AudioInputStream in = AudioSystem.getAudioInputStream(this.source);
AudioFormat baseFormat = in.getFormat();
AudioFormat decodedFormat = new AudioFormat(AudioFormat.Encoding.PCM_SIGNED,
baseFormat.getSampleRate(),
16,
baseFormat.getChannels(),
baseFormat.getChannels() * 2,
baseFormat.getSampleRate(),
false);
AudioInputStream din = AudioSystem.getAudioInputStream(decodedFormat, in);
调用AudioSystem.getAudioInputStream()的最后一行仅适用于第一次迭代。所有迭代都发生在同一个音频文件中,每个参数都是" new"对于每次迭代,我都不明白某些东西可能是空的。
以下是错误日志的最后一部分:
mai 18, 2017 6:57:18 PM beatmaptweaker.menus.MultipleRate
jButtonStartRatingMouseClicked
GRAVE: null
java.lang.NullPointerException
at javax.sound.sampled.AudioFormat.matches(AudioFormat.java:450)
at javax.sound.sampled.spi.FormatConversionProvider.isConversionSupported(FormatConversionProvider.java:169)
at javax.sound.sampled.AudioSystem.getAudioInputStream(AudioSystem.java:968)
at beatmaptweaker.customClasses.ConvertMP3.newRatedMusicFile(ConvertMP3.java:56)
在比较两个AudioFormat对象时(我在调用getAudioInputStream之前刚刚实例化并且在我的循环的每次迭代中严格相同)时,错误似乎触发了
所以我被困在这里,我希望有人能解决这个问题:/
更新1:我没有在我的代码中关闭AudioInpuStream。既然我做了它,它仍然无法正常工作。
更新2:错误来自javax.sound.sampled.AudioFormat内部,因为它会检查一堆格式,但不会验证它们是否为空,从而导致崩溃。我无法覆盖这个类,因为当我尝试在javax.sound.sampled.spi.FormatConversionProvider中获取格式时,如果我不使用默认类,它会返回一个空数组...
以下是不检查null的代码:
public boolean isConversionSupported(AudioFormat targetFormat, AudioFormat sourceFormat){
AudioFormat targetFormats[] = getTargetFormats( targetFormat.getEncoding(), sourceFormat );
for(int i=0; i<targetFormats.length; i++) {
if( targetFormat.matches( targetFormats[i] ) ) {
return true;
}
}
return false;
}
public boolean matches(AudioFormat format) {
if (format.getEncoding().equals(getEncoding())
&& (format.getChannels() == AudioSystem.NOT_SPECIFIED
|| format.getChannels() == getChannels())
&& (format.getSampleRate() == (float)AudioSystem.NOT_SPECIFIED
|| format.getSampleRate() == getSampleRate())
&& (format.getSampleSizeInBits() == AudioSystem.NOT_SPECIFIED
|| format.getSampleSizeInBits() == getSampleSizeInBits())
&& (format.getFrameRate() == (float)AudioSystem.NOT_SPECIFIED
|| format.getFrameRate() == getFrameRate())
&& (format.getFrameSize() == AudioSystem.NOT_SPECIFIED
|| format.getFrameSize() == getFrameSize())
&& (getSampleSizeInBits() <= 8
|| format.isBigEndian() == isBigEndian())) {
return true;
}
return false;
}
答案 0 :(得分:0)
好的,所以我终于在经过数小时的搜索后解决了我的问题。
事实上,AudioInputStream或者在转换它时以某种方式耗尽了什么(是的,当类乱搞你的变量时很烦人) -
无论如何,我做的是在做我的事情之前把它转换成ByteArray。 这是我的新循环:
private void passRates() throws Exception {
for (Float rate : this.rates) {
AudioInputStream in = null;
in = AudioSystem.getAudioInputStream(new File(this.directory + currentBeatmaps.get(0).getAudioFileName()));
AudioFormat baseFormat = in.getFormat();
AudioFormat decodedFormat = new AudioFormat(AudioFormat.Encoding.PCM_SIGNED,
baseFormat.getSampleRate(),
16,
baseFormat.getChannels(),
baseFormat.getChannels() * 2,
baseFormat.getSampleRate(),
false);
AudioInputStream din2 = AudioSystem.getAudioInputStream(decodedFormat, in);
long length = din2.getFrameLength();
byte[] bytes = IOUtils.toByteArray(din2);
in.close();
InputStream is1 = new ByteArrayInputStream(bytes);
AudioInputStream din = new AudioInputStream(
is1,
decodedFormat,
length
);
String audio = this.jInputAudioFilename.getText() + " x" + Float.toString(rate) + ".mp3";
createAudio(din, this.directory, audio, rate);
for (Beatmap beatmap : this.currentBeatmaps) {
createRate(beatmap, audio, rate);
}
}
}
我不认为这是优化的或任何东西,但这完美地运作
注意:这似乎不适用于某些MP3文件。我已经导入了一些库并且创建了AudioInputStream但是当FrameLength未知时,IOUtils.toByteArray()会陷入无限循环,因为它正在等待EOF。