PCM
自然界中的聲音非常復雜,波形極其復雜,通常我們采用的是脈沖代碼調制編碼,即PCM編碼。PCM通過抽樣、量化、編碼三個步驟將連續變化的模擬信號轉換為數字編碼。
采樣率
采樣頻率,也稱為采樣速度或者采樣率,定義了每秒從連續信號中提取並組成離散信號的采樣個數,它用赫茲(Hz)來表示。采樣頻率的倒數是采樣周期或者叫作采樣時間,它是采樣之間的時間間隔。通俗的講采樣頻率是指計算機每秒鍾采集多少個信號樣本。
工業界常用的16K,就是1s有16000個采樣點。
WAV
PCM是原始語音,依據采樣率的定義,我們知道要播放PCM,需要知道采樣率,因此需要一個文件格式可以封裝PCM,wav
就是微軟公司專門為Windows開發的一種標准數字音頻文件,該文件能記錄各種單聲道或立體聲的聲音信息。
wav文件前44個字節,定義了采樣率,channel等參數,播放器通過這個數據就可以播放PCM數據了。
MP3
wav
很好的解決了PCM播放的問題,但是PCM實在是太大了,因此出現了mp3
等音頻格式,通過一定的壓縮算法壓縮語音,以便於互聯網傳輸分享。
Ogg 與 Opus
隨着音視頻應用的越來越廣泛,工業界有了越來越多的編解碼器,比如Speek
,Opus
Opus編解碼器是專門設計用於互聯網的交互式語音和音頻傳輸。它是由IETF的編解碼器工作組設計的,合並了Skype的SILK和Xiph. Org的CELT技術。
OPUS編解碼
https://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類似 |
參考: https://juejin.cn/post/6844904016254599175
借博主的圖:
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();
}
感謝您的認真閱讀。
如果你覺得有幫助,歡迎點贊支持!
不定期分享軟件開發經驗,歡迎關注作者, 一起交流軟件開發: