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