Так что это может стать слишком сложным для объяснения, но я постараюсь сделать его простым, но информативным. моя программа, написанная на C#.net, отслеживает микрофон в течение 2 секунд и возвращает максимальное значение из выборки. Я не очень хорошо разбираюсь в том, как звук и т. д. генерируется из winmm.dll, но моя программа частично основана на NAudio и другом проекте CodeProject для визуализации волны. Формат волны, который я использую, таков:
//WaveIn.cs
private WaveFormat Format= new WaveFormat(8000, 16,1);
//waveFormat.cs
[StructLayout(LayoutKind.Sequential)]
public class WaveFormat
{
public short wFormatTag;
public short nChannels;
public int nSamplesPerSec;
public int nAvgBytesPerSec;
public short nBlockAlign;
public short wBitsPerSample;
public short cbSize;
public WaveFormat(int rate, int bits, short channels)
{
wFormatTag = (short)WaveFormats.Pcm;
nChannels = channels;
nSamplesPerSec = rate;
wBitsPerSample = (short)bits;
cbSize = 0;
nBlockAlign = (short)(nChannels * (wBitsPerSample / 8));
nAvgBytesPerSec = nSamplesPerSec * nBlockAlign;
}
(Я думаю, что, возможно, только что нашел свою проблему, опубликовав это, но я все равно спрошу)
поэтому я устанавливаю событие для максимального уровня звука в моем файле wavein. Если я правильно понимаю исходный код, он срабатывает, когда буфер заполнен. вот этот код
private void CallBack(IntPtr waveInHandle, WaveMessage message, int userData, ref WaveHeader waveHeader, IntPtr reserved)
{
if (message == WaveMessage.WIM_DATA)
{
GCHandle hBuffer = (GCHandle)waveHeader.dwUser;
WaveInBuffer buffer = (WaveInBuffer)hBuffer.Target;
Exception exception = null;
if (DataAvailable != null)
{
DataAvailable(buffer.Data, buffer.BytesRecorded);
}
if (MaxSoundLevel != null) //FOLLOW THIS ONE
{
byte[] waveStream = new byte[buffer.BytesRecorded];
Marshal.Copy(buffer.Data, waveStream, 0, buffer.BytesRecorded);
MaxSoundLevel(GetMaxSound(GetWaveChannels(waveStream)));
}
if (recording)
{
try
{
buffer.Reuse();
}
catch (Exception e)
{
recording = false;
exception = e;
}
}
}
}
private short[] GetWaveChannels(byte[] waveStream)
{
short[] monoWave = new short[waveStream.Length/2];
int h=0;
for (int i = 0 ; i < waveStream.Length; i += 2)
{
monoWave[h] = BitConverter.ToInt16(waveStream, i);
h++;
}
return monoWave;
}
private int GetMaxSound(short[] wave)
{
int maxSound = 0;
for (int i = 0; i < wave.Length; i++)
{
maxSound = Math.Max(maxSound, Math.Abs(wave[i]));
}
return maxSound;
}
поэтому, когда я наблюдаю за ним из этого теста, он не выйдет из строя, если я буду поддерживать уровень звука «нормальным».
[Test]
public void TestSound()
{
var waveIn = new WaveIn();
waveIn.MaxSoundLevel += new WaveIn.MaxSoundHandler(waveIn_MaxSoundLevel);
waveIn.StartRecording();
Console.WriteLine("Starting to record");
Thread.Sleep(4800); //record for 4.8 seconds.
waveIn.StopRecording();
Console.WriteLine("Done Recording");
}
void waveIn_MaxSoundLevel(int MaxSound)
{
Console.WriteLine("MaxSound:{0}", MaxSound);
}
вот мой вывод
MaxSound:28 MaxSound:24 MaxSound:31 MaxSound:17 MaxSound:18760
Необработанное исключение: System.OverflowException: отрицание минимального значения числа с дополнением до двух недопустимо.
Однажды я получил его, чтобы дать мне MaxSound: 32767 (0x7FFF).
Итак, я понял, что моя проблема заключалась в попытке преобразовать 32-битное число в 16-битное число, поэтому я переключил GetMaxSound с короткого на целое. Так что я не знаю. Я в тупике. Так почему у меня эта проблема? Разве моя волна не предполагает, что максимальное значение составляет 32 767, и что winmm.dll будет знать об этом и не превысит это? и поскольку он просто преобразует 2 байта данных в короткие, он никогда не столкнется с этой проблемой? Пожалуйста помоги :)
GetMaxSound
, но оставили наBitConverter.ToInt16
. - person Joshua Drake   schedule 16.05.2012GetMaxSound
из-за того, что не совсем понимаю, как он может вылететь с его настройкой. Если это битовый преобразователь, разве он никогда не должен сталкиваться с переполнением??? и не должен ли winmm просто возвращать 32767 или -32768 ... подождите, я использую абс на коротком замыкании. что 32768 приведет к переполнению, ха... BRB - person Robert Snyder   schedule 16.05.2012maxSound = Math.Max(maxSound, Math.Abs((int)wave[i]));
- это решение. Я вдул в него, и он дал мне следующий вывод. 32768 - person Robert Snyder   schedule 16.05.2012