]> git.sesse.net Git - kdenlive/blob - src/lib/audio/audioCorrelation.cpp
Added option to enable Audio Alignment in the config dialog.
[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 <QTime>
15 #include <cmath>
16 #include <iostream>
17
18 AudioCorrelation::AudioCorrelation(AudioEnvelope *mainTrackEnvelope) :
19     m_mainTrackEnvelope(mainTrackEnvelope)
20 {
21     m_mainTrackEnvelope->normalizeEnvelope();
22 }
23
24 AudioCorrelation::~AudioCorrelation()
25 {
26     delete m_mainTrackEnvelope;
27     foreach (AudioEnvelope *envelope, m_children) {
28         delete envelope;
29     }
30     foreach (AudioCorrelationInfo *info, m_correlations) {
31         delete info;
32     }
33
34     std::cout << "Envelope deleted." << std::endl;
35 }
36
37 int AudioCorrelation::addChild(AudioEnvelope *envelope, bool useFFT)
38 {
39     envelope->normalizeEnvelope();
40
41     const int sizeMain = m_mainTrackEnvelope->envelopeSize();
42     const int sizeSub = envelope->envelopeSize();
43
44
45     AudioCorrelationInfo *info = new AudioCorrelationInfo(sizeMain, sizeSub);
46     int64_t *correlation = info->correlationVector();
47
48     const int64_t *envMain = m_mainTrackEnvelope->envelope();
49     const int64_t *envSub = envelope->envelope();
50     int64_t max = 0;
51
52     if (useFFT) {
53         FFTCorrelation::correlate(envMain, sizeMain,
54                                   envSub, sizeSub,
55                                   correlation);
56     } else {
57         correlate(envMain, sizeMain,
58                   envSub, sizeSub,
59                   correlation,
60                   &max);
61         info->setMax(max);
62     }
63
64
65     m_children.append(envelope);
66     m_correlations.append(info);
67
68     Q_ASSERT(m_correlations.size() == m_children.size());
69
70     return m_children.indexOf(envelope);
71 }
72
73 int AudioCorrelation::getShift(int childIndex) const
74 {
75     Q_ASSERT(childIndex >= 0);
76     Q_ASSERT(childIndex < m_correlations.size());
77
78     int indexOffset = m_correlations.at(childIndex)->maxIndex();
79     indexOffset -= m_children.at(childIndex)->envelopeSize();
80
81     return indexOffset;
82 }
83
84 AudioCorrelationInfo const* AudioCorrelation::info(int childIndex) const
85 {
86     Q_ASSERT(childIndex >= 0);
87     Q_ASSERT(childIndex < m_correlations.size());
88
89     return m_correlations.at(childIndex);
90 }
91
92
93 void AudioCorrelation::correlate(const int64_t *envMain, int sizeMain,
94                                  const int64_t *envSub, int sizeSub,
95                                  int64_t *correlation,
96                                  int64_t *out_max)
97 {
98     Q_ASSERT(correlation != NULL);
99
100     int64_t const* left;
101     int64_t const* right;
102     int size;
103     int64_t sum;
104     int64_t max = 0;
105
106
107     /*
108       Correlation:
109
110       SHIFT \in [-sS..sM]
111
112       <--sS----
113       [  sub  ]----sM--->[ sub ]
114                [  main  ]
115
116             ^ correlation vector index = SHIFT + sS
117
118       main is fixed, sub is shifted along main.
119
120     */
121
122
123     QTime t;
124     t.start();
125     for (int shift = -sizeSub; shift <= sizeMain; shift++) {
126
127         if (shift <= 0) {
128             left = envSub-shift;
129             right = envMain;
130             size = std::min(sizeSub+shift, sizeMain);
131         } else {
132             left = envSub;
133             right = envMain+shift;
134             size = std::min(sizeSub, sizeMain-shift);
135         }
136
137         sum = 0;
138         for (int i = 0; i < size; i++) {
139             sum += (*left) * (*right);
140             left++;
141             right++;
142         }
143         correlation[sizeSub+shift] = std::abs(sum);
144
145         if (sum > max) {
146             max = sum;
147         }
148
149     }
150     std::cout << "Correlation calculated. Time taken: " << t.elapsed() << " ms." << std::endl;
151
152     if (out_max != NULL) {
153         *out_max = max;
154     }
155 }