Разбор через волновой файл с BinaryReader - PullRequest
1 голос
/ 12 мая 2011

В пространстве имен .NET mscorlib System.IO я использую метод ReadInt16 () для циклического прохождения байтов аудиоданных и выгрузки целочисленных значений со знаком в текстовый файл. Как интерпретировать два значения, связанные с одной частотой дискретизации? То есть, если у меня есть одна секунда монофонических данных, будет 88200 байт, следовательно, использование ReadInt16 () возвращает 88200 дискретных целых чисел. Это слишком много информации, у меня должно быть только 44100 целых чисел. Поэтому мне нужно использовать другой метод или, возможно, увеличивать цикл на 1 за каждую итерацию.

Большое спасибо .......... Микки

Ответы [ 4 ]

0 голосов
/ 13 мая 2011
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();
    }
}
0 голосов
/ 12 мая 2011

вы должны прочитать chunkinfos. Блок данных сообщает вам, сколько байтов вы должны прочитать. WaveFormat сообщает вам, сколько у вас в среднем средних секунд, и многое другое. У меня есть некоторый VB-код ...

0 голосов
/ 13 мая 2011

преобразовали VB-код с sharpdevelop в 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;
    }
}
0 голосов
/ 12 мая 2011

Как правило, когда вы читаете массивы данных, ваш код должен выглядеть следующим образом:

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 (если сэмплы вместе) или считывание каналов отдельно, если данные для одного канала следуют за другим.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...