Improved animation rules

This commit is contained in:
Daniel Wolf 2016-11-18 20:39:39 +01:00
parent a913fa113b
commit 82a76c9971
2 changed files with 36 additions and 25 deletions

View File

@ -17,12 +17,12 @@ constexpr Shape X = Shape::X;
Timeline<ShapeSet> animatePhone(optional<Phone> phone, centiseconds duration, centiseconds previousDuration) { Timeline<ShapeSet> animatePhone(optional<Phone> phone, centiseconds duration, centiseconds previousDuration) {
// Returns a timeline with a single shape set // Returns a timeline with a single shape set
auto single = [&](ShapeSet value) { auto single = [duration](ShapeSet value) {
return Timeline<ShapeSet> { { 0_cs, duration, value } }; return Timeline<ShapeSet> { { 0_cs, duration, value } };
}; };
// Returns a timeline with two shape sets, timed as a diphthong // Returns a timeline with two shape sets, timed as a diphthong
auto diphthong = [&](ShapeSet first, ShapeSet second) { auto diphthong = [duration](ShapeSet first, ShapeSet second) {
centiseconds firstDuration = duration_cast<centiseconds>(duration * 0.6); centiseconds firstDuration = duration_cast<centiseconds>(duration * 0.6);
return Timeline<ShapeSet> { return Timeline<ShapeSet> {
{ 0_cs, firstDuration, first }, { 0_cs, firstDuration, first },
@ -31,17 +31,27 @@ Timeline<ShapeSet> animatePhone(optional<Phone> phone, centiseconds duration, ce
}; };
// Returns a timeline with two shape sets, timed as a plosive // Returns a timeline with two shape sets, timed as a plosive
auto plosive = [&](ShapeSet first, ShapeSet second) { auto plosive = [duration, previousDuration](ShapeSet first, ShapeSet second) {
centiseconds minOcclusionDuration = 4_cs;
centiseconds maxOcclusionDuration = 12_cs; centiseconds maxOcclusionDuration = 12_cs;
centiseconds leftOverlap = clamp(previousDuration / 2, 4_cs, maxOcclusionDuration); centiseconds occlusionDuration = clamp(previousDuration / 2, minOcclusionDuration, maxOcclusionDuration);
centiseconds rightOverlap = min(duration, maxOcclusionDuration - leftOverlap);
return Timeline<ShapeSet> { return Timeline<ShapeSet> {
{ -leftOverlap, rightOverlap, first }, { -occlusionDuration, 0_cs, first },
{ rightOverlap, duration, second } { 0_cs, duration, second }
}; };
}; };
if (!phone) return single({ X }); // Returns the result of `animatePhone` when called with identical arguments
// except for a different phone.
auto like = [duration, previousDuration](optional<Phone> referencePhone) {
return animatePhone(referencePhone, duration, previousDuration);
};
static const ShapeSet any = { A, B, C, D, E, F, G, H, X };
if (!phone) {
return single({ X });
}
switch (*phone) { switch (*phone) {
case Phone::AO: return single({ E }); case Phone::AO: return single({ E });
@ -50,23 +60,23 @@ Timeline<ShapeSet> animatePhone(optional<Phone> phone, centiseconds duration, ce
case Phone::UW: return single({ F }); case Phone::UW: return single({ F });
case Phone::EH: return duration < 20_cs ? single({ C }) : single({ D }); case Phone::EH: return duration < 20_cs ? single({ C }) : single({ D });
case Phone::IH: return single({ B }); case Phone::IH: return single({ B });
case Phone::UH: return single({ E }); case Phone::UH: return single({ F });
case Phone::AH: return single({ C }); case Phone::AH: return single({ C });
case Phone::Schwa: return single({ { B, C, D, E, F } }); case Phone::Schwa: return single({ { B, C, D, E, F } });
case Phone::AE: return single({ D }); case Phone::AE: return single({ C });
case Phone::EY: return duration < 20_cs ? diphthong({ C }, { B }) : diphthong({ D }, { B }); case Phone::EY: return diphthong({ C }, { B });
case Phone::AY: return diphthong({ D }, { B }); case Phone::AY: return duration < 20_cs ? diphthong({ C }, { B }) : diphthong({ D }, { B });
case Phone::OW: return diphthong({ E }, { F }); case Phone::OW: return single({ F });
case Phone::AW: return diphthong({ D }, { F }); case Phone::AW: return duration < 20_cs ? diphthong({ C }, { F }) : diphthong({ D }, { F });
case Phone::OY: return diphthong({ F }, { B }); case Phone::OY: return diphthong({ F }, { B });
case Phone::ER: return duration < 7_cs ? single({ B }) : single({ E }); case Phone::ER: return duration < 7_cs ? like(Phone::Schwa) : single({ F });
case Phone::P: case Phone::P:
case Phone::B: return plosive({ A }, { A, B, C, D, E, F, G, H, X }); case Phone::B: return plosive({ A }, any);
case Phone::T: case Phone::T:
case Phone::D: case Phone::D: return plosive({ B, C, F, G, H }, any);
case Phone::K: return single({ B, F }); case Phone::K:
case Phone::G: return single({ B, C, E, F }); case Phone::G: return plosive({ B, C, E, F, G, H }, any);
case Phone::CH: case Phone::CH:
case Phone::JH: return single({ B, F }); case Phone::JH: return single({ B, F });
case Phone::F: case Phone::F:
@ -77,13 +87,13 @@ Timeline<ShapeSet> animatePhone(optional<Phone> phone, centiseconds duration, ce
case Phone::Z: case Phone::Z:
case Phone::SH: case Phone::SH:
case Phone::ZH: return single({ B, F }); case Phone::ZH: return single({ B, F });
case Phone::HH: return single({ B, C, D, E, F }); case Phone::HH: return single(any);
case Phone::M: return single({ A }); case Phone::M: return single({ A });
case Phone::N: return single({ B, C, F }); case Phone::N: return single({ B, C, F, G, H });
case Phone::NG: return single({ B, C, D, E, F }); case Phone::NG: return single({ B, C, E, F, G });
case Phone::L: return single({ E, F, H }); case Phone::L: return duration < 20_cs ? single({ B, C, D, E, F, G, H }) : single({ H });
case Phone::R: return single({ B, F }); case Phone::R: return single({ B, C, E, F });
case Phone::Y: return single({ B }); case Phone::Y: return single({ B, C, F });
case Phone::W: return single({ F }); case Phone::W: return single({ F });
case Phone::Breath: case Phone::Breath:

View File

@ -6,6 +6,7 @@
#include "Timeline.h" #include "Timeline.h"
#include "Phone.h" #include "Phone.h"
// A set of mouth shapes that can be used to represent a certain sound
using ShapeSet = std::set<Shape>; using ShapeSet = std::set<Shape>;
Timeline<ShapeSet> animatePhone(boost::optional<Phone> phone, centiseconds duration, centiseconds previousDuration); Timeline<ShapeSet> animatePhone(boost::optional<Phone> phone, centiseconds duration, centiseconds previousDuration);