/// <summary> /// Loads a track for playing as the raw loop track. /// </summary> /// <param name="filename">The filename.</param> /// <returns></returns> /// <exception cref="System.Exception">Cannot find file + filename</exception> public Track LoadRawLoopTrack(string filename) { if (!File.Exists(filename)) throw new Exception("Cannot find file " + filename); if (RawLoopTrack != null) UnloadRawLoopTrack(); var track = new Track { Id = _nextTrackId++, Filename = filename }; SetArtistAndTitle(track, "", ""); LoadTagData(track); ExtenedAttributesHelper.LoadExtendedAttributes(track); LoadTrackAudioData(track); DebugHelper.WriteLine("Loaded raw loop track " + track.Description); // set track sync event track.SyncProc = OnTrackSync; track.CurrentStartLoop = 0; track.CurrentEndLoop = 0; track.RawLoopStart = 0; track.RawLoopEnd = track.Length; DebugHelper.WriteLine("Loading raw loop track " + track.Description); AudioStreamHelper.AddToMixer(track, _rawLoopMixer.ChannelId); RawLoopTrack = track; SetRawLoopPositions(0, track.Length, 0); return RawLoopTrack; }
public static AutomationAttributes ReloadAutomationAttributes(Track track, string folder) { if (track == null || folder == "") return null; if (_cachedAttributes.ContainsKey(track.Description)) { _cachedAttributes.Remove(track.Description); } return GetAutomationAttributes(track, folder); }
/// <summary> /// Clears the track FX triggers for the specified track. /// </summary> public void ClearTrackFxTriggers(Track track) { if (track == null) return; var attributes = GetAutomationAttributes(track); if (attributes.TrackFXTriggers.Count == 0) return; if (IsTrackInUse(track)) ClearTrackSyncPositions(track); attributes.TrackFXTriggers.Clear(); SaveAutomationAttributes(track); if (IsTrackInUse(track)) ResetTrackSyncPositions(); }
private void LoadSamples(Track track) { if (track == null) return; DebugHelper.WriteLine("Loading samples for " + track.Description); var trackSamples = GetTrackSamples(track); foreach (var trackSample in trackSamples) { LoadSample(track, trackSample); } }
/// <summary> /// Gets the BPM of the sample /// </summary> public decimal CalculateBpm(Track track) { if (Key == "PreFadeIn") { return track.StartBpm; } if (Length != 0 && IsLooped) { return BpmHelper.GetBpmFromLoopLength(Length); } return track.Bpm; }
public void LoadSamples(Track currentTrack, Track nextTrack) { if (!HaveTracksChanged(currentTrack, nextTrack)) return; _audioPlayer.UnloadAll(); _currentTrack = currentTrack; _nextTrack = nextTrack; LoadSamples(_currentTrack); LoadSamples(_nextTrack); }
private static IEnumerable<TrackSample> GetTrackSamples(Track track) { DebugHelper.WriteLine("GetTrackSamples for " + track.Description); var trackSamples = new List<TrackSample>(); if (track.UsePreFadeIn) { trackSamples.Add(new TrackSample { IsLooped = false, Start = track.SamplesToSeconds(track.PreFadeInStart), Length = track.PreFadeInLengthSeconds, Description = "Pre Fade In", Key = "PreFadeIn" }); } trackSamples.Add(new TrackSample { IsLooped = track.IsLoopedAtStart, Start = track.SamplesToSeconds(track.FadeInStart), Length = track.FadeInLengthSeconds, Description = "Fade In", Key = "FadeIn" }); trackSamples.Add(new TrackSample { IsLooped = track.IsLoopedAtEnd, Start = track.SamplesToSeconds(track.FadeOutStart), Length = track.FadeOutLengthSeconds, Description = "Fade Out", Key = "FadeOut" }); trackSamples.AddRange(GetAdditionalTrackSamples(track.Description)); return trackSamples; }
/// <summary> /// Initializes this instance. /// </summary> public void Initialize() { CurrentTrack = BassPlayer.CurrentTrack; PreviousTrack = BassPlayer.PreviousTrack; NextTrack = BassPlayer.NextTrack; BassPlayer.OnTrackQueued += BassPlayer_OnTrackChange; BassPlayer.OnTrackChange += BassPlayer_OnTrackChange; BassPlayer.OnManualMixVolumeChanged += BassPlayer_OnManualMixVolumeChanged; BassPlayer.OnTrackFxVolumeChanged += BassPlayer_OnTrackFxVolumeChanged; BassPlayer.OnManualMixModeChanged += BassPlayer_OnManualMixModeChanged; sldFader.Minimum = 0; sldFader.Maximum = 100; sldTrackFXVolume.Scrolled += sldTrackFXVolume_Scrolled; sldTrackFXVolume.Minimum = 0; sldTrackFXVolume.Maximum = 100; var volume = Convert.ToInt32(BassPlayer.GetTrackSendFxVolume()); lblVolume.Text = volume.ToString(); sldTrackFXVolume.Value = volume; rdbDelay2.Checked = true; chkEnableTrackFXAutomation.Checked = BassPlayer.TrackFxAutomationEnabled; cmbFadeOutType.SelectedIndex = 0; BassPlayer.DisableManualMixMode(); BindData(); _timer.Tick += Timer_Tick; _timer.Interval = 200; _timer.Start(); }
private void LoadSample(Track track, TrackSample trackSample) { var sampleId = track.Description + " - " + trackSample.Key; var sample = (Sample) _audioPlayer.Load(sampleId, track.Filename); sample.LinkedTrackDescription = track.Description; sample.Gain = track.Gain; sample.SampleKey = trackSample.Key; sample.IsLooped = trackSample.IsLooped; sample.Bpm = trackSample.CalculateBpm(track); sample.Description = trackSample.Description; _audioPlayer.AddSection(sampleId, sampleId, start: trackSample.Start, length: trackSample.Length, bpm: sample.Bpm, loopIndefinitely: trackSample.IsLooped); _audioPlayer.QueueSection(sampleId, sampleId); }
/// <summary> /// Loads any attributes stored in a the track comment tag. /// </summary> /// <param name="track">The track.</param> public static void LoadExtendedAttributes(Track track) { if (track == null) return; if (track.Artist == "" || track.Title == "") return; DebugHelper.WriteLine("Loading Extended Attributes " + track.Description); var attributes = GetExtendedAttributes(track); if (attributes.ContainsKey("FadeIn")) { track.FadeInStart = track.SecondsToSamples(ConversionHelper.ToDouble(attributes["FadeIn"])); } if (attributes.ContainsKey("FadeOut")) { track.FadeOutStart = track.SecondsToSamples(ConversionHelper.ToDouble(attributes["FadeOut"])); } if (attributes.ContainsKey("BPMAdjust")) { track.BpmAdjustmentRatio = ConversionHelper.ToDecimal(attributes["BPMAdjust"]); } if (attributes.ContainsKey("FadeInLengthInSeconds")) { track.FadeInEnd = track.FadeInStart + track.SecondsToSamples(ConversionHelper.ToDouble(attributes["FadeInLengthInSeconds"])); } if (attributes.ContainsKey("FadeOutLengthInSeconds")) { track.FadeOutEnd = track.FadeOutStart + track.SecondsToSamples(ConversionHelper.ToDouble(attributes["FadeOutLengthInSeconds"])); } if (attributes.ContainsKey("PreFadeInStartVolume")) { track.PreFadeInStartVolume = ConversionHelper.ToFloat(attributes["PreFadeInStartVolume"])/100; track.UsePreFadeIn = true; } if (attributes.ContainsKey("PreFadeInPosition")) { track.PreFadeInStart = track.SecondsToSamples(ConversionHelper.ToDouble(attributes["PreFadeInPosition"])); track.UsePreFadeIn = true; } if (attributes.ContainsKey("PreFadeInStart")) { track.PreFadeInStart = track.SecondsToSamples(ConversionHelper.ToDouble(attributes["PreFadeInStart"])); track.UsePreFadeIn = true; } if (attributes.ContainsKey("StartBPM")) { track.StartBpm = BpmHelper.NormaliseBpm(ConversionHelper.ToDecimal(attributes["StartBPM"])); } if (attributes.ContainsKey("EndBPM")) { track.EndBpm = BpmHelper.NormaliseBpm(ConversionHelper.ToDecimal(attributes["EndBPM"])); } if (attributes.ContainsKey("Duration")) { if (track.Length == 0) track.Length = (long) (ConversionHelper.ToDouble(attributes["Duration"])*1000); } if (attributes.ContainsKey("PowerDown")) { track.PowerDownOnEnd = ConversionHelper.ToBoolean(attributes["PowerDown"]); track.PowerDownOnEndOriginal = track.PowerDownOnEnd; } if (attributes.ContainsKey("StartLoopCount")) { track.StartLoopCount = ConversionHelper.ToInt(attributes["StartLoopCount"]); } if (attributes.ContainsKey("EndLoopCount")) { track.EndLoopCount = ConversionHelper.ToInt(attributes["EndLoopCount"]); } if (attributes.ContainsKey("SkipStart")) { track.SkipStart = track.SecondsToSamples(ConversionHelper.ToDouble(attributes["SkipStart"])); } if (attributes.ContainsKey("SkipLengthInSeconds")) { track.SkipEnd = track.SkipStart + track.SecondsToSamples(ConversionHelper.ToDouble(attributes["SkipLengthInSeconds"])); } if (attributes.ContainsKey("Rank")) { track.Rank = ConversionHelper.ToInt(attributes["Rank"], 1); } if (attributes.ContainsKey("Key")) { track.Key = attributes["Key"]; } }
/// <summary> /// Saves the track details to the track comment tag /// </summary> /// <param name="track">The track.</param> public static void SaveExtendedAttributes(Track track) { var attributes = new Dictionary<string, string>(); if (track.StartBpm != 0) attributes.Add("StartBPM", $"{track.StartBpm}"); if (track.EndBpm != 0) attributes.Add("EndBPM", $"{track.EndBpm}"); attributes.Add("Duration", $"{track.LengthSeconds}"); if (track.FadeInStart != 0) attributes.Add("FadeIn", $"{track.SamplesToSeconds(track.FadeInStart):0.000}"); if (track.FadeOutStart != 0) attributes.Add("FadeOut", $"{track.SamplesToSeconds(track.FadeOutStart):0.000}"); if (track.BpmAdjustmentRatio != 1) attributes.Add("BPMAdjust", $"{track.BpmAdjustmentRatio}"); if (track.FadeInLength != 0) attributes.Add("FadeInLengthInSeconds", $"{track.FadeInLengthSeconds:0.000}"); if (track.StartLoopCount > 0) attributes.Add("StartLoopCount", $"{track.StartLoopCount}"); if (track.FadeOutLength != 0) attributes.Add("FadeOutLengthInSeconds", $"{track.SamplesToSeconds(track.FadeOutLength):0.000}"); if (track.EndLoopCount > 0) attributes.Add("EndLoopCount", $"{track.EndLoopCount}"); if (track.UsePreFadeIn) { attributes.Add("PreFadeInStartVolume", $"{track.PreFadeInStartVolume*100:00}"); attributes.Add("PreFadeInPosition", $"{track.SamplesToSeconds(track.PreFadeInStart):0.000}"); } if (track.PowerDownOnEnd) attributes.Add("PowerDown", $"{track.PowerDownOnEnd}"); if (track.HasSkipSection) { attributes.Add("SkipStart", $"{track.SamplesToSeconds(track.SkipStart):0.000}"); attributes.Add("SkipLengthInSeconds", $"{track.SamplesToSeconds(track.SkipLength):0.000}"); } if (track.Rank != 1) attributes.Add("Rank", $"{track.Rank}"); if (track.Key != "") attributes.Add("Key", track.Key); var extendedAttributeFile = GetExtendedAttributeFile(track.Description); SaveExtendedAttributes(attributes, extendedAttributeFile); }
/// <summary> /// Determines whether the specified track has an extended attribute file. /// </summary> /// <param name="track">The track.</param> /// <returns> /// True if the specified track has an extended attribute file; otherwise, false. /// </returns> public static bool HasExtendedAttributeFile(Track track) { return File.Exists(GetExtendedAttributeFile(track.Description)); }
/// <summary> /// Loads the track audio data. /// </summary> /// <param name="track">The track to load.</param> /// <returns> /// The loaded track /// </returns> public Track LoadTrackAudioData(Track track) { // abort if audio data already loaded if (track.IsAudioLoaded()) return track; // ensure mp3 tag data is loaded if (!track.TagDataLoaded) LoadTagData(track); DebugHelper.WriteLine("Loading track Audio Data " + track.Description); lock (track) { AudioStreamHelper.LoadAudio(track); track.FadeInStart = 0; track.FadeInStartVolume = (float) (DefaultFadeInStartVolume/100); track.FadeInEndVolume = (float) (DefaultFadeInEndVolume/100); track.FadeOutEnd = 0; track.FadeOutStartVolume = (float) (DefaultFadeOutStartVolume/100); track.FadeOutEndVolume = (float) (DefaultFadeOutEndVolume/100); ExtenedAttributesHelper.LoadExtendedAttributes(track); if (track.FadeOutStart == 0) { if (LimitSongLength && track.LengthSeconds > MaxSongLength) { track.FadeOutStart = track.SecondsToSamples(MaxSongLength - DefaultFadeLength - 1); } else { track.FadeOutStart = track.SecondsToSamples(track.LengthSeconds - DefaultFadeLength - 1); } } if (track.FadeInEnd == track.FadeInStart || track.FadeInEnd == 0) { track.FadeInEnd = track.FadeInStart + track.SecondsToSamples(BpmHelper.GetBestFitLoopLength(track.StartBpm, DefaultFadeLength)); } if (track.FadeOutEnd == track.FadeInStart || track.FadeOutEnd == 0) { track.FadeOutEnd = track.FadeOutStart + track.SecondsToSamples(BpmHelper.GetBestFitLoopLength(track.EndBpm, DefaultFadeLength)); } if (!track.UsePreFadeIn) { track.PreFadeInStart = track.FadeInStart; track.PreFadeInStartVolume = 0; } } AddToRecentTracks(track); DebugHelper.WriteLine("Finished loading track Audio Data " + track.Description); return track; }
public double GetExtendedFadeOutLength(Track fromTrack, Track toTrack) { if (fromTrack == null) return 0; var attributes = GetExtendedMixAttributes(fromTrack, toTrack); if (attributes != null) return attributes.FadeLength; var fadeOutLength = fromTrack.FullEndLoopLengthSeconds; if (fadeOutLength == 0) fadeOutLength = BpmHelper.GetDefaultLoopLength(fromTrack.EndBpm); if (toTrack != null) fadeOutLength = BpmHelper.GetLengthAdjustedToMatchAnotherTrack(fromTrack, toTrack, fadeOutLength); return fadeOutLength; }
/// <summary> /// Clears the automation sync positions. /// </summary> /// <param name="track">The track.</param> private void ClearAutomationSyncPositions(Track track) { foreach (var trigger in GetAutomationAttributes(track).TrackFXTriggers) { if (trigger.StartSyncId != int.MinValue) { BassMix.BASS_Mixer_ChannelRemoveSync(track.Channel, trigger.StartSyncId); trigger.StartSyncId = int.MinValue; } if (trigger.EndSyncId == int.MinValue) continue; BassMix.BASS_Mixer_ChannelRemoveSync(track.Channel, trigger.EndSyncId); trigger.EndSyncId = int.MinValue; } foreach (var trigger in GetCurrentSampleTriggers()) { if (trigger.StartSyncId != int.MinValue) { BassMix.BASS_Mixer_ChannelRemoveSync(track.Channel, trigger.StartSyncId); trigger.StartSyncId = int.MinValue; } if (trigger.EndSyncId == int.MinValue) continue; BassMix.BASS_Mixer_ChannelRemoveSync(track.Channel, trigger.EndSyncId); trigger.EndSyncId = int.MinValue; } }
/// <summary> /// Reloads the automation attributes. /// </summary> /// <param name="track">The track.</param> public void ReloadAutomationAttributes(Track track) { if (track == null) return; AutomationAttributes.SaveAutomationAttributes(track, ExtenedAttributesHelper.ExtendedAttributeFolder); }
private static double GetAdjustedPositionSeconds(Track track) { return track?.SamplesToSeconds(GetAdjustedPosition(track)) ?? 0; }
private static long GetAdjustedPosition(Track track) { if (track == null) return 0; var channelPosition = AudioStreamHelper.GetPosition(track); return GetAdjustedPosition(channelPosition, track); }
/// <summary> /// Gets the adjusted position. /// </summary> /// <param name="channelPosition">The channel position.</param> /// <param name="track">The track.</param> /// <returns>The adjusted position</returns> private static long GetAdjustedPosition(long channelPosition, Track track) { var position = channelPosition - track.FadeInStart; if (track.IsLoopedAtStart) { if (track.CurrentStartLoop < track.StartLoopCount) { position += (track.CurrentStartLoop)*track.FadeInLength; } else { position += track.AdditionalStartLoopLength; } } if (track.HasSkipSection && channelPosition > track.SkipStart) { position -= track.SkipLength; } return position; }
/// <summary> /// Forces a track to be played /// </summary> /// <param name="track">The track.</param> public void ForcePlay(Track track) { ForcePlay(track.Filename); }
private static void AddToRecentTracks(Track track) { const int length = 5; if (track == null) return; lock (_recentTracks) { if (_recentTracks.Exists(rt => rt.Description == track.Description)) { _recentTracks.RemoveAll(rt => rt.Description == track.Description); } _recentTracks.Insert(0, track); if (_recentTracks.Count > length) { _recentTracks = _recentTracks.Take(length).ToList(); } } }
/// <summary> /// Unloads the track audio data. /// </summary> /// <param name="track">The track.</param> public void UnloadTrackAudioData(Track track) { if (!track.IsAudioLoaded()) return; DebugHelper.WriteLine("Unloading track Audio Data " + track.Description); AudioStreamHelper.RemoveFromMixer(track, _trackMixer.ChannelId); AudioStreamHelper.UnloadAudio(track); track.SyncProc = null; }
/// <summary> /// Gets the automation attributes for a track. /// </summary> /// <param name="track">The track.</param> /// <returns>The automation attributes</returns> public AutomationAttributes GetAutomationAttributes(Track track) { return track == null ? null : GetAutomationAttributes(track.Description); }
/// <summary> /// Loads data for a track from its mp3 tags /// </summary> /// <param name="track">The track.</param> public void LoadTagData(Track track) { if (track == null) return; if ((Path.GetExtension(track.Filename) + "").ToLower() == ".wav") return; lock (track) { if (track.TagDataLoaded) return; DebugHelper.WriteLine("Loading track tags - " + track.Description); var tags = TagHelper.LoadTags(track.Filename); track.Title = tags.Title; track.Artist = tags.Artist; if (track.Title == "" || track.Artist == "") { GuessArtistAndTitleFromFilename(track); } if (tags.Gain.HasValue) track.Gain = tags.Gain.Value; track.Key = tags.Key; if (tags.Bpm.HasValue) track.TagBpm = tags.Bpm.Value; if(tags.Length.HasValue) track.Length = (long)tags.Length.Value * 1000; track.TagDataLoaded = true; TrackTagsLoaded?.Invoke(track, EventArgs.Empty); } }
/// <summary> /// Sets the automation sync positions. /// </summary> /// <param name="track">The track.</param> private void SetAutomationSyncPositions(Track track) { if (track != CurrentTrack) return; foreach (var trigger in GetAutomationAttributes(track).TrackFXTriggers) { trigger.StartSample = track.SecondsToSamples(trigger.Start); trigger.EndSample = track.SecondsToSamples(trigger.Start + trigger.Length); trigger.StartSyncId = SetTrackSync(track, trigger.StartSample, SyncType.StartTrackFxTrigger); trigger.EndSyncId = SetTrackSync(track, trigger.EndSample, SyncType.EndTrackFxTrigger); } foreach (var trigger in GetCurrentSampleTriggers()) { trigger.StartSample = track.SecondsToSamples(trigger.Start); trigger.EndSample = track.SecondsToSamples(trigger.Start + trigger.Length); trigger.StartSyncId = SetTrackSync(track, trigger.StartSample, SyncType.StartSampleTrigger); trigger.EndSyncId = SetTrackSync(track, trigger.EndSample, SyncType.EndSampleTrigger); } }
/// <summary> /// Gets the audio stream tempo change as an audio stream rate /// </summary> /// <param name="track1">The audio stream being fading out</param> /// <param name="track2">The audio stream being faded into.</param> /// <returns>The audio stream rate the first audioStream needs to be changed to in order to match the second audioStream</returns> private static float GetTrackTempoChangeAsSampleRate(Track track1, Track track2) { if (track1 == null || track2 == null) return DefaultSampleRate; return track1.DefaultSampleRate * BpmHelper.GetTrackTempoChangeAsRatio(track1, track2); }
public ExtendedFadeType GetExtendedFadeType(Track fromTrack, Track toTrack) { if (fromTrack == null || toTrack == null) return ExtendedFadeType.Default; var hasExtendedMix = HasExtendedMixAttributes(fromTrack, toTrack); if (!hasExtendedMix) return ExtendedFadeType.Default; var mixAttributes = GetExtendedMixAttributes(fromTrack, toTrack); return mixAttributes.ExtendedFadeType; }
/// <summary> /// Sets the audio stream tempo to match another audio stream's tempo /// </summary> /// <param name="changeTrack">The audio stream to change the temp of.</param> /// <param name="matchTrack">The audio stream to match the BPM of</param> public static void SetTrackTempoToMatchAnotherTrack(Track changeTrack, Track matchTrack) { if (changeTrack == null || matchTrack == null) return; if (!changeTrack.IsAudioLoaded()) return; if (!matchTrack.IsAudioLoaded()) return; var percentChange = (float)(BpmHelper.GetAdjustedBpmPercentChange(changeTrack.EndBpm, matchTrack.StartBpm)); Bass.BASS_ChannelSetAttribute(changeTrack.Channel, BASSAttribute.BASS_ATTRIB_TEMPO, percentChange); }
/// <summary> /// Sets the audio stream pitch to match another audioStream's BPM /// </summary> /// <param name="changeTrack">The audio stream to change the pitch of.</param> /// <param name="matchTrack">The audio stream to match the BPM of</param> public static void SetTrackPitchToMatchAnotherTrack(Track changeTrack, Track matchTrack) { if (changeTrack == null || matchTrack == null) return; if (!changeTrack.IsAudioLoaded()) return; if (!matchTrack.IsAudioLoaded()) return; var sampleRate = GetTrackTempoChangeAsSampleRate(changeTrack, matchTrack); Bass.BASS_ChannelSetAttribute(changeTrack.Channel, BASSAttribute.BASS_ATTRIB_TEMPO_FREQ, sampleRate); }
/// <summary> /// Unloads a track from the cached tracks /// </summary> /// <param name="track">The track to unload.</param> public void UnloadTrack(Track track) { if (track == null) return; DebugHelper.WriteLine("Unloading track " + track.Description); AudioStreamHelper.Pause(track); if (IsTrackInUse(track)) { RemoveTrackFromMixer(track); } UnloadTrackAudioData(track); CachedTracks.Remove(track); }