/// <summary>
        /// Register the Stream Freed Event
        /// </summary>
        /// <param name="stream"></param>
        /// <returns></returns>
        private int RegisterStreamFreedEvent(int stream)
        {
            int syncHandle = 0;

            syncHandle = Bass.BASS_ChannelSetSync(stream,
                                                  BASSSync.BASS_SYNC_FREE | BASSSync.BASS_SYNC_MIXTIME,
                                                  0, _streamFreedDelegate,
                                                  IntPtr.Zero);

            if (syncHandle == 0)
            {
                Log.Debug("BASS: RegisterStreamFreedEvent of stream {0} failed with error {1}", stream,
                          Enum.GetName(typeof(BASSError), Bass.BASS_ErrorGetCode()));
            }
            return(syncHandle);
        }
示例#2
0
        private void PlayInternal(string path, double offset, double volume, double speed)
        {
            Queue <int> freelist;

            lock (handles)
            {
                if (!handles.ContainsKey(path))
                {
                    throw new InvalidOperationException("sound source was not registered.");
                }
                freelist = handles[path];
            }

            int handle;

            lock (freelist)
            {
                if (freelist.Count > 0)
                {
                    handle = freelist.Dequeue();
                }
                else
                {
                    handle = GetHandle(path);

                    var proc = new SYNCPROC((h, channel, data, user) =>
                    {
                        lock (freelist) freelist.Enqueue(handle);
                    });

                    int syncHandle;
                    syncHandle = Bass.BASS_ChannelSetSync(handle, BASSSync.BASS_SYNC_END, 0, proc, IntPtr.Zero);
                    if (syncHandle == 0)
                    {
                        throw new InvalidOperationException("cannot set sync");
                    }
                    lock (syncProcs) syncProcs.Add(proc); // avoid GC
                }
            }

            lock (playing) playing.Add(handle);
            Bass.BASS_ChannelSetPosition(handle, offset);
            Bass.BASS_ChannelSetAttribute(handle, BASSAttribute.BASS_ATTRIB_VOL, (float)volume);
            Bass.BASS_ChannelSetAttribute(handle, BASSAttribute.BASS_ATTRIB_TEMPO, (float)((speed - 1.0) * 100));
            Bass.BASS_ChannelPlay(handle, false);
        }
示例#3
0
        public SoundEffectInstance(int bassHandle, bool loop, int loopstart, int loopend)
        {
            handle = bassHandle;                                                                  // Store the handle
            Bass.BASS_ChannelGetAttribute(handle, BASSAttribute.BASS_ATTRIB_FREQ, ref baseSRate); // Store the original sample rate (for pitch bending)
            var sz = Bass.BASS_ChannelGetLength(handle);

            if (loopend > sz | (loopend - loopstart) < 3000) // Hax until i figure out wtf is going on with looping.
            {
                loopend = (int)sz;
            }
            //Console.WriteLine("{0} {1}", loopstart, loopend);
            if (loop)                                                                                                                                                      // If we loop
            {
                syncHandle = Bass.BASS_ChannelSetSync(handle, BASSSync.BASS_SYNC_POS | BASSSync.BASS_SYNC_MIXTIME, loopend, Engine.globalLoopProc, new IntPtr(loopstart)); // Set the global loop proc to take place at the loop end position, then return to the start.
            }
            looping = loop;                                                                                                                                                // Loopyes
        }
        /// <summary>
        ///   Register the Playback end Event
        /// </summary>
        private int RegisterPlaybackEndEvent()
        {
            int syncHandle = 0;

            syncHandle = Bass.BASS_ChannelSetSync(_stream,
                                                  BASSSync.BASS_SYNC_END,
                                                  0, PlaybackEndProcDelegate,
                                                  IntPtr.Zero);

            if (syncHandle == 0)
            {
                int error = (int)Bass.BASS_ErrorGetCode();
                log.Error("Player: RegisterPlaybackEndEvent of stream {0} failed with error {1}", _stream, error);
            }

            return(syncHandle);
        }
示例#5
0
        /// <summary>
        /// Called when a stream has been created. This actually starts the playback of the stream.
        /// </summary>
        /// <param name="track">The track that is to be played.</param>
        /// <param name="stream">The BASS.NET stream pointer to play.</param>
        protected virtual void StreamCreated(IAudioItem track, int stream)
        {
            // Init mixer
            if (_mixer == -1)
            {
                _mixer = BassMix.BASS_Mixer_StreamCreate(44100, 6, BASSFlag.BASS_MIXER_END);

                // Set playback done callback on mixer
                _channelEndCallback = new SYNCPROC(ChannelEnd);
                Bass.BASS_ChannelSetSync(_mixer, BASSSync.BASS_SYNC_END | BASSSync.BASS_SYNC_MIXTIME, 0, _channelEndCallback, IntPtr.Zero);
            }

            // Load streamin mixer
            bool ok = BassMix.BASS_Mixer_StreamAddChannel(_mixer, stream, BASSFlag.BASS_STREAM_AUTOFREE | BASSFlag.BASS_MIXER_MATRIX);

            if (!ok)
            {
                Log(Bass.BASS_ErrorGetCode().ToString(), Logger.LogLevel.Error);
            }

            // Set matrix
            SetMatrix(stream);

            // Remove current channel from mixer
            if (_currentStream != -1)
            {
                BassMix.BASS_Mixer_ChannelRemove(_currentStream);
                Bass.BASS_StreamFree(_currentStream);
            }

            //
            if (track is IWebcast)
            {
                SYNCPROC _mySync = new SYNCPROC(MetaSync);
                Bass.BASS_ChannelSetSync(_currentStream, BASSSync.BASS_SYNC_META, 0, _mySync, IntPtr.Zero);
            }

            // Play it!
            Bass.BASS_ChannelSetPosition(_mixer, 0);
            Bass.BASS_Start();
            Bass.BASS_ChannelPlay(_mixer, false);

            // Set current stuff
            _currentStream = stream;
        }
示例#6
0
 public void StopFile(int handle, bool fadeOut, int fadeOutTime, bool isCrossFade)
 {
     if (!fadeOut || fadeOutTime == 0)
     {
         Bass.BASS_ChannelStop(handle); // no error handling, unimportant
         FileFinished(handle, true);
     }
     else
     {
         long pos           = Bass.BASS_ChannelGetPosition(handle);
         long length        = Bass.BASS_ChannelGetLength(handle);
         long remaining     = length - pos;
         long fadeOutLength = Bass.BASS_ChannelSeconds2Bytes(handle, 0.001 * fadeOutTime);
         if (fadeOutLength == -1)
         {
             // on error, just stop the file
             Bass.BASS_ChannelStop(handle);
             FileFinished(handle, true);
             return;
         }
         if (pos == -1 || length == -1 || remaining <= 0)
         {
             // web radio doesn't have a length
             remaining = fadeOutLength;
         }
         if (fadeOutLength > remaining)
         {
             fadeOutLength = remaining;
         }
         // if (Bass.BASS_ChannelSetSync(handle, BASSSync.BASS_SYNC_POS, pos + fadeOutLength, m_StopSync, new IntPtr(0)) == 0)
         if (Bass.BASS_ChannelSetSync(handle, BASSSync.BASS_SYNC_SLIDE | BASSSync.BASS_SYNC_ONETIME, 0, m_StopSync, new IntPtr(handle)) == 0)
         {
             // on error, just stop the file
             Bass.BASS_ChannelStop(handle);
             FileFinished(handle, true);
             return;
         }
         FadeOut(handle, fadeOutTime);
         if (isCrossFade)
         {
             // call finished immediately to start the next file
             FileFinished(handle, false);
         }
     }
 }
示例#7
0
        public async Task OpenFile(string fileName)
        {
            _openningStream = fileName;
            Stop();
            await Task.Run(() =>
            {
                if (ActiveStreamHandle != 0)
                {
                    ChannelPosition = 0;
                    Bass.BASS_StreamFree(ActiveStreamHandle);
                }

                if (File.Exists(fileName))
                {
                    ActiveStreamHandle = Bass.BASS_StreamCreateFile(fileName, 0, 0, openFileConfig);
                    if (ActiveStreamHandle != 0)
                    {
                        ChannelLength = Bass.BASS_ChannelBytes2Seconds(ActiveStreamHandle, Bass.BASS_ChannelGetLength(ActiveStreamHandle, 0));

                        //Obtain the sample rate of the sstream
                        var info = new BASS_CHANNELINFO();
                        Bass.BASS_ChannelGetInfo(ActiveStreamHandle, info);
                        sampleFrequency = info.freq;

                        // Set the stream to call Stop() when it ends.
                        int syncHandle = Bass.BASS_ChannelSetSync(ActiveStreamHandle,
                                                                  BASSSync.BASS_SYNC_END,
                                                                  0,
                                                                  endTrackSyncProc,
                                                                  IntPtr.Zero);

                        if (syncHandle == 0)
                        {
                            throw new ArgumentException("Error establishing End Sync on file stream.", "path");
                        }

                        CanPlay = true;
                    }
                    else
                    {
                        Debug.WriteLine($"Failed to open file: {fileName},Error Code: {Bass.BASS_ErrorGetCode()}");
                    }
                }
            });
        }
示例#8
0
        // callback that handles end of measure
        private void LoopEnd(int handle, int c, int data, IntPtr user)
        {
            // switch to random measure if not on hold
            if (!form.GetHold(nr))
            {
                measure = random.Next(0, length + 1);
                form.SetTrackbar(nr, measure);

                // set end pos callback
                Bass.BASS_ChannelRemoveSync(channel, synchandle);
                synchandle = Bass.BASS_ChannelSetSync(channel, BASSSync.BASS_SYNC_POS | BASSSync.BASS_SYNC_MIXTIME, MeasuresToBytes(measure + 1), sync, IntPtr.Zero);
            }

            // move to start point
            Bass.BASS_ChannelSetPosition(channel, MeasuresToBytes(measure), BASSMode.BASS_POS_BYTE);

            //Console.WriteLine("Channel: " + channel + " Measure: " + measure);
        }
示例#9
0
        public async Task OpenUrl(string url)
        {
            _openningStream = url;
            Stop();
            await Task.Run(() =>
            {
                int handle = Bass.BASS_StreamCreateURL(url, 0, openUrlConfig, null, IntPtr.Zero);
                if (handle != 0)
                {
                    if (_openningStream == url)
                    {
                        ActiveStreamHandle = handle;
                        ChannelLength      = Bass.BASS_ChannelBytes2Seconds(ActiveStreamHandle, Bass.BASS_ChannelGetLength(ActiveStreamHandle));
                        var info           = new BASS_CHANNELINFO();
                        Bass.BASS_ChannelGetInfo(ActiveStreamHandle, info);
                        sampleFrequency = info.freq;

                        int syncHandle = Bass.BASS_ChannelSetSync(ActiveStreamHandle,
                                                                  BASSSync.BASS_SYNC_END,
                                                                  0,
                                                                  endTrackSyncProc,
                                                                  IntPtr.Zero);

                        if (syncHandle == 0)
                        {
                            throw new ArgumentException("Error establishing End Sync on file stream.", "url");
                        }

                        CanPlay = true;
                    }
                    else
                    {
                        if (!Un4seen.Bass.Bass.BASS_StreamFree(handle))
                        {
                            Debug.WriteLine("BASS_StreamFree() Failed:" + Un4seen.Bass.Bass.BASS_ErrorGetCode());
                        }
                    }
                }
                else
                {
                    Debug.WriteLine($"Failed to open URL: {url}, Error Code: {Bass.BASS_ErrorGetCode()}");
                }
            });
        }
示例#10
0
        private void PlayInternal(string path, TimeSpan offset)
        {
            Queue <int> freelist;

            lock (handles)
            {
                if (!handles.ContainsKey(path))
                {
                    throw new InvalidOperationException("sound source was not registered.");
                }
                freelist = handles[path];
            }

            int handle;

            lock (freelist)
            {
                if (freelist.Count > 0)
                {
                    handle = freelist.Dequeue();
                }
                else
                {
                    handle = GetHandle(path);

                    var proc = new SYNCPROC((h, channel, data, user) =>
                    {
                        lock (freelist) freelist.Enqueue(handle);
                    });

                    int syncHandle;
                    syncHandle = Bass.BASS_ChannelSetSync(handle, BASSSync.BASS_SYNC_END, 0, proc, IntPtr.Zero);
                    if (syncHandle == 0)
                    {
                        throw new InvalidOperationException("cannot set sync");
                    }
                    lock (syncProcs) syncProcs.Add(proc); // avoid GC
                }
            }

            lock (playing) playing.Add(handle);
            Bass.BASS_ChannelSetPosition(handle, offset.TotalSeconds);
            Bass.BASS_ChannelPlay(handle, false);
        }
示例#11
0
        public void PlaySound(string filename)
        {
            Bass.BASS_StreamFree(stream);
            syncCallback = new SYNCPROC(OnSongFinished);
            BASSActive isActive = default(BASSActive);

            isActive = Bass.BASS_ChannelIsActive(stream);
            if (isActive == BASSActive.BASS_ACTIVE_PLAYING)
            {
                Bass.BASS_ChannelStop(stream);
            }
            stream = Bass.BASS_StreamCreateURL(filename, 0, 0, null, IntPtr.Zero);
            Bass.BASS_ChannelSetAttribute(stream, BASSAttribute.BASS_ATTRIB_VOL, tbVolume.Value / 100F);
            Bass.BASS_ChannelSetSync(stream, BASSSync.BASS_SYNC_END, 0, syncCallback, IntPtr.Zero);
            //Bass.BASS_Init(deviceIndex, 44100, BASSInit.BASS_DEVICE_DEFAULT, IntPtr.Zero);
            Bass.BASS_SetDevice(deviceIndex);
            Bass.BASS_ChannelSetDevice(stream, deviceIndex);
            Bass.BASS_ChannelPlay(stream, false);
        }
示例#12
0
        /// <summary>
        /// Register the Fade out Event
        /// </summary>
        /// <param name="stream"></param>
        /// <returns></returns>
        private int RegisterCrossFadeEvent(int stream)
        {
            int    syncHandle     = 0;
            double fadeOutSeconds = Config.CrossFadeIntervalMs / 1000.0;

            long bytePos = Bass.BASS_ChannelSeconds2Bytes(stream, TotalStreamSeconds - fadeOutSeconds);

            syncHandle = Bass.BASS_ChannelSetSync(stream,
                                                  BASSSync.BASS_SYNC_POS,
                                                  bytePos, _playbackCrossFadeProcDelegate,
                                                  IntPtr.Zero);

            if (syncHandle == 0)
            {
                Log.Debug("BASS: RegisterCrossFadeEvent of stream {0} failed with error {1}", stream,
                          Enum.GetName(typeof(BASSError), Bass.BASS_ErrorGetCode()));
            }
            return(syncHandle);
        }
示例#13
0
        public Sync(ChannelHandle channelHandle, BASSSync syncType, Action <int, int, int, IntPtr> sync)
        {
            ChannelHandle = channelHandle;

            if (!ChannelHandle.Valid)
            {
                throw new ArgumentException("Invalid handle provided for sync.");
            }

            SyncType       = syncType;
            _syncProcedure = new SYNCPROC(sync);

            Handle = Bass.BASS_ChannelSetSync(ChannelHandle.Handle, syncType, 0, _syncProcedure, IntPtr.Zero);

            if (!Valid)
            {
                throw new Exception($"Couldn't set sync procedure for channel handle {ChannelHandle.Handle.ToString("X8")}, file name {ChannelHandle.FileName}.");
            }
        }
示例#14
0
        /// <summary>
        /// Sets a SyncPos on the mixer stream
        /// </summary>
        /// <param name="stream"></param>
        /// <param name="timePos"></param>
        public void SetSyncPos(MusicStream stream, double timePos)
        {
            double fadeOutSeconds = Config.CrossFadeIntervalMs / 1000.0;
            double totalStreamLen = Bass.BASS_ChannelBytes2Seconds(stream.BassStream, Bass.BASS_ChannelGetLength(stream.BassStream, BASSMode.BASS_POS_BYTES));
            long   mixerPos       = Bass.BASS_ChannelGetPosition(_mixer, BASSMode.BASS_POS_BYTES | BASSMode.BASS_POS_DECODE);
            long   syncPos        = mixerPos + Bass.BASS_ChannelSeconds2Bytes(_mixer, totalStreamLen - timePos - fadeOutSeconds);

            if (_syncProc != 0)
            {
                Bass.BASS_ChannelRemoveSync(_mixer, _syncProc);
            }

            GCHandle pFilePath = GCHandle.Alloc(stream);

            _syncProc = Bass.BASS_ChannelSetSync(_mixer,
                                                 BASSSync.BASS_SYNC_ONETIME | BASSSync.BASS_SYNC_POS | BASSSync.BASS_SYNC_MIXTIME,
                                                 syncPos, _playbackEndProcDelegate,
                                                 GCHandle.ToIntPtr(pFilePath));
        }
示例#15
0
        public void ChangeSpeed(float newValue)
        {
            speed = newValue;
            if (lysnc != 0)
            {
                Bass.BASS_ChannelRemoveSync(chan, lysnc);
            }

            chan = bass.ChangeSpeed(chan, SelectedSong.FilePath, newValue);

            if (lysnc != 0)
            {
                lysnc = Bass.BASS_ChannelSetSync(chan, BASSSync.BASS_SYNC_POS, endPos, LoopSync, (IntPtr)0);
            }

            if (this.PlayPause == "Pause")
            {
                Bass.BASS_ChannelPlay(chan, false);
            }
        }
示例#16
0
        private async Task PlayFileAsync(int currentIndex)
        {
            Bass.BASS_StreamFree(stream);
            try
            {
                var streamInfoSet = await client.GetVideoMediaStreamInfosAsync(videos[currentIndex].Id);

                var streamInfo = streamInfoSet.Muxed.WithHighestVideoQuality();
                syncCallback = new SYNCPROC(OnSongFinished);
                stream       = Bass.BASS_StreamCreateURL(streamInfo.Url, 0, 0, null, IntPtr.Zero);
                Bass.BASS_ChannelSetAttribute(stream, BASSAttribute.BASS_ATTRIB_VOL, tbVolume.Value / 100f);
                Bass.BASS_ChannelSetSync(stream, BASSSync.BASS_SYNC_END, 0, syncCallback, IntPtr.Zero);
                Bass.BASS_ChannelPlay(stream, false);
                tmSeek.Enabled = true;
            }
            catch (YoutubeExplode.Exceptions.VideoUnplayableException ex)
            {
                MessageBox.Show($"Видео не может быть воспроизведено, {ex.Message}", "Ошибка");
                return;
            }
        }
示例#17
0
 public void  playSong(int number, double position = 0)
 {
     playlist.config.currState = "play";
     if (playlist.config.playlist.Count > 0)
     {
         playlist.config.currPlay = number;
         string file = playlist.config.playlist[playlist.config.currPlay].Path;
         Console.WriteLine(file);
         Stream = Bass.BASS_StreamCreateFile(file, 0, 0, BASSFlag.BASS_DEFAULT);
         if (Stream != 0)
         {
             setPosition(position);
             Bass.BASS_ChannelPlay(stream, false);
         }
         else
         {
             Console.WriteLine("Stream error: {0}", Bass.BASS_ErrorGetCode());
         }
         handleSynchronizationEndStream = Bass.BASS_ChannelSetSync(Stream, BASSSync.BASS_SYNC_END, 0, syncProcEndStream, IntPtr.Zero);
     }
 }
示例#18
0
        static TrackViewModel BuildNetTags()
        {
            var t = new TrackViewModel();

            // get the meta tags (manually - will not work for WMA streams here)
            string[] icy = Bass.BASS_ChannelGetTagsICY(Player.Instance.Wave.Handle);
            if (icy == null)
            {
                // try http...
                icy = Bass.BASS_ChannelGetTagsHTTP(Player.Instance.Wave.Handle);
            }
            if (icy != null)
            {
                t.Title   = icy.Where(c => c.Contains("icy-name:")).First().Replace("icy-name:", "");
                t.Bitrate = Convert.ToUInt32(icy.Where(c => c.Contains("icy-br:")).First().Replace("icy-br:", ""));
            }

            _tagInfo = new TAG_INFO(Player.Instance.Wave.Path);
            t.Path   = Player.Instance.Wave.Path;
            if (BassTags.BASS_TAG_GetFromURL(Player.Instance.Wave.Handle, _tagInfo))
            {
                // and display what we get
                t.Album  = _tagInfo.album;
                t.Artist = _tagInfo.artist;
                if (!String.IsNullOrEmpty(_tagInfo.title))
                {
                    t.Title = _tagInfo.title;
                }

                t.Genre = _tagInfo.genre;

                if (t.Bitrate == 0)
                {
                    t.Bitrate = (uint)_tagInfo.bitrate;
                }
            }
            mySync = new SYNCPROC(MetaSync);
            Bass.BASS_ChannelSetSync(Player.Instance.Wave.Handle, BASSSync.BASS_SYNC_META, 0, mySync, IntPtr.Zero);
            return(t);
        }
示例#19
0
        public static void Play(string file, bool loadOnly)
        {
            Stop();
            baseStreamHandle = Bass.BASS_StreamCreateFile(file, 0, 0, BASSFlag.BASS_STREAM_DECODE);
            BASS_CHANNELINFO info = Bass.BASS_ChannelGetInfo(baseStreamHandle);

            mixStreamHandle = BassMix.BASS_Mixer_StreamCreate(info.freq, info.chans, BASSFlag.BASS_STREAM_DECODE);
            BassMix.BASS_Mixer_StreamAddChannel(mixStreamHandle, baseStreamHandle, BASSFlag.BASS_MIXER_MATRIX);
            streamHandle = BassFx.BASS_FX_TempoCreate(mixStreamHandle, BASSFlag.BASS_FX_FREESOURCE);
            Mono         = mono;
            Speed        = speed;
            if (!loadOnly)
            {
                Bass.BASS_ChannelPlay(streamHandle, false);
            }
            BASSError er = Bass.BASS_ErrorGetCode();

            syncProc = new SYNCPROC(AudioEnded);
            Bass.BASS_ChannelSetSync(streamHandle, BASSSync.BASS_SYNC_END, 0, syncProc, IntPtr.Zero);
            Playing    = !loadOnly;
            FileLoaded = true;
        }
示例#20
0
        public void Play(int volume)
        {
            Stop();
            if (InitBass(HZ))
            {
                Stream = Bass.BASS_StreamCreateURL(URL, 0, BASSFlag.BASS_DEFAULT, null, IntPtr.Zero);

                tagInfo = new TAG_INFO(URL);

                if (BassTags.BASS_TAG_GetFromURL(Stream, tagInfo))
                {
                    UpdatePlayList();
                }

                mySync = new SYNCPROC(MetaSync);
                Bass.BASS_ChannelSetSync(Stream, BASSSync.BASS_SYNC_META, 0, mySync, IntPtr.Zero);

                Bass.BASS_ChannelPlay(Stream, false);
                //Установка громкости
                Bass.BASS_ChannelSetAttribute(Stream, BASSAttribute.BASS_ATTRIB_VOL, volume / 100f);
            }
        }
 private void Play_B_Click(object sender, System.Windows.RoutedEventArgs e)
 {
     if (IsClosing)
     {
         return;
     }
     if (Sound_List.SelectedIndex == -1)
     {
         return;
     }
     else if (!File.Exists(Voice_Set.Special_Path + "/Wwise/Temp_02.ogg"))
     {
         Message_Feed_Out("サウンドファイルが変換されませんでした。");
         return;
     }
     if (SelectIndex == Sound_List.SelectedIndex)
     {
         Bass.BASS_ChannelPlay(Stream, false);
     }
     else
     {
         Bass.BASS_ChannelStop(Stream);
         Location_S.Value = 0;
         Bass.BASS_StreamFree(Stream);
         int StreamHandle = Bass.BASS_StreamCreateFile(Voice_Set.Special_Path + "/Wwise/Temp_02.wav", 0, 0, BASSFlag.BASS_SAMPLE_FLOAT | BASSFlag.BASS_STREAM_DECODE | BASSFlag.BASS_SAMPLE_LOOP);
         Stream     = BassFx.BASS_FX_TempoCreate(StreamHandle, BASSFlag.BASS_FX_FREESOURCE);
         IsMusicEnd = new SYNCPROC(EndSync);
         Bass.BASS_ChannelSetDevice(Stream, Video_Mode.Sound_Device);
         Bass.BASS_ChannelSetSync(Stream, BASSSync.BASS_SYNC_END | BASSSync.BASS_SYNC_MIXTIME, 0, IsMusicEnd, IntPtr.Zero);
         Bass.BASS_ChannelPlay(Stream, true);
         Bass.BASS_ChannelSetAttribute(Stream, BASSAttribute.BASS_ATTRIB_VOL, (float)Volume_S.Value / 100);
         Bass.BASS_ChannelGetAttribute(Stream, BASSAttribute.BASS_ATTRIB_TEMPO_FREQ, ref SetFirstFreq);
         Bass.BASS_ChannelSetAttribute(Stream, BASSAttribute.BASS_ATTRIB_TEMPO_FREQ, SetFirstFreq + (float)Speed_S.Value);
         SelectIndex        = Sound_List.SelectedIndex;
         Location_S.Maximum = Bass.BASS_ChannelBytes2Seconds(Stream, Bass.BASS_ChannelGetLength(Stream, BASSMode.BASS_POS_BYTES));
         Speed_T.Text       = "速度:" + (SetFirstFreq + Math.Floor(Speed_S.Value));
     }
     IsPaused = false;
 }
示例#22
0
        private void SetRepeatRange(TimeSpan startTime, TimeSpan endTime)
        {
            if (repeatSyncId != 0)
            {
                Bass.BASS_ChannelRemoveSync(ActiveStreamHandle, repeatSyncId);
            }

            if ((endTime - startTime) > TimeSpan.FromMilliseconds(repeatThreshold))
            {
                long channelLength = Bass.BASS_ChannelGetLength(ActiveStreamHandle);
                long endPosition   = (long)((endTime.TotalSeconds / ChannelLength) * channelLength);
                repeatSyncId = Bass.BASS_ChannelSetSync(ActiveStreamHandle,
                                                        BASSSync.BASS_SYNC_POS,
                                                        (long)endPosition,
                                                        repeatSyncProc,
                                                        IntPtr.Zero);
                ChannelPosition = SelectionBegin.TotalSeconds;
            }
            else
            {
                ClearRepeatRange();
            }
        }
示例#23
0
        public void Loop(Preset preset)
        {
            this.Pause();

            startPos = Bass.BASS_ChannelSeconds2Bytes(chan, preset.Begin);
            endPos   = Bass.BASS_ChannelSeconds2Bytes(chan, preset.End);

            LoopSync = new SYNCPROC(ProcSync);
            if (lysnc != 0)
            {
                Bass.BASS_ChannelRemoveSync(chan, lysnc);
            }

            lysnc = Bass.BASS_ChannelSetSync(chan, BASSSync.BASS_SYNC_POS, endPos, LoopSync, (IntPtr)0);

            long curPos = Bass.BASS_ChannelGetPosition(chan);

            if (curPos < startPos || curPos >= endPos)
            {
                Bass.BASS_ChannelSetPosition(chan, startPos, BASSMode.BASS_POS_BYTES);
            }

            this.Play();
        }
示例#24
0
        protected override void OnLoopEndUpdated()
        {
            if (this.BassHandle.HasValue)
            {
                if (loopSyncHandle > 0)
                {
                    Bass.BASS_ChannelRemoveSync(this.BassHandle.Value, loopSyncHandle);
                    _mySyncProc = null;
                }

                _mySyncProc = new SYNCPROC(LoopEndReached);

                long end;
                if (this.LoopEnd == 0)
                {
                    end = Bass.BASS_ChannelSeconds2Bytes(this.BassHandle.Value, this.Length);
                }
                else
                {
                    end = Bass.BASS_ChannelSeconds2Bytes(this.BassHandle.Value, this.LoopEnd);
                }
                loopSyncHandle = Bass.BASS_ChannelSetSync(this.BassHandle.Value, BASSSync.BASS_SYNC_POS | BASSSync.BASS_SYNC_MIXTIME, end, _mySyncProc, IntPtr.Zero);
            }
        }
示例#25
0
        private void AudioToSpeaker(byte[] buffer, int offset, int length)
        {
            // Write compressed audio data to Circulairbuffer
            lock (lockObject)
            {
                cbbListenAudio.Write(buffer, offset, length);
                // When not listening to audio clear buffer up to 16 kb
                if (listenHandle == 0)
                {
                    // Purge circulair buffer
                    // we only keep 16 kb in memory
                    while (cbbListenAudio.UsedBytes > (16 * 1024))
                    {
                        byte[] dummyBuffer = new byte[1024];
                        cbbListenAudio.Read(dummyBuffer, 1024);
                    } //while
                }
            }

            if (!listen && listenHandle == 0)
            {
                return;
            }

            // Geluid wordt uitgezet
            if (!listen && listenHandle != 0)
            {
                Bass.BASS_ChannelStop(listenHandle);
                Bass.BASS_StreamFree(listenHandle);
                listenHandle = 0;
                return;
            }

            // Geluid wordt aangezet
            if (listen && listenHandle == 0 && cbbListenAudio.UsedBytes >= 8000)
            {
                // bass needs for mp3 atleast 4000 bytes before is can play
                listenHandle = Bass.BASS_StreamCreateFileUser(BASSStreamSystem.STREAMFILE_BUFFERPUSH, BASSFlag.BASS_DEFAULT, bassFileProcsOut, GCHandle.ToIntPtr((GCHandle)gcHandle));
                Bass.BASS_ChannelSetSync(listenHandle, BASSSync.BASS_SYNC_STALL, 0, bassStalledSync, GCHandle.ToIntPtr((GCHandle)gcHandle));
                Bass.BASS_ChannelSetSync(listenHandle, BASSSync.BASS_SYNC_END, 0, bassEndSync, GCHandle.ToIntPtr((GCHandle)gcHandle));
                Bass.BASS_ChannelPlay(listenHandle, false);
            }

            // push new audiodata when available (and basstream is opened)
            if (listenHandle != 0)
            {
                // voed bass met audio data zodat deze het naar pcm data kan decompressen
                long bassBufLen = Bass.BASS_StreamGetFilePosition(listenHandle, BASSStreamFilePosition.BASS_FILEPOS_END);
                long bassBufPos = Bass.BASS_StreamGetFilePosition(listenHandle, BASSStreamFilePosition.BASS_FILEPOS_BUFFER);
                int  todo       = Convert.ToInt32(bassBufLen - bassBufPos);
                if (todo > 0)
                {
                    int count      = todo;
                    int writeBytes = 0;
                    while (!cbbListenAudio.IsEmpty && todo > 0 && writeBytes > -1)
                    {
                        if (count > 16384)
                        {
                            count = 16384;
                        }
                        byte[] tmpBuffer = new byte[count];
                        lock (lockObject)
                        {
                            count = cbbListenAudio.Read(tmpBuffer, count);
                        }
                        if (count > 0)
                        {
                            writeBytes = Bass.BASS_StreamPutFileData(listenHandle, tmpBuffer, count);
                            todo      -= writeBytes;
                        }
                    } //while audio buffer not empty
                }
            }
        }
示例#26
0
        private void ProcessStreamData(byte[] buffer, int offset, int length)
        {
            if (length < 1)
            {
                return;
            }

            // Write compressed audio data to Circulairbuffer
            byte[] data = new byte[length];
            Buffer.BlockCopy(buffer, offset, data, 0, length);
            lock (lockObject)
            {
                cbbChunkAudio.Write(buffer, offset, length);
            }


            // If basshandle wasn't opened then open it now (when there is enough data. Min 4010 bytes)
            if (inputHandle == 0 && cbbChunkAudio.UsedBytes >= 8000)
            {
                // bass needs for mp3 atleast 4000 bytes before is can play
                inputHandle = Bass.BASS_StreamCreateFileUser(BASSStreamSystem.STREAMFILE_BUFFERPUSH, BASSFlag.BASS_STREAM_DECODE | BASSFlag.BASS_SAMPLE_FLOAT, bassFileProcs, GCHandle.ToIntPtr((GCHandle)gcHandle));
                Bass.BASS_ChannelSetSync(inputHandle, BASSSync.BASS_SYNC_STALL, 0, bassStalledSync, GCHandle.ToIntPtr((GCHandle)gcHandle));
                Bass.BASS_ChannelSetSync(inputHandle, BASSSync.BASS_SYNC_END, 0, bassEndSync, GCHandle.ToIntPtr((GCHandle)gcHandle));

                mixerHandle = BassMix.BASS_Mixer_StreamCreate(44100, 2, BASSFlag.BASS_STREAM_DECODE | BASSFlag.BASS_SAMPLE_FLOAT);
                BassMix.BASS_Mixer_StreamAddChannel(mixerHandle, inputHandle, BASSFlag.BASS_MIXER_FILTER | BASSFlag.BASS_MIXER_DOWNMIX);
                Bass.BASS_ChannelPlay(inputHandle, false);
                Bass.BASS_ChannelPlay(mixerHandle, false);
                return;
            }

            // push new audiodata when available (and basstream is opened)
            if (inputHandle != 0)
            {
                // voed bass met audio data zodat deze het naar pcm data kan decompressen
                long bassBufLen = Bass.BASS_StreamGetFilePosition(inputHandle, BASSStreamFilePosition.BASS_FILEPOS_END);
                long bassBufPos = Bass.BASS_StreamGetFilePosition(inputHandle, BASSStreamFilePosition.BASS_FILEPOS_BUFFER);
                int  todo       = Convert.ToInt32(bassBufLen - bassBufPos);
                if (todo > 0)
                {
                    int count      = todo;
                    int writeBytes = 0;
                    while (!cbbChunkAudio.IsEmpty && todo > 0 && writeBytes > -1)
                    {
                        if (count > 16384)
                        {
                            count = 16384;
                        }
                        byte[] tmpBuffer = new byte[count];
                        lock (lockObject)
                        {
                            count = cbbChunkAudio.Read(tmpBuffer, count);
                        }
                        if (count > 0)
                        {
                            writeBytes = Bass.BASS_StreamPutFileData(inputHandle, tmpBuffer, count);
                            todo      -= writeBytes;
                        }
                    } //while audio buffer not empty
                }
                ProcessDecompressedData();
            }
        }
示例#27
0
        private void OpenMIDIButton_Click(object sender, EventArgs e)
        {
            if (OpenMIDI.ShowDialog() == DialogResult.OK)
            {
                Bass.BASS_StreamFree(chan);

                if (!IsWinXPOrOlder())
                {
                    BassWasapi.BASS_WASAPI_Free();
                    WasapiProc = new WASAPIPROC(MyWasapiProc);
                    BassWasapi.BASS_WASAPI_Init(-1, 0, 2, BASSWASAPIInit.BASS_WASAPI_BUFFER | BASSWASAPIInit.BASS_WASAPI_SHARED, 0.5f, 0, WasapiProc, IntPtr.Zero);
                }

                LoopSyncProc  = null;
                LyricSyncProc = null;
                EndSyncProc   = null;
                TempoSyncProc = null;

                LyricsFromStream.Text = "";

                if ((chan = BassMidi.BASS_MIDI_StreamCreateFile(OpenMIDI.FileName, 0L, 0L,
                                                                (IsWinXPOrOlder() ? BASSFlag.BASS_DEFAULT : (BASSFlag.BASS_STREAM_DECODE | BASSFlag.BASS_SAMPLE_FLOAT)) | BASSFlag.BASS_MIDI_DECAYEND | (RvAndChr.Checked ? BASSFlag.BASS_MIDI_NOFX : 0),
                                                                0)) == 0)
                {
                    OpenMIDIButton.Text = "Click here to open a file...";
                    MIDITitle.Text      = "";
                    Position.Text       = "-";
                    Error("Can't play the file");
                    return;
                }

                Bass.BASS_ChannelSetAttribute(chan, BASSAttribute.BASS_ATTRIB_MIDI_VOICES, VoiceBar.Value); // apply to current MIDI file too
                Bass.BASS_ChannelSetAttribute(chan, BASSAttribute.BASS_ATTRIB_MIDI_CPU, CPUBar.Value);      // apply to current MIDI file too
                OpenMIDIButton.Text = OpenMIDI.FileName;
                {                                                                                           // set the title (track name of first track)
                    BASS_MIDI_MARK mark = new BASS_MIDI_MARK();
                    if (BassMidi.BASS_MIDI_StreamGetMark(chan, BASSMIDIMarker.BASS_MIDI_MARK_TRACK, 0, mark) && mark.track == 0)
                    {
                        MIDITitle.Text = mark.text;
                    }
                    else
                    {
                        MIDITitle.Text = "";
                    }
                }
                TrackbarStream.Value   = 0;
                TrackbarStream.Minimum = 0;
                TrackbarStream.Maximum = (int)Bass.BASS_ChannelGetLength(chan, BASSMode.BASS_POS_MIDI_TICK) / 120;
                { // set looping syncs
                    BASS_MIDI_MARK mark = new BASS_MIDI_MARK();
                    LoopSyncProc = new SYNCPROC(LoopSync);
                    if (FindMarker(chan, "loopend", mark))                                                                                        // found a loop end point
                    {
                        Bass.BASS_ChannelSetSync(chan, BASSSync.BASS_SYNC_POS | BASSSync.BASS_SYNC_MIXTIME, mark.pos, LoopSyncProc, IntPtr.Zero); // set a sync there
                    }
                    Bass.BASS_ChannelSetSync(chan, BASSSync.BASS_SYNC_END | BASSSync.BASS_SYNC_MIXTIME, 0, LoopSyncProc, IntPtr.Zero);            // set one at the end too (eg. in case of seeking past the loop point)
                }
                {                                                                                                                                 // clear lyrics buffer and set lyrics syncs
                    BASS_MIDI_MARK mark = new BASS_MIDI_MARK();
                    LyricSyncProc = new SYNCPROC(LyricSync);
                    EndSyncProc   = new SYNCPROC(EndSync);
                    lyrics        = "";
                    if (BassMidi.BASS_MIDI_StreamGetMark(chan, BASSMIDIMarker.BASS_MIDI_MARK_LYRIC, 0, mark)) // got lyrics
                    {
                        Bass.BASS_ChannelSetSync(chan, BASSSync.BASS_SYNC_MIDI_MARKER, (long)BASSMIDIMarker.BASS_MIDI_MARK_LYRIC, LyricSyncProc, (IntPtr)BASSMIDIMarker.BASS_MIDI_MARK_LYRIC);
                    }
                    else if (BassMidi.BASS_MIDI_StreamGetMark(chan, BASSMIDIMarker.BASS_MIDI_MARK_TEXT, 20, mark)) // got text instead (over 20 of them)
                    {
                        Bass.BASS_ChannelSetSync(chan, BASSSync.BASS_SYNC_MIDI_MARKER, (long)BASSMIDIMarker.BASS_MIDI_MARK_TEXT, LyricSyncProc, (IntPtr)BASSMIDIMarker.BASS_MIDI_MARK_TEXT);
                    }
                    Bass.BASS_ChannelSetSync(chan, BASSSync.BASS_SYNC_END, 0, EndSyncProc, IntPtr.Zero);
                }
                { // override the initial tempo, and set a sync to override tempo events and another to override after seeking
                    SetTempo(true);
                    TempoSyncProc = new SYNCPROC(TempoSync);
                    Bass.BASS_ChannelSetSync(chan, BASSSync.BASS_SYNC_MIDI_EVENT | BASSSync.BASS_SYNC_MIXTIME, (long)BASSMIDIEvent.MIDI_EVENT_TEMPO, TempoSyncProc, IntPtr.Zero);
                    Bass.BASS_ChannelSetSync(chan, BASSSync.BASS_SYNC_SETPOS | BASSSync.BASS_SYNC_MIXTIME, 0, TempoSyncProc, IntPtr.Zero);
                }
                { // get default soundfont in case of matching soundfont being used
                    BASS_MIDI_FONT[] sf = { new BASS_MIDI_FONT(font, fontp, fontb) };
                    // now set them
                    BassMidi.BASS_MIDI_StreamSetFonts(chan, sf, sf.Length);
                }
            }
            Bass.BASS_ChannelSetAttribute(chan, BASSAttribute.BASS_ATTRIB_MIDI_CPU, 95);
            if (PlayPauseBtn.Text != "Pause")
            {
                if (IsWinXPOrOlder())
                {
                    Bass.BASS_ChannelPlay(chan, true);
                }
                else
                {
                    BassWasapi.BASS_WASAPI_Start();
                }
            }
        }
示例#28
0
        /// <summary>
        /// Create the stream for the file assigned to the Musicstream
        /// </summary>
        private void CreateStream()
        {
            if (!_temporaryStream)
            {
                Log.Info("BASS: ---------------------------------------------");
                Log.Info("BASS: Creating BASS audio stream");
            }

            BASSFlag streamFlags = BASSFlag.BASS_SAMPLE_FLOAT | BASSFlag.BASS_STREAM_DECODE;

            _fileType = Utils.GetFileType(_filePath);

            switch (_fileType.FileMainType)
            {
            case FileMainType.Unknown:
                return;

            case FileMainType.AudioFile:
            case FileMainType.MidiFile:
                _stream = Bass.BASS_StreamCreateFile(_filePath, 0, 0, streamFlags);

                if (!_temporaryStream)
                {
                    // Read the Tag
                    _musicTag = TagReader.TagReader.ReadTag(_filePath);
                }
                break;

            case FileMainType.CDTrack:
                // StreamCreateFile causes problems with Multisession disks, so use StreamCreate with driveindex and track index
                int driveindex = Config.CdDriveLetters.IndexOf(_filePath.Substring(0, 1));
                int tracknum   = Convert.ToInt16(_filePath.Substring(_filePath.IndexOf(".cda") - 2, 2));
                _stream = BassCd.BASS_CD_StreamCreate(driveindex, tracknum - 1, streamFlags);
                break;

            case FileMainType.MODFile:
                _stream = Bass.BASS_MusicLoad(_filePath, 0, 0,
                                              BASSFlag.BASS_SAMPLE_SOFTWARE | BASSFlag.BASS_SAMPLE_FLOAT |
                                              BASSFlag.BASS_MUSIC_DECODE | BASSFlag.BASS_MUSIC_PRESCAN |
                                              BASSFlag.BASS_MUSIC_RAMP, 0);
                break;

            case FileMainType.WebStream:
                // Turn on parsing of ASX files
                Bass.BASS_SetConfig(BASSConfig.BASS_CONFIG_NET_PLAYLIST, 2);
                _stream = Bass.BASS_StreamCreateURL(_filePath, 0, streamFlags, null, IntPtr.Zero);
                if (_stream != 0 && !_temporaryStream)
                {
                    // Get the Tags and set the Meta Tag SyncProc
                    _tagInfo = new TAG_INFO(_filePath);
                    SetStreamTags(_stream);
                    if (BassTags.BASS_TAG_GetFromURL(_stream, _tagInfo))
                    {
                        GetMetaTags();
                    }
                    Bass.BASS_ChannelSetSync(_stream, BASSSync.BASS_SYNC_META, 0, _metaTagSyncProcDelegate, IntPtr.Zero);
                    Log.Debug("BASS: Webstream found - fetching stream {0}", Convert.ToString(_stream));
                }
                break;
            }

            if (_stream == 0)
            {
                Log.Error("BASS: Unable to create Stream for {0}.  Reason: {1}.", _filePath,
                          Enum.GetName(typeof(BASSError), Bass.BASS_ErrorGetCode()));
                return;
            }

            // When we have a MIDI file, we need to assign the sound banks to the stream
            if (_fileType.FileMainType == FileMainType.MidiFile && Config.SoundFonts != null)
            {
                BassMidi.BASS_MIDI_StreamSetFonts(_stream, Config.SoundFonts, Config.SoundFonts.Length);
            }

            _channelInfo = Bass.BASS_ChannelGetInfo(_stream);
            if (Bass.BASS_ErrorGetCode() != BASSError.BASS_OK)
            {
                Log.Error("BASS: Unable to get information for stream {0}.  Reason: {1}.", _filePath,
                          Enum.GetName(typeof(BASSError), Bass.BASS_ErrorGetCode()));
                return;
            }

            // This stream has just been created to check upfront, the sample rate
            // We don't need further processing of this stream
            if (_temporaryStream)
            {
                return;
            }

            Log.Info("BASS: Stream Information");
            Log.Info("BASS: ---------------------------------------------");
            Log.Info("BASS: File: {0}", _filePath);
            Log.Debug("BASS: Type of Stream: {0}", _channelInfo.ctype);
            Log.Info("BASS: Number of Channels: {0}", _channelInfo.chans);
            Log.Info("BASS: Stream Samplerate: {0}", _channelInfo.freq);
            Log.Debug("BASS: Stream Flags: {0}", _channelInfo.flags);
            Log.Info("BASS: ---------------------------------------------");

            Log.Debug("BASS: Registering stream playback events");
            RegisterPlaybackEvents();

            AttachDspToStream();

            if (Config.EnableReplayGain && _musicTag != null)
            {
                SetReplayGain();
            }
            Log.Info("BASS: Successfully created BASS audio stream");
            Log.Info("BASS: ---------------------------------------------");
        }
示例#29
0
        private void btnPlay_Click(object sender, EventArgs e)
        {
            updateTimer.Stop();
            Bass.BASS_StreamFree(stream);
            if (filename != string.Empty)
            {
                stream = Bass.BASS_StreamCreateFile(filename, 0, 0, BASSFlag.BASS_SAMPLE_FLOAT | BASSFlag.BASS_STREAM_PRESCAN);
                if (stream != 0)
                {
                    mslength           = (int)Bass.BASS_ChannelSeconds2Bytes(stream, 0.03);
                    deviceLatencyBytes = (int)Bass.BASS_ChannelSeconds2Bytes(stream, deviceLatencyMS / 1000.0);

                    myDSPAddr = new DSPPROC(MyDSPGain);
                    Bass.BASS_ChannelSetDSP(stream, myDSPAddr, IntPtr.Zero, 2);

                    if (WF2 != null && WF2.IsRendered)
                    {
                        WF2.SyncPlayback(stream);

                        long cuein  = WF2.GetMarker("CUE");
                        long cueout = WF2.GetMarker("END");

                        int cueinFrame  = WF2.Position2Frames(cuein);
                        int cueoutFrame = WF2.Position2Frames(cueout);

                        if (cuein >= 0)
                        {
                            Bass.BASS_ChannelSetPosition(stream, cuein);
                        }
                        if (cueout >= 0)
                        {
                            Bass.BASS_ChannelRemoveSync(stream, syncer);
                            syncer = Bass.BASS_ChannelSetSync(stream, BASSSync.BASS_SYNC_POS, cueout, sync, IntPtr.Zero);
                        }
                    }
                }

                if (stream != 0 && Bass.BASS_ChannelPlay(stream, false))
                {
                    textBox1.Text = "";
                    updateTimer.Start();

                    BASS_CHANNELINFO info = new BASS_CHANNELINFO();
                    Bass.BASS_ChannelGetInfo(stream, info);

                    textBox1.Text += "Info: " + info.ToString() + Environment.NewLine;

                    TAG_INFO tagInfo = new TAG_INFO();
                    if (BassTags.BASS_TAG_GetFromFile(stream, tagInfo))
                    {
                        textBoxAlbum.Text   = tagInfo.album;
                        textBoxArtist.Text  = tagInfo.artist;
                        textBoxTitle.Text   = tagInfo.title;
                        textBoxComment.Text = tagInfo.comment;
                        textBoxGenre.Text   = tagInfo.genre;
                        textBoxYear.Text    = tagInfo.year;
                        textBoxTrack.Text   = tagInfo.track;
                    }

                    btnStop.Enabled = true;
                    btnPlay.Enabled = false;
                }
            }
        }
示例#30
0
        public int PlayFile(ISoundFile file, int fadeInTime, PlayingFinished callback, bool loop)
        {
            int      channel     = 0;
            BASSFlag speakerFlag = GetSpeakerFlag(file);
            BASSFlag decodeFlag  = BASSFlag.BASS_STREAM_DECODE;

            if (file.SoundFileType == SoundFileType.Music && file.Effects.SpeakerAssignment.Active)
            {
                switch (file.Effects.SpeakerAssignment.Assignment)
                {
                case Data.SpeakerAssignment.AllSpeakers:
                case Data.SpeakerAssignment.BothCenterRears:
                case Data.SpeakerAssignment.BothFronts:
                case Data.SpeakerAssignment.BothRears:
                case Data.SpeakerAssignment.CenterAndSubwoofer:
                case Data.SpeakerAssignment.Default:
                    break;

                default:
                    decodeFlag |= BASSFlag.BASS_SAMPLE_MONO;
                    break;
                }
            }
#if MONO
            System.Runtime.InteropServices.GCHandle gcHandle = new System.Runtime.InteropServices.GCHandle();
#endif
            if (file.SoundFileType == SoundFileType.WebRadio)
            {
                channel = Bass.BASS_StreamCreateURL(file.Path, 0, decodeFlag | BASSFlag.BASS_STREAM_BLOCK, null, IntPtr.Zero);
            }
            else
            {
#if MONO
                byte[] buffer = null;
                long   length = 0;
                try
                {
#if ANDROID
                    if (file.Path.IsSmbFile())
                    {
                        buffer = SambaHelpers.GetFileContent(file.Path);
                        length = buffer.Length;
                    }
                    else
                    {
#endif
                    System.IO.FileStream fs = System.IO.File.OpenRead(file.Path);
                    length = fs.Length;
                    buffer = new byte[length];
                    fs.Read(buffer, 0, (int)length);
                    fs.Close();
#if ANDROID
                }
#endif
                }
                catch (System.IO.IOException e)
                {
                    ErrorHandling.ErrorOccurred(file.Id, e.Message);
                    return(0);
                }
                gcHandle = System.Runtime.InteropServices.GCHandle.Alloc(buffer, System.Runtime.InteropServices.GCHandleType.Pinned);
                channel  = Bass.BASS_StreamCreateFile(gcHandle.AddrOfPinnedObject(), 0L, length, decodeFlag);
#else // #if MONO
                channel = Bass.BASS_StreamCreateFile(file.Path, 0, 0, decodeFlag);
#endif
            }
            if (channel == 0)
            {
#if MONO
                if (gcHandle.IsAllocated)
                {
                    gcHandle.Free();
                }
#endif
                ErrorHandling.BassErrorOccurred(file.Id, StringResources.FilePlayingError);
                return(0);
            }
            RunningFileInfo info         = new RunningFileInfo();
            bool isStreaming             = BassStreamer.Instance.IsStreaming;
            bool useMultiSpeakerChannels = false;
            int speakers    = 2;
            int origChannel = channel;
            if (!isStreaming && file.Effects != null &&
                file.Effects.SpeakerAssignment.Active && file.Effects.SpeakerAssignment.Assignment == Data.SpeakerAssignment.AllSpeakers &&
                !file.Effects.Balance.Active && !file.Effects.Pitch.Active && !file.Effects.Tempo.Active)
            {
                speakers = Bass.BASS_GetInfo().speakers;
                if (speakers > 2)
                {
                    useMultiSpeakerChannels = true;
                }
            }

            Un4seen.Bass.BASSFlag flags = BASSFlag.BASS_DEFAULT;
            if (isStreaming)
            {
                flags = BASSFlag.BASS_FX_FREESOURCE | BASSFlag.BASS_STREAM_DECODE;
            }
            else if (useMultiSpeakerChannels)
            {
                flags = BASSFlag.BASS_FX_FREESOURCE | BASSFlag.BASS_STREAM_DECODE;
            }
            else
            {
                flags = BASSFlag.BASS_STREAM_AUTOFREE | BASSFlag.BASS_FX_FREESOURCE | speakerFlag;
            }
            channel = Un4seen.Bass.AddOn.Fx.BassFx.BASS_FX_TempoCreate(channel, flags);
            if (channel == 0)
            {
#if MONO
                if (gcHandle.IsAllocated)
                {
                    gcHandle.Free();
                }
#endif
                ErrorHandling.BassErrorOccurred(file.Id, StringResources.FilePlayingError);
                return(0);
            }
            bool result = true;
            if (useMultiSpeakerChannels)
            {
                int splitStream = Un4seen.Bass.AddOn.Mix.BassMix.BASS_Split_StreamCreate(channel, BASSFlag.BASS_STREAM_AUTOFREE | BASSFlag.BASS_SPEAKER_FRONT, null);
                if (splitStream == 0)
                {
                    result = false;
                }
                else
                {
                    int splitStream2 = Un4seen.Bass.AddOn.Mix.BassMix.BASS_Split_StreamCreate(channel, BASSFlag.BASS_STREAM_AUTOFREE | BASSFlag.BASS_SPEAKER_REAR, null);
                    if (splitStream2 == 0)
                    {
                        result = false;
                    }
                    else
                    {
                        Bass.BASS_ChannelSetLink(splitStream, splitStream2);
                        info.LinkedChannels = new List <int>();
                        info.LinkedChannels.Add(splitStream2);
                    }
                    if (result && speakers > 4)
                    {
                        int splitStream3 = Un4seen.Bass.AddOn.Mix.BassMix.BASS_Split_StreamCreate(channel, BASSFlag.BASS_STREAM_AUTOFREE | BASSFlag.BASS_SPEAKER_CENLFE, null);
                        if (splitStream3 == 0)
                        {
                            result = false;
                        }
                        else
                        {
                            Bass.BASS_ChannelSetLink(splitStream, splitStream3);
                            info.LinkedChannels.Add(splitStream3);
                        }
                    }
                    if (result && speakers > 6)
                    {
                        int splitStream4 = Un4seen.Bass.AddOn.Mix.BassMix.BASS_Split_StreamCreate(channel, BASSFlag.BASS_STREAM_AUTOFREE | BASSFlag.BASS_SPEAKER_REAR2, null);
                        if (splitStream4 == 0)
                        {
                            result = false;
                        }
                        else
                        {
                            Bass.BASS_ChannelSetLink(splitStream, splitStream4);
                            info.LinkedChannels.Add(splitStream4);
                        }
                    }
                    if (result)
                    {
                        channel = splitStream;
                    }
                }
            }
            if (result)
            {
                lock (m_Mutex)
                {
                    info.EndAction = new Action(() =>
                    {
                        callback(file.Id, channel);
                    });
                    info.Volume = file.Volume;
                }
                if (!loop)
                {
                    int sync = 0;
                    // If CueOut is active ...
                    if (file.Effects.CueOut.Active)
                    {
                        // Convert the CueOut position (seconds) into a byte offset
                        long cueOutPos = Bass.BASS_ChannelSeconds2Bytes(channel, file.Effects.CueOut.Position);
                        // Set the "end" sync to that position
                        sync = Bass.BASS_ChannelSetSync(channel, BASSSync.BASS_SYNC_POS, cueOutPos, m_CueOutSync, new IntPtr(file.Id));
                    }
                    else
                    {
                        long totalLength = Bass.BASS_ChannelGetLength(channel);
                        long endingTime  = Bass.BASS_ChannelSeconds2Bytes(channel, 0.1);

                        // Default: set the "end" sync to the end of the stream, minus one ms
                        sync = Bass.BASS_ChannelSetSync(channel, BASSSync.BASS_SYNC_POS, totalLength - endingTime, m_StartNextSync, IntPtr.Zero);
                    }

                    if (sync == 0)
                    {
#if MONO
                        if (gcHandle.IsAllocated)
                        {
                            gcHandle.Free();
                        }
#endif
                        ErrorHandling.BassErrorOccurred(file.Id, StringResources.FilePlayingError);
                        return(0);
                    }
                    else
                    {
                        lock (m_Mutex)
                        {
                            m_NotLoops[channel] = sync;
                        }
                    }
                }
                if (!SetStartVolume(file, fadeInTime, channel, info))
                {
                    return(0);
                }
                info.CrossFade = false;
                if (file.Effects != null && file.Effects.FadeOutTime != 0)
                {
                    long totalLength = Bass.BASS_ChannelGetLength(channel);
                    if (totalLength == -1)
                    {
                        ErrorHandling.BassErrorOccurred(file.Id, StringResources.SetVolumeError);
                        return(0);
                    }
                    long fadeOutLength = Bass.BASS_ChannelSeconds2Bytes(channel, 0.001 * file.Effects.FadeOutTime);
                    if (fadeOutLength == -1)
                    {
                        ErrorHandling.BassErrorOccurred(file.Id, StringResources.SetVolumeError);
                        return(0);
                    }
                    if (fadeOutLength > totalLength)
                    {
                        fadeOutLength = totalLength;
                    }
                    // If CueOut is active ...
                    if (file.Effects.CueOut.Active)
                    {
                        // Convert the CueOut position (seconds) into a byte offset
                        long cueOutPos = Bass.BASS_ChannelSeconds2Bytes(channel, file.Effects.CueOut.Position);
                        // Set the "end" sync to that position
                        if (Bass.BASS_ChannelSetSync(channel, BASSSync.BASS_SYNC_POS, cueOutPos - fadeOutLength, m_FadeOutSync, new IntPtr(file.Effects.FadeOutTime)) == 0)
                        {
                            ErrorHandling.BassErrorOccurred(file.Id, StringResources.FilePlayingError);
                            return(0);
                        }
                    }
                    else
                    {
                        if (Bass.BASS_ChannelSetSync(channel, BASSSync.BASS_SYNC_POS, totalLength - fadeOutLength, m_FadeOutSync, new IntPtr(file.Effects.FadeOutTime)) == 0)
                        {
                            ErrorHandling.BassErrorOccurred(file.Id, StringResources.FilePlayingError);
                            return(0);
                        }
                    }
                    if (loop)
                    {
                        // If CueOut is active ...
                        if (file.Effects.CueOut.Active)
                        {
                            // Convert the CueOut position (seconds) into a byte offset
                            long cueOutPos = Bass.BASS_ChannelSeconds2Bytes(channel, file.Effects.CueOut.Position);
                            // Set the "end" sync to that position
                            if (Bass.BASS_ChannelSetSync(channel, BASSSync.BASS_SYNC_POS, cueOutPos, m_LoopSync, new IntPtr(file.Id)) == 0)
                            {
                                ErrorHandling.BassErrorOccurred(file.Id, StringResources.FilePlayingError);
                                return(0);
                            }
                        }
                        else
                        {
                            if (Bass.BASS_ChannelSetSync(channel, BASSSync.BASS_SYNC_POS, totalLength, m_LoopSync, new IntPtr(file.Id)) == 0)
                            {
                                ErrorHandling.BassErrorOccurred(file.Id, StringResources.FilePlayingError);
                                return(0);
                            }
                        }
                    }
                    else
                    {
                        info.CrossFade = file.Effects.CrossFading;
                    }
                }
                if (file.Effects != null && file.Effects.Pitch.Active)
                {
                    float pitchValue = DetermineIntEffectValue(file.Effects.Pitch);
                    if (!Bass.BASS_ChannelSetAttribute(channel, BASSAttribute.BASS_ATTRIB_TEMPO_PITCH, pitchValue))
                    {
                        ErrorHandling.BassErrorOccurred(file.Id, StringResources.SetEffectError);
                        return(0);
                    }
                }
                if (file.Effects != null && file.Effects.Tempo.Active)
                {
                    float tempoValue = DetermineIntEffectValue(file.Effects.Tempo);
                    if (!Bass.BASS_ChannelSetAttribute(channel, BASSAttribute.BASS_ATTRIB_TEMPO, tempoValue))
                    {
                        ErrorHandling.BassErrorOccurred(file.Id, StringResources.SetEffectError);
                        return(0);
                    }
                }
                if (file.Effects != null && file.Effects.Balance.Active && !useMultiSpeakerChannels)
                {
                    SetBalanceEffect(channel, file.Id, file.Effects.Balance);
                }
                if (file.Effects != null && file.Effects.VolumeDB.Active)
                {
                    float volumeDB = DetermineIntEffectValue(file.Effects.VolumeDB);
                    float linear   = (float)Math.Pow(10d, volumeDB / 20);
                    int   volFx    = Bass.BASS_ChannelSetFX(channel, BASSFXType.BASS_FX_BFX_VOLUME, 1);
                    if (volFx == 0)
                    {
                        ErrorHandling.BassErrorOccurred(file.Id, StringResources.SetEffectError);
                        return(0);
                    }
                    Un4seen.Bass.AddOn.Fx.BASS_BFX_VOLUME fxVol = new Un4seen.Bass.AddOn.Fx.BASS_BFX_VOLUME(linear, Un4seen.Bass.AddOn.Fx.BASSFXChan.BASS_BFX_CHANALL);
                    if (!Bass.BASS_FXSetParameters(volFx, fxVol))
                    {
                        ErrorHandling.BassErrorOccurred(file.Id, StringResources.SetEffectError);
                        return(0);
                    }
                    if (info.LinkedChannels != null)
                    {
                        foreach (int splitStream2 in info.LinkedChannels)
                        {
                            int volFx2 = splitStream2 != 0 ? Bass.BASS_ChannelSetFX(splitStream2, BASSFXType.BASS_FX_BFX_VOLUME, 1) : 0;
                            if (splitStream2 != 0 && volFx2 == 0)
                            {
                                ErrorHandling.BassErrorOccurred(file.Id, StringResources.SetEffectError);
                                return(0);
                            }
                            if (volFx2 != 0 && !Bass.BASS_FXSetParameters(volFx2, fxVol))
                            {
                                ErrorHandling.BassErrorOccurred(file.Id, StringResources.SetEffectError);
                                return(0);
                            }
                        }
                    }
                }
#pragma warning disable CS0618 // Type or member is obsolete
                if (file.Effects != null && file.Effects.Reverb.Active)
                {
                    float linearLevel = (float)Math.Pow(10d, file.Effects.Reverb.Level / 20);
                    int   reverbFx    = Bass.BASS_ChannelSetFX(channel, BASSFXType.BASS_FX_BFX_REVERB, 1);
                    if (reverbFx == 0)
                    {
                        ErrorHandling.BassErrorOccurred(file.Id, StringResources.SetEffectError);
                        return(0);
                    }
                    Un4seen.Bass.AddOn.Fx.BASS_BFX_REVERB fxReverb = new Un4seen.Bass.AddOn.Fx.BASS_BFX_REVERB(linearLevel, file.Effects.Reverb.Delay);
                    if (!Bass.BASS_FXSetParameters(reverbFx, fxReverb))
                    {
                        ErrorHandling.BassErrorOccurred(file.Id, StringResources.SetEffectError);
                        return(0);
                    }
                    if (info.LinkedChannels != null)
                    {
                        foreach (int splitStream2 in info.LinkedChannels)
                        {
                            int reverbFx2 = splitStream2 != 0 ? Bass.BASS_ChannelSetFX(splitStream2, BASSFXType.BASS_FX_BFX_REVERB, 1) : 0;
                            if (splitStream2 != 0 && reverbFx2 == 0)
                            {
                                ErrorHandling.BassErrorOccurred(file.Id, StringResources.SetEffectError);
                                return(0);
                            }
                            if (reverbFx2 != 0 && !Bass.BASS_FXSetParameters(reverbFx2, fxReverb))
                            {
                                ErrorHandling.BassErrorOccurred(file.Id, StringResources.SetEffectError);
                                return(0);
                            }
                        }
                    }
                }
#pragma warning restore CS0618 // Type or member is obsolete
                if (loop)
                {
                    Bass.BASS_ChannelFlags(channel, BASSFlag.BASS_SAMPLE_LOOP, BASSFlag.BASS_SAMPLE_LOOP);
                }
                lock (m_Mutex)
                {
                    m_Loops[file.Id] = file;
                    if (file.Effects != null && file.Effects.CueOut.Active)
                    {
                        m_CueOutRepeats[channel] = loop;
                    }
                }

                if (file.Effects.CueIn.Active)
                {
                    Bass.BASS_ChannelSetPosition(channel, file.Effects.CueIn.Position);
                }

                if (isStreaming)
                {
                    result = BassStreamer.Instance.AddChannel(channel);
                }
                else
                {
                    result = Bass.BASS_ChannelPlay(channel, false);
                }
                if (!result)
                {
                    ErrorHandling.BassErrorOccurred(file.Id, StringResources.FilePlayingError);
                    Bass.BASS_StreamFree(channel);
#if MONO
                    if (gcHandle.IsAllocated)
                    {
                        gcHandle.Free();
                    }
#endif
                    return(0);
                }
                lock (m_Mutex)
                {
                    m_RunningFiles[channel] = info;
#if MONO
                    if (gcHandle.IsAllocated)
                    {
                        m_GCHandles[channel] = gcHandle;
                    }
#endif
                }
                return(channel);
            }
            else
            {
                ErrorHandling.BassErrorOccurred(file.Id, StringResources.FilePlayingError);
                return(0);
            }
        }