public BassAsioStreamOutput(BassAsioStreamOutputBehaviour behaviour, BassOutputStream stream) : this() { this.Behaviour = behaviour; if (BassUtils.GetChannelDsdRaw(stream.ChannelHandle)) { this.Rate = BassUtils.GetChannelDsdRate(stream.ChannelHandle); this.Flags |= BassFlags.DSDRaw; } else { if (behaviour.Output.Rate == stream.Rate) { this.Rate = stream.Rate; } else if (!behaviour.Output.EnforceRate && BassAsioDevice.Info.SupportedRates.Contains(stream.Rate)) { this.Rate = stream.Rate; } else { Logger.Write(this, LogLevel.Debug, "The requested output rate is either enforced or the device does not support the stream's rate: {0} => {1}", stream.Rate, behaviour.Output.Rate); this.Rate = behaviour.Output.Rate; } if (behaviour.Output.Float) { this.Flags |= BassFlags.Float; } } this.Channels = stream.Channels; }
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(); }
protected virtual void OnCreatingPipeline(object sender, CreatingPipelineEventArgs e) { if (BassUtils.GetChannelDsdRaw(e.Stream.ChannelHandle)) { //Cannot apply effects to DSD. return; } var component = new BassReplayGainStreamComponent(this, e.Stream); component.InitializeComponent(this.Core); e.Components.Add(component); }
public BassResamplerStreamComponent(BassResamplerStreamComponentBehaviour behaviour, BassOutputStream stream) { if (BassUtils.GetChannelDsdRaw(stream.ChannelHandle)) { throw new InvalidOperationException("Cannot resample DSD streams."); } this.Behaviour = behaviour; this.Rate = behaviour.Output.Rate; this.Channels = stream.Channels; this.Flags = BassFlags.Decode; if (this.Behaviour.Output.Float) { this.Flags |= BassFlags.Float; } }
protected virtual void OnCreatingPipeline(object sender, CreatingPipelineEventArgs e) { if (!this.Enabled) { return; } if (BassUtils.GetChannelDsdRaw(e.Stream.ChannelHandle)) { return; } var component = new BassParametricEqualizerStreamComponent(this, e.Stream); component.InitializeComponent(this.Core); e.Components.Add(component); }
public BassParametricEqualizerStreamComponent(BassParametricEqualizerStreamComponentBehaviour behaviour, BassOutputStream stream) { if (BassUtils.GetChannelDsdRaw(stream.ChannelHandle)) { throw new InvalidOperationException("Cannot apply effects to DSD streams."); } this.Behaviour = behaviour; this.Rate = behaviour.Output.Rate; this.Channels = stream.Channels; this.Flags = BassFlags.Decode; if (this.Behaviour.Output.Float) { this.Flags |= BassFlags.Float; } this.Attach(); }
public override bool CheckFormat(BassOutputStream stream) { var rate = default(int); var channels = default(int); if (BassUtils.GetChannelDsdRaw(stream.ChannelHandle)) { rate = BassUtils.GetChannelDsdRate(stream.ChannelHandle); channels = BassUtils.GetChannelCount(stream.ChannelHandle); } else { rate = BassUtils.GetChannelPcmRate(stream.ChannelHandle); channels = BassUtils.GetChannelCount(stream.ChannelHandle); } return(this.Rate == rate && this.Channels == channels); }
public BassCrossfadeStreamInput(BassCrossfadeStreamInputBehaviour behaviour, BassOutputStream stream) { this.Behaviour = behaviour; this.Channels = stream.Channels; this.Flags = BassFlags.Decode; if (BassUtils.GetChannelDsdRaw(stream.ChannelHandle)) { throw new InvalidOperationException("Cannot apply effects to DSD streams."); } else { this.Rate = stream.Rate; if (behaviour.Output.Float) { this.Flags |= BassFlags.Float; } } }
protected virtual void Add(BassOutputStream stream) { if (!FileSystemHelper.IsLocalPath(stream.FileName)) { return; } if (BassUtils.GetChannelDsdRaw(stream.ChannelHandle)) { return; } var gain = default(float); var peak = default(float); var mode = default(ReplayGainMode); if (!this.TryGetReplayGain(stream, out gain, out mode)) { if (this.OnDemand) { //TODO: Bad .Result using (var duplicated = this.Output.Duplicate(stream).Result as BassOutputStream) { if (duplicated == null) { Logger.Write(this, LogLevel.Warn, "Failed to duplicate stream for file \"{0}\", cannot calculate.", stream.FileName); return; } if (!this.TryCalculateReplayGain(duplicated, out gain, out peak, out mode)) { return; } } this.Dispatch(() => this.UpdateMetaData(stream, gain, peak, mode)); } else { return; } } var effect = new ReplayGainEffect(stream.ChannelHandle, gain, mode); effect.Activate(); this.Effects.Add(stream, effect); }
protected virtual void OnCreatingPipeline(object sender, CreatingPipelineEventArgs e) { if (!this.Enabled || this.Output.Rate == e.Stream.Rate) { return; } if (!this.Output.EnforceRate && e.Query.OutputRates.Contains(e.Stream.Rate)) { return; } if (BassUtils.GetChannelDsdRaw(e.Stream.ChannelHandle)) { return; } var component = new BassResamplerStreamComponent(this, e.Stream); component.InitializeComponent(this.Core); e.Components.Add(component); }
public BassGaplessStreamInput(BassGaplessStreamInputBehaviour behaviour, BassOutputStream stream) { this.Behaviour = behaviour; this.Channels = stream.Channels; this.Flags = BassFlags.Decode; if (BassUtils.GetChannelDsdRaw(stream.ChannelHandle)) { this.Rate = BassUtils.GetChannelDsdRate(stream.ChannelHandle); this.Flags |= BassFlags.DSDRaw; } else { this.Rate = stream.Rate; if (behaviour.Output.Float) { this.Flags |= BassFlags.Float; } } }
public static bool ShouldCreateResampler(BassResamplerStreamComponentBehaviour behaviour, BassOutputStream stream, IBassStreamPipelineQueryResult query) { if (BassUtils.GetChannelDsdRaw(stream.ChannelHandle)) { //Cannot resample DSD. return(false); } if (behaviour.Output.EnforceRate && behaviour.Output.Rate != stream.Rate) { //Rate is enforced and not equal to the stream rate. return(true); } if (!query.OutputRates.Contains(stream.Rate)) { //Output does not support the stream rate. return(true); } //Something else. return(false); }