java - 多次使用AudioSystem.getAudioInputStream的nullPointerException

标签 java audio nullpointerexception mp3 decode

几天来,我一直在寻找解码MP3,更改amplingRate并将其重新编码为MP3的方法。
现在可行,我将其放入一个循环中,因为我需要多次重复该过程。

“比率”是一个 float 变量,表示我将音频文件的速度乘以多少。

对于上下文,这是当我多次调用函数时:

    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。

这是 buggy 的一部分:
        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()的最后一行仅适用于第一次迭代。所有迭代都针对同一个音频文件进行,并且每次迭代中每个参数都是“新的”,因此我不了解某些东西可能为空。

这是错误日志的最后一段:
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内部,因为它检查了一堆格式,但不验证它们是否为null,从而导致崩溃。我无法覆盖此类,因为当我尝试获取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;
    }

最佳答案

好了,经过数小时的搜索,我终于解决了我的问题。

事实是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。

关于java - 多次使用AudioSystem.getAudioInputStream的nullPointerException,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44054103/

相关文章:

java - 应用程序启动后崩溃

java - 如何在方法上显示 javadoc 中变量的值?

java - 如何在java中将对象的ArrayList转换为整数列表

java - 空指针异常/数组

java - JLabel 数组中的空指针异常

java - 用数据填充 Fragment 中的 GridView

javascript - 单击播放列表项上的播放/暂停音频元素

c# - 在Windows 8应用中转换字节数组以产生不同的音频声音

actionscript-3 - Action 3声音ioError问题

java - 改变图像颜色