Beispiel #1
0
        /// <summary>
        /// Sets a value indicating whether the specified channel is looping.
        /// </summary>
        /// <param name="handle">The handle of the channel to modify.</param>
        /// <param name="looping">A value indicating whether the channel is looping.</param>
        public static void SetIsLooping(UInt32 handle, Boolean looping)
        {
            var flags = looping ?
                        BASSNative.ChannelFlags(handle, BASSNative.BASS_SAMPLE_LOOP, BASSNative.BASS_SAMPLE_LOOP) :
                        BASSNative.ChannelFlags(handle, 0, BASSNative.BASS_SAMPLE_LOOP);

            if (!BASSUtil.IsValidValue(flags))
            {
                throw new BASSException();
            }
        }
Beispiel #2
0
        /// <summary>
        /// Gets a value indicating whether the specified channel is looping.
        /// </summary>
        /// <param name="handle">The handle of the channel to evaluate.</param>
        /// <returns>true if the channel is looping; otherwise, false.</returns>
        public static Boolean GetIsLooping(UInt32 handle)
        {
            var flags = BASSNative.ChannelFlags(handle, 0, 0);

            if (!BASSUtil.IsValidValue(flags))
            {
                throw new BASSException();
            }

            return((flags & BASSNative.BASS_SAMPLE_LOOP) == BASSNative.BASS_SAMPLE_LOOP);
        }
Beispiel #3
0
        /// <summary>
        /// Sets the position of the specified channel.
        /// </summary>
        /// <param name="handle">The handle of the channel to modify.</param>
        /// <param name="position">The position in seconds to which to set the channel.</param>
        public static void SetPositionInSeconds(UInt32 handle, Double position)
        {
            var positionInBytes = BASSNative.ChannelSeconds2Bytes(handle, position);

            if (!BASSUtil.IsValidValue(positionInBytes))
            {
                throw new BASSException();
            }

            if (!BASSNative.ChannelSetPosition(handle, positionInBytes, 0))
            {
                throw new BASSException();
            }
        }
        /// <inheritdoc/>
        public override void Play(Single volume, Single pitch, Single pan)
        {
            Contract.EnsureNotDisposed(this, Disposed);

            var channel = 0u;

            if (pitch == 0)
            {
                channel = BASSNative.SampleGetChannel(sample, false);
                if (!BASSUtil.IsValidHandle(channel))
                {
                    throw new BASSException();
                }
            }
            else
            {
                var stream = BASSNative.StreamCreate(sampleInfo.freq, sampleInfo.chans, sampleInfo.flags | BASSNative.BASS_STREAM_DECODE, BASSNative.STREAMPROC_PUSH, IntPtr.Zero);
                if (!BASSUtil.IsValidHandle(stream))
                {
                    throw new BASSException();
                }

                var pushed = BASSNative.StreamPutData(stream, data, sampleInfo.length);
                if (!BASSUtil.IsValidValue(pushed))
                {
                    throw new BASSException();
                }

                stream = BASSFXNative.TempoCreate(stream, BASSNative.BASS_FX_FREESOURCE | BASSNative.BASS_STREAM_AUTOFREE);
                if (!BASSUtil.IsValidHandle(stream))
                {
                    throw new BASSException();
                }

                channel = stream;

                BASSUtil.SetPitch(channel, MathUtil.Clamp(pitch, -1f, 1f));
            }

            BASSUtil.SetVolume(channel, MathUtil.Clamp(volume, 0f, 1f));
            BASSUtil.SetPan(channel, MathUtil.Clamp(pan, -1f, 1f));

            if (!BASSNative.ChannelPlay(channel, false))
            {
                throw new BASSException();
            }
        }
Beispiel #5
0
        /// <summary>
        /// Gets the position of the specified channel.
        /// </summary>
        /// <param name="handle">The handle of the channel to evaluate.</param>
        /// <returns>The current position of the channel in seconds.</returns>
        public static Double GetPositionInSeconds(UInt32 handle)
        {
            var position = BASSNative.ChannelGetPosition(handle, 0);

            if (!BASSUtil.IsValidValue(position))
            {
                throw new BASSException();
            }

            var seconds = BASSNative.ChannelBytes2Seconds(handle, position);

            if (seconds < 0)
            {
                throw new BASSException();
            }

            return(seconds);
        }
Beispiel #6
0
        /// <summary>
        /// Gets the duration of the specified channel in seconds.
        /// </summary>
        /// <param name="handle">The handle of the channel to evaluate.</param>
        /// <returns>The duration of the specified channel in seconds.</returns>
        public static Double GetDurationInSeconds(UInt32 handle)
        {
            var length = BASSNative.ChannelGetLength(handle, 0);

            if (!BASSUtil.IsValidValue(length))
            {
                throw new BASSException();
            }

            var seconds = BASSNative.ChannelBytes2Seconds(handle, length);

            if (seconds < 0)
            {
                throw new BASSException();
            }

            return(seconds);
        }
Beispiel #7
0
        /// <summary>
        /// Promotes the current channel to a stream.
        /// This is necessary if the pitch is shifted, because BASS_FX only works on streams.
        /// </summary>
        /// <param name="volume">The stream's initial volume.</param>
        /// <param name="pitch">The stream's initial pitch.</param>
        /// <param name="pan">The stream's initial pan.</param>
        /// <param name="loop">A value indicating whether to loop the stream.</param>
        private Boolean PromoteToStream(Single volume, Single pitch, Single pan, Boolean loop)
        {
            if (BASSUtil.IsValidHandle(stream))
            {
                return(false);
            }

            // If the channel is currently playing, pause it.
            var playing = (State == PlaybackState.Playing);

            if (playing)
            {
                if (!BASSNative.ChannelPause(channel))
                {
                    throw new BASSException();
                }
            }

            // Get the current position of the playing channel so that we can advance the stream to match.
            var streampos = (uint)BASSNative.ChannelGetPosition(channel, 0);

            if (!BASSUtil.IsValidValue(streampos))
            {
                throw new BASSException();
            }

            // Create a process for streaming data from our sample into the new stream.
            sampleDataPosition   = (int)streampos;
            sampleDataLength     = (int)sampleInfo.length;
            sampleDataStreamProc = new StreamProc((handle, buffer, length, user) =>
            {
                if (sampleDataPosition >= sampleDataLength)
                {
                    sampleDataPosition = 0;
                }

                var byteCount = Math.Min(length, (uint)sampleDataLength - streampos);
                unsafe
                {
                    byte *pBufferSrc = (byte *)(sampleData + sampleDataPosition).ToPointer();
                    byte *pBufferDst = (byte *)(buffer).ToPointer();
                    for (int i = 0; i < byteCount; i++)
                    {
                        *pBufferDst++ = *pBufferSrc++;
                    }
                }
                sampleDataPosition += (int)byteCount;

                return(streampos >= sampleDataLength ?
                       byteCount | BASSNative.BASS_STREAMPROC_END :
                       byteCount);
            });

            // Create a decoding stream based on our sample channel.
            stream = BASSNative.StreamCreate(sampleInfo.freq, sampleInfo.chans, sampleInfo.flags | BASSNative.BASS_STREAM_DECODE, sampleDataStreamProc, IntPtr.Zero);
            if (!BASSUtil.IsValidHandle(stream))
            {
                throw new BASSException();
            }

            // Create an FX stream to shift the sound effect's pitch.
            stream = BASSFXNative.TempoCreate(stream, BASSNative.BASS_FX_FREESOURCE);
            if (!BASSUtil.IsValidHandle(stream))
            {
                throw new BASSException();
            }

            // Set the new stream's attributes.
            BASSUtil.SetVolume(stream, volume);
            BASSUtil.SetPitch(stream, pitch);
            BASSUtil.SetPan(stream, pan);
            BASSUtil.SetIsLooping(stream, loop);

            // Stop the old channel and switch to the stream.
            if (!BASSNative.ChannelStop(channel))
            {
                throw new BASSException();
            }
            channel = stream;

            // If we were previously playing, play the stream.
            if (playing)
            {
                if (!BASSNative.ChannelPlay(channel, false))
                {
                    throw new BASSException();
                }
            }

            promoted = true;
            return(true);
        }