Merge pull request #48 from DanielSWolf/bugfix/#46-progress
Fix progress reporting
This commit is contained in:
commit
f4418ff25a
|
@ -3,6 +3,7 @@
|
||||||
## Unreleased
|
## Unreleased
|
||||||
|
|
||||||
* **Added** basic support for non-English recordings through phonetic recognition ([issue #45](https://github.com/DanielSWolf/rhubarb-lip-sync/issues/45)).
|
* **Added** basic support for non-English recordings through phonetic recognition ([issue #45](https://github.com/DanielSWolf/rhubarb-lip-sync/issues/45)).
|
||||||
|
* **Fixed** a bug that prevented the progress bar from reaching 100% ([issue #48](https://github.com/DanielSWolf/rhubarb-lip-sync/issues/48)).
|
||||||
|
|
||||||
## Version 1.8.0
|
## Version 1.8.0
|
||||||
|
|
||||||
|
|
|
@ -467,6 +467,8 @@ add_library(rhubarb-tools
|
||||||
src/tools/parallel.h
|
src/tools/parallel.h
|
||||||
src/tools/platformTools.cpp
|
src/tools/platformTools.cpp
|
||||||
src/tools/platformTools.h
|
src/tools/platformTools.h
|
||||||
|
src/tools/progress.cpp
|
||||||
|
src/tools/progress.h
|
||||||
src/tools/ProgressBar.cpp
|
src/tools/ProgressBar.cpp
|
||||||
src/tools/ProgressBar.h
|
src/tools/ProgressBar.h
|
||||||
src/tools/stringTools.cpp
|
src/tools/stringTools.cpp
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
#include "processing.h"
|
#include "processing.h"
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
using std::function;
|
using std::function;
|
||||||
using std::vector;
|
using std::vector;
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <functional>
|
#include <functional>
|
||||||
#include "AudioClip.h"
|
#include "AudioClip.h"
|
||||||
#include "tools/ProgressBar.h"
|
#include "tools/progress.h"
|
||||||
|
|
||||||
void process16bitAudioClip(const AudioClip& audioClip, std::function<void(const std::vector<int16_t>&)> processBuffer, size_t bufferCapacity, ProgressSink& progressSink);
|
void process16bitAudioClip(const AudioClip& audioClip, std::function<void(const std::vector<int16_t>&)> processBuffer, size_t bufferCapacity, ProgressSink& progressSink);
|
||||||
void process16bitAudioClip(const AudioClip& audioClip, std::function<void(const std::vector<int16_t>&)> processBuffer, ProgressSink& progressSink);
|
void process16bitAudioClip(const AudioClip& audioClip, std::function<void(const std::vector<int16_t>&)> processBuffer, ProgressSink& progressSink);
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
#include "AudioClip.h"
|
#include "AudioClip.h"
|
||||||
#include "time/BoundedTimeline.h"
|
#include "time/BoundedTimeline.h"
|
||||||
#include "tools/ProgressBar.h"
|
#include "tools/progress.h"
|
||||||
|
|
||||||
JoiningBoundedTimeline<void> detectVoiceActivity(const AudioClip& audioClip, int maxThreadCount, ProgressSink& progressSink);
|
JoiningBoundedTimeline<void> detectVoiceActivity(const AudioClip& audioClip, int maxThreadCount, ProgressSink& progressSink);
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
#include "core/Shape.h"
|
#include "core/Shape.h"
|
||||||
#include "time/ContinuousTimeline.h"
|
#include "time/ContinuousTimeline.h"
|
||||||
#include "audio/AudioClip.h"
|
#include "audio/AudioClip.h"
|
||||||
#include "tools/ProgressBar.h"
|
#include "tools/progress.h"
|
||||||
#include <boost/filesystem.hpp>
|
#include <boost/filesystem.hpp>
|
||||||
#include "animation/targetShapeSet.h"
|
#include "animation/targetShapeSet.h"
|
||||||
#include "recognition/Recognizer.h"
|
#include "recognition/Recognizer.h"
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
#include "audio/AudioClip.h"
|
#include "audio/AudioClip.h"
|
||||||
#include "core/Phone.h"
|
#include "core/Phone.h"
|
||||||
#include "tools/ProgressBar.h"
|
#include "tools/progress.h"
|
||||||
#include "time/BoundedTimeline.h"
|
#include "time/BoundedTimeline.h"
|
||||||
|
|
||||||
class Recognizer {
|
class Recognizer {
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
#include "time/BoundedTimeline.h"
|
#include "time/BoundedTimeline.h"
|
||||||
#include "core/Phone.h"
|
#include "core/Phone.h"
|
||||||
#include "audio/AudioClip.h"
|
#include "audio/AudioClip.h"
|
||||||
#include "tools/ProgressBar.h"
|
#include "tools/progress.h"
|
||||||
#include <boost/filesystem/path.hpp>
|
#include <boost/filesystem/path.hpp>
|
||||||
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
|
|
|
@ -16,6 +16,7 @@ using boost::optional;
|
||||||
|
|
||||||
NiceStderrSink::NiceStderrSink(Level minLevel) :
|
NiceStderrSink::NiceStderrSink(Level minLevel) :
|
||||||
minLevel(minLevel),
|
minLevel(minLevel),
|
||||||
|
progress(0.0),
|
||||||
innerSink(make_shared<StdErrSink>(make_shared<SimpleConsoleFormatter>()))
|
innerSink(make_shared<StdErrSink>(make_shared<SimpleConsoleFormatter>()))
|
||||||
{}
|
{}
|
||||||
|
|
||||||
|
@ -26,7 +27,8 @@ void NiceStderrSink::receive(const logging::Entry& entry) {
|
||||||
startProgressIndication();
|
startProgressIndication();
|
||||||
} else if (const ProgressEntry* progressEntry = dynamic_cast<const ProgressEntry*>(&entry)) {
|
} else if (const ProgressEntry* progressEntry = dynamic_cast<const ProgressEntry*>(&entry)) {
|
||||||
assert(progressBar);
|
assert(progressBar);
|
||||||
progressBar->reportProgress(progressEntry->getProgress());
|
progress = progressEntry->getProgress();
|
||||||
|
progressBar->reportProgress(progress);
|
||||||
} else if (dynamic_cast<const SuccessEntry*>(&entry)) {
|
} else if (dynamic_cast<const SuccessEntry*>(&entry)) {
|
||||||
interruptProgressIndication();
|
interruptProgressIndication();
|
||||||
std::cerr << "Done." << std::endl;
|
std::cerr << "Done." << std::endl;
|
||||||
|
@ -44,7 +46,6 @@ void NiceStderrSink::receive(const logging::Entry& entry) {
|
||||||
void NiceStderrSink::startProgressIndication() {
|
void NiceStderrSink::startProgressIndication() {
|
||||||
std::cerr << "Progress: ";
|
std::cerr << "Progress: ";
|
||||||
progressBar = boost::in_place();
|
progressBar = boost::in_place();
|
||||||
progressBar->setClearOnDestruction(false);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void NiceStderrSink::interruptProgressIndication() {
|
void NiceStderrSink::interruptProgressIndication() {
|
||||||
|
@ -54,8 +55,7 @@ void NiceStderrSink::interruptProgressIndication() {
|
||||||
|
|
||||||
void NiceStderrSink::resumeProgressIndication() {
|
void NiceStderrSink::resumeProgressIndication() {
|
||||||
std::cerr << "Progress (cont'd): ";
|
std::cerr << "Progress (cont'd): ";
|
||||||
progressBar = boost::in_place();
|
progressBar = boost::in_place(progress);
|
||||||
progressBar->setClearOnDestruction(false);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
QuietStderrSink::QuietStderrSink(Level minLevel) :
|
QuietStderrSink::QuietStderrSink(Level minLevel) :
|
||||||
|
|
|
@ -17,6 +17,7 @@ private:
|
||||||
void resumeProgressIndication();
|
void resumeProgressIndication();
|
||||||
|
|
||||||
logging::Level minLevel;
|
logging::Level minLevel;
|
||||||
|
double progress;
|
||||||
boost::optional<ProgressBar> progressBar;
|
boost::optional<ProgressBar> progressBar;
|
||||||
std::shared_ptr<Sink> innerSink;
|
std::shared_ptr<Sink> innerSink;
|
||||||
};
|
};
|
||||||
|
|
|
@ -3,55 +3,26 @@
|
||||||
#include <future>
|
#include <future>
|
||||||
#include <chrono>
|
#include <chrono>
|
||||||
#include <format.h>
|
#include <format.h>
|
||||||
#include <iostream>
|
|
||||||
#include <boost/algorithm/clamp.hpp>
|
#include <boost/algorithm/clamp.hpp>
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
|
|
||||||
using std::string;
|
using std::string;
|
||||||
|
|
||||||
ProgressForwarder::ProgressForwarder(std::function<void(double progress)> callback) :
|
double sanitizeProgress(double progress) {
|
||||||
callback(callback)
|
// Make sure value is in [0..1] range
|
||||||
|
return std::isnan(progress)
|
||||||
|
? 0.0
|
||||||
|
: boost::algorithm::clamp(progress, 0.0, 1.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
ProgressBar::ProgressBar(double progress) :
|
||||||
|
ProgressBar(std::cerr, progress)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
void ProgressForwarder::reportProgress(double value) {
|
ProgressBar::ProgressBar(std::ostream& stream, double progress) :
|
||||||
callback(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
ProgressMerger::ProgressMerger(ProgressSink& sink) :
|
|
||||||
sink(sink)
|
|
||||||
{}
|
|
||||||
|
|
||||||
ProgressSink& ProgressMerger::addSink(double weight) {
|
|
||||||
std::lock_guard<std::mutex> lock(mutex);
|
|
||||||
|
|
||||||
totalWeight += weight;
|
|
||||||
int sinkIndex = weightedValues.size();
|
|
||||||
weightedValues.push_back(0);
|
|
||||||
forwarders.push_back(ProgressForwarder([weight, sinkIndex, this](double progress) {
|
|
||||||
weightedValues[sinkIndex] = progress * weight;
|
|
||||||
report();
|
|
||||||
}));
|
|
||||||
return forwarders.back();
|
|
||||||
}
|
|
||||||
|
|
||||||
void ProgressMerger::report() {
|
|
||||||
std::lock_guard<std::mutex> lock(mutex);
|
|
||||||
|
|
||||||
if (totalWeight != 0) {
|
|
||||||
double weightedSum = 0;
|
|
||||||
for (double weightedValue : weightedValues) {
|
|
||||||
weightedSum += weightedValue;
|
|
||||||
}
|
|
||||||
double progress = weightedSum / totalWeight;
|
|
||||||
sink.reportProgress(progress);
|
|
||||||
} else {
|
|
||||||
sink.reportProgress(0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ProgressBar::ProgressBar(std::ostream& stream) :
|
|
||||||
stream(stream)
|
stream(stream)
|
||||||
{
|
{
|
||||||
|
currentProgress = sanitizeProgress(progress);
|
||||||
updateLoopFuture = std::async(std::launch::async, &ProgressBar::updateLoop, this);
|
updateLoopFuture = std::async(std::launch::async, &ProgressBar::updateLoop, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -61,37 +32,42 @@ ProgressBar::~ProgressBar() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void ProgressBar::reportProgress(double value) {
|
void ProgressBar::reportProgress(double value) {
|
||||||
// Make sure value is in [0..1] range
|
currentProgress = sanitizeProgress(value);
|
||||||
value = boost::algorithm::clamp(value, 0.0, 1.0);
|
|
||||||
if (std::isnan(value)) {
|
|
||||||
value = 0.0;
|
|
||||||
}
|
|
||||||
|
|
||||||
currentProgress = value;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ProgressBar::updateLoop() {
|
void ProgressBar::updateLoop() {
|
||||||
const int blockCount = 20;
|
|
||||||
const std::chrono::milliseconds animationInterval(1000 / 8);
|
const std::chrono::milliseconds animationInterval(1000 / 8);
|
||||||
const string animation = "|/-\\";
|
|
||||||
|
|
||||||
while (!done) {
|
while (!done) {
|
||||||
int progressBlockCount = static_cast<int>(currentProgress * blockCount);
|
update();
|
||||||
int percent = static_cast<int>(currentProgress * 100);
|
|
||||||
string text = fmt::format("[{0}{1}] {2:3}% {3}",
|
|
||||||
string(progressBlockCount, '#'), string(blockCount - progressBlockCount, '-'),
|
|
||||||
percent,
|
|
||||||
animation[animationIndex++ % animation.size()]);
|
|
||||||
updateText(text);
|
|
||||||
|
|
||||||
std::this_thread::sleep_for(animationInterval);
|
std::this_thread::sleep_for(animationInterval);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (clearOnDestruction) {
|
if (clearOnDestruction) {
|
||||||
updateText("");
|
updateText("");
|
||||||
|
} else {
|
||||||
|
update(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ProgressBar::update(bool showSpinner) {
|
||||||
|
const int blockCount = 20;
|
||||||
|
const string animation = "|/-\\";
|
||||||
|
|
||||||
|
int progressBlockCount = static_cast<int>(currentProgress * blockCount);
|
||||||
|
const double epsilon = 0.0001;
|
||||||
|
int percent = static_cast<int>(currentProgress * 100 + epsilon);
|
||||||
|
const string spinner = showSpinner
|
||||||
|
? string(1, animation[animationIndex++ % animation.size()])
|
||||||
|
: "";
|
||||||
|
string text = fmt::format("[{0}{1}] {2:3}% {3}",
|
||||||
|
string(progressBlockCount, '#'), string(blockCount - progressBlockCount, '-'),
|
||||||
|
percent,
|
||||||
|
spinner
|
||||||
|
);
|
||||||
|
updateText(text);
|
||||||
|
}
|
||||||
|
|
||||||
void ProgressBar::updateText(const string& text) {
|
void ProgressBar::updateText(const string& text) {
|
||||||
// Get length of common portion
|
// Get length of common portion
|
||||||
int commonPrefixLength = 0;
|
int commonPrefixLength = 0;
|
||||||
|
|
|
@ -2,49 +2,13 @@
|
||||||
|
|
||||||
#include <atomic>
|
#include <atomic>
|
||||||
#include <future>
|
#include <future>
|
||||||
#include <functional>
|
|
||||||
#include <list>
|
|
||||||
#include <vector>
|
|
||||||
#include <mutex>
|
|
||||||
#include <string>
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
#include "progress.h"
|
||||||
class ProgressSink {
|
|
||||||
public:
|
|
||||||
virtual ~ProgressSink() {}
|
|
||||||
virtual void reportProgress(double value) = 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
class NullProgressSink : public ProgressSink {
|
|
||||||
public:
|
|
||||||
void reportProgress(double) override {}
|
|
||||||
};
|
|
||||||
|
|
||||||
class ProgressForwarder : public ProgressSink {
|
|
||||||
public:
|
|
||||||
ProgressForwarder(std::function<void(double progress)> callback);
|
|
||||||
void reportProgress(double value) override;
|
|
||||||
private:
|
|
||||||
std::function<void(double progress)> callback;
|
|
||||||
};
|
|
||||||
|
|
||||||
class ProgressMerger {
|
|
||||||
public:
|
|
||||||
ProgressMerger(ProgressSink& sink);
|
|
||||||
ProgressSink& addSink(double weight);
|
|
||||||
private:
|
|
||||||
void report();
|
|
||||||
|
|
||||||
ProgressSink& sink;
|
|
||||||
std::mutex mutex;
|
|
||||||
double totalWeight = 0;
|
|
||||||
std::list<ProgressForwarder> forwarders;
|
|
||||||
std::vector<double> weightedValues;
|
|
||||||
};
|
|
||||||
|
|
||||||
class ProgressBar : public ProgressSink {
|
class ProgressBar : public ProgressSink {
|
||||||
public:
|
public:
|
||||||
ProgressBar(std::ostream& stream = std::cerr);
|
explicit ProgressBar(double progress = 0.0);
|
||||||
|
ProgressBar(std::ostream& stream, double progress = 0.0);
|
||||||
~ProgressBar();
|
~ProgressBar();
|
||||||
void reportProgress(double value) override;
|
void reportProgress(double value) override;
|
||||||
|
|
||||||
|
@ -58,6 +22,7 @@ public:
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void updateLoop();
|
void updateLoop();
|
||||||
|
void update(bool showSpinner = true);
|
||||||
void updateText(const std::string& text);
|
void updateText(const std::string& text);
|
||||||
|
|
||||||
std::future<void> updateLoopFuture;
|
std::future<void> updateLoopFuture;
|
||||||
|
@ -67,5 +32,5 @@ private:
|
||||||
std::ostream& stream;
|
std::ostream& stream;
|
||||||
std::string currentText;
|
std::string currentText;
|
||||||
int animationIndex = 0;
|
int animationIndex = 0;
|
||||||
bool clearOnDestruction = true;
|
bool clearOnDestruction = false;
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,7 +1,8 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <functional>
|
#include <functional>
|
||||||
#include "ProgressBar.h"
|
#include <future>
|
||||||
|
#include "progress.h"
|
||||||
#include <gsl_util.h>
|
#include <gsl_util.h>
|
||||||
|
|
||||||
template<typename TCollection>
|
template<typename TCollection>
|
||||||
|
|
|
@ -0,0 +1,45 @@
|
||||||
|
#include "progress.h"
|
||||||
|
|
||||||
|
#include <mutex>
|
||||||
|
|
||||||
|
using std::string;
|
||||||
|
|
||||||
|
ProgressForwarder::ProgressForwarder(std::function<void(double progress)> callback) :
|
||||||
|
callback(callback)
|
||||||
|
{}
|
||||||
|
|
||||||
|
void ProgressForwarder::reportProgress(double value) {
|
||||||
|
callback(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
ProgressMerger::ProgressMerger(ProgressSink& sink) :
|
||||||
|
sink(sink)
|
||||||
|
{}
|
||||||
|
|
||||||
|
ProgressSink& ProgressMerger::addSink(double weight) {
|
||||||
|
std::lock_guard<std::mutex> lock(mutex);
|
||||||
|
|
||||||
|
totalWeight += weight;
|
||||||
|
int sinkIndex = weightedValues.size();
|
||||||
|
weightedValues.push_back(0);
|
||||||
|
forwarders.push_back(ProgressForwarder([weight, sinkIndex, this](double progress) {
|
||||||
|
weightedValues[sinkIndex] = progress * weight;
|
||||||
|
report();
|
||||||
|
}));
|
||||||
|
return forwarders.back();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ProgressMerger::report() {
|
||||||
|
std::lock_guard<std::mutex> lock(mutex);
|
||||||
|
|
||||||
|
if (totalWeight != 0) {
|
||||||
|
double weightedSum = 0;
|
||||||
|
for (double weightedValue : weightedValues) {
|
||||||
|
weightedSum += weightedValue;
|
||||||
|
}
|
||||||
|
double progress = weightedSum / totalWeight;
|
||||||
|
sink.reportProgress(progress);
|
||||||
|
} else {
|
||||||
|
sink.reportProgress(0);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,39 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <list>
|
||||||
|
#include <functional>
|
||||||
|
#include <mutex>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
class ProgressSink {
|
||||||
|
public:
|
||||||
|
virtual ~ProgressSink() {}
|
||||||
|
virtual void reportProgress(double value) = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
class NullProgressSink : public ProgressSink {
|
||||||
|
public:
|
||||||
|
void reportProgress(double) override {}
|
||||||
|
};
|
||||||
|
|
||||||
|
class ProgressForwarder : public ProgressSink {
|
||||||
|
public:
|
||||||
|
ProgressForwarder(std::function<void(double progress)> callback);
|
||||||
|
void reportProgress(double value) override;
|
||||||
|
private:
|
||||||
|
std::function<void(double progress)> callback;
|
||||||
|
};
|
||||||
|
|
||||||
|
class ProgressMerger {
|
||||||
|
public:
|
||||||
|
ProgressMerger(ProgressSink& sink);
|
||||||
|
ProgressSink& addSink(double weight);
|
||||||
|
private:
|
||||||
|
void report();
|
||||||
|
|
||||||
|
ProgressSink& sink;
|
||||||
|
std::mutex mutex;
|
||||||
|
double totalWeight = 0;
|
||||||
|
std::list<ProgressForwarder> forwarders;
|
||||||
|
std::vector<double> weightedValues;
|
||||||
|
};
|
Loading…
Reference in New Issue