protected virtual void ConfigureDirectSound(IBassStreamComponent previous) { if (this.Behaviour.Output.EnforceRate) { if (!BassDirectSoundDevice.Info.SupportedRates.Contains(this.Rate)) { var nearestRate = BassDirectSoundDevice.Info.GetNearestRate(this.Rate); Logger.Write(this, LogLevel.Warn, "Enforced rate {0} isn't supposed by the device, falling back to {1}.", this.Rate, nearestRate); this.Rate = nearestRate; } else { //Enfoced rate is supported by the device, nothing to do. } } else { if (!BassDirectSoundDevice.Info.SupportedRates.Contains(previous.Rate)) { var nearestRate = BassDirectSoundDevice.Info.GetNearestRate(previous.Rate); Logger.Write(this, LogLevel.Debug, "Stream rate {0} isn't supposed by the device, falling back to {1}.", this.Rate, nearestRate); this.Rate = nearestRate; } else { //Stream rate is supported by the device, nothing to do. this.Rate = previous.Rate; } } }
protected virtual bool ConfigureASIO_PCM(IBassStreamComponent previous) { Logger.Write(this, LogLevel.Debug, "Configuring PCM."); BassAsioUtils.OK(BassAsio.SetDSD(false)); if (!this.CheckFormat(this.Rate, this.Channels)) { Logger.Write(this, LogLevel.Warn, "PCM format {0}:{1} is unsupported.", this.Rate, this.Channels); return(false); } else { BassAsio.Rate = this.Rate; } var format = default(AsioSampleFormat); if (previous.Flags.HasFlag(BassFlags.Float)) { format = AsioSampleFormat.Float; } else { format = AsioSampleFormat.Bit16; } Logger.Write(this, LogLevel.Debug, "PCM: Rate = {0}, Format = {1}", BassAsio.Rate, Enum.GetName(typeof(AsioSampleFormat), format)); BassAsioUtils.OK(BassAsio.ChannelSetRate(false, BassAsioDevice.PRIMARY_CHANNEL, previous.Rate)); BassAsioUtils.OK(BassAsio.ChannelSetFormat(false, BassAsioDevice.PRIMARY_CHANNEL, format)); return(true); }
public override void Connect(IBassStreamComponent previous) { Logger.Write(this, LogLevel.Debug, "Creating BASS PARAMETRIC EQUALIZER stream with rate {0} => {1} and {2} channels.", previous.Rate, this.Rate, this.Channels); this.ChannelHandle = previous.ChannelHandle; this.Start(); this.Configure(); }
public override void Connect(IBassStreamComponent previous) { if (previous.Channels > BassAsioDevice.Info.Outputs) { //TODO: We should down mix. Logger.Write(this, LogLevel.Error, "Cannot play stream with more channels than device outputs."); throw new NotImplementedException(string.Format("The stream contains {0} channels which is greater than {1} output channels provided by the device.", previous.Channels, BassAsioDevice.Info.Outputs)); } if (!this.CheckFormat(this.Rate, previous.Channels)) { Logger.Write(this, LogLevel.Error, "Cannot play stream with unsupported rate."); throw new NotImplementedException(string.Format("The stream has a rate of {0} which is not supported by the device.", this.Rate)); } var exception = default(Exception); for (var a = 1; a <= CONNECT_ATTEMPTS; a++) { Logger.Write(this, LogLevel.Debug, "Configuring ASIO, attempt: {0}", a); try { if (BassAsioUtils.OK(this.ConfigureASIO(previous))) { var success = default(bool); if (previous.Flags.HasFlag(BassFlags.DSDRaw) || BassUtils.GetChannelDsdRaw(previous.ChannelHandle)) { success = BassAsioUtils.OK(this.ConfigureASIO_DSD(previous)); } else { success = BassAsioUtils.OK(this.ConfigureASIO_PCM(previous)); } if (success) { Logger.Write(this, LogLevel.Debug, "Configured ASIO."); return; } } } catch (Exception e) { exception = e; Logger.Write(this, LogLevel.Warn, "Failed to configure ASIO: {0}", e.Message); if (BassAsioDevice.IsInitialized) { Logger.Write(this, LogLevel.Warn, "Re-initializing ASIO, have you just switched from DSD to PCM?"); BassAsioDevice.Free(); BassAsioDevice.Init(); } } Thread.Sleep(CONNECT_ATTEMPT_INTERVAL); } if (exception != null) { throw exception; } throw new NotImplementedException(); }
public override void Connect(IBassStreamComponent previous) { this.Rate = previous.Rate; this.Channels = previous.Channels; this.ChannelHandle = previous.ChannelHandle; if (this.IsActive) { this.Update(); } }
public override void Connect(IBassStreamComponent previous) { //BassUtils.OK(BassGapless.SetConfig(BassGaplessAttriubute.KeepAlive, true)); Logger.Write(this, LogLevel.Debug, "Creating BASS CROSSFADE stream with rate {0} and {1} channels.", this.Rate, this.Channels); this.ChannelHandle = BassCrossfade.StreamCreate(this.Rate, this.Channels, this.Flags); if (this.ChannelHandle == 0) { BassUtils.Throw(); } }
public override void Connect(IBassStreamComponent previous) { Logger.Write(this, LogLevel.Debug, "Creating BASS SOX stream with rate {0} => {1} and {2} channels.", previous.Rate, this.Rate, this.Channels); this.InputRate = previous.Rate; this.ChannelHandle = BassSox.StreamCreate(this.Rate, this.Flags, previous.ChannelHandle); if (this.ChannelHandle == 0) { BassUtils.Throw(); } this.Configure(); }
public override void Connect(IBassStreamComponent previous) { Logger.Write(this, LogLevel.Debug, "Creating BASS MIX stream with rate {0} and {1} channels.", this.Rate, this.Channels); this.ChannelHandle = BassMix.CreateMixerStream(this.Rate, this.Channels, this.Flags); if (this.ChannelHandle == 0) { BassUtils.Throw(); } Logger.Write(this, LogLevel.Debug, "Adding stream to the mixer: {0}", previous.ChannelHandle); BassUtils.OK(BassMix.MixerAddChannel(this.ChannelHandle, previous.ChannelHandle, BassFlags.Default | BassFlags.MixerBuffer)); this.MixerChannelHandles.Add(previous.ChannelHandle); }
protected virtual bool ConfigureASIO_DSD(IBassStreamComponent previous) { try { Logger.Write(this, LogLevel.Debug, "Configuring DSD RAW."); try { BassAsioUtils.OK(BassAsio.SetDSD(true)); } catch { //If we get here some drivers (at least Creative) will crash when BassAsio.Start is called. //I can't find a way to prevent it but it seems to be related to the allocated buffer size //not being what the driver *thinks* it is and over-flowing. // //It should be unlikely in real life as the device would have to report capability of some //very high PCM frequencies. Logger.Write(this, LogLevel.Error, "Failed to enable DSD RAW on the device. Creative ASIO driver becomes unstable and usually crashes soon..."); return(false); } if (!this.CheckFormat(this.Rate, previous.Channels)) { Logger.Write(this, LogLevel.Warn, "DSD format {0}:{1} is unsupported.", previous.Rate, previous.Channels); return(false); } else { BassAsio.Rate = this.Rate; } //It looks like BASS DSD always outputs 8 bit/MSB data so we don't need to determine the format. //var format = default(AsioSampleFormat); //switch (this.Depth) //{ // case BassAttribute.DSDFormat_LSB: // format = AsioSampleFormat.DSD_LSB; // break; // case BassAttribute.DSDFormat_None: // case BassAttribute.DSDFormat_MSB: // format = AsioSampleFormat.DSD_MSB; // break; // default: // throw new NotImplementedException(); //} Logger.Write(this, LogLevel.Debug, "DSD: Rate = {0}, Format = {1}", BassAsio.Rate, Enum.GetName(typeof(AsioSampleFormat), AsioSampleFormat.DSD_MSB)); BassAsioUtils.OK(BassAsio.ChannelSetFormat(false, BassAsioDevice.PRIMARY_CHANNEL, AsioSampleFormat.DSD_MSB)); return(true); } catch (Exception e) { Logger.Write(this, LogLevel.Warn, "Failed to configure DSD RAW: {0}", e.Message); return(false); } }
protected virtual void ConfigureWASAPI(IBassStreamComponent previous) { BassWasapiDevice.Init(this.Rate, this.Channels); if (this.Rate != BassWasapiDevice.Info.Rate) { Logger.Write(this, LogLevel.Warn, "Failed to set the requested rate {0}, falling back to device default {1}.", this.Rate, BassWasapiDevice.Info.Rate); this.Rate = BassWasapiDevice.Info.Rate; } if (this.Channels != BassWasapiDevice.Info.Outputs) { Logger.Write(this, LogLevel.Warn, "Failed to set the requested channel count {0}, falling back to device default {1}.", this.Channels, BassWasapiDevice.Info.Outputs); this.Channels = BassWasapiDevice.Info.Outputs; } }
public override void Connect(IBassStreamComponent previous) { this.Rate = previous.Rate; this.Channels = previous.Channels; this.ChannelHandle = BassFx.TempoCreate(previous.ChannelHandle, previous.Flags); if (this.ChannelHandle == 0) { BassUtils.Throw(); } if (this.IsActive) { this.Update(); } }
protected virtual void ConfigureASIO(IBassStreamComponent previous) { if (previous.Flags.HasFlag(BassFlags.DSDRaw)) { this.Rate = previous.Rate; this.Flags |= BassFlags.DSDRaw; } else { if (this.Behaviour.Output.EnforceRate) { if (!BassAsioDevice.Info.SupportedRates.Contains(this.Rate)) { var nearestRate = BassAsioDevice.Info.GetNearestRate(this.Rate); Logger.Write(this, LogLevel.Warn, "Enforced rate {0} isn't supposed by the device, falling back to {1}.", this.Rate, nearestRate); this.Rate = nearestRate; } else { //Enfoced rate is supported by the device, nothing to do. } } else { if (!BassAsioDevice.Info.SupportedRates.Contains(previous.Rate)) { var nearestRate = BassAsioDevice.Info.GetNearestRate(previous.Rate); Logger.Write(this, LogLevel.Debug, "Stream rate {0} isn't supposed by the device, falling back to {1}.", this.Rate, nearestRate); this.Rate = nearestRate; } else { //Stream rate is supported by the device, nothing to do. this.Rate = previous.Rate; } } } BassAsioDevice.Init( this.Behaviour.AsioDevice, this.Rate, this.Channels, this.Flags ); }
protected virtual void ConfigureWASAPI(IBassStreamComponent previous) { if (this.Behaviour.Output.EnforceRate) { if (!BassWasapiDevice.Info.SupportedRates.Contains(this.Rate)) { var nearestRate = BassWasapiDevice.Info.GetNearestRate(this.Rate); Logger.Write(this, LogLevel.Warn, "Enforced rate {0} isn't supposed by the device, falling back to {1}.", this.Rate, nearestRate); this.Rate = nearestRate; } else { //Enfoced rate is supported by the device, nothing to do. } } else { if (!BassWasapiDevice.Info.SupportedRates.Contains(previous.Rate)) { var nearestRate = BassWasapiDevice.Info.GetNearestRate(previous.Rate); Logger.Write(this, LogLevel.Debug, "Stream rate {0} isn't supposed by the device, falling back to {1}.", this.Rate, nearestRate); this.Rate = nearestRate; } else { //Stream rate is supported by the device, nothing to do. this.Rate = previous.Rate; } } BassWasapiDevice.Init( this.Behaviour.WasapiDevice, this.Behaviour.Exclusive, this.Behaviour.AutoFormat, this.Behaviour.BufferLength, this.Behaviour.DoubleBuffer, this.Behaviour.EventDriven, this.Behaviour.Async, this.Behaviour.Dither, this.Behaviour.Raw, this.Rate, this.Channels ); }
protected virtual bool ConfigureASIO(IBassStreamComponent previous) { Logger.Write(this, LogLevel.Debug, "Configuring ASIO."); BassAsioUtils.OK(BassAsioHandler.StreamSet(previous.ChannelHandle)); BassAsioUtils.OK(BassAsioHandler.ChannelEnable(false, BassAsioDevice.PRIMARY_CHANNEL)); if (previous.Channels == 1) { Logger.Write(this, LogLevel.Debug, "Mirroring channel: {0} => {1}", BassAsioDevice.PRIMARY_CHANNEL, BassAsioDevice.SECONDARY_CHANNEL); BassAsioUtils.OK(BassAsio.ChannelEnableMirror(BassAsioDevice.SECONDARY_CHANNEL, false, BassAsioDevice.PRIMARY_CHANNEL)); } else { for (var channel = 1; channel < previous.Channels; channel++) { Logger.Write(this, LogLevel.Debug, "Joining channel: {0} => {1}", channel, BassAsioDevice.PRIMARY_CHANNEL); BassAsioUtils.OK(BassAsio.ChannelJoin(false, channel, BassAsioDevice.PRIMARY_CHANNEL)); } } return(true); }
protected virtual bool ShouldCreateMixer(IBassStreamComponent previous) { if (previous.Flags.HasFlag(BassFlags.DSDRaw)) { //Can't create mixer for DSD. return(false); } if (this.Behaviour.Mixer) { //Mixer is forced on, probably so visualizations work. return(true); } else if (previous.Rate != this.Rate || previous.Channels != this.Channels) { //Stream rate or channel count differs from device. return(true); } //Looks like no mixer is required. return(false); }
public override void Connect(IBassStreamComponent previous) { this.InputRate = previous.Rate; if (this.Behaviour.Output.EnforceRate) { //Rate is enforced. this.Rate = this.Behaviour.Output.Rate; } else { //We already established that the output does not support the stream rate so use the closest one. this.Rate = this.Query.GetNearestRate(previous.Rate); } Logger.Write(this, LogLevel.Debug, "Creating BASS SOX stream with rate {0} => {1} and {2} channels.", previous.Rate, this.Rate, this.Channels); this.ChannelHandle = BassSox.StreamCreate(this.Rate, this.Flags, previous.ChannelHandle); if (this.ChannelHandle == 0) { BassUtils.Throw(); } this.Configure(); }
public override void Connect(IBassStreamComponent previous) { this.ConfigureWASAPI(previous); if (this.ShouldCreateMixer(previous)) { Logger.Write(this, LogLevel.Debug, "Creating BASS MIX stream with rate {0} and {1} channels.", this.Rate, this.Channels); this.ChannelHandle = BassMix.CreateMixerStream(this.Rate, this.Channels, this.Flags); if (this.ChannelHandle == 0) { BassUtils.Throw(); } Logger.Write(this, LogLevel.Debug, "Adding stream to the mixer: {0}", previous.ChannelHandle); BassUtils.OK(BassMix.MixerAddChannel(this.ChannelHandle, previous.ChannelHandle, BassFlags.Default | BassFlags.MixerBuffer)); BassUtils.OK(BassWasapiHandler.StreamSet(this.ChannelHandle)); this.MixerChannelHandles.Add(previous.ChannelHandle); } else { Logger.Write(this, LogLevel.Debug, "The stream properties match the device, playing directly."); BassUtils.OK(BassWasapiHandler.StreamSet(previous.ChannelHandle)); } }
public override void Connect(IBassStreamComponent previous) { this.Rate = previous.Rate; this.Channels = previous.Channels; this.ChannelHandle = previous.ChannelHandle; }
public abstract void Connect(IBassStreamComponent previous);