public virtual List<Tuple<TimeSpan, TimeSpan>> Execute(IAudioStream s1, IAudioStream s2) { s1 = PrepareStream(s1); s2 = PrepareStream(s2); int diagonalWidth = (int)(searchWidth.TotalSeconds * (1d * FrameReader.SAMPLERATE / FrameReader.WINDOW_HOP_SIZE)); // init ring buffers rb1 = new float[diagonalWidth][]; rb1FrameCount = 0; rb2 = new float[diagonalWidth][]; rb2FrameCount = 0; stream1FrameQueue = new BlockingCollection<float[]>(20); FrameReader stream1FrameReader = new FrameReader(s1); Task.Factory.StartNew(() => { while (stream1FrameReader.HasNext()) { float[] frame = new float[FrameReader.FRAME_SIZE]; stream1FrameReader.ReadFrame(frame); //Thread.Sleep(20); stream1FrameQueue.Add(frame); } stream1FrameQueue.CompleteAdding(); }); stream2FrameQueue = new BlockingCollection<float[]>(20); FrameReader stream2FrameReader = new FrameReader(s2); Task.Factory.StartNew(() => { while (stream2FrameReader.HasNext()) { float[] frame = new float[FrameReader.FRAME_SIZE]; stream2FrameReader.ReadFrame(frame); //Thread.Sleep(20); stream2FrameQueue.Add(frame); } stream2FrameQueue.CompleteAdding(); }); IProgressReporter progressReporter = progressMonitor.BeginTask("DTW aligning...", true); int n = stream1FrameReader.WindowCount; int m = stream2FrameReader.WindowCount; double deltaN; double deltaM; if (m > n) { deltaN = (double)(n - 1) / (m - 1); deltaM = 1d; } else if (m < n) { deltaN = 1d; deltaM = (double)(m - 1) / (n - 1); } else { deltaN = 1d; deltaM = 1d; } // NOTE the SparseMatrix is NOT USABLE for DTW -> OutOfMemoryException (1.3GB RAM) at a densely filled matrix of ~4000x3000 IMatrix<double> totalCostMatrix = new PatchMatrix<double>(double.PositiveInfinity); IMatrix<double> cellCostMatrix = new PatchMatrix<double>(double.PositiveInfinity); // init matrix // NOTE do not explicitely init the PatchMatrix, otherwise the sparse matrix characteristic would // be gone and the matrix would take up all the space like a standard matrix does totalCostMatrix[0, 0] = 0; cellCostMatrix[0, 0] = 0; double progressN = 0; double progressM = 0; int i, x = 0; int j, y = 0; FireOltwInit(diagonalWidth, cellCostMatrix, totalCostMatrix); while (x < n || y < m) { x = (int)progressN + 1; y = (int)progressM + 1; ReadFrames(x, y); i = Math.Max(x - diagonalWidth, 1); j = y; for (; i <= x; i++) { double cost = CalculateCost(rb1[(i - 1) % diagonalWidth], rb2[(j - 1) % diagonalWidth]); totalCostMatrix[i, j] = cost + Min( totalCostMatrix[i - 1, j], totalCostMatrix[i, j - 1], totalCostMatrix[i - 1, j - 1]); cellCostMatrix[i, j] = cost; } i = x; j = Math.Max(y - diagonalWidth, 1); for (; j <= y; j++) { double cost = CalculateCost(rb1[(i - 1) % diagonalWidth], rb2[(j - 1) % diagonalWidth]); totalCostMatrix[i, j] = cost + Min( totalCostMatrix[i - 1, j], totalCostMatrix[i, j - 1], totalCostMatrix[i - 1, j - 1]); cellCostMatrix[i, j] = cost; } FireOltwProgress(x, y, x, y, false); progressReporter.ReportProgress((double)x / n * 100); progressN += deltaN; progressM += deltaM; } FireOltwProgress(x, y, x, y, true); progressReporter.Finish(); List<Pair> path = OptimalWarpingPath(totalCostMatrix); path.Reverse(); return WarpingPathTimes(path, true); }
public override List <Tuple <TimeSpan, TimeSpan> > Execute(IAudioStream s1, IAudioStream s2) { s1 = PrepareStream(s1); s2 = PrepareStream(s2); int searchWidth = (int)(this.searchWidth.TotalSeconds * (1d * FrameReader.SAMPLERATE / FrameReader.WINDOW_HOP_SIZE)); totalCostMatrix = new PatchMatrix <double>(double.PositiveInfinity); cellCostMatrix = new PatchMatrix <double>(double.PositiveInfinity); rb1 = new RingBuffer <float[]>(searchWidth); rb1FrameCount = 0; rb2 = new RingBuffer <float[]>(searchWidth); rb2FrameCount = 0; stream1FrameQueue = new BlockingCollection <float[]>(20); FrameReader stream1FrameReader = new FrameReader(s1); Task.Factory.StartNew(() => { while (stream1FrameReader.HasNext()) { float[] frame = new float[FrameReader.FRAME_SIZE]; stream1FrameReader.ReadFrame(frame); Thread.Sleep(20); stream1FrameQueue.Add(frame); } stream1FrameQueue.CompleteAdding(); }); stream2FrameQueue = new BlockingCollection <float[]>(20); FrameReader stream2FrameReader = new FrameReader(s2); Task.Factory.StartNew(() => { while (stream2FrameReader.HasNext()) { float[] frame = new float[FrameReader.FRAME_SIZE]; stream2FrameReader.ReadFrame(frame); Thread.Sleep(20); stream2FrameQueue.Add(frame); } stream2FrameQueue.CompleteAdding(); }); // init matrix // NOTE do not explicitely init the PatchMatrix, otherwise the sparse matrix characteristic would // be gone and the matrix would take up all the space like a standard matrix does totalCostMatrix[0, 0] = 0; cellCostMatrix[0, 0] = 0; IProgressReporter progressReporter = progressMonitor.BeginTask("OLTW", true); int totalFrames = stream1FrameReader.WindowCount + stream2FrameReader.WindowCount; // --------- OLTW ----------- t = 1; j = 1; previous = GetIncResult.None; runCount = 0; c = searchWidth; EvaluatePathCost(t, j); FireOltwInit(c, cellCostMatrix, totalCostMatrix); while (rb1FrameCount + rb2FrameCount < totalFrames) { GetIncResult getInc = GetInc(t, j); if (t < stream1FrameReader.WindowCount && getInc != GetIncResult.Column) { t++; for (int k = j - c + 1; k <= j; k++) { if (k > 0) { EvaluatePathCost(t, k); } } } if (j < stream2FrameReader.WindowCount && getInc != GetIncResult.Row) { j++; for (int k = t - c + 1; k <= t; k++) { if (k > 0) { EvaluatePathCost(k, j); } } } if (getInc == previous) { runCount++; } else { runCount = 1; } if (getInc != GetIncResult.Both) { previous = getInc; } FireOltwProgress(t, j, t, j, false); //Debug.WriteLine(t + " " + j + " " + getInc); progressReporter.ReportProgress((rb1FrameCount + rb2FrameCount) / (double)totalFrames * 100); } FireOltwProgress(t, j, t, j, true); Debug.WriteLine("OLTW finished @ t={0}/{1}, j={2}/{3}", t, stream1FrameReader.WindowCount, j, stream2FrameReader.WindowCount); progressReporter.Finish(); // --------- generate results ----------- List <Pair> path = OptimalWarpingPath(totalCostMatrix); path.Reverse(); List <Tuple <TimeSpan, TimeSpan> > pathTimes = new List <Tuple <TimeSpan, TimeSpan> >(); foreach (Pair pair in path) { Tuple <TimeSpan, TimeSpan> timePair = new Tuple <TimeSpan, TimeSpan>( PositionToTimeSpan(pair.i1 * FrameReader.WINDOW_HOP_SIZE), PositionToTimeSpan(pair.i2 * FrameReader.WINDOW_HOP_SIZE)); if (timePair.Item1 >= TimeSpan.Zero && timePair.Item2 >= TimeSpan.Zero) { pathTimes.Add(timePair); } } return(pathTimes); }