Example #1
0
 private void DisposeDecodingChannel()
 {
     if (_decodingChannel != null)
     {
         _decodingChannel.Stop();
         _decodingChannel.Free();
         _decodingChannel = null;
     }
 }
Example #2
0
 private void CreateDecodingChannel(string audioFilePath)
 {
     _decodingChannel = Channel.CreateFileStreamForDecoding(audioFilePath, _useFloatingPoint);
     _currentFilePath = audioFilePath;
     _channelLength = _decodingChannel.GetLength();
     _decodePosition = 0;
     lock (_locker)
     {
         Monitor.Pulse(_locker);
     }
 }
Example #3
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;
            }
        }
Example #4
0
        /// <summary>
        /// Frees the device currently used for playback.
        /// </summary>
        public void FreeDevice()
        {
            if (!_isDeviceInitialized)
                return;

#if !IOS && !ANDROID

            // Check driver type
            if (_device.DriverType == DriverType.ASIO)
            {
                // Free ASIO device
                if (!BassAsio.BASS_ASIO_Free())
                {
                    // Get error
                    BASSError error = Bass.BASS_ErrorGetCode();
                    throw new Exception("Error freeing ASIO device: " + error.ToString());
                }
            }
            else if (_device.DriverType == DriverType.WASAPI)
            {
                // Free WASAPI device
                if (!BassWasapi.BASS_WASAPI_Free())
                {
                    // Get error
                    BASSError error = Bass.BASS_ErrorGetCode();
                    throw new Exception("Error freeing WASAPI device: " + error.ToString());
                }
            }
#endif

            Base.Free();
            _mixerChannel = null;
            _device = null;
            _isDeviceInitialized = false;
        }
Example #5
0
        /// <summary>
        /// Disposes the current channel.
        /// </summary>
        public void Dispose()
        {
            #if !PCL && !WINDOWSSTORE && !WINDOWS_PHONE

            // Check if a channel already exists
            if (_channel != null)
            {
                try
                {
                    // Stop and free channel
                    Console.WriteLine("Freeing channel " + AudioFile.FilePath + "...");
                    _channel.Stop();
                    _channel.Free();
                    _channel = null;
                }
                catch(Exception ex)
                {
                    if(_audioFile != null)
                        Console.WriteLine("Could not dispose channel " + AudioFile.FilePath + ": " + ex.Message);
                }

//                // Check if the channel is in use
//                if (channel.IsActive() == BASSActive.BASS_ACTIVE_PLAYING)
//                {
//                    // Stop and free channel                    
//                    channel.Stop();
//                    channel.Free();
//                    channel = null;
//                }                
            }

            #endif

            _isLoaded = false;
        }       
Example #6
0
        /// <summary>
        /// Loads the current channel and audio file metadata.
        /// </summary>
        public void Load(bool useFloatingPoint)
        {
            // Load audio file metadata
            _audioFile.RefreshMetadata();

            #if !PCL && !WINDOWSSTORE && !WINDOWS_PHONE

            // Check if a channel already exists
            if(_channel != null)
                Dispose();

            // Load channel
            _channel = Channel.CreateFileStreamForDecoding(_audioFile.FilePath, useFloatingPoint);
            _lengthBytes = _channel.GetLength();

            // Divide length by 2 if using floating point
            if (_channel.IsFloatingPoint)
                _lengthBytes /= 2;

            // Check if this is a FLAC file over 44100Hz
            if (_audioFile.FileType == AudioFileFormat.FLAC && _audioFile.SampleRate > 44100)
                _lengthBytes = (long)((float)_lengthBytes * 1.5f);

            _lengthSamples = ConvertAudio.ToPCM(_lengthBytes, (uint)_audioFile.BitsPerSample, 2);
            _lengthMilliseconds = (int)ConvertAudio.ToMS(_lengthSamples, (uint)_audioFile.SampleRate);
            _lengthString = Conversion.MillisecondsToTimeString((ulong)_lengthMilliseconds);

            #endif

            _isLoaded = true;
        }