バグの巣 - [[レンダー乙女とか]]
目次
- 「ムービーの変換が変」な件 kiyo(2007/10/05)
- 「ファイル読み出し内容が消える」件 kiyo
- 「app.project.importの返り値が変」な件 kiyo
- コマ数ズレるぞー kiyo
- コマ数ズレるぞー の続報 kiyo
AEスクリプトのバグと対処法のページです。 バグを見つけたらご自由に書き込んでくださいね。(管理人)
「ムービーの変換が変」な件 kiyo(2007/10/05)
AE8(CS3)でムービーフッテージのバッファのとりかたがあやしい件について。
ムービーフッテージのみの現象です。 静止画連番フッテージでは、現在この現象は確認されていません。 …一応なさそう。以下のサンプルプロジェクトを開くとAE6.5およびAE7 と AE8で動作に違いが発生します。
http://www.nekomataya.info/nekojyarashi/misc/movieBug.zip
このアーカイブの sample.aep(AE6.5プロジェクト)
内容はシンプルで 継続時間 1秒/15fpsのムービーフッテージを「フッテージを変換」>「メイン」で0.5秒/30fpsに変換したものです。
期待する内容は、当然ですが0.5秒の継続時間で15フレームの画像ですが…
第8フレーム目で絵の変化がなくなって以降15フレーム目まで第8フレームが表示されます。 継続時間は期待通りなのですが、明らかにおかしい。もちろんAE7までのバージョンでは期待通りの動作をします。
考えられるのは、ムービーフッテージに対して
- 1.元のムービーの継続時間でバッファに展開する。
- 2.バッファの延長(変更)を行わずに内部的にタイムリマップする(当然継続時間の後方が欠落)
- 3.バッファを延長(変更)して指定のフッテージを作る
こんなふうにやってるわけだ…
2番と3番は明らかに逆ですね。こういうバカな手順で処理をしているわけで…信じがたいがどうもそうらしい
ちなみに逆方の変換の(フレームレートをさげる)場合も似た様な症状が出ています。(なぜ?)
かなり基本的なあたりで…悲しいバグです。
対処方法
バグフィックスされるまでの回避方法「フッテージを変換」でフレームレートの変更をしない…そのくらいしか思いつかない。
どうしてもムービーをファイルにセットされた以外のフレームレートで扱う必要がある場合は、
- 1.希望のフレームレートでプリコンポしてからタイムリマップ等で操作する。
- 2.いったん静止画フッテージに分解する(音は…)
困るヒトもけっこう大勢居ると思うので、バグフィックスは速いか…(無かったら軽蔑しちゃう)
プルダウン解除とかの定番変換もこれから試験します。
ざっと…しました
プルダウン削除も「ちびっと変」
2-3変換で 24fpsから30fpsにコンバートしたデータを24fpsのフッテージとして使用するための簡便な方法として「フッテージを変換」メニューで「フィールド分解」+「プルダウン削除」が利用できますが、この方法だとムービーの最終フレームが取得できない様です。
いくつかファイルを作成して上記メニューで読み込みをかけたところ、「最終フレーム」が「最終1フレーム前の画像」で置き換わっています。上の現象と同じ根のような印象ですが…ただいま、さらに追っかけ中
暫定対処法
これも、静止画連番のフッテージだと正常動作しますので。
- オリジナルのフッテージを一度連番画像として書き出して、それを使う
- オリジナルのフッテージはサウンドフッテージとして割り切る
とすれば、作業上の問題は出ない様です。…トホホ
「ファイル読み出し内容が消える」件 kiyo
簡易XPSリンカ の障害報告で判明したなにやらあやしげな動作(2006/12/04現在 追跡中)AE6.5 AE7 ともに Fileオブジェクトの読み出しメソッド read() で 特定のファイルの読み出しデータが 消失する。
発生条件 不明
エラーになるわけでなく 読み出したはずのデータが突然「なにも無し」になります。 これから追跡開始です。
あーっと でも仕事が忙しいので時間かかるかも。
簡易XPSリンカのユーザの方でこの障害に引っかかった方へ
この障害に当たると、保存したXPSデータを読み込もうとした時に "false"とのみ表示されたアラートが出て、ファイルが読み込めません。
判定すべき読み込みデータがサイズ 0 になるので、プログラム内のトラップに引っかかってこの表示がでます。本来エラーのなさそうな位置なのですごくそっけないメッセージです。(falseのあとには、不正データが表示されているはずなのですが…サイズ0なのでなにもない)
もし、そのようなケースにあたった場合は、一時的な回避策として
「コメント欄になにか書き込んでファイルサイズを変えてください。」
今のところそうやって読み込み可能になるケースが多いです。
「app.project.importの返り値が変」な件 kiyo
http://bry-ful.ddo.jp/BRY/software/AE_Script/help/index.html
こちらで、指摘のあった「戻り値がおかしい問題」を追っかけてみました。
同ページの 「メモ&Tips」>「app.project.importの返り値が変」
試験用のスクリプトをお借りして試してみると…
たしかに… 同じアイテムが戻ってくる。
固定ファイルだと期待の結果がでないので、少し突っ込んで調べる為にfileGetDialogで書き換えてみました。
{ function importSafeWithError (importOptions) { try { return app.project.importFile (importOptions); } catch (error) { alert(error.toString() + importOptions.file.fsName); } } //---------------------------------------------------------------------------- // Main //プロジェクトがなかったら作る。 if (app.project==null) { app.newProject(); } app.beginUndoGroup("Test import"); var footageList = new Array; for (io=0;io<3;io++) { myIO = new ImportOptions(fileGetDialog("importFile","*"));//for Win // myIO = new ImportOptions(fileGetDialog("importFile",""));//for Mac myIO.sequence = false; footageList.push(importSafeWithError(myIO)); alert(myIO.file.fsName + "\n" + footageList[footageList.length-1].file.fsName); // この行を挿入すると期待通りの動作になるかわりにセレクト解除される // footageList[footageList.length-1].selected=false; } var s=""; for (i=0;i < footageList.length;i++){ s+= i +" Name:"+footageList[i].name+ " file.name:"+footageList[i].file.name+footageList[i].toString()+"\n"; } alert(s); app.endUndoGroup(); }
で、だんだんわかってきた様な気がする。
どうやら、「現在選択されているフッテージの一番上のアイテムが戻っている。」みたいである。
AE7.0でもやってみる。…と、期待通りの動作をする…正常である。
- まとめ
- app.project.importFile() メソッドの戻り値は、インポートしたFootageItem?であるべきだが、状況によっては正常なアイテムが戻らない。
このメソッドの戻り値異常はAE6.5のバグである。
本来そのメソッドでインポートしたフッテージが戻るべきであるが、その場で選択されている中から最もINDEXの小さなフッテージが戻る。
7.0でFIXされている。
- 回避方法
- いくつか考えられる回避方法
- インポート操作をする前にフッテージの選択状態を解除する。
こんな感じ
for (idx=1;idx<=app.project.items.length;idx++) { app.project.item(idx).selected=false; }
- 上の対処をした上で、複数フッテージを処理する場合は毎回ループを回すのも「ナニ」なので、サンプルの様なケースではインポート直後に戻り値をセレクト解除したほうがヨサゲ?
footageList.push(importSafeWithError(myIO)); footageList[footageList.length-1].selected=false;
- インポートした直後はセレクトされているのを利用するなら以下の方法も有効
- インポート前にフッテージのセレクトを全解除
- インポート操作後にapp.project.items.selectionを参照する。
- 「チカラワザ」系ならインポート操作の際にファイル名を記録して、そのデータからアイテムを再抽出する…しても良いけどあまりスマートではない。
チカラワザ用にこんなメソッドもありかも?
/* このコードを実行すると、以降は app.project.getItemByFsName() メソッドが使える様になります。 引数は、ファイルパス 戻り値はファイルの一致するアイテムオブジェクト 二つ以上の同一ファイルを参照するアイテムは先にマッチした方が戻る。 マッチがなければnull */ app.project.getItemByFile=function(file) { if(! file.exists) return null; for(idx=1;idx<=this.items.length;idx++){ if(this.item(idx) instanceof FootageItem){ // フルパスで比較 if(this.item(idx).file.fsName===file.fsName){ return this.item(idx); }; }else{ continue; } } return null; } //この下のコードはチェック用なので実際の使用時は不要です。 var myFootage=app.project.getItemByFile(fileGetDialog("tst","*")); if(myFootage){alert(myFootage.name);}else{alert("NULL");}
コマ数ズレるぞー kiyo
有名なアレ
最初、JavascriptとAEの内部精度とのずれだとばかり思っていたが…どうも違うっぽい?
なんかすごく変!
たとえば 24fps で継続時間 101フレームのコンポを作成すると
メニューから作る
コンポ設定で取得 101フレームの表示(正常) スクリプトで引き出すコマ数 101フレーム スクリプトで取得した継続時間 4.20833333333333秒(循環少数を12桁で四捨五入)
スクリプトから作る
app.project.item(ホゲホゲ).duration=101/24;
コンポ設定で取得 102フレームの表示(異常。ただしこれはフレーム表示上切り上げせざるを得ない為) スクリプトで引き出すコマ数 101.000003814697フレーム(わずかに多い) スクリプトで取得した継続時間 4.20833349227905秒(無駄に多いそれも桁数の浅い位置で誤差がある)
もちろん、Javascript的にも 101/24 は 4.2083333333.. な循環小数である。(当然)
これで予想されるのは、内部的なフレーム修正誤差が集積している事…かな? 内部で、無駄に切り上げしている場所があるのでは無いかと勝手に推測中 ひょっとすると内部的にはフレームベースでデータを持っていて実時間を計算して出している…のか?いや、それだとこんなふうな誤差ののり方にはならんような気がする…
アー、ちなみに、これもAE7.0で試したらFIXされているモヨウです。
…やっぱりバグ…それも計算ミス系ぽい
- まとめ
- AE6.5では、特定のフレーム数のコンポを作成すると微妙に1コマ増えたりする。
循環小数や無限小数の処理にフレーム処理の誤差が乗っかってわるさを働いているのでは無かろうかと推測中。
追加情報求む!
- 対処法
- きちんと計算して精度を上げてもあまり意味がなさそう。 現在考えられる対応処置
- 故意に精度を下げて(数値の桁数を下げる)微妙に生成数値を下げてやる。 フレームカウントが「切り上げ」ベースなのを利用して
目標値 | 実効値 | 認識フレーム数 |
101 | 101.0000038 | 102 フレーム |
101 | 100.9999987 | 101 フレーム |
こんな感じで、目標値よりも微妙に少ない値を得てフレーム勘定の実害を低減する。
- 無視する コンポにフレームブレンドがかかっている場合、継続時間が微妙に短いと最終フレームが暗くなる(または透ける)ので あえてフレームが多くても無視する。 画像の状態次第ではこちらが得策。
- おまけ
- スクリプトで尺を操作すると誤差がでるのでボールド等でフレーム数を取得する必要がある場合以下の様にフレームを整数化しましょう。
myFrames=Math.round(app.project.item(ほげほげ).duration/app.project.item(ほげほげ).frameDuration);
この際 (希望のコマ数が欲しければ)ラウンド(Math.round)で、 (コンポのコマ数がほしい場合は)切り上げ(Math.ceil)で
レンダリングで余計なコマがでそうな場合は、同様にコマ数を取得してレンダリング対象フレームを操作するべしし…面倒くさい
コマ数ズレるぞー の続報 kiyo
http://bry-ful.ddo.jp/BRY/software/AE_Script/help/html/memo_tips/komazure.html
bry-ful's Homepage さんで 上の問題の追加検証して頂きました。
CompItem?.duration への代入は、AE7で解消されていますが itemCorection.addComp() メソッドのバグは以前のままだそうです。
私、duration が fix されているのでてっきり addComp も修正されているとか思いこんでましたよ…
こちらでも追加で同問題のトレースをしてみました。チョト気になる点があったので
コマ数ズレる問題回避法(AE6.5むけ たぶん最終版)
コンポ継続時間をセットして実際にセットされた値と比較します。myResult=""; for (n=1;n<=32;n++) { app.project.item(1).duration=1/n; myResult +=n +": "+ 1/n +" : "+app.project.item(1).duration+"?n"; } alert(myResult);分数で並べて代入して結果を見たところ。
結果
こんなカンジで継続時間がセットされました。
思いの外どれもこれも誤差だらけ…でも
よーく見ると、設定したい値と設定された値が所々マッチしています。 なんだか よく見慣れた 1/2 1/4 1/8 … と 1/(2^2) の系列です。
で、確認
myResult=""; for (n=1;n<=32;n++) { app.project.item(9).duration=1/Math.pow(2,n); myResult +=n +": "+ (1/Math.pow(2,n)) +" : "+app.project.item(9).duration+"?n"; } alert(myResult);
結果
どうもそのようです。
きっとこの数列を使って循環少数など 無理数の回避をして精度を出そうとしている部分があるのでしょう。(いや、全く勝手な推測…)
それでは、ひょっとするとこの単位系列で近似した値を設定してやるとぐっと良好な近似値が…(希望的観測…)
でも、ハズレでダメモト 試してみましょう。これではイカに?
myResult=""; for(replayCount=1;replayCount<33;replayCount++){ //(1/2^n)を合成して近似値を求める var myTargetDuration=0.4; var myDuration=myTargetDuration; var coc=new Array(); // var replayCount=23; for (cO=0;cO<replayCount;cO++) { coc[cO]=Math.floor(myDuration); if(myTargetDuration%(1/Math.pow(2,cO))==0) { //割り切れたので終了 break }else{ myDuration=(myDuration%1)*2; } } myDuration=0;//使い終わったので再初期化して流用 for (c=0;c<coc.length;c++) { myDuration+=(1/Math.pow(2,c))*coc[c]; } app.project.item(9).duration=myDuration; myResult+= replayCount+":"+coc[replayCount-1]+">>"+ app.project.item(9).duration+" : "+myDuration+" : "+myTargetDuration +"?n"; } alert(myResult);
結果こんなカンジに
1:0>>0 : 0 : 0.4 2:0>>0 : 0 : 0.4 3:1>>0.25 : 0.25 : 0.4 4:1>>0.375 : 0.375 : 0.4 5:0>>0.375 : 0.375 : 0.4 6:0>>0.375 : 0.375 : 0.4 7:1>>0.390625 : 0.390625 : 0.4 8:1>>0.3984375 : 0.3984375 : 0.4 9:0>>0.3984375 : 0.3984375 : 0.4 10:0>>0.3984375 : 0.3984375 : 0.4 11:1>>0.3994140625 : 0.3994140625 : 0.4 12:1>>0.39990234375 : 0.39990234375 : 0.4 13:0>>0.39990234375 : 0.39990234375 : 0.4 14:0>>0.39990234375 : 0.39990234375 : 0.4 15:1>>0.39996337890625 : 0.39996337890625 : 0.4 16:1>>0.39999389648438 : 0.39999389648438 : 0.4 17:0>>0.39999389648438 : 0.39999389648438 : 0.4 18:0>>0.39999389648438 : 0.39999389648438 : 0.4 19:1>>0.39999771118164 : 0.39999771118164 : 0.4 20:1>>0.39999961853027 : 0.39999961853027 : 0.4 21:0>>0.39999961853027 : 0.39999961853027 : 0.4 22:0>>0.39999961853027 : 0.39999961853027 : 0.4 23:1>>0.39999985694885 : 0.39999985694885 : 0.4 24:1>>0.39999997615814 : 0.39999997615814 : 0.4 25:0>>0.39999997615814 : 0.39999997615814 : 0.4 26:0>>0.39999997615814 : 0.39999997615814 : 0.4 27:1>>0.39999997615814 : 0.3999999910593 : 0.4 28:1>>0.40000000596046 : 0.39999999850988 : 0.4 29:0>>0.40000000596046 : 0.39999999850988 : 0.4 30:0>>0.40000000596046 : 0.39999999850988 : 0.4 31:1>>0.40000000596046 : 0.39999999944121 : 0.4 32:1>>0.40000000596046 : 0.39999999990687 : 0.41/2^24 までは設定した値がそのまま反映されています。
1/2^25 1/2^26 は加算なしで 1/2^27 では操作値を加算したにも関わらず値に変化が無くなっています。
さらに近似を求めてゆくと アルゴリズム上目標値の下からしか近似しないはずなのに 0.40000000596046 とわずかに上の値で安定してしまいます。 この値は直接 0.4を代入した時の誤差を含む値と同じです。
これは、数を打ってどういう動作か試してみるべき…
で、(途中省略) だいたい 1/2^26を下回る値をいれてもダメみたい… よく使用する各フレームレートで誤差が上側にでない最大の係数を調べてみると 1/2^24 みたい?
ここまでの値で近似すると有効数値下7桁程度の精度で目標値の下側に近似値がとれるのでその補正コードを作ってみました。
以下のコードを実行するとコンポアイテムに app.project.item(index).setFrames() メソッドが増設されます。
このメソッドでフレームをセットすると現在のフレームレートでフレーム数をオーバーしない長さの継続時間をセットします。
CompItem.prototype.setFrames = function(targetFrames) { //(1/2^n)を合成して近似値を求める var myTargetDuration=targetFrames/this.frameRate; var myDuration=myTargetDuration; var coc=new Array(); var replayCount=24;//24/25/29.97/30fpsで誤差の乗らない最大係数と思う… for (cO=0;cO<replayCount;cO++) { coc[cO]=Math.floor(myDuration); if(myTargetDuration%(1/Math.pow(2,cO))==0) { //割り切れたので終了 break }else{ myDuration=(myDuration%1)*2; } } myDuration=0;//使い終わったので再初期化して流用 for (c=0;c<coc.length;c++) { myDuration+=(1/Math.pow(2,c))*coc[c]; } this.duration=myDuration; return this.duration; } //動作確認用 app.project.item(1).setFrames(103);
こんなモノかな?風邪引いてるので細かい動作確認はマダです。 6.5のみ 7.0以降は同バグがFIXされているので不要。
さらに続報!係数変更だよー
色々とパターンを変えて試験してみました。 係数22だと処理するコマ数が増えた際に目標値上側の誤差が出ました。
係数を18まで下げると一応1200フレームまでの間で下側誤差に収まるようです。
もう少し徹底的に試験して、必要ならばフォールバックを組み込んだ新しいコードを出すことにします。 上の情報をご使用の方は、暫定的に係数を18まで下げてご使用下さい。
最終的な試験コードは、こちら
/* * 以下のコードを実行するとコンポアイテムに * setFrames() メソッドが増設されます。 * このメソッドはコンポのフレームをセットします。 * * 例: newDuration=app.project.item(1).setFrames(105); * * 現在のフレームレートでフレーム数をオーバーしない長さの継続時間をセットして * コンポにセットされた継続時間を返します。Nekomataya/kiyo 2006/07/19 */ var AEVersion=app.version.split(".")[0]*1+app.version.split(".")[1]*.1; alert(AEVersion); if(AEVersion<7.0) { CompItem.prototype.setFrames = function(targetFrames) { //(1/2^n)を合成して近似値を求める var myTargetDuration=targetFrames/this.frameRate; var replayCount=18;//初期係数設定値に誤差がある場合はこの値をフォールダウン //再帰処理ループ while(true) { var myDuration=myTargetDuration;//再初期化 var coc=new Array(); for (cO=0;cO<replayCount;cO++) { coc[cO]=Math.floor(myDuration); if(myTargetDuration%(1/Math.pow(2,cO))==0) { //割り切れたので終了 break; }else{ myDuration=(myDuration%1)*2; } } myDuration=0;//使い終わったので再初期化して流用 for (c=0;c<coc.length;c++) { myDuration+=(1/Math.pow(2,c))*coc[c]; } //コンポに時間を設定する this.duration=myDuration; //継続時間が設定値と異なる場合は、設定失敗なので係数を1つ下げて再度トライする if(this.duration!=myDuration){replayCount--;continue;}else{break;}; } return [myDuration,replayCount];//フォールダウン発生を検出する為にcount付きで返す } }else{ //AE7.0以降用同機能コード AE7以降は、同バグがFIXされている為上記のコードは副作用があるので注意 CompItem.prototype.setFrames = function(targetFrames) { this.duration= targetFrames / this.frameRate; return [this.duration,0]; } } //以上きっと最後の版と重い鯛 //試験コード //myAlert="フレームレート\tコマ//\t誤差====\継続時間\tフォールダウン\n"; fRts=[3,15,24,29.97,30,96];//フレームレートを設定 // var total =0; var testCount =0; var falldownCount =0; var fdMin =18; var max =0; var min =1; var gosa=0; var stack =new Array(); var myResult =",フレームレート,フォールダウン件数,フォールダウン最小値,最大誤差,最小誤差(0以外),各レート内平均誤差(0含む)\n"; for (frid=0; frid < fRts.length;frid++) { testCount =0; falldownCount =0; fdMin =18; max =0; min =1; gosa =0; total =0; fr=fRts[frid]; app.project.item(1).frameRate=fr; // 各戟[トで1から3600フレームまで試験 for(f =1;f<=3600;f++) { result=app.project.item(1).setFrames(f);//セット //フォールダウン発生 if (result[1]<18){falldownCount++;if(fdMin>result[1]){fdMin=result[1];};}; //フレーム継続時間にたいする誤差を最大・最小・平均で拾う gosa=100*(f/fr-result[0])/(1/fr);//誤差を"%"で if(max<gosa)max=gosa; if((min>gosa) && (gosa!=0))min=gosa; total+=gosa; testCount ++;//トータル・サンプル数 } stack[frid]=[fr,falldownCount,fdMin,max,min,(total/testCount)]; myResult +=","+stack[frid].toString()+"\n"; //,フレームレート,フォールダウン件数,最大誤差,最小誤差(0以外),各レート内平均誤差(0含む) } alert(myResult);気が向いた方は試験コードをおためしください。(現在の試験コードは実行すると10分くらい計算時間がかかるのでご注意。)
フォールダウンフィードバック補正をお試しコードに組み込んであります。 設定値が、上側誤差を含むと係数を下げて処理をやり直します。
…やっぱり初期係数は、18かな? 20くらいでも良いか?
'AE7.0でも試験してみましたが''
あはは、ガンガンずれます。…実用時は危険なのでこのコードAE7では実行しないようにしましょう…
どうもAE7…「きちんと数値を認識」しているのではなくて「ある程度まで近似値になった指定を無理やりフレームの変化点にする」処置をしているみたいです。でもバグフィックス済なのでこのコードは不要
フォールダウンの最小値つきで検証してみる。
係数24で開始
フレームレート | フォールダウン件数 | フォールダウン最小値 | 最大誤差 | 最小誤差(0以外) | 各レート内平均誤差(0含む) |
3 | 2394 | 14 | 0.02441406247726 | 0.00001192092894 | 0.00526259342829 |
15 | 3298 | 17 | 0.02136230469318 | 0.00001192092891 | 0.00688364108404 |
24 | 2352 | 17 | 0.02441406247726 | 0.00009536743155 | 0.00526301066081 |
29.97 | 3362 | 18 | 0.0371322631978 | 0.00005960464479 | 0.01470895291053 |
30 | 3236 | 18 | 0.02136230469318 | 0.00002384185782 | 0.00688433647156 |
96 | 2208 | 19 | 0.02441406247726 | 0.00038146972621 | 0.00526936848958 |
係数22で開始
フレームレート | フォールダウン件数 | フォールダウン最小値 | 最大誤差 | 最小誤差(0以外) | 各レート内平均誤差(0含む) |
3 | 2376 | 14 | 0.02441406247726 | 0.00004768371578 | 0.00526269276937 |
15 | 3112 | 17 | 0.02136230469318 | 0.00004768371564 | 0.00688711802165 |
24 | 2208 | 17 | 0.02441406247726 | 0.00038146972621 | 0.00526936848958 |
29.97 | 2897 | 18 | 0.0371322631978 | 0.00005960464479 | 0.01472244978629 |
30 | 2864 | 18 | 0.02136230469318 | 0.00009536743129 | 0.00689824422201 |
96 | 1632 | 19 | 0.02441406247726 | 0.00152587890483 | 0.00537109375 |
係数20で開始
フレームレート | フォールダウン件数 | フォールダウン最小値 | 最大誤差 | 最小誤差(0以外) | 各レート内平均誤差(0含む) |
3 | 2304 | 14 | 0.02441406247726 | 0.0001907348631 | 0.00526428222656 |
15 | 2384 | 17 | 0.02136230469318 | 0.00019073486257 | 0.00694274902344 |
24 | 1632 | 17 | 0.02441406247726 | 0.00152587890483 | 0.00537109375 |
29.97 | 1741 | 18 | 0.0371322631978 | 0.00023841857915 | 0.01496142388069 |
30 | 1680 | 18 | 0.02136230469318 | 0.00038146972514 | 0.00712076822917 |
96 | 176 | 19 | 0.02441406247726 | 0.00610351561932 | 0.00699869791667 |
係数18で開始
フレームレート | フォールダウン件数 | フォールダウン最小値 | 最大誤差 | 最小誤差(0以外) | 各レート内平均誤差(0含む) |
3 | 2016 | 14 | 0.02441406247726 | 0.00076293945241 | 0.00528971354167 |
15 | 784 | 17 | 0.02136230469318 | 0.00076293945028 | 0.00783284505208 |
24 | 176 | 17 | 0.02441406247726 | 0.00610351561932 | 0.00699869791667 |
29.97 | 0 | 18 | 0.0371322631978 | 0.00095367431661 | 0.01878818512641 |
30 | 0 | 18 | 0.02136230469318 | 0.00152587890057 | 0.01068115234375 |
96 | 0 | 18 | 0.04882812502274 | 0.02441406247726 | 0.0244140625 |
ううむ、最大誤差0.05%でかつフォールダウンが激減するので、やっぱり初期係数は18に決定!
こんどこそ最終コード
nas ライブラリには次の版で組み込みます。/* * 以下のコードを実行するとコンポアイテムに * setFrames() メソッドが増設されます。 * このメソッドはコンポのフレームをセットします。 * * 例: newDuration=app.project.item(1).setFrames(105); * * 現在のフレームレートでフレーム数をオーバーしない長さの継続時間をセットして * コンポにセットされた継続時間を返します。Nekomataya/kiyo 2006/07/20 *このコードを、AE 7.0以降で実行すると望ましくない副作用が有ります。 *バージョン分岐して7.0以降の環境でこのコードが実行されないよう注意してください。 */ var AEVersion=app.version.split(".")[0]*1+app.version.split(".")[1]*.1; if(AEVersion<7.0) { CompItem.prototype.setFrames = function(targetFrames) { //(1/2^n)を合成して近似値を求める var myTargetDuration=targetFrames/this.frameRate; var replayCount=18;//初期係数設定値に誤差がある場合はこの値をフォールダウン //再帰処理ループ while(true) { var myDuration=myTargetDuration;//再初期化 var coc=new Array(); for (cO=0;cO<replayCount;cO++) { coc[cO]=Math.floor(myDuration); if(myTargetDuration%(1/Math.pow(2,cO))==0) { //割り切れたので終了 break; }else{ myDuration=(myDuration%1)*2; } } myDuration=0;//使い終わったので再初期化して流用 for (c=0;c<coc.length;c++) { myDuration+=(1/Math.pow(2,c))*coc[c]; } //コンポに時間を設定する this.duration=myDuration; //継続時間が設定値と異なる場合は、設定失敗なので係数を1つ下げて再度トライする if(this.duration!=myDuration){replayCount--;continue;}else{break;}; } return this.duration; } }else{ //AE7.0以降用同機能コード AE7以降は、同バグがFIXされている為上記のコードは副作用があるので注意 CompItem.prototype.setFrames = function(targetFrames) { this.duration= targetFrames / this.frameRate; return this.duration; } } //以上きっと最後の版だと思います。より精度の必要な方は計算時間がかかりますが初期係数を24とかにしてみてください…あまり実用上は変化なさそうですけど
これにて、この件はオシマイ
じゃあね
バグを見つけたヒトは、ご自由にこのページに書き込んでください。 よろしくでーす
Powered by YukiWiki 2.1.2a / Modified by Nekomataya.