一個.wav-文件有3個大塊: 每個塊的大小4字節的
第一塊是「RIFF」 - 大塊。它包括8字節的文件大小(4字節)和格式名稱(4字節,通常是「WAVE」)。
下一個塊是「fmt」-chunk(塊名中的空間很重要)。它包括音頻格式(2字節),通道數量(2字節),採樣率(4字節),字節速率(4字節),塊對齊(2字節)以及每個採樣位數(2字節) 。
第三個也是最後一個塊是數據塊。這裏是真實的數據和樣本的幅度。它包含數據大小的4字節,這是數據的字節數。
您可以進一步瞭解.wav文件here的屬性。
從這個知識,我已經創建了下面的類:
public sealed class WaveFile
{
//privates
private int fileSize;
private string format;
private int fmtChunkSize;
private int audioFormat;
private int numChannels;
private int sampleRate;
private int byteRate;
private int blockAlign;
private int bitsPerSample;
private int dataSize;
private int[][] data;//One array per channel
//publics
public int FileSize => fileSize;
public string Format => format;
public int FmtChunkSize => fmtChunkSize;
public int AudioFormat => audioFormat;
public int NumChannels => numChannels;
public int SampleRate => sampleRate;
public int ByteRate => byteRate;
public int BitsPerSample => bitsPerSample;
public int DataSize => dataSize;
public int[][] Data => data;
public WaveFile(string path)
{
FileStream fs = File.OpenRead(path);
LoadChunk(fs); //read RIFF Chunk
LoadChunk(fs); //read fmt Chunk
LoadChunk(fs); //read data Chunk
fs.Close();
}
private void LoadChunk(FileStream fs)
{
ASCIIEncoding Encoder = new ASCIIEncoding();
byte[] bChunkID = new byte[4];
fs.Read(bChunkID, 0, 4);
string sChunkID = Encoder.GetString(bChunkID);
byte[] ChunkSize = new byte[4];
fs.Read(ChunkSize, 0, 4);
if (sChunkID.Equals("RIFF"))
{
fileSize = BitConverter.ToInt32(ChunkSize, 0);
byte[] Format = new byte[4];
fs.Read(Format, 0, 4);
this.format = Encoder.GetString(Format);
}
if (sChunkID.Equals("fmt "))
{
fmtChunkSize = BitConverter.ToInt32(ChunkSize, 0);
byte[] audioFormat = new byte[2];
fs.Read(audioFormat, 0, 2);
this.audioFormat = BitConverter.ToInt16(audioFormat, 0);
byte[] numChannels = new byte[2];
fs.Read(numChannels, 0, 2);
this.numChannels = BitConverter.ToInt16(numChannels, 0);
byte[] sampleRate = new byte[4];
fs.Read(sampleRate, 0, 4);
this.sampleRate = BitConverter.ToInt32(sampleRate, 0);
byte[] byteRate = new byte[4];
fs.Read(byteRate, 0, 4);
this.byteRate = BitConverter.ToInt32(byteRate, 0);
byte[] blockAlign = new byte[2];
fs.Read(blockAlign, 0, 2);
this.blockAlign = BitConverter.ToInt16(blockAlign, 0);
byte[] bitsPerSample = new byte[2];
fs.Read(bitsPerSample, 0, 2);
this.bitsPerSample = BitConverter.ToInt16(bitsPerSample, 0);
}
if (sChunkID.Equals("data"))
{
dataSize = BitConverter.ToInt32(ChunkSize, 0);
data = new int[this.numChannels][];
byte[] temp = new byte[dataSize];
for (int i = 0; i < this.numChannels; i++)
{
data[i] = new int[this.dataSize/(numChannels * bitsPerSample/8)];
}
for (int i = 0; i < data[0].Length; i++)
{
for (int j = 0; j < numChannels; j++)
{
if (fs.Read(temp, 0, blockAlign/numChannels) > 0)
{
if (blockAlign/numChannels == 2)
{ data[j][i] = BitConverter.ToInt32(temp, 0); }
else
{ data[j][i] = BitConverter.ToInt16(temp, 0); }
}
}
}
}
}
}
所需using指令:
using System;
using System.IO;
using System.Text;
該類讀取每個字節的所有字節塊,並設置屬性。你只需要初始化這個類,它將返回你選擇的波形文件的所有屬性。
它非常含糊地提及它沒有運行/沒有工作。請提及您的例外情況,如有任何或任何有關錯誤的細節。 –
我確實提到過這些東西。我沒有看到第一個緩衝區中的「數據」,我的subchunk2size太小了。 – Thundercleez
你能解釋你如何期待數據被格式化嗎?從代碼它看起來像︰ 標題(40):chunksize(4):(數據塊大小):(:(4個字節的東西?):(新的塊大小):(數據塊大小):等... 是否正確? – meganaut