int contemplate_data(unsigned int absolute, double skew, double errorbar, int freq) { /* Here is the actual phase lock loop. * Need to keep a ring buffer of points to make a rational * decision how to proceed. if (debug) print a lot. */ static int rp=0, valid=0; int both_sides_now=0; int j, n, c, max_avail, min_avail, dinit; int nextj=0; /* initialization not needed; but gcc can't figure out my logic */ double cum; struct _seg check, save_min, save_max; double last_slope; int delta_freq; double delta_f; int inconsistent=0, max_imax, max_imin=0, min_imax, min_imin=0; int computed_freq=freq; if (debug) printf("xontemplate %u %.1f %.1f %d\n",absolute,skew,errorbar,freq); d_ring[rp].absolute = absolute; d_ring[rp].skew = skew; d_ring[rp].errorbar = errorbar - 800.0; /* quick hack to speed things up */ d_ring[rp].freq = freq; if (valid<RING_SIZE) ++valid; if (valid==RING_SIZE) { /* * Pass 1: correct for wandering freq's */ cum = 0.0; if (debug) printf("\n"); for (j=rp; ; j=n) { d_ring[j].s.s.max = d_ring[j].skew - cum + d_ring[j].errorbar; d_ring[j].s.s.min = d_ring[j].skew - cum - d_ring[j].errorbar; if (debug) printf("hist %d %d %f %f %f\n",j,d_ring[j].absolute-absolute, cum,d_ring[j].s.s.min,d_ring[j].s.s.max); n=next_dn(j); if (n == rp) break; /* Assume the freq change took place immediately after * the data was taken; this is valid for the case where * this program was responsible for the change. */ cum = cum + (d_ring[j].absolute-d_ring[n].absolute) * (double)(d_ring[j].freq-freq)/65536; } /* * Pass 2: find the convex down envelope of s.max, composed of * line segments in s.max vs. absolute space, which are * points in freq vs. dt space. Find points in order of increasing * slope == freq */ dinit=1; last_slope=-100; for (c=1, j=next_up(rp); ; j=nextj) { nextj = search(rp, j, 1, 1, 0, &maxseg[c]); search(rp, j, 0, 1, 1, &check); if (check.slope < maxseg[c].slope && check.slope > last_slope && (dinit || check.slope < save_min.slope)) {dinit=0; save_min=check; } if (debug) printf("maxseg[%d] = %f *x+ %f\n", c, maxseg[c].slope, maxseg[c].offset); last_slope = maxseg[c].slope; c++; if (nextj == rp) break; } if (dinit==1) inconsistent=1; if (debug && dinit==0) printf ("mincross %f *x+ %f\n", save_min.slope, save_min.offset); max_avail=c; /* * Pass 3: find the convex up envelope of s.min, composed of * line segments in s.min vs. absolute space, which are * points in freq vs. dt space. These points are found in * order of decreasing slope. */ dinit=1; last_slope=+100.0; for (c=1, j=next_up(rp); ; j=nextj) { nextj = search(rp, j, 0, 0, 1, &minseg[c]); search(rp, j, 1, 0, 0, &check); if (check.slope > minseg[c].slope && check.slope < last_slope && (dinit || check.slope < save_max.slope)) {dinit=0; save_max=check; } if (debug) printf("minseg[%d] = %f *x+ %f\n", c, minseg[c].slope, minseg[c].offset); last_slope = minseg[c].slope; c++; if (nextj == rp) break; } if (dinit==1) inconsistent=1; if (debug && dinit==0) printf ("maxcross %f *x+ %f\n", save_max.slope, save_max.offset); min_avail=c; /* * Pass 4: splice together the convex polygon that forms * the envelope of slope/offset coordinates that are consistent * with the observed data. The order of calls to polygon_point * doesn't matter for the frequency shift determination, but * the order chosen is nice for visual display. */ if (!inconsistent) { polygon_reset(); polygon_point(&save_min); for (dinit=1, c=1; c<max_avail; c++) { if (dinit && maxseg[c].slope > save_min.slope) { max_imin = c-1; maxseg[max_imin] = save_min; dinit = 0; } if (maxseg[c].slope > save_max.slope) break; if (dinit==0) polygon_point(&maxseg[c]); } if (dinit && debug) printf("found maxseg vs. save_min inconsistency\n"); if (dinit) inconsistent=1; max_imax = c; maxseg[max_imax] = save_max; polygon_point(&save_max); for (dinit=1, c=1; c<min_avail; c++) { if (dinit && minseg[c].slope < save_max.slope) { max_imin = c-1; minseg[min_imin] = save_max; dinit = 0; } if (minseg[c].slope < save_min.slope) break; if (dinit==0) polygon_point(&minseg[c]); } if (dinit && debug) printf("found minseg vs. save_max inconsistency\n"); if (dinit) inconsistent=1; min_imax = c; minseg[min_imax] = save_max; /* not needed for analysis, but shouldn't hurt either */ if (debug) polygon_point(&save_min); } /* !inconsistent */ /* * Pass 5: decide on a new freq */ if (inconsistent) { printf("# inconsistent\n"); } else { delta_f = find_df(&both_sides_now); if (debug) printf("find_df() = %e\n", delta_f); delta_f += find_df_center(&save_min,&save_max, delta_f); delta_freq = delta_f*65536+.5; if (debug) printf("delta_f %f delta_freq %d bsn %d\n", delta_f, delta_freq, both_sides_now); computed_freq -= delta_freq; printf ("# box [( %.3f , %.1f ) ", save_min.slope, save_min.offset); printf ( " ( %.3f , %.1f )] ", save_max.slope, save_max.offset); printf (" delta_f %.3f computed_freq %d\n", delta_f, computed_freq); if (computed_freq < -6000000) computed_freq=-6000000; if (computed_freq > 6000000) computed_freq= 6000000; } } rp = (rp+1)%RING_SIZE; return computed_freq; }
static gboolean process (GeglOperation *operation, GeglBuffer *input, GeglBuffer *output, const GeglRectangle *result, gint level) { GeglChantO *o = GEGL_CHANT_PROPERTIES (operation); GeglOperationAreaFilter *op_area = GEGL_OPERATION_AREA_FILTER (operation); GeglRectangle boundary = get_effective_area (operation); GeglRectangle extended; const Babl *format = babl_format ("RGBA float"); GRand *gr = g_rand_new_with_seed (o->seed); gfloat color[4]; gint cols, rows, num_tiles, count; gint *random_indices; gfloat *dst_buf; Polygon poly; gint i; extended.x = CLAMP (result->x - op_area->left, boundary.x, boundary.x + boundary.width); extended.width = CLAMP (result->width + op_area->left + op_area->right, 0, boundary.width); extended.y = CLAMP (result->y - op_area->top, boundary.y, boundary.y + boundary.width); extended.height = CLAMP (result->height + op_area->top + op_area->bottom, 0, boundary.height); dst_buf = g_new0 (gfloat, extended.width * extended.height * 4); cols = (result->width + o->tile_size - 1) / o->tile_size; rows = (result->height + o->tile_size - 1) / o->tile_size; num_tiles = (rows + 1) * (cols + 1); random_indices = g_new0 (gint, num_tiles); for (i = 0; i < num_tiles; i++) random_indices[i] = i; randomize_indices (num_tiles, random_indices, gr); for (count = 0; count < num_tiles; count++) { gint i, j, ix, iy; gdouble x, y, width, height, theta; i = random_indices[count] / (cols + 1); j = random_indices[count] % (cols + 1); x = j * o->tile_size + (o->tile_size / 4.0) - g_rand_double_range (gr, 0, (o->tile_size /2.0)) + result->x; y = i * o->tile_size + (o->tile_size / 4.0) - g_rand_double_range (gr, 0, (o->tile_size /2.0)) + result->y; width = (o->tile_size + g_rand_double_range (gr, -o->tile_size / 8.0, o->tile_size / 8.0)) * o->tile_saturation; height = (o->tile_size + g_rand_double_range (gr, -o->tile_size / 8.0, o->tile_size / 8.0)) * o->tile_saturation; theta = g_rand_double_range (gr, 0, 2 * G_PI); polygon_reset (&poly); polygon_add_point (&poly, -width / 2.0, -height / 2.0); polygon_add_point (&poly, width / 2.0, -height / 2.0); polygon_add_point (&poly, width / 2.0, height / 2.0); polygon_add_point (&poly, -width / 2.0, height / 2.0); polygon_rotate (&poly, theta); polygon_translate (&poly, x, y); ix = CLAMP (x, boundary.x, boundary.x + boundary.width - 1); iy = CLAMP (y, boundary.y, boundary.y + boundary.height - 1); gegl_buffer_sample (input, ix, iy, NULL, color, format, GEGL_SAMPLER_NEAREST, GEGL_ABYSS_NONE); fill_poly_color (&poly, &extended, &boundary, dst_buf, color); } gegl_buffer_set (output, &extended, 0, format, dst_buf, GEGL_AUTO_ROWSTRIDE); g_free (dst_buf); g_free (random_indices); g_free (gr); return TRUE; }