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();
        }
示例#3
0
        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);
        }
示例#4
0
 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);
        }
示例#6
0
 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;
         }
     }
 }
示例#9
0
        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);
        }
示例#10
0
        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;
         }
     }
 }
示例#12
0
 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);
 }