2014-05-19 74 views
3

我正在使用Ogg Vorbis SPI作爲解碼.ogg文件的方法。使用Ogg Vorbis SPI解碼.ogg文件對於小文件大小失敗

的代碼片段我用裝載.ogg文件,並轉換成PCM是不建議的一個文檔中也不同:

// The streams are valid at this point. 
try (InputStream bin = new BufferedInputStream(file.getInputStream(entry)); 
    AudioInputStream in = AudioSystem.getAudioInputStream(bin)) { 

    AudioFormat baseFormat = in.getFormat(); 
    // At this point the format is valid: 
    // VORBISENC 44100.0 Hz, unknown bits per sample, mono, 1 bytes/frame, 12000.0 frames/second, 
    // I can't make a Clip directly from this or it will be all buzzy, so I convert to PCM 

    // Decoding to PCM 
    AudioFormat decodedFormat = 
     new AudioFormat(AudioFormat.Encoding.PCM_SIGNED, 
         baseFormat.getSampleRate(), 
         16, 
         baseFormat.getChannels(), 
         baseFormat.getChannels() * 2, 
         baseFormat.getSampleRate(), 
         false); 

    // This is where the issues appear... 
    AudioInputStream decodedInputStream = AudioSystem.getAudioInputStream(decodedFormat, in); 

    Clip clip = AudioSystem.getClip(); 
    clip.open(decodedInputStream); 

    // entry.getName is basically the filename. Any files with '0' frame length didn't get converted properly. 
    System.out.println("Clip " + entry.getName() + " loaded at " + clip.getFrameLength() + " frame length"); 

    return clip; 
} catch { ... } 

正在發生的事情是,我裝幾個小的聲音文件,在低5K到高32K的範圍(ogg格式)。然而,一些文件不能正確地轉換成PCM。我注意到他們都有一些共同點,它們的大小從5K到6K不等。聲音文件似乎開始在7K左右正確轉換。我測試了11K的聲音並將其切下,直到它不再被轉換(〜6K)

我覺得一個方法是增加一些聽不到的噪音來填充尺寸,但我更喜歡只是正確的轉換聲音文件,無論大小。除了API本身之外,對於聲音表示的概念還完全陌生,我不知道從哪裏開始看看爲什麼會出現這種情況。

+0

我在想如果AudioInputStream.getFormat()移動流中的位置並且不重置它。也許嘗試關閉並重新打開流? – GreyBeardedGeek

+0

感謝您的關注;在我使用getFormat()後,我剛剛嘗試了reset()並關閉/打開一個新流。不幸的是,問題仍在發生。 –

回答

1

我已經進入了和你一樣的場景,編碼的小文件和文件不符合原始緩衝區長度(這是一個好運氣),但似乎會由於Vorbis SPI的實現 - 這是非常古老的,我希望他們會支持它,並且會修復。 作爲一種變通方法,你可以在2個地方固定DecodedVorbisAudioInputStream.java:

private int readFromStream(byte[] buffer, int index, int bufferSize_) { 
    int bytes = 0; 
    try { 
     bytes = oggBitStream_.read(buffer, index, bufferSize_); 
    } 
    catch (Exception e) { 
     if (TDebug.TraceAudioConverter) 
      TDebug.out("Cannot Read Selected Song"); 
     bytes = -1; 
    } 
    if (bytes >= 0) { 
     currentBytes += bytes; 
    } 
    return bytes; 
} 

而且從緩衝部分閱讀:

case playState_ReadData: 
      int result; 
      index = oggSyncState_.buffer(bufferSize_); 
      buffer = oggSyncState_.data; 
      bytes = readFromStream(buffer, index, bufferSize_); 
      if (TDebug.TraceAudioConverter) { 
       TDebug.out("More data : " + bytes); 
      } 
      // has no data in buffer also 
      if (bytes == -1 && bufferSize_ - index == 0) { 
       playState = playState_Done; 
       if (TDebug.TraceAudioConverter) { 
        TDebug.out("Ogg Stream empty. Settings playState to playState_Done."); 
       } 
       break; 
      } 
      else { 
       if (bytes != -1) { 
        oggSyncState_.wrote(bytes); 
       } 
       if (bytes == 0 && bufferSize_ - index == 0) { 
        if ((oggPage_.eos() != 0) || (oggStreamState_.e_o_s != 0) || (oggPacket_.e_o_s != 0)) { 
         if (TDebug.TraceAudioConverter) { 
          TDebug.out("oggSyncState wrote 0 bytes: settings playState to playState_Done."); 
         } 
         playState = playState_Done; 
        } 
        if (TDebug.TraceAudioConverter) { 
         TDebug.out("oggSyncState wrote 0 bytes: but stream not yet empty."); 
        } 
        break; 
       } 
      } 

      result = oggSyncState_.pageout(oggPage_); 
      if (result == 0) { 
       if (TDebug.TraceAudioConverter) { 
        TDebug.out("Setting playState to playState_ReadData."); 
       } 
       playState = playState_ReadData; 
       break; 
      } // need more data 
      if (result == -1) { // missing or corrupt data at this page position 
       if (TDebug.TraceAudioConverter) 
        TDebug.out("Corrupt or missing data in bitstream; setting playState to playState_ReadData"); 
       playState = playState_ReadData; 
       break; 
      } 

      oggStreamState_.pagein(oggPage_); 

      if (TDebug.TraceAudioConverter) 
       TDebug.out("Setting playState to playState_WriteData."); 
      playState = playState_WriteData; 
      break; 

在閱讀他們忽略了那些已經從緩衝區中讀取的字節,所以,他們只是跳過緩衝區中的最後讀取字節。

希望有幫助!

+0

不幸的是我還沒有把它付諸實踐,因爲自從問這個問題以來,我開始轉向其他項目......但是我真的很感謝您的解決方案的詳細輸入,我不希望這個答案會浪費掉我接受它。 –