/// <summary> /// Sets the Bass inputstream and initializes the playbackbuffer. /// </summary> /// <param name="stream">New inputstream.</param> public void SetInputStream(BassStream stream) { ResetInputStream(); _inputStream = stream; // If a Mixer has been created before, e.g. because of UpDownMixing, // use the mixer as output stream instead of using a Ringbuffer if (stream.BassInfo.ctype == BASSChannelType.BASS_CTYPE_STREAM_MIXER) { _outputStream = stream; } else { _buffer = new AudioRingBuffer(stream.SampleRate, stream.Channels, _bufferSize); _streamEnded = false; _buffer.ResetPointers(); CreateOutputStream(); // Ensure prebuffering _updateThreadFinished.Reset(); StartBufferUpdateThread(); _updateThreadFinished.WaitOne(); } CreateVizStream(); _inputStreamInitialized = true; }
public void SetInputStream(BassStream stream, bool passThrough) { if (_deviceState != DeviceState.Stopped) { throw new BassPlayerException("Device state is not 'DeviceState.Stopped'"); } _inputStream = stream; Log.Debug("Creating output stream"); const BASSFlag flags = BASSFlag.BASS_SAMPLE_FLOAT; int handle = Bass.BASS_StreamCreate( _inputStream.SampleRate, _inputStream.Channels, flags, _streamWriteProcDelegate, IntPtr.Zero); if (handle == BassConstants.BassInvalidHandle) { throw new BassLibraryException("BASS_StreamCreate"); } _outputStream = BassStream.Create(handle); if (passThrough) { _fader = new BassStreamFader(_inputStream, Controller.GetSettings().FadeDuration); } ResetState(); }
/// <summary> /// Initializes a new instance. /// </summary> private void Initialize() { Log.Debug("BassMODFileInputSource.Initialize()"); const BASSFlag flags = BASSFlag.BASS_SAMPLE_SOFTWARE | BASSFlag.BASS_SAMPLE_FLOAT | BASSFlag.BASS_MUSIC_AUTOFREE | BASSFlag.BASS_MUSIC_PRESCAN; int handle; ILocalFsResourceAccessor lfra = _accessor as ILocalFsResourceAccessor; if (lfra == null) { // Build stream reading procs for the resource's input stream Stream inputStream = _accessor.OpenRead(); int length = (int)inputStream.Length; byte[] audioData = new byte[length]; inputStream.Read(audioData, 0, length); handle = Bass.BASS_MusicLoad(audioData, 0, length, flags, 0); } else { // Optimize access to local filesystem resource handle = Bass.BASS_MusicLoad(lfra.LocalFileSystemPath, 0, 0, flags, 0); } if (handle == BassConstants.BassInvalidHandle) { throw new BassLibraryException("BASS_MusicLoad"); } _bassStream = BassStream.Create(handle); }
/// <summary> /// Initializes a new instance. /// </summary> private void Initialize() { Log.Debug("BassAudioFileInputSource.Initialize()"); BASSFlag flags = BASSFlag.BASS_STREAM_DECODE | BASSFlag.BASS_SAMPLE_FLOAT; int handle; ILocalFsResourceAccessor lfra = _accessor as ILocalFsResourceAccessor; if (lfra == null) { // Build stream reading procs for the resource's input stream flags |= BASSFlag.BASS_STREAM_PRESCAN; _streamInput = new StreamInput(_accessor.OpenRead()); handle = Bass.BASS_StreamCreateFileUser( BASSStreamSystem.STREAMFILE_NOBUFFER, flags, _streamInput.FileProcs, IntPtr.Zero); } else { // Optimize access to local filesystem resource using (lfra.EnsureLocalFileSystemAccess()) handle = Bass.BASS_StreamCreateFile(lfra.LocalFileSystemPath, 0, 0, flags); } if (handle == BassConstants.BassInvalidHandle) { throw new BassLibraryException("BASS_StreamCreateFile"); } _BassStream = BassStream.Create(handle); }
/// <summary> /// Ends and discards this playback session. /// </summary> public void End(bool waitForFadeOut) { lock (_syncObj) { if (_state == SessionState.Reset) { return; } _state = SessionState.Reset; } _controller.OutputDeviceManager.StopDevice(waitForFadeOut); _controller.OutputDeviceManager.ResetInputStream(); _playbackBuffer.ResetInputStream(); _winAmpDSPProcessor.ResetInputStream(); _vstProcessor.ResetInputStream(); _upDownMixer.ResetInputStream(); lock (_syncObj) { _controller.ScheduleDisposeObject_Async(_outputStream); _outputStream = null; _controller.ScheduleDisposeObject_Async(_currentInputSource); _currentInputSource = null; } }
/// <summary> /// Sets the Bass inputstream. /// </summary> /// <param name="stream"></param> public void SetInputStream(BassStream stream) { ResetInputStream(); _inputStream = stream; _outputStream = stream; _initialized = true; }
public void Dispose() { Stop(); Log.Debug("Disposing output stream"); _outputStream.Dispose(); _outputStream = null; Log.Debug("Resetting global Bass environment"); if (!Bass.BASS_SetConfig(BASSConfig.BASS_CONFIG_UPDATEPERIOD, 0)) { throw new BassLibraryException("BASS_SetConfig"); } if (!Bass.BASS_SetDevice(_deviceNo)) { throw new BassLibraryException("BASS_SetDevice"); } if (!Bass.BASS_Free()) { throw new BassLibraryException("BASS_Free"); } if (!Bass.BASS_SetDevice(BassConstants.BassNoSoundDevice)) { throw new BassLibraryException("BASS_SetDevice"); } }
/// <summary> /// Sets the Bass inputstream. /// </summary> /// <param name="stream">The stream to be used as input stream.</param> public void SetInputStream(BassStream stream) { ResetInputStream(); _inputStream = stream; _outputStream = stream; CheckForUpDownMixing(); _initialized = true; }
public void Dispose() { if (_bassStream == null) { return; } _bassStream.Dispose(); _bassStream = null; }
/// <summary> /// Resets the instance to its uninitialized state. /// </summary> public void ResetInputStream() { if (_initialized) { _initialized = false; //_OutputStream.Dispose(); _outputStream = null; _inputStream = null; } }
/// <summary> /// Register the Stream Freed Event /// </summary> /// <returns></returns> private void RegisterStreamFreedEvent(BassStream stream) { int syncHandle = Bass.BASS_ChannelSetSync(stream.Handle, BASSSync.BASS_SYNC_FREE | BASSSync.BASS_SYNC_MIXTIME, 0, _onPlaybackEndDelegate, IntPtr.Zero); if (syncHandle == 0) { Log.Debug("BASS: RegisterStreamFreedEvent of stream {0} failed with error {1}", stream.Handle, Enum.GetName(typeof(BASSError), Bass.BASS_ErrorGetCode())); } else { stream.SyncProcHandles.Add(syncHandle); } }
/// <summary> /// Resets the instance to its uninitialized state. /// </summary> public void ResetInputStream() { if (_initialized) { _initialized = false; // Dispose has to be done if we have our own OutputStream //_OutputStream.Dispose(); _outputStream = null; _inputStream = null; _mixerStream = null; } }
/// <summary> /// Sets the Bass inputstream and initializes the outputdevice. /// </summary> /// <param name="stream">The stream delivering the input data for this output device.</param> /// <param name="passThrough">Sets the passthrough mode.</param> public void SetInputStream(BassStream stream, bool passThrough) { Log.Debug("OutputDeviceManager.SetInputStream()"); ResetInputStream(); Log.Debug("Instantiating output device"); _OutputDevice = _OutputDeviceFactory.CreateOutputDevice(); Log.Debug("Calling SetInputStream()"); _OutputDevice.SetInputStream(stream, passThrough); _Initialized = true; }
/// <summary> /// Creates the visualization Bass stream. /// </summary> private void CreateVizStream() { BASSFlag streamFlags = BASSFlag.BASS_STREAM_DECODE | BASSFlag.BASS_SAMPLE_FLOAT; int handle = Bass.BASS_StreamCreate( _inputStream.SampleRate, _inputStream.Channels, streamFlags, _vizRawStreamWriteProcDelegate, IntPtr.Zero); if (handle == BassConstants.BassInvalidHandle) { throw new BassLibraryException("BASS_StreamCreate"); } _vizRawStream = BassStream.Create(handle); // Todo: apply AGC streamFlags = BASSFlag.BASS_MIXER_NONSTOP | BASSFlag.BASS_SAMPLE_FLOAT | BASSFlag.BASS_STREAM_DECODE; handle = BassMix.BASS_Mixer_StreamCreate(_inputStream.SampleRate, 2, streamFlags); if (handle == BassConstants.BassInvalidHandle) { throw new BassLibraryException("BASS_StreamCreate"); } _vizStream = BassStream.Create(handle); streamFlags = BASSFlag.BASS_MIXER_NORAMPIN | BASSFlag.BASS_MIXER_DOWNMIX | BASSFlag.BASS_MIXER_MATRIX; if (!BassMix.BASS_Mixer_StreamAddChannel(_vizStream.Handle, _vizRawStream.Handle, streamFlags)) { throw new BassLibraryException("BASS_Mixer_StreamAddChannel"); } // TODO Albert 2010-02-27: What is this? if (_inputStream.Channels == 1) { float[,] mixMatrix = new float[2, 1]; mixMatrix[0, 0] = 1; mixMatrix[1, 0] = 1; if (!BassMix.BASS_Mixer_ChannelSetMatrix(_vizRawStream.Handle, mixMatrix)) { throw new BassLibraryException("BASS_Mixer_ChannelSetMatrix"); } } }
/// <summary> /// Blocks the current thread until our output device has finished and then calls /// <see cref="PlaybackProcessor.HandleOutputStreamEnded"/>. /// </summary> protected internal override void WaitAndHandleOutputEnd_Sync() { DateTime timeout = DateTime.Now + CurrentDeviceInfo.Latency + TimeSpan.FromSeconds(1); BassStream stream = _outputStream; if (stream != null) { while (Bass.BASS_ChannelIsActive(stream.Handle) != BASSActive.BASS_ACTIVE_STOPPED && DateTime.Now < timeout) { Thread.Sleep(10); } } base.WaitAndHandleOutputEnd_Sync(); }
/// <summary> /// Creates and initializes a new instance. /// </summary> /// <param name="controller">Reference to controller object.</param> public static PlaybackSession Create(Controller controller) { IInputSource inputSource = controller.PlaybackProcessor.GetAndClearNextInputSource(); if (inputSource == null) { return(null); } BassStream stream = inputSource.OutputStream; PlaybackSession playbackSession = new PlaybackSession(controller, stream.Channels, stream.SampleRate, stream.IsPassThrough); playbackSession.Initialize(inputSource); return(playbackSession); }
/// <summary> /// Initializes a new instance. /// </summary> private void Initialize() { Log.Debug("BassWebStreamInputSource.Initialize()"); const BASSFlag flags = BASSFlag.BASS_STREAM_DECODE | BASSFlag.BASS_SAMPLE_FLOAT; _handle = Bass.BASS_StreamCreateURL(_url, 0, flags, null, new IntPtr()); if (_handle == BassConstants.BassInvalidHandle) { throw new BassLibraryException("BASS_StreamCreateURL"); } _bassStream = BassStream.Create(_handle); }
/// <summary> /// Blocks the current thread until our output device has finished and then calls /// <see cref="PlaybackProcessor.HandleOutputStreamEnded"/>. /// </summary> internal void WaitAndHandleOutputEnd_Sync() { DateTime timeout = DateTime.Now + CurrentDeviceInfo.Latency + TimeSpan.FromSeconds(1); BassStream stream = _outputStream; if (stream != null) { while (Bass.BASS_ChannelIsActive(stream.Handle) != BASSActive.BASS_ACTIVE_STOPPED && DateTime.Now < timeout) { Thread.Sleep(10); } } if (_deviceState == DeviceState.Started) { _controller.PlaybackProcessor.HandleOutputStreamEnded(); } }
private void CreateOutputStream() { const BASSFlag flags = BASSFlag.BASS_SAMPLE_FLOAT | BASSFlag.BASS_STREAM_DECODE; int handle = Bass.BASS_StreamCreate( _inputStream.SampleRate, _inputStream.Channels, flags, _streamWriteProcDelegate, IntPtr.Zero); if (handle == BassConstants.BassInvalidHandle) { throw new BassLibraryException("BASS_StreamCreate"); } _outputStream = BassStream.Create(handle); }
public override void Dispose() { base.Dispose(); Log.Debug("Disposing mixer stream"); if (_mixer != null) { _mixer.Dispose(); _mixer = null; } Log.Debug("Resetting global Bass environment"); if (!Bass.BASS_SetConfig(BASSConfig.BASS_CONFIG_UPDATEPERIOD, 0)) throw new BassLibraryException("BASS_SetConfig"); if (!BassWasapi.BASS_WASAPI_Free()) throw new BassLibraryException("BASS_WASAPI_Free"); }
/// <summary> /// Sets the Bass inputstream and initializes the playbackbuffer. /// </summary> /// <param name="stream">New inputstream.</param> public void SetInputStream(BassStream stream) { ResetInputStream(); _inputStream = stream; _buffer = new AudioRingBuffer(stream.SampleRate, stream.Channels, _bufferSize); _streamEnded = false; _buffer.ResetPointers(); CreateOutputStream(); CreateVizStream(); _inputStreamInitialized = true; // Ensure prebuffering _updateThreadFinished.Reset(); StartBufferUpdateThread(); _updateThreadFinished.WaitOne(); }
protected bool Initialize(IInputSource inputSource) { if (_state != SessionState.Reset) { return(false); } if (!MatchesInputSource(inputSource)) { return(false); } _currentInputSource = inputSource; Log.Debug("PlaybackSession: Creating output stream"); const BASSFlag flags = BASSFlag.BASS_SAMPLE_FLOAT | BASSFlag.BASS_STREAM_DECODE; int handle = Bass.BASS_StreamCreate( _currentInputSource.OutputStream.SampleRate, _currentInputSource.OutputStream.Channels, flags, _streamWriteProcDelegate, IntPtr.Zero); if (handle == BassConstants.BassInvalidHandle) { throw new BassLibraryException("BASS_StreamCreate"); } _outputStream = BassStream.Create(handle); _state = SessionState.Initialized; _upDownMixer.SetInputStream(_outputStream); _vstProcessor.SetInputStream(_upDownMixer.OutputStream); _winAmpDSPProcessor.SetInputStream(_vstProcessor.OutputStream); _playbackBuffer.SetInputStream(_winAmpDSPProcessor.OutputStream); _controller.OutputDeviceManager.SetInputStream(_playbackBuffer.OutputStream, _outputStream.IsPassThrough); return(true); }
/// <summary> /// Resets the instance to its uninitialized state. /// </summary> public void ResetInputStream() { TerminateBufferUpdateThread(); if (_inputStreamInitialized) { _inputStreamInitialized = false; _outputStream.Dispose(); _outputStream = null; _vizStream.Dispose(); _vizStream = null; _vizRawStream.Dispose(); _vizRawStream = null; _buffer = null; _inputStream = null; _vizReadOffsetBytes = 0; } }
public bool SwitchTo(BassCDTrackInputSource other) { if (other.Drive != _drive) { return(false); } BassStream stream = _bassStream; if (stream != null && BassCd.BASS_CD_StreamSetTrack(stream.Handle, other.BassTrackNo)) { Log.Debug("BassCDTrackInputSource: Simply switched the current track to drive '{0}', track {1}", other.Drive, other.TrackNo); _trackNo = other._trackNo; _length = other._length; stream.UpdateLocalFields(); other.Dispose(); return(true); } Log.Debug("BassCDTrackInputSource: Could not simply switch the current track to drive '{0}', track {1}", other.Drive, other.TrackNo); return(false); }
/// <summary> /// Create a mixer to be used as Output stream. /// We currently need this in case of Up- or Downmixing /// </summary> private void CreateMixer(int channels) { _mixerHandle = BassMix.BASS_Mixer_StreamCreate(_inputStream.SampleRate, channels, MIXER_FLAGS); if (_mixerHandle == BassConstants.BassInvalidHandle) { throw new BassLibraryException("BASS_Mixer_StreamCreate"); } _mixerStream = BassStream.Create(_mixerHandle); // Now Attach the Input Stream to the mixer try { Bass.BASS_ChannelLock(_mixerHandle, true); bool result = BassMix.BASS_Mixer_StreamAddChannel(_mixerHandle, _inputStream.Handle, BASSFlag.BASS_MIXER_NORAMPIN | BASSFlag.BASS_MIXER_BUFFER | BASSFlag.BASS_MIXER_MATRIX | BASSFlag.BASS_MIXER_DOWNMIX | BASSFlag.BASS_STREAM_AUTOFREE ); if (!result) { throw new BassLibraryException("BASS_UpDownMix_StreamAddChannel"); } } finally { Bass.BASS_ChannelLock(_mixerHandle, false); } if (_mixingMatrix != null) { bool result = BassMix.BASS_Mixer_ChannelSetMatrix(_inputStream.Handle, _mixingMatrix); if (!result) { throw new BassLibraryException("BASS_UpDownMix_SetMixingMatrix"); } } }
/// <summary> /// Initializes a new instance. /// </summary> private void Initialize() { Log.Debug("BassCDTrackInputSource.Initialize()"); Bass.BASS_SetConfig(BASSConfig.BASS_CONFIG_CD_FREEOLD, false); const BASSFlag flags = BASSFlag.BASS_STREAM_DECODE | BASSFlag.BASS_SAMPLE_FLOAT; int bassDrive = BassUtils.Drive2BassID(_drive); int handle = BassCd.BASS_CD_StreamCreate(bassDrive, BassTrackNo, flags); if (handle == 0) { if (Bass.BASS_ErrorGetCode() == BASSError.BASS_ERROR_ALREADY) { // Drive is already playing - stream must be lazily initialized return; } throw new BassLibraryException("BASS_CD_StreamCreate"); } _bassStream = BassStream.Create(handle); }
public override void Dispose() { base.Dispose(); Log.Debug("Disposing mixer stream"); if (_mixer != null) { _mixer.Dispose(); _mixer = null; } Log.Debug("Resetting global Bass environment"); if (!Bass.BASS_SetConfig(BASSConfig.BASS_CONFIG_UPDATEPERIOD, 0)) { throw new BassLibraryException("BASS_SetConfig"); } if (!BassWasapi.BASS_WASAPI_Free()) { throw new BassLibraryException("BASS_WASAPI_Free"); } }
/// <summary> /// Ends and discards this playback session. /// </summary> public void End(bool waitForFadeOut) { lock (_syncObj) { if (_state == SessionState.Reset) return; _state = SessionState.Reset; } _controller.OutputDeviceManager.StopDevice(waitForFadeOut); _controller.OutputDeviceManager.ResetInputStream(); _playbackBuffer.ResetInputStream(); _winAmpDSPProcessor.ResetInputStream(); _vstProcessor.ResetInputStream(); _upDownMixer.ResetInputStream(); lock (_syncObj) { _controller.ScheduleDisposeObject_Async(_outputStream); _outputStream = null; _controller.ScheduleDisposeObject_Async(_currentInputSource); _currentInputSource = null; } }
/// <summary> /// Initializes a new instance. /// </summary> private void Initialize() { Log.Debug("BassWebStreamInputSource.Initialize()"); const BASSFlag flags = BASSFlag.BASS_STREAM_DECODE | BASSFlag.BASS_SAMPLE_FLOAT; _handle = Bass.BASS_StreamCreateURL(_url, 0, flags, null, new IntPtr()); if (_handle == BassConstants.BassInvalidHandle) throw new BassLibraryException("BASS_StreamCreateURL"); _bassStream = BassStream.Create(_handle); }
/// <summary> /// Sets the Bass inputstream and initializes the outputdevice. /// </summary> /// <param name="stream">The stream delivering the input data for this output device.</param> /// <param name="passThrough">Sets the passthrough mode.</param> public void SetInputStream(BassStream stream, bool passThrough) { Log.Debug("OutputDeviceManager.SetInputStream()"); ResetInputStream(); Log.Debug("Instantiating output device"); _outputDevice = _outputDeviceFactory.CreateOutputDevice(); Log.Debug("Calling SetInputStream()"); _outputDevice.SetInputStream(stream, passThrough); _initialized = true; }
public override void SetInputStream(BassStream stream, bool passThrough) { if (_deviceState != DeviceState.Stopped) throw new BassPlayerException("Device state is not 'DeviceState.Stopped'"); _inputStream = stream; _flags = BASSWASAPIInit.BASS_WASAPI_AUTOFORMAT | BASSWASAPIInit.BASS_WASAPI_BUFFER; // If Exclusive mode is used, check, if that would be supported, otherwise init in shared mode bool isExclusive = Controller.GetSettings().WASAPIExclusiveMode; if (isExclusive) { _flags |= BASSWASAPIInit.BASS_WASAPI_EXCLUSIVE; BASSWASAPIFormat wasapiFormat = BassWasapi.BASS_WASAPI_CheckFormat(_deviceNo, _inputStream.SampleRate, _inputStream.Channels, BASSWASAPIInit.BASS_WASAPI_EXCLUSIVE); if (wasapiFormat == BASSWASAPIFormat.BASS_WASAPI_FORMAT_UNKNOWN) { Log.Info("BASS: WASAPI exclusive mode not directly supported for samplerate of {0} and {1} channels", _inputStream.SampleRate, _inputStream.Channels); isExclusive = false; } } retry: if (!isExclusive) { Log.Debug("BASS: Init WASAPI shared mode with Event driven system enabled."); _flags &= ~BASSWASAPIInit.BASS_WASAPI_EXCLUSIVE; _flags |= BASSWASAPIInit.BASS_WASAPI_SHARED | BASSWASAPIInit.BASS_WASAPI_EVENT; } Log.Debug("BASS: Try to init WASAPI with a samplerate of {0} and {1} channels", _inputStream.SampleRate, _inputStream.Channels); bool result = BassWasapi.BASS_WASAPI_Init(_deviceNo, _inputStream.SampleRate, _inputStream.Channels, _flags, 0.5f, 0f, _streamWriteProcDelegate, IntPtr.Zero); BASSError? bassInitErrorCode = result ? null : new BASSError?(Bass.BASS_ErrorGetCode()); if (bassInitErrorCode.HasValue) { if (bassInitErrorCode.Value == BASSError.BASS_ERROR_ALREADY) { if (!BassWasapi.BASS_WASAPI_SetDevice(_deviceNo)) throw new BassLibraryException("BASS_WASAPI_SetDevice"); } else if (isExclusive) { // Allow one retry in shared mode Log.Warn("BASS: Failed to initialize WASAPI exclusive mode for samplerate of {0} and {1} channels. Trying fallback to shared mode.", _inputStream.SampleRate, _inputStream.Channels); isExclusive = false; goto retry; } else throw new BassLibraryException("BASS_WASAPI_Init"); } // If the GetDeviceNo() method returned BassConstants.BassDefaultDevice, we must request the actual device number // of the choosen default device _deviceNo = BassWasapi.BASS_WASAPI_GetDevice(); CollectDeviceInfo(_deviceNo); 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"); // For shared mode we require a mixer to change the sampling rates of input stream to device output stream. if (!wasapiInfo.IsExclusive) { // Recreate Mixer with new value Log.Debug("BASS: Creating new {0} channel mixer for frequency {1}", wasapiInfo.chans, wasapiInfo.freq); _mixerHandle = BassMix.BASS_Mixer_StreamCreate(wasapiInfo.freq, wasapiInfo.chans, MIXER_FLAGS); if (_mixerHandle == BassConstants.BassInvalidHandle) throw new BassLibraryException("BASS_Mixer_StreamCreate"); _mixer = BassStream.Create(_mixerHandle); AttachStream(); } int ms = Convert.ToInt32(Controller.GetSettings().DirectSoundBufferSize.TotalMilliseconds); if (!Bass.BASS_SetConfig(BASSConfig.BASS_CONFIG_BUFFER, ms)) throw new BassLibraryException("BASS_SetConfig"); // Enable update thread while the output device is active if (!Bass.BASS_SetConfig(BASSConfig.BASS_CONFIG_UPDATEPERIOD, ms / 4)) throw new BassLibraryException("BASS_SetConfig"); if (passThrough) _fader = new BassStreamFader(_inputStream, Controller.GetSettings().FadeDuration); ResetState(); }
/// <summary> /// Sets the Bass inputstream and initializes the playbackbuffer. /// </summary> /// <param name="stream">New inputstream.</param> public void SetInputStream(BassStream stream) { ResetInputStream(); _inputStream = stream; UpdateVizLatencyCorrection(); _buffer = new AudioRingBuffer(stream.SampleRate, stream.Channels, _bufferSize + _vizReadOffset); _streamEnded = false; _buffer.ResetPointers(); CreateOutputStream(); CreateVizStream(); _inputStreamInitialized = true; // Ensure prebuffering _updateThreadFinished.Reset(); StartBufferUpdateThread(); _updateThreadFinished.WaitOne(); }
/// <summary> /// Resets the instance to its uninitialized state. /// </summary> public void ResetInputStream() { if (_Initialized) { _Initialized = false; // Dispose has to be done if we have our own OutputStream //_OutputStream.Dispose(); _OutputStream = null; _InputStream = null; } }
/// <summary> /// Initializes a new instance. /// </summary> private void Initialize() { Log.Debug("BassAudioFileInputSource.Initialize()"); BASSFlag flags = BASSFlag.BASS_STREAM_DECODE | BASSFlag.BASS_SAMPLE_FLOAT; int handle; ILocalFsResourceAccessor lfra = _accessor as ILocalFsResourceAccessor; if (lfra == null) { // Build stream reading procs for the resource's input stream flags |= BASSFlag.BASS_STREAM_PRESCAN; _streamInput = new StreamInput(_accessor.OpenRead()); handle = Bass.BASS_StreamCreateFileUser( BASSStreamSystem.STREAMFILE_NOBUFFER, flags, _streamInput.FileProcs, IntPtr.Zero); } else // Optimize access to local filesystem resource using (lfra.EnsureLocalFileSystemAccess()) handle = Bass.BASS_StreamCreateFile(lfra.LocalFileSystemPath, 0, 0, flags); if (handle == BassConstants.BassInvalidHandle) throw new BassLibraryException("BASS_StreamCreateFile"); _BassStream = BassStream.Create(handle); }
public void Dispose() { if (_BassStream == null) return; _BassStream.Dispose(); _BassStream = null; }
/// <summary> /// Initializes a new instance. /// </summary> private void Initialize() { Log.Debug("BassCDTrackInputSource.Initialize()"); Bass.BASS_SetConfig(BASSConfig.BASS_CONFIG_CD_FREEOLD, false); const BASSFlag flags = BASSFlag.BASS_STREAM_DECODE | BASSFlag.BASS_SAMPLE_FLOAT; int bassDrive = BassUtils.Drive2BassID(_drive); int handle = BassCd.BASS_CD_StreamCreate(bassDrive, BassTrackNo, flags); if (handle == 0) { if (Bass.BASS_ErrorGetCode() == BASSError.BASS_ERROR_ALREADY) // Drive is already playing - stream must be lazily initialized return; throw new BassLibraryException("BASS_CD_StreamCreate"); } _BassStream = BassStream.Create(handle); }
private void CreateOutputStream() { const BASSFlag flags = BASSFlag.BASS_SAMPLE_FLOAT | BASSFlag.BASS_STREAM_DECODE; int handle = Bass.BASS_StreamCreate( _inputStream.SampleRate, _inputStream.Channels, flags, _streamWriteProcDelegate, IntPtr.Zero); if (handle == BassConstants.BassInvalidHandle) throw new BassLibraryException("BASS_StreamCreate"); _outputStream = BassStream.Create(handle); }
/// <summary> /// Creates the visualization Bass stream. /// </summary> private void CreateVizStream() { BASSFlag streamFlags = BASSFlag.BASS_STREAM_DECODE | BASSFlag.BASS_SAMPLE_FLOAT; int handle = Bass.BASS_StreamCreate( _inputStream.SampleRate, _inputStream.Channels, streamFlags, _vizRawStreamWriteProcDelegate, IntPtr.Zero); if (handle == BassConstants.BassInvalidHandle) throw new BassLibraryException("BASS_StreamCreate"); _vizRawStream = BassStream.Create(handle); // Todo: apply AGC streamFlags = BASSFlag.BASS_MIXER_NONSTOP | BASSFlag.BASS_SAMPLE_FLOAT | BASSFlag.BASS_STREAM_DECODE; handle = BassMix.BASS_Mixer_StreamCreate(_inputStream.SampleRate, 2, streamFlags); if (handle == BassConstants.BassInvalidHandle) throw new BassLibraryException("BASS_StreamCreate"); _vizStream = BassStream.Create(handle); streamFlags = BASSFlag.BASS_MIXER_NORAMPIN | BASSFlag.BASS_MIXER_DOWNMIX | BASSFlag.BASS_MIXER_MATRIX; if (!BassMix.BASS_Mixer_StreamAddChannel(_vizStream.Handle, _vizRawStream.Handle, streamFlags)) throw new BassLibraryException("BASS_Mixer_StreamAddChannel"); // TODO Albert 2010-02-27: What is this? if (_inputStream.Channels == 1) { float[,] mixMatrix = new float[2, 1]; mixMatrix[0, 0] = 1; mixMatrix[1, 0] = 1; if (!BassMix.BASS_Mixer_ChannelSetMatrix(_vizRawStream.Handle, mixMatrix)) throw new BassLibraryException("BASS_Mixer_ChannelSetMatrix"); } }
/// <summary> /// Register the Stream Freed Event /// </summary> /// <returns></returns> private void RegisterStreamFreedEvent(BassStream stream) { int syncHandle = Bass.BASS_ChannelSetSync(stream.Handle, BASSSync.BASS_SYNC_FREE | BASSSync.BASS_SYNC_MIXTIME, 0, _onPlaybackEndDelegate, IntPtr.Zero); if (syncHandle == 0) Log.Debug("BASS: RegisterStreamFreedEvent of stream {0} failed with error {1}", stream.Handle, Enum.GetName(typeof(BASSError), Bass.BASS_ErrorGetCode())); else stream.SyncProcHandles.Add(syncHandle); }
public void SetInputStream(BassStream stream, bool passThrough) { if (_deviceState != DeviceState.Stopped) throw new BassPlayerException("Device state is not 'DeviceState.Stopped'"); _inputStream = stream; Log.Debug("Creating output stream"); const BASSFlag flags = BASSFlag.BASS_SAMPLE_FLOAT; int handle = Bass.BASS_StreamCreate( _inputStream.SampleRate, _inputStream.Channels, flags, _streamWriteProcDelegate, IntPtr.Zero); if (handle == BassConstants.BassInvalidHandle) throw new BassLibraryException("BASS_StreamCreate"); _outputStream = BassStream.Create(handle); if (passThrough) _fader = new BassStreamFader(_inputStream, Controller.GetSettings().FadeDuration); ResetState(); }
public BassStreamFader(BassStream stream, TimeSpan duration) { _stream = stream; _duration = duration; _durationMS = Convert.ToInt32(duration.TotalMilliseconds); }
public void Dispose() { Stop(); Log.Debug("Disposing output stream"); _outputStream.Dispose(); _outputStream = null; Log.Debug("Resetting global Bass environment"); if (!Bass.BASS_SetConfig(BASSConfig.BASS_CONFIG_UPDATEPERIOD, 0)) throw new BassLibraryException("BASS_SetConfig"); if (!Bass.BASS_SetDevice(_deviceNo)) throw new BassLibraryException("BASS_SetDevice"); if (!Bass.BASS_Free()) throw new BassLibraryException("BASS_Free"); if (!Bass.BASS_SetDevice(BassConstants.BassNoSoundDevice)) throw new BassLibraryException("BASS_SetDevice"); }
public abstract void SetInputStream(BassStream stream, bool passThrough);
/// <summary> /// Callback function for the outputstream. /// </summary> /// <param name="streamHandle">Bass stream handle that requests sample data.</param> /// <param name="buffer">Buffer to write the sampledata to.</param> /// <param name="requestedBytes">Requested number of bytes.</param> /// <param name="userData"></param> /// <returns>Number of bytes read.</returns> private int OutputStreamWriteProc(int streamHandle, IntPtr buffer, int requestedBytes, IntPtr userData) { IInputSource inputSource; lock (_syncObj) { if (_state == SessionState.Reset) { return(0); } inputSource = _currentInputSource; if (inputSource == null) { _state = SessionState.Ended; return((int)BASSStreamProc.BASS_STREAMPROC_END); } } try { BassStream stream = inputSource.OutputStream; int read = stream.Read(buffer, requestedBytes); bool doCheckNextInputSource = false; lock (_syncObj) if (!_isAwaitingNextInputSource && stream.GetPosition() > stream.Length.Subtract(REQUEST_NEXT_ITEM_THRESHOLD)) { // Near end of the stream - make sure that next input source is available _isAwaitingNextInputSource = true; doCheckNextInputSource = true; } if (doCheckNextInputSource) { _playbackProcessor.CheckInputSourceAvailable(); } if (read > 0) { // Normal case, we have finished return(read); } // Old buffer ran out of samples - either we can get another valid input source below or we are finished. End wait state. _isAwaitingNextInputSource = false; // Nothing could be read from old input source. Second try: Next input source. IInputSource newInputSource = _playbackProcessor.PeekNextInputSource(); // Special treatment for CD drives: If the new input source is from the same audio CD drive, we must take the stream over BassCDTrackInputSource bcdtisOld = inputSource as BassCDTrackInputSource; BassCDTrackInputSource bcdtisNew = newInputSource as BassCDTrackInputSource; if (bcdtisOld != null && bcdtisNew != null) { if (bcdtisOld.SwitchTo(bcdtisNew)) { _playbackProcessor.ClearNextInputSource(); return(OutputStreamWriteProc(streamHandle, buffer, requestedBytes, userData)); } } lock (_syncObj) { _currentInputSource = null; _controller.ScheduleDisposeObject_Async(inputSource); if (newInputSource == null) { _state = SessionState.Ended; return((int)BASSStreamProc.BASS_STREAMPROC_END); } } if (!MatchesInputSource(newInputSource)) { // The next available input source is not compatible, so end our stream. The playback processor will start a new playback session later. lock (_syncObj) _state = SessionState.Ended; return((int)BASSStreamProc.BASS_STREAMPROC_END); } _playbackProcessor.ClearNextInputSource(); // Should be the contents of newInputSource lock (_syncObj) { _currentInputSource = newInputSource; _state = SessionState.Playing; } // Next try return(OutputStreamWriteProc(streamHandle, buffer, requestedBytes, userData)); } catch (Exception) { // We might come here due to a race condition. To avoid that, we would have to employ a new manual locking mechanism // to avoid that during the execution of this method, no methods are called from outside which change our // streams/partner instances. return(0); } }
protected bool Initialize(IInputSource inputSource) { if (_state != SessionState.Reset) return false; if (!MatchesInputSource(inputSource)) return false; _currentInputSource = inputSource; Log.Debug("PlaybackSession: Creating output stream"); const BASSFlag flags = BASSFlag.BASS_SAMPLE_FLOAT | BASSFlag.BASS_STREAM_DECODE; int handle = Bass.BASS_StreamCreate( _currentInputSource.OutputStream.SampleRate, _currentInputSource.OutputStream.Channels, flags, _streamWriteProcDelegate, IntPtr.Zero); if (handle == BassConstants.BassInvalidHandle) throw new BassLibraryException("BASS_StreamCreate"); _outputStream = BassStream.Create(handle); _state = SessionState.Initialized; _upDownMixer.SetInputStream(_outputStream); _vstProcessor.SetInputStream(_upDownMixer.OutputStream); _winAmpDSPProcessor.SetInputStream(_vstProcessor.OutputStream); _playbackBuffer.SetInputStream(_winAmpDSPProcessor.OutputStream); _controller.OutputDeviceManager.SetInputStream(_playbackBuffer.OutputStream, _outputStream.IsPassThrough); return true; }
public override void SetInputStream(BassStream stream, bool passThrough) { if (_deviceState != DeviceState.Stopped) { throw new BassPlayerException("Device state is not 'DeviceState.Stopped'"); } _inputStream = stream; _flags = BASSWASAPIInit.BASS_WASAPI_AUTOFORMAT | BASSWASAPIInit.BASS_WASAPI_BUFFER; // If Exclusive mode is used, check, if that would be supported, otherwise init in shared mode bool isExclusive = Controller.GetSettings().WASAPIExclusiveMode; if (isExclusive) { _flags |= BASSWASAPIInit.BASS_WASAPI_EXCLUSIVE; BASSWASAPIFormat wasapiFormat = BassWasapi.BASS_WASAPI_CheckFormat(_deviceNo, _inputStream.SampleRate, _inputStream.Channels, BASSWASAPIInit.BASS_WASAPI_EXCLUSIVE); if (wasapiFormat == BASSWASAPIFormat.BASS_WASAPI_FORMAT_UNKNOWN) { Log.Info("BASS: WASAPI exclusive mode not directly supported for samplerate of {0} and {1} channels", _inputStream.SampleRate, _inputStream.Channels); isExclusive = false; } } retry: if (!isExclusive) { Log.Debug("BASS: Init WASAPI shared mode with Event driven system enabled."); _flags &= ~BASSWASAPIInit.BASS_WASAPI_EXCLUSIVE; _flags |= BASSWASAPIInit.BASS_WASAPI_SHARED | BASSWASAPIInit.BASS_WASAPI_EVENT; } Log.Debug("BASS: Try to init WASAPI with a samplerate of {0} and {1} channels", _inputStream.SampleRate, _inputStream.Channels); bool result = BassWasapi.BASS_WASAPI_Init(_deviceNo, _inputStream.SampleRate, _inputStream.Channels, _flags, 0.5f, 0f, _streamWriteProcDelegate, IntPtr.Zero); BASSError?bassInitErrorCode = result ? null : new BASSError?(Bass.BASS_ErrorGetCode()); if (bassInitErrorCode.HasValue) { if (bassInitErrorCode.Value == BASSError.BASS_ERROR_ALREADY) { if (!BassWasapi.BASS_WASAPI_SetDevice(_deviceNo)) { throw new BassLibraryException("BASS_WASAPI_SetDevice"); } } else if (isExclusive) { // Allow one retry in shared mode Log.Warn("BASS: Failed to initialize WASAPI exclusive mode for samplerate of {0} and {1} channels. Trying fallback to shared mode.", _inputStream.SampleRate, _inputStream.Channels); isExclusive = false; goto retry; } else { throw new BassLibraryException("BASS_WASAPI_Init"); } } // If the GetDeviceNo() method returned BassConstants.BassDefaultDevice, we must request the actual device number // of the choosen default device _deviceNo = BassWasapi.BASS_WASAPI_GetDevice(); CollectDeviceInfo(_deviceNo); 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"); // For shared mode we require a mixer to change the sampling rates of input stream to device output stream. if (!wasapiInfo.IsExclusive) { // Recreate Mixer with new value Log.Debug("BASS: Creating new {0} channel mixer for frequency {1}", wasapiInfo.chans, wasapiInfo.freq); _mixerHandle = BassMix.BASS_Mixer_StreamCreate(wasapiInfo.freq, wasapiInfo.chans, MIXER_FLAGS); if (_mixerHandle == BassConstants.BassInvalidHandle) { throw new BassLibraryException("BASS_Mixer_StreamCreate"); } _mixer = BassStream.Create(_mixerHandle); AttachStream(); } int ms = Convert.ToInt32(Controller.GetSettings().DirectSoundBufferSize.TotalMilliseconds); if (!Bass.BASS_SetConfig(BASSConfig.BASS_CONFIG_BUFFER, ms)) { throw new BassLibraryException("BASS_SetConfig"); } // Enable update thread while the output device is active if (!Bass.BASS_SetConfig(BASSConfig.BASS_CONFIG_UPDATEPERIOD, ms / 4)) { throw new BassLibraryException("BASS_SetConfig"); } if (passThrough) { _fader = new BassStreamFader(_inputStream, Controller.GetSettings().FadeDuration); } ResetState(); }
/// <summary> /// Initializes a new instance. /// </summary> private void Initialize() { Log.Debug("BassMODFileInputSource.Initialize()"); const BASSFlag flags = BASSFlag.BASS_SAMPLE_SOFTWARE | BASSFlag.BASS_SAMPLE_FLOAT | BASSFlag.BASS_MUSIC_AUTOFREE | BASSFlag.BASS_MUSIC_PRESCAN; int handle; ILocalFsResourceAccessor lfra = _accessor as ILocalFsResourceAccessor; if (lfra == null) { // Build stream reading procs for the resource's input stream Stream inputStream = _accessor.OpenRead(); int length = (int) inputStream.Length; byte[] audioData = new byte[length]; inputStream.Read(audioData, 0, length); handle = Bass.BASS_MusicLoad(audioData, 0, length, flags, 0); } else // Optimize access to local filesystem resource handle = Bass.BASS_MusicLoad(lfra.LocalFileSystemPath, 0, 0, flags, 0); if (handle == BassConstants.BassInvalidHandle) throw new BassLibraryException("BASS_MusicLoad"); _bassStream = BassStream.Create(handle); }
/// <summary> /// Create a sample stream from a WMA Bass stream. /// </summary> /// <param name="bassStream">The Bass stream.</param> /// <param name="configs">Configure of <see cref="WmaStream" />.</param> /// <param name="systemType">File system to use.</param> public WmaStream(BassStream bassStream, WmaStreamCreateConfig configs, StreamFileSystemType systemType) : this(bassStream.StreamHandlers, configs, systemType, IntPtr.Zero) { }