]> git.sesse.net Git - kdenlive/blob - src/lib/audio/audioCorrelation.cpp
Auto-align works!
[kdenlive] / src / lib / audio / audioCorrelation.cpp
1 /***************************************************************************
2  *   Copyright (C) 2012 by Simon Andreas Eugster (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 2 of the License, or     *
8  *   (at your option) any later version.                                   *
9  ***************************************************************************/
10
11 #include "audioCorrelation.h"
12
13 #include <QTime>
14 #include <cmath>
15 #include <iostream>
16
17 AudioCorrelation::AudioCorrelation(AudioEnvelope *mainTrackEnvelope) :
18     m_mainTrackEnvelope(mainTrackEnvelope)
19 {
20     m_mainTrackEnvelope->normalizeEnvelope();
21 }
22
23 AudioCorrelation::~AudioCorrelation()
24 {
25     delete m_mainTrackEnvelope;
26     foreach (AudioEnvelope *envelope, m_children) {
27         delete envelope;
28     }
29     std::cout << "Envelope deleted." << std::endl;
30 }
31
32 int AudioCorrelation::addChild(AudioEnvelope *envelope)
33 {
34     envelope->normalizeEnvelope();
35
36     const int sizeMain = m_mainTrackEnvelope->envelopeSize();
37     const int sizeSub = envelope->envelopeSize();
38
39
40     AudioCorrelationInfo *info = new AudioCorrelationInfo(sizeMain, sizeSub);
41     int64_t *correlation = info->correlationVector();
42
43     const int64_t *envMain = m_mainTrackEnvelope->envelope();
44     const int64_t *envSub = envelope->envelope();
45     int64_t const* left;
46     int64_t const* right;
47     int size;
48     int64_t sum;
49     int64_t max = 0;
50
51
52     /*
53       Correlation:
54
55       SHIFT \in [-sS..sM]
56
57       <--sS----
58       [  sub  ]----sM--->[ sub ]
59                [  main  ]
60
61             ^ correlation vector index = SHIFT + sS
62
63       main is fixed, sub is shifted along main.
64
65     */
66
67
68     QTime t;
69     t.start();
70     for (int shift = -sizeSub; shift <= sizeMain; shift++) {
71
72         if (shift <= 0) {
73             left = envSub-shift;
74             right = envMain;
75             size = std::min(sizeSub+shift, sizeMain);
76         } else {
77             left = envSub;
78             right = envMain+shift;
79             size = std::min(sizeSub, sizeMain-shift);
80         }
81
82         sum = 0;
83         for (int i = 0; i < size; i++) {
84             sum += (*left) * (*right);
85             left++;
86             right++;
87         }
88         correlation[sizeSub+shift] = std::abs(sum);
89
90         if (sum > max) {
91             max = sum;
92         }
93
94     }
95     info->setMax(max);
96     std::cout << "Correlation calculated. Time taken: " << t.elapsed() << " ms." << std::endl;
97
98
99     m_children.append(envelope);
100     m_correlations.append(info);
101
102     Q_ASSERT(m_correlations.size() == m_children.size());
103
104     return m_children.indexOf(envelope);
105 }
106
107 int AudioCorrelation::getShift(int childIndex) const
108 {
109     Q_ASSERT(childIndex >= 0);
110     Q_ASSERT(childIndex < m_correlations.size());
111
112     int indexOffset = m_correlations.at(childIndex)->maxIndex();
113     indexOffset -= m_children.at(childIndex)->envelopeSize();
114
115     return indexOffset;
116 }
117
118 AudioCorrelationInfo const* AudioCorrelation::info(int childIndex) const
119 {
120     Q_ASSERT(childIndex >= 0);
121     Q_ASSERT(childIndex < m_correlations.size());
122
123     return m_correlations.at(childIndex);
124 }