Attempted to read or write protected memory. This is often an indication that other memory is corrupt.

Jan 4, 2013 at 11:26 AM
Edited Jan 4, 2013 at 3:11 PM

Hi..

I have created Audio player which supports GUI as well as thread environment. It works fine if we are playing audio on GUI thread but if there are so many background threads which are playing audio file then within 1 hour audio player getting crashed with above exception.

to support threading i am using WaveOutEvent.

Also internally for each play i am creating new device to play loaded audio.

All operation like create device, stop, play audio, reset duration am doing on single thread using AutoResetEvent.

Also if we want to play audio for 30 seconds then i am playing same audio for 30 second but for each replay i am creating new device and loading same file again. 

for play and replay purpose i am using same code please check following

 

 private bool PlayAudioFile()
        {
            if (_wavePlayer == null || _fileStream == null || _wavePlayer.PlaybackState == PlaybackState.Playing)
                return false;
            _fileStream.Position = 0;
            CloseWavePlayer();
            EnsureDeviceCreated();
            _wavePlayer.Init(new SampleToWaveProvider(_sampleChannel));
            _wavePlayer.Play();
            _dontFireEvent = false;
            return true;
        }

 

here EnsureDeviceCreated creating new WaveOutEvent with 200 latency.

Exception coming at following line in WaveOutBuffer's constructor.

 

 MmException.Try(WaveInterop.waveOutPrepareHeader(hWaveOut, header, Marshal.SizeOf(header)), "waveOutPrepareHeader");

 

Please help me to sort out above issue...

Thanks in Advanced..

NileshN

Feb 1, 2013 at 12:56 PM
generally Why system throws access violation error ?
Coordinator
Feb 5, 2013 at 9:47 AM
access violation relates to memory corruption. It could be something strange with the way you do threading, or a bug somewhere in NAudio (are you using the latest version?), or even a problem with your soundcard drivers. Tracking them down is hard. I usually try to create the simplest program possible that exhibits the problem.
Feb 5, 2013 at 6:15 PM
I ran into the same problem. Looks like it occurs if you create and destroy waveOutEvent player continuously.
Could not trace the root cause though.
My requirement was to play a succession of wav files. Creating, initing with file provider, playing, destroying a waveplayer in a cycle seemed the obvious solution. But alas.
I ended up solving the problem in another way: creating a SwitchingWaveProvider, which wraps actual providers, which can be changed at runtime. Create a player once and init once with this provider. Keep switching providers on this front provider. Probably one of the mixing providers could have done the trick too, but could'nt find one for 16 bit format.
Here is SwitchingWaveProvider.cs code. Include if it seems useful
using System;
using System.Collections.Generic;
using System.Text;
using System.Collections;
using NAudio.Wave;
using NAudio.Utils;

namespace NAudio.Wave
{
    /// <summary>
    /// Facade for a real wave provider which can be switched at runtime
    /// </summary>
    public class SwitchingWaveProvider : IWaveProvider
    {
        private WaveFormat waveFormat;
        private IWaveProvider srcProvider = null;
        private object lockObj = new object();

        /// <summary>
        /// Creates a new switching WaveProvider
        /// </summary>
        /// <param name="waveFormat">WaveFormat</param>
        public SwitchingWaveProvider(WaveFormat waveFormat)
        {
            this.waveFormat = waveFormat;
        }

        /// <summary>
        /// Gets the WaveFormat
        /// </summary>
        public WaveFormat WaveFormat
        {
            get { return waveFormat; }
        }

        /// <summary>
        /// Switch input source to new provider
        /// </summary>
        public bool SwitchWaveProvider(IWaveProvider newProvider)
        {
            if ((newProvider != null) &&
                !this.waveFormat.Equals(newProvider.WaveFormat))
                return false;

            lock (lockObj)
            {
                srcProvider = newProvider;
            }
            return true;
        }

        /// <summary>
        /// Reads from source WaveProvider
        /// </summary>
        public int Read(byte[] buffer, int offset, int count) 
        {
            int readCount = 0;
            lock (lockObj)
            {
                if (srcProvider != null)
                {
                    readCount = srcProvider.Read(buffer, offset, count);
                }
            }

            if (readCount < count)
            {
                int strt = offset + readCount;
                int end = offset + count;
                for (int i = strt; i < end; i++)
                    buffer[i] = 0;
            }

            return count;
        }
    }
}
Coordinator
Feb 5, 2013 at 11:16 PM
One thing to try is making sure you don't Dispose WaveOutEvent until after the PlaybackStopped event has been fired. Otherwise the background thread could be making calls into the driver at the same time as it is being closed.
Feb 6, 2013 at 5:35 AM
Yes, that would certainly spoil your day.
I ran into a couple of more issues: media not playing after a few Play/Stop cycles, garbled output sometimes. The core issue seems to be that we don't wait for play thread to exit at Stop. That results in multiple play threads at times if you do Play/Start very fast. And also the issue that you mentioned. I fixed it by a ManualResetEvent which tracks if play thread is off or not. Below is the waveOutEvent changes I ended up with. It also includes setting callbackEvent when creating a new play thread. This fixed no media problem:
private ManualResetEvent playThreadOff; // <----- declare this class var

this.playThreadOff = new ManualResetEvent(true); // <------ init in contructor

public void Play()
        {
            if (playbackState == PlaybackState.Stopped)
            {
                callbackEvent.Set();      // <---- Kick thread
                playThreadOff.WaitOne(); // <---------wait for previous thread, if any to end
                playThreadOff.Reset(); // <-------- Play thread is now on
                playbackState = PlaybackState.Playing;
                callBackEvent.Set(); // <------- set again if it was reset by any previous thread
                ThreadPool.QueueUserWorkItem((state) => PlaybackThread(), null);
            }
            else if (playbackState == PlaybackState.Paused)
            {
                Resume();
                callbackEvent.Set(); // give the thread a kick
            }
        }

private void PlaybackThread()
        {
            Exception exception = null;
            try
            {
                DoPlayback();
            }
            catch (Exception e)
            {
                exception = e;
            }
            finally
            {
                playbackState = PlaybackState.Stopped;
                playThreadOff.Set(); <----------- Thread going off
                // we're exiting our background thread
                RaisePlaybackStoppedEvent(exception);
            }
        }

public void Stop()
        {
            if (playbackState != PlaybackState.Stopped)
            {
                // in the call to waveOutReset with function callbacks
                // some drivers will block here until OnDone is called
                // for every buffer
                playbackState = PlaybackState.Stopped; // set this here to avoid a problem with some drivers whereby 
                MmResult result;
                lock (waveOutLock)
                {
                    result = WaveInterop.waveOutReset(hWaveOut);
                }
                if (result != MmResult.NoError)
                {
                    throw new MmException(result, "waveOutReset");
                }
                callbackEvent.Set(); // give the thread a kick, make sure we exit
                playThreadOff.WaitOne(); // <---------------------wait for play thread to exit
            }
        }
Feb 6, 2013 at 6:57 AM
Edited Feb 17, 2013 at 8:44 AM
markheath wrote:
access violation relates to memory corruption. It could be something strange with the way you do threading, or a bug somewhere in NAudio (are you using the latest version?), or even a problem with your soundcard drivers. Tracking them down is hard. I usually try to create the simplest program possible that exhibits the problem.
Thanks sir,

Yes i am using latest NAudio.
i'll create simplest program to play audio file and i'll update you if i'll get same exception..