可以正确读取WAV文件的数据

Posted

技术标签:

【中文标题】可以正确读取WAV文件的数据【英文标题】:Could read properly the data of WAV file 【发布时间】:2016-01-10 01:44:03 【问题描述】:

我正在尝试阅读wav file,如下所示

class Program
    
        struct WavHeader
        
            public int riffID; 
            public int size; 
            public int wavID;  
            public int fmtID; 
            public int fmtSize;
            public int format;
            public int channels; 
            public int sampleRate;
            public int bytePerSec; 
            public int blockSize;
            public int bit; 
            public int dataID; 
            public int dataSize; 
        
        static void Main(string[] args)
        
            WavHeader Header = new WavHeader();
            List<short> lDataList = new List<short>();
            List<short> rDataList = new List<short>();

            using (FileStream fs = new FileStream(@"D:\Test.wav", FileMode.Open, FileAccess.Read))
            using (BinaryReader br = new BinaryReader(fs))
            
                try
                                    
                    Header.riffID = br.ReadInt32();
                    Header.size = br.ReadInt32();
                    Header.wavID = br.ReadInt32();
                    Header.fmtID = br.ReadInt32();
                    Header.fmtSize = br.ReadInt32();
                    Header.format = br.ReadUInt16();
                    Header.channels = br.ReadUInt16();
                    Header.sampleRate = br.ReadInt32();
                    Header.bytePerSec = br.ReadInt32();
                    Header.blockSize = br.ReadInt16();
                    Header.bit = br.ReadInt16();

                    if (Header.fmtSize == 18)
                    
                        // Read any extra values
                        int fmtExtraSize = br.ReadInt16();
                        br.ReadBytes(fmtExtraSize);
                    
                    Header.dataID = br.ReadInt32();
                    Header.dataSize = br.ReadInt32();

                    int bytesForSamp = Header.bit / 8;
                    int samps = Header.dataSize / bytesForSamp;


                    for (int i = 0; i < samps; i++)
                    
                        lDataList.Add((short)br.ReadUInt16());
                        rDataList.Add((short)br.ReadUInt16());
                    


                
                finally
                
                    if (br != null)
                    
                        br.Close();
                    
                    if (fs != null)
                    
                        fs.Close();
                    
                
            
        
    

但是在

处出现运行时错误
lDataList.Add((short)br.ReadUInt16());
rDataList.Add((short)br.ReadUInt16());

“无法在流结束后读取。”

我已经看到了这个SO Q/A 并尝试按照要求进行调整,但返回浮动。

【问题讨论】:

【参考方案1】:

在这里您正确计算了每个样本的字节数和样本数:

int bytesForSamp = Header.bit / 8;
int samps = Header.dataSize / bytesForSamp;

但在这里您假设该文件有 2 个通道和 16 位样本:

for (int i = 0; i < samps; i++)

    lDataList.Add((short)br.ReadUInt16());
    rDataList.Add((short)br.ReadUInt16());

如果文件实际上有 8 位样本和/或只有 1 个通道,则此循环会尝试在某个点读取输入文件之外的内容。 您要么必须断言,在读取标头后文件实际上是 16 位 2ch,要么通过根据波形文件标头中指定的每个样本的位数和通道正确读取来正确处理文件。

【讨论】:

它有 16 位但有 1 个通道..你是对的..那么如何处理呢? 作为一个快速修复,仅对于 this 特殊情况,您可以这样做: unsigned short data = br.ReadUInt16(); lDataList.Add(数据); rDataList.Add(数据);将数据复制到两个通道。但是您必须在生产代码中正确处理所有情况(1 到 n 个通道,n 位样本大小)。或者,如果 wav 文件具有未处理的属性,则会显示错误消息 正确,我就是这么做的。

以上是关于可以正确读取WAV文件的数据的主要内容,如果未能解决你的问题,请参考以下文章

Java 读取/操作 Wav 文件

C++ 读取 WAV 文件的数据部分

这是读取音频文件 FFT 的正确方法吗? (python + wav)

使用 Hopfield 神经网络读取 WAV 文件的数据部分以进行语音识别

在应用 FFT 之前从 wav 文件中读取数据

写入 WAV 文件 C++