예제 #1
0
        public static unsafe double CrossCorrelationOffset(byte[] x, byte[] y)
        {
            if (x.Length != y.Length)
            {
                throw new ArgumentException("interval lengths do not match");
            }

            fixed(byte *xB = &x[0], yB = &y[0])
            {
                float *xF = (float *)xB;
                float *yF = (float *)yB;
                int    n  = x.Length / sizeof(float);

                CrossCorrelation.Result ccr;
                return((1 - Math.Abs(CrossCorrelation.Calculate(xF, yF, n, out ccr)) / (n / 2d)) * ccr.AbsoluteMaxValue);
            }
        }
예제 #2
0
        public void Execute()
        {
            Debug.WriteLine("window length: {0}s, interval length: {1}s, sample rate: {2}",
                            windowLength.TotalSeconds, intervalLength.TotalSeconds, sampleRate);
            IProgressReporter reporter = progressMonitor.BeginTask("Analyzing alignment...", true);

            List <IAudioStream> streams = new List <IAudioStream>(audioTracks.Count);
            TimeSpan            start   = audioTracks.Start;
            TimeSpan            end     = audioTracks.End;

            foreach (AudioTrack audioTrack in audioTracks)
            {
                streams.Add(CrossCorrelation.PrepareStream(audioTrack.CreateAudioStream(), sampleRate));
            }

            long[] streamOffsets = new long[audioTracks.Count];
            for (int i = 0; i < audioTracks.Count; i++)
            {
                streamOffsets[i] = TimeUtil.TimeSpanToBytes(audioTracks[i].Offset - start, streams[0].Properties);
            }

            int  windowLengthInBytes    = (int)TimeUtil.TimeSpanToBytes(windowLength, streams[0].Properties);
            int  windowLengthInSamples  = windowLengthInBytes / streams[0].Properties.SampleBlockByteSize;
            long intervalLengthInBytes  = TimeUtil.TimeSpanToBytes(intervalLength, streams[0].Properties);
            long analysisIntervalLength = TimeUtil.TimeSpanToBytes(end - start, streams[0].Properties);

            OnStarted();

            byte[] x = new byte[windowLengthInBytes];
            byte[] y = new byte[windowLengthInBytes];
            long   positionX;
            long   positionY;
            double sumNegative   = 0;
            double sumPositive   = 0;
            int    countNegative = 0;
            int    countPositive = 0;
            double min           = 0;
            double max           = 0;

            for (long position = 0; position < analysisIntervalLength; position += intervalLengthInBytes)
            {
                double windowSumNegative   = 0;
                double windowSumPositive   = 0;
                int    windowCountNegative = 0;
                int    windowCountPositive = 0;
                double windowMin           = 0;
                double windowMax           = 0;

                Debug.WriteLine("Analyzing {0} @ {1} / {2}", intervalLengthInBytes, position, analysisIntervalLength);
                // at each position in the analysis interval, compare each stream with each other
                for (int i = 0; i < streams.Count; i++)
                {
                    positionX = position - streamOffsets[i];
                    if (positionX >= 0 && positionX < streams[i].Length)
                    {
                        streams[i].Position = positionX;
                        StreamUtil.ForceRead(streams[i], x, 0, windowLengthInBytes);
                        for (int j = i + 1; j < streams.Count; j++)
                        {
                            positionY = position - streamOffsets[j];
                            if (positionY >= 0 && positionY < streams[j].Length)
                            {
                                streams[j].Position = positionY;
                                StreamUtil.ForceRead(streams[j], y, 0, windowLengthInBytes);

                                double val = analyzeSection(x, y);
                                if (val > 0)
                                {
                                    windowSumPositive += val;
                                    windowCountPositive++;
                                }
                                else
                                {
                                    windowSumNegative += val;
                                    windowCountNegative++;
                                }
                                if (windowMin > val)
                                {
                                    windowMin = val;
                                }
                                if (windowMax < val)
                                {
                                    windowMax = val;
                                }
                                Debug.WriteLine("{0,2}->{1,2}: {2}", i, j, val);
                            }
                        }
                    }
                }
                sumPositive   += windowSumPositive;
                countPositive += windowCountPositive;
                sumNegative   += windowSumNegative;
                countNegative += windowCountNegative;
                if (min > windowMin)
                {
                    min = windowMin;
                }
                if (max < windowMax)
                {
                    max = windowMax;
                }
                reporter.ReportProgress((double)position / analysisIntervalLength * 100);
                OnWindowAnalyzed(start + TimeUtil.BytesToTimeSpan(position, streams[0].Properties),
                                 windowCountPositive, windowCountNegative,
                                 windowMin, windowMax,
                                 windowSumPositive, windowSumNegative);
            }

            reporter.Finish();
            Debug.WriteLine("Finished. sum: {0}, sum+: {1}, sum-: {2}, sumAbs: {3}, avg: {4}, avg+: {5}, avg-: {6}, avgAbs: {7}, min: {8}, max: {9}, points: {10}",
                            sumPositive + sumNegative, sumPositive, sumNegative, sumPositive + (sumNegative * -1),
                            (sumPositive + sumNegative) / (countPositive + countNegative), sumPositive / countPositive,
                            sumNegative / countNegative, (sumPositive + (sumNegative * -1)) / (countPositive + countNegative),
                            min, max, countPositive + countNegative);
            double score = (sumPositive + (sumNegative * -1)) / (countPositive + countNegative);

            Debug.WriteLine("Score: {0} => {1}%", score, Math.Round(score * 100));

            OnFinished(countPositive, countNegative, min, max, sumPositive, sumNegative);

            streams.ForEach(s => s.Close());
        }