naudio / NAudio

Audio and MIDI library for .NET
MIT License
5.5k stars 1.1k forks source link

NAudio pcm record with "winmm.dll" - Casual "AccessViolationException" on waveInPrepareHeader #1084

Open FossaMalaEnt opened 11 months ago

FossaMalaEnt commented 11 months ago

Hi,

My application (.NET 7), sometimes crash when I'm trying to start recording using NAudio WaveIn with the following error

System.AccessViolationException: Attempted to read or write protected memory. This is often an indication that other memory is corrupt. Stack: at NAudio.Wave.WaveInterop.waveInPrepareHeader(IntPtr, NAudio.Wave.WaveHeader, Int32) at NAudio.Wave.WaveInterop.waveInPrepareHeader(IntPtr, NAudio.Wave.WaveHeader, Int32) at NAudio.Wave.WaveInBuffer.Reuse() at NAudio.Wave.WaveInEvent.DoRecording() at NAudio.Wave.WaveInEvent.RecordThread() at System.Threading.QueueUserWorkItemCallback.Execute() at System.Threading.ThreadPoolWorkQueue.Dispatch() at System.Threading.PortableThreadPool+WorkerThread.WorkerThreadStart()

This is how i start the recording on user interaction;

if (this.PcmWaveIn == null)
{
    Console.WriteLine("PcmWaveIn init started...");

    this.PcmWaveIn = new WaveInEvent
    {
        DeviceNumber = 0,
        WaveFormat = new WaveFormat(rate: 8000, bits: 16, channels: 1),
        BufferMilliseconds = 20
    };

    this.PcmWaveIn.DataAvailable += (object? sender, WaveInEventArgs e) =>
    {
        // copy buffer into an array of integers
        Int16[] values = new Int16[e.Buffer.Length / 2];
        Buffer.BlockCopy(e.Buffer, 0, values, 0, e.Buffer.Length);

        // Perform A-law encoding
        byte[] alawData = new byte[e.Buffer.Length / 2];
        for (int i = 0; i < e.Buffer.Length; i += 2)
        {
            short sample = BitConverter.ToInt16(e.Buffer, i);
            alawData[i / 2] = NAudio.Codecs.ALawEncoder.LinearToALawSample(sample);
        }
        // Do things....
    };

    Console.WriteLine("PcmWaveIn init complete...");
}
this.PcmWaveIn.StartRecording();

And then simply stop with: this.PcmWaveIn?.StopRecording();

I always leave the application running, and this issue sometimes occurs on the same day I start the software, or sometimes after a week or a few days. The application also makes extensive use of multithreading. Could this affect how the library manages resources?

markheath commented 10 months ago

An access violation can be hard to track down because it could be completely different code that is corrupting memory. Is there any other unsafe code or interop involved?