/// <summary> /// Plays the specified song. /// </summary> /// <param name="song">The song to play.</param> /// <param name="volume">A value from 0.0 (silent) to 1.0 (full volume) representing the song's volume.</param> /// <param name="pitch">A value from -1.0 (down one octave) to 1.0 (up one octave) indicating the song's pitch adjustment.</param> /// <param name="pan">A value from -1.0 (full left) to 1.0 (full right) representing the song's panning position.</param> /// <param name="loop">A value indicating whether to loop the song.</param> /// <returns>true if the song began playing successfully; otherwise, false.</returns> public override Boolean Play(Song song, Single volume, Single pitch, Single pan, Boolean loop = false) { Contract.EnsureNotDisposed(this, Disposed); Contract.Require(song, "song"); return PlayInternal(song, volume, pitch, pan, loop); }
/// <summary> /// Plays the specified song. /// </summary> /// <param name="song">The song to play.</param> /// <param name="loop">A value indicating whether to loop the song.</param> /// <returns>true if the song began playing successfully; otherwise, false.</returns> public override Boolean Play(Song song, Boolean loop = false) { Contract.EnsureNotDisposed(this, Disposed); Contract.Require(song, "song"); return PlayInternal(song, 1f, 0f, 0f, loop); }
/// <summary> /// Plays the specified song. /// </summary> private Boolean PlayInternal(Song song, Single volume, Single pitch, Single pan, Boolean loop) { Ultraviolet.ValidateResource(song); Stop(); stream = ((BASSSong)song).CreateStream(BASSNative.BASS_STREAM_DECODE); stream = BASSFXNative.TempoCreate(stream, BASSNative.BASS_FX_FREESOURCE | BASSNative.BASS_STREAM_AUTOFREE); if (!BASSUtil.IsValidHandle(stream)) throw new BASSException(); BASSUtil.SetIsLooping(stream, loop); BASSUtil.SetVolume(stream, MathUtil.Clamp(volume, 0f, 1f)); BASSUtil.SetPitch(stream, MathUtil.Clamp(pitch, -1f, 1f)); BASSUtil.SetPan(stream, MathUtil.Clamp(pan, -1f, 1f)); if (!BASSNative.ChannelPlay(stream, true)) throw new BASSException(); return true; }
/// <inheritdoc/> public override Boolean Play(Song song, Single volume, Single pitch, Single pan, TimeSpan loopStart, TimeSpan? loopLength) { Contract.EnsureNotDisposed(this, Disposed); Contract.Require(song, nameof(song)); return PlayInternal(song, volume, pitch, pan, loopStart, loopLength ?? Duration - loopStart); }
/// <summary> /// Plays the specified song. /// </summary> private Boolean PlayInternal(Song song, Single volume, Single pitch, Single pan, TimeSpan? loopStart, TimeSpan? loopLength) { Ultraviolet.ValidateResource(song); Stop(); stream = ((BASSSong)song).CreateStream(BASSNative.BASS_STREAM_DECODE); stream = BASSFXNative.TempoCreate(stream, BASSNative.BASS_FX_FREESOURCE | BASSNative.BASS_STREAM_AUTOFREE); if (!BASSUtil.IsValidHandle(stream)) throw new BASSException(); var autoloop = loopStart.HasValue && !loopLength.HasValue; var syncloop = loopStart.HasValue && !autoloop; BASSUtil.SetIsLooping(stream, autoloop); BASSUtil.SetVolume(stream, MathUtil.Clamp(volume, 0f, 1f)); BASSUtil.SetPitch(stream, MathUtil.Clamp(pitch, -1f, 1f)); BASSUtil.SetPan(stream, MathUtil.Clamp(pan, -1f, 1f)); if (loopStart > TimeSpan.Zero && loopLength <= TimeSpan.Zero) throw new ArgumentException(nameof(loopLength)); if (syncloop) { var loopStartInBytes = BASSNative.ChannelSeconds2Bytes(stream, loopStart.Value.TotalSeconds); var loopEndInBytes = BASSNative.ChannelSeconds2Bytes(stream, (loopStart + loopLength).Value.TotalSeconds); syncLoopDelegate = SyncLoopThunk; syncLoop = BASSNative.ChannelSetSync(stream, BASSSync.SYNC_POS, loopEndInBytes, syncLoopDelegate, new IntPtr((Int32)loopStartInBytes)); if (syncLoop == 0) throw new BASSException(); } syncEndDelegate = SyncEndThunk; syncEnd = BASSNative.ChannelSetSync(stream, BASSSync.SYNC_END, 0, syncEndDelegate, GCHandle.ToIntPtr(gcHandle)); if (syncEnd == 0) throw new BASSException(); if (!BASSNative.ChannelPlay(stream, true)) throw new BASSException(); OnStateChanged(); OnSongStarted(); return true; }
/// <inheritdoc/> public override Boolean Play(Song song, TimeSpan loopStart, TimeSpan? loopLength) { Contract.EnsureNotDisposed(this, Disposed); Contract.Require(song, nameof(song)); return PlayInternal(song, 1f, 0f, 0f, loopStart, loopLength ?? Duration - loopStart); }
/// <inheritdoc/> public override Boolean Play(Song song, Single volume, Single pitch, Single pan, Boolean loop = false) { Contract.EnsureNotDisposed(this, Disposed); Contract.Require(song, nameof(song)); return PlayInternal(song, volume, pitch, pan, loop ? TimeSpan.Zero : (TimeSpan?)null, null); }
/// <inheritdoc/> public override Boolean Play(Song song, Boolean loop = false) { Contract.EnsureNotDisposed(this, Disposed); Contract.Require(song, nameof(song)); return PlayInternal(song, 1f, 0f, 0f, loop ? TimeSpan.Zero : (TimeSpan?)null, null); }
/// <summary> /// Plays the specified <see cref="Song"/>. /// </summary> /// <param name="song">The <see cref="Song"/> to play.</param> /// <param name="volume">A value from 0.0 (silent) to 1.0 (full volume) representing the song's volume.</param> /// <param name="pitch">A value from -1.0 (down one octave) to 1.0 (up one octave) indicating the song's pitch adjustment.</param> /// <param name="pan">A value from -1.0 (full left) to 1.0 (full right) representing the song's panning position.</param> /// <param name="loopStart">The time at which the song beings looping.</param> /// <param name="loopLength">The length of the portion of the song which loops, or <see langword="null"/> /// to loop until the end of the song.</param> /// <returns><see langword="true"/> if the song began playing successfully; otherwise, <see langword="false"/>.</returns> public abstract Boolean Play(Song song, Single volume, Single pitch, Single pan, TimeSpan loopStart, TimeSpan? loopLength = null);
/// <summary> /// Plays the specified <see cref="Song"/>. /// </summary> /// <param name="song">The <see cref="Song"/> to play.</param> /// <param name="volume">A value from 0.0 (silent) to 1.0 (full volume) representing the song's volume.</param> /// <param name="pitch">A value from -1.0 (down one octave) to 1.0 (up one octave) indicating the song's pitch adjustment.</param> /// <param name="pan">A value from -1.0 (full left) to 1.0 (full right) representing the song's panning position.</param> /// <param name="loop">A value indicating whether to loop the song.</param> /// <returns><see langword="true"/> if the song began playing successfully; otherwise, <see langword="false"/>.</returns> public abstract Boolean Play(Song song, Single volume, Single pitch, Single pan, Boolean loop = false);
/// <summary> /// Plays the specified <see cref="Song"/>. /// </summary> /// <param name="song">The <see cref="Song"/> to play.</param> /// <param name="loopStart">The time at which the song beings looping.</param> /// <param name="loopLength">The length of the portion of the song which loops, or <see langword="null"/> /// to loop until the end of the song.</param> /// <returns><see langword="true"/> if the song began playing successfully; otherwise, <see langword="false"/>.</returns> public abstract Boolean Play(Song song, TimeSpan loopStart, TimeSpan? loopLength = null);
/// <summary> /// Plays the specified <see cref="Song"/>. /// </summary> /// <param name="song">The <see cref="Song"/> to play.</param> /// <param name="loop">A value indicating whether to loop the song.</param> /// <returns><see langword="true"/> if the song began playing successfully; otherwise, <see langword="false"/>.</returns> public abstract Boolean Play(Song song, Boolean loop = false);