Using two-element shape rules instead of shape sets
This commit is contained in:
parent
82a76c9971
commit
4e9a588c66
|
@ -15,27 +15,32 @@ constexpr Shape G = Shape::G;
|
||||||
constexpr Shape H = Shape::H;
|
constexpr Shape H = Shape::H;
|
||||||
constexpr Shape X = Shape::X;
|
constexpr Shape X = Shape::X;
|
||||||
|
|
||||||
Timeline<ShapeSet> animatePhone(optional<Phone> phone, centiseconds duration, centiseconds previousDuration) {
|
ShapeRule::ShapeRule(const ShapeSet& regularShapes, const ShapeSet& alternativeShapes) :
|
||||||
|
regularShapes(regularShapes),
|
||||||
|
alternativeShapes(alternativeShapes)
|
||||||
|
{}
|
||||||
|
|
||||||
|
Timeline<ShapeRule> 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 = [duration](ShapeSet value) {
|
auto single = [duration](ShapeRule value) {
|
||||||
return Timeline<ShapeSet> { { 0_cs, duration, value } };
|
return Timeline<ShapeRule> {{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 = [duration](ShapeSet first, ShapeSet second) {
|
auto diphthong = [duration](ShapeRule first, ShapeRule second) {
|
||||||
centiseconds firstDuration = duration_cast<centiseconds>(duration * 0.6);
|
centiseconds firstDuration = duration_cast<centiseconds>(duration * 0.6);
|
||||||
return Timeline<ShapeSet> {
|
return Timeline<ShapeRule> {
|
||||||
{0_cs, firstDuration, first},
|
{0_cs, firstDuration, first},
|
||||||
{firstDuration, duration, second}
|
{firstDuration, duration, second}
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
// Returns a timeline with two shape sets, timed as a plosive
|
// Returns a timeline with two shape sets, timed as a plosive
|
||||||
auto plosive = [duration, previousDuration](ShapeSet first, ShapeSet second) {
|
auto plosive = [duration, previousDuration](ShapeRule first, ShapeRule second) {
|
||||||
centiseconds minOcclusionDuration = 4_cs;
|
centiseconds minOcclusionDuration = 4_cs;
|
||||||
centiseconds maxOcclusionDuration = 12_cs;
|
centiseconds maxOcclusionDuration = 12_cs;
|
||||||
centiseconds occlusionDuration = clamp(previousDuration / 2, minOcclusionDuration, maxOcclusionDuration);
|
centiseconds occlusionDuration = clamp(previousDuration / 2, minOcclusionDuration, maxOcclusionDuration);
|
||||||
return Timeline<ShapeSet> {
|
return Timeline<ShapeRule> {
|
||||||
{-occlusionDuration, 0_cs, first},
|
{-occlusionDuration, 0_cs, first},
|
||||||
{0_cs, duration, second}
|
{0_cs, duration, second}
|
||||||
};
|
};
|
||||||
|
@ -47,59 +52,59 @@ Timeline<ShapeSet> animatePhone(optional<Phone> phone, centiseconds duration, ce
|
||||||
return animatePhone(referencePhone, duration, previousDuration);
|
return animatePhone(referencePhone, duration, previousDuration);
|
||||||
};
|
};
|
||||||
|
|
||||||
static const ShapeSet any = { A, B, C, D, E, F, G, H, X };
|
static const ShapeRule any{{A, B, C, D, E, F, G, H, X}};
|
||||||
|
|
||||||
if (!phone) {
|
if (!phone) {
|
||||||
return single({ X });
|
return single({{X}});
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (*phone) {
|
switch (*phone) {
|
||||||
case Phone::AO: return single({ E });
|
case Phone::AO: return single({{E}});
|
||||||
case Phone::AA: return single({ D });
|
case Phone::AA: return single({{D}});
|
||||||
case Phone::IY: return single({ B });
|
case Phone::IY: return single({{B}, {C}});
|
||||||
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}, {C}});
|
||||||
case Phone::UH: return single({ F });
|
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({ C });
|
case Phone::AE: return single({{C}});
|
||||||
case Phone::EY: return diphthong({ C }, { B });
|
case Phone::EY: return diphthong({{C}}, {{B}, {C}});
|
||||||
case Phone::AY: return duration < 20_cs ? diphthong({ C }, { B }) : diphthong({ D }, { B });
|
case Phone::AY: return duration < 20_cs ? diphthong({{C}}, {{B}, {C}}) : diphthong({{D}}, {{B}, {C}});
|
||||||
case Phone::OW: return single({ F });
|
case Phone::OW: return single({{F}});
|
||||||
case Phone::AW: return duration < 20_cs ? diphthong({ C }, { F }) : 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}, {C}});
|
||||||
case Phone::ER: return duration < 7_cs ? like(Phone::Schwa) : single({ F });
|
case Phone::ER: return duration < 7_cs ? like(Phone::Schwa) : single({{F}});
|
||||||
|
|
||||||
case Phone::P:
|
case Phone::P:
|
||||||
case Phone::B: return plosive({ A }, any);
|
case Phone::B: return plosive({{A}}, any);
|
||||||
case Phone::T:
|
case Phone::T:
|
||||||
case Phone::D: return plosive({ B, C, F, G, H }, any);
|
case Phone::D: return plosive({{B, C, F, G, H}}, any);
|
||||||
case Phone::K:
|
case Phone::K:
|
||||||
case Phone::G: return plosive({ B, C, E, F, G, H }, any);
|
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:
|
||||||
case Phone::V: return single({ G });
|
case Phone::V: return single({{G}});
|
||||||
case Phone::TH:
|
case Phone::TH:
|
||||||
case Phone::DH:
|
case Phone::DH:
|
||||||
case Phone::S:
|
case Phone::S:
|
||||||
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(any);
|
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, G, H });
|
case Phone::N: return single({{B, C, F, G, H}});
|
||||||
case Phone::NG: return single({ B, C, E, F, G });
|
case Phone::NG: return single({{B, C, E, F, G}});
|
||||||
case Phone::L: return duration < 20_cs ? single({ B, C, D, E, F, G, H }) : single({ H });
|
case Phone::L: return duration < 20_cs ? single({{B, C, D, E, F, G, H}}) : single({{H}});
|
||||||
case Phone::R: return single({ B, C, E, F });
|
case Phone::R: return single({{B, C, E, F}});
|
||||||
case Phone::Y: return single({ B, C, F });
|
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:
|
||||||
case Phone::Cough:
|
case Phone::Cough:
|
||||||
case Phone::Smack: return single({ C });
|
case Phone::Smack: return single({{C}});
|
||||||
case Phone::Noise: return single({ B });
|
case Phone::Noise: return single({{B}});
|
||||||
|
|
||||||
default: throw std::invalid_argument("Unexpected phone.");
|
default: throw std::invalid_argument("Unexpected phone.");
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,4 +9,11 @@
|
||||||
// A set of mouth shapes that can be used to represent a certain sound
|
// 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);
|
struct ShapeRule {
|
||||||
|
ShapeRule(const ShapeSet& regularShapes, const ShapeSet& alternativeShapes = {});
|
||||||
|
|
||||||
|
ShapeSet regularShapes;
|
||||||
|
ShapeSet alternativeShapes;
|
||||||
|
};
|
||||||
|
|
||||||
|
Timeline<ShapeRule> animatePhone(boost::optional<Phone> phone, centiseconds duration, centiseconds previousDuration);
|
||||||
|
|
Loading…
Reference in New Issue