]> git.sesse.net Git - kdenlive/blob - testingArea/audioOffset.cpp
Calculating correlation to synchronize audio tracks
[kdenlive] / testingArea / audioOffset.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
12 #include <QMap>
13 #include <QFile>
14 #include <QTime>
15 #include <QImage>
16 #include <QFileInfo>
17 #include <QDateTime>
18 #include <mlt++/Mlt.h>
19 #include <iostream>
20 #include <cstdlib>
21 #include <cmath>
22
23 #include "audioInfo.h"
24 #include "audioStreamInfo.h"
25 #include "audioEnvelope.h"
26
27 int main(int argc, char *argv[])
28 {
29     char *fileMain;
30     char *fileSub;
31     if (argc > 2) {
32         fileMain = argv[1];
33         fileSub = argv[2];
34     } else {
35         std::cout << "Usage: " << argv[0] << " <main audio file> <second audio file>" << std::endl;
36         return 0;
37     }
38     std::cout << "Trying to align (1)\n\t" << fileSub << "\nto fit on (2)\n\t" << fileMain
39               << "\n, result will indicate by how much (1) has to be moved." << std::endl;
40
41     // Initialize MLT
42     Mlt::Factory::init(NULL);
43
44     // Load an arbitrary profile
45     Mlt::Profile prof("hdv_1080_25p");
46
47     // Load the MLT producers
48     Mlt::Producer prodMain(prof, fileMain);
49     if (!prodMain.is_valid()) {
50         std::cout << fileMain << " is invalid." << std::endl;
51         return 2;
52     }
53     Mlt::Producer prodSub(prof, fileSub);
54     if (!prodSub.is_valid()) {
55         std::cout << fileSub << " is invalid." << std::endl;
56         return 2;
57     }
58
59     AudioEnvelope envelopeMain(&prodMain);
60     envelopeMain.loadEnvelope();
61     envelopeMain.loadStdDev();
62     envelopeMain.dumpInfo();
63     envelopeMain.normalizeEnvelope();
64     envelopeMain.dumpInfo();
65
66     AudioEnvelope envelopeSub(&prodSub);
67     envelopeSub.loadEnvelope();
68     envelopeMain.normalizeEnvelope();
69     envelopeSub.dumpInfo();
70
71
72     QString outImg = QString("envelope-%1.png")
73             .arg(QDateTime::currentDateTime().toString("yyyy-MM-dd-hh:mm:ss"));
74     envelopeMain.drawEnvelope().save(outImg);
75     std::cout << "Saved volume envelope as "
76               << QFileInfo(outImg).absoluteFilePath().toStdString()
77               << std::endl;
78
79
80
81     const int sizeX = envelopeMain.envelopeSize();
82     const int sizeY = envelopeSub.envelopeSize();
83     int64_t correlation[sizeX + sizeY + 1];
84     const int64_t *envX = envelopeMain.envelope();
85     const int64_t *envY = envelopeSub.envelope();
86     int64_t const* left;
87     int64_t const* right;
88     int size;
89     int64_t sum;
90     int64_t max = 0;
91
92     QTime t;
93     t.start();
94     for (int shift = -sizeX; shift <= sizeY; shift++) {
95
96         if (shift <= 0) {
97             left = envX-shift;
98             right = envY;
99             size = std::min(sizeX+shift, sizeY);
100         } else {
101             left = envX;
102             right = envY+shift;
103             size = std::min(sizeX, sizeY-shift);
104         }
105
106         sum = 0;
107         for (int i = 0; i < size; i++) {
108             sum += (*left) * (*right);
109             left++;
110             right++;
111         }
112         correlation[sizeX+shift] = std::abs(sum);
113         std::cout << sum << " ";
114
115         if (sum > max) {
116             max = sum;
117         }
118
119     }
120     std::cout << "Correlation calculated. Time taken: " << t.elapsed() << " ms." << std::endl;
121
122     int val;
123     QImage img(sizeX + sizeY + 1, 400, QImage::Format_ARGB32);
124     img.fill(qRgb(255,255,255));
125     for (int x = 0; x < sizeX+sizeY+1; x++) {
126         val = correlation[x]/double(max)*img.height();
127         for (int y = img.height()-1; y > img.height() - val - 1; y--) {
128             img.setPixel(x, y, qRgb(50, 50, 50));
129         }
130     }
131
132     outImg = QString("correlation-%1.png")
133             .arg(QDateTime::currentDateTime().toString("yyyy-MM-dd-hh:mm:ss"));
134     img.save(outImg);
135     std::cout << "Saved volume envelope as "
136               << QFileInfo(outImg).absoluteFilePath().toStdString()
137               << std::endl;
138
139
140     return 0;
141
142 }
143
144
145