/// <summary> /// 設定を基にAviUtl拡張編集ファイルの保存処理を行う。 /// </summary> /// <param name="exoFilePath">AviUtl拡張編集ファイルパス。</param> /// <param name="waveFilePath">WAVEファイルパス。</param> /// <param name="text">テキスト。</param> /// <param name="common">共通設定。</param> /// <param name="charaStyle">キャラ別スタイル。</param> /// <returns>保存した拡張編集オブジェクト。失敗したならば null 。</returns> private static async Task <ExEditObject> DoOperateExoSave( string exoFilePath, string waveFilePath, string text, ExoCommonConfig common, ExoCharaStyle charaStyle) { // フレーム数算出 int frameCount = 0; try { var waveTime = await Task.Run(() => (new WaveFileInfo(waveFilePath)).TotalTime); var f = (waveTime.Ticks * common.Fps) / (charaStyle.PlaySpeed.Begin * (TimeSpan.TicksPerSecond / 100)); frameCount = (int)decimal.Floor(f); // 拡張編集の仕様に合わせて切り捨て } catch (Exception ex) { ThreadTrace.WriteException(ex); return(null); } var exo = new ExEditObject { Width = common.Width, Height = common.Height, Length = frameCount + common.ExtraFrames, AudioSampleRate = common.AudioSampleRate, AudioChannelCount = common.AudioChannelCount, }; // decimal の小数部桁数を取得 var scale = (decimal.GetBits(common.Fps)[3] & 0xFF0000) >> 16; exo.FpsScale = (int)Math.Pow(10, scale); exo.FpsBase = decimal.Floor(common.Fps * exo.FpsScale); // テキストレイヤー追加 { var item = new LayerItem { BeginFrame = 1, EndFrame = exo.Length, LayerId = 1, GroupId = common.IsGrouping ? 1 : 0, IsClipping = charaStyle.IsTextClipping }; var c = charaStyle.Text.Clone(); ExoTextStyleTemplate.ClearUnused(c); c.Text = text; item.Components.Add(c); item.Components.Add(charaStyle.Render.Clone()); exo.LayerItems.Add(item); } // 音声レイヤー追加 { var item = new LayerItem { BeginFrame = 1, EndFrame = frameCount, LayerId = 2, GroupId = common.IsGrouping ? 1 : 0, IsAudio = true, }; item.Components.Add( new AudioFileComponent { PlaySpeed = charaStyle.PlaySpeed.Clone(), FilePath = waveFilePath, }); item.Components.Add(charaStyle.Play.Clone()); exo.LayerItems.Add(item); } // ファイル書き出し try { await ExoFileReaderWriter.WriteAsync(exoFilePath, exo); } catch (Exception ex) { ThreadTrace.WriteException(ex); return(null); } return(exo); }
/// <summary> /// 現在開いているAviUtl拡張編集プロジェクトの情報から、 /// AviUtl拡張編集ファイル用の共通設定を更新する。 /// </summary> /// <param name="common">更新対象の共通設定。処理成功時のみ変更される。</param> /// <returns>処理結果値。</returns> private static GcmzDrops.FileDrop.Result UpdateExoCommonConfigByAviUtl( ref ExoCommonConfig common) { switch (GcmzDrops.GcmzInfoReader.Read(out var info)) {
/// <summary> /// 設定を基にAviUtl拡張編集ファイル関連の処理を行う。 /// </summary> /// <param name="filePath">WAVEファイルパス。</param> /// <param name="voiceroidId">VOICEROID識別ID。</param> /// <param name="text">テキスト。</param> /// <param name="appConfig">アプリ設定。</param> /// <param name="exoConfig">AviUtl拡張編集ファイル用設定。</param> /// <param name="aviUtlFileDropService"> /// AviUtl拡張編集ファイルドロップサービス。 /// </param> /// <returns>処理結果とエラー文字列のタプル。</returns> private static async Task <Tuple <ExoOperationResult, string> > DoOperateExo( string filePath, VoiceroidId voiceroidId, string text, AppConfig appConfig, ExoConfig exoConfig, IAviUtlFileDropService aviUtlFileDropService) { if (appConfig.IsExoFileMaking) { var exoFilePath = Path.ChangeExtension(filePath, @".exo"); // 共通設定更新 ExoCommonConfig common = null; var gcmzResult = GcmzDrops.FileDrop.Result.Success; if ( appConfig.IsSavedExoFileToAviUtl && appConfig.IsExoFileParamReplacedByAviUtl) { common = exoConfig.Common.Clone(); gcmzResult = UpdateExoCommonConfigByAviUtl(ref common); } // ファイル保存 var exo = await DoOperateExoSave( exoFilePath, filePath, text, common ?? exoConfig.Common, exoConfig.CharaStyles[voiceroidId]); if (exo == null) { return (Tuple.Create( ExoOperationResult.SaveFail, @".exo ファイルを保存できませんでした。")); } // ファイルドロップ if (appConfig.IsSavedExoFileToAviUtl) { // UpdateExoCommonConfigByAviUtl で失敗しているなら実施しない var failMessage = (gcmzResult != GcmzDrops.FileDrop.Result.Success) ? MakeFailMessageFromExoDropResult(gcmzResult) : await DoOperateExoDrop( exoFilePath, exo.Length, appConfig.AviUtlDropLayers[voiceroidId].Layer, aviUtlFileDropService); // 処理失敗時、そもそも AviUtl が起動していないなら成功扱い if (failMessage != null && Process.GetProcessesByName(@"aviutl").Length > 0) { return(Tuple.Create(ExoOperationResult.DropFail, failMessage)); } } } return(Tuple.Create(ExoOperationResult.Success, (string)null)); }