How to get from .wav sound into double[] C#

生来就可爱ヽ(ⅴ<●) 提交于 2020-07-18 07:29:05

问题


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.

  1. You have to read wav file header.
  2. 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

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!