How to read the data in a wav file to an array

后端 未结 7 2042
清酒与你
清酒与你 2020-11-27 15:17

I need to get all the samples of a wav file into an array (or two if you need to do that to keep the stereo) so that I can apply some modifications to them. I was wondering

7条回答
  •  挽巷
    挽巷 (楼主)
    2020-11-27 16:01

    At time of writing nobody has addressed 32-bit or 64-bit encoded WAVs.

    The following code handles 16/32/64 bit and mono/stereo:

    static bool readWav( 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 (expect 16 or 18)
    
                // 16 bytes coming...
                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
                int dataID = reader.ReadInt32();
                int bytes = reader.ReadInt32();
    
                // DATA!
                byte[] byteArray = reader.ReadBytes(bytes);
    
                int bytesForSamp = bitDepth/8;
                int nValues = bytes / bytesForSamp;
    
    
                float[] asFloat = null;
                switch( bitDepth ) {
                    case 64:
                        double[] 
                            asDouble = new double[nValues];  
                        Buffer.BlockCopy(byteArray, 0, asDouble, 0, bytes);
                        asFloat = Array.ConvertAll( asDouble, e => (float)e );
                        break;
                    case 32:
                        asFloat = new float[nValues];   
                        Buffer.BlockCopy(byteArray, 0, asFloat, 0, bytes);
                        break;
                    case 16:
                        Int16 [] 
                            asInt16 = new Int16[nValues];   
                        Buffer.BlockCopy(byteArray, 0, asInt16, 0, bytes);
                        asFloat = Array.ConvertAll( asInt16, e => e / (float)(Int16.MaxValue+1) );
                        break;
                    default:
                        return false;
                }
    
                switch( channels ) {
                case 1:
                    L = asFloat;
                    R = null;
                    return true;
                case 2:
                    // de-interleave
                    int nSamps = nValues / 2;
                    L = new float[nSamps];
                    R = new float[nSamps];
                    for( int s=0, v=0; s

提交回复
热议问题