public override void Play(bool restart = true) { PendingActions.Enqueue(() => { if (!IsLoaded) { channel = 0; return; } // We are creating a new channel for every playback, since old channels may // be overridden when too many other channels are created from the same sample. channel = ((SampleBass)Sample).CreateChannel(); Bass.ChannelGetAttribute(channel, ChannelAttribute.Frequency, out initialFrequency); }); InvalidateState(); PendingActions.Enqueue(() => { if (channel != 0) { Bass.ChannelPlay(channel, restart); } }); // Needs to happen on the main thread such that // Played does not become true for a short moment. playing = true; base.Play(restart); }
public override bool Seek(double seek) { // At this point the track may not yet be loaded which is indicated by a 0 length. // In that case we still want to return true, hence the conservative length. double conservativeLength = Length == 0 ? double.MaxValue : Length; double conservativeClamped = MathHelper.Clamp(seek, 0, conservativeLength); Action action = null; action = () => { // we only want to run the most fresh seek event, else we may fall behind (seeks can be relatively expensive). if (action != seekAction) { return; } double clamped = MathHelper.Clamp(seek, 0, Length); if (clamped != CurrentTime) { long pos = Bass.ChannelSeconds2Bytes(activeStream, clamped / 1000d); Bass.ChannelSetPosition(activeStream, pos); } }; seekAction = action; PendingActions.Enqueue(action); return(conservativeClamped == seek); }
/// <summary> /// Specify an AudioTrack which should get exclusive playback over everything else. /// Will pause all other tracks and throw away any existing exclusive track. /// </summary> public void SetExclusive(Track track) { if (track == null) { throw new ArgumentNullException(nameof(track)); } Track last; lock (exclusiveMutex) { if (exclusiveTrack == track) { return; } last = exclusiveTrack; exclusiveTrack = track; } PendingActions.Enqueue(() => { foreach (var item in Items) { if (!item.HasCompleted) { item.Stop(); } } last?.Dispose(); AddItem(track); }); }
public override void Play(bool restart = true) { base.Play(); PendingActions.Enqueue(() => { if (!hasSample) { channel = 0; return; } if (!hasChannel) { channel = Bass.SampleGetChannel(SampleId); Bass.ChannelGetAttribute(channel, ChannelAttribute.Frequency, out initialFrequency); } }); InvalidateState(); PendingActions.Enqueue(() => { Bass.ChannelPlay(channel, restart); }); }
public override void Start() { isPlayed = true; PendingActions.Enqueue(() => { Bass.ChannelPlay(activeStream); }); }
public override void Start() { Update(); //ensure state is valid. isPlayed = true; PendingActions.Enqueue(() => { Bass.ChannelPlay(activeStream); }); }
public SampleBass(byte[] data, ConcurrentQueue <Action> customPendingActions = null) { if (customPendingActions != null) { PendingActions = customPendingActions; } PendingActions.Enqueue(() => { sampleId = Bass.SampleLoad(data, 0, data.Length, 8, BassFlags.Default); }); }
public SampleBass(byte[] data, ConcurrentQueue <Action> customPendingActions = null, int concurrency = DEFAULT_CONCURRENCY) : base(concurrency) { if (customPendingActions != null) { PendingActions = customPendingActions; } PendingActions.Enqueue(() => { sampleId = Bass.SampleLoad(data, 0, data.Length, PlaybackConcurrency, BassFlags.Default | BassFlags.SampleOverrideLongestPlaying); }); }
public void AddItemToList(T item) { PendingActions.Enqueue(delegate { if (Items.Contains(item)) { return; } Items.Add(item); }); }
public override void Stop() { isPlayed = false; PendingActions.Enqueue(() => { if (IsRunning) { Bass.ChannelPause(activeStream); } }); }
public override void Pause() { if (!hasChannel) { return; } base.Pause(); PendingActions.Enqueue(() => { Bass.ChannelPause(channel); }); }
protected override void Dispose(bool disposing) { base.Dispose(disposing); if (freeWhenDone) { var s = SampleId; PendingActions.Enqueue(() => { Bass.SampleFree(s); }); SampleId = 0; } }
protected override void OnStateChanged(object sender, EventArgs e) { base.OnStateChanged(sender, e); if (hasChannel) { PendingActions.Enqueue(() => { Bass.ChannelSetAttribute(channel, ChannelAttribute.Volume, VolumeCalculated); Bass.ChannelSetAttribute(channel, ChannelAttribute.Pan, BalanceCalculated); Bass.ChannelSetAttribute(channel, ChannelAttribute.Frequency, initialFrequency * FrequencyCalculated); }); } }
public override void Stop() { base.Stop(); PendingActions.Enqueue(() => { if (Bass.ChannelIsActive(activeStream) == PlaybackState.Playing) { Bass.ChannelPause(activeStream); } isPlayed = false; }); }
public override void Stop() { if (!hasChannel) { return; } base.Stop(); PendingActions.Enqueue(() => { Bass.ChannelStop(channel); }); }
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(); }
public override bool Seek(double seek) { double clamped = MathHelper.Clamp(seek, 0, Length); PendingActions.Enqueue(() => { if (clamped != CurrentTime) { long pos = Bass.ChannelSeconds2Bytes(activeStream, clamped / 1000d); Bass.ChannelSetPosition(activeStream, pos); } }); return(clamped == seek); }
public override void Start() { base.Start(); PendingActions.Enqueue(() => { if (Bass.ChannelPlay(activeStream)) { isPlayed = true; } else { isRunning = false; } }); }
private void setDirection(bool reverse) { int newDirection = reverse ? -1 : 1; if (direction == newDirection) { return; } direction = newDirection; PendingActions.Enqueue(() => { Bass.ChannelSetAttribute(activeStream, ChannelAttribute.ReverseDirection, direction); }); }
public override void Stop() { if (channel == 0) { return; } base.Stop(); PendingActions.Enqueue(() => { Bass.ChannelStop(channel); // ChannelStop frees the channel. channel = 0; }); }
public AudioTrackBass(Stream data, bool quick = false) { PendingActions.Enqueue(() => { Preview = quick; BassFlags flags = Preview ? 0 : (BassFlags.Decode | BassFlags.Prescan); 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); 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); SampleRate = initialFrequency; Bass.ChannelSetDSP(activeStream, dspProcessor); }); InvalidateState(); }
public override bool Seek(double seek) { // At this point the track may not yet be loaded which is indicated by a 0 length. // In that case we still want to return true, hence the conservative length. double conservativeLength = Length == 0 ? double.MaxValue : Length; double conservativeClamped = MathHelper.Clamp(seek, 0, conservativeLength); PendingActions.Enqueue(() => { double clamped = MathHelper.Clamp(seek, 0, Length); if (clamped != CurrentTime) { long pos = Bass.ChannelSeconds2Bytes(activeStream, clamped / 1000d); Bass.ChannelSetPosition(activeStream, pos); } }); return(conservativeClamped == seek); }
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); }
internal void InvalidateState(object sender = null, EventArgs e = null) { PendingActions.Enqueue(() => OnStateChanged(this, null)); }
public void RegisterItem(T item) { PendingActions.Enqueue(() => item.AddAdjustmentDependency(this)); }
public AudioSampleBass(byte[] data) { PendingActions.Enqueue(() => { SampleId = Bass.SampleLoad(data, 0, data.Length, 8, BassFlags.Default); }); }
internal void InvalidateState(double newValue = 0) { PendingActions.Enqueue(OnStateChanged); }
public void UnregisterItem(T item) { PendingActions.Enqueue(() => item.RemoveAdjustmentDependency(this)); }