summaryrefslogtreecommitdiffstats
path: root/gst/monoscope/convolve.c
diff options
context:
space:
mode:
Diffstat (limited to 'gst/monoscope/convolve.c')
-rw-r--r--gst/monoscope/convolve.c438
1 files changed, 230 insertions, 208 deletions
diff --git a/gst/monoscope/convolve.c b/gst/monoscope/convolve.c
index b707621b..6b8cdd50 100644
--- a/gst/monoscope/convolve.c
+++ b/gst/monoscope/convolve.c
@@ -62,19 +62,28 @@
#include <stdlib.h>
#include "convolve.h"
-typedef union stack_entry_s {
- struct {const double * left, * right; double * out;} v;
- struct {double * main, * null;} b;
+typedef union stack_entry_s
+{
+ struct
+ {
+ const double *left, *right;
+ double *out;
+ } v;
+ struct
+ {
+ double *main, *null;
+ } b;
} 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];
+struct _struct_convolve_state
+{
+ double left[CONVOLVE_BIG];
+ double right[CONVOLVE_SMALL * 3];
+ double scratch[CONVOLVE_SMALL * 3];
+ stack_entry stack[STACK_SIZE];
};
/*
@@ -83,48 +92,53 @@ struct _struct_convolve_state {
* On error, returns NULL.
* The pointer should be freed when it is finished with, by convolve_close().
*/
-convolve_state *convolve_init(void)
+convolve_state *
+convolve_init (void)
{
- return (convolve_state *) malloc (sizeof(convolve_state));
+ return (convolve_state *) malloc (sizeof (convolve_state));
}
/*
* Free the state allocated with convolve_init().
*/
-void convolve_close(convolve_state *state)
+void
+convolve_close (convolve_state * state)
{
- if (state)
- free(state);
+ if (state)
+ free (state);
}
-static void convolve_4 (double * out, const double * left, const double * right)
+static void
+convolve_4 (double *out, const double *left, const double *right)
/* This does a 4x4 -> 7 convolution. For what it's worth, the slightly odd
* ordering gives about a 1% speed up on my Pentium II. */
{
- double l0, l1, l2, l3, r0, r1, r2, r3;
- double a;
- l0 = left[0];
- r0 = right[0];
- a = l0 * r0;
- l1 = left[1];
- r1 = right[1];
- out[0] = a;
- a = (l0 * r1) + (l1 * r0);
- l2 = left[2];
- r2 = right[2];
- out[1] = a;
- a = (l0 * r2) + (l1 * r1) + (l2 * r0);
- l3 = left[3];
- r3 = right[3];
- out[2] = a;
-
- out[3] = (l0 * r3) + (l1 * r2) + (l2 * r1) + (l3 * r0);
- out[4] = (l1 * r3) + (l2 * r2) + (l3 * r1);
- out[5] = (l2 * r3) + (l3 * r2);
- out[6] = l3 * r3;
+ double l0, l1, l2, l3, r0, r1, r2, r3;
+ double a;
+
+ l0 = left[0];
+ r0 = right[0];
+ a = l0 * r0;
+ l1 = left[1];
+ r1 = right[1];
+ out[0] = a;
+ a = (l0 * r1) + (l1 * r0);
+ l2 = left[2];
+ r2 = right[2];
+ out[1] = a;
+ a = (l0 * r2) + (l1 * r1) + (l2 * r0);
+ l3 = left[3];
+ r3 = right[3];
+ out[2] = a;
+
+ out[3] = (l0 * r3) + (l1 * r2) + (l2 * r1) + (l3 * r0);
+ out[4] = (l1 * r3) + (l2 * r2) + (l3 * r1);
+ out[5] = (l2 * r3) + (l3 * r2);
+ out[6] = l3 * r3;
}
-static void convolve_run (stack_entry * top, unsigned size, double * scratch)
+static void
+convolve_run (stack_entry * top, unsigned size, double *scratch)
/* Interpret a stack of commands. The stack starts with two entries; the
* convolution to do, and an illegal entry used to mark the stack top. The
* size is the number of entries in each input, and must be a power of 2,
@@ -132,102 +146,105 @@ static void convolve_run (stack_entry * top, unsigned size, double * scratch)
* scratch must have length 3*size. The number of stack entries needed is
* 3n-4 where size=2^n. */
{
- do {
- const double * left;
- const double * right;
- double * out;
-
- /* When we get here, the stack top is always a convolve,
- * with size > 4. So we will split it. We repeatedly split
- * the top entry until we get to size = 4. */
-
- left = top->v.left;
- right = top->v.right;
- out = top->v.out;
- top++;
-
- do {
- double * s_left, * s_right;
- int i;
-
- /* Halve the size. */
- size >>= 1;
-
- /* Allocate the scratch areas. */
- s_left = scratch + size * 3;
- /* s_right is a length 2*size buffer also used for
- * intermediate output. */
- s_right = scratch + size * 4;
-
- /* Create the intermediate factors. */
- for (i = 0; i < size; i++) {
- double l = left[i] + left[i + size];
- double r = right[i] + right[i + size];
- s_left[i + size] = r;
- s_left[i] = l;
- }
-
- /* Push the combine entry onto the stack. */
- top -= 3;
- top[2].b.main = out;
- top[2].b.null = NULL;
-
- /* Push the low entry onto the stack. This must be
- * the last of the three sub-convolutions, because
- * it may overwrite the arguments. */
- top[1].v.left = left;
- top[1].v.right = right;
- top[1].v.out = out;
-
- /* Push the mid entry onto the stack. */
- top[0].v.left = s_left;
- top[0].v.right = s_right;
- top[0].v.out = s_right;
-
- /* Leave the high entry in variables. */
- left += size;
- right += size;
- out += size * 2;
-
- } while (size > 4);
-
- /* When we get here, the stack top is a group of 3
- * convolves, with size = 4, followed by some combines. */
- convolve_4 (out, left, right);
- convolve_4 (top[0].v.out, top[0].v.left, top[0].v.right);
- convolve_4 (top[1].v.out, top[1].v.left, top[1].v.right);
- top += 2;
-
- /* Now process combines. */
- do {
- /* b.main is the output buffer, mid is the middle
- * part which needs to be adjusted in place, and
- * then folded back into the output. We do this in
- * a slightly strange way, so as to avoid having
- * two loops. */
- double * out = top->b.main;
- double * mid = scratch + size * 4;
- unsigned int i;
- top++;
- out[size * 2 - 1] = 0;
- for (i = 0; i < size-1; i++) {
- double lo;
- double hi;
- lo = mid[0] - (out[0] + out[2 * size]) + out[size];
- hi = mid[size] - (out[size] + out[3 * size]) + out[2 * size];
- out[size] = lo;
- out[2 * size] = hi;
- out++;
- mid++;
- }
- size <<= 1;
- } while (top->b.null == NULL);
- } while (top->b.main != NULL);
+ do {
+ const double *left;
+ const double *right;
+ double *out;
+
+ /* When we get here, the stack top is always a convolve,
+ * with size > 4. So we will split it. We repeatedly split
+ * the top entry until we get to size = 4. */
+
+ left = top->v.left;
+ right = top->v.right;
+ out = top->v.out;
+ top++;
+
+ do {
+ double *s_left, *s_right;
+ int i;
+
+ /* Halve the size. */
+ size >>= 1;
+
+ /* Allocate the scratch areas. */
+ s_left = scratch + size * 3;
+ /* s_right is a length 2*size buffer also used for
+ * intermediate output. */
+ s_right = scratch + size * 4;
+
+ /* Create the intermediate factors. */
+ for (i = 0; i < size; i++) {
+ double l = left[i] + left[i + size];
+ double r = right[i] + right[i + size];
+
+ s_left[i + size] = r;
+ s_left[i] = l;
+ }
+
+ /* Push the combine entry onto the stack. */
+ top -= 3;
+ top[2].b.main = out;
+ top[2].b.null = NULL;
+
+ /* Push the low entry onto the stack. This must be
+ * the last of the three sub-convolutions, because
+ * it may overwrite the arguments. */
+ top[1].v.left = left;
+ top[1].v.right = right;
+ top[1].v.out = out;
+
+ /* Push the mid entry onto the stack. */
+ top[0].v.left = s_left;
+ top[0].v.right = s_right;
+ top[0].v.out = s_right;
+
+ /* Leave the high entry in variables. */
+ left += size;
+ right += size;
+ out += size * 2;
+
+ } while (size > 4);
+
+ /* When we get here, the stack top is a group of 3
+ * convolves, with size = 4, followed by some combines. */
+ convolve_4 (out, left, right);
+ convolve_4 (top[0].v.out, top[0].v.left, top[0].v.right);
+ convolve_4 (top[1].v.out, top[1].v.left, top[1].v.right);
+ top += 2;
+
+ /* Now process combines. */
+ do {
+ /* b.main is the output buffer, mid is the middle
+ * part which needs to be adjusted in place, and
+ * then folded back into the output. We do this in
+ * a slightly strange way, so as to avoid having
+ * two loops. */
+ double *out = top->b.main;
+ double *mid = scratch + size * 4;
+ unsigned int i;
+
+ top++;
+ out[size * 2 - 1] = 0;
+ for (i = 0; i < size - 1; i++) {
+ double lo;
+ double hi;
+
+ lo = mid[0] - (out[0] + out[2 * size]) + out[size];
+ hi = mid[size] - (out[size] + out[3 * size]) + out[2 * size];
+ out[size] = lo;
+ out[2 * size] = hi;
+ out++;
+ mid++;
+ }
+ size <<= 1;
+ } while (top->b.null == NULL);
+ } while (top->b.main != NULL);
}
-int convolve_match (const int * lastchoice,
- const short * input,
- convolve_state * state)
+int
+convolve_match (const int *lastchoice,
+ const short *input, convolve_state * state)
/* lastchoice is a 256 sized array. input is a 512 array. We find the
* contiguous length 256 sub-array of input that best matches lastchoice.
* A measure of how good a sub-array is compared with the lastchoice is
@@ -236,85 +253,90 @@ int convolve_match (const int * lastchoice,
* entry in the convolutions. state is a (non-NULL) pointer returned by
* convolve_init. */
{
- double avg;
- double best;
- int p = 0;
- int i;
- double * left = state->left;
- double * right = state->right;
- double * scratch = state->scratch;
- stack_entry * top = state->stack + STACK_SIZE - 1;
+ double avg;
+ double best;
+ int p = 0;
+ int i;
+ double *left = state->left;
+ double *right = state->right;
+ double *scratch = state->scratch;
+ stack_entry *top = state->stack + STACK_SIZE - 1;
+
#if 1
- for (i = 0; i < 512; i++)
- left[i] = input[i];
-
- avg = 0;
- for (i = 0; i < 256; i++) {
- double a = lastchoice[255 - i];
- right[i] = a;
- avg += a;
- }
+ for (i = 0; i < 512; i++)
+ left[i] = input[i];
+
+ avg = 0;
+ for (i = 0; i < 256; i++) {
+ double a = lastchoice[255 - i];
+
+ right[i] = a;
+ avg += a;
+ }
#endif
- /* 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 /= 256;
- for (i = 0; i < 256; i++)
- right[i] -= avg;
- /* End-of-stack marker. */
-#if 0 /* The following line produces a CRASH, need to figure out why?!! */
- top[1].b.null = scratch;
-#endif
- top[1].b.main = NULL;
- /* The low 256x256, of which we want the high 256 outputs. */
- top->v.left = left;
- top->v.right = right;
- top->v.out = right + 256;
- convolve_run (top, 256, scratch);
-
- /* The high 256x256, of which we want the low 256 outputs. */
- top->v.left = left + 256;
- top->v.right = right;
- top->v.out = right;
- convolve_run (top, 256, 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[511];
- right[767] = 0;
- p = -1;
- for (i = 0; i < 256; i++) {
- double a = right[i] + right[i + 512];
- if (a > best) {
- best = a;
- p = i;
- }
- }
- p++;
-
+ /* 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 /= 256;
+ for (i = 0; i < 256; i++)
+ right[i] -= avg;
+ /* End-of-stack marker. */
+#if 0 /* The following line produces a CRASH, need to figure out why?!! */
+ top[1].b.null = scratch;
+#endif
+ top[1].b.main = NULL;
+ /* The low 256x256, of which we want the high 256 outputs. */
+ top->v.left = left;
+ top->v.right = right;
+ top->v.out = right + 256;
+ convolve_run (top, 256, scratch);
+
+ /* The high 256x256, of which we want the low 256 outputs. */
+ top->v.left = left + 256;
+ top->v.right = right;
+ top->v.out = right;
+ convolve_run (top, 256, 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[511];
+ right[767] = 0;
+ p = -1;
+ for (i = 0; i < 256; i++) {
+ double a = right[i] + right[i + 512];
+
+ if (a > best) {
+ best = a;
+ p = i;
+ }
+ }
+ p++;
+
#if 0
- {
- /* This is some debugging code... */
- int bad = 0;
- best = 0;
- for (i = 0; i < 256; i++)
- best += ((double) input[i+p]) * ((double) lastchoice[i] - avg);
-
- for (i = 0; i < 257; i++) {
- double tot = 0;
- unsigned int j;
- for (j = 0; j < 256; j++)
- tot += ((double) input[i+j]) * ((double) lastchoice[j] - avg);
- if (tot > best)
- printf ("(%i)", i);
- if (tot != left[i + 255])
- printf ("!");
- }
-
- printf ("%i\n", p);
- }
-#endif
-
- return p;
+ {
+ /* This is some debugging code... */
+ int bad = 0;
+
+ best = 0;
+ for (i = 0; i < 256; i++)
+ best += ((double) input[i + p]) * ((double) lastchoice[i] - avg);
+
+ for (i = 0; i < 257; i++) {
+ double tot = 0;
+ unsigned int j;
+
+ for (j = 0; j < 256; j++)
+ tot += ((double) input[i + j]) * ((double) lastchoice[j] - avg);
+ if (tot > best)
+ printf ("(%i)", i);
+ if (tot != left[i + 255])
+ printf ("!");
+ }
+
+ printf ("%i\n", p);
+ }
+#endif
+
+ return p;
}