2017-05-18 27 views
0

几天来,我一直在寻找解码MP3的方法,更改samplingRate并将其重新编码为MP3。 现在,这是工作,我已经把它放在一个循环,因为我需要重复该过程多次。nullPointerException多次使用AudioSystem.getAudioInputStream

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

对于这里的上下文是当我把我的功能一堆时间:

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(最后一行)只适用于第一次迭代。所有迭代都发生在同一个音频文件中,每个迭代的每个参数都是“新”的,所以我不明白怎么可能是空的。

以下是错误日志的最后一段:

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) 

的错误似乎调用getAudioInputStream在比较两个AudioFormat的对象(即我刚才实例化的那些时触发,并且严格对每个迭代相同我的循环)

所以我坚持在这里,我希望有人能想出解决办法:/

更新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

如果您总是使用相同的音频文件,为什么不将createAudio()函数调用出for循环并在for循环之前创建一次? –

+0

因为我想我的函数ConvertMP3.newRatedMusicFile()是独立的,它只是要求一个目录,一个源,一个目标和一个浮动数字。将来这首歌可能会改变:/ –

+0

我看不到第一个循环与下一个代码片段之间的关系。如果这应该是'createAudio'方法的一部分,那么它不清楚它对参数做了什么或者它如何改变对象的状态,最显着的是,'this.source'被初始化或修改。 – Holger

回答

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。