使用 BinaryReader 解析 Wave 文件

发布于 2024-11-06 11:05:47 字数 247 浏览 0 评论 0原文

在 .NET Assembly mscorlib System.IO 命名空间中,我使用 ReadInt16() 方法循环遍历音频数据字节并将有符号整数值转储到文本文件中。如何解释与一种采样率相关的两个值?也就是说,如果我有一秒的单声道数据,则将有 88200 个字节,因此使用 ReadInt16() 返回 88200 个离散整数。这信息太多了,我应该只有 44100 个整数。那么我是否需要使用不同的方法,或者每次迭代将循环推进 1?

非常感谢......米奇

In .NET Assembly mscorlib System.IO namespace, I am using ReadInt16() method to loop through audio data bytes and dumping signed integer values into a text file. How does one interpret the two values associated with one sample rate? That is if I have one second of mono data there will be 88200 bytes, hence using ReadInt16() returns 88200 discrete integers. This is too much information, I should only have 44100 integers. So do I need to use a different method or perhaps advance the loop by 1 per each iteration.

Many thanks..........Mickey

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

俏︾媚 2024-11-13 11:05:47
using System;
using System.IO;

public struct WaveFormat
{

    private short m_FormatTag;       // most often PCM = 1      
    private short m_nChannels;       // number of channels      
    private int m_SamplesPerSecond;  // samples per second eg 44100     
    private int m_AvgBytesPerSecond; // bytes per second eg 176000      
    private short m_BlockAlign;      // blockalign (byte per sample) eg 4 bytes         
    private short m_BitsPerSample;   // bits per sample, 8, 16, 24

    public WaveFormat(byte BPS, int SPS, byte nChn)
    {
        m_FormatTag = 1; //PCM
        m_nChannels = nChn;
        m_SamplesPerSecond = SPS;
        m_BitsPerSample = BPS;
        m_BlockAlign = (short)(m_nChannels * m_BitsPerSample / 8);
        m_AvgBytesPerSecond = (int)(m_BlockAlign * m_SamplesPerSecond);
    }
    public short FormatTag
    {
        get { return m_FormatTag; }
        set { m_FormatTag = value; }
    }
    public short Channels
    {
        get { return m_nChannels; }
    }
    public int SamplesPerSecond
    {
        get { return m_SamplesPerSecond; }
    }
    public int AvgBytesPerSecond
    {
        get { return m_AvgBytesPerSecond; }
    }
    public short BlockAlign
    {
        get { return m_BlockAlign; }
    }
    public short BitsPerSample
    {
        get { return m_BitsPerSample; }
    }
    public void Read(BinaryReader br)
    {
        m_FormatTag = br.ReadInt16();
        m_nChannels = br.ReadInt16();
        m_SamplesPerSecond = br.ReadInt32();
        m_AvgBytesPerSecond = br.ReadInt32();
        m_BlockAlign = br.ReadInt16();
        m_BitsPerSample = br.ReadInt16();
    }
    public void Write(BinaryWriter bw)
    {
        bw.Write(m_FormatTag);
        bw.Write(m_nChannels);
        bw.Write(m_SamplesPerSecond);
        bw.Write(m_AvgBytesPerSecond);
        bw.Write(m_BlockAlign);
        bw.Write(m_BitsPerSample);
    }
    public override string ToString()
    {
        System.Text.StringBuilder sb = new System.Text.StringBuilder();
        sb.AppendLine("FormatTag:         " + m_FormatTag.ToString());
        sb.AppendLine("nChannels:         " + m_nChannels.ToString());
        sb.AppendLine("SamplesPerSecond:  " + m_SamplesPerSecond.ToString());
        sb.AppendLine("AvgBytesPerSecond: " + m_AvgBytesPerSecond.ToString());
        sb.AppendLine("BlockAlign:        " + m_BlockAlign.ToString());
        sb.AppendLine("BitsPerSample:     " + m_BitsPerSample.ToString());
        return sb.ToString();
    }
}
using System;
using System.IO;

public struct WaveFormat
{

    private short m_FormatTag;       // most often PCM = 1      
    private short m_nChannels;       // number of channels      
    private int m_SamplesPerSecond;  // samples per second eg 44100     
    private int m_AvgBytesPerSecond; // bytes per second eg 176000      
    private short m_BlockAlign;      // blockalign (byte per sample) eg 4 bytes         
    private short m_BitsPerSample;   // bits per sample, 8, 16, 24

    public WaveFormat(byte BPS, int SPS, byte nChn)
    {
        m_FormatTag = 1; //PCM
        m_nChannels = nChn;
        m_SamplesPerSecond = SPS;
        m_BitsPerSample = BPS;
        m_BlockAlign = (short)(m_nChannels * m_BitsPerSample / 8);
        m_AvgBytesPerSecond = (int)(m_BlockAlign * m_SamplesPerSecond);
    }
    public short FormatTag
    {
        get { return m_FormatTag; }
        set { m_FormatTag = value; }
    }
    public short Channels
    {
        get { return m_nChannels; }
    }
    public int SamplesPerSecond
    {
        get { return m_SamplesPerSecond; }
    }
    public int AvgBytesPerSecond
    {
        get { return m_AvgBytesPerSecond; }
    }
    public short BlockAlign
    {
        get { return m_BlockAlign; }
    }
    public short BitsPerSample
    {
        get { return m_BitsPerSample; }
    }
    public void Read(BinaryReader br)
    {
        m_FormatTag = br.ReadInt16();
        m_nChannels = br.ReadInt16();
        m_SamplesPerSecond = br.ReadInt32();
        m_AvgBytesPerSecond = br.ReadInt32();
        m_BlockAlign = br.ReadInt16();
        m_BitsPerSample = br.ReadInt16();
    }
    public void Write(BinaryWriter bw)
    {
        bw.Write(m_FormatTag);
        bw.Write(m_nChannels);
        bw.Write(m_SamplesPerSecond);
        bw.Write(m_AvgBytesPerSecond);
        bw.Write(m_BlockAlign);
        bw.Write(m_BitsPerSample);
    }
    public override string ToString()
    {
        System.Text.StringBuilder sb = new System.Text.StringBuilder();
        sb.AppendLine("FormatTag:         " + m_FormatTag.ToString());
        sb.AppendLine("nChannels:         " + m_nChannels.ToString());
        sb.AppendLine("SamplesPerSecond:  " + m_SamplesPerSecond.ToString());
        sb.AppendLine("AvgBytesPerSecond: " + m_AvgBytesPerSecond.ToString());
        sb.AppendLine("BlockAlign:        " + m_BlockAlign.ToString());
        sb.AppendLine("BitsPerSample:     " + m_BitsPerSample.ToString());
        return sb.ToString();
    }
}
今天小雨转甜 2024-11-13 11:05:47

一般来说,当您读取数据数组时,您的代码应该如下所示:

for(int i = 0; i < totalNumberOfEntries; i++)
{
  // read all data for this entry
  var component1 = reader.ReadXXX();
  var component2 = reader.ReadXXX();

  // deal with data for this entry
  someEntryStroage.Add(new Entry(component1, component2);
}

最有可能(我不知道 Wave 文件格式)在您的情况下,您要么需要读取成对的 Int16 值(如果样本在一起),要么单独读取通道(如果数据为一个频道接着另一个频道。

Generally when you read arrays of data your code should look like:

for(int i = 0; i < totalNumberOfEntries; i++)
{
  // read all data for this entry
  var component1 = reader.ReadXXX();
  var component2 = reader.ReadXXX();

  // deal with data for this entry
  someEntryStroage.Add(new Entry(component1, component2);
}

Most likely (I don't know Wave file format) in your case you either need to read pairs of Int16 values (if samples are together) or read channels separately if data for one channel is after another.

我的影子我的梦 2024-11-13 11:05:47

您必须阅读 chunkinfos。数据块告诉您必须读取多少字节。 WaveFormat 告诉您每秒有多少平均字节数,以及更多信息。我有一些VB代码...

you must read the chunkinfos. The data-chunk tells you how much bytes you have to read. the WaveFormat tells you ho much Averagebytespersecond you have, and much more. I have some VB-code...

秋风の叶未落 2024-11-13 11:05:47

已使用 Sharpdevelop 将 VB 代码转换为 C# ,也许这会有所帮助......

using System;
using System.IO;

public class ChunkInfo
{
    private byte[] m_Header;
    private long m_Length;
    private long m_OffSet;
    public ChunkInfo(string Header)
    {
        m_Header = new byte[Header.Length];
        for (int i = 0; i <= m_Header.GetUpperBound(0); i++)
        {
            m_Header[i] = (byte)Header[i];
        }
    }
    public ChunkInfo(byte[] Header)
    {
        m_Header = Header;
    }
    public void Read(BinaryReader br)
    {
        m_OffSet = SearchOffset(br);
        if (m_OffSet >= 0)
        {
            br.BaseStream.Position = m_OffSet + m_Header.Length;
            m_Length = br.ReadInt32();
        }
    }
    public void Write(BinaryWriter bw)
    {
        bw.Write(m_Header);
        bw.Write(m_Length);
    }
    public long Length
    {
        get { return m_Length; }
    }
    public long OffSet
    {
        get { return m_OffSet; }
    }
    private long SearchOffset(BinaryReader br)
    {
        byte[] haystack = null;
        bool found = false;
        long offset = 0;
        long basepos = 0;
        int hlength = 260;
        long basepos_grow = hlength - m_Header.Length;
        while (!(found || (basepos >= br.BaseStream.Length)))
        {
            br.BaseStream.Position = basepos;
            haystack = br.ReadBytes(hlength);
            offset = BoyerMooreHorspool.find(haystack, m_Header);
            found = offset >= 0;
            if (found)
            {
                offset += basepos;
                break; 
            }
            else
            {
                basepos += basepos_grow;
            }
        }
        return offset;
    }
}
public static class BoyerMooreHorspool
{
    //detects a needle in the haystack
    const int UBYTE_MAX = 255;
    static int[] bad_char_skip4 = new int[UBYTE_MAX + 3];
    static int[] bad_char_skip8 = new int[UBYTE_MAX + 3];
    static bool IsInitialized = false;
    public static void init()
    {
        //little optimization for needles with length 4 or 8
        for (int i = 0; i <= UBYTE_MAX + 2; i++)
        {
            bad_char_skip4[i] = 4;
            bad_char_skip8[i] = 8;
        }
        IsInitialized = true;
    }
    public static int find(byte[] haystack, byte[] needle, int start = 0)
    {
        if (!IsInitialized) init();
        int i_n = 0;
        //needle index
        int n_n = needle.Length;
        int[] bad_char_skip = null;
        switch (n_n)
        {
            case 4:
                bad_char_skip = bad_char_skip4;
                break;
            case 8:
                bad_char_skip = bad_char_skip8;
                break;
            default:
                bad_char_skip = new int[UBYTE_MAX + 3];
                for (i_n = 0; i_n <= UBYTE_MAX + 2; i_n++)
                {
                    bad_char_skip[i_n] = n_n;
                }

                break;
        }
        int ifind = -1;
        //if not found then return - 1
        int i_h = start;
        //haystack index
        int n_h = haystack.Length;
        if (n_n > n_h)
            throw new ArgumentOutOfRangeException("needle", "needle is to long");
        int last = n_n - 1;
        for (i_n = 0; i_n <= last - 1; i_n++)
        {
            bad_char_skip[needle[i_n]] = last - i_n;
        }
        byte bcs = 0;
        int bhs = 0;
        while ((n_h - start) >= n_n)
        {
            i_n = last;
            while (haystack[i_h + i_n] == needle[i_n])
            {
                i_n -= 1;
                if (i_n == 0)
                {
                    ifind = i_h;
                    break; 
                }
            }
            bhs = haystack[i_h + last];
            bcs = (byte)(bad_char_skip[bhs]);
            n_h -= bcs;
            i_h += bcs;
        }
        return ifind;
    }
}

have converted the VB-code with sharpdevelop to C# maybe it helps a little bit...

using System;
using System.IO;

public class ChunkInfo
{
    private byte[] m_Header;
    private long m_Length;
    private long m_OffSet;
    public ChunkInfo(string Header)
    {
        m_Header = new byte[Header.Length];
        for (int i = 0; i <= m_Header.GetUpperBound(0); i++)
        {
            m_Header[i] = (byte)Header[i];
        }
    }
    public ChunkInfo(byte[] Header)
    {
        m_Header = Header;
    }
    public void Read(BinaryReader br)
    {
        m_OffSet = SearchOffset(br);
        if (m_OffSet >= 0)
        {
            br.BaseStream.Position = m_OffSet + m_Header.Length;
            m_Length = br.ReadInt32();
        }
    }
    public void Write(BinaryWriter bw)
    {
        bw.Write(m_Header);
        bw.Write(m_Length);
    }
    public long Length
    {
        get { return m_Length; }
    }
    public long OffSet
    {
        get { return m_OffSet; }
    }
    private long SearchOffset(BinaryReader br)
    {
        byte[] haystack = null;
        bool found = false;
        long offset = 0;
        long basepos = 0;
        int hlength = 260;
        long basepos_grow = hlength - m_Header.Length;
        while (!(found || (basepos >= br.BaseStream.Length)))
        {
            br.BaseStream.Position = basepos;
            haystack = br.ReadBytes(hlength);
            offset = BoyerMooreHorspool.find(haystack, m_Header);
            found = offset >= 0;
            if (found)
            {
                offset += basepos;
                break; 
            }
            else
            {
                basepos += basepos_grow;
            }
        }
        return offset;
    }
}
public static class BoyerMooreHorspool
{
    //detects a needle in the haystack
    const int UBYTE_MAX = 255;
    static int[] bad_char_skip4 = new int[UBYTE_MAX + 3];
    static int[] bad_char_skip8 = new int[UBYTE_MAX + 3];
    static bool IsInitialized = false;
    public static void init()
    {
        //little optimization for needles with length 4 or 8
        for (int i = 0; i <= UBYTE_MAX + 2; i++)
        {
            bad_char_skip4[i] = 4;
            bad_char_skip8[i] = 8;
        }
        IsInitialized = true;
    }
    public static int find(byte[] haystack, byte[] needle, int start = 0)
    {
        if (!IsInitialized) init();
        int i_n = 0;
        //needle index
        int n_n = needle.Length;
        int[] bad_char_skip = null;
        switch (n_n)
        {
            case 4:
                bad_char_skip = bad_char_skip4;
                break;
            case 8:
                bad_char_skip = bad_char_skip8;
                break;
            default:
                bad_char_skip = new int[UBYTE_MAX + 3];
                for (i_n = 0; i_n <= UBYTE_MAX + 2; i_n++)
                {
                    bad_char_skip[i_n] = n_n;
                }

                break;
        }
        int ifind = -1;
        //if not found then return - 1
        int i_h = start;
        //haystack index
        int n_h = haystack.Length;
        if (n_n > n_h)
            throw new ArgumentOutOfRangeException("needle", "needle is to long");
        int last = n_n - 1;
        for (i_n = 0; i_n <= last - 1; i_n++)
        {
            bad_char_skip[needle[i_n]] = last - i_n;
        }
        byte bcs = 0;
        int bhs = 0;
        while ((n_h - start) >= n_n)
        {
            i_n = last;
            while (haystack[i_h + i_n] == needle[i_n])
            {
                i_n -= 1;
                if (i_n == 0)
                {
                    ifind = i_h;
                    break; 
                }
            }
            bhs = haystack[i_h + last];
            bcs = (byte)(bad_char_skip[bhs]);
            n_h -= bcs;
            i_h += bcs;
        }
        return ifind;
    }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文