Created
September 22, 2025 17:45
-
-
Save polson/f73a1110315ad849e07049facc2b28fc to your computer and use it in GitHub Desktop.
ManagedBass WASAPI input device monitoring example
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using ManagedBass; | |
using ManagedBass.Fx; | |
using ManagedBass.Mix; | |
using ManagedBass.Wasapi; | |
class Program | |
{ | |
private static int pushHandle = 0; | |
private static int mixer = 0; | |
private static int reverbHandle = 0; | |
private const int FREQUENCY = 48000; | |
private static readonly ReverbParameters REVERB_PARAMETERS = new() | |
{ | |
fDryMix = 0.7f, | |
fWetMix = 0.4f, | |
fRoomSize = 0.5f, | |
fDamp = 0.6f | |
}; | |
static void Main(string[] args) | |
{ | |
try | |
{ | |
if (!Bass.Init(Bass.NoSoundDevice, FREQUENCY, DeviceInitFlags.Default)) | |
{ | |
Console.WriteLine($"Failed to initialize BASS: {Bass.LastError}"); | |
return; | |
} | |
var outputDeviceIndex = InitializeOutput(); | |
var inputDeviceIndex = InitializeInput(); | |
pushHandle = Bass.CreateStream( | |
FREQUENCY, | |
1, | |
BassFlags.Float | BassFlags.Decode, | |
StreamProcedureType.Push | |
); | |
mixer = BassMix.CreateMixerStream( | |
FREQUENCY, | |
2, | |
BassFlags.Float | BassFlags.Decode | |
); | |
BassMix.MixerAddChannel(mixer, pushHandle, BassFlags.MixerChanMatrix); | |
float[,] matrix = new float[2, 1] { { 1.0f }, { 1.0f } }; | |
BassMix.ChannelSetMatrix(pushHandle, matrix); | |
Console.WriteLine(BassFx.Version); | |
reverbHandle = Bass.ChannelSetFX(mixer, EffectType.Freeverb, 1); | |
if (reverbHandle == 0) | |
{ | |
Console.WriteLine($"Failed to add reverb effect: {Bass.LastError}"); | |
} | |
else | |
{ | |
if (!Bass.FXSetParameters(reverbHandle, REVERB_PARAMETERS)) | |
{ | |
Console.WriteLine($"Failed to set reverb parameters: {Bass.LastError}"); | |
} | |
else | |
{ | |
Console.WriteLine("Reverb effect added successfully!"); | |
Console.WriteLine($" Dry Mix: {REVERB_PARAMETERS.fDryMix:F1}"); | |
Console.WriteLine($" Wet Mix: {REVERB_PARAMETERS.fWetMix:F1}"); | |
Console.WriteLine($" Room Size: {REVERB_PARAMETERS.fRoomSize:F1}"); | |
Console.WriteLine($" Damping: {REVERB_PARAMETERS.fDamp:F1}"); | |
} | |
} | |
BassWasapi.CurrentDevice = inputDeviceIndex; | |
BassWasapi.Start(); | |
BassWasapi.CurrentDevice = outputDeviceIndex; | |
BassWasapi.Start(); | |
Console.WriteLine("\nVocal monitoring with medium reverb is now active!"); | |
Console.WriteLine("Press any key to exit..."); | |
Console.ReadKey(); | |
Console.WriteLine("\nStopping monitoring..."); | |
} | |
catch (Exception ex) | |
{ | |
Console.WriteLine($"Error: {ex.Message}"); | |
} | |
finally | |
{ | |
BassWasapi.Free(); | |
Bass.Free(); | |
} | |
} | |
static int DefaultInputProcedure(IntPtr buffer, int length, IntPtr user) | |
{ | |
return Math.Max(0, Bass.StreamPutData(pushHandle, buffer, length)); | |
} | |
static int DefaultOutputProcedure(IntPtr buffer, int length, IntPtr user) | |
{ | |
return Bass.ChannelGetData(mixer, buffer, length); | |
} | |
static int InitializeOutput() | |
{ | |
var deviceIndex = 0; | |
String name = "Unknown"; | |
for (int i = 0; i < BassWasapi.DeviceCount; i++) | |
{ | |
var info = BassWasapi.GetDeviceInfo(i); | |
if (!info.IsInput && info.IsDefault) | |
{ | |
name = info.Name; | |
deviceIndex = i; | |
break; | |
} | |
} | |
if (BassWasapi.Init(-1, FREQUENCY, 0, WasapiInitFlags.Exclusive | WasapiInitFlags.EventDriven | WasapiInitFlags.Raw, 0.00001f, 0, DefaultOutputProcedure, IntPtr.Zero)) | |
{ | |
var wasapiInfo = BassWasapi.Info; | |
Console.WriteLine("Initialized Output Device Format:"); | |
Console.WriteLine($" ID: {deviceIndex}"); | |
Console.WriteLine($" Name: {name}"); | |
Console.WriteLine($" Sample Rate: {wasapiInfo.Frequency}Hz"); | |
Console.WriteLine($" Channels: {wasapiInfo.Channels}"); | |
Console.WriteLine($" Format: {GetFormatName(wasapiInfo.Format)}"); | |
Console.WriteLine($" Buffer Length: {wasapiInfo.BufferLength}"); | |
} | |
else | |
{ | |
Console.WriteLine($"Failed to initialize WASAPI output device. Error: {Bass.LastError}"); | |
} | |
return deviceIndex; | |
} | |
static int InitializeInput() | |
{ | |
var deviceIndex = 0; | |
String name = "Unknown"; | |
for (int i = 0; i < BassWasapi.DeviceCount; i++) | |
{ | |
var info = BassWasapi.GetDeviceInfo(i); | |
if (info.IsInput && info.IsDefault) | |
{ | |
name = info.Name; | |
deviceIndex = i; | |
break; | |
} | |
} | |
if (BassWasapi.Init(-2, FREQUENCY, 0, WasapiInitFlags.Exclusive | WasapiInitFlags.EventDriven | WasapiInitFlags.Raw, 0.00001f, 0, DefaultInputProcedure, IntPtr.Zero)) | |
{ | |
var wasapiInfo = BassWasapi.Info; | |
Console.WriteLine("Initialized Input Device Format:"); | |
Console.WriteLine($" ID: {deviceIndex}"); | |
Console.WriteLine($" Name: {name}"); | |
Console.WriteLine($" Sample Rate: {wasapiInfo.Frequency}Hz"); | |
Console.WriteLine($" Channels: {wasapiInfo.Channels}"); | |
Console.WriteLine($" Format: {GetFormatName(wasapiInfo.Format)}"); | |
Console.WriteLine($" Buffer Length: {wasapiInfo.BufferLength}"); | |
} | |
else | |
{ | |
Console.WriteLine($"Failed to initialize WASAPI input device. Error: {Bass.LastError}"); | |
} | |
return deviceIndex; | |
} | |
static string GetFormatName(WasapiFormat format) | |
{ | |
return format switch | |
{ | |
WasapiFormat.Float => "32-bit Float", | |
WasapiFormat.Bit8 => "8-bit PCM", | |
WasapiFormat.Bit16 => "16-bit PCM", | |
WasapiFormat.Bit24 => "24-bit PCM", | |
WasapiFormat.Bit32 => "32-bit PCM", | |
WasapiFormat.Unknown => "Unknown", | |
_ => format.ToString() | |
}; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment