]> git.sesse.net Git - kdenlive/blob - testingArea/audioOffset.cpp
842096aa61c4113c0748925197730f352760f474
[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 <QDebug>
17 #include <QFileInfo>
18 #include <QDateTime>
19 #include <QStringList>
20 #include <QCoreApplication>
21 #include <mlt++/Mlt.h>
22 #include <iostream>
23 #include <cstdlib>
24 #include <cmath>
25
26 #include "audioInfo.h"
27 #include "audioStreamInfo.h"
28 #include "audioEnvelope.h"
29 #include "audioCorrelation.h"
30
31 void printUsage(const char *path)
32 {
33     std::cout << "Usage: " << path << " <main audio file> <second audio file>" << std::endl
34               << "\t-h, --help\tDisplay this help" << std::endl
35               << "\t--profile=<profile>\tUse the given profile for calculation (run: melt -query profiles)" << std::endl
36               << "\t--no-images\tDo not save envelope and correlation images" << std::endl
37                  ;
38 }
39
40 int main(int argc, char *argv[])
41 {
42     QCoreApplication app(argc, argv);
43     QStringList args = app.arguments();
44     args.removeAt(0);
45
46     std::string profile = "atsc_1080p_24";
47     bool saveImages = true;
48
49     // Load arguments
50     foreach (QString str, args) {
51
52         if (str.startsWith("--profile=")) {
53             QString s = str;
54             s.remove(0, QString("--profile=").length());
55             profile = s.toStdString();
56             args.removeOne(str);
57
58         } else if (str == "-h" || str == "--help") {
59             printUsage(argv[0]);
60             return 0;
61
62         } else if (str == "--no-images") {
63             saveImages = false;
64             args.removeOne(str);
65         }
66
67     }
68
69     if (args.length() < 2) {
70         printUsage(argv[0]);
71         return 1;
72     }
73
74
75
76     std::string fileMain(args.at(0).toStdString());
77     args.removeFirst();
78     std::string fileSub = args.at(0).toStdString();
79     args.removeFirst();
80
81
82     qDebug() << "Unused arguments: " << args;
83
84
85     if (argc > 2) {
86         fileMain = argv[1];
87         fileSub = argv[2];
88     } else {
89         std::cout << "Usage: " << argv[0] << " <main audio file> <second audio file>" << std::endl;
90         return 0;
91     }
92     std::cout << "Trying to align (2)\n\t" << fileSub << "\nto fit on (1)\n\t" << fileMain
93               << "\n, result will indicate by how much (2) has to be moved." << std::endl
94               << "Profile used: " << profile << std::endl
95                  ;
96
97
98     // Initialize MLT
99     Mlt::Factory::init(NULL);
100
101     // Load an arbitrary profile
102     Mlt::Profile prof(profile.c_str());
103
104     // Load the MLT producers
105     Mlt::Producer prodMain(prof, fileMain.c_str());
106     if (!prodMain.is_valid()) {
107         std::cout << fileMain << " is invalid." << std::endl;
108         return 2;
109     }
110     Mlt::Producer prodSub(prof, fileSub.c_str());
111     if (!prodSub.is_valid()) {
112         std::cout << fileSub << " is invalid." << std::endl;
113         return 2;
114     }
115
116
117     // Build the audio envelopes for the correlation
118     AudioEnvelope envelopeMain(&prodMain);
119     envelopeMain.loadEnvelope();
120     envelopeMain.loadStdDev();
121     envelopeMain.dumpInfo();
122
123     AudioEnvelope envelopeSub(&prodSub);
124     envelopeSub.loadEnvelope();
125     envelopeSub.loadStdDev();
126     envelopeSub.dumpInfo();
127
128
129
130
131
132
133     // Calculate the correlation and hereby the audio shift
134     AudioCorrelation corr(&envelopeMain);
135     int index = corr.addChild(&envelopeSub);
136
137     int shift = corr.getShift(index);
138     std::cout << fileSub << " should be shifted by " << shift << " frames" << std::endl
139               << "\trelative to " << fileMain << std::endl
140               << "\tin a " << prodMain.get_fps() << " fps profile (" << profile << ")." << std::endl
141                  ;
142
143
144     if (saveImages) {
145         QString outImg;
146         outImg = QString("envelope-main-%1.png")
147                 .arg(QDateTime::currentDateTime().toString("yyyy-MM-dd-hh:mm:ss"));
148         envelopeMain.drawEnvelope().save(outImg);
149         std::cout << "Saved volume envelope as "
150                   << QFileInfo(outImg).absoluteFilePath().toStdString()
151                   << std::endl;
152         outImg = QString("envelope-sub-%1.png")
153                 .arg(QDateTime::currentDateTime().toString("yyyy-MM-dd-hh:mm:ss"));
154         envelopeSub.drawEnvelope().save(outImg);
155         std::cout << "Saved volume envelope as "
156                   << QFileInfo(outImg).absoluteFilePath().toStdString()
157                   << std::endl;
158         outImg = QString("correlation-%1.png")
159                 .arg(QDateTime::currentDateTime().toString("yyyy-MM-dd-hh:mm:ss"));
160         corr.info(index)->toImage().save(outImg);
161         std::cout << "Saved correlation image as "
162                   << QFileInfo(outImg).absoluteFilePath().toStdString()
163                   << std::endl;
164     }
165
166
167     return 0;
168
169 }
170
171
172