幀
幀是樣品在所有通道中的音頻文件的橫截面。因此,一個16位立體聲(雙聲道)音頻文件將具有32位幀(每個採樣16位*每幀2個通道=每幀32位)。
裝入原始數據
爪哇8位字節讀出原始音頻數據,但大多數的音頻具有更高的樣本大小。因此,爲了表示音頻,您必須合併多個字節才能以音頻格式創建樣本。但首先,在將字節組合到採樣中之前,您需要將所有音頻加載到緩衝區中。
開始從文件中獲取音頻流:
File file = new File(filename);
AudioInputStream audioInputStream = AudioSystem.getAudioInputStream(file);
現在,你有的AudioInputStream,您可以在音頻數據讀出。 AudioInputStream有一個read()方法,它接受一個未填充的字節[],並讀取數據中byte []的長度。要一次性讀取整個音頻文件,請在整個音頻文件的長度上創建一個字節[]。以字節爲單位的文件的完整長度爲:
的每幀的字節=字節總數*幀
總數
你可以得到的幀的整個文件(幀長度)的數量和的大小幀(幀大小)從AudioInputStream:
int frameLength =(int)audioInputStream.getFrameLength(); int frameSize =(int)audioInputStream.getFormat()。getFrameSize();
您可以創建一個長度設定爲幀長度*框架尺寸字節[]:
byte[] bytes = new byte[frameLength * frameSize];
最後,你可以在音頻讀取,傳遞的AudioInputStream空字節[]和捕捉適當的例外:
int result = 0;
try {
result = audioInputStream.read(bytes);
} catch (Exception e) {
e.printStackTrace();
}
轉換爲樣品和渠道
原始音頻數據不是非常有用的。它需要分解成渠道和樣本。從那裏,很容易畫樣品。
字節將被轉換爲採樣並以int表示。您需要一個容器來存儲所有渠道的樣本。因此,創建一個兩維的int [] []來引用每個通道的通道和採樣。您已經看到如何從AuduioInputStream獲取幀長度,並且您可以通過相同的方式獲取通道數量。這裏是初始化INT [] []的代碼:
int numChannels = audioInputStream.getFormat().getChannels();
int frameLength = (int) audioInputStream.getFrameLength();
int[][] toReturn = new int[numChannels][frameLength];
現在,需要通過字節[]進行迭代時,字節轉換成樣品,並放置在適當的信道的樣品中的INT [ ] []。字節[]按幀組織,這意味着您將讀取每個通道的樣本,而不是針對某一行中特定通道的所有樣本。因此,流動是通過渠道循環,直到字節[]已經完全重複添加樣本:
int sampleIndex = 0;
for (int t = 0; t < eightBitByteArray.length;) {
for (int channel = 0; channel < numChannels; channel++) {
int low = (int) eightBitByteArray[t];
t++;
int high = (int) eightBitByteArray[t];
t++;
int sample = getSixteenBitSample(high, low);
toReturn[channel][sampleIndex] = sample;
}
sampleIndex++;
}
這是一個相當寬泛的問題,我想打破它分爲兩個更集中的問題,比如「如何你是否在Java Swing應用程序中播放音樂?「 (我認爲人們會把你引導到JMF)和「你如何爲可視化樣本播放一段音樂?」 (我想你會被告知快速傅里葉變換(FFT))。 –
當然,當你打字的時候,這個人很可能會丟掉你正在看的完美的例子。這就是有時這樣工作的方式:) –