X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=testingArea%2FaudioOffset.cpp;h=f71b105231abff9bf53893809ab33cd9e3d836c2;hb=56aee6aedeeed3efd10ada8fe3c229eddc01ef05;hp=30bb936d5b155ddffee4e29f6095b91ccd8ce8f0;hpb=9e475c571a1a3f985663879cbc40678168f7a323;p=kdenlive diff --git a/testingArea/audioOffset.cpp b/testingArea/audioOffset.cpp index 30bb936d..f71b1052 100644 --- a/testingArea/audioOffset.cpp +++ b/testingArea/audioOffset.cpp @@ -1,33 +1,96 @@ -/*************************************************************************** - * Copyright (C) 2012 by Simon Andreas Eugster (simon.eu@gmail.com) * - * This file is part of kdenlive. See www.kdenlive.org. * - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - ***************************************************************************/ +/* +Copyright (C) 2012 Simon A. Eugster (Granjow) +This file is part of kdenlive. See www.kdenlive.org. +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. +*/ #include #include #include #include +#include #include #include +#include +#include #include #include #include #include -#include "audioInfo.h" -#include "audioStreamInfo.h" -#include "audioEnvelope.h" +#include "../src/lib/audio/audioInfo.h" +#include "../src/lib/audio/audioStreamInfo.h" +#include "../src/lib/audio/audioEnvelope.h" +#include "../src/lib/audio/audioCorrelation.h" + +void printUsage(const char *path) +{ + std::cout << "This executable takes two audio/video files A and B and determines " << std::endl + << "how much B needs to be shifted in order to be synchronized with A." << std::endl << std::endl + << path << "
" << std::endl + << "\t-h, --help\n\t\tDisplay this help" << std::endl + << "\t--fft\n\t\tUse Fourier Transform (FFT) to calculate the offset. This only takes" << std::endl + << "\t\tO(n log n) time compared to O(n²) when using normal correlation and should be " << std::endl + << "\t\tfaster for large data (several minutes)." << std::endl + << "\t--profile=\n\t\tUse the given profile for calculation (run: melt -query profiles)" << std::endl + << "\t--no-images\n\t\tDo not save envelope and correlation images" << std::endl + ; +} int main(int argc, char *argv[]) { - char *fileMain; - char *fileSub; + QCoreApplication app(argc, argv); + QStringList args = app.arguments(); + args.removeAt(0); + + std::string profile = "atsc_1080p_24"; + bool saveImages = true; + bool useFFT = false; + + // Load arguments + foreach (const QString &str, args) { + + if (str.startsWith("--profile=")) { + QString s = str; + s.remove(0, QString("--profile=").length()); + profile = s.toStdString(); + args.removeOne(str); + + } else if (str == "-h" || str == "--help") { + printUsage(argv[0]); + return 0; + + } else if (str == "--no-images") { + saveImages = false; + args.removeOne(str); + + } else if (str == "--fft") { + useFFT = true; + args.removeOne(str); + } + + } + + if (args.length() < 2) { + printUsage(argv[0]); + return 1; + } + + + + std::string fileMain(args.at(0).toStdString()); + args.removeFirst(); + std::string fileSub = args.at(0).toStdString(); + args.removeFirst(); + + + qDebug() << "Unused arguments: " << args; + + if (argc > 2) { fileMain = argv[1]; fileSub = argv[2]; @@ -35,106 +98,78 @@ int main(int argc, char *argv[]) std::cout << "Usage: " << argv[0] << "
" << std::endl; return 0; } - std::cout << "Trying to align (1)\n\t" << fileSub << "\nto fit on (2)\n\t" << fileMain - << "\n, result will indicate by how much (1) has to be moved." << std::endl; + std::cout << "Trying to align (2)\n\t" << fileSub << "\nto fit on (1)\n\t" << fileMain + << "\n, result will indicate by how much (2) has to be moved." << std::endl + << "Profile used: " << profile << std::endl + ; + if (useFFT) { + std::cout << "Will use FFT based correlation." << std::endl; + } + // Initialize MLT Mlt::Factory::init(NULL); // Load an arbitrary profile - Mlt::Profile prof("hdv_1080_25p"); + Mlt::Profile prof(profile.c_str()); // Load the MLT producers - Mlt::Producer prodMain(prof, fileMain); + Mlt::Producer prodMain(prof, fileMain.c_str()); if (!prodMain.is_valid()) { std::cout << fileMain << " is invalid." << std::endl; return 2; } - Mlt::Producer prodSub(prof, fileSub); + Mlt::Producer prodSub(prof, fileSub.c_str()); if (!prodSub.is_valid()) { std::cout << fileSub << " is invalid." << std::endl; return 2; } - AudioEnvelope envelopeMain(&prodMain); - envelopeMain.loadEnvelope(); - envelopeMain.loadStdDev(); - envelopeMain.dumpInfo(); - envelopeMain.normalizeEnvelope(); - envelopeMain.dumpInfo(); - - AudioEnvelope envelopeSub(&prodSub); - envelopeSub.loadEnvelope(); - envelopeMain.normalizeEnvelope(); - envelopeSub.dumpInfo(); - - - QString outImg = QString("envelope-%1.png") - .arg(QDateTime::currentDateTime().toString("yyyy-MM-dd-hh:mm:ss")); - envelopeMain.drawEnvelope().save(outImg); - std::cout << "Saved volume envelope as " - << QFileInfo(outImg).absoluteFilePath().toStdString() - << std::endl; - - - - const int sizeX = envelopeMain.envelopeSize(); - const int sizeY = envelopeSub.envelopeSize(); - int64_t correlation[sizeX + sizeY + 1]; - const int64_t *envX = envelopeMain.envelope(); - const int64_t *envY = envelopeSub.envelope(); - int64_t const* left; - int64_t const* right; - int size; - int64_t sum; - int64_t max = 0; - - QTime t; - t.start(); - for (int shift = -sizeX; shift <= sizeY; shift++) { - - if (shift <= 0) { - left = envX-shift; - right = envY; - size = std::min(sizeX+shift, sizeY); - } else { - left = envX; - right = envY+shift; - size = std::min(sizeX, sizeY-shift); - } - - sum = 0; - for (int i = 0; i < size; i++) { - sum += (*left) * (*right); - left++; - right++; - } - correlation[sizeX+shift] = std::abs(sum); - std::cout << sum << " "; - - if (sum > max) { - max = sum; - } + // Build the audio envelopes for the correlation + AudioEnvelope *envelopeMain = new AudioEnvelope(fileMain.c_str(), &prodMain); + envelopeMain->loadEnvelope(); + envelopeMain->loadStdDev(); + envelopeMain->dumpInfo(); + + AudioEnvelope *envelopeSub = new AudioEnvelope(fileSub.c_str(), &prodSub); + envelopeSub->loadEnvelope(); + envelopeSub->loadStdDev(); + envelopeSub->dumpInfo(); + + // Calculate the correlation and hereby the audio shift + AudioCorrelation corr(envelopeMain); + int index = corr.addChild(envelopeSub, useFFT); + + int shift = corr.getShift(index); + std::cout << " Should be shifted by " << shift << " frames: " << fileSub << std::endl + << "\trelative to " << fileMain << std::endl + << "\tin a " << prodMain.get_fps() << " fps profile (" << profile << ")." << std::endl; + + + if (saveImages) { + QString outImg = QString::fromLatin1("envelope-main-%1.png") + .arg(QDateTime::currentDateTime().toString("yyyy-MM-dd-hh:mm:ss")); + envelopeMain->drawEnvelope().save(outImg); + std::cout << "Saved volume envelope as " + << QFileInfo(outImg).absoluteFilePath().toStdString() + << std::endl; + outImg = QString::fromLatin1("envelope-sub-%1.png") + .arg(QDateTime::currentDateTime().toString("yyyy-MM-dd-hh:mm:ss")); + envelopeSub->drawEnvelope().save(outImg); + std::cout << "Saved volume envelope as " + << QFileInfo(outImg).absoluteFilePath().toStdString() + << std::endl; + outImg = QString::fromLatin1("correlation-%1.png") + .arg(QDateTime::currentDateTime().toString("yyyy-MM-dd-hh:mm:ss")); + corr.info(index)->toImage().save(outImg); + std::cout << "Saved correlation image as " + << QFileInfo(outImg).absoluteFilePath().toStdString() + << std::endl; } - std::cout << "Correlation calculated. Time taken: " << t.elapsed() << " ms." << std::endl; - - int val; - QImage img(sizeX + sizeY + 1, 400, QImage::Format_ARGB32); - img.fill(qRgb(255,255,255)); - for (int x = 0; x < sizeX+sizeY+1; x++) { - val = correlation[x]/double(max)*img.height(); - for (int y = img.height()-1; y > img.height() - val - 1; y--) { - img.setPixel(x, y, qRgb(50, 50, 50)); - } - } - outImg = QString("correlation-%1.png") - .arg(QDateTime::currentDateTime().toString("yyyy-MM-dd-hh:mm:ss")); - img.save(outImg); - std::cout << "Saved volume envelope as " - << QFileInfo(outImg).absoluteFilePath().toStdString() - << std::endl; + + // Mlt::Factory::close(); return 0;