|
發表於 2013年3月5日 06:50 PM
|
顯示全部樓層
回復 930樓 suvsuvsuv 的帖子
關於 混控曲線(curves.c)中 多點直線( s16 interpolate(struct Curve *curve, s32 value) ) 的 "精度" 與 "偏差".
(1) 精度(分辨率) :
(1.1) interpolate() 函式
- 傳回值: "return PCT_TO_RANGE(curve->points[num_points-1]);"
- 範圍: CHAN_MIN_VALUE~CHAN_MAX_VALUE 即 -10000 ~ +10000
複製代碼 PCT_TO_RANGE() 的功能為 放大 100倍,
因此 傳回值為 : -10000, -10100, -10200, -10300 ... +9800, +9900, +10000.
相當於只有 200個刻度值 !!
(2) 偏差 :
(2.1) interpolate() 函式
- s32 step = 2 * 10000 / (num_points - 1) ;
- s32 pos1 = PCT_TO_RANGE(x / 100);
- s32 pos2 = PCT_TO_RANGE((x + step) / 100);
複製代碼 用step作為分隔每個區間的大小.
例如: 7點直線 則分成6個區間, 11點直線 則分成10個區間, 即(num_points-1)個區間.
其中: 7 與13點 直線 分成 6 與 12 個區間, 會遇到 除3的因子 無法整除而捨棄小數(只取整數).
並且 pos1與pos2又被 除100再乘100, 相當於捨棄最後兩位數.
當 7 與13點直線 時, 這個step用來逐次做為區間分隔, 逐次加乘又造成 區間偏差的積累.
最後一個區間只到 +9900 (偏差100).
也因此才會在 "for迴圈之外" 有此指令 "return PCT_TO_RANGE(curve->points[num_points-1]);"
(1.2) 建議 採用 先放大 100倍 "100*curve->points[ i ]" 計算後將值傳回, 讓精度回復 (1個刻度值: -10000~+10000).
- ----- curves.c --- interpolate() -----
- s32 tmp = (value-pos1)* 100*(curve->points[i+1] - curve->points) / (pos2-pos1) + 100*curve->points;
- return tmp;
複製代碼 (2.2) 建議 減少區間偏差 方式:
(2.2.1) 恢復最後兩位數. 並放棄 step , 每次都計算 pos1與pos2區間.
- ----- curves.c --- interpolate() -----
- s32 pos1 = -10000 + i * 2 * 10000 / (num_points - 1) ;
- s32 pos2 = -10000 + (i+1) * 2 * 10000 / (num_points - 1) ;
複製代碼 則不需要 "for迴圈之外" 的指令 "return PCT_TO_RANGE(curve->points[num_points-1]);"
(2.2.2) 另一個較簡易的方式 只 恢復最後兩位數, 仍採用step計算 pos1與pos2區間.
- ----- curves.c --- interpolate() -----
- s32 pos1 = x;
- s32 pos2 = x + step;
複製代碼 這樣還是會有偏差, 但
7點直線最後一個區間可到 +9998 (偏差2).
13點直線最後一個區間可到 +9992 (偏差8).
還是需要 "for迴圈之外" 的指令 "return PCT_TO_RANGE(curve->points[num_points-1]);"
[ 本帖最後由 hmjack2008 於 2013年3月5日 06:56 PM 編輯 ] |
|