![](/img/trans.png)
[英]Vorbis SPI throws UnsupportedAudioFileException for OGG files
[英]Using Ogg Vorbis SPI for decoding .ogg files fails for small file sizes
我使用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本身之外,對聲音表示的概念完全陌生,我不知道從哪里開始尋找可能發生這種情況的原因。
我和你一樣進入了相同的場景,看起來編碼小文件和不符合原始緩沖區長度的文件(幸運的是這樣)會因為Vorbis SPI實現中的錯誤而被削減 - 它真的很老了,我希望它們會支持它並且會修復它。 作為一種解決方法,您可以在兩個位置修復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;
在讀取它們時忽略已經從緩沖區讀取的字節,因此,它們只是跳過緩沖區中的最后讀取字節。
希望有所幫助!
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.