]> git.sesse.net Git - kdenlive/blob - src/lib/audio/audioCorrelation.cpp
Add an fps counter for debugging.
[kdenlive] / src / lib / audio / audioCorrelation.cpp
1 /*
2 Copyright (C) 2012  Simon A. Eugster (Granjow)  <simon.eu@gmail.com>
3 This file is part of kdenlive. See www.kdenlive.org.
4
5 This program is free software: you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation, either version 3 of the License, or
8 (at your option) any later version.
9 */
10
11 #include "audioCorrelation.h"
12 #include "fftCorrelation.h"
13
14 #include <QDebug>
15 #include <QTime>
16 #include <cmath>
17 #include <iostream>
18
19
20 AudioCorrelation::AudioCorrelation(AudioEnvelope *mainTrackEnvelope) :
21     m_mainTrackEnvelope(mainTrackEnvelope)
22 {
23     m_mainTrackEnvelope->normalizeEnvelope();
24 }
25
26 AudioCorrelation::~AudioCorrelation()
27 {
28     delete m_mainTrackEnvelope;
29     foreach (AudioEnvelope *envelope, m_children) {
30         delete envelope;
31     }
32     foreach (AudioCorrelationInfo *info, m_correlations) {
33         delete info;
34     }
35
36     qDebug() << "Envelope deleted.";
37 }
38
39 int AudioCorrelation::addChild(AudioEnvelope *envelope, bool useFFT)
40 {
41     envelope->normalizeEnvelope();
42
43     const int sizeMain = m_mainTrackEnvelope->envelopeSize();
44     const int sizeSub = envelope->envelopeSize();
45
46     AudioCorrelationInfo *info = new AudioCorrelationInfo(sizeMain, sizeSub);
47     int64_t *correlation = info->correlationVector();
48
49     const int64_t *envMain = m_mainTrackEnvelope->envelope();
50     const int64_t *envSub = envelope->envelope();
51     int64_t max = 0;
52
53     if (useFFT) {
54         FFTCorrelation::correlate(envMain, sizeMain,
55                                   envSub, sizeSub,
56                                   correlation);
57     } else {
58         correlate(envMain, sizeMain,
59                   envSub, sizeSub,
60                   correlation,
61                   &max);
62         info->setMax(max);
63     }
64
65
66     m_children.append(envelope);
67     m_correlations.append(info);
68
69     Q_ASSERT(m_correlations.size() == m_children.size());
70
71     return m_children.indexOf(envelope);
72 }
73
74 int AudioCorrelation::getShift(int childIndex) const
75 {
76     Q_ASSERT(childIndex >= 0);
77     Q_ASSERT(childIndex < m_correlations.size());
78
79     int indexOffset = m_correlations.at(childIndex)->maxIndex();
80     indexOffset -= m_children.at(childIndex)->envelopeSize();
81
82     return indexOffset;
83 }
84
85 AudioCorrelationInfo const* AudioCorrelation::info(int childIndex) const
86 {
87     Q_ASSERT(childIndex >= 0);
88     Q_ASSERT(childIndex < m_correlations.size());
89
90     return m_correlations.at(childIndex);
91 }
92
93
94 void AudioCorrelation::correlate(const int64_t *envMain, int sizeMain,
95                                  const int64_t *envSub, int sizeSub,
96                                  int64_t *correlation,
97                                  int64_t *out_max)
98 {
99     Q_ASSERT(correlation != NULL);
100
101     int64_t const* left;
102     int64_t const* right;
103     int size;
104     int64_t sum;
105     int64_t max = 0;
106
107
108     /*
109       Correlation:
110
111       SHIFT \in [-sS..sM]
112
113       <--sS----
114       [  sub  ]----sM--->[ sub ]
115                [  main  ]
116
117             ^ correlation vector index = SHIFT + sS
118
119       main is fixed, sub is shifted along main.
120
121     */
122
123
124     QTime t;
125     t.start();
126     for (int shift = -sizeSub; shift <= sizeMain; shift++) {
127
128         if (shift <= 0) {
129             left = envSub-shift;
130             right = envMain;
131             size = std::min(sizeSub+shift, sizeMain);
132         } else {
133             left = envSub;
134             right = envMain+shift;
135             size = std::min(sizeSub, sizeMain-shift);
136         }
137
138         sum = 0;
139         for (int i = 0; i < size; ++i) {
140             sum += (*left) * (*right);
141             left++;
142             right++;
143         }
144         correlation[sizeSub+shift] = qAbs(sum);
145
146         if (sum > max) {
147             max = sum;
148         }
149
150     }
151     qDebug() << "Correlation calculated. Time taken: " << t.elapsed() << " ms.";
152
153     if (out_max != NULL) {
154         *out_max = max;
155     }
156 }