/// <summary> /// Initializes a device for playback. /// </summary> /// <param name="device">Device to use for playback</param> /// <param name="frequency">Mixer sample rate/frequency</param> private void InitializeDevice(Device device, int frequency) { // Set properties this.device = device; // Check driver type if (device.DriverType == DriverType.DirectSound) { // Initialize sound system Base.Init(device.Id, frequency, BASSInit.BASS_DEVICE_DEFAULT); } #if !IOS && !ANDROID else if (device.DriverType == DriverType.ASIO) { // Initialize sound system BaseASIO.Init(device.Id, frequency, BASSInit.BASS_DEVICE_DEFAULT, BASSASIOInit.BASS_ASIO_THREAD); } else if (device.DriverType == DriverType.WASAPI) { // Create callback wasapiProc = new WASAPIPROC(WASAPICallback); // Initialize sound system BaseWASAPI.Init(device.Id, frequency, 2, BASSInit.BASS_DEVICE_DEFAULT, BASSWASAPIInit.BASS_WASAPI_SHARED, 0, 0, wasapiProc); } #endif }
/// <summary> /// Detects the standard/DirectSound output devices present in the system. /// </summary> /// <returns>List of standard/DirectSound output devices</returns> public static IEnumerable<Device> DetectOutputDevices() { var devices = new List<Device>(); var devicesDirectSound = Bass.BASS_GetDeviceInfos().ToList(); for(int a = 0; a < devicesDirectSound.Count; a++) { // Make sure the device is usable if (devicesDirectSound[a].IsEnabled) { Device device = new Device(); device.IsDefault = devicesDirectSound[a].IsDefault; device.Id = a; device.DriverType = DriverType.DirectSound; device.Name = devicesDirectSound[a].name; device.Driver = devicesDirectSound[a].driver; // If the driver name is No Sound, don't add it to the list of devices if (device.Name.ToUpper() != "NO SOUND") { devices.Add(device); } } } return devices; }
public AudioAppConfig() { // Set defaults AudioDevice = new Device(); SampleRate = 44100; Volume = 1; BufferSize = 1000; UpdatePeriod = 100; }
/// <summary> /// Detects the ASIO output devices present in the system. /// </summary> /// <returns>List of ASIO output devices</returns> public static IEnumerable<Device> DetectASIOOutputDevices() { var devices = new List<Device>(); #if !IOS && !ANDROID var devicesASIO = BassAsio.BASS_ASIO_GetDeviceInfos().ToList(); for (int a = 0; a < devicesASIO.Count; a++) { Device device = new Device(); device.IsDefault = false; device.Id = a; device.DriverType = DriverType.ASIO; device.Name = devicesASIO[a].name; device.Driver = devicesASIO[a].driver; devices.Add(device); } #endif return devices; }
/// <summary> /// Frees the device currently used for playback. /// </summary> public void FreeDevice() { if (!_isDeviceInitialized) return; #if !IOS && !ANDROID // Check driver type if (_device.DriverType == DriverType.ASIO) { // Free ASIO device if (!BassAsio.BASS_ASIO_Free()) { // Get error BASSError error = Bass.BASS_ErrorGetCode(); throw new Exception("Error freeing ASIO device: " + error.ToString()); } } else if (_device.DriverType == DriverType.WASAPI) { // Free WASAPI device if (!BassWasapi.BASS_WASAPI_Free()) { // Get error BASSError error = Bass.BASS_ErrorGetCode(); throw new Exception("Error freeing WASAPI device: " + error.ToString()); } } #endif Base.Free(); _mixerChannel = null; _device = null; _isDeviceInitialized = false; }
/// <summary> /// Initializes a specific audio device for playback. /// </summary> /// <param name="device">Audio device</param> /// <param name="mixerSampleRate">Mixer sample rate (in Hz)</param> public void InitializeDevice(Device device, int mixerSampleRate) { _device = device; _mixerSampleRate = mixerSampleRate; Tracing.Log("Player -- Initializing device (SampleRate: " + mixerSampleRate.ToString() + " Hz, DriverType: " + device.DriverType.ToString() + ", Id: " + device.Id.ToString() + ", Name: " + device.Name + ", BufferSize: " + _bufferSize.ToString() + ", UpdatePeriod: " + _updatePeriod.ToString() + ")"); // Check driver type if (device.DriverType == DriverType.DirectSound) { // Initialize sound system Base.Init(device.Id, mixerSampleRate, BASSInit.BASS_DEVICE_DEFAULT | BASSInit.BASS_DEVICE_LATENCY); } #if !IOS && !ANDROID else if (device.DriverType == DriverType.ASIO) { // Initialize sound system BaseASIO.Init(device.Id, mixerSampleRate, BASSInit.BASS_DEVICE_DEFAULT, BASSASIOInit.BASS_ASIO_THREAD); } else if (device.DriverType == DriverType.WASAPI) { // Create callback wasapiProc = new WASAPIPROC(WASAPICallback); // Initialize sound system //Base.InitWASAPI(device.Id, mixerSampleRate, 2, BASSInit.BASS_DEVICE_DEFAULT, BASSWASAPIInit.BASS_WASAPI_SHARED, 10.0f, 0, wasapiProc); BaseWASAPI.Init(device.Id, mixerSampleRate, 2, BASSInit.BASS_DEVICE_DEFAULT, BASSWASAPIInit.BASS_WASAPI_SHARED, 0.5f, 0, wasapiProc); //Base.InitWASAPI(device.Id, mixerSampleRate, 2, BASSInit.BASS_DEVICE_DEFAULT, BASSWASAPIInit.BASS_WASAPI_EXCLUSIVE, 1, 0, wasapiProc); //BASS_WASAPI_INFO info = BassWasapi.BASS_WASAPI_GetInfo(); } #endif // Default BASS.NET configuration values for Windows *AND* Linux: // // BASS_CONFIG_BUFFER: 500 // BASS_CONFIG_UPDATEPERIOD: 100 // BASS_CONFIG_UPDATETHREADS: 1 if(OS.Type == OSType.Windows) { // Set configuration for buffer and update period // This only works for the default BASS output (http://www.un4seen.com/forum/?topic=13429.msg93740#msg93740) Base.SetConfig(BASSConfig.BASS_CONFIG_BUFFER, _bufferSize); Base.SetConfig(BASSConfig.BASS_CONFIG_UPDATEPERIOD, _updatePeriod); } else if (OS.Type == OSType.Linux) { // 10ms update period does not work under Linux. Major stuttering Base.SetConfig(BASSConfig.BASS_CONFIG_BUFFER, _bufferSize); Base.SetConfig(BASSConfig.BASS_CONFIG_UPDATEPERIOD, 100); #if ANDROID Base.SetConfig(BASSConfig.BASS_CONFIG_DEV_BUFFER, 500); // Default on Android: 30ms #endif } else if (OS.Type == OSType.MacOSX) { Base.SetConfig(BASSConfig.BASS_CONFIG_BUFFER, _bufferSize); Base.SetConfig(BASSConfig.BASS_CONFIG_UPDATEPERIOD, _updatePeriod); } _isDeviceInitialized = true; }
/// <summary> /// Initializes the player. /// </summary> /// <param name="device">Device output</param> /// <param name="mixerSampleRate">Mixer sample rate (default: 44100 Hz)</param> /// <param name="bufferSize">Buffer size (default: 500 ms)</param> /// <param name="updatePeriod">Update period (default: 10 ms)</param> /// <param name="initializeDevice">Indicates if the device should be initialized</param> private void Initialize(Device device, int mixerSampleRate, int bufferSize, int updatePeriod, bool initializeDevice) { OnPlaylistEnded += () => { }; Player.CurrentPlayer = this; _device = device; _mixerSampleRate = mixerSampleRate; _bufferSize = bufferSize; _updatePeriod = updatePeriod; //_decodingService = new DecodingService(100000, UseFloatingPoint); _playlist = new ShufflePlaylist(); _syncProcs = new List<PlayerSyncProc>(); #if !ANDROID _useFloatingPoint = true; #endif _timerPlayer = new System.Timers.Timer(); _timerPlayer.Elapsed += new System.Timers.ElapsedEventHandler(timerPlayer_Elapsed); _timerPlayer.Interval = 1000; _timerPlayer.Enabled = false; // Initialize BASS library by OS type if (OS.Type == OSType.Windows) { // Load decoding plugins //plugins = Base.LoadPluginDirectory(Path.GetDirectoryName((new Uri(Assembly.GetExecutingAssembly().CodeBase)).AbsolutePath)); Tracing.Log("Player init -- Loading plugins..."); //aacPluginHandle = Base.LoadPlugin("bass_aac.dll"); _apePluginHandle = Base.LoadPlugin("bass_ape.dll"); _flacPluginHandle = Base.LoadPlugin("bassflac.dll"); _mpcPluginHandle = Base.LoadPlugin("bass_mpc.dll"); //ofrPluginHandle = Base.LoadPlugin("bass_ofr.dll"); // Requires OptimFrog.DLL //ttaPluginHandle = Base.LoadPlugin("bass_tta.dll"); _wmaPluginHandle = Base.LoadPlugin("basswma.dll"); _wvPluginHandle = Base.LoadPlugin("basswv.dll"); int bassFxVersion = Base.GetFxPluginVersion(); int bassEncVersion = BaseEnc.GetVersion(); //Base.LoadFxPlugin(); } else // Linux or Mac OS X { // Load BASS library Tracing.Log("Player init -- Checking BASS library and plugin versions..."); int bassVersion = Base.GetBASSVersion(); int bassFxVersion = Base.GetFxPluginVersion(); int bassMixVersion = Base.GetMixPluginVersion(); int bassEncVersion = BaseEnc.GetVersion(); Tracing.Log("Player init -- BASS Version: " + bassVersion); Tracing.Log("Player init -- BASS FX Version: " + bassFxVersion); Tracing.Log("Player init -- BASS Mix Version: " + bassMixVersion); Tracing.Log("Player init -- BASS Enc Version: " + bassEncVersion); // Check OS type Console.WriteLine("Player init -- OS is " + OS.Type.ToString()); if (OS.Type == OSType.Linux) { string pluginPath = string.Empty; #if ANDROID pluginPath = PluginDirectoryPath; _aacPluginHandle = Base.LoadPlugin(Path.Combine(pluginPath, "libbass_aac.so")); _alacPluginHandle = Base.LoadPlugin(Path.Combine(pluginPath, "libbass_alac.so")); _apePluginHandle = Base.LoadPlugin(Path.Combine(pluginPath, "libbass_ape.so")); _mpcPluginHandle = Base.LoadPlugin(Path.Combine(pluginPath, "libbass_mpc.so")); _flacPluginHandle = Base.LoadPlugin(Path.Combine(pluginPath, "libbassflac.so")); _wvPluginHandle = Base.LoadPlugin(Path.Combine(pluginPath, "libbasswv.so")); #else // Find plugins either in current directory (i.e. development) or in a system directory (ex: /usr/lib/Sessions or /opt/lib/Sessions) string exePath = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location); // Check in the current directory first if(!File.Exists(exePath + "/libbassflac.so")) { // Check in /usr/lib/Sessions if(!File.Exists("/usr/lib/Sessions/libbassflac.so")) { // Check in /opt/lib/Sessions if(!File.Exists("/opt/lib/Sessions/libbassflac.so")) { // The plugins could not be found! throw new Exception("The BASS plugins could not be found either in the current directory, in /usr/lib/Sessions or in /opt/lib/Sessions!"); } else { pluginPath = "/opt/lib/Sessions"; } } else { pluginPath = "/usr/lib/Sessions"; } } else { pluginPath = exePath; } // Load decoding plugins _flacPluginHandle = Base.LoadPlugin(Path.Combine(pluginPath, "libbassflac.so")); _wvPluginHandle = Base.LoadPlugin(Path.Combine(pluginPath, "libbasswv.so")); _mpcPluginHandle = Base.LoadPlugin(Path.Combine(pluginPath, "libbass_mpc.so")); #endif } else if (OS.Type == OSType.MacOSX) { #if IOS // Load decoding plugins (http://www.un4seen.com/forum/?topic=13851.msg96559#msg96559) _flacPluginHandle = Base.LoadPlugin("BASSFLAC"); _wvPluginHandle = Base.LoadPlugin("BASSWV"); _apePluginHandle = Base.LoadPlugin("BASS_APE"); _mpcPluginHandle = Base.LoadPlugin("BASS_MPC"); int bassEncVersionOSX = BaseEnc.GetVersion(); Console.WriteLine("Player init -- Configuring IOSNOTIFY delegate..."); _iosNotifyProc = new IOSNOTIFYPROC(IOSNotifyProc); IntPtr ptr = Marshal.GetFunctionPointerForDelegate(_iosNotifyProc); Bass.BASS_SetConfigPtr((BASSConfig)46, ptr); //Bass.BASS_SetConfigPtr(BASSIOSConfig.BASS_CONFIG_IOS_NOTIFY, ptr); Console.WriteLine("Player init -- Configuring AirPlay and remote control..."); Bass.BASS_SetConfig(BASSConfig.BASS_CONFIG_IOS_MIXAUDIO, 0); // 0 = AirPlay #else // Try to get the plugins in the current path Console.WriteLine("Loading OS X plugins..."); string exePath = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location); string pluginPath = exePath.Replace("MonoBundle", "Resources"); // Check in the current directory first if(!File.Exists(pluginPath + "/libbassflac.dylib")) { // The plugins could not be found! throw new Exception("The BASS plugins could not be found in the current directory!"); } // Load decoding plugins _flacPluginHandle = Base.LoadPlugin(pluginPath + "/libbassflac.dylib"); _wvPluginHandle = Base.LoadPlugin(pluginPath + "/libbasswv.dylib"); _mpcPluginHandle = Base.LoadPlugin(pluginPath + "/libbass_mpc.dylib"); _apePluginHandle = Base.LoadPlugin(pluginPath + "/libbass_ape.dylib"); _ttaPluginHandle = Base.LoadPlugin(pluginPath + "/libbass_tta.dylib"); int bassEncVersion2 = BaseEnc.GetVersion(); //Console.WriteLine("OSX Bassenc.dylib version: {0}", bassEncVersion); #endif } } #if IOS _bpmProc = new BPMPROC(BPMDetectionProcIOS); //bpmBeatProc = new BPMBEATPROC(BPMDetectionBeatProcIOS); #else _bpmProc = new BPMPROC(BPMDetectionProc); //bpmBeatProc = new BPMBEATPROC(BPMDetectionBeatProc); #endif // Create default EQ Tracing.Log("Player init -- Creating default EQ preset..."); _currentEQPreset = new EQPreset(); if (initializeDevice) { Tracing.Log("Player init -- Initializing device..."); InitializeDevice(device, mixerSampleRate); } }
/// <summary> /// Constructor for the Player class which requires the mixer sample rate value to be passed /// in parameter. /// </summary> /// <param name="device">Device output</param> /// <param name="mixerSampleRate">Mixer sample rate (default: 44100 Hz)</param> /// <param name="bufferSize">Buffer size (default: 500 ms)</param> /// <param name="updatePeriod">Update period (default: 10 ms)</param> /// <param name="initializeDevice">Indicates if the device should be initialized</param> public Player(Device device, int mixerSampleRate, int bufferSize, int updatePeriod, bool initializeDevice) { Initialize(device, mixerSampleRate, bufferSize, updatePeriod, initializeDevice); }
/// <summary> /// Constructor for the TestDevice class which requires a Device class. /// </summary> /// <param name="device">Device to use for playback</param> /// <param name="frequency">Mixer sample rate/frequency</param> public TestDevice(Device device, int frequency) { // Initialize the audio device InitializeDevice(device, frequency); }
/// <summary> /// Detects the WASAPI output devices present in the system. For Windows only. /// </summary> /// <returns>List of WASAPI output devices</returns> public static IEnumerable<Device> DetectWASAPIOutputDevices() { var devices = new List<Device>(); #if !IOS && !ANDROID var devicesWASAPI = BassWasapi.BASS_WASAPI_GetDeviceInfos().ToList(); for (int a = 0; a < devicesWASAPI.Count; a++) { // Make sure the device is usable, and an output device if (devicesWASAPI[a].IsEnabled && !devicesWASAPI[a].IsInput) { Device device = new Device(); device.IsDefault = devicesWASAPI[a].IsDefault; device.Id = a; device.DriverType = DriverType.WASAPI; device.Name = devicesWASAPI[a].name; device.Driver = devicesWASAPI[a].id; devices.Add(device); } } #endif return devices; }
/// <summary> /// Returns the default WASAPI device. /// If no device was no found, the value is null. /// </summary> /// <returns>Default WASAPI device</returns> public static Device GetDefaultWASAPIOutputDevice() { // Detect WASAPI devices List<BASS_WASAPI_DEVICEINFO> devicesWASAPI = BassWasapi.BASS_WASAPI_GetDeviceInfos().ToList(); for (int a = 0; a < devicesWASAPI.Count; a++) { // Check if the device is the default one if (devicesWASAPI[a].IsEnabled && devicesWASAPI[a].IsDefault && !devicesWASAPI[a].IsInput) { // Create device and add to list Device device = new Device(); device.IsDefault = devicesWASAPI[a].IsDefault; device.Id = a; device.DriverType = DriverType.WASAPI; device.Name = devicesWASAPI[a].name; device.Driver = devicesWASAPI[a].id; return device; } } return null; }
/// <summary> /// Returns the default DirectSound device. /// If no device was no found, the value is null. /// </summary> /// <returns>Default DirectSound device</returns> public static Device GetDefaultDirectSoundOutputDevice() { // Detect DirectSound devices List<BASS_DEVICEINFO> devicesDirectSound = Bass.BASS_GetDeviceInfos().ToList(); for (int a = 0; a < devicesDirectSound.Count; a++) { // Check if the device is the default one if (devicesDirectSound[a].IsEnabled && devicesDirectSound[a].IsDefault) { // Create device and add to list Device device = new Device(); device.IsDefault = devicesDirectSound[a].IsDefault; device.Id = a; device.DriverType = DriverType.DirectSound; device.Name = devicesDirectSound[a].name; device.Driver = devicesDirectSound[a].driver; return device; } } return null; }
/// <summary> /// Find an output device by its driver type and its device name. /// This is useful to get the actual deviceId because it can change if the /// user plugs/unplugs a sound card. /// </summary> /// <param name="driverType">Driver type</param> /// <param name="deviceName">Device name</param> /// <returns>Device (null if none found)</returns> public static Device FindOutputDevice(DriverType driverType, string deviceName) { // Check driver type if (driverType == DriverType.DirectSound) { // Detect DirectSound devices List<BASS_DEVICEINFO> devicesDirectSound = Bass.BASS_GetDeviceInfos().ToList(); for (int a = 0; a < devicesDirectSound.Count; a++) { // Check if the driver name is the same, and make sure the device is also enabled (i.e. available) if (devicesDirectSound[a].name.ToUpper() == deviceName.ToUpper() && devicesDirectSound[a].IsEnabled) { // Create device and add to list Device device = new Device(); device.IsDefault = devicesDirectSound[a].IsDefault; device.Id = a; device.DriverType = DriverType.DirectSound; device.Name = devicesDirectSound[a].name; device.Driver = devicesDirectSound[a].driver; return device; } } } #if !IOS && !ANDROID else if (driverType == DriverType.ASIO) { // Detect ASIO devices List<BASS_ASIO_DEVICEINFO> devicesASIO = BassAsio.BASS_ASIO_GetDeviceInfos().ToList(); for (int a = 0; a < devicesASIO.Count; a++) { // Check if the driver name is the same if (devicesASIO[a].name.ToUpper() == deviceName.ToUpper()) { // Create device and add to list Device device = new Device(); device.IsDefault = false; device.Id = a; device.DriverType = DriverType.ASIO; device.Name = devicesASIO[a].name; device.Driver = devicesASIO[a].driver; return device; } } } else if (driverType == DriverType.WASAPI) { // Detect WASAPI devices List<BASS_WASAPI_DEVICEINFO> devicesWASAPI = BassWasapi.BASS_WASAPI_GetDeviceInfos().ToList(); for (int a = 0; a < devicesWASAPI.Count; a++) { // Check if the driver name is the same, that the device is an output device, and make sure that it is enabled if (devicesWASAPI[a].name.ToUpper() == deviceName.ToUpper() && devicesWASAPI[a].IsEnabled && !devicesWASAPI[a].IsInput) { // Create device and add to list Device device = new Device(); device.IsDefault = devicesWASAPI[a].IsDefault; device.Id = a; device.DriverType = DriverType.WASAPI; device.Name = devicesWASAPI[a].name; device.Driver = devicesWASAPI[a].id; return device; } } } #endif return null; }