從wav到Ogg Opus 以及使用java解碼OPUS

PCM

自然界中的聲音非常複雜,波形極其複雜,通常我們採用的是脈衝程式碼調製編碼,即PCM編碼。PCM通過抽樣、量化、編碼三個步驟將連續變化的模擬訊號轉換為數字編碼。

取樣率

取樣頻率,也稱為取樣速度或者取樣率,定義了每秒從連續訊號中提取並組成離散訊號的取樣個數,它用赫茲(Hz)來表示。取樣頻率的倒數是取樣周期或者叫作取樣時間,它是取樣之間的時間間隔。通俗的講取樣頻率是指電腦每秒鐘採集多少個訊號樣本。

工業界常用的16K,就是1s有16000個取樣點。

WAV

PCM是原始語音,依據取樣率的定義,我們知道要播放PCM,需要知道取樣率,因此需要一個文件格式可以封裝PCM,wav就是微軟公司專門為Windows開發的一種標準數字音頻文件,該文件能記錄各種單聲道或立體聲的聲音資訊。

WAV格式

wav文件前44個位元組,定義了取樣率,channel等參數,播放器通過這個數據就可以播放PCM數據了。

MP3

wav 很好的解決了PCM播放的問題,但是PCM實在是太大了,因此出現了mp3等音頻格式,通過一定的壓縮演算法壓縮語音,以便於互聯網傳輸分享。

Ogg 與 Opus

隨著音影片應用的越來越廣泛,工業界有了越來越多的編解碼器,比如Speek,Opus

Opus編解碼器是專門設計用於互聯網的互動式語音和音頻傳輸。它是由IETF的編解碼器工作組設計的,合併了Skype的SILK和Xiph. Org的CELT技術。

OPUS

OPUS編解碼

//github.com/lostromb/concentus 是一個純java庫,可以編解碼OPUS。

OPUS一般是分幀編碼,比如一個320取樣點(640位元組)的數據,編碼後為70多個位元組,和PCM一樣,編碼後的OPUS不能直接播放:

  • 無法從文件本身獲取音頻的元數據(取樣率,聲道數,碼率等)
  • 缺少幀分隔標識,無法從連續的文件流中分隔幀(尤其是vbr情況)

伴隨著HTML5的發展,出現了OGG媒體文件格式,Ogg是一個自由且開放標準的多媒體文件格式,由Xiph.Org基金會所維護。Ogg格式並不受到軟體專利的限制,並設計用於有效率地流媒體和處理高品質的數字多媒體。「Ogg」意指一種文件格式,可以納入各式各樣自由和開放源程式碼的編解碼器,包含音效、影片、文字(像字幕)與元數據的處理。

OGG音頻

壓縮類型 格式 說明
有損 Speek 以低比特率處理語音數據(〜2.1-32 kbit / s /通道)
Vorbis 處理中高級可變比特率(每通道≈16-500kbit / s)的一般音頻數據
Opus: 以低和高可變比特率處理語音,音樂和通用音頻(每通道≈6-510kbit / s)
無損 FLAC 處理文件和高保真音頻數據
未壓縮 OggPCM 處理未壓縮的PCM音頻,與WAV類似

參考: //juejin.cn/post/6844904016254599175

借部落客的圖:

OGG封裝

java 解碼OPUS文件

通過ffmpeg可以輕鬆的將wav轉換為opus文件,本質是一個ogg封裝的opus,我們可以通過vorbis-java 來讀取opus文件。

通過OpusInfoTool,可以列印OPUS文件資訊:

Processing file "C:\Users\jqpeng\Downloads\opus\wav16k.opus"

Opus Headers:
  Version: 1
  Vendor: Lavf58.27.103
  Channels: 1
  Rate: 16000Hz
  Pre-Skip: 104
  Playback Gain: 0dB

User Comments:
  encoder=Lavc58.53.100 libopus

Logical stream 81c1bbc0 (-2118009920) completed

Opus Audio:
  Total Data Packets: 579
  Total Data Length: 41406
  Audio Length Seconds: 11.564333333333334
  Audio Length: 00:00:11.56
  Packet duration:     20.0ms (max),     20.0ms (avg),     20.0ms (min)
  Page duration:     1000.0ms (max),    965.0ms (avg),    580.0ms (min)
  Total data length: 41406 (overhead: 2.34%)
  Playback length: 00:00:11.56
  Average bitrate: 28.70 kb/s, w/o overhead: 27.97 kb/s

再藉助concentus ,我們來解碼OPUS文件為PCM文件。


public void testDecode() throws IOException, OpusException {
        FileInputStream fs = new FileInputStream("\\wav16k.opus");
        OggFile ogg = new OggFile(fs);
        OpusFile of = new OpusFile(ogg);
        OpusAudioData ad = null;

        System.out.println(of.getInfo().getSampleRate());
        System.out.println(of.getInfo().getNumChannels());

        OpusDecoder decoder = new OpusDecoder(of.getInfo().getSampleRate(),
                                              of.getInfo().getNumChannels());
        System.out.println(of.getTags());
        FileOutputStream fileOut = new FileOutputStream("wav16k.pcm");
        // 
        byte[] data_packet = new byte[of.getInfo().getSampleRate()];
        int samples = 0;
        while ((ad = of.getNextAudioPacket()) != null) {
            // NOTE: samplesDecoded 是decode出來的short個數,byte需要*2
            int samplesDecoded =
                    decoder.decode(ad.getData(), 0, ad.getData().length
                            , data_packet, 0, of.getInfo().getSampleRate() / 2,
                                   false);

            fileOut.write(data_packet, 0, samplesDecoded * 2);
            samples += samplesDecoded;
        }

        System.out.println("samples: " + samples);
        System.out.println("durationSeconds: " + (samples / 16000f));
        fileOut.close();
    }

感謝您的認真閱讀。

如果你覺得有幫助,歡迎點贊支援!

不定期分享軟體開發經驗,歡迎關注作者, 一起交流軟體開發: