diff --git a/gst/monoscope/convolve.c b/gst/monoscope/convolve.c index 913773431e..35f18ece50 100644 --- a/gst/monoscope/convolve.c +++ b/gst/monoscope/convolve.c @@ -83,14 +83,13 @@ typedef union stack_entry_s } stack_entry; -#define STACK_SIZE (CONVOLVE_DEPTH * 3) - struct _struct_convolve_state { - double left[CONVOLVE_BIG]; - double right[CONVOLVE_SMALL * 3]; - double scratch[CONVOLVE_SMALL * 3]; - stack_entry stack[STACK_SIZE + 1]; + int depth, small, big, stack_size; + double *left; + double *right; + double *scratch; + stack_entry *stack; }; /* @@ -100,9 +99,20 @@ struct _struct_convolve_state * The pointer should be freed when it is finished with, by convolve_close(). */ convolve_state * -convolve_init (void) +convolve_init (int depth) { - return (convolve_state *) calloc (1, sizeof (convolve_state)); + convolve_state *state; + + state = malloc (sizeof (convolve_state)); + state->depth = depth; + state->small = (1 << depth); + state->big = (2 << depth); + state->stack_size = depth * 3; + state->left = calloc (state->big, sizeof (double)); + state->right = calloc (state->small * 3, sizeof (double)); + state->scratch = calloc (state->small * 3, sizeof (double)); + state->stack = calloc (state->stack_size + 1, sizeof (stack_entry)); + return state; } /* @@ -111,6 +121,10 @@ convolve_init (void) void convolve_close (convolve_state * state) { + free (state->left); + free (state->right); + free (state->scratch); + free (state->stack); free (state); } @@ -273,13 +287,13 @@ convolve_match (const int *lastchoice, const short *input, double *left = state->left; double *right = state->right; double *scratch = state->scratch; - stack_entry *top = state->stack + (STACK_SIZE - 1); + stack_entry *top = state->stack + (state->stack_size - 1); - for (i = 0; i < CONVOLVE_BIG; i++) + for (i = 0; i < state->big; i++) left[i] = input[i]; - for (i = 0; i < CONVOLVE_SMALL; i++) { - double a = lastchoice[(CONVOLVE_SMALL - 1) - i]; + for (i = 0; i < state->small; i++) { + double a = lastchoice[(state->small - 1) - i]; right[i] = a; avg += a; @@ -288,32 +302,32 @@ convolve_match (const int *lastchoice, const short *input, /* We adjust the smaller of the two input arrays to have average * value 0. This makes the eventual result insensitive to both * constant offsets and positive multipliers of the inputs. */ - avg /= CONVOLVE_SMALL; - for (i = 0; i < CONVOLVE_SMALL; i++) + avg /= state->small; + for (i = 0; i < state->small; i++) right[i] -= avg; /* End-of-stack marker. */ top[1].b.null = scratch; top[1].b.main = NULL; - /* The low SMALLxSMALL, of which we want the high outputs. */ + /* The low (small x small) part, of which we want the high outputs. */ top->v.left = left; top->v.right = right; - top->v.out = right + CONVOLVE_SMALL; - convolve_run (top, CONVOLVE_SMALL, scratch); + top->v.out = right + state->small; + convolve_run (top, state->small, scratch); - /* The high SMALLxSMALL, of which we want the low outputs. */ - top->v.left = left + CONVOLVE_SMALL; + /* The high (small x small) part, of which we want the low outputs. */ + top->v.left = left + state->small; top->v.right = right; top->v.out = right; - convolve_run (top, CONVOLVE_SMALL, scratch); + convolve_run (top, state->small, scratch); /* Now find the best position amoungs this. Apart from the first * and last, the required convolution outputs are formed by adding * outputs from the two convolutions above. */ - best = right[CONVOLVE_BIG - 1]; - right[CONVOLVE_BIG + CONVOLVE_SMALL + 1] = 0; + best = right[state->big - 1]; + right[state->big + state->small - 1] = 0; p = -1; - for (i = 0; i < CONVOLVE_SMALL; i++) { - double a = right[i] + right[i + CONVOLVE_BIG]; + for (i = 0; i < state->small; i++) { + double a = right[i] + right[i + state->big]; if (a > best) { best = a; @@ -326,18 +340,18 @@ convolve_match (const int *lastchoice, const short *input, { /* This is some debugging code... */ best = 0; - for (i = 0; i < CONVOLVE_SMALL; i++) + for (i = 0; i < state->small; i++) best += ((double) input[i + p]) * ((double) lastchoice[i] - avg); - for (i = 0; i <= CONVOLVE_SMALL; i++) { + for (i = 0; i <= state->small; i++) { double tot = 0; unsigned int j; - for (j = 0; j < CONVOLVE_SMALL; j++) + for (j = 0; j < state->small; j++) tot += ((double) input[i + j]) * ((double) lastchoice[j] - avg); if (tot > best) printf ("(%i)", i); - if (tot != left[i + (CONVOLVE_SMALL - 1)]) + if (tot != left[i + (state->small - 1)]) printf ("!"); } diff --git a/gst/monoscope/convolve.h b/gst/monoscope/convolve.h index 64da744452..d6a7f05cca 100644 --- a/gst/monoscope/convolve.h +++ b/gst/monoscope/convolve.h @@ -31,16 +31,10 @@ extern "C" { #endif -/* convolve_match takes two blocks, one twice the size of the other. The - * sizes of these are CONVOLVE_BIG and CONVOLVE_SMALL respectively. */ -#define CONVOLVE_DEPTH 8 -#define CONVOLVE_SMALL (1 << CONVOLVE_DEPTH) -#define CONVOLVE_BIG (CONVOLVE_SMALL * 2) - -/* Convolution stuff */ +/* Convolution state */ typedef struct _struct_convolve_state convolve_state; -convolve_state *convolve_init (void); +convolve_state *convolve_init (int depth); void convolve_close (convolve_state * state); int convolve_match (const int * lastchoice, diff --git a/gst/monoscope/monoscope.c b/gst/monoscope/monoscope.c index e0c7651657..9606a34b06 100644 --- a/gst/monoscope/monoscope.c +++ b/gst/monoscope/monoscope.c @@ -63,12 +63,12 @@ monoscope_init (guint32 resx, guint32 resy) struct monoscope_state *stateptr; /* I didn't program monoscope to only do 256*128, but it works that way */ - g_return_val_if_fail (resx == 256, 0); - g_return_val_if_fail (resy == 128, 0); + g_return_val_if_fail (resx == scope_width, 0); + g_return_val_if_fail (resy == scope_height, 0); stateptr = calloc (1, sizeof (struct monoscope_state)); if (stateptr == 0) return 0; - stateptr->cstate = convolve_init (); + stateptr->cstate = convolve_init (convolver_depth); colors_init (stateptr->colors); return stateptr; } @@ -81,9 +81,8 @@ monoscope_close (struct monoscope_state *stateptr) } guint32 * -monoscope_update (struct monoscope_state *stateptr, gint16 data[512]) +monoscope_update (struct monoscope_state *stateptr, gint16 data[convolver_big]) { - /* Note that CONVOLVE_BIG must == data size here, ie 512. */ /* Really, we want samples evenly spread over the available data. * Just taking a continuous chunk will do for now, though. */ int i; @@ -95,14 +94,14 @@ monoscope_update (struct monoscope_state *stateptr, gint16 data[512]) int factor; int val; int max = 1; - short *thisEq = stateptr->copyEq; + gint16 *thisEq = stateptr->copyEq; - memcpy (thisEq, data, sizeof (short) * CONVOLVE_BIG); - val = convolve_match (stateptr->avgEq, stateptr->copyEq, stateptr->cstate); + memcpy (thisEq, data, sizeof (short) * convolver_big); + val = convolve_match (stateptr->avgEq, thisEq, stateptr->cstate); thisEq += val; - memset (stateptr->display, 0, 256 * 128 * sizeof (guint32)); - for (i = 0; i < 256; i++) { + memset (stateptr->display, 0, scope_width * scope_height * sizeof (guint32)); + for (i = 0; i < convolver_small; i++) { foo = thisEq[i] + (stateptr->avgEq[i] >> 1); stateptr->avgEq[i] = foo; if (foo < 0) diff --git a/gst/monoscope/monoscope.h b/gst/monoscope/monoscope.h index 8e7d759137..3e79fe49de 100644 --- a/gst/monoscope/monoscope.h +++ b/gst/monoscope/monoscope.h @@ -4,21 +4,24 @@ #include #include "convolve.h" +#define convolver_depth 8 +#define convolver_small (1 << convolver_depth) +#define convolver_big (2 << convolver_depth) #define scope_width 256 #define scope_height 128 struct monoscope_state { - gint16 copyEq[CONVOLVE_BIG]; - int avgEq[CONVOLVE_SMALL]; /* a running average of the last few. */ - int avgMax; /* running average of max sample. */ - guint32 display[(scope_width + 1) * (scope_height + 1)]; + short copyEq[convolver_big]; + int avgEq[convolver_small]; /* a running average of the last few. */ + int avgMax; /* running average of max sample. */ + guint32 display[scope_width * scope_height]; - convolve_state *cstate; - guint32 colors[64]; + convolve_state *cstate; + guint32 colors[64]; }; struct monoscope_state * monoscope_init (guint32 resx, guint32 resy); -guint32 * monoscope_update (struct monoscope_state * stateptr, gint16 data [512]); +guint32 * monoscope_update (struct monoscope_state * stateptr, gint16 data [convolver_big]); void monoscope_close (struct monoscope_state * stateptr); #endif