precise timing control of double-buffering flip



Hello,

I'm searching a way to ask the time of double-buffering flip.
In order to make a kind of oscilloscope.

At any time t_now, I can access data corresponding to time values before
t_last, where (t_now - t_last) is always < tau_delay_1
I want to draw points using gdk_draw_points
and I know that I can compute them in a time less than tau_delay_2.

Then at time t_now, I want to:
1) compute and draw points using data at time (t_now - tau_delay_1). I know to do that
2) see the resulting image at time t_now + tau_delay_2. I don't know
to do that. Please can you help me.

The following program should show a sinusoidal line slowly scrolling to the left. It works, but it suffer a small jitter due to the lack of timing control around
gdk_window_process_updates i think.
Also, if the system becomes heavy loaded, the image freeze (this is normal
if tau_delay_2 has a too small value),
and then all the successive images are shown in an accelerated way
I would prefer that out of time images will be not shown.


#include <stdlib.h>
#include <stdio.h>
#include <math.h>
#include <gtk/gtk.h>

#define NPOINTS 800
#define NSAMP 2000 /*  > NPOINTS + tau_sync/tau_samp */

GTimer *timer;
GdkPoint points[NPOINTS];

struct meas {
   double samp[NSAMP];
   double t_samp;
} data;

double tau_samp = 1.0/44100.0;
double f_sound = 440.1;
double tau_sync = 1.0/440.0;

double min_samp_delay = 1e99;
double max_samp_delay = 0.0;
double max_draw_delay = 0.0;

double timer_elapsed () {
   ulong dummy;
   return g_timer_elapsed (timer, &dummy);
}

gboolean sample_generator () {
   int i;
   data.t_samp = timer_elapsed ();
   double delay;

   for (i=0; i<NSAMP; i++) {
data.samp[i] = 50.0 * sin (2.0 * M_PI * fmod (f_sound * (data.t_samp - (NSAMP - 1 - i)*tau_samp), 1.0));
   }
   delay = timer_elapsed () - data.t_samp;
   if (delay > max_samp_delay) max_samp_delay = delay;
   if (delay < min_samp_delay) min_samp_delay = delay;
   return TRUE;
}

double compute_points () {
   double t = timer_elapsed ();
   double dt;
   int i, ishift;

   dt = data.t_samp - tau_sync * floor (t / tau_sync);
   while (dt < 0.0) dt += tau_sync;
   ishift = NSAMP - NPOINTS - (int) (dt / tau_samp);
   if (NPOINTS + ishift > NSAMP) {
   fprintf (stderr, "NSAMP too low\n");
   abort ();
   }
   for (i = 0; i < NPOINTS; i++) {
   points[i].x = i;
   points[i].y = 75 + (int) data.samp[i + ishift];
   }
   return t;
}

gboolean draw_callback (GtkWidget *widget, GdkEventExpose *event, gpointer data) {
   gdk_draw_points(widget->window,
           widget->style->fg_gc[GTK_WIDGET_STATE (widget)],
points, NPOINTS); return TRUE;
}

gboolean recompute_points(gpointer pDrawingArea) {
   GtkWidget *widget;
   GdkRegion *region;
   double t, delay;

   widget = GTK_WIDGET (pDrawingArea);
   if (!widget->window) return;
   region = gdk_drawable_get_clip_region (widget->window);
gdk_window_invalidate_region (widget->window, region, TRUE);
   t = compute_points ();
   gdk_window_process_updates (widget->window, TRUE);

   delay = timer_elapsed () - t;
   if (delay > max_draw_delay) max_draw_delay = delay;

   return TRUE;
}

gboolean bye () {
   fprintf (stderr, "Min. samp delay = %.6lf\n", min_samp_delay);
   fprintf (stderr, "Max. samp delay = %.6lf\n", max_samp_delay);
   fprintf (stderr, "Max. draw delay = %.6lf\n", max_draw_delay);
   gtk_main_quit ();
   return TRUE;
}

int main(int argc, char **argv) {
   GtkWidget *pWindow;
   GtkWidget *pDrawingArea;

   gtk_init(&argc,&argv);

   pWindow = gtk_window_new(GTK_WINDOW_TOPLEVEL);
g_signal_connect(G_OBJECT(pWindow), "destroy", G_CALLBACK(gtk_main_quit), NULL);

   pDrawingArea = gtk_drawing_area_new();
   gtk_widget_set_size_request(pDrawingArea, 800,150);
g_signal_connect (G_OBJECT (pDrawingArea), "expose_event", G_CALLBACK (draw_callback), NULL);

   gtk_container_add(GTK_CONTAINER(pWindow), pDrawingArea);

   timer = g_timer_new ();
   sample_generator ();
   compute_points ();
   gtk_widget_show_all(pWindow);

   g_timeout_add(50, recompute_points, (gpointer) pDrawingArea);
   g_timeout_add(31, sample_generator, NULL);
   g_timeout_add(10000, bye, NULL);

   gtk_main();

   return EXIT_SUCCESS;
}


--
FP




[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]