naudio / NAudio

Audio and MIDI library for .NET
MIT License
5.37k stars 1.09k forks source link

NAudio.MmException: NoDriver calling waveOutSetVolume #1112

Closed SMSapereAude closed 4 months ago

SMSapereAude commented 5 months ago

Hello,

I'm getting random exception, when I'm changing WaveOutEvent volume, during longer runs of my program (>24h). I'm using WaveOut as my output driver.

Environment, where this issue could be reproduced is Lenovo ThinkPad 10 (Type 20E3). Device paths for device outputs are: SWD\MMDEVAPI\{0.0.0.00000000}.{9065EB97-5291-4481-9DC0-C8CB3CC08DBD} (Intel SST Audio Device) SWD\MMDEVAPI\{0.0.0.00000000}.{2B7EF839-49FB-49E1-97CC-0CF0A6A6B26C} (ThinkPad TabletDock)

Issue context is, that I'm trying to do volume fade-in:

if (breakPlayTime <= 30)
{
    player.Volume = (float) breakPlayTime / 30f; // exception originates from this line - basically I'd like to do fade-in using this line
}
else
{
    player.Volume = 1;
}

Here's exception stack trace:

NAudio.MmException: NoDriver calling waveOutSetVolume
   w NAudio.Wave.WaveOutUtils.SetWaveOutVolume(Single value, IntPtr hWaveOut, Object lockObject)
   w RTOR.RtorBreakPlayer.Start() w S:\rtor-tablet-client\RtorBreakPlayer.cs:wiersz 118
   w System.Threading.ThreadHelper.ThreadStart_Context(Object state)
   w System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
   w System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
   w System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
   w System.Threading.ThreadHelper.ThreadStart()

Let me know if you need additional context related to app logic, and/or additional code snippets. Thanks!

Sebastian

SMSapereAude commented 4 months ago

Closing issue, as workaround specific to target environment was found. Code change in NAudio wouldn't do much

jooapa commented 3 months ago

whats the workaround, what did you do, I pretty much have this same problem. Unhandled exception. NAudio.MmException: NoDriver calling waveOutRestart at NAudio.Wave.WaveOutEvent.Resume()

SMSapereAude commented 3 months ago

Hi @jooapa,

mine workaround was basically forcing in particular audio device:

for (int n = -1; n < WaveOut.DeviceCount; n++)
{
    var caps = WaveOut.GetCapabilities(n);
    Console.WriteLine($"{n}: {caps.ProductName}"); // in my app, I was checking if I had device called "Intel SST Audio Device"
}

Since we're working with tablet devices, when we were performing WinMM calls during putting tablet to the docking station, it was switching to "ThinkPad TabletDock". This has caused loss of MM handle to original device - hence the source of NoDevice error. This can't be fixed on NAudio level, as it forwards calls to WinMM native API.

During creation of WaveOutEvent, we've requested the device based on the check above:

WaveOutEvent player = new WaveOutEvent { 
    DeviceNumber = ??? // you take the matching device number from "for" loop above
};

Mine use case is little bit different though (as you try to resume playback, we tried to set the playback volume to mimic fade-in/fade-out). We've opened pull request with carry-over from our NAudio patch aiding implementation of proper logic after fade-in/fade-out completion - https://github.com/naudio/NAudio/pull/1136

I hope that this could help. Don't hesitate to contact me if you need help!

jooapa commented 3 months ago

Thanks man, bro is a legend 🙏