Пример #1
0
 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;
         }
     }
 }
Пример #2
0
        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);
        }
Пример #3
0
 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();
 }
Пример #4
0
        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();
        }
Пример #5
0
 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();
     }
 }
Пример #7
0
 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();
 }
Пример #8
0
 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);
 }
Пример #9
0
 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);
     }
 }
Пример #10
0
 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;
     }
 }
Пример #11
0
 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();
     }
 }
Пример #12
0
 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
         );
 }
Пример #13
0
 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
         );
 }
Пример #14
0
 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);
 }
Пример #15
0
 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);
 }
Пример #16
0
 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();
 }
Пример #17
0
 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;
 }
Пример #19
0
 public abstract void Connect(IBassStreamComponent previous);