/// <summary> /// 口形状キー領域をモーフウェイト値で変換してタイムラインへ追加する。 /// </summary> /// <param name="table">追加先のタイムラインテーブル。</param> /// <param name="lipKeyArea">口形状キー領域。</param> /// <param name="morphWeight">モーフ名とそのウェイト値。</param> /// <param name="morphEtoAI"> /// "え" から "あ","い" へのモーフ変更を行うならば true 。 /// </param> private void AddMorphKeyArea( MorphTimelineTable table, KeyArea lipKeyArea, MorphWeightData morphWeight, bool morphEtoAI) { // "え" から "あ","い" への変換を行うか? bool e2ai = (morphEtoAI && morphWeight.MorphName == "え"); // キー領域作成 var area = new KeyArea(); foreach (var p in lipKeyArea.Points) { area.AddPointAfter( p.Key, p.Value * morphWeight.Weight * (e2ai ? 0.5f : 1.0f)); } // タイムラインに追加 if (e2ai) { table.GetOrAddNew("あ").KeyAreas.Add(area); table.GetOrAddNew("い").KeyAreas.Add(area); } else { table.GetOrAddNew(morphWeight.MorphName).KeyAreas.Add(area); } }
/// <summary> /// 口形状キー領域をモーフウェイト値で変換してタイムラインへ追加する。 /// </summary> /// <param name="table">追加先のタイムラインテーブル。</param> /// <param name="lipKeyArea">口形状キー領域。</param> /// <param name="morphWeight">モーフ名とそのウェイト値。</param> /// <param name="morphEtoAI"> /// "え" から "あ","い" へのモーフ変更を行うならば true 。 /// </param> private void AddMorphKeyArea( MorphTimelineTable table, TimelineKeyArea lipKeyArea, MorphWeightData morphWeight, bool morphEtoAI) { // "え" から "あ","い" への変換を行うか? bool e2ai = (morphEtoAI && morphWeight.MorphName == "え"); // キー領域作成 var area = lipKeyArea.Clone(); foreach (var p in lipKeyArea.Points.Keys) { area.Points[p] *= morphWeight.Weight * (e2ai ? 0.5f : 1.0f); } // タイムラインに追加 // モーフ名が空文字列のものは弾く if (e2ai) { table.GetOrAddNew("あ").KeyAreas.Add(area); table.GetOrAddNew("い").KeyAreas.Add(area); } else if (!string.IsNullOrEmpty(morphWeight.MorphName)) { table.GetOrAddNew(morphWeight.MorphName).KeyAreas.Add(area); } }
/// <summary> /// 口形状タイムラインセットとモーフ情報セットから /// モーフ別タイムラインテーブルを作成する。 /// </summary> /// <param name="tlSet">口形状タイムラインセット。</param> /// <param name="morphSet">モーフ情報セット。</param> /// <param name="morphEtoAI"> /// "え" から "あ","い" へのモーフ変更を行うならば true 。 /// </param> /// <returns>モーフ別タイムラインテーブル。</returns> public MorphTimelineTable Make( LipTimelineSet tlSet, LipMorphSet morphSet, bool morphEtoAI) { var table = new MorphTimelineTable(); foreach (var mt in tlSet) { var timeline = mt.Value; var morphInfo = morphSet[mt.Key]; timeline.KeyAreas.ForEach( area => morphInfo.MorphWeights.ForEach( mw => AddMorphKeyArea(table, area, mw, morphEtoAI))); } return table; }
/// <summary> /// キーフレームリストを作成する。 /// </summary> /// <returns>キーフレームリスト。</returns> private static KeyFrameList MakeKeyFrameListCore( MorphTimelineTable tlTable, LipSpanRange spanRange, decimal spanFrame, long beginFrame, bool edgeWeightZero) { // 基準フレーム長算出 if (spanRange == LipSpanRange.All) { var end = tlTable.GetEndPlace(); if (end > 0) { spanFrame /= end; } } // キーフレームリスト作成 KeyFrameList dest = null; { var maker = new KeyFrameListMaker(); maker.UnitFrameLength = spanFrame; maker.IsEdgeWeightZero = edgeWeightZero; dest = maker.Make(tlTable, beginFrame); } return dest; }
/// <summary> /// KeyFrames コマンドを設定する。 /// </summary> /// <param name="targetMorphNames"> /// 操作対象モーフ名配列。 tlTable.MorphNames を用いるならば null 。 /// </param> /// <param name="tlTable">モーフ別タイムラインテーブル。</param> /// <param name="unitSeconds"> /// ユニット基準長(「ア」の長さ)に相当する秒数値。 /// </param> /// <param name="edgeWeightZero"> /// キーフレームリストの先頭と終端で、 /// 含まれている全モーフのウェイト値をゼロ初期化するならば true 。 /// </param> /// <param name="naturalLink"> /// クライアント側が対応していれば、キーフレームリスト挿入位置前後の /// ウェイト値から自然に繋ぐならば true 。 /// </param> /// <param name="keyFrameReplacing"> /// クライアント側が対応していれば、キーフレームリスト挿入範囲の /// 既存キーフレームを削除して置き換えるならば true 。 /// </param> public void SetKeyFramesCommand( string[] targetMorphNames, MorphTimelineTable tlTable, decimal unitSeconds, bool edgeWeightZero, bool naturalLink, bool keyFrameReplacing) { if (tlTable == null) { throw new ArgumentNullException(nameof(tlTable)); } if (unitSeconds <= 0) { throw new ArgumentOutOfRangeException(nameof(unitSeconds)); } var param = new KeyFramesCommandParameter { TargetMorphNames = targetMorphNames, TimelineTable = tlTable, UnitSeconds = unitSeconds, IsEdgeWeightZero = edgeWeightZero, IsNaturalLink = naturalLink, IsKeyFrameReplacing = keyFrameReplacing, }; lock (commandLockObject) { this.Command = new LipServiceCommand( this.Command.Counter + 1, LipServiceCommandId.KeyFrames, param); } }