Files
gtav-src/tools_ng/bin/audio/FaceFx 2012/Scripts/Massaro-Cohen-Coarticulation.py
T
2025-09-29 00:52:08 +02:00

736 lines
39 KiB
Python
Executable File

#-------------------------------------------------------------------------------
# Create a partial analysis actor based on the Massaro-Cohen model of
# coarticulation. Massaro-Cohen uses a dominance function to represent the
# dominance of a given phoneme over a particular speech parameter. These
# dominance functions, in conjunction with the target value for a given phoneme
# over a particular speech parameter, provide a smooth curve for the given
# speech parameter.
#
# Owner: John Briggs
#
# Copyright (c) 2002-2011 OC3 Entertainment, Inc.
#-------------------------------------------------------------------------------
from FxStudio import *
from FxGestureShared import *
import copy
import math
# A modified version of the Anim class in FxGestureShared
class MCAnim(Anim):
def buildAnim(self):
count = 0
for curve in self.curves:
issueCommand('curve -group "%s" -anim "%s" -add -name "%s" -owner "user";'%(self.group, self.name, curve.name))
issueCommand('select -type "animgroup" -names "%s";'%(self.group))
issueCommand('select -type "anim" -names "%s";'%(self.name))
issueCommand('select -type "curve" -names "%s";'%(curve.name))
issueCommand('batch')
for key in curve.keys:
issueCommand('key -insert -curveIndex "%d" -index -time "%s" -value "%s" -slopeIn "%s" -slopeOut "%s";'%(count, key.time, key.value, key.slopein, key.slopeout));
count += 1
issueCommand('execBatch -changedanim')
for event in self.events:
if self.groupChildEvents == "false":
issueCommand('event -group "%s" -anim "%s" -add -eventgroup "%s" -eventanim "%s" -persist "%s" -inheritmag "%s" -inheritdur "%s" -probability "%f" -minstart "%f" -maxstart "%f" -minduration "%f" -maxduration "%f" -minmagnitude "%f" -maxmagnitude "%f" -minblendin "%f" -maxblendin "%f" -minblendout "%f" -maxblendout "%f";'%(self.group, self.name, event.group, event.name, event.persist, event.inheritmag, event.inheritdur, event.probability, event.minstart, event.maxstart, event.minduration, event.maxduration, event.minmagnitude, event.maxmagnitude, event.minblendin, event.maxblendin, event.minblendout, event.maxblendout))
if self.groupChildEvents != "false":
issueCommand('event -group "%s" -anim "%s" -add -eventgroup "%s" -eventanim "%s" -persist "%s" -inheritmag "%s" -inheritdur "%s" -weight "%f" -probability "%f" -minstart "%f" -maxstart "%f" -minduration "%f" -maxduration "%f" -minmagnitude "%f" -maxmagnitude "%f" -minblendin "%f" -maxblendin "%f" -minblendout "%f" -maxblendout "%f";'%(self.group, self.name, event.group, event.name, event.persist, event.inheritmag, event.inheritdur, event.weight, event.probability, event.minstart, event.maxstart, event.minduration, event.maxduration, event.minmagnitude, event.maxmagnitude, event.minblendin, event.maxblendin, event.minblendout, event.maxblendout))
class MCEvent(Event):
def __init__(self, animName, animGroup, durationScale = 1, magnitudeScale = 1):
Event.__init__(self, animName, animGroup, durationScale, magnitudeScale)
self.inheritdur = "false"
#-----------------------------------------------------------------------------
# Massaro-Cohen specific structures
#-----------------------------------------------------------------------------
class MCData:
def __init__(self, magnitude, rate, rate_str, target, offset = None):
self.magnitude = magnitude
self.rate_in = rate
self.rate_out = rate
self.duration_scale = 1.0
self.target = target
if offset is None:
offset = 0.5
self.offset = offset
try:
self.duration_scale = {
'jaw_vclo' : 0.35,
'jaw_clos' : 0.47,
'jaw_medi' : 0.60,
'jaw_dist' : 0.75,
'jaw_vdis' : 0.90,
'lip_vclo' : 0.30,
'lip_clos' : 0.45,
'lip_medi' : 0.65,
'lip_dist' : 0.80,
'lip_vdis' : 1.00,
'tng_vclo' : 0.25,
'tng_clos' : 0.35,
'tng_medi' : 0.50,
'tng_dist' : 0.75,
'tng_vdis' : 0.80
}[rate_str]
except KeyError:
self.duration_scale = 1.0
def __str__(self):
return '[mag: %f rate_in: %f rate_out %f target %f]' % (self.magnitude, self.rate_in, self.rate_out, self.target)
def __repr__(self):
return '%s[mag: %f rate_in: %f rate_out %f target %f]' % (self.__class__.__name__,
self.magnitude, self.rate_in, self.rate_out, self.target)
def calc_dominance_value(self, time):
if time < 0:
rate = self.rate_in
elif time >= 0:
rate = self.rate_out
return self.magnitude * math.pow(math.e, -rate * math.fabs(time))
def calc_scaled_dominance_value(self, time):
return self.calc_dominance_value(time) * self.target
def calc_slope_in(self, time):
if time <= 0:
rate = self.rate_in
flip = -1
elif time > 0:
rate = self.rate_out
flip = 1
return flip * -self.magnitude * rate * math.pow(math.e, -rate * math.fabs(time))
def calc_slope_out(self, time):
if time < 0:
rate = self.rate_in
flip = -1
elif time >= 0:
rate = self.rate_out
flip = 1
return flip * -self.magnitude * rate * math.pow(math.e, -rate * math.fabs(time))
#-----------------------------------------------------------------------------
# Utility functions
#-----------------------------------------------------------------------------
# frange, from the Python Cookbook
def frange(start, end=None, inc=1.0):
"A range-like function that accepts float increments..."
if end == None:
end = start + 0.0 # Ensure a float value for 'end'
start = 0.0
assert inc # sanity check
L = []
while 1:
next = start + len(L) * inc
if inc > 0 and next >= end:
break
elif inc < 0 and next <= end:
break
L.append(next)
return L
#------------------------------------------------------------------------------
# Constants
#------------------------------------------------------------------------------
# Dominance array.
# least dominant <--------------------> most dominant
d = (0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1)
# Rate array.
# fastest <-------------------------------> slowest
r = [50, 60, 70, 80, 90, 100, 110, 120, 130, 140, 150]
global_mod = 0.30
jaw_vclo = 140 * global_mod
jaw_clos = 120 * global_mod
jaw_medi = 110 * global_mod
jaw_dist = 95 * global_mod
jaw_vdis = 85 * global_mod
lip_vclo = 125 * global_mod
lip_clos = 110 * global_mod
lip_medi = 95 * global_mod
lip_dist = 80 * global_mod
lip_vdis = 65 * global_mod
tng_vclo = 110 * global_mod
tng_clos = 100 * global_mod
tng_medi = 80 * global_mod
tng_dist = 65 * global_mod
tng_vdis = 50 * global_mod
# Target array.
# min <-----------------------------------------> max
t = (0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1)
# Target names
jaw_open = '_jaw_open'
lip_round_compression = '_lip_round_compression'
lip_round_protrusion = '_lip_round_protrusion'
lip_press_together = '_lip_press_together'
lower_lip_f_tuck = '_lower_lip_f_tuck'
lip_stretch = '_lip_stretch'
tongue_to_back = '_tongue_to_back'
tongue_to_roof = '_tongue_to_roof'
tongue_to_teeth = '_tongue_to_teeth'
# Modifiers
scaled = '_scaled'
sum = '_sum'
spawned = '_spawned'
targetList = (jaw_open, lip_round_compression, lip_round_protrusion, lip_press_together, lower_lip_f_tuck, lip_stretch, tongue_to_back, tongue_to_roof, tongue_to_teeth)
finalTargetList = (('open', jaw_open + sum),
('W', lip_round_compression + sum),
('ShCh', lip_round_protrusion + sum),
('PBM', lip_press_together + sum),
('FV', lower_lip_f_tuck + sum),
('wide', lip_stretch + sum),
('tBack', tongue_to_back + sum),
('tRoof', tongue_to_roof + sum),
('tTeeth', tongue_to_teeth + sum))
nodesToCreate = ( (jaw_open, jaw_open + scaled, jaw_open + sum),
(lip_round_compression, lip_round_compression + scaled, lip_round_compression + sum),
(lip_round_protrusion, lip_round_protrusion + scaled, lip_round_protrusion + sum),
(lip_press_together, lip_press_together + scaled, lip_press_together + sum),
(lower_lip_f_tuck, lower_lip_f_tuck + scaled, lower_lip_f_tuck + sum),
(lip_stretch, lip_stretch + scaled, lip_stretch + sum),
(tongue_to_back, tongue_to_back + scaled, tongue_to_back + sum),
(tongue_to_roof, tongue_to_roof + scaled, tongue_to_roof + sum),
(tongue_to_teeth, tongue_to_teeth + scaled, tongue_to_teeth + sum) )
# Anim group names
phonemeEventGroup = '_PhonemeEventGroup'
spawnedPhonemeEventGroup = '_DominanceFunctions'
# Data blocks should be grouped by phoneme.
PhonemeDict = dict()
# We'll create an animation for each phoneme which contains the dominance
# curves for each target.
# SIL - silence.
SIL_Data = dict()
SIL_Data[jaw_open] = MCData(d[10], jaw_vdis, 'jaw_vdis', t[0])
SIL_Data[lip_round_compression] = MCData(d[10], lip_vdis, 'lip_vdis', t[0])
SIL_Data[lip_round_protrusion] = MCData(d[10], lip_vdis, 'lip_vdis', t[0])
SIL_Data[lip_press_together] = MCData(d[10], lip_vdis, 'lip_vdis', t[0])
SIL_Data[lower_lip_f_tuck] = MCData(d[10], lip_vdis, 'lip_vdis', t[0])
SIL_Data[lip_stretch] = MCData(d[10], lip_vdis, 'lip_vdis', t[0])
SIL_Data[tongue_to_back] = MCData(d[9], tng_vdis, 'tng_vdis', t[0])
SIL_Data[tongue_to_roof] = MCData(d[9], tng_vdis, 'tng_vdis', t[0])
SIL_Data[tongue_to_teeth] = MCData(d[9], tng_vdis, 'tng_vdis', t[0])
PhonemeDict['SIL'] = SIL_Data
# P - bilabial voiceless plosive /p/rint, s/p/in
P_Data = dict()
P_Data[jaw_open] = MCData(d[10], jaw_medi, 'jaw_medi', t[0], 0.1)
P_Data[lip_round_compression] = MCData(d[3], lip_clos, 'lip_clos', t[0])
P_Data[lip_round_protrusion] = MCData(d[3], lip_clos, 'lip_clos', t[0])
P_Data[lip_press_together] = MCData(d[8], lip_medi, 'lip_medi', t[8], 0.1)
P_Data[lower_lip_f_tuck] = MCData(d[3], lip_clos, 'lip_clos', t[0])
P_Data[lip_stretch] = MCData(d[5], lip_clos, 'lip_clos', t[0])
P_Data[tongue_to_back] = MCData(d[3], tng_vclo, 'tng_vclo', t[0])
P_Data[tongue_to_roof] = MCData(d[3], tng_vclo, 'tng_vclo', t[0])
P_Data[tongue_to_teeth] = MCData(d[3], tng_vclo, 'tng_vclo', t[0])
PhonemeDict['P'] = P_Data
# B - bilabial voiced plosive /b/oot, a/b/out
PhonemeDict['B'] = PhonemeDict['P']
# T - alveolar voiceless plosive /t/ry, /t/oday
T_Data = dict()
T_Data[jaw_open] = MCData(d[4], jaw_medi, 'jaw_medi', t[4])
T_Data[lip_round_compression] = MCData(d[1], lip_medi, 'lip_medi', t[0])
T_Data[lip_round_protrusion] = MCData(d[1], lip_medi, 'lip_medi', t[0])
T_Data[lip_press_together] = MCData(d[8], lip_medi, 'lip_medi', t[0])
T_Data[lower_lip_f_tuck] = MCData(d[8], lip_medi, 'lip_medi', t[0])
T_Data[lip_stretch] = MCData(d[1], lip_medi, 'lip_medi', t[0])
T_Data[tongue_to_back] = MCData(d[5], tng_medi, 'tng_medi', t[0])
T_Data[tongue_to_roof] = MCData(d[10], tng_dist, 'tng_dist', t[8], 0.1)
T_Data[tongue_to_teeth] = MCData(d[5], tng_medi, 'tng_medi', t[0])
PhonemeDict['T'] = T_Data
# D - alveolar voiced plosive /d/og, bombe/d/
PhonemeDict['D'] = PhonemeDict['T']
# K - velar voiced plosive /c/at, s/k/in
K_Data = dict()
K_Data[jaw_open] = MCData(d[3], jaw_medi, 'jaw_medi', t[3])
K_Data[lip_round_compression] = MCData(d[1], lip_clos, 'lip_clos', t[0])
K_Data[lip_round_protrusion] = MCData(d[1], lip_clos, 'lip_clos', t[0])
K_Data[lip_press_together] = MCData(d[7], lip_clos, 'lip_clos', t[0])
K_Data[lower_lip_f_tuck] = MCData(d[8], lip_clos, 'lip_clos', t[0])
K_Data[lip_stretch] = MCData(d[1], lip_clos, 'lip_clos', t[0])
K_Data[tongue_to_back] = MCData(d[9], tng_medi, 'tng_medi', t[8], 0.1)
K_Data[tongue_to_roof] = MCData(d[6], tng_vclo, 'tng_vclo', t[0])
K_Data[tongue_to_teeth] = MCData(d[6], tng_vclo, 'tng_vclo', t[0])
PhonemeDict['K'] = K_Data
# G - velar voiceless plosive /g/um, ba/g/
PhonemeDict['G'] = PhonemeDict['K']
# M - bilabial nasal /m/ore, botto/m/
PhonemeDict['M'] = PhonemeDict['B']
# N - alveolar nasal /n/i/n/e, pla/n/
N_Data = dict()
N_Data[jaw_open] = MCData(d[5], jaw_clos, 'jaw_clos', t[4])
N_Data[lip_round_compression] = MCData(d[1], lip_clos, 'lip_clos', t[0])
N_Data[lip_round_protrusion] = MCData(d[1], lip_clos, 'lip_clos', t[0])
N_Data[lip_press_together] = MCData(d[5], lip_clos, 'lip_clos', t[0])
N_Data[lower_lip_f_tuck] = MCData(d[5], lip_clos, 'lip_clos', t[0])
N_Data[lip_stretch] = MCData(d[1], lip_clos, 'lip_clos', t[0])
N_Data[tongue_to_back] = MCData(d[7], tng_medi, 'tng_medi', t[0])
N_Data[tongue_to_roof] = MCData(d[8], tng_medi, 'tng_medi', t[8], 0.2)
N_Data[tongue_to_teeth] = MCData(d[2], tng_medi, 'tng_medi', t[0])
PhonemeDict['N'] = N_Data
# NG - velar nasal si/ng/, ba/n/k
PhonemeDict['NG'] = PhonemeDict['N']
# RA - alveolar trill es: pe/rr/o
RA_Data = dict()
RA_Data[jaw_open] = MCData(d[7], jaw_medi, 'jaw_medi', t[4])
RA_Data[lip_round_compression] = MCData(d[2], lip_clos, 'lip_clos', t[0])
RA_Data[lip_round_protrusion] = MCData(d[2], lip_clos, 'lip_clos', t[0])
RA_Data[lip_press_together] = MCData(d[7], lip_clos, 'lip_clos', t[0])
RA_Data[lower_lip_f_tuck] = MCData(d[5], lip_clos, 'lip_clos', t[0])
RA_Data[lip_stretch] = MCData(d[2], lip_clos, 'lip_clos', t[0])
RA_Data[tongue_to_back] = MCData(d[7], tng_medi, 'tng_medi', t[0])
RA_Data[tongue_to_roof] = MCData(d[8], tng_medi, 'tng_medi', t[5])
RA_Data[tongue_to_teeth] = MCData(d[6], tng_medi, 'tng_medi', t[0])
PhonemeDict['RA'] = RA_Data
# RU - uvular trill fr: /r/ue, de: /R/echt
RU_Data = dict()
RU_Data[jaw_open] = MCData(d[3], jaw_clos, 'jaw_clos', t[2])
RU_Data[lip_round_compression] = MCData(d[4], lip_clos, 'lip_clos', t[0])
RU_Data[lip_round_protrusion] = MCData(d[2], lip_clos, 'lip_clos', t[0])
RU_Data[lip_press_together] = MCData(d[3], lip_clos, 'lip_clos', t[0])
RU_Data[lower_lip_f_tuck] = MCData(d[5], lip_clos, 'lip_clos', t[0])
RU_Data[lip_stretch] = MCData(d[2], lip_clos, 'lip_clos', t[0])
RU_Data[tongue_to_back] = MCData(d[7], tng_medi, 'tng_medi', t[8])
RU_Data[tongue_to_roof] = MCData(d[5], tng_medi, 'tng_medi', t[0])
RU_Data[tongue_to_teeth] = MCData(d[7], tng_medi, 'tng_medi', t[0])
PhonemeDict['RU'] = RU_Data
# FLAP - alveolar flap wa/t/er
PhonemeDict['FLAP'] = PhonemeDict['T']
# PH - bilabial voiceless fric. japanese & korean
PH_Data = dict()
PH_Data[jaw_open] = MCData(d[10], jaw_medi, 'jaw_medi', t[0], 0.1)
PH_Data[lip_round_compression] = MCData(d[5], lip_clos, 'lip_clos', t[0])
PH_Data[lip_round_protrusion] = MCData(d[8], lip_clos, 'lip_clos', t[0])
PH_Data[lip_press_together] = MCData(d[7], lip_clos, 'lip_clos', t[0])
PH_Data[lower_lip_f_tuck] = MCData(d[8], lip_medi, 'lip_medi', t[7], 0.1)
PH_Data[lip_stretch] = MCData(d[4], lip_clos, 'lip_clos', t[0])
PH_Data[tongue_to_back] = MCData(d[2], tng_medi, 'tng_medi', t[0])
PH_Data[tongue_to_roof] = MCData(d[2], tng_medi, 'tng_medi', t[0])
PH_Data[tongue_to_teeth] = MCData(d[2], tng_medi, 'tng_medi', t[0])
PhonemeDict['PH'] = PH_Data
# F - labiodental voiceless fric. /f/arm, ta/ff/y
PhonemeDict['F'] = PhonemeDict['PH']
# V - labiodental voiced fric. /v/isit, ra/v/e
PhonemeDict['V'] = PhonemeDict['F']
# TH - dental voiceless fric. /th/ing, ba/th/
TH_Data = dict()
TH_Data[jaw_open] = MCData(d[6], jaw_medi, 'jaw_medi', t[5])
TH_Data[lip_round_compression] = MCData(d[3], lip_clos, 'lip_clos', t[0])
TH_Data[lip_round_protrusion] = MCData(d[2], lip_clos, 'lip_clos', t[0])
TH_Data[lip_press_together] = MCData(d[7], lip_clos, 'lip_clos', t[0])
TH_Data[lower_lip_f_tuck] = MCData(d[6], lip_clos, 'lip_clos', t[0])
TH_Data[lip_stretch] = MCData(d[2], lip_clos, 'lip_clos', t[0])
TH_Data[tongue_to_back] = MCData(d[8], tng_medi, 'tng_medi', t[0])
TH_Data[tongue_to_roof] = MCData(d[8], tng_medi, 'tng_medi', t[0])
TH_Data[tongue_to_teeth] = MCData(d[8], tng_vdis, 'tng_vdis', t[9], 0.1)
PhonemeDict['TH'] = TH_Data
# DH - dental voiced fric. /th/is, /th/e
PhonemeDict['DH'] = PhonemeDict['TH']
# S - alveolar voiceless fric. /s/it, pa/ss/
S_Data = dict()
S_Data[jaw_open] = MCData(d[7], jaw_medi, 'jaw_medi', t[2])
S_Data[lip_round_compression] = MCData(d[6], lip_clos, 'lip_clos', t[0])
S_Data[lip_round_protrusion] = MCData(d[4], lip_clos, 'lip_clos', t[0])
S_Data[lip_press_together] = MCData(d[7], lip_clos, 'lip_clos', t[0])
S_Data[lower_lip_f_tuck] = MCData(d[8], lip_clos, 'lip_clos', t[0])
S_Data[lip_stretch] = MCData(d[2], lip_medi, 'lip_medi', t[5])
S_Data[tongue_to_back] = MCData(d[5], tng_medi, 'tng_medi', t[0])
S_Data[tongue_to_roof] = MCData(d[7], tng_medi, 'tng_medi', t[4], 0.25)
S_Data[tongue_to_teeth] = MCData(d[4], tng_medi, 'tng_medi', t[0])
PhonemeDict['S'] = S_Data
# Z - alveolar voiced fric. /z/oo, ro/s/es
PhonemeDict['Z'] = PhonemeDict['S']
# SH - postalveolar voiceless fric. /sh/oe, pa/ssi/on, dona/ti/on
SH_Data = dict()
SH_Data[jaw_open] = MCData(d[7], jaw_medi, 'jaw_medi', t[0])
SH_Data[lip_round_compression] = MCData(d[5], lip_clos, 'lip_clos', t[0])
SH_Data[lip_round_protrusion] = MCData(d[9], lip_dist, 'lip_dist', t[8], 0.25)
SH_Data[lip_press_together] = MCData(d[4], lip_medi, 'lip_medi', t[0])
SH_Data[lower_lip_f_tuck] = MCData(d[8], lip_clos, 'lip_clos', t[0])
SH_Data[lip_stretch] = MCData(d[8], lip_medi, 'lip_medi', t[0])
SH_Data[tongue_to_back] = MCData(d[6], tng_medi, 'tng_medi', t[0])
SH_Data[tongue_to_roof] = MCData(d[8], tng_medi, 'tng_medi', t[4], 0.25)
SH_Data[tongue_to_teeth] = MCData(d[6], tng_medi, 'tng_medi', t[0])
PhonemeDict['SH'] = SH_Data
# ZH - poatalveolar voiced fric. trea/s/ure, mira/ge/
PhonemeDict['ZH'] = PhonemeDict['SH']
# CX - palatal voiceless fric. de: i/ch/
PhonemeDict['CX'] = PhonemeDict['RU']
# X - velar voiceless fric. lo/ch/, /Ch/anuka
PhonemeDict['X'] = PhonemeDict['RU']
# GH - velar voiced fric. not in en
PhonemeDict['GH'] = PhonemeDict['RU']
# HH - glottal voiceless fric. /h/appy, a/h/ead
HH_Data = dict()
HH_Data[jaw_open] = MCData(d[5], jaw_clos, 'jaw_clos', t[3])
HH_Data[lip_round_compression] = MCData(d[2], lip_vclo, 'lip_vclo', t[0])
HH_Data[lip_round_protrusion] = MCData(d[2], lip_vclo, 'lip_vclo', t[0])
HH_Data[lip_press_together] = MCData(d[4], lip_vclo, 'lip_vclo', t[0])
HH_Data[lower_lip_f_tuck] = MCData(d[4], lip_vclo, 'lip_vclo', t[0])
HH_Data[lip_stretch] = MCData(d[2], lip_vclo, 'lip_vclo', t[0])
HH_Data[tongue_to_back] = MCData(d[1], tng_vclo, 'tng_vclo', t[0])
HH_Data[tongue_to_roof] = MCData(d[1], tng_vclo, 'tng_vclo', t[0])
HH_Data[tongue_to_teeth] = MCData(d[1], tng_vclo, 'tng_vclo', t[0])
PhonemeDict['HH'] = HH_Data
# R - alveolar approximant /r/ed
R_Data = dict()
R_Data[jaw_open] = MCData(d[7], jaw_medi, 'jaw_medi', t[1])
R_Data[lip_round_compression] = MCData(d[2], lip_medi, 'lip_medi', t[7])
R_Data[lip_round_protrusion] = MCData(d[2], lip_clos, 'lip_clos', t[0])
R_Data[lip_press_together] = MCData(d[6], lip_clos, 'lip_clos', t[0])
R_Data[lower_lip_f_tuck] = MCData(d[5], lip_clos, 'lip_clos', t[0])
R_Data[lip_stretch] = MCData(d[3], lip_clos, 'lip_clos', t[0])
R_Data[tongue_to_back] = MCData(d[6], tng_medi, 'tng_medi', t[0])
R_Data[tongue_to_roof] = MCData(d[6], tng_medi, 'tng_medi', t[4])
R_Data[tongue_to_teeth] = MCData(d[6], tng_medi, 'tng_medi', t[0])
PhonemeDict['R'] = R_Data
# Y - palatal approximant /y/ou, /y/esterday
Y_Data = dict()
Y_Data[jaw_open] = MCData(d[3], jaw_medi, 'jaw_medi', t[0])
Y_Data[lip_round_compression] = MCData(d[2], lip_medi, 'lip_medi', t[0])
Y_Data[lip_round_protrusion] = MCData(d[2], lip_medi, 'lip_medi', t[0])
Y_Data[lip_press_together] = MCData(d[4], lip_clos, 'lip_clos', t[0])
Y_Data[lower_lip_f_tuck] = MCData(d[5], lip_clos, 'lip_clos', t[0])
Y_Data[lip_stretch] = MCData(d[3], lip_clos, 'lip_clos', t[0])
Y_Data[tongue_to_back] = MCData(d[7], tng_medi, 'tng_medi', t[0])
Y_Data[tongue_to_roof] = MCData(d[8], tng_medi, 'tng_medi', t[4])
Y_Data[tongue_to_teeth] = MCData(d[7], tng_medi, 'tng_medi', t[0])
PhonemeDict['Y'] = Y_Data
# L - alveolar lateral approx. /l/ip, p/l/ease
L_Data = dict()
L_Data[jaw_open] = MCData(d[4], jaw_medi, 'jaw_medi', t[4])
L_Data[lip_round_compression] = MCData(d[3], lip_clos, 'lip_clos', t[0])
L_Data[lip_round_protrusion] = MCData(d[3], lip_clos, 'lip_clos', t[0])
L_Data[lip_press_together] = MCData(d[6], lip_clos, 'lip_clos', t[0])
L_Data[lower_lip_f_tuck] = MCData(d[7], lip_clos, 'lip_clos', t[0])
L_Data[lip_stretch] = MCData(d[3], lip_clos, 'lip_clos', t[0])
L_Data[tongue_to_back] = MCData(d[4], tng_medi, 'tng_medi', t[0])
L_Data[tongue_to_roof] = MCData(d[8], tng_medi, 'tng_medi', t[8], 0.25)
L_Data[tongue_to_teeth] = MCData(d[5], tng_medi, 'tng_medi', t[0])
PhonemeDict['L'] = L_Data
# W - labial-velar approximant /w/ater, /w/alk
W_Data = dict()
W_Data[jaw_open] = MCData(d[4], jaw_medi, 'jaw_medi', t[0])
W_Data[lip_round_compression] = MCData(d[7], lip_dist, 'lip_dist', t[9])
W_Data[lip_round_protrusion] = MCData(d[3], lip_clos, 'lip_clos', t[0])
W_Data[lip_press_together] = MCData(d[3], lip_clos, 'lip_clos', t[0])
W_Data[lower_lip_f_tuck] = MCData(d[7], lip_clos, 'lip_clos', t[0])
W_Data[lip_stretch] = MCData(d[5], lip_clos, 'lip_clos', t[0])
W_Data[tongue_to_back] = MCData(d[6], tng_medi, 'tng_medi', t[0])
W_Data[tongue_to_roof] = MCData(d[6], tng_medi, 'tng_medi', t[0])
W_Data[tongue_to_teeth] = MCData(d[7], tng_medi, 'tng_medi', t[0])
PhonemeDict['W'] = W_Data
# H - labial-palatal approximant fr: /hu/it
PhonemeDict['H'] = PhonemeDict['HH']
# TS - alveolar voiceless affricate pi/zz/a, de: /z/ehn
PhonemeDict['TS'] = PhonemeDict['N']
# CH - postalveolar voiceless affr. /ch/ip
CH_Data = dict()
CH_Data[jaw_open] = MCData(d[4], jaw_medi, 'jaw_medi', t[0])
CH_Data[lip_round_compression] = MCData(d[5], lip_clos, 'lip_clos', t[0])
CH_Data[lip_round_protrusion] = MCData(d[8], lip_vdis, 'lip_vdis', t[8])
CH_Data[lip_press_together] = MCData(d[6], lip_medi, 'lip_medi', t[0])
CH_Data[lower_lip_f_tuck] = MCData(d[4], lip_clos, 'lip_clos', t[0])
CH_Data[lip_stretch] = MCData(d[5], lip_clos, 'lip_clos', t[0])
CH_Data[tongue_to_back] = MCData(d[6], tng_medi, 'tng_medi', t[0])
CH_Data[tongue_to_roof] = MCData(d[7], tng_medi, 'tng_medi', t[6], 0.2)
CH_Data[tongue_to_teeth] = MCData(d[6], tng_medi, 'tng_medi', t[0])
PhonemeDict['CH'] = CH_Data
# JH - postalveolar voiced affric. /g/irrafe, /j/ump
PhonemeDict['JH'] = PhonemeDict['CH']
# IY - close front unlip_round_compressioned b/ee/t, fr: f/i/n/i/
IY_Data = dict()
IY_Data[jaw_open] = MCData(d[7], jaw_medi, 'jaw_medi', t[4])
IY_Data[lip_round_compression] = MCData(d[7], lip_medi, 'lip_medi', t[0])
IY_Data[lip_round_protrusion] = MCData(d[7], lip_medi, 'lip_medi', t[0])
IY_Data[lip_press_together] = MCData(d[7], lip_medi, 'lip_medi', t[0])
IY_Data[lower_lip_f_tuck] = MCData(d[7], lip_medi, 'lip_medi', t[0])
IY_Data[lip_stretch] = MCData(d[7], lip_vdis, 'lip_vdis', t[8])
IY_Data[tongue_to_back] = MCData(d[5], tng_medi, 'tng_medi', t[0])
IY_Data[tongue_to_roof] = MCData(d[5], tng_medi, 'tng_medi', t[2])
IY_Data[tongue_to_teeth] = MCData(d[5], tng_medi, 'tng_medi', t[0])
PhonemeDict['IY'] = IY_Data
# E - close-mid front unlip_round_compressioned fr: beaut//
E_Data = dict()
E_Data[jaw_open] = MCData(d[7], jaw_medi, 'jaw_medi', t[4])
E_Data[lip_round_compression] = MCData(d[6], lip_medi, 'lip_medi', t[0])
E_Data[lip_round_protrusion] = MCData(d[6], lip_medi, 'lip_medi', t[0])
E_Data[lip_press_together] = MCData(d[6], lip_clos, 'lip_clos', t[0])
E_Data[lower_lip_f_tuck] = MCData(d[8], lip_clos, 'lip_clos', t[0])
E_Data[lip_stretch] = MCData(d[8], lip_dist, 'lip_dist', t[3])
E_Data[tongue_to_back] = MCData(d[7], tng_medi, 'tng_medi', t[0])
E_Data[tongue_to_roof] = MCData(d[7], tng_medi, 'tng_medi', t[3])
E_Data[tongue_to_teeth] = MCData(d[7], tng_medi, 'tng_medi', t[0])
PhonemeDict['E'] = E_Data
# EN - close-mid front unlip_round_compressioned+n fr: /ain/si
PhonemeDict['EN'] = PhonemeDict['E']
# EH - jaw_open-mid front unlip_round_compressioned b/e/d, fr: b/e/te
EH_Data = dict()
EH_Data[jaw_open] = MCData(d[7], jaw_dist, 'jaw_dist', t[5])
EH_Data[lip_round_compression] = MCData(d[6], lip_medi, 'lip_medi', t[0])
EH_Data[lip_round_protrusion] = MCData(d[6], lip_medi, 'lip_medi', t[0])
EH_Data[lip_press_together] = MCData(d[6], lip_medi, 'lip_medi', t[0])
EH_Data[lower_lip_f_tuck] = MCData(d[8], lip_medi, 'lip_medi', t[0])
EH_Data[lip_stretch] = MCData(d[8], lip_dist, 'lip_dist', t[6])
EH_Data[tongue_to_back] = MCData(d[7], tng_medi, 'tng_medi', t[4])
EH_Data[tongue_to_roof] = MCData(d[7], tng_medi, 'tng_medi', t[0])
EH_Data[tongue_to_teeth] = MCData(d[7], tng_medi, 'tng_medi', t[0])
PhonemeDict['EH'] = EH_Data
# A - jaw_open front unlip_round_compressioned fr: r/a/t
A_Data = dict()
A_Data[jaw_open] = MCData(d[7], jaw_medi, 'jaw_medi', t[5])
A_Data[lip_round_compression] = MCData(d[6], lip_medi, 'lip_medi', t[0])
A_Data[lip_round_protrusion] = MCData(d[6], lip_medi, 'lip_medi', t[0])
A_Data[lip_press_together] = MCData(d[6], lip_medi, 'lip_medi', t[0])
A_Data[lower_lip_f_tuck] = MCData(d[6], lip_medi, 'lip_medi', t[0])
A_Data[lip_stretch] = MCData(d[6], lip_medi, 'lip_medi', t[0])
A_Data[tongue_to_back] = MCData(d[7], tng_medi, 'tng_medi', t[0])
A_Data[tongue_to_roof] = MCData(d[7], tng_medi, 'tng_medi', t[0])
A_Data[tongue_to_teeth] = MCData(d[7], tng_medi, 'tng_medi', t[0])
PhonemeDict['A'] = A_Data
# AA - jaw_open back unlip_round_compressioned sp/a/, h/o/t
PhonemeDict['AA'] = PhonemeDict['A']
# AAN - jaw_open back unlip_round_compressioned+n fr: qu/and/, fr: /un/
PhonemeDict['AAN'] = PhonemeDict['AA']
# AO - jaw_open-mid back lip_round_compressioned fr: s/o/rt
AO_Data = dict()
AO_Data[jaw_open] = MCData(d[8], jaw_dist, 'jaw_dist', t[4])
AO_Data[lip_round_compression] = MCData(d[7], lip_dist, 'lip_dist', t[5])
AO_Data[lip_round_protrusion] = MCData(d[6], lip_medi, 'lip_medi', t[0])
AO_Data[lip_press_together] = MCData(d[6], lip_medi, 'lip_medi', t[0])
AO_Data[lower_lip_f_tuck] = MCData(d[6], lip_medi, 'lip_medi', t[0])
AO_Data[lip_stretch] = MCData(d[6], lip_medi, 'lip_medi', t[0])
AO_Data[tongue_to_back] = MCData(d[7], tng_medi, 'tng_medi', t[0])
AO_Data[tongue_to_roof] = MCData(d[7], tng_medi, 'tng_medi', t[3 ])
AO_Data[tongue_to_teeth] = MCData(d[7], tng_medi, 'tng_medi', t[0])
PhonemeDict['AO'] = AO_Data
# AON - jaw_open-mid back lip_round_compressioned+n fr: s/on/
PhonemeDict['AON'] = PhonemeDict['AO']
# O - close-mid back lip_round_compressioned fr: rs/eau/
PhonemeDict['O'] = PhonemeDict['AO']
# ON - close-mid back lip_round_compressioned+n fr: m/an/teau
PhonemeDict['ON'] = PhonemeDict['O']
# UW - close back lip_round_compressioned b/oo/t
PhonemeDict['UW'] = PhonemeDict['AO']
# UY - close front lip_round_compressioned fr: ch/u/te
UY_Data = dict()
UY_Data[jaw_open] = MCData(d[8], jaw_dist, 'jaw_dist', t[0])
UY_Data[lip_round_compression] = MCData(d[8], lip_vdis, 'lip_vdis', t[0])
UY_Data[lip_round_protrusion] = MCData(d[8], lip_dist, 'lip_dist', t[9])
UY_Data[lip_press_together] = MCData(d[7], lip_dist, 'lip_dist', t[0])
UY_Data[lower_lip_f_tuck] = MCData(d[7], lip_medi, 'lip_medi', t[0])
UY_Data[lip_stretch] = MCData(d[7], lip_vdis, 'lip_vdis', t[0])
UY_Data[tongue_to_back] = MCData(d[6], tng_medi, 'tng_medi', t[0])
UY_Data[tongue_to_roof] = MCData(d[6], tng_medi, 'tng_medi', t[0])
UY_Data[tongue_to_teeth] = MCData(d[6], tng_medi, 'tng_medi', t[0])
PhonemeDict['UY'] = UY_Data
# EU - close-mid front lip_round_compressioned fr: p/eu/
EU_Data = dict()
EU_Data[jaw_open] = MCData(d[8], jaw_medi, 'jaw_medi', t[4])
EU_Data[lip_round_compression] = MCData(d[7], lip_medi, 'lip_medi', t[0])
EU_Data[lip_round_protrusion] = MCData(d[8], lip_vdis, 'lip_vdis', t[6])
EU_Data[lip_press_together] = MCData(d[7], lip_medi, 'lip_medi', t[0])
EU_Data[lower_lip_f_tuck] = MCData(d[6], lip_medi, 'lip_medi', t[0])
EU_Data[lip_stretch] = MCData(d[6], lip_medi, 'lip_medi', t[0])
EU_Data[tongue_to_back] = MCData(d[6], tng_medi, 'tng_medi', t[0])
EU_Data[tongue_to_roof] = MCData(d[6], tng_medi, 'tng_medi', t[0])
EU_Data[tongue_to_teeth] = MCData(d[6], tng_medi, 'tng_medi', t[0])
PhonemeDict['EU'] = EU_Data
# OE - jaw_open-mid front lip_round_compressioned de: H//lle
PhonemeDict['OE'] = PhonemeDict['EU']
# OEN - jaw_open-mid front lip_round_compressioned+n fr: j/eu/ne
PhonemeDict['OEN'] = PhonemeDict['OE']
# AH - jaw_open-mid back unlip_round_compressioned n/u/t, r/u/n
PhonemeDict['AH'] = PhonemeDict['EH']
# IH - near-close near-front unrnd. b/i/t
PhonemeDict['IH'] = PhonemeDict['EH']
# UU - near-close near-front lip_round_compression. de: h//bsch
PhonemeDict['UU'] = PhonemeDict['EU']
# UH - near-close near-back lip_round_compression. h/oo/k
PhonemeDict['UH'] = PhonemeDict['EU']
# AX - mid central /a/bout, syn/o/nym, /uh/
PhonemeDict['AX'] = PhonemeDict['EH']
# UX - near-jaw_open central de: de/r/
PhonemeDict['UX'] = PhonemeDict['EH']
# AE - near-jaw_open front unlip_round_compressioned f/a/t
PhonemeDict['AE'] = PhonemeDict['EH']
# ER - jaw_open-mid central unlip_round_compressioned p/er/fect
ER_Data = dict()
ER_Data[jaw_open] = MCData(d[6], jaw_dist, 'jaw_dist', t[4])
ER_Data[lip_round_compression] = MCData(d[6], lip_medi, 'lip_medi', t[0])
ER_Data[lip_round_protrusion] = MCData(d[6], lip_dist, 'lip_dist', t[5])
ER_Data[lip_press_together] = MCData(d[5], lip_medi, 'lip_medi', t[0])
ER_Data[lower_lip_f_tuck] = MCData(d[5], lip_medi, 'lip_medi', t[0])
ER_Data[lip_stretch] = MCData(d[5], lip_medi, 'lip_medi', t[0])
ER_Data[tongue_to_back] = MCData(d[4], tng_medi, 'tng_medi', t[0])
ER_Data[tongue_to_roof] = MCData(d[4], tng_medi, 'tng_medi', t[5])
ER_Data[tongue_to_teeth] = MCData(d[4], tng_medi, 'tng_medi', t[0])
PhonemeDict['ER'] = ER_Data
# AXR - mid central rhotacized butt/er/
PhonemeDict['AXR'] = PhonemeDict['ER']
# EXR - jaw_open-mid central rhotacized f/ur/
PhonemeDict['EXR'] = PhonemeDict['ER']
# EY - dipthong, split
PhonemeDict['EY'] = PhonemeDict['EH']
# AW - dipthong, split
PhonemeDict['AW'] = PhonemeDict['EH']
# AY - dipthong, split
PhonemeDict['AY'] = PhonemeDict['EH']
# OY - dipthong, split
PhonemeDict['OY'] = PhonemeDict['EU']
# OW - dipthong, split
PhonemeDict['OW'] = PhonemeDict['EU']
#------------------------------------------------------------------------------
# Routines
#------------------------------------------------------------------------------
timeIntervals = (-8.0, -6.0, -4.0, -2.0, -1.0, -0.5, -0.45, -0.40, -0.35, -0.30, -0.25, -0.20, -0.15, -0.1, -0.05, -0.04, -0.03, -0.02, -0.01, 0, 0.01, 0.02, 0.03, 0.04, 0.05, 0.1, 0.15, 0.20, 0.25, 0.30, 0.35, 0.40, 0.45, 0.5, 1.0, 2.0, 4.0, 6.0, 8.0)
def GeneratePrototypeDominanceCurve(curveName):
mcData = MCData(1.0, 20, 'n/a', 1.0)
dominanceCurve = Curve(curveName)
for time in timeIntervals:
dominanceCurve.keys.append(Key(time, mcData.calc_dominance_value(time), mcData.calc_slope_in(time), mcData.calc_slope_out(time)))
return dominanceCurve
def GenerateDominanceCurves(mcData, anim, curveName):
dominanceCurve = Curve(curveName)
# calculate the dominance curves
for time in timeIntervals:
dominanceCurve.keys.append(Key(time, mcData.calc_dominance_value(time), mcData.calc_slope_in(time), mcData.calc_slope_out(time)))
anim.curves.append(dominanceCurve)
scaledDominanceCurve = Curve(curveName + scaled)
# calculate the scaled dominance curve.
for key in dominanceCurve.keys:
scaledDominanceCurve.keys.append(Key(key.time, key.value * mcData.target, key.slopein * mcData.target, key.slopeout * mcData.target))
anim.curves.append(scaledDominanceCurve)
def CreateMCAnimations():
# Create the dominance functions group.
issueCommand('animGroup -create -group "%s";' % (phonemeEventGroup))
issueCommand('animGroup -create -group "%s";' % (spawnedPhonemeEventGroup))
# Create the dominance curves animations.
for target in targetList:
targetDominanceAnimation = MCAnim(target, spawnedPhonemeEventGroup)
targetDominanceAnimation.curves.append(GeneratePrototypeDominanceCurve(target))
targetDominanceAnimation.buildAnim()
targetDominanceScaledAnimation = MCAnim(target + scaled, spawnedPhonemeEventGroup)
targetDominanceScaledAnimation.curves.append(GeneratePrototypeDominanceCurve(target + scaled))
targetDominanceScaledAnimation.buildAnim()
# For each phoneme in the data dictionary, add an animation with events that
# reference each of the 18 dominance curves.
total = len(PhonemeDict)
curr = 0
for phoneme in sorted(PhonemeDict):
# Create the phoneme's animation
print 'Processing phoneme %d of %d' % (curr, total)
phonemeAnim = MCAnim(phoneme, phonemeEventGroup)
# For each target, add the dominance animation and the scaled dominance animation
phonemeData = PhonemeDict[phoneme]
for target in sorted(phonemeData):
targetMCData = phonemeData[target]
dominanceEvent = MCEvent(target, spawnedPhonemeEventGroup, targetMCData.duration_scale, targetMCData.magnitude)
dominanceEvent.set_start(targetMCData.offset)
scaledDominanceEvent = MCEvent(target + scaled, spawnedPhonemeEventGroup, targetMCData.duration_scale, targetMCData.magnitude * targetMCData.target)
scaledDominanceEvent.set_start(targetMCData.offset)
phonemeAnim.events.append(dominanceEvent)
phonemeAnim.events.append(scaledDominanceEvent)
# Finish the work for the phoneme by building the animation
phonemeAnim.buildAnim()
curr += 1
issueCommand('flushUndo')
def CreateMCFaceGraph():
# Create the face graph structure.
issueCommand('batch;')
issueCommand('graph -addnode -nodetype "FxCombinerNode" -name "_constant_feeder" -min 0 -max 10')
for nodeTuple in nodesToCreate:
# Add the nodes
issueCommand('graph -addnode -nodetype "FxCombinerNode" -name "%s" -min 0 -max 10' % (nodeTuple[0]))
issueCommand('graph -addnode -nodetype "FxCombinerNode" -name "%s" -min 0 -max 10' % (nodeTuple[1]))
issueCommand('graph -addnode -nodetype "FxCombinerNode" -name "%s" -min 0 -max 10 -inputop "mul"' % (nodeTuple[2]))
# Create the links
issueCommand('graph -link -from "_constant_feeder" -to "%s" -linkfn "constant" -linkfnparams "c=0.001"' % (nodeTuple[0]))
issueCommand('graph -link -from "%s" -to "%s" -linkfn "linear";' % (nodeTuple[1], nodeTuple[2]))
issueCommand('graph -link -from "%s" -to "%s" -linkfn "inverse";' % (nodeTuple[0], nodeTuple[2]))
#issueCommand('graph -addnode -nodetype "FxCombinerNode" -name "_jaw_corrector" -min -0 -max 1"')
#issueCommand('graph -link -from "%s" -to "%s" -linkfn "linear";' % (lip_press_together + sum, '_jaw_corrector'))
#issueCommand('graph -link -from "%s" -to "%s" -linkfn "linear";' % (lower_lip_f_tuck + sum, '_jaw_corrector'))
#issueCommand('graph -link -from "%s" -to "%s" -linkfn "corrective";' % ('_jaw_corrector', jaw_open + sum))
for nodeTuple in finalTargetList:
issueCommand('graph -addnode -nodetype "FxCombinerNode" -name "%s" -min 0 -max 1' % (nodeTuple[0]))
issueCommand('graph -link -from "%s" -to "%s" -linkfn "linear";' % (nodeTuple[1], nodeTuple[0]))
issueCommand('execBatch -editednodes;')
def DoFullModel():
phonemeWordList = FxPhonemes.PhonemeWordList()
phonemeList = phonemeWordList.phonemes
phonemeString = 'Phones: '
for phone in phonemeList:
phonemeString += ' %s %f %f' % (FxPhonemes.PHONEME_REGISTRY.entries[phone.phonemeId].facefxCoding, phone.startTime, phone.endTime)
print phonemeString
targetString = 'Targets: '
curveDict = dict()
for target in targetList:
targetString += ' %s,' % (target)
curveDict[target] = Curve(target + sum)
print targetString
# loop through each target
for time in frange(0, 28.148, 0.05):
for target in targetList:
Dsp_sum = 0.0
DspxTsp_sum = 0.0
for phone in phonemeList:
mcData = PhonemeDict[FxPhonemes.PHONEME_REGISTRY.entries[phone.phonemeId].facefxCoding][target]
tcsp = phone.startTime + (phone.endTime - phone.startTime) * 0.5
#tcsp = phone.startTime
tau = tcsp - time
DspxTsp_sum += mcData.calc_scaled_dominance_value(tau)
Dsp_sum += mcData.calc_dominance_value(tau)
Fpt = 0.0
if Dsp_sum != 0.0:
Fpt = DspxTsp_sum / Dsp_sum
curveDict[target].keys.append(Key(time, Fpt, 0, 0))
animToAdd = MCAnim('allaround16_2', 'Comparison')
for curveName in sorted(curveDict):
animToAdd.curves.append(curveDict[curveName])
animToAdd.buildAnim()
#------------------------------------------------------------------------------
# Main program begins here
#------------------------------------------------------------------------------
CreateMCAnimations()
CreateMCFaceGraph()
#DoFullModel()