问题
I need to perform FFT and I have a sound sample .wav format.
The function needs double[] xRe, double[] xIm, REAL PART and imaginary part
How to convert the sound file into double[]?
I have never seen something like that. Could not find in the internet that kind of operation.
This is this sound sample:
http://www.speedyshare.com/fFD8t/e.wav
Please help, cause I used Pascal and now don't know what to do here.
回答1:
It's a simple stream operation.
- You have to read wav file header.
- You have to read data bytes.
Paste from MSDN:
BinaryReader reader = new BinaryReader(waveFileStream);
//Read the wave file header from the buffer.
int chunkID = reader.ReadInt32();
int fileSize = reader.ReadInt32();
int riffType = reader.ReadInt32();
int fmtID = reader.ReadInt32();
int fmtSize = reader.ReadInt32();
int fmtCode = reader.ReadInt16();
int channels = reader.ReadInt16();
int sampleRate = reader.ReadInt32();
int fmtAvgBPS = reader.ReadInt32();
int fmtBlockAlign = reader.ReadInt16();
int bitDepth = reader.ReadInt16();
if (fmtSize == 18)
{
// Read any extra values
int fmtExtraSize = reader.ReadInt16();
reader.ReadBytes(fmtExtraSize);
}
int dataID = reader.ReadInt32();
int dataSize = reader.ReadInt32();
// Store the audio data of the wave file to a byte array.
byteArray = reader.ReadBytes(dataSize);
// After this you have to split that byte array for each channel (Left,Right)
// Wav supports many channels, so you have to read channel from header
Here this is more detailed explanation:
http://msdn.microsoft.com/en-us/library/ff827591.aspx
And here you can read about WAV file format:
https://ccrma.stanford.edu/courses/422/projects/WaveFormat/
And something about WAV as complex numbers and FFT:
How to convert wave data into Complex numbers
回答2:
Kamil's solution was very close, but didn't work for some of the wav files I ran across. After some research, here is what I discovered. In the description of the canonical WAV PCM sound file format (http://soundfile.sapp.org/doc/WaveFormat/), I discovered this reference in the Notes: There may be additional subchunks in a Wave data stream. If so, each will have a char[4] SubChunkID, and unsigned long SubChunkSize, and SubChunkSize amount of data.
In a few wav files I ran across, there were indeed extra subchunks, so I had to add some code to read until it found the "data" marker. After adding this, it worked universally. My complete code is below.
public static bool ReadWavFile(string filename, out float[] L, out float[] R)
{
L = R = null;
try
{
using (FileStream fs = File.Open(filename, FileMode.Open))
{
BinaryReader reader = new BinaryReader(fs);
// chunk 0
int chunkID = reader.ReadInt32();
int fileSize = reader.ReadInt32();
int riffType = reader.ReadInt32();
// chunk 1
int fmtID = reader.ReadInt32();
int fmtSize = reader.ReadInt32(); // bytes for this chunk
int fmtCode = reader.ReadInt16();
int channels = reader.ReadInt16();
int sampleRate = reader.ReadInt32();
int byteRate = reader.ReadInt32();
int fmtBlockAlign = reader.ReadInt16();
int bitDepth = reader.ReadInt16();
if (fmtSize == 18)
{
// Read any extra values
int fmtExtraSize = reader.ReadInt16();
reader.ReadBytes(fmtExtraSize);
}
// chunk 2 -- HERE'S THE NEW STUFF (ignore these subchunks, I don't know what they are!)
int bytes;
while(new string(reader.ReadChars(4)) != "data")
{
bytes = reader.ReadInt32();
reader.ReadBytes(bytes);
}
// DATA!
bytes = reader.ReadInt32();
byte[] byteArray = reader.ReadBytes(bytes);
int bytesForSamp = bitDepth / 8;
int samps = bytes / bytesForSamp;
float[] asFloat = null;
switch (bitDepth)
{
case 64:
double[]
asDouble = new double[samps];
Buffer.BlockCopy(byteArray, 0, asDouble, 0, bytes);
asFloat = Array.ConvertAll(asDouble, e => (float)e);
break;
case 32:
asFloat = new float[samps];
Buffer.BlockCopy(byteArray, 0, asFloat, 0, bytes);
break;
case 16:
Int16[]
asInt16 = new Int16[samps];
Buffer.BlockCopy(byteArray, 0, asInt16, 0, bytes);
asFloat = Array.ConvertAll(asInt16, e => e / (float)Int16.MaxValue);
break;
default:
return false;
}
switch (channels)
{
case 1:
L = asFloat;
R = null;
return true;
case 2:
L = new float[samps];
R = new float[samps];
for (int i = 0, s = 0; i < samps; i++)
{
L[i] = asFloat[s++];
R[i] = asFloat[s++];
}
return true;
default:
return false;
}
}
}
catch
{
Debug.WriteLine("...Failed to load note: " + filename);
return false;
//left = new float[ 1 ]{ 0f };
}
}
来源:https://stackoverflow.com/questions/13390472/how-to-get-from-wav-sound-into-double-c-sharp