filoe / cscore

An advanced audio library, written in C#. Provides tons of features. From playing/recording audio to decoding/encoding audio streams/files to processing audio data in realtime (e.g. applying custom effects during playback, create visualizations,...). The possibilities are nearly unlimited.
Other
2.15k stars 451 forks source link

WaveIn and WaveInBuffer Finalization Methods Throwing MMException #393

Open jbarber3388 opened 4 years ago

jbarber3388 commented 4 years ago

I am trying to use this library to constantly record the currect audio and adjust the output audio based on the input volume level. While using this library on a Windows 10 machine, I found that sometimes the WaveIn object will unexpected call the Stopped event call back with an error condition. Below is the stack trace along with the Exceptions information:

Received MM Exception from recording stopped event call back Function:waveInUnprepareHeader; Result:StillPlaying; Exception:CSCore.MmException: Exception of type 'CSCore.MmException' was thrown. at CSCore.MmException.Try(MmResult result, String function) at CSCore.SoundIn.WaveInBuffer.AddBufferToQueue() at CSCore.SoundIn.WaveIn.FireUpBuffer(WaveInBuffer buffer)

After this occurs, the object will also throw the same exception when I try to dispose of it. Below is s an example of this:

Received MM Exception while disposing AGC meter. Function:waveInUnprepareHeader; Result:StillPlaying; Exception:CSCore.MmException: Exception of type 'CSCore.MmException' was thrown. at CSCore.MmException.Try(MmResult result, String function) at CSCore.SoundIn.WaveInBuffer.Dispose(Boolean disposing) at CSCore.SoundIn.WaveInBuffer.Dispose() at CSCore.SoundIn.WaveIn.DisposeBuffers() at CSCore.SoundIn.WaveIn.CleanupResources() at CSCore.SoundIn.WaveIn.Dispose(Boolean disposing) at CSCore.SoundIn.WaveIn.Dispose()

This is generally OK. Technically this would cause a small memory leak since I need to create a new object to start recording again but that is not a huge deal. What is a big deal, is that the Garbage Collector will still try to Finalize the WaveIn and WaveInBuffer objects. The finalization of these objects causes the same MMException to be thrown causing my entire application to crash. Below are the .Net Runtime logs form Windows Event Viewer.

GC Crashing on WaveIn Finalization Application: myApp.exe Framework Version: v4.0.30319 Description: The process was terminated due to an unhandled exception. Exception Info: CSCore.MmException at CSCore.MmException.Try(CSCore.MmResult, System.String) at CSCore.SoundIn.WaveInBuffer.Dispose(Boolean) at CSCore.SoundIn.WaveInBuffer.Dispose() at CSCore.SoundIn.WaveIn.DisposeBuffers() at CSCore.SoundIn.WaveIn.CleanupResources() at CSCore.SoundIn.WaveIn.Dispose(Boolean) at CSCore.SoundIn.WaveIn.Finalize()

GC Crashing on WaveInBufferFinalization Application: myApp.exe Framework Version: v4.0.30319 Description: The process was terminated due to an unhandled exception. Exception Info: CSCore.MmException at CSCore.MmException.Try(CSCore.MmResult, System.String) at CSCore.SoundIn.WaveInBuffer.Dispose(Boolean) at CSCore.SoundIn.WaveInBuffer.Finalize()

I was able to get around this a little bit by calling GC.SuppressFinalization on the WaveIn object. However, the library does not expose the WaveInBuffer to my application. So, that situation will still crash my application.

Is there any way I can prevent these MMExceptions from being thrown? Could we change the logic so that the MMExceptions are never thrown from the Finalization method? Obviously, with the understanding, there would be a memory leak..

filoe commented 4 years ago

See https://github.com/filoe/cscore/issues/395#issuecomment-560516752