internal HolofunkBassAsioInput(HolofunkBassAsio bassAsio, int asioChannel, BufferAllocator<float> audioAllocator)
        {
            m_bassAsio = bassAsio;
            m_asioChannel = asioChannel;

            // buffer one second's worth of audio; that will always be more than we need to look at
            m_recentPastStream = new DenseSampleFloatStream(
                default(Time<Sample>),
                audioAllocator,
                1, // input channels are mono
                maxBufferedDuration: Clock.TimepointRateHz);

            m_inputToInputPushStreamAsioProc = new ASIOPROC(InputToInputPushStreamAsioProc);

            // create input push stream; this receives data pushed from ASIO's input, and feeds the mixer
            m_inputPushStream = (StreamHandle)Bass.BASS_StreamCreatePush(
                Clock.TimepointRateHz,
                HolofunkBassAsio.InputChannelCount,
                BASSFlag.BASS_STREAM_DECODE | BASSFlag.BASS_SAMPLE_FLOAT,
                new IntPtr(m_asioChannel));

            // connect to ASIO input channel
            CheckError(BassAsio.BASS_ASIO_ChannelEnable(
                HolofunkBassAsio.IsInputChannel,
                m_asioChannel,
                m_inputToInputPushStreamAsioProc,
                new IntPtr(m_asioChannel)));

            // join right channel if we have more than one input channel
            // (this is not generalized for >stereo)
            if (HolofunkBassAsio.InputChannelCount == 2) {
                CheckError(BassAsio.BASS_ASIO_ChannelJoin(HolofunkBassAsio.IsInputChannel, 1, m_asioChannel));
            }

            // set format and rate of input channel
            CheckError(BassAsio.BASS_ASIO_ChannelSetFormat(HolofunkBassAsio.IsInputChannel, m_asioChannel, BASSASIOFormat.BASS_ASIO_FORMAT_FLOAT));
            CheckError(BassAsio.BASS_ASIO_ChannelSetRate(HolofunkBassAsio.IsInputChannel, m_asioChannel, Clock.TimepointRateHz));

            // add input push stream to mixer
            CheckError(BassMix.BASS_Mixer_StreamAddChannel(
                (int)m_bassAsio.MixerHStream,
                (int)m_inputPushStream,
                BASSFlag.BASS_MIXER_DOWNMIX | BASSFlag.BASS_MIXER_NORAMPIN));

            // set up the input effects (aka microphone effects)
            m_inputPushEffects = AllEffects.CreateLoopEffectSet(m_inputPushStream, m_bassAsio.BaseForm);

            // connect peak level meter to input push stream
            m_plmRec = new DSP_PeakLevelMeter((int)m_inputPushStream, 0);
            m_plmRec.Notification += new EventHandler(Plm_Rec_Notification);

            // Register DSPPROC handler for input channel.  Make sure to hold the DSPPROC itself.
            // See documentation for BassAsioHandler.InputChannel
            m_inputDspProc = new DSPPROC(InputDspProc);

            // set up our recording DSP -- priority 10 hopefully means "run first first first!"
            CheckError(Bass.BASS_ChannelSetDSP((int)m_inputPushStream, m_inputDspProc, new IntPtr(0), 10) != 0);
        }
Ejemplo 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();
                    }
                }
            }
        }
Ejemplo n.º 3
0
        public void SetPluginHost(IPluginHost Host)
        {
            this.FHost   = Host;
            this.manager = ChannelsManager.GetInstance();

            //We play this channel trough Asio output, so we choose the device NOSOUND
            Bass.BASS_Init(0, 48000, 0, IntPtr.Zero, null);

            //int cnt = BassAsio.BASS_ASIO_GetDeviceCount();
            //List<string> devices = new List<string>();
            //BASS_ASIO_DEVICEINFO[] devinfo = BassAsio.BASS_ASIO_GetDeviceInfos();
            //for (int i = 0; i < devinfo.Length; i++)
            //{
            //    BASS_ASIO_DEVICEINFO d = devinfo[i];
            //    devices.Add(d.name);
            //}



            //this.FHost.UpdateEnum("Bass Asio Devices", devices[0], devices.ToArray());

            BassUtils.LoadPlugins();

            //this.FHost.CreateEnumInput("Device Id", TSliceMode.Single, TPinVisibility.True, out this.FPinInDeviceEnum);
            // this.FPinInDeviceEnum.SetSubType("Bass Asio Devices");

            this.FHost.CreateValueInput("Device", 1, null, TSliceMode.Single, TPinVisibility.True, out this.FPinInDevice);
            this.FPinInDevice.SetSubType(0, double.MaxValue, 1, 0, false, false, true);

            this.FHost.CreateValueInput("Control Panel", 1, null, TSliceMode.Single, TPinVisibility.True, out this.FControlPanel);
            this.FControlPanel.SetSubType(0, 1, 1, 0, true, false, false);

            this.FHost.CreateValueInput("Is Active", 1, null, TSliceMode.Dynamic, TPinVisibility.True, out this.FPinInActive);
            this.FPinInActive.SetSubType(0.0, 1.0, 1, 0, false, true, true);

            this.FHost.CreateValueInput("Volume", 1, null, TSliceMode.Dynamic, TPinVisibility.True, out this.FPinInVolumeOutput);
            this.FPinInVolumeOutput.SetSubType(0, 1, 0.01, 1, false, false, false);

            this.FHost.CreateValueInput("Handles In", 1, null, TSliceMode.Dynamic, TPinVisibility.True, out this.FPinInChannels);
            this.FPinInChannels.SetSubType(double.MinValue, double.MaxValue, 1, -1, false, false, true);

            this.FHost.CreateStringOutput("Status", TSliceMode.Single, TPinVisibility.True, out this.FPinErrorCode);

            this.myAsioProc = new ASIOPROC(AsioCallback);
        }
Ejemplo n.º 4
0
        private bool EnableAndJoin(bool input, int channel, int numchans, ASIOPROC proc, BASSASIOFormat format)
        {
            bool flag = true;

            if (BassAsio.BASS_ASIO_ChannelIsActive(input, channel) == BASSASIOActive.BASS_ASIO_ACTIVE_DISABLED)
            {
                flag &= BassAsio.BASS_ASIO_ChannelEnable(input, channel, proc, IntPtr.Zero);
                for (int i = 1; i < numchans; i++)
                {
                    BassAsio.BASS_ASIO_ChannelJoin(input, channel + i, channel);
                }
            }
            else
            {
                flag &= BassAsio.BASS_ASIO_ChannelEnable(input, channel, proc, IntPtr.Zero);
            }
            flag &= BassAsio.BASS_ASIO_ChannelSetFormat(input, channel, format);
            return(flag & BassAsio.BASS_ASIO_ChannelSetRate(input, channel, this._samplerate));
        }
Ejemplo n.º 5
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));
        }
Ejemplo n.º 6
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);
        }
Ejemplo n.º 7
0
        internal HolofunkBassAsio(HolofunkBass bass)
        {
            m_bass = bass;

            m_outputAsioProcAverageLatency = new FloatAverager(20);
            m_outputAsioProcStopwatch = new Stopwatch();
            m_mixerToOutputAsioProc = new ASIOPROC(MixerToOutputAsioProc);
        }
Ejemplo n.º 8
0
        /// <summary>
        /// Plays the playlist from the current item index.
        /// </summary>
        public void Play(double initialPosition, bool startPaused)
        {
            try
            {
                if (_isPlaying)
                {
                    if (_currentLoop != null)
                    {
						//Tracing.Log("Player.Play -- Stopping current loop...");
                        StopLoop();
                    }

					//Tracing.Log("Player.Play -- Stopping playback...");
                    Stop();
                }

                RemoveSyncCallbacks();
                _currentLoop = null;
                _positionOffset = 0;
                _currentMixPlaylistIndex = Playlist.CurrentItemIndex;

                // How many channels are left?                
                int channelsToLoad = Playlist.Items.Count - Playlist.CurrentItemIndex;                

                // If there are more than 2, just limit to 2 for now. The other channels are loaded dynamically.
                if (channelsToLoad > 2)
                    channelsToLoad = 2;

                // Check for channels to load
                if (channelsToLoad == 0)
                    throw new Exception("Error in Player.Play: There aren't any channels to play!");

                // Load the current channel and the next channel if it exists
                for (int a = Playlist.CurrentItemIndex; a < Playlist.CurrentItemIndex + channelsToLoad; a++)
                    _playlist.Items[a].Load(_useFloatingPoint);

                // Start decoding first playlist item
                //_decodingService.StartDecodingFile(_playlist.Items[0].AudioFile.FilePath, _positionOffset);

                try
                {
                    // Create the streaming channel (set the frequency to the first file in the list)
					//Tracing.Log("Player.Play -- Creating streaming channel (SampleRate: " + _playlist.CurrentItem.AudioFile.SampleRate + " Hz, FloatingPoint: true)...");

#if IOS
                    _streamProc = new STREAMPROC(StreamCallbackIOS);
#else
                    _streamProc = new STREAMPROC(StreamCallback);
#endif

                    _streamChannel = Channel.CreateStream(_playlist.CurrentItem.AudioFile.SampleRate, 2, _useFloatingPoint, _streamProc);
					//Tracing.Log("Player.Play -- Creating time shifting channel...");
                    _fxChannel = Channel.CreateStreamForTimeShifting(_streamChannel.Handle, true, _useFloatingPoint);
                    //_fxChannel = Channel.CreateStreamForTimeShifting(_streamChannel.Handle, false, _useFloatingPoint);
                    //_fxChannel = _streamChannel;
                }
                catch(Exception ex)
                {
                    // Raise custom exception with information (so the client application can maybe deactivate floating point for example)
                    PlayerCreateStreamException newEx = new PlayerCreateStreamException("The player has failed to create the stream channel (" + ex.Message + ").", ex);
                    newEx.Decode = true;
                    newEx.UseFloatingPoint = true;
                    newEx.SampleRate = _playlist.CurrentItem.AudioFile.SampleRate;
                    throw newEx;
                }

                // Check driver type
                if (_device.DriverType == DriverType.DirectSound)
                {
                    try
                    {
                        // Create mixer stream
						Tracing.Log("Player.Play -- Creating mixer channel (DirectSound)...");
                        _mixerChannel = MixerChannel.CreateMixerStream(_playlist.CurrentItem.AudioFile.SampleRate, 2, _useFloatingPoint, false);
                        _mixerChannel.AddChannel(_fxChannel.Handle);
                        //_mixerChannel = _fxChannel;
                        AddBPMCallbacks();
                    }
                    catch (Exception ex)
                    {   
                        // Raise custom exception with information (so the client application can maybe deactivate floating point for example)
                        PlayerCreateStreamException newEx = new PlayerCreateStreamException("The player has failed to create the time shifting channel.", ex);
                        newEx.UseFloatingPoint = true;
                        newEx.UseTimeShifting = true;
                        newEx.SampleRate = _playlist.CurrentItem.AudioFile.SampleRate;
                        throw newEx;
                    }
                }
#if !IOS && !ANDROID
                else if (_device.DriverType == DriverType.ASIO)
                {
                    try
                    {
                        // Create mixer stream
                        Tracing.Log("Player.Play -- Creating mixer channel (ASIO)...");
                        _mixerChannel = MixerChannel.CreateMixerStream(_playlist.CurrentItem.AudioFile.SampleRate, 2, _useFloatingPoint, true);
                        _mixerChannel.AddChannel(_fxChannel.Handle);
                    }
                    catch (Exception ex)
                    {
                        // Raise custom exception with information (so the client application can maybe deactivate floating point for example)
                        PlayerCreateStreamException newEx = new PlayerCreateStreamException("The player has failed to create the time shifting channel.", ex);
                        newEx.DriverType = DriverType.ASIO;
                        newEx.UseFloatingPoint = true;
                        newEx.UseTimeShifting = true;
                        newEx.Decode = true;
                        newEx.SampleRate = _playlist.CurrentItem.AudioFile.SampleRate;
                        throw newEx;  
                    }
                    
                    // Set floating point
                    BassAsio.BASS_ASIO_ChannelSetFormat(false, 0, BASSASIOFormat.BASS_ASIO_FORMAT_FLOAT);

                    // Create callback
                    asioProc = new ASIOPROC(AsioCallback);

                    try
                    {
                        // Enable and join channels (for stereo output
                        Tracing.Log("Player.Play -- Enabling ASIO channels...");
                        BassAsio.BASS_ASIO_ChannelEnable(false, 0, asioProc, new IntPtr(_mixerChannel.Handle));
                        Tracing.Log("Player.Play -- Joining ASIO channels...");
                        BassAsio.BASS_ASIO_ChannelJoin(false, 1, 0);

                        // Set sample rate
                        Tracing.Log("Player.Play -- Set ASIO sample rates...");
                        BassAsio.BASS_ASIO_ChannelSetRate(false, 0, _playlist.CurrentItem.AudioFile.SampleRate);
                        BassAsio.BASS_ASIO_SetRate(_playlist.CurrentItem.AudioFile.SampleRate);
                    }
                    catch (Exception ex)
                    {
                        // Raise custom exception with information (so the client application can maybe deactivate floating point for example)
                        PlayerCreateStreamException newEx = new PlayerCreateStreamException("The player has failed to enable or join ASIO channels.", ex);
                        newEx.DriverType = DriverType.ASIO;
                        newEx.SampleRate = _playlist.CurrentItem.AudioFile.SampleRate;
                        throw newEx;
                    }

                    // Start playback
                    Tracing.Log("Player.Play -- Starting ASIO buffering...");
                    if (!BassAsio.BASS_ASIO_Start(0))
                    {
                        // Get BASS error
                        BASSError error = Bass.BASS_ErrorGetCode();

                        // Raise custom exception with information (so the client application can maybe deactivate floating point for example)
                        PlayerCreateStreamException newEx = new PlayerCreateStreamException("The player has failed to create the ASIO channel (" + error.ToString() + ").", null);
                        newEx.DriverType = DriverType.ASIO;
                        newEx.UseFloatingPoint = true;
                        newEx.UseTimeShifting = true;
                        newEx.Decode = true;
                        newEx.SampleRate = _playlist.CurrentItem.AudioFile.SampleRate;
                        throw newEx;                        
                    }
                }
                else if (_device.DriverType == DriverType.WASAPI)
                {
                    // Create mixer stream
                    Tracing.Log("Player.Play -- Creating mixer channel (WASAPI)...");
                    _mixerChannel = MixerChannel.CreateMixerStream(_playlist.CurrentItem.AudioFile.SampleRate, 2, true, true);
                    _mixerChannel.AddChannel(_fxChannel.Handle);

                    // Start playback
                    if (!BassWasapi.BASS_WASAPI_Start())
                    {
                        // Get error
                        BASSError error = Bass.BASS_ErrorGetCode();
                        throw new Exception("Player.Play error: Error playing files in WASAPI: " + error.ToString());
                    }
                }
#endif
                // Set initial volume
                _mixerChannel.Volume = Volume;

                // Load 18-band equalizer
				//Tracing.Log("Player.Play -- Creating equalizer (Preset: " + _currentEQPreset + ")...");
                AddEQ(_currentEQPreset);

                // Check if EQ is bypassed
                if (_isEQBypassed)
                {
                    // Reset EQ
					//Tracing.Log("Player.Play -- Equalizer is bypassed; resetting EQ...");
                    ResetEQ();
                }

                // Check if the song must be looped
                if (_repeatType == RepeatType.Song)
                    _playlist.CurrentItem.Channel.SetFlags(BASSFlag.BASS_SAMPLE_LOOP, BASSFlag.BASS_SAMPLE_LOOP);

                long length = _playlist.CurrentItem.Channel.GetLength();
                SetSyncCallback(length);
                _isPlaying = true;

                // Only the DirectSound mode needs to start the main channel since it's not in decode mode.
                if (_device.DriverType == DriverType.DirectSound)
                {
                    // For iOS: This is required to update the AirPlay/remote player status
                    Base.Start();

                    // Start playback
					//Tracing.Log("Player.Play -- Starting DirectSound playback...");
                    _mixerChannel.Play(false);

                    if (startPaused)
                    {
                        if(initialPosition > 0)
                            SetPosition(initialPosition);

                        Base.Pause();
                    }

                    _isPaused = startPaused;
                }

//                StartEncode(EncoderType.OGG);
//                StartCast(new CastServerParams()
//                {
//                    Bitrate = 128,
//                    Name = "Sessions Test Server",
//                    Url = "localhost:8000",
//                    Password = "******"
//                });

                // Raise audio file finished event (if an event is subscribed)
                if (OnPlaylistIndexChanged != null)
                {
                    PlayerPlaylistIndexChangedData data = new PlayerPlaylistIndexChangedData();
                    data.IsPlaybackStopped = false;
                    data.AudioFileStarted = _playlist.CurrentItem.AudioFile;
                    data.PlaylistName = "New playlist 1";
                    data.PlaylistCount = _playlist.Items.Count;
                    data.PlaylistIndex = _playlist.CurrentItemIndex; 
                    if (Playlist.CurrentItemIndex < Playlist.Items.Count - 2)
                        data.NextAudioFile = Playlist.Items[Playlist.CurrentItemIndex + 1].AudioFile;
                    OnPlaylistIndexChanged(data);
                }
            }
            catch (Exception ex)
            {
                Tracing.Log("Player.Play error: " + ex.Message + "\n" + ex.StackTrace);
                throw;
            }
        }
Ejemplo n.º 9
0
        /// <summary>
        /// Starts the playback of an audio file.
        /// </summary>
        /// <param name="filePath">Audio file path</param>
        public void Play(string filePath)
        {
            // Check if the file exists
            if (!File.Exists(filePath))
            {
                throw new Exception("Error in TestDevice.Play: The file doesn't exist!");
            }
            
            // Check driver type
            if (device.DriverType == DriverType.DirectSound)
            {
                // Create stream
                stream = Bass.BASS_StreamCreateFile(filePath, 0, 0, BASSFlag.BASS_DEFAULT);
                if (stream == 0)
                {
                    // Get error
                    BASSError error = Bass.BASS_ErrorGetCode();
                    throw new Exception("Error playing TestDevice: " + error.ToString());
                }

                // Get stream info
                BASS_CHANNELINFO channelInfo = Bass.BASS_ChannelGetInfo(stream);

                // Create callback
                streamProc = new STREAMPROC(DirectSoundCallback);

                // Create master stream
                streamDirectSound = Bass.BASS_StreamCreate(channelInfo.freq, channelInfo.chans, BASSFlag.BASS_DEFAULT, streamProc, IntPtr.Zero);

                // Start playback
                if(!Bass.BASS_ChannelPlay(stream, false))
                {
                    // Get error
                    BASSError error = Bass.BASS_ErrorGetCode();
                    throw new Exception("Error playing TestDevice: " + error.ToString());
                }
            }
#if !IOS && !ANDROID
            else if (device.DriverType == DriverType.ASIO)
            {
                // Create stream
                stream = Bass.BASS_StreamCreateFile(filePath, 0, 0, BASSFlag.BASS_STREAM_DECODE);                
                if (stream == 0)
                {
                    // Get error
                    BASSError error = Bass.BASS_ErrorGetCode();
                    throw new Exception("Error playing TestDevice: " + error.ToString());
                }

                // Create callback
                asioProc = new ASIOPROC(AsioCallback);

                // Create channel
                BassAsio.BASS_ASIO_ChannelEnable(false, 0, asioProc, new IntPtr(stream));
                BassAsio.BASS_ASIO_ChannelJoin(false, 1, 0);

                // Start playback
                if (!BassAsio.BASS_ASIO_Start(0))
                {
                    // Get error
                    BASSError error = Bass.BASS_ErrorGetCode();
                    throw new Exception("Error playing TestDevice: " + error.ToString());
                }
            }
            else if (device.DriverType == DriverType.WASAPI)
            {
                // Create stream
                stream = Bass.BASS_StreamCreateFile(filePath, 0, 0, BASSFlag.BASS_STREAM_DECODE | BASSFlag.BASS_SAMPLE_FLOAT);
                if (stream == 0)
                {
                    // Get error
                    BASSError error = Bass.BASS_ErrorGetCode();
                    throw new Exception("Error playing TestDevice: " + error.ToString());
                }

                // Start playback
                if (!BassWasapi.BASS_WASAPI_Start())
                {
                    // Get error
                    BASSError error = Bass.BASS_ErrorGetCode();
                    throw new Exception("Error playing TestDevice: " + error.ToString());
                }
            }
#endif
        }
Ejemplo n.º 10
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;
    }
Ejemplo n.º 11
0
        public static void SetDevice(int inputChannel, int outputChannel)
        {
            //  Bass.BASS_SetConfig(BASSConfig.BASS_CONFIG_UPDATEPERIOD, 0);
            //   Bass.BASS_SetConfig(BASSConfig.BASS_CONFIG_FLOATDSP, true);
            // BassAsio.BASS_ASIO_Init(0, BASSASIOInit.BASS_ASIO_DEFAULT);
            //   Bass.BASS_Init(0, (int)samplerate, 0, IntPtr.Zero);

            //   m_asioInputHandlers = new BassAsioHandler();
            //   m_asioOutputHandlers = new BassAsioHandler();
            devinfo              = new BASS_ASIO_DEVICEINFO();
            m_asioInputChannels  = new List <object>();
            m_asioOutputChannels = new List <object>();
            thisControl          = PlayerControl.MainFormControl;
            m_inputChannel       = inputChannel;
            m_outputChannel      = outputChannel;

            /*   for (int n = 0; BassAsio.BASS_ASIO_GetDeviceInfo(n, devinfo); n++)
             * {
             *     if (devinfo.name.Contains("ASIO4ALL"))
             *     {
             *         if (!BassAsio.BASS_ASIO_IsStarted())
             *             BassAsio.BASS_ASIO_Init(n, BASSASIOInit.BASS_ASIO_DEFAULT);
             *
             *         samplerate = BassAsio.BASS_ASIO_GetRate();
             *         m_asiodevice = n;
             *
             *         BASS_ASIO_INFO asioinfo = BassAsio.BASS_ASIO_GetInfo();
             *         if (asioinfo != null)
             *         {
             *             // assuming stereo input
             *             for (int i = 0; i < asioinfo.inputs; i += 2)
             *             {
             *                 BASS_ASIO_CHANNELINFO chanInfo = BassAsio.BASS_ASIO_ChannelGetInfo(true, i);
             *                 if (chanInfo != null)
             *                     GetAsioInputChannels.Add(chanInfo);
             *
             *                 if (chanInfo.name.Contains("VB-Audio Point 1"))
             *                     GetVlcAsioInputChannel = i;
             *             }
             *
             *             for (int o = 0; o < asioinfo.outputs; o += 2)
             *             {
             *                 BASS_ASIO_CHANNELINFO chanInfo = BassAsio.BASS_ASIO_ChannelGetInfo(false, o);
             *                 if (chanInfo != null)
             *                     GetAsioOutputChannels.Add(chanInfo);
             *             }
             *         }
             *     }
             *
             * }
             *
             * CreateInputs(m_inputChannel);
             * CreateOutput(m_outputChannel);
             * Connect();
             * int ggg = 0;*/


            for (int n = 0; BassAsio.BASS_ASIO_GetDeviceInfo(n, devinfo); n++)
            {
                if (devinfo.name.Contains("ASIO4ALL"))
                {
                    if (!BassAsio.BASS_ASIO_IsStarted())
                    {
                        BassAsio.BASS_ASIO_Init(n, BASSASIOInit.BASS_ASIO_THREAD);
                    }

                    samplerate   = BassAsio.BASS_ASIO_GetRate();
                    m_asiodevice = n;

                    BASS_ASIO_INFO asioinfo = BassAsio.BASS_ASIO_GetInfo();
                    if (asioinfo != null)
                    {
                        // assuming stereo input
                        for (int i = 0; i < asioinfo.inputs; i += 2)
                        {
                            BASS_ASIO_CHANNELINFO chanInfo = BassAsio.BASS_ASIO_ChannelGetInfo(true, i);
                            if (chanInfo != null)
                            {
                                GetAsioInputChannels.Add(chanInfo);
                            }

                            if (chanInfo.name.Contains("VB-Audio Point 1"))
                            {
                                VlcAsioInputChannel = i;
                            }
                        }

                        for (int o = 0; o < asioinfo.outputs; o += 2)
                        {
                            BASS_ASIO_CHANNELINFO chanInfo = BassAsio.BASS_ASIO_ChannelGetInfo(false, o);
                            if (chanInfo != null)
                            {
                                AsioOutputChannels.Add(chanInfo);
                            }
                        }
                    }

                    BassAsio.BASS_ASIO_ChannelSetVolume(true, m_inputChannel, PlayerControl.MicVolumeScroll.Value * 0.01f);
                    BassAsio.BASS_ASIO_ChannelSetVolume(true, m_inputChannel + 1, PlayerControl.MicVolumeScroll.Value * 0.01f);

                    _asioProc = new ASIOPROC(AsioCallback);
                }
            }

            if (!m_bassinit)
            {
                Bass.BASS_SetConfig(BASSConfig.BASS_CONFIG_UPDATEPERIOD, 0);
                Bass.BASS_SetConfig(BASSConfig.BASS_CONFIG_FLOATDSP, true);
                Bass.BASS_Init(0, 48000, 0, IntPtr.Zero);

                Player.Mixer = MixerStreamCreate((int)samplerate);

                if (Player.Mixer == 0)
                {
                    var error = Bass.BASS_ErrorGetCode();
                    MessageBox.Show(error.ToString(), "Could not create mixer!");
                    Bass.BASS_Free();
                    return;
                }

                m_mixerChannel = Player.Mixer;

                m_streamInputMic = Bass.BASS_StreamCreatePush((int)samplerate, 2, BASSFlag.BASS_STREAM_DECODE | BASSFlag.BASS_SAMPLE_FLOAT, IntPtr.Zero);
                StreamInputVlc   = Bass.BASS_StreamCreatePush((int)samplerate, 2, BASSFlag.BASS_STREAM_DECODE | BASSFlag.BASS_SAMPLE_FLOAT, IntPtr.Zero);

                //m_streamInputMic = Bass.BASS_StreamCreateFile(f, 0L, 0L, BASSFlag.BASS_STREAM_DECODE | BASSFlag.BASS_SAMPLE_FLOAT | BASSFlag.BASS_SAMPLE_LOOP);
                //m_stream[0] = BassMix.BASS_Split_StreamCreate(m_streamInputMic, BASSFlag.BASS_SAMPLE_FLOAT | BASSFlag.BASS_STREAM_DECODE, null);//_instream;
                //m_stream[1] = BassMix.BASS_Split_StreamCreate(m_streamInputMic, BASSFlag.BASS_SAMPLE_FLOAT | BASSFlag.BASS_STREAM_DECODE, null);// _instream;
                //m_stream[2] = BassMix.BASS_Split_StreamCreate(m_streamInputMic, BASSFlag.BASS_SAMPLE_FLOAT | BASSFlag.BASS_STREAM_DECODE, null);//_instream;
                //m_stream[3] = BassMix.BASS_Split_StreamCreate(m_streamInputMic, BASSFlag.BASS_SAMPLE_FLOAT | BASSFlag.BASS_STREAM_DECODE, null);//_instream;


                //Group 1 VST Effects ============================================================
                Channel1Fx.SetEffects(m_streamInputMic);


                //Group 2 VST Effects ============================================================
                // Channel2Fx.SetEffects(m_stream[1]);


                //Group 3 VST Effects ============================================================
                // Channel3Fx.SetEffects(m_stream[2]);


                //Group 4 VST Effects ============================================================
                // Channel4Fx.SetEffects(m_stream[3]);

                BassMix.BASS_Mixer_StreamAddChannel(m_mixerChannel, StreamInputVlc, BASSFlag.BASS_MIXER_DOWNMIX | BASSFlag.BASS_STREAM_AUTOFREE);
                BassMix.BASS_Mixer_StreamAddChannel(m_mixerChannel, m_streamInputMic, BASSFlag.BASS_MIXER_DOWNMIX | BASSFlag.BASS_STREAM_AUTOFREE);
                // BassMix.BASS_Mixer_StreamAddChannel(m_mixerChannel, m_stream[1], BASSFlag.BASS_MIXER_DOWNMIX | BASSFlag.BASS_STREAM_AUTOFREE);
                //BassMix.BASS_Mixer_StreamAddChannel(m_mixerChannel, m_stream[2], BASSFlag.BASS_MIXER_DOWNMIX | BASSFlag.BASS_STREAM_AUTOFREE);
                //BassMix.BASS_Mixer_StreamAddChannel(m_mixerChannel, m_stream[3], BASSFlag.BASS_MIXER_DOWNMIX | BASSFlag.BASS_STREAM_AUTOFREE);
                BASS_CHANNELINFO info = Bass.BASS_ChannelGetInfo(m_mixerChannel);

                m_bassinit = true;
            }

            //BassAsio.BASS_ASIO_ControlPanel();
            BassAsio.BASS_ASIO_ChannelEnable(true, VlcAsioInputChannel, _asioProc, new IntPtr(StreamInputVlc));
            BassAsio.BASS_ASIO_ChannelJoin(true, VlcAsioInputChannel + 1, VlcAsioInputChannel);
            BassAsio.BASS_ASIO_ChannelSetFormat(true, VlcAsioInputChannel, BASSASIOFormat.BASS_ASIO_FORMAT_FLOAT);
            BassAsio.BASS_ASIO_ChannelSetRate(true, VlcAsioInputChannel, samplerate);
            BassAsio.BASS_ASIO_SetRate(samplerate);

            BassAsio.BASS_ASIO_ChannelEnable(true, m_inputChannel, _asioProc, new IntPtr(m_streamInputMic));
            BassAsio.BASS_ASIO_ChannelJoin(true, m_inputChannel + 1, m_inputChannel);
            BassAsio.BASS_ASIO_ChannelSetFormat(true, m_inputChannel, BASSASIOFormat.BASS_ASIO_FORMAT_FLOAT);
            BassAsio.BASS_ASIO_ChannelSetRate(true, m_inputChannel, samplerate);
            BassAsio.BASS_ASIO_SetRate(samplerate);

            BassAsio.BASS_ASIO_ChannelEnable(false, m_outputChannel, _asioProc, new IntPtr(m_mixerChannel));
            BassAsio.BASS_ASIO_ChannelJoin(false, m_outputChannel + 1, m_outputChannel);
            BassAsio.BASS_ASIO_ChannelSetFormat(false, m_outputChannel, BASSASIOFormat.BASS_ASIO_FORMAT_FLOAT);
            BassAsio.BASS_ASIO_ChannelSetRate(false, m_outputChannel, samplerate);
            BassAsio.BASS_ASIO_SetRate(samplerate);
        }
Ejemplo n.º 12
0
 public static extern bool BASS_ASIO_ChannelEnable([MarshalAs(UnmanagedType.Bool)] bool input, int channel, ASIOPROC proc, IntPtr user);