Я написал библиотеку-оболочку библиотеки WinMM, которая предоставляет классы WaveOut и WaveIn для записи и воспроизведения необработанных аудиопотоков.
Все отлично работает, но для того, чтобы следовать спецификациям операционной системы о том, как обрабатывать готовые буферы, я добавил поток, который освобождает буферы и освобождает память. Я также отключил всю синхронизацию, чтобы классы были надежными и потокобезопасными.
Однако, кажется, есть редкая проблема, когда я добавляю буфер на устройство WaveOut, и операционная система возвращает код успеха, но если устройство сразу после слов сбрасывается, ОС не помечает буфер как завершенный и возвращает это к заявке.
Кажется, что он теряет буферы. Итак, проблема в том, что я отслеживаю количество отдельных буферов, отправляемых на устройство, и блокирую присоединение функции Close () к потоку, который их очищает.
Есть идеи или известные ошибки?
PS: Похоже, что это не происходит на Quad Core в Vista, но происходит на моем Dual Core в XP pro.
РЕДАКТИРОВАТЬ1: Я полностью готов предоставить полный исходный код, как только я загружу его и лицензирую надлежащим образом на codeplex, если это кому-нибудь поможет.
РЕДАКТИРОВАТЬ 2: Размещенная библиотека для CodePlex: http://winmm.codeplex.com/
Вот идея причины проблемы:
public partial class MainView : Form
{
private WaveIn waveIn = new WaveIn(WaveIn.WaveInMapperDeviceId);
private WaveOut waveOut = new WaveOut(WaveOut.WaveOutMapperDeviceId);
public MainView()
{
InitializeComponent();
WaveFormat format = WaveFormat.Pcm44Khz16BitMono;
waveOut.Open(format);
waveIn.DataReady += new EventHandler<DataReadyEventArgs>(WaveIn_DataReady);
// Tweaking these values affects the internal buffering thread.
// Setting too small of a QueueSize with too small of a BufferSize
// will cause buffer underruns, which will sound like choppy audio.
waveIn.BufferQueueSize = 200;
waveIn.BufferSize = 64;
waveIn.Open(format);
waveIn.Start();
}
void WaveIn_DataReady(object sender, DataReadyEventArgs e)
{
if (waveOut != null)
{
lock (waveOut)
{
// We have to check for null after the lock,
// because waveOut may have been disposed
// inside another lock.
if (waveOut != null)
{
waveOut.Write(e.Data);
}
}
}
}
private void MainView_FormClosed(object sender, FormClosedEventArgs e)
{
if (waveIn != null)
{
lock (waveIn)
{
waveIn.Dispose();
waveIn = null;
}
}
if (waveOut != null)
{
lock (waveOut)
{
waveOut.Dispose();
waveOut = null;
}
}
}
}