2 #include "../src/lib/audio/audioEnvelope.h"
3 #include "../src/lib/audio/fftCorrelation.h"
5 #include <QCoreApplication>
11 void printUsage(const char *path)
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
22 int main(int argc, char *argv[])
24 QCoreApplication app(argc, argv);
25 QStringList args = app.arguments();
28 std::string profile = "atsc_1080p_24";
29 bool saveImages = true;
32 foreach (QString str, args) {
34 if (str.startsWith("--profile=")) {
36 s.remove(0, QString("--profile=").length());
37 profile = s.toStdString();
40 } else if (str == "-h" || str == "--help") {
44 } else if (str == "--no-images") {
51 if (args.length() < 2) {
58 std::string fileMain(args.at(0).toStdString());
60 std::string fileSub = args.at(0).toStdString();
64 qDebug() << "Unused arguments: " << args;
71 std::cout << "Usage: " << argv[0] << " <main audio file> <second audio file>" << std::endl;
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
81 Mlt::Factory::init(NULL);
83 // Load an arbitrary profile
84 Mlt::Profile prof(profile.c_str());
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;
92 Mlt::Producer prodSub(prof, fileSub.c_str());
93 if (!prodSub.is_valid()) {
94 std::cout << fileSub << " is invalid." << std::endl;
99 // Build the audio envelopes for the correlation
100 AudioEnvelope *envelopeMain = new AudioEnvelope(&prodMain);
101 envelopeMain->loadEnvelope();
102 envelopeMain->loadStdDev();
103 envelopeMain->dumpInfo();
105 AudioEnvelope *envelopeSub = new AudioEnvelope(&prodSub);
106 envelopeSub->loadEnvelope();
107 envelopeSub->loadStdDev();
108 envelopeSub->dumpInfo();
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();
117 for (int i = 0; i < leftSize; i++) {
118 left[i] = double(leftEnv[i])/envelopeMain->maxValue();
119 if (i < 20) std::cout << left[i] << " ";
121 std::cout << " (max: " << envelopeMain->maxValue() << ")" << std::endl;
122 for (int i = 0; i < rightSize; i++) {
123 right[i] = double(rightEnv[i])/envelopeSub->maxValue();
128 FFTCorrelation::correlate(left, leftSize, right, rightSize, &correlated, corrSize);
130 qDebug() << "Correlated: Size " << corrSize;
133 for (int i = 0; i < corrSize; i++) {
134 if (correlated[i] > max) {
138 qDebug() << "Max correlation value is " << max;
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));
148 img.save("correlated-fft.png");