Exemplo n.º 1
0
        private int prepareStream(Stream data, bool quick)
        {
            //encapsulate incoming stream with async buffer if it isn't already.
            dataStream = data as AsyncBufferStream ?? new AsyncBufferStream(data, quick ? 8 : -1);

            fileCallbacks = new FileCallbacks(new DataStreamFileProcedures(dataStream));

            BassFlags flags  = Preview ? 0 : BassFlags.Decode | BassFlags.Prescan;
            int       stream = Bass.CreateStream(StreamSystem.NoBuffer, flags, fileCallbacks.Callbacks, fileCallbacks.Handle);

            if (!Preview)
            {
                // We assign the BassFlags.Decode streams to the device "bass_nodevice" to prevent them from getting
                // cleaned up during a Bass.Free call. This is necessary for seamless switching between audio devices.
                // Further, we provide the flag BassFlags.FxFreeSource such that freeing the stream also frees
                // all parent decoding streams.
                const int bass_nodevice = 0x20000;

                Bass.ChannelSetDevice(stream, bass_nodevice);
                tempoAdjustStream = BassFx.TempoCreate(stream, BassFlags.Decode | BassFlags.FxFreeSource);
                Bass.ChannelSetDevice(tempoAdjustStream, bass_nodevice);
                stream = BassFx.ReverseCreate(tempoAdjustStream, 5f, BassFlags.Default | BassFlags.FxFreeSource);

                Bass.ChannelSetAttribute(stream, ChannelAttribute.TempoUseQuickAlgorithm, 1);
                Bass.ChannelSetAttribute(stream, ChannelAttribute.TempoOverlapMilliseconds, 4);
                Bass.ChannelSetAttribute(stream, ChannelAttribute.TempoSequenceMilliseconds, 30);
            }

            return(stream);
        }
Exemplo n.º 2
0
        protected override void Dispose(bool disposing)
        {
            if (activeStream != 0)
            {
                isRunning = false;
                Bass.ChannelStop(activeStream);
                Bass.StreamFree(activeStream);
            }

            activeStream = 0;

            dataStream?.Dispose();
            dataStream = null;

            fileCallbacks?.Dispose();
            fileCallbacks = null;

            stopCallback?.Dispose();
            stopCallback = null;

            endCallback?.Dispose();
            endCallback = null;

            base.Dispose(disposing);
        }
Exemplo n.º 3
0
        public AudioTrackBass(Stream data, bool quick = false)
        {
            Preview = quick;

            BassFlags flags = Preview ? 0 : (BassFlags.Decode | BassFlags.Prescan);

            if (data == null)
                throw new ArgumentNullException(@"Data couldn't be loaded!");
            //encapsulate incoming stream with async buffer if it isn't already.
            dataStream = data as AsyncBufferStream ?? new AsyncBufferStream(data, quick ? 8 : -1);

            procs = new DataStreamFileProcedures(dataStream);

            audioStreamPrefilter = Bass.CreateStream(StreamSystem.NoBuffer, flags, procs.BassProcedures, IntPtr.Zero);

            if (Preview)
                activeStream = audioStreamPrefilter;
            else
            {
                activeStream = BassFx.TempoCreate(audioStreamPrefilter, BassFlags.Decode);
                activeStream = BassFx.ReverseCreate(activeStream, 5f, BassFlags.Default);

                Bass.ChannelSetAttribute(activeStream, ChannelAttribute.TempoUseQuickAlgorithm, 1);
                Bass.ChannelSetAttribute(activeStream, ChannelAttribute.TempoOverlapMilliseconds, 4);
                Bass.ChannelSetAttribute(activeStream, ChannelAttribute.TempoSequenceMilliseconds, 30);
            }

            Length = (Bass.ChannelBytes2Seconds(activeStream, Bass.ChannelGetLength(activeStream)) * 1000);
            Bass.ChannelGetAttribute(activeStream, ChannelAttribute.Frequency, out initialFrequency);
        }
Exemplo n.º 4
0
        /// <summary>
        /// Constructs a new <see cref="TrackBass"/> from provided audio data.
        /// </summary>
        /// <param name="data">The sample data stream.</param>
        /// <param name="quick">If true, the track will not be fully loaded, and should only be used for preview purposes.  Defaults to false.</param>
        public TrackBass(Stream data, bool quick = false)
        {
            EnqueueAction(() =>
            {
                Preview = quick;

                if (data == null)
                {
                    throw new ArgumentNullException(nameof(data));
                }
                //encapsulate incoming stream with async buffer if it isn't already.
                dataStream = data as AsyncBufferStream ?? new AsyncBufferStream(data, quick ? 8 : -1);

                procedures = CreateDataStreamFileProcedures(dataStream);

                if (!RuntimeInfo.SupportsIL)
                {
                    pinnedProcedures = GCHandle.Alloc(procedures, GCHandleType.Pinned);
                }

                BassFlags flags = Preview ? 0 : BassFlags.Decode | BassFlags.Prescan | BassFlags.Float;
                activeStream    = Bass.CreateStream(StreamSystem.NoBuffer, flags, procedures.BassProcedures, RuntimeInfo.SupportsIL ? IntPtr.Zero : GCHandle.ToIntPtr(pinnedProcedures));

                if (!Preview)
                {
                    // We assign the BassFlags.Decode streams to the device "bass_nodevice" to prevent them from getting
                    // cleaned up during a Bass.Free call. This is necessary for seamless switching between audio devices.
                    // Further, we provide the flag BassFlags.FxFreeSource such that freeing the activeStream also frees
                    // all parent decoding streams.
                    const int bass_nodevice = 0x20000;

                    Bass.ChannelSetDevice(activeStream, bass_nodevice);
                    tempoAdjustStream = BassFx.TempoCreate(activeStream, BassFlags.Decode | BassFlags.FxFreeSource);
                    Bass.ChannelSetDevice(activeStream, bass_nodevice);
                    activeStream = BassFx.ReverseCreate(tempoAdjustStream, 5f, BassFlags.Default | BassFlags.FxFreeSource);

                    Bass.ChannelSetAttribute(activeStream, ChannelAttribute.TempoUseQuickAlgorithm, 1);
                    Bass.ChannelSetAttribute(activeStream, ChannelAttribute.TempoOverlapMilliseconds, 4);
                    Bass.ChannelSetAttribute(activeStream, ChannelAttribute.TempoSequenceMilliseconds, 30);
                }

                // will be -1 in case of an error
                double seconds = Bass.ChannelBytes2Seconds(activeStream, Bass.ChannelGetLength(activeStream));

                bool success = seconds >= 0;

                if (success)
                {
                    Length = seconds * 1000;

                    Bass.ChannelGetAttribute(activeStream, ChannelAttribute.Frequency, out float frequency);
                    initialFrequency = frequency;
                    bitrate          = (int)Bass.ChannelGetAttribute(activeStream, ChannelAttribute.Bitrate);

                    isLoaded = true;
                }
            });

            InvalidateState();
        }
Exemplo n.º 5
0
        protected override void Dispose(bool disposing)
        {
            if (activeStream != 0) Bass.ChannelStop(activeStream);

            if (audioStreamPrefilter != 0) Bass.StreamFree(audioStreamPrefilter);

            activeStream = 0;
            audioStreamPrefilter = 0;

            dataStream?.Dispose();
            dataStream = null;

            base.Dispose(disposing);
        }
Exemplo n.º 6
0
        public TrackBass(Stream data, bool quick = false)
        {
            PendingActions.Enqueue(() =>
            {
                Preview = quick;

                if (data == null)
                {
                    throw new ArgumentNullException(nameof(data));
                }
                //encapsulate incoming stream with async buffer if it isn't already.
                dataStream = data as AsyncBufferStream ?? new AsyncBufferStream(data, quick ? 8 : -1);

                var procs = new DataStreamFileProcedures(dataStream);

                BassFlags flags = Preview ? 0 : BassFlags.Decode | BassFlags.Prescan;
                activeStream    = Bass.CreateStream(StreamSystem.NoBuffer, flags, procs.BassProcedures, IntPtr.Zero);

                if (!Preview)
                {
                    // We assign the BassFlags.Decode streams to the device "bass_nodevice" to prevent them from getting
                    // cleaned up during a Bass.Free call. This is necessary for seamless switching between audio devices.
                    // Further, we provide the flag BassFlags.FxFreeSource such that freeing the activeStream also frees
                    // all parent decoding streams.
                    const int bass_nodevice = 0x20000;

                    Bass.ChannelSetDevice(activeStream, bass_nodevice);
                    tempoAdjustStream = BassFx.TempoCreate(activeStream, BassFlags.Decode | BassFlags.FxFreeSource);
                    Bass.ChannelSetDevice(activeStream, bass_nodevice);
                    activeStream = BassFx.ReverseCreate(tempoAdjustStream, 5f, BassFlags.Default | BassFlags.FxFreeSource);

                    Bass.ChannelSetAttribute(activeStream, ChannelAttribute.TempoUseQuickAlgorithm, 1);
                    Bass.ChannelSetAttribute(activeStream, ChannelAttribute.TempoOverlapMilliseconds, 4);
                    Bass.ChannelSetAttribute(activeStream, ChannelAttribute.TempoSequenceMilliseconds, 30);
                }

                Length = Bass.ChannelBytes2Seconds(activeStream, Bass.ChannelGetLength(activeStream)) * 1000;

                float frequency;
                Bass.ChannelGetAttribute(activeStream, ChannelAttribute.Frequency, out frequency);
                initialFrequency = frequency;
                bitrate          = (int)Bass.ChannelGetAttribute(activeStream, ChannelAttribute.Bitrate);

                isLoaded = true;
                OnLoaded?.Invoke(this);
            });

            InvalidateState();
        }
Exemplo n.º 7
0
        protected override void Dispose(bool disposing)
        {
            if (activeStream != 0)
            {
                isRunning = false;
                Bass.ChannelStop(activeStream);
                Bass.StreamFree(activeStream);
            }

            activeStream = 0;

            dataStream?.Dispose();
            dataStream = null;

            base.Dispose(disposing);
        }
Exemplo n.º 8
0
        internal AudioTrackBass(Stream data, bool quick = false, bool loop = false)
        {
            procs = new BASS_FILEPROCS(ac_Close, ac_Length, ac_Read, ac_Seek);

            Preview = quick;
            Looping = loop;

            BASSFlag flags = Preview ? 0 : (BASSFlag.BASS_STREAM_DECODE | BASSFlag.BASS_STREAM_PRESCAN);

            if (data == null)
            {
                throw new AudioNotLoadedException();
            }
            else
            {
                //encapsulate incoming stream with async buffer if it isn't already.
                DataStream = data as AsyncBufferStream;
                if (DataStream == null)
                {
                    DataStream = new AsyncBufferStream(data, quick ? 8 : -1);
                }

                audioStreamPrefilter = Bass.BASS_StreamCreateFileUser(BASSStreamSystem.STREAMFILE_NOBUFFER, flags, procs, IntPtr.Zero);
            }

            if (Preview)
            {
                audioStream = audioStreamForwards = audioStreamPrefilter;
            }
            else
            {
                audioStream          = audioStreamForwards = BassFx.BASS_FX_TempoCreate(audioStreamPrefilter, loop ? BASSFlag.BASS_MUSIC_LOOP : BASSFlag.BASS_DEFAULT);
                audioStreamBackwards = BassFx.BASS_FX_ReverseCreate(audioStreamPrefilter, 5f, BASSFlag.BASS_DEFAULT);

                Bass.BASS_ChannelSetAttribute(audioStream, BASSAttribute.BASS_ATTRIB_TEMPO_OPTION_USE_QUICKALGO, Bass.TRUE);
                Bass.BASS_ChannelSetAttribute(audioStream, BASSAttribute.BASS_ATTRIB_TEMPO_OPTION_OVERLAP_MS, 4);
                Bass.BASS_ChannelSetAttribute(audioStream, BASSAttribute.BASS_ATTRIB_TEMPO_OPTION_SEQUENCE_MS, 30);
            }

            Length = (Bass.BASS_ChannelBytes2Seconds(audioStream, Bass.BASS_ChannelGetLength(audioStream)) * 1000);
            Bass.BASS_ChannelGetAttribute(audioStream, BASSAttribute.BASS_ATTRIB_FREQ, ref initialAudioFrequency);
            currentAudioFrequency = initialAudioFrequency;

            AudioEngine.RegisterTrack(this);
        }
Exemplo n.º 9
0
        internal static AudioTrack CreateAudioTrack(Beatmap beatmap, bool quick, bool loop = false, AudioTrack last = null)
        {
            AudioTrack track = null;

            Stream stream = null;

            AudioTrackBass bass = last as AudioTrackBass;

            if (bass != null && bass.Beatmap == beatmap && bass.DataStream != null)
            {
                //reuse memory-backed buffer when we can.
                stream = new AsyncBufferStream(beatmap.GetAudioStream(), quick ? 4 : -1, bass.DataStream);
            }
            else
            {
                stream = beatmap.GetAudioStream();
            }

            if (stream == null)
            {
                track = new AudioTrackVirtual()
                {
                    Length = beatmap.TotalLength < 0 ? 600 * 1000 : beatmap.TotalLength + 10000
                }
            }
            ;
            else
            {
                track = new AudioTrackBass(stream, quick, loop);
            }

            if (track != null)
            {
                track.Beatmap = beatmap;
            }

            return(track);
        }
Exemplo n.º 10
0
        protected override void Dispose(bool disposing)
        {
            if (activeStream != 0)
            {
                isRunning = false;
                Bass.ChannelStop(activeStream);
                Bass.StreamFree(activeStream);
            }

            activeStream = 0;

            dataStream?.Dispose();
            dataStream = null;

            if (pinnedProcedures.IsAllocated)
            {
                pinnedProcedures.Free();
            }

            procedures = null;

            base.Dispose(disposing);
        }
Exemplo n.º 11
0
        protected override void Dispose(bool disposing)
        {
            PendingActions.Enqueue(() =>
            {
                if (activeStream != 0)
                {
                    Bass.ChannelStop(activeStream);
                }

                if (audioStreamPrefilter != 0)
                {
                    Bass.StreamFree(audioStreamPrefilter);
                }

                activeStream         = 0;
                audioStreamPrefilter = 0;

                dataStream?.Dispose();
                dataStream = null;
            });

            base.Dispose(disposing);
        }
Exemplo n.º 12
0
        protected override void Dispose(bool disposing)
        {
            if (audioStream != 0)
            {
                Bass.BASS_ChannelStop(audioStream);
            }

            if (audioStreamForwards != 0)
            {
                Bass.BASS_StreamFree(audioStreamForwards);
            }
            if (audioStreamBackwards != 0)
            {
                Bass.BASS_StreamFree(audioStreamBackwards);
            }
            if (audioStreamPrefilter != 0)
            {
                Bass.BASS_StreamFree(audioStreamPrefilter);
            }

            audioStream          = 0;
            audioStreamForwards  = 0;
            audioStreamBackwards = 0;
            audioStreamPrefilter = 0;

            State = AudioStates.Stopped;

            if (DataStream != null)
            {
                DataStream.Dispose();
            }
            DataStream = null;

            AudioEngine.UnregisterTrack(this);

            base.Dispose(disposing);
        }
Exemplo n.º 13
0
        /// <summary>
        /// Constructs a new <see cref="TrackBass"/> from provided audio data.
        /// </summary>
        /// <param name="data">The sample data stream.</param>
        /// <param name="quick">If true, the track will not be fully loaded, and should only be used for preview purposes.  Defaults to false.</param>
        public TrackBass(Stream data, bool quick = false)
        {
            if (data == null)
            {
                throw new ArgumentNullException(nameof(data));
            }

            // todo: support this internally to match the underlying Track implementation (which can support this).
            const float tempo_minimum_supported = 0.05f;

            AggregateTempo.ValueChanged += t =>
            {
                if (t.NewValue < tempo_minimum_supported)
                {
                    throw new ArgumentException($"{nameof(TrackBass)} does not support {nameof(Tempo)} specifications below {tempo_minimum_supported}. Use {nameof(Frequency)} instead.");
                }
            };

            EnqueueAction(() =>
            {
                Preview = quick;

                //encapsulate incoming stream with async buffer if it isn't already.
                dataStream = data as AsyncBufferStream ?? new AsyncBufferStream(data, quick ? 8 : -1);

                fileCallbacks = new FileCallbacks(new DataStreamFileProcedures(dataStream));

                BassFlags flags = Preview ? 0 : BassFlags.Decode | BassFlags.Prescan;
                activeStream    = Bass.CreateStream(StreamSystem.NoBuffer, flags, fileCallbacks.Callbacks, fileCallbacks.Handle);

                if (!Preview)
                {
                    // We assign the BassFlags.Decode streams to the device "bass_nodevice" to prevent them from getting
                    // cleaned up during a Bass.Free call. This is necessary for seamless switching between audio devices.
                    // Further, we provide the flag BassFlags.FxFreeSource such that freeing the activeStream also frees
                    // all parent decoding streams.
                    const int bass_nodevice = 0x20000;

                    Bass.ChannelSetDevice(activeStream, bass_nodevice);
                    tempoAdjustStream = BassFx.TempoCreate(activeStream, BassFlags.Decode | BassFlags.FxFreeSource);
                    Bass.ChannelSetDevice(tempoAdjustStream, bass_nodevice);
                    activeStream = BassFx.ReverseCreate(tempoAdjustStream, 5f, BassFlags.Default | BassFlags.FxFreeSource);

                    Bass.ChannelSetAttribute(activeStream, ChannelAttribute.TempoUseQuickAlgorithm, 1);
                    Bass.ChannelSetAttribute(activeStream, ChannelAttribute.TempoOverlapMilliseconds, 4);
                    Bass.ChannelSetAttribute(activeStream, ChannelAttribute.TempoSequenceMilliseconds, 30);
                }

                // will be -1 in case of an error
                double seconds = Bass.ChannelBytes2Seconds(activeStream, byteLength = Bass.ChannelGetLength(activeStream));

                bool success = seconds >= 0;

                if (success)
                {
                    Length = seconds * 1000;

                    // Bass does not allow seeking to the end of the track, so the last available position is 1 sample before.
                    lastSeekablePosition = Bass.ChannelBytes2Seconds(activeStream, byteLength - BYTES_PER_SAMPLE) * 1000;

                    Bass.ChannelGetAttribute(activeStream, ChannelAttribute.Frequency, out float frequency);
                    initialFrequency = frequency;
                    bitrate          = (int)Bass.ChannelGetAttribute(activeStream, ChannelAttribute.Bitrate);

                    stopCallback = new SyncCallback((a, b, c, d) => RaiseFailed());
                    endCallback  = new SyncCallback((a, b, c, d) =>
                    {
                        if (!Looping)
                        {
                            RaiseCompleted();
                        }
                    });

                    Bass.ChannelSetSync(activeStream, SyncFlags.Stop, 0, stopCallback.Callback, stopCallback.Handle);
                    Bass.ChannelSetSync(activeStream, SyncFlags.End, 0, endCallback.Callback, endCallback.Handle);

                    isLoaded = true;
                }
            });

            InvalidateState();
        }
Exemplo n.º 14
0
 public DataStreamFileProcedures(AsyncBufferStream data)
 {
     dataStream = data;
 }
Exemplo n.º 15
0
        /// <summary>
        /// Constructs a new <see cref="TrackBass"/> from provided audio data.
        /// </summary>
        /// <param name="data">The sample data stream.</param>
        /// <param name="quick">If true, the track will not be fully loaded, and should only be used for preview purposes.  Defaults to false.</param>
        public TrackBass(Stream data, bool quick = false)
        {
            EnqueueAction(() =>
            {
                Preview = quick;

                if (data == null)
                {
                    throw new ArgumentNullException(nameof(data));
                }
                //encapsulate incoming stream with async buffer if it isn't already.
                dataStream = data as AsyncBufferStream ?? new AsyncBufferStream(data, quick ? 8 : -1);

                fileCallbacks = new FileCallbacks(new DataStreamFileProcedures(dataStream));

                BassFlags flags = Preview ? 0 : BassFlags.Decode | BassFlags.Prescan;
                activeStream    = Bass.CreateStream(StreamSystem.NoBuffer, flags, fileCallbacks.Callbacks, fileCallbacks.Handle);

                if (!Preview)
                {
                    // We assign the BassFlags.Decode streams to the device "bass_nodevice" to prevent them from getting
                    // cleaned up during a Bass.Free call. This is necessary for seamless switching between audio devices.
                    // Further, we provide the flag BassFlags.FxFreeSource such that freeing the activeStream also frees
                    // all parent decoding streams.
                    const int bass_nodevice = 0x20000;

                    Bass.ChannelSetDevice(activeStream, bass_nodevice);
                    tempoAdjustStream = BassFx.TempoCreate(activeStream, BassFlags.Decode | BassFlags.FxFreeSource);
                    Bass.ChannelSetDevice(activeStream, bass_nodevice);
                    activeStream = BassFx.ReverseCreate(tempoAdjustStream, 5f, BassFlags.Default | BassFlags.FxFreeSource);

                    Bass.ChannelSetAttribute(activeStream, ChannelAttribute.TempoUseQuickAlgorithm, 1);
                    Bass.ChannelSetAttribute(activeStream, ChannelAttribute.TempoOverlapMilliseconds, 4);
                    Bass.ChannelSetAttribute(activeStream, ChannelAttribute.TempoSequenceMilliseconds, 30);
                }

                // will be -1 in case of an error
                double seconds = Bass.ChannelBytes2Seconds(activeStream, Bass.ChannelGetLength(activeStream));

                bool success = seconds >= 0;

                if (success)
                {
                    Length = seconds * 1000;

                    Bass.ChannelGetAttribute(activeStream, ChannelAttribute.Frequency, out float frequency);
                    initialFrequency = frequency;
                    bitrate          = (int)Bass.ChannelGetAttribute(activeStream, ChannelAttribute.Bitrate);

                    stopCallback = new SyncCallback((a, b, c, d) => RaiseFailed());
                    endCallback  = new SyncCallback((a, b, c, d) =>
                    {
                        if (!Looping)
                        {
                            RaiseCompleted();
                        }
                    });

                    Bass.ChannelSetSync(activeStream, SyncFlags.Stop, 0, stopCallback.Callback, stopCallback.Handle);
                    Bass.ChannelSetSync(activeStream, SyncFlags.End, 0, endCallback.Callback, endCallback.Handle);

                    isLoaded = true;
                }
            });

            InvalidateState();
        }