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); }
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(); } } } }
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); }
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)); }
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)); }
/// <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); }
internal HolofunkBassAsio(HolofunkBass bass) { m_bass = bass; m_outputAsioProcAverageLatency = new FloatAverager(20); m_outputAsioProcStopwatch = new Stopwatch(); m_mixerToOutputAsioProc = new ASIOPROC(MixerToOutputAsioProc); }
/// <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; } }
/// <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 }
/// <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; }
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); }
public static extern bool BASS_ASIO_ChannelEnable([MarshalAs(UnmanagedType.Bool)] bool input, int channel, ASIOPROC proc, IntPtr user);