#include #include #include #include #include "audio_input/WaveFileReader.h" #include "phone_extraction.h" #include "mouth_animation.h" #include "platform_tools.h" using std::exception; using std::string; using std::unique_ptr; using std::map; using std::chrono::duration; using std::chrono::duration_cast; using boost::filesystem::path; using boost::property_tree::ptree; string getMessage(const exception& e) { string result(e.what()); try { std::rethrow_if_nested(e); } catch(const exception& innerException) { result += "\n" + getMessage(innerException); } catch(...) {} return result; } unique_ptr createAudioStream(path filePath) { try { return unique_ptr(new WaveFileReader(filePath)); } catch (...) { std::throw_with_nested(std::runtime_error("Could not open sound file.") ); } } string formatDuration(duration seconds) { return fmt::format("{0:.2f}", seconds.count()); } ptree createXmlTree(const path& filePath, const map& phones, const map& shapes) { ptree tree; // Add sound file path tree.add("rhubarbResult.info.soundFile", filePath.string()); // Add phones for (auto it = phones.cbegin(), itNext = ++phones.cbegin(); itNext != phones.cend(); ++it, ++itNext) { auto pair = *it; auto nextPair = *itNext; ptree& phoneElement = tree.add("rhubarbResult.phones.phone", pair.second); phoneElement.add(".start", formatDuration(pair.first)); phoneElement.add(".duration", formatDuration(nextPair.first - pair.first)); } // Add mouth cues for (auto it = shapes.cbegin(), itNext = ++shapes.cbegin(); itNext != shapes.cend(); ++it, ++itNext) { auto pair = *it; auto nextPair = *itNext; ptree& mouthCueElement = tree.add("rhubarbResult.mouthCues.mouthCue", pair.second); mouthCueElement.add(".start", formatDuration(pair.first)); mouthCueElement.add(".duration", formatDuration(nextPair.first - pair.first)); } return tree; } int main(int argc, char *argv[]) { try { // Get sound file name if (argc != 2) { throw std::runtime_error("Invalid command line arguments. Call with sound file name as sole argument."); } string soundFileName = argv[1]; // Create audio streams unique_ptr audioStream = createAudioStream(soundFileName); // Detect phones map phones = detectPhones(std::move(audioStream)); // Generate mouth shapes map shapes = animate(phones); // Print XML boost::property_tree::ptree xmlTree = createXmlTree(soundFileName, phones, shapes); boost::property_tree::write_xml(std::cout, xmlTree, boost::property_tree::xml_writer_settings(' ', 2)); return 0; } catch (const exception& e) { std::cerr << "An error occurred. " << getMessage(e); return 1; } }