#c# #file #wave #audio-processing
#c# #файл #wave #обработка звука
Вопрос:
В системе mscorlib сборки .NET.Пространство имен ввода-вывода, я использую метод ReadInt16() для перебора байтов аудиоданных и сброса целых значений со знаком в текстовый файл. Как интерпретировать два значения, связанные с одной частотой дискретизации? То есть, если у меня есть одна секунда моноданных, там будет 88200 байт, следовательно, использование ReadInt16 () возвращает 88200 дискретных целых чисел. Это слишком много информации, у меня должно быть только 44100 целых чисел. Итак, нужно ли мне использовать другой метод или, возможно, увеличивать цикл на 1 за каждую итерацию.
Большое спасибо………. Микки
Ответ №1:
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();
}
}
Ответ №2:
Обычно, когда вы читаете массивы данных, ваш код должен выглядеть следующим образом:
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 (если выборки находятся вместе), либо прочитать каналы отдельно, если данные для одного канала следуют за другим.
Комментарии:
1. каналы в wav-файле «мультиплексированы», это означает: sample1_chnl_1, sample1_chnl_2, sample2_chnl_1, sample2_chnl_2, sample3_chnl_1, sample3_chnl_2, sample4_chnl_1, sample4_chnl_2…
Ответ №3:
вы должны прочитать chunkinfos. Блок данных сообщает вам, сколько байт вам нужно прочитать. формат WaveFormat сообщает вам, сколько средних байт в секунду у вас есть, и многое другое. У меня есть некоторый VB-код…
Ответ №4:
преобразовал 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;
}
}