void setCurve(uint8_t c, const pm_int8_t ar[]) { int8_t * cv = curveAddress(c); for (uint8_t i=0; i<5; i++) { cv[i] = pgm_read_byte(&ar[i]); } }
CurveInfo curveInfo(uint8_t idx) { CurveInfo result; result.crv = curveAddress(idx); int8_t *next = curveAddress(idx+1); uint8_t size = next - result.crv; if ((size & 1) == 0) { result.points = (size / 2) + 1; result.custom = true; } else { result.points = size; result.custom = false; } return result; }
int intpol(int x, uint8_t idx) // -100, -75, -50, -25, 0 ,25 ,50, 75, 100 { #if defined(XCURVES) CurveInfo &crv = g_model.curves[idx]; int8_t *points = curveAddress(idx); uint8_t count = crv.points+5; bool custom = (crv.type == CURVE_TYPE_CUSTOM); #else CurveInfo crv = curveInfo(idx); int8_t *points = crv.crv; uint8_t count = crv.points; bool custom = crv.custom; #endif int16_t erg = 0; x += RESXu; if (x <= 0) { erg = (int16_t)points[0] * (RESX/4); } else if (x >= (RESX*2)) { erg = (int16_t)points[count-1] * (RESX/4); } else { uint16_t a=0, b=0; uint8_t i; if (custom) { for (i=0; i<count-1; i++) { a = b; b = (i==count-2 ? 2*RESX : RESX + calc100toRESX(points[count+i])); if ((uint16_t)x<=b) break; } } else { uint16_t d = (RESX * 2) / (count-1); i = (uint16_t)x / d; a = i * d; b = a + d; } erg = (int16_t)points[i]*(RESX/4) + ((int32_t)(x-a) * (points[i+1]-points[i]) * (RESX/4)) / ((b-a)); } return erg / 25; // 100*D5/RESX; }
/* The following is a hermite cubic spline. The basis functions can be found here: http://en.wikipedia.org/wiki/Cubic_Hermite_spline The tangents are computed via the 'cubic monotone' rules (allowing for local-maxima) */ int16_t hermite_spline(int16_t x, uint8_t idx) { CurveInfo &crv = g_model.curves[idx]; int8_t *points = curveAddress(idx); uint8_t count = crv.points+5; bool custom = (crv.type == CURVE_TYPE_CUSTOM); if (x < -RESX) x = -RESX; else if (x > RESX) x = RESX; for (int i=0; i<count-1; i++) { s32 p0x, p3x; if (custom) { p0x = (i>0 ? calc100toRESX(points[count+i-1]) : -RESX); p3x = (i<count-2 ? calc100toRESX(points[count+i]) : RESX); } else { p0x = -RESX + (i*2*RESX)/(count-1); p3x = -RESX + ((i+1)*2*RESX)/(count-1); } if (x >= p0x && x <= p3x) { s32 p0y = calc100toRESX(points[i]); s32 p3y = calc100toRESX(points[i+1]); s32 m0 = compute_tangent(&crv, points, i); s32 m3 = compute_tangent(&crv, points, i+1); s32 y; s32 h = p3x - p0x; s32 t = (h > 0 ? (MMULT * (x - p0x)) / h : 0); s32 t2 = t * t / MMULT; s32 t3 = t2 * t / MMULT; s32 h00 = 2*t3 - 3*t2 + MMULT; s32 h10 = t3 - 2*t2 + t; s32 h01 = -2*t3 + 3*t2; s32 h11 = t3 - t2; y = p0y * h00 + h * (m0 * h10 / MMULT) + p3y * h01 + h * (m3 * h11 / MMULT); y /= MMULT; return y; } } return 0; }
static int luaModelGetCurve(lua_State *L) { unsigned int idx = luaL_checkunsigned(L, 1); if (idx < MAX_CURVES) { CurveInfo & curveInfo = g_model.curves[idx]; lua_newtable(L); lua_pushtablezstring(L, "name", g_model.curveNames[idx]); lua_pushtableinteger(L, "type", curveInfo.type); lua_pushtableboolean(L, "smooth", curveInfo.smooth); lua_pushtableinteger(L, "points", curveInfo.points+5); lua_pushstring(L, "y"); lua_newtable(L); int8_t * point = curveAddress(idx); for (int i=0; i<curveInfo.points+5; i++) { lua_pushinteger(L, i); lua_pushinteger(L, *point++); lua_settable(L, -3); } lua_settable(L, -3); if (curveInfo.type == CURVE_TYPE_CUSTOM) { lua_pushstring(L, "x"); lua_newtable(L); lua_pushinteger(L, 0); lua_pushinteger(L, 0); lua_settable(L, -3); for (int i=0; i<curveInfo.points+3; i++) { lua_pushinteger(L, i+1); lua_pushinteger(L, *point++); lua_settable(L, -3); } lua_pushinteger(L, curveInfo.points+4); lua_pushinteger(L, 100); lua_settable(L, -3); lua_settable(L, -3); } } else { lua_pushnil(L); } return 1; }