コード例 #1
0
 public SampleChannelBass(Sample sample, Action <SampleChannel> onPlay)
     : base(sample, onPlay)
 {
     relativeFrequencyHandler = new BassRelativeFrequencyHandler
     {
         FrequencyChangedToZero   = () => Bass.ChannelPause(channel),
         FrequencyChangedFromZero = () => Bass.ChannelPlay(channel),
     };
 }
コード例 #2
0
        public SampleChannelBass(SampleBass sample)
        {
            this.sample = sample;

            relativeFrequencyHandler = new BassRelativeFrequencyHandler
            {
                FrequencyChangedToZero   = stopChannel,
                FrequencyChangedFromZero = () =>
                {
                    // Only unpause if the channel has been played by the user.
                    if (userRequestedPlay)
                    {
                        playChannel();
                    }
                },
            };

            ensureChannel();
        }
コード例 #3
0
        public TrackBass(Stream data, bool quick = false)
        {
            if (data == null)
            {
                throw new ArgumentNullException(nameof(data));
            }

            relativeFrequencyHandler = new BassRelativeFrequencyHandler
            {
                FrequencyChangedToZero   = () => stopInternal(),
                FrequencyChangedFromZero = () =>
                {
                    // Do not resume the track if a play wasn't requested at all or has been paused via Stop().
                    if (!isPlayed)
                    {
                        return;
                    }

                    startInternal();
                }
            };

            // 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;

                activeStream = prepareStream(data, quick);

                long byteLength = Bass.ChannelGetLength(activeStream);

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

                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;

                    isLoaded = true;

                    relativeFrequencyHandler.SetChannel(activeStream);
                }
            });

            InvalidateState();
        }
コード例 #4
0
ファイル: TrackBass.cs プロジェクト: geshii/osu-framework
        /// <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));
            }

            relativeFrequencyHandler = new BassRelativeFrequencyHandler
            {
                FrequencyChangedToZero   = () => stopInternal(),
                FrequencyChangedFromZero = () =>
                {
                    // Do not resume the track if a play wasn't requested at all or has been paused via Stop().
                    if (!isPlayed)
                    {
                        return;
                    }

                    startInternal();
                }
            };

            // 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;

                activeStream = prepareStream(data, quick);

                long byteLength = Bass.ChannelGetLength(activeStream);

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

                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;

                    bitrate = (int)Bass.ChannelGetAttribute(activeStream, ChannelAttribute.Bitrate);

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

                        hasCompleted = true;
                        RaiseCompleted();
                    });
                    endMixtimeCallback = new SyncCallback((a, b, c, d) =>
                    {
                        // this is separate from the above callback as this is required to be invoked on mixtime.
                        // see "BASS_SYNC_MIXTIME" part of http://www.un4seen.com/doc/#bass/BASS_ChannelSetSync.html for reason why.
                        if (Looping)
                        {
                            seekInternal(RestartPoint);
                        }
                    });

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

                    isLoaded = true;

                    relativeFrequencyHandler.SetChannel(activeStream);
                    bassAmplitudeProcessor?.SetChannel(activeStream);
                }
            });

            InvalidateState();
        }