]> git.sesse.net Git - kdenlive/blob - testingArea/correlation.cpp
Working on FFT based correlation
[kdenlive] / testingArea / correlation.cpp
1
2 #include "../src/lib/audio/audioEnvelope.h"
3 #include "../src/lib/audio/fftCorrelation.h"
4
5 #include <QCoreApplication>
6 #include <QStringList>
7 #include <QImage>
8 #include <QDebug>
9 #include <iostream>
10
11 void printUsage(const char *path)
12 {
13     std::cout << "This executable takes two audio/video files A and B and determines " << std::endl
14               << "how much B needs to be shifted in order to be synchronized with A." << std::endl << std::endl
15               << path << " <main audio file> <second audio file>" << std::endl
16               << "\t-h, --help\n\t\tDisplay this help" << std::endl
17               << "\t--profile=<profile>\n\t\tUse the given profile for calculation (run: melt -query profiles)" << std::endl
18               << "\t--no-images\n\t\tDo not save envelope and correlation images" << std::endl
19                  ;
20 }
21
22 int main(int argc, char *argv[])
23 {
24     QCoreApplication app(argc, argv);
25     QStringList args = app.arguments();
26     args.removeAt(0);
27
28     std::string profile = "atsc_1080p_24";
29     bool saveImages = true;
30
31     // Load arguments
32     foreach (QString str, args) {
33
34         if (str.startsWith("--profile=")) {
35             QString s = str;
36             s.remove(0, QString("--profile=").length());
37             profile = s.toStdString();
38             args.removeOne(str);
39
40         } else if (str == "-h" || str == "--help") {
41             printUsage(argv[0]);
42             return 0;
43
44         } else if (str == "--no-images") {
45             saveImages = false;
46             args.removeOne(str);
47         }
48
49     }
50
51     if (args.length() < 2) {
52         printUsage(argv[0]);
53         return 1;
54     }
55
56
57
58     std::string fileMain(args.at(0).toStdString());
59     args.removeFirst();
60     std::string fileSub = args.at(0).toStdString();
61     args.removeFirst();
62
63
64     qDebug() << "Unused arguments: " << args;
65
66
67     if (argc > 2) {
68         fileMain = argv[1];
69         fileSub = argv[2];
70     } else {
71         std::cout << "Usage: " << argv[0] << " <main audio file> <second audio file>" << std::endl;
72         return 0;
73     }
74     std::cout << "Trying to align (2)\n\t" << fileSub << "\nto fit on (1)\n\t" << fileMain
75               << "\n, result will indicate by how much (2) has to be moved." << std::endl
76               << "Profile used: " << profile << std::endl
77                  ;
78
79
80     // Initialize MLT
81     Mlt::Factory::init(NULL);
82
83     // Load an arbitrary profile
84     Mlt::Profile prof(profile.c_str());
85
86     // Load the MLT producers
87     Mlt::Producer prodMain(prof, fileMain.c_str());
88     if (!prodMain.is_valid()) {
89         std::cout << fileMain << " is invalid." << std::endl;
90         return 2;
91     }
92     Mlt::Producer prodSub(prof, fileSub.c_str());
93     if (!prodSub.is_valid()) {
94         std::cout << fileSub << " is invalid." << std::endl;
95         return 2;
96     }
97
98
99     // Build the audio envelopes for the correlation
100     AudioEnvelope *envelopeMain = new AudioEnvelope(&prodMain);
101     envelopeMain->loadEnvelope();
102     envelopeMain->loadStdDev();
103     envelopeMain->dumpInfo();
104
105     AudioEnvelope *envelopeSub = new AudioEnvelope(&prodSub);
106     envelopeSub->loadEnvelope();
107     envelopeSub->loadStdDev();
108     envelopeSub->dumpInfo();
109
110     int leftSize = envelopeMain->envelopeSize();
111     int rightSize = envelopeSub->envelopeSize();
112     float left[leftSize];
113     float right[rightSize];
114     const int64_t *leftEnv = envelopeMain->envelope();
115     const int64_t *rightEnv = envelopeSub->envelope();
116
117     for (int i = 0; i < leftSize; i++) {
118         left[i] = double(leftEnv[i])/envelopeMain->maxValue();
119         if (i < 20) std::cout << left[i] << " ";
120     }
121     std::cout << " (max: " << envelopeMain->maxValue() << ")" << std::endl;
122     for (int i = 0; i < rightSize; i++) {
123         right[i] = double(rightEnv[i])/envelopeSub->maxValue();
124     }
125
126     float *correlated;
127     int corrSize = 0;
128     FFTCorrelation::correlate(left, leftSize, right, rightSize, &correlated, corrSize);
129
130     qDebug() << "Correlated: Size " << corrSize;
131
132     float max = 0;
133     for (int i = 0; i < corrSize; i++) {
134         if (correlated[i] > max) {
135             max = correlated[i];
136         }
137     }
138     qDebug() << "Max correlation value is " << max;
139
140     QImage img(corrSize, 400, QImage::Format_ARGB32);
141     img.fill(qRgb(255,255,255));
142     for (int x = 0; x < corrSize; x++) {
143         float val = correlated[x]/max;
144         for (int y = 0; y < 400*val; y++) {
145             img.setPixel(x, 400-1-y, qRgb(50,50,50));
146         }
147     }
148     img.save("correlated-fft.png");
149
150
151     delete correlated;
152
153 }