/// <summary> /// Gets the current BPM. /// </summary> /// <returns>The current BPM</returns> public decimal GetCurrentBpm() { var bpm = 100M; if (CurrentTrack != null) { var trackPosition = GetPositionNoLock(); var position = trackPosition.Positition; if (position < 0) { position = 0; } if (position < CurrentTrack.FullStartLoopLength) { bpm = CurrentTrack.StartBpm; } else { var range = CurrentTrack.EndBpm - CurrentTrack.StartBpm; var percentComplete = (decimal)(position / (double)trackPosition.Length); bpm = CurrentTrack.StartBpm + range * percentComplete; } } bpm = BpmHelper.NormaliseBpm(bpm); return(bpm); }
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); }
private decimal CalculateSampleBpm() { var length = cmbSampleLength.Seconds; var start = txtSampleStartPosition.Seconds; if (length == 0D) { return(0M); } if (GetLoopModeFromDropdown() == LoopMode.FullLoop) { return(BpmHelper.GetBpmFromLoopLength(length)); } var samples = Samples.Where(x => x.LoopMode == LoopMode.FullLoop).ToList(); samples.Remove(CurrentSample); if (!samples.Any()) { return(Track.Bpm); } var firstSample = samples .OrderByDescending(x => Math.Abs(start - x.Start)) .FirstOrDefault(); return(firstSample?.Bpm ?? 100M); }
public void AddSample(string sampleKey, string path, double start, double length, double offset, bool loopIndefinitely = true) { _sampleKeys.Add(sampleKey); if (_targetBpm == int.MinValue) { _targetBpm = BpmHelper.GetBpmFromLoopLength(length); } AudioPlayer channelPlayer; if (_sampleKeys.Count > _channelPlayers.Count) { channelPlayer = new AudioPlayer(); _mixer.AddInputChannel(channelPlayer.Output); _channelPlayers.Add(channelPlayer); } else { channelPlayer = _channelPlayers[_sampleKeys.Count - 1]; } channelPlayer.UnloadAll(); channelPlayer.Load(sampleKey, path); var section = channelPlayer.AddSection(sampleKey, sampleKey, start, length, offset, calculateBpmFromLength: true, targetBpm: _targetBpm); section.LoopIndefinitely = loopIndefinitely; }
/// <summary> /// Sets the BPM values. /// </summary> private void SetBpmValues() { if (_bindingData) { return; } var fadeInLength = BpmHelper.GetDefaultLoopLength(Track.TagBpm); if (cmbCustomFadeInLength.Seconds != 0D) { fadeInLength = cmbCustomFadeInLength.Seconds; } var startBpm = BpmHelper.GetBpmFromLoopLength(fadeInLength); lblStartBPM.Text = startBpm.ToString("0.00"); var fadeOutLength = BpmHelper.GetDefaultLoopLength(Track.TagBpm); if (cmbCustomFadeOutLength.Seconds != 0D) { fadeOutLength = cmbCustomFadeOutLength.Seconds; } var endBpm = BpmHelper.GetBpmFromLoopLength(fadeOutLength); lblEndBPM.Text = endBpm.ToString("0.00"); PopulateVolumeDropDown(cmbPreFadeInStartVolume); }
private void AddSample(string sampleName, double start, double length) { var sample = new Sample { Description = sampleName }; if (LibraryTrack != null) { TrackSampleLibrary.UpdateSampleFromTrack(sample, LibraryTrack); } Samples.Add(sample); CurrentSample = sample; trackWave.CurrentSample = sample; trackWave.Samples = Samples; sample.Start = start; sample.Length = length; sample.Bpm = BpmHelper.GetBpmFromLoopLength(sample.Length); RefreshTrackWavePositions(); BindData(); }
private IEnumerable <Tuple <string, double> > GetPositions(int channelIndex) { var positions = new List <Tuple <string, double> >(); var currentPosition = 0D; for (var i = 0; i < 32; i++) { var sampleKey = _sampleKeys[channelIndex]; var audioSection = _channelPlayers[channelIndex].GetAudioSection(sampleKey, sampleKey); var sampleLength = audioSection.Length; var bpm = audioSection.Bpm; var adjustedLength = BpmHelper.GetAdjustedAudioLength(sampleLength, bpm, _targetBpm); positions.Add(new Tuple <string, double>(sampleKey, currentPosition)); currentPosition += adjustedLength; if (currentPosition > _loopLength) { break; } } return(positions); }
private void LoadSample(string file) { var lengthInSeconds = AudioStreamHelper.GetLength(file); var bpm = BpmHelper.GetBpmFromLoopLength(lengthInSeconds); var sample = new Sample { Filename = file, Description = (Path.GetFileNameWithoutExtension(file) + "").Replace(_folder, "").Replace("\\", ""), IsAtonal = true, IsPrimaryLoop = true, Gain = 0, LoopMode = LoopMode.FullLoop, Length = lengthInSeconds, TrackLength = (decimal)lengthInSeconds, Offset = 0, Start = 0, Key = "", Bpm = bpm, Tags = new List <string>(), TrackArtist = (Path.GetDirectoryName(file) + "").Replace(_folder, "").Replace("\\", ""), TrackTitle = (Path.GetFileNameWithoutExtension(file) + "").Replace(_folder, "").Replace("\\", ""), }; lock (_samples) { _samples.Add(sample); } }
public void LoadModule(Module module) { Pause(); _mainPlayer.UnloadAll(); foreach (var player in _channelPlayers) { player.UnloadAll(); } _targetBpm = module.Bpm; _loopLength = BpmHelper.GetDefaultLoopLength(_targetBpm); Module = module; foreach (var audioFile in module.AudioFiles) { if (File.Exists(audioFile.Path) || _libraryFolder == "" || !_libraryFolder.EndsWith("Library") || !audioFile.Path.Contains("Library")) { continue; } var index = audioFile.Path.IndexOf("Library", StringComparison.Ordinal) + "Libary".Length + 1; var path = _libraryFolder + audioFile.Path.Substring(index); audioFile.Path = path; } LoadChannelPlayers(module); LoadAudioFiles(module); }
public List <Sample> GetMixSectionsAsSamples(Track track) { var bassTrack = BassPlayer.LoadTrackAndAudio(track.Filename); var samples = new List <Sample>(); var fadeIn = new Sample { Description = "FadeIn", Start = bassTrack.SamplesToSeconds(bassTrack.FadeInStart), Length = bassTrack.FadeInLengthSeconds, Bpm = BpmHelper.GetBpmFromLoopLength(bassTrack.FadeInLengthSeconds), Gain = bassTrack.Gain }; UpdateSampleFromTrack(fadeIn, track); samples.Add(fadeIn); var fadeOut = new Sample { Description = "FadeOut", Start = bassTrack.SamplesToSeconds(bassTrack.FadeOutStart), Length = bassTrack.FadeOutLengthSeconds, Bpm = BpmHelper.GetBpmFromLoopLength(bassTrack.FadeOutLengthSeconds), Gain = bassTrack.Gain }; UpdateSampleFromTrack(fadeOut, track); samples.Add(fadeOut); BassPlayer.UnloadTrackAudioData(bassTrack); return(samples); }
public void SetSectionBpm(string streamKey, string sectionKey, decimal bpm = 0, bool calculateBpmFromLength = false, decimal targetBpm = 0) { var audioStream = GetAudioStream(streamKey); if (audioStream == null) { return; } var audioSection = GetAudioSection(streamKey, sectionKey); if (audioSection == null) { return; } if (calculateBpmFromLength) { var length = audioStream.SamplesToSeconds(audioSection.End.Position - audioSection.Start.Position); audioSection.Bpm = BpmHelper.GetBpmFromLoopLength(length); } else if (bpm != 0) { audioSection.Bpm = bpm; } else if (audioSection.Bpm != 0) { audioSection.Bpm = 100; } audioSection.TargetBpm = targetBpm; }
private double GetAdjustedSampleLenth(string streamKey, string sampleKey) { var audioFile = Module.AudioFiles.FirstOrDefault(x => x.Key == streamKey); var sample = audioFile?.Samples.FirstOrDefault(x => x.Key == sampleKey); if (sample == null) { return(0); } var bpm = BpmHelper.GetBpmFromLoopLength(sample.Length); return(BpmHelper.GetAdjustedAudioLength(sample.Length, bpm, Module.Bpm)); }
/// <summary> /// Binds the data. /// </summary> private void BindData() { _bindingData = true; var loopLengths = BpmHelper.GetLoopLengths(Track.StartBpm); cmbCustomFadeInLength.PopulateItemsFromSecondsList(loopLengths); loopLengths = BpmHelper.GetLoopLengths(Track.EndBpm); cmbCustomFadeOutLength.PopulateItemsFromSecondsList(loopLengths); lblStartBPM.Text = Track.StartBpm.ToString("0.00"); lblEndBPM.Text = Track.EndBpm.ToString("0.00"); Text = @"Halloumi : Shuffler : Shuffler Details : " + Track.Description; chkUsePreFadeIn.Checked = Track.UsePreFadeIn; chkUseSkipSection.Checked = Track.HasSkipSection; txtSkipStart.Seconds = Track.SamplesToSeconds(Track.SkipStart); cmbSkipLength.Seconds = Track.SkipLengthSeconds; cmbSkipLength.PopulateItemsFromSecondsList(loopLengths); txtFadeInPosition.Seconds = Track.SamplesToSeconds(Track.FadeInStart); txtFadeOutStartPosition.Seconds = Track.SamplesToSeconds(Track.FadeOutStart); txtPreFadeInStartPosition.Seconds = Track.SamplesToSeconds(Track.PreFadeInStart); if (Track.FadeInEnd != 0) { cmbCustomFadeInLength.Seconds = Track.SamplesToSeconds(Track.FadeInEnd - Track.FadeInStart); } if (Track.FadeOutEnd != 0) { cmbCustomFadeOutLength.Seconds = Track.SamplesToSeconds(Track.FadeOutEnd - Track.FadeOutStart); } cmbPreFadeInStartVolume.Text = (Track.PreFadeInStartVolume * 100).ToString(CultureInfo.InvariantCulture); cmbFadeInLoopCount.Text = !Track.IsLoopedAtStart ? "0" : Track.StartLoopCount.ToString(); cmbFadeOutLoopCount.Text = !Track.IsLoopedAtEnd ? "0" : Track.EndLoopCount.ToString(); chkPowerDown.Checked = Track.PowerDownOnEnd; BindSamples(); BindSample(); _bindingData = false; }
/// <summary> /// Gets the mix level for mixing track 1 into track 1 /// </summary> /// <param name="track1">The track 1.</param> /// <param name="track2">The track 2.</param> /// <returns>A mix level from 0 to 5</returns> public int GetMixLevel(Track track1, Track track2) { if (track1 == null || track2 == null) { return(0); } var mixRank = GetMixRank(track1.Description, track2.Description); if (mixRank != null) { return(mixRank.MixLevel); } return(BpmHelper.IsBpmInRange(track1.EndBpm, track2.StartBpm, 5M) ? 1 : 0); }
private string FadeOutDescription(Track track, Track nextTrack) { if (track == null) { return(""); } var standardEndLength = BpmHelper.GetFullEndLoopLengthAdjustedToMatchAnotherTrack(track, nextTrack); var looped = track.EndLoopCount > 1; var powerDown = track.PowerDownOnEnd; var description = "Fade Out: "; if (powerDown) { description = "PowerDown"; } else { description += GetFormattedSeconds(standardEndLength); } var hasExtendedMix = BassPlayer.HasExtendedMixAttributes(track, nextTrack); if (hasExtendedMix) { var extendedFadeType = BassPlayer.GetExtendedFadeType(track, nextTrack); if (extendedFadeType == ExtendedFadeType.Default) { var extendedEndLength = BassPlayer.GetExtendedFadeOutLength(track, nextTrack); description += " (" + GetFormattedSeconds(extendedEndLength) + "*)"; } else { description += " (" + extendedFadeType + "*)"; } } if (looped) { description += " looped"; } description += " " + track.EndBpm.ToString("00.00") + "BPM"; return(description); }
/// <summary> /// Gets the BPM of the sample /// </summary> public decimal CalculateBpm(Track track = null) { if (track == null || IsExternalLoop) { return(BpmHelper.GetBpmFromLoopLength(Length)); } if (Key == "PreFadeIn") { return(track.StartBpm); } if (Length != 0 && IsLooped) { return(BpmHelper.GetBpmFromLoopLength(Length)); } return(track.Bpm); }
private void BindSample() { List <double> loopLengths; if (CurrentSample == null) { txtSampleStartPosition.Seconds = 0; loopLengths = BpmHelper.GetLoopLengths(Track.Bpm); cmbSampleLength.Seconds = 0; chkLoopSample.Checked = false; } else { txtSampleStartPosition.Seconds = CurrentSample.Start; loopLengths = BpmHelper.GetLoopLengths(CurrentSample.CalculateBpm(Track)); cmbSampleLength.Seconds = CurrentSample.Length; chkLoopSample.Checked = CurrentSample.IsLooped; } cmbSampleLength.PopulateItemsFromSecondsList(loopLengths); }
private string FadeInDescription(Track previousTrack, Track track) { if (track == null) { return(""); } var standardStartLength = track.FullStartLoopLengthSeconds; var looped = track.StartLoopCount > 1; var powerDown = previousTrack?.PowerDownOnEnd ?? false; var description = "Fade In: "; description += GetFormattedSeconds(standardStartLength); if (powerDown) { var powerDownFadeIn = BpmHelper.GetDefaultLoopLength(track.StartBpm) / 4D; description += " (" + GetFormattedSeconds(powerDownFadeIn) + ")"; } else { var hasExtendedMix = BassPlayer.HasExtendedMixAttributes(previousTrack, track); if (hasExtendedMix) { var extendedEndLength = BassPlayer.GetExtendedFadeOutLength(previousTrack, track); description += " (" + GetFormattedSeconds(extendedEndLength) + "*)"; } } if (looped) { description += " looped"; } description += " " + track.StartBpm.ToString("00.00") + "BPM"; return(description); }
private void SetPluginBpm(VstPlugin plugin) { if (plugin == null) { return; } if (BpmProvider == null) { return; } if (!plugin.Parameters.Any(x => x.SyncToBpm)) { return; } var bpm = BpmProvider.GetCurrentBpm(); var quarterNoteLength = BpmHelper.GetDefaultDelayLength(bpm); var fullNoteLength = quarterNoteLength * 4; var syncParameters = plugin.Parameters.Where(p => p.SyncToBpm).ToList(); var mutePlugin = syncParameters.Any(p => p.SyncNotes == 0); BassVst.BASS_VST_SetBypass(plugin.Id, mutePlugin); if (mutePlugin) { return; } foreach (var parameter in syncParameters) { var syncLength = fullNoteLength * (double)parameter.SyncNotes; var vstDelayValue = GetVstSyncValue(syncLength, parameter); BassVst.BASS_VST_SetParam(plugin.Id, parameter.Id, vstDelayValue); } }
private void BindSample() { List <double> loopLengths; if (CurrentSample == null) { txtSampleStartPosition.Seconds = 0; txtSampleOffsetPosition.Seconds = 0; loopLengths = BpmHelper.GetLoopLengths(Track.Bpm); cmbSampleLength.Seconds = 0; SetLoopModeOnDropdown(LoopMode.FullLoop); chkAtonal.Checked = false; chkPrimaryLoop.Checked = false; lblSampleBPM.Text = @"100.00"; txtTags.Text = ""; } else { loopLengths = BpmHelper.GetLoopLengths(CurrentSample.Bpm); txtSampleStartPosition.Seconds = CurrentSample.Start; txtSampleOffsetPosition.Seconds = CurrentSample.Offset; lblSampleBPM.Text = CurrentSample.Bpm.ToString("0.00"); cmbSampleLength.Seconds = CurrentSample.Length; SetLoopModeOnDropdown(CurrentSample.LoopMode); chkAtonal.Checked = CurrentSample.IsAtonal; chkPrimaryLoop.Checked = CurrentSample.IsPrimaryLoop; txtTags.Text = string.Join(", ", CurrentSample.Tags.ToArray()); } // SetSampleCheckBoxes(); SetSampleBpmLabel(); cmbSampleLength.PopulateItemsFromSecondsList(loopLengths); }
/// <summary> /// Loads the track details from the tags in the associate mp3 /// </summary> /// <param name="track">The track to load the details of.</param> /// <param name="updateLength">if set to <c>true</c> [update length].</param> public static void LoadTrack(Track track, bool updateLength = true) { if (!File.Exists(track.Filename)) { return; } if (!track.Filename.ToLower().EndsWith(".mp3")) { return; } DebugHelper.WriteLine("Library - LoadTrack - " + track.Description); GuessTrackDetailsFromFileName(track); var dateLastModified = GetTrackLastModified(track.Filename); track.LastModified = dateLastModified; if (ID3v2Tag.DoesTagExist(track.Filename)) { var tags = new ID3v2Tag(track.Filename); if (!string.IsNullOrEmpty(tags.Artist)) { track.Artist = tags.Artist.Trim(); } if (!string.IsNullOrEmpty(tags.Artist)) { track.AlbumArtist = tags.Artist.Trim(); } if (!string.IsNullOrEmpty(tags.Title)) { track.Title = tags.Title.Trim(); } if (!string.IsNullOrEmpty(tags.Album)) { track.Album = tags.Album.Trim(); } if (!string.IsNullOrEmpty(tags.Genre)) { track.Genre = tags.Genre.Trim(); } if (!string.IsNullOrEmpty(tags.InitialKey)) { var tagKey = tags.InitialKey.Trim(); track.Key = KeyHelper.ParseKey(tagKey); } LoadArtistAndAlbumArtist(track); if (tags.LengthMilliseconds.HasValue) { track.Length = (decimal)tags.LengthMilliseconds / 1000M; } decimal bpm; if (decimal.TryParse(tags.BPM, out bpm)) { track.Bpm = bpm; } track.Bpm = BpmHelper.NormaliseBpm(track.Bpm); track.EndBpm = track.Bpm; track.StartBpm = track.Bpm; track.Bpm = BpmHelper.GetAdjustedBpmAverage(track.StartBpm, track.EndBpm); int trackNumber; var trackNumberTag = (tags.TrackNumber + "/").Split('/')[0].Trim(); if (int.TryParse(trackNumberTag, out trackNumber)) { track.TrackNumber = trackNumber; } if (GenreCode.IsGenreCode(track.Genre)) { track.Genre = GenreCode.GetGenre(track.Genre); } if (track.Artist == "") { track.Artist = NoValue; } if (track.AlbumArtist == "") { track.AlbumArtist = NoValue; } if (track.Title == "") { track.Title = NoValue; } if (track.Album == "") { track.Album = NoValue; } if (track.Genre == "") { track.Genre = NoValue; } } track.OriginalDescription = track.Description; track.FullLength = track.Length; var audioFile = AudioFile.Create(track.Filename, true); track.Bitrate = audioFile.Bitrate; track.Length = audioFile.TotalSeconds; if (updateLength) { UpdateLength(track); } //UpdateKey(track); track.Bpm = BpmHelper.GetAdjustedBpmAverage(track.StartBpm, track.EndBpm); track.OriginalDescription = track.Description; if (track.EndBpm == 0 || track.EndBpm == 100) { track.EndBpm = track.Bpm; } if (track.StartBpm == 0 || track.StartBpm == 100) { track.StartBpm = track.Bpm; } }
/// <summary> /// Loads the shuffler details for a track /// </summary> /// <param name="track">The track.</param> public static Dictionary <string, string> LoadShufflerDetails(Track track) { //if(track.Title.Contains("Escobar")) // DebugHelper.WriteLine("Stop"); track.Key = KeyHelper.ParseKey(track.Key); track.IsShufflerTrack = ExtenedAttributesHelper.HasExtendedAttributes(track.Description); if (!track.IsShufflerTrack) { return(null); } var attributes = ExtenedAttributesHelper.GetExtendedAttributes(track.Description); if (attributes.ContainsKey("Rank")) { track.Rank = ConversionHelper.ToInt(attributes["Rank"], 1); } decimal start = 0; if (attributes.ContainsKey("FadeIn")) { start = ConversionHelper.ToDecimal(attributes["FadeIn"], start); } var end = track.Length; if (attributes.ContainsKey("FadeOut")) { end = ConversionHelper.ToDecimal(attributes["FadeOut"], end); } var length = end - start; var inLoopCount = 0; if (attributes.ContainsKey("StartLoopCount")) { inLoopCount = ConversionHelper.ToInt(attributes["StartLoopCount"], inLoopCount); } decimal inLoopLength = 0; if (attributes.ContainsKey("FadeInLengthInSeconds")) { inLoopLength = ConversionHelper.ToDecimal(attributes["FadeInLengthInSeconds"]); } if (inLoopLength > 0) { track.StartBpm = BpmHelper.GetBpmFromLoopLength(Convert.ToDouble(inLoopLength)); } inLoopCount = inLoopCount - 1; if (inLoopCount > 0) { length = length + inLoopCount * inLoopLength; } decimal skipLength = 0; if (attributes.ContainsKey("SkipLengthInSeconds")) { skipLength = ConversionHelper.ToDecimal(attributes["SkipLengthInSeconds"]); } if (skipLength > 0) { length = length - skipLength; } track.PowerDown = false; if (attributes.ContainsKey("PowerDown")) { track.PowerDown = ConversionHelper.ToBoolean(attributes["PowerDown"]); } if (attributes.ContainsKey("Key")) { track.Key = KeyHelper.ParseKey(attributes["Key"]); } decimal outLoopLength = 0; if (attributes.ContainsKey("FadeOutLengthInSeconds")) { outLoopLength = ConversionHelper.ToDecimal(attributes["FadeOutLengthInSeconds"], 0); } if (outLoopLength > 0) { track.EndBpm = BpmHelper.GetBpmFromLoopLength(Convert.ToDouble(outLoopLength)); } track.Length = length; if (attributes.ContainsKey("StartBPM")) { track.StartBpm = BpmHelper.NormaliseBpm(ConversionHelper.ToDecimal(attributes["StartBPM"], track.Bpm)); } if (attributes.ContainsKey("EndBPM")) { track.EndBpm = BpmHelper.NormaliseBpm(ConversionHelper.ToDecimal(attributes["EndBPM"], track.Bpm)); } track.Bpm = BpmHelper.GetAdjustedBpmAverage(track.StartBpm, track.EndBpm); return(attributes); }
public void SetBpm(decimal bpm) { _targetBpm = bpm; _loopLength = BpmHelper.GetDefaultLoopLength(_targetBpm); }
/// <summary> /// Gets the tracks in BPM range. /// </summary> /// <param name="bpm">The BPM.</param> /// <param name="percentVariance">The percent variance.</param> /// <param name="tracks">The tracks.</param> /// <returns>A list of matching tracks</returns> public List <Track> GetTracksInStartBpmRange(decimal bpm, decimal percentVariance, List <Track> tracks) { return(tracks .Where(t => BpmHelper.IsBpmInRange(bpm, t.StartBpm, percentVariance)) .ToList()); }
/// <summary> /// Binds the data. /// </summary> private void BindData() { if (!_bindDataAllowed) { return; } var view = cmbView.ParseEnum <View>(); var rankFilter = cmbRank.GetTextThreadSafe(); List <int> ranks; switch (rankFilter) { case "Good+": ranks = new List <int> { 5, 4, 3 }; break; case "Bearable+": ranks = new List <int> { 5, 4, 3, 2 }; break; case "Unranked": ranks = new List <int> { 1 }; break; case "Forbidden": ranks = new List <int> { 0 }; break; default: ranks = new List <int> { 5, 4, 3, 2, 1, 0 }; break; } var keyRankFilter = cmbKeyRank.GetTextThreadSafe(); int minimumKeyRank; switch (keyRankFilter) { case "Very Good+": minimumKeyRank = 4; break; case "Good+": minimumKeyRank = 3; break; case "Bearable+": minimumKeyRank = 2; break; case "Not Good": minimumKeyRank = 0; break; default: minimumKeyRank = -1; break; } List <Track> tracks; if (_parentTrack == null) { tracks = new List <Track>(); } else if (view == View.FromTracks) { tracks = GetMixableFromTracks(_parentTrack, ranks); } else { tracks = GetMixableToTracks(_parentTrack, ranks); } var playListTracks = new List <Track>(); if (PlaylistControl != null) { playListTracks = PlaylistControl.GetTracks(); } if (minimumKeyRank == 0 && _parentTrack != null) { tracks = tracks .Where(t => KeyHelper.GetKeyMixRank(_parentTrack.Key, t.Key) <= 1) .ToList(); } else if (minimumKeyRank != -1 && _parentTrack != null) { tracks = tracks .Where(t => KeyHelper.GetKeyMixRank(_parentTrack.Key, t.Key) >= minimumKeyRank) .ToList(); } var mixableTracks = new List <MixableTrackModel>(); foreach (var track in tracks) { if (_parentTrack == null) { continue; } if (mixableTracks.Exists(mt => mt.Description == track.Description)) { continue; } if (chkExcludeQueued.Checked && playListTracks.Exists(mt => mt != null && mt.Description == track.Description)) { continue; } var mixRank = view == View.FromTracks ? _mixLibrary.GetExtendedMixLevel(track, _parentTrack) : _mixLibrary.GetExtendedMixLevel(_parentTrack, track); var mixRankDescription = view == View.FromTracks ? _mixLibrary.GetExtendedMixDescription(track, _parentTrack) : _mixLibrary.GetExtendedMixDescription(_parentTrack, track); var mixableTrack = new MixableTrackModel { Track = track, Description = track.Description, Bpm = track.Bpm, Diff = BpmHelper.GetAbsoluteBpmPercentChange(_parentTrack.EndBpm, track.StartBpm), MixRank = mixRank, MixRankDescription = mixRankDescription, Rank = track.Rank, RankDescription = track.RankDescription, Key = KeyHelper.GetDisplayKey(track.Key), KeyDiff = KeyHelper.GetKeyDifference(_parentTrack.Key, track.Key), KeyRankDescription = KeyHelper.GetKeyMixRankDescription(track.Key, _parentTrack.Key) }; mixableTrack.MixRankDescription = _mixLibrary.GetRankDescription(Convert.ToInt32(Math.Floor(mixableTrack.MixRank))); var hasExtendedMix = _mixLibrary.HasExtendedMix(_parentTrack, track); if (hasExtendedMix) { mixableTrack.MixRankDescription += "*"; } mixableTracks.Add(mixableTrack); } if (grdMixableTracks.SortedColumn != null) { var sortField = grdMixableTracks.SortedColumn.DataPropertyName; if (sortField == "Description") { mixableTracks = mixableTracks.OrderBy(t => t.Description).ToList(); } if (sortField == "BPM") { mixableTracks = mixableTracks.OrderBy(t => t.Bpm).ToList(); } if (sortField == "Diff") { mixableTracks = mixableTracks.OrderBy(t => t.Diff).ToList(); } if (sortField == "MixRankDescription") { mixableTracks = mixableTracks.OrderBy(t => t.MixRank).ThenByDescending(t => t.Diff).ToList(); } if (sortField == "RankDescription") { mixableTracks = mixableTracks.OrderBy(t => t.Rank).ThenByDescending(t => t.Diff).ToList(); } if (sortField == "Key") { mixableTracks = mixableTracks.OrderBy(t => t.Key).ToList(); } if (sortField == "KeyRankDescription") { mixableTracks = mixableTracks.OrderByDescending(t => t.KeyDiff).ToList(); } if (grdMixableTracks.SortOrder == SortOrder.Descending) { mixableTracks.Reverse(); } } else { mixableTracks = mixableTracks .OrderByDescending(t => t.MixRank) .ThenBy(t => t.KeyDiff) .ThenBy(t => t.Diff) .ThenByDescending(t => t.Rank) .ThenBy(t => t.Description) .ToList(); } grdMixableTracks.SaveSelectedRows(); grdMixableTracks.DataSource = mixableTracks; grdMixableTracks.RestoreSelectedRows(); lblCount.Text = $"{mixableTracks.Count} tracks"; }