簡體   English   中英

使用Ogg Vorbis SPI解碼.ogg文件對於小文件大小會失敗

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM