1 /***************************************************************************
2 * Copyright (C) 2012 by Simon Andreas Eugster (simon.eu@gmail.com) *
3 * This file is part of kdenlive. See www.kdenlive.org. *
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 ***************************************************************************/
19 #include <QStringList>
20 #include <QCoreApplication>
21 #include <mlt++/Mlt.h>
26 #include "../src/lib/audio/audioInfo.h"
27 #include "../src/lib/audio/audioStreamInfo.h"
28 #include "../src/lib/audio/audioEnvelope.h"
29 #include "../src/lib/audio/audioCorrelation.h"
31 void printUsage(const char *path)
33 std::cout << "This executable takes two audio/video files A and B and determines " << std::endl
34 << "how much B needs to be shifted in order to be synchronized with A." << std::endl << std::endl
35 << path << " <main audio file> <second audio file>" << std::endl
36 << "\t-h, --help\n\t\tDisplay this help" << std::endl
37 << "\t--profile=<profile>\n\t\tUse the given profile for calculation (run: melt -query profiles)" << std::endl
38 << "\t--no-images\n\t\tDo not save envelope and correlation images" << std::endl
42 int main(int argc, char *argv[])
44 QCoreApplication app(argc, argv);
45 QStringList args = app.arguments();
48 std::string profile = "atsc_1080p_24";
49 bool saveImages = true;
52 foreach (QString str, args) {
54 if (str.startsWith("--profile=")) {
56 s.remove(0, QString("--profile=").length());
57 profile = s.toStdString();
60 } else if (str == "-h" || str == "--help") {
64 } else if (str == "--no-images") {
71 if (args.length() < 2) {
78 std::string fileMain(args.at(0).toStdString());
80 std::string fileSub = args.at(0).toStdString();
84 qDebug() << "Unused arguments: " << args;
91 std::cout << "Usage: " << argv[0] << " <main audio file> <second audio file>" << std::endl;
94 std::cout << "Trying to align (2)\n\t" << fileSub << "\nto fit on (1)\n\t" << fileMain
95 << "\n, result will indicate by how much (2) has to be moved." << std::endl
96 << "Profile used: " << profile << std::endl
101 Mlt::Factory::init(NULL);
103 // Load an arbitrary profile
104 Mlt::Profile prof(profile.c_str());
106 // Load the MLT producers
107 Mlt::Producer prodMain(prof, fileMain.c_str());
108 if (!prodMain.is_valid()) {
109 std::cout << fileMain << " is invalid." << std::endl;
112 Mlt::Producer prodSub(prof, fileSub.c_str());
113 if (!prodSub.is_valid()) {
114 std::cout << fileSub << " is invalid." << std::endl;
119 // Build the audio envelopes for the correlation
120 AudioEnvelope *envelopeMain = new AudioEnvelope(&prodMain);
121 envelopeMain->loadEnvelope();
122 envelopeMain->loadStdDev();
123 envelopeMain->dumpInfo();
125 AudioEnvelope *envelopeSub = new AudioEnvelope(&prodSub);
126 envelopeSub->loadEnvelope();
127 envelopeSub->loadStdDev();
128 envelopeSub->dumpInfo();
135 // Calculate the correlation and hereby the audio shift
136 AudioCorrelation corr(envelopeMain);
137 int index = corr.addChild(envelopeSub);
139 int shift = corr.getShift(index);
140 std::cout << fileSub << " should be shifted by " << shift << " frames" << std::endl
141 << "\trelative to " << fileMain << std::endl
142 << "\tin a " << prodMain.get_fps() << " fps profile (" << profile << ")." << std::endl
148 outImg = QString("envelope-main-%1.png")
149 .arg(QDateTime::currentDateTime().toString("yyyy-MM-dd-hh:mm:ss"));
150 envelopeMain->drawEnvelope().save(outImg);
151 std::cout << "Saved volume envelope as "
152 << QFileInfo(outImg).absoluteFilePath().toStdString()
154 outImg = QString("envelope-sub-%1.png")
155 .arg(QDateTime::currentDateTime().toString("yyyy-MM-dd-hh:mm:ss"));
156 envelopeSub->drawEnvelope().save(outImg);
157 std::cout << "Saved volume envelope as "
158 << QFileInfo(outImg).absoluteFilePath().toStdString()
160 outImg = QString("correlation-%1.png")
161 .arg(QDateTime::currentDateTime().toString("yyyy-MM-dd-hh:mm:ss"));
162 corr.info(index)->toImage().save(outImg);
163 std::cout << "Saved correlation image as "
164 << QFileInfo(outImg).absoluteFilePath().toStdString()