private void AddGraphLine(OxyPlot.PlotModel plotModel, MatchPair matchPair) { var lineSeries = new LineSeries(); lineSeries.Title = matchPair.Track1.Name + " <-> " + matchPair.Track2.Name; lineSeries.TrackerFormatString = "{0}\n{1}: {2}\n{3}: {4}"; // bugfix https://github.com/oxyplot/oxyplot/issues/265 matchPair.Matches.OrderBy(match => match.Track1Time).ToList() .ForEach(match => lineSeries.Points.Add(new DataPoint( DateTimeAxis.ToDouble(match.Track1.Offset + match.Track1Time), DateTimeAxis.ToDouble((match.Track1.Offset + match.Track1Time) - (match.Track2.Offset + match.Track2Time))))); plotModel.Series.Add(lineSeries); }
private bool IsInOtherCluster(MatchPair <T> matchPair) { // check, if a connection point (startnode or endnode) is already in another cluster bool found = false; foreach (var checkCluster in this.clusters) { if (checkCluster.Any(x => x.From.Equals(matchPair.From) || x.To.Equals(matchPair.To))) { // when found add to this cluster checkCluster.Add(matchPair); found = true; break; } } return(found); }
private void correlationButton_Click(object sender, RoutedEventArgs e) { List <MatchGroup> trackGroups = DetermineMatchGroups(); foreach (MatchGroup trackGroup in trackGroups) { foreach (MatchPair trackPair in trackGroup.MatchPairs) { MatchPair localMP = trackPair; Task.Factory.StartNew(() => { TimeSpan t1Offset; TimeSpan t2Offset; if (localMP.Track1.Offset < localMP.Track2.Offset) { t1Offset = localMP.Track2.Offset - localMP.Track1.Offset; t2Offset = TimeSpan.Zero; } else { t1Offset = TimeSpan.Zero; t2Offset = localMP.Track1.Offset - localMP.Track2.Offset; } TimeSpan length; if (localMP.Track1.Length > localMP.Track2.Length) { length = localMP.Track2.Length; } else { length = localMP.Track1.Length; } TimeSpan interval = CorrelationIntervalSize; TimeSpan window = CorrelationWindowSize; List <Match> computedMatches = new List <Match>(); for (TimeSpan position = TimeSpan.Zero; position < length; position += interval) { Interval t1Interval = new Interval((t1Offset + position).Ticks, (t1Offset + position + window).Ticks); Interval t2Interval = new Interval((t2Offset + position).Ticks, (t2Offset + position + window).Ticks); if (t1Interval.TimeTo >= localMP.Track1.Length || t2Interval.TimeTo >= localMP.Track2.Length) { // not enough samples remaining to compute the correlation (end of track reached) break; } CrossCorrelation.Result ccr; IAudioStream s1 = localMP.Track1.CreateAudioStream(); IAudioStream s2 = localMP.Track2.CreateAudioStream(); TimeSpan offset = CrossCorrelation.Calculate(s1, t1Interval, s2, t2Interval, progressMonitor, out ccr); s1.Close(); s2.Close(); // always apply a positive offset that moves the match position inside the corelation interval, // else it can happen that a negative offset is applied to a match at the beginning of the stream // which means that the matching point would be at a negative position in the audio stream computedMatches.Add(new Match { Track1 = localMP.Track1, Track1Time = t1Offset + position + (offset < TimeSpan.Zero ? -offset : TimeSpan.Zero), Track2 = localMP.Track2, Track2Time = t2Offset + position + (offset >= TimeSpan.Zero ? offset : TimeSpan.Zero), Similarity = ccr.AbsoluteMaxValue, Source = "CC" }); } Dispatcher.BeginInvoke((Action) delegate { foreach (Match match in computedMatches) { multiTrackViewer.Matches.Add(match); } }); }); } } }
public override void Execute() { // build the graph Graph <T> graph = new Graph <T>(); //graph.AddUndirectedEdge("Frankfurt", "Wiesbaden", 40); //graph.AddUndirectedEdge("Frankfurt", "Mainz", 30); //graph.AddUndirectedEdge("Mainz", "Wiesbaden", 15); //graph.AddUndirectedEdge("Rüdesheim", "Geisenheim", 4); foreach (var matchpair in this.matches) { graph.AddUndirectedEdge(matchpair.From, matchpair.To, matchpair.Cost); } // uses the FloyWarshall algorithm to compute the transitive closure this // means to determine all possible ways in a graph (so you can check, if nodes have a way to each other in the graph) FloydWarshall <T> transClosureAlgorithm = new FloydWarshall <T>(); transClosureAlgorithm.Execute(graph); // now for all nodes in the graph e.g (Wiesbaden, Mainz, Frankfurt, Rüdesheim, Geisenheim) for (int i = 0; i < transClosureAlgorithm.CostMatrix.GetLength(0); i++) { var cluster = new List <MatchPair <T> >(); T startNode = transClosureAlgorithm.Graph.Nodes[i].Value; // loop through all nodes in the graph e.g (Wiesbaden, Mainz, Frankfurt, Rüdesheim, Geisenheim) for (int j = 0; j < transClosureAlgorithm.CostMatrix.GetLength(0); j++) { T endNode = transClosureAlgorithm.Graph.Nodes[j].Value; var cost = transClosureAlgorithm.CostMatrix[i, j]; // only when a way in the graph exits (waycosts != Infinity) // and it is not himself (startNode != endNode) if (cost != transClosureAlgorithm.Graph.Infinity && !startNode.Equals(endNode)) { // a way exists var matchPair = new MatchPair <T>(startNode, endNode, cost); // checked if it is in the original list if (this.matches.Contains(matchPair)) { // check, if a connection point (startnode or endnode) is already in another cluster var found = this.IsInOtherCluster(matchPair); if (!found) { // add to the new cluster cluster.Add(matchPair); } } } } // when a cluster was build, add to the clusterlist if (cluster.Count > 0) { this.clusters.Add(cluster); } // clusters will be e.g. // Cluster 1: (Frankfurt, Wiesbaden, Mainz) // Cluster 2: (Rüdesheim, Geisenheim) } }
public override void Execute() { // build the graph Graph <T> graph = new Graph <T>(); //graph.AddUndirectedEdge("Frankfurt", "Wiesbaden", 40); //graph.AddUndirectedEdge("Frankfurt", "Mainz", 30); //graph.AddUndirectedEdge("Mainz", "Wiesbaden", 15); //graph.AddUndirectedEdge("Rüdesheim", "Geisenheim", 4); foreach (MatchPair <T> matchpair in this.matches) { graph.AddUndirectedEdge(matchpair.From, matchpair.To, matchpair.Cost); } BreadthFirstSearch <T> bfsSearch = new BreadthFirstSearch <T>(); // take every node from the graph as startnode for the search e.g. "Frankfurt", "Wiesbaden", "Mainz", "Rüdesheim", "Geisenheim" GraphNode <T> startNode = null; GraphNode <T> endNode = null; int cost = graph.Infinity; int i = 0; while (i < graph.Nodes.Count) { var cluster = new List <MatchPair <T> >(); // take current node as startnode and search the whole graph for reachable nodes startNode = (GraphNode <T>)graph.Nodes[i]; bfsSearch.Execute(startNode, null, null); // add the found nodes to the subgraph int j = 0; while (j < bfsSearch.AllNodes.Count) { endNode = (GraphNode <T>)bfsSearch.AllNodes[j]; cost = startNode.CostToNeighbor(endNode); if (!startNode.Equals(endNode)) { var matchPair = new MatchPair <T>(startNode.Value, endNode.Value, cost); // check, if it is in the original list if (this.matches.Contains(matchPair)) { // check, if a connection point (startnode or endnode) is already in another cluster var found = this.IsInOtherCluster(matchPair); if (!found) { // add to the new cluster cluster.Add(matchPair); } } } j++; } // when a cluster was build, add to the clusterlist if (cluster.Count > 0) { this.clusters.Add(cluster); } // clusters will be e.g. // Cluster 1: (Frankfurt, Wiesbaden, Mainz) // Cluster 2: (Rüdesheim, Geisenheim) i++; } }