mobiletechtracker / NetCoreAudio

Allows playback of audio files on .NET Core with minimal dependencies
MIT License
124 stars 20 forks source link

Feature request: Volume control #4

Closed MortenChristiansen closed 2 years ago

MortenChristiansen commented 5 years ago

It would be great if the player had a way to set the volume. This would also allow users of the library to build things like fade-in and fade-out or crossfade between different tracks.

I would have made a PR if I could test for linux and mac, but I did throw something together that works on windows:

[DllImport("winmm.dll")]
private static extern int waveOutSetVolume(IntPtr hwo, uint dwVolume);
[DllImport("winmm.dll")]
private static extern int waveOutGetVolume(IntPtr hwo, out uint dwVolume);

public int GetVolume()
{
    var result = waveOutGetVolume(IntPtr.Zero, out var v);
    if (result != 0)
        throw new Exception($"Error executing command 'waveOutGetVolume'. Error code: {result}.");

    var volume = Math.Min(100, v * 100 / ushort.MaxValue);
    return (int)volume;
}

public void SetVolume(int volume)
{
    var v = (uint)(ushort.MaxValue * Math.Max(0, Math.Min(100, volume)) / 100.0);

    var result = waveOutSetVolume(IntPtr.Zero, v);
    if (result != 0)
        throw new Exception($"Error executing command 'waveOutSetVolume'. Error code: {result}.");
}

It always takes the first audio device (IntPtr hwo) - I don't know if this is always correct and it would probably not scale to playing multiple sounds simultaneously but it worked for me. Another thing to note is that if you get the volume without ever having set it, then it will return uint.MaxValue (or something close to it), but my code just converts it to max volume which I think is correct.