Esempio n. 1
0
        private void UpdateChannels()
        {
            if (this.FDeviceIndex != -1 || this.FPinInVolumeOutput.SliceCount > 0)
            {
                BASS_ASIO_INFO deviceinfo = BassAsio.BASS_ASIO_GetInfo();

                int current = 0;
                for (int i = 0; i < deviceinfo.outputs; i++)
                {
                    double active;

                    this.FPinInActive.GetValue(current, out active);

                    if (active == 1)
                    {
                        BassAsio.BASS_ASIO_ChannelReset(false, i, BASSASIOReset.BASS_ASIO_RESET_PAUSE);
                    }
                    else
                    {
                        BassAsio.BASS_ASIO_ChannelPause(false, i);
                    }
                    //Bin for the channels
                    current++;
                    if (current == this.FPinInActive.SliceCount)
                    {
                        current = 0;
                    }
                }
            }
        }
Esempio n. 2
0
        private void buttonPlay_Click(object sender, System.EventArgs e)
        {
            BassAsio.BASS_ASIO_Stop();
            BassAsio.BASS_ASIO_ChannelReset(false, -1, BASSASIOReset.BASS_ASIO_RESET_PAUSE | BASSASIOReset.BASS_ASIO_RESET_JOIN);
            Bass.BASS_StreamFree(_streamFX);
            if (_fileName != String.Empty)
            {
                // create the decoding stream
                _stream = Bass.BASS_StreamCreateFile(_fileName, 0, 0, BASSFlag.BASS_STREAM_DECODE | BASSFlag.BASS_SAMPLE_FLOAT);
                if (_stream != 0)
                {
                    // now we create a Tempo channel (again a decoding one)...the actual playing channel
                    _streamFX = BassFx.BASS_FX_TempoCreate(_stream, BASSFlag.BASS_STREAM_DECODE | BASSFlag.BASS_FX_FREESOURCE | BASSFlag.BASS_SAMPLE_FLOAT);
                    if (_streamFX == 0)
                    {
                        MessageBox.Show(this, "Can't create FX stream!", Enum.GetName(typeof(BASSError), Bass.BASS_ErrorGetCode()));
                        return;
                    }

                    // now setup ASIO
                    myAsioProc = new ASIOPROC(AsioCallback);

                    // get the stream channel info
                    BASS_CHANNELINFO info = new BASS_CHANNELINFO();
                    Bass.BASS_ChannelGetInfo(_streamFX, info);
                    _originSampleRate = (float)info.freq;
                    this.button2.Text = _originSampleRate.ToString("0");
                    // enable 1st output channel...(0=first)
                    BassAsio.BASS_ASIO_ChannelEnable(false, 0, myAsioProc, new IntPtr(_streamFX));
                    // and join the next channels to it
                    for (int a = 1; a < info.chans; a++)
                    {
                        BassAsio.BASS_ASIO_ChannelJoin(false, a, 0);
                    }
                    // since we joined the channels, the next commands will applay to all channles joined
                    // so setting the values to the first channels changes them all automatically
                    // set the source format (float, as the decoding channel is)
                    BassAsio.BASS_ASIO_ChannelSetFormat(false, 0, BASSASIOFormat.BASS_ASIO_FORMAT_FLOAT);
                    // set the source rate
                    BassAsio.BASS_ASIO_ChannelSetRate(false, 0, (double)info.freq);
                    // try to set the device rate too (saves resampling)
                    BassAsio.BASS_ASIO_SetRate((double)info.freq);
                    // and start playing it...
                    // start output using default buffer/latency
                    if (!BassAsio.BASS_ASIO_Start(0))
                    {
                        MessageBox.Show(this, "Can't start ASIO output", Enum.GetName(typeof(BASSError), BassAsio.BASS_ASIO_ErrorGetCode()));
                    }
                    else
                    {
                        this.labelStatus.Text = "playing";
                        this.timerUpdate.Start();
                    }
                }
            }
        }
Esempio n. 3
0
 private void buttonPause_Click(object sender, System.EventArgs e)
 {
     if (BassAsio.BASS_ASIO_ChannelIsActive(false, 0) == BASSASIOActive.BASS_ASIO_ACTIVE_PAUSED)
     {
         // channel is paused...so unpause
         BassAsio.BASS_ASIO_ChannelReset(false, 0, BASSASIOReset.BASS_ASIO_RESET_PAUSE);
         this.labelStatus.Text = "playing";
     }
     else
     {
         // channel is playing...so pause
         BassAsio.BASS_ASIO_ChannelPause(false, 0);
         this.labelStatus.Text         = "paused";
         this.progressBarVULeft.Value  = 0;
         this.progressBarVURight.Value = 0;
     }
 }
Esempio n. 4
0
        private bool setupChannel(int Frequency, BASSASIOFormat Format)
        {
            proc = new ASIOPROC(AsioCallback);

            BassAsio.BASS_ASIO_Stop();

            if (!BassAsio.BASS_ASIO_ChannelReset(false,
                                                 -1,
                                                 BASSASIOReset.BASS_ASIO_RESET_PAUSE | BASSASIOReset.BASS_ASIO_RESET_JOIN))
            {
                return(false);
            }

            if (!BassAsio.BASS_ASIO_ChannelEnable(false, 0, proc, IntPtr.Zero))
            {
                return(false);
            }

            if (!BassAsio.BASS_ASIO_ChannelJoin(false, 1, 0))
            {
                return(false);
            }

            if (!BassAsio.BASS_ASIO_ChannelSetFormat(false, 0, Format))
            {
                return(false);
            }

            BassAsio.BASS_ASIO_SetRate((double)Frequency);

            if (!BassAsio.BASS_ASIO_ChannelSetRate(false, 0, (double)Frequency))
            {
                return(false);
            }

            return(BassAsio.BASS_ASIO_Start(0));
        }
Esempio n. 5
0
        /// <summary>
        /// Create a mixer using the stream attributes
        /// </summary>
        /// <param name="stream"></param>
        /// <returns></returns>
        public bool CreateMixer(MusicStream stream)
        {
            Log.Debug("BASS: ---------------------------------------------");
            Log.Debug("BASS: Creating BASS mixer stream");

            bool result = false;

            BASSFlag mixerFlags = BASSFlag.BASS_MIXER_NONSTOP | BASSFlag.BASS_SAMPLE_FLOAT | BASSFlag.BASS_MIXER_NORAMPIN;

            if (Config.MusicPlayer == AudioPlayer.Asio || Config.MusicPlayer == AudioPlayer.WasApi)
            {
                mixerFlags |= BASSFlag.BASS_STREAM_DECODE;
            }

            int outputChannels = _bassPlayer.DeviceChannels;

            _mixingMatrix = null;

            // See, if we need Upmixing
            if (outputChannels > stream.ChannelInfo.chans)
            {
                Log.Debug("BASS: Found more output channels ({0}) than input channels ({1}). Check for upmixing.", outputChannels,
                          stream.ChannelInfo.chans);
                _mixingMatrix = CreateMixingMatrix(stream.ChannelInfo.chans);
                if (_mixingMatrix != null)
                {
                    outputChannels = Math.Min(_mixingMatrix.GetLength(0), outputChannels);
                    _upmixing      = true;
                }
                else
                {
                    outputChannels = stream.ChannelInfo.chans;
                }
            }
            else if (outputChannels < stream.ChannelInfo.chans)
            {
                // Downmix to Stereo
                Log.Debug("BASS: Found more input channels ({0}) than output channels ({1}). Downmix.", stream.ChannelInfo.chans,
                          outputChannels);
                outputChannels = Math.Min(outputChannels, 2);
            }

            Log.Debug("BASS: Creating {0} channel mixer with sample rate of {1}", outputChannels, stream.ChannelInfo.freq);
            _mixer = BassMix.BASS_Mixer_StreamCreate(stream.ChannelInfo.freq, outputChannels, mixerFlags);
            if (_mixer == 0)
            {
                Log.Error("BASS: Unable to create Mixer.  Reason: {0}.",
                          Enum.GetName(typeof(BASSError), Bass.BASS_ErrorGetCode()));
                return(false);
            }

            switch (Config.MusicPlayer)
            {
            case AudioPlayer.Bass:
            case AudioPlayer.DShow:

                if (!Bass.BASS_ChannelPlay(_mixer, false))
                {
                    Log.Error("BASS: Unable to start Mixer.  Reason: {0}.", Enum.GetName(typeof(BASSError), Bass.BASS_ErrorGetCode()));
                    return(false);
                }

                result = true;

                break;

            case AudioPlayer.Asio:

                Log.Info("BASS: Initialising ASIO device");

                if (BassAsio.BASS_ASIO_IsStarted() && !BassAsio.BASS_ASIO_Stop())
                {
                    Log.Error("BASS: Error stopping Asio Device: {0}", BassAsio.BASS_ASIO_ErrorGetCode());
                }

                // Disable and Unjoin all the channels
                if (!BassAsio.BASS_ASIO_ChannelReset(false, -1, BASSASIOReset.BASS_ASIO_RESET_ENABLE))
                {
                    Log.Error("BASS: Error disabling Asio Channels: {0}", BassAsio.BASS_ASIO_ErrorGetCode());
                }

                if (!BassAsio.BASS_ASIO_ChannelReset(false, -1, BASSASIOReset.BASS_ASIO_RESET_JOIN))
                {
                    Log.Error("BASS: Error unjoining Asio Channels: {0}", BassAsio.BASS_ASIO_ErrorGetCode());
                }

                _asioProc = new ASIOPROC(AsioCallback);

                BassAsio.BASS_ASIO_ChannelSetVolume(false, -1, (float)Config.StreamVolume / 100f);

                // enable 1st output channel...(0=first)
                Log.Debug("BASS: Joining Asio Channel #{0}", "0");
                BassAsio.BASS_ASIO_ChannelEnable(false, 0, _asioProc, new IntPtr(_mixer));

                // and join the next channels to it
                int numChannels = Math.Max(stream.ChannelInfo.chans, outputChannels);
                for (int i = 1; i < numChannels; i++)
                {
                    Log.Debug("BASS: Joining Asio Channel #{0}", i);
                    BassAsio.BASS_ASIO_ChannelJoin(false, i, 0);
                }

                // since we joined the channels, the next commands will apply to all channles joined
                // so setting the values to the first channels changes them all automatically
                // set the source format (float, as the decoding channel is)
                if (!BassAsio.BASS_ASIO_ChannelSetFormat(false, 0, BASSASIOFormat.BASS_ASIO_FORMAT_FLOAT))
                {
                    Log.Error("BASS: Error setting Asio Sample Format: {0}", BassAsio.BASS_ASIO_ErrorGetCode());
                }

                // set the source rate
                Log.Debug("BASS: Set sample rate to {0}", stream.ChannelInfo.freq);
                if (!BassAsio.BASS_ASIO_ChannelSetRate(false, 0, (double)stream.ChannelInfo.freq))
                {
                    Log.Error("BASS: Error setting Asio Channel Samplerate: {0}", BassAsio.BASS_ASIO_ErrorGetCode());
                }

                // try to set the device rate too (saves resampling)
                if (!BassAsio.BASS_ASIO_SetRate((double)stream.ChannelInfo.freq))
                {
                    Log.Error("BASS: Error setting Asio Samplerate: {0}", BassAsio.BASS_ASIO_ErrorGetCode());
                }

                // and start playing it...start output using default buffer/latency
                if (!BassAsio.BASS_ASIO_Start(0))
                {
                    Log.Error("BASS: Error starting Asio playback: {0}", BassAsio.BASS_ASIO_ErrorGetCode());
                }
                Log.Info("BASS: Finished initialising ASIO device");
                result = true;

                break;

            case AudioPlayer.WasApi:

                Log.Info("BASS: Initialising WASAPI device");

                try
                {
                    BassWasapi.BASS_WASAPI_Free();
                    Log.Debug("BASS: Freed WASAPI device");
                }
                catch (Exception ex)
                {
                    Log.Error("BASS: Exception freeing WASAPI. {0} {1}", ex.Message, ex.StackTrace);
                }

                BASSWASAPIInit initFlags = BASSWASAPIInit.BASS_WASAPI_AUTOFORMAT;

                _wasapiProc = new WASAPIPROC(WasApiCallback);

                bool wasApiExclusiveSupported = true;

                // Check if we have an uneven number of channels
                var chkChannels = outputChannels % 2;
                if (chkChannels == 1)
                {
                    Log.Warn("BASS: Found uneven number of channels {0}. increase output channels.", outputChannels);
                    outputChannels++;                 // increase the number of output channels
                    wasApiExclusiveSupported = false; // And indicate that we need a new mixer
                }

                // Handle the special cases of 3.0, 4.0 and 5.0 files being played on a 5.1 or 6.1 device
                if (outputChannels == 3) // a 3.0 file
                {
                    Log.Info("BASS: Found a 3 channel file. Set upmixing with LFE, LR, RR set to silent");
                    _mixingMatrix            = CreateThreeDotZeroUpMixMatrix();
                    outputChannels           = _bassPlayer.DeviceChannels; // WASAPI device should be initialised with all channels active
                    wasApiExclusiveSupported = false;                      // And indicate that we need a new mixer
                }
                else if (outputChannels == 4)                              // a 4.0 file
                {
                    Log.Info("BASS: Found a 4 channel file. Set upmixing with Center and LFE set to silent");
                    _mixingMatrix            = CreateFourDotZeroUpMixMatrix();
                    outputChannels           = _bassPlayer.DeviceChannels; // WASAPI device should be initialised with all channels active
                    wasApiExclusiveSupported = false;                      // And indicate that we need a new mixer
                }
                else if (outputChannels == 5)                              // a 5.0 file
                {
                    Log.Info("BASS: Found a 5 channel file. Set upmixing with LFE set to silent");
                    _mixingMatrix            = CreateFiveDotZeroUpMixMatrix();
                    outputChannels           = _bassPlayer.DeviceChannels; // WASAPI device should be initialised with all channels active
                    wasApiExclusiveSupported = false;                      // And indicate that we need a new mixer
                }

                // If Exclusive mode is used, check, if that would be supported, otherwise init in shared mode
                if (Config.WasApiExclusiveMode)
                {
                    initFlags        |= BASSWASAPIInit.BASS_WASAPI_EXCLUSIVE;
                    _wasapiShared     = false;
                    _wasapiMixedChans = 0;
                    _wasapiMixedFreq  = 0;

                    BASSWASAPIFormat wasapiFormat = BassWasapi.BASS_WASAPI_CheckFormat(_bassPlayer.DeviceNumber,
                                                                                       stream.ChannelInfo.freq,
                                                                                       outputChannels,
                                                                                       BASSWASAPIInit.BASS_WASAPI_EXCLUSIVE);
                    if (wasapiFormat == BASSWASAPIFormat.BASS_WASAPI_FORMAT_UNKNOWN)
                    {
                        Log.Warn("BASS: WASAPI exclusive mode not directly supported. Let BASS WASAPI choose better mode.");
                        wasApiExclusiveSupported = false;
                    }
                }
                else
                {
                    Log.Debug("BASS: Init WASAPI shared mode with Event driven system enabled.");
                    initFlags |= BASSWASAPIInit.BASS_WASAPI_SHARED | BASSWASAPIInit.BASS_WASAPI_EVENT;

                    // In case of WASAPI Shared mode we need to setup the mixer to use the same sample rate as set in
                    // the Windows Mixer, otherwise we wioll have increased playback speed
                    BASS_WASAPI_DEVICEINFO devInfo = BassWasapi.BASS_WASAPI_GetDeviceInfo(_bassPlayer.DeviceNumber);
                    Log.Debug("BASS: Creating {0} channel mixer for frequency {1}", devInfo.mixchans, devInfo.mixfreq);
                    _mixer = BassMix.BASS_Mixer_StreamCreate(devInfo.mixfreq, devInfo.mixchans, mixerFlags);
                    if (_mixer == 0)
                    {
                        Log.Error("BASS: Unable to create Mixer.  Reason: {0}.",
                                  Enum.GetName(typeof(BASSError), Bass.BASS_ErrorGetCode()));
                        return(false);
                    }
                    _wasapiShared = true;
                }

                Log.Debug("BASS: Try to init WASAPI with a Frequency of {0} and {1} channels", stream.ChannelInfo.freq, outputChannels);

                if (BassWasapi.BASS_WASAPI_Init(_bassPlayer.DeviceNumber, stream.ChannelInfo.freq, outputChannels,
                                                initFlags | BASSWASAPIInit.BASS_WASAPI_BUFFER, Convert.ToSingle(Config.BufferingMs / 1000.0), 0f, _wasapiProc, IntPtr.Zero))
                {
                    BASS_WASAPI_INFO wasapiInfo = BassWasapi.BASS_WASAPI_GetInfo();

                    Log.Debug("BASS: ---------------------------------------------");
                    Log.Debug("BASS: Buffer Length: {0}", wasapiInfo.buflen);
                    Log.Debug("BASS: Channels: {0}", wasapiInfo.chans);
                    Log.Debug("BASS: Frequency: {0}", wasapiInfo.freq);
                    Log.Debug("BASS: Format: {0}", wasapiInfo.format.ToString());
                    Log.Debug("BASS: InitFlags: {0}", wasapiInfo.initflags.ToString());
                    Log.Debug("BASS: Exclusive: {0}", wasapiInfo.IsExclusive.ToString());
                    Log.Debug("BASS: ---------------------------------------------");
                    Log.Info("BASS: WASAPI Device successfully initialised");

                    // Now we need to check, if WASAPI decided to switch to a different mode
                    if (Config.WasApiExclusiveMode && !wasApiExclusiveSupported)
                    {
                        // Recreate Mixer with new value
                        Log.Debug("BASS: Creating new {0} channel mixer for frequency {1}", wasapiInfo.chans, wasapiInfo.freq);
                        _mixer = BassMix.BASS_Mixer_StreamCreate(wasapiInfo.freq, wasapiInfo.chans, mixerFlags);
                        if (_mixer == 0)
                        {
                            Log.Error("BASS: Unable to create Mixer.  Reason: {0}.",
                                      Enum.GetName(typeof(BASSError), Bass.BASS_ErrorGetCode()));
                            return(false);
                        }
                    }

                    BassWasapi.BASS_WASAPI_SetVolume(BASSWASAPIVolume.BASS_WASAPI_CURVE_DB, (float)Config.StreamVolume / 100f);
                    BassWasapi.BASS_WASAPI_Start();
                    result = true;
                }
                else
                {
                    Log.Error("BASS: Couldn't init WASAPI device. Error: {0}", Enum.GetName(typeof(BASSError), Bass.BASS_ErrorGetCode()));
                }
                break;
            }

            if (result)
            {
                Log.Debug("BASS: Successfully created BASS Mixer stream");
            }
            return(result);
        }
Esempio n. 6
0
 public void Dispose()
 {
     BassAsio.BASS_ASIO_ChannelReset(true, 0, BASSASIOReset.BASS_ASIO_RESET_PAUSE | BASSASIOReset.BASS_ASIO_RESET_JOIN);
 }
Esempio n. 7
0
 public void Dispose()
 {
     BassAsio.BASS_ASIO_Stop();
     BassAsio.BASS_ASIO_ChannelReset(false, -1, BASSASIOReset.BASS_ASIO_RESET_PAUSE | BASSASIOReset.BASS_ASIO_RESET_JOIN);
 }
Esempio n. 8
0
        public void Evaluate(int SpreadMax)
        {
            try
            {
                #region Channel and device
                if (this.FPinInChannels.PinIsChanged || this.FPinInDevice.PinIsChanged)
                {
                    double dbldevice;
                    this.FPinInDevice.GetValue(0, out dbldevice);

                    this.FDeviceIndex = Convert.ToInt32(dbldevice);
                    if (this.FDeviceIndex != -1)
                    {
                        BassAsio.BASS_ASIO_Init(this.FDeviceIndex);
                        BassAsio.BASS_ASIO_SetDevice(this.FDeviceIndex);
                    }

                    this.FOutputHandled.Clear();
                    BassAsio.BASS_ASIO_Stop();

                    BassAsio.BASS_ASIO_ChannelReset(false, -1, BASSASIOReset.BASS_ASIO_RESET_PAUSE | BASSASIOReset.BASS_ASIO_RESET_JOIN);

                    if (this.FDeviceIndex != -1 && this.FPinInChannels.IsConnected)
                    {
                        int    asiooutindex = 0;
                        double dhandle;
                        for (int i = 0; i < this.FPinInChannels.SliceCount; i++)
                        {
                            this.FPinInChannels.GetValue(i, out dhandle);
                            int handle = Convert.ToInt32(dhandle);

                            if (handle != 0 && handle != -1)
                            {
                                ChannelInfo channel = this.manager.GetChannel(handle);

                                if (channel.BassHandle == null)
                                {
                                    //Initialize channel (in nosound)
                                    channel.Initialize(0);
                                }

                                //Check if the channel has its own handler
                                if (!BassAsioUtils.InputChannels.ContainsKey(handle))
                                {
                                    BASS_CHANNELINFO info = Bass.BASS_ChannelGetInfo(channel.BassHandle.Value);

                                    BassAsio.BASS_ASIO_ChannelEnable(false, asiooutindex, myAsioProc, new IntPtr(handle));
                                    if (info.chans == 1)
                                    {
                                        //No need to join on mono channels
                                        asiooutindex++;
                                    }
                                    else
                                    {
                                        for (int chan = 1; chan < info.chans; chan++)
                                        {
                                            bool join = BassAsio.BASS_ASIO_ChannelJoin(false, asiooutindex + chan, asiooutindex);
                                            if (!join)
                                            {
                                                this.FHost.Log(TLogType.Error, "Error: join failed");
                                                this.FHost.Log(TLogType.Error, BassAsio.BASS_ASIO_ErrorGetCode().ToString());
                                            }
                                        }

                                        BassAsio.BASS_ASIO_ChannelSetFormat(false, asiooutindex, BASSASIOFormat.BASS_ASIO_FORMAT_FLOAT);
                                        BassAsio.BASS_ASIO_ChannelSetRate(false, asiooutindex, (double)info.freq);
                                        BassAsio.BASS_ASIO_SetRate((double)info.freq);

                                        asiooutindex += info.chans;
                                    }
                                }
                                else
                                {
                                    BassAsioHandler handler = BassAsioUtils.InputChannels[handle].Handler;
                                    handler.SetMirror(asiooutindex);
                                    asiooutindex += 2;
                                    this.FOutputHandled.Add(asiooutindex);
                                    this.FOutputHandled.Add(asiooutindex + 1);
                                }
                            }
                        }

                        bool start = BassAsio.BASS_ASIO_Start(0);
                        if (!start)
                        {
                            this.FPinErrorCode.SetString(0, BassAsio.BASS_ASIO_ErrorGetCode().ToString());
                            this.FHost.Log(TLogType.Error, "Error: Start failed");
                            this.FHost.Log(TLogType.Error, BassAsio.BASS_ASIO_ErrorGetCode().ToString());
                        }
                        else
                        {
                            this.FPinErrorCode.SetString(0, "OK");
                        }

                        UpdateChannels();
                    }
                }

                if (FControlPanel.PinIsChanged)
                {
                    double v;
                    FControlPanel.GetValue(0, out v);
                    if (v > 0.5)
                    {
                        BassAsio.BASS_ASIO_ControlPanel();
                    }
                }
                #endregion

                #region Volume
                if (this.FPinInVolumeOutput.PinIsChanged)
                {
                    if (this.FDeviceIndex != -1 || this.FPinInVolumeOutput.SliceCount > 0)
                    {
                        BASS_ASIO_INFO deviceinfo = BassAsio.BASS_ASIO_GetInfo();

                        int current = 0;
                        for (int i = 0; i < deviceinfo.outputs; i++)
                        {
                            double vol;

                            this.FPinInVolumeOutput.GetValue(current, out vol);
                            BassAsio.BASS_ASIO_ChannelSetVolume(false, i, (float)vol);

                            //Bin for the channels
                            current++;
                            if (current == this.FPinInVolumeOutput.SliceCount)
                            {
                                current = 0;
                            }
                        }
                    }
                }
                #endregion

                #region Is Active Pin
                if (this.FPinInActive.PinIsChanged)
                {
                    UpdateChannels();
                }
                #endregion
            }
            catch (Exception ex)
            {
                this.FHost.Log(TLogType.Error, ex.Message);
                this.FHost.Log(TLogType.Error, ex.StackTrace);
            }
        }
Esempio n. 9
0
 public override void Resume()
 {
     BassAsio.BASS_ASIO_ChannelReset(false, -1, BASSASIOReset.BASS_ASIO_RESET_PAUSE);
 }