mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-01-11 18:05:37 +00:00
monoscpe: make the convolver use dynamic memory
Replace all #defines with members and initialize the convolver with a parameter.
This commit is contained in:
parent
3d23ceebae
commit
8d17911b33
4 changed files with 63 additions and 53 deletions
|
@ -83,14 +83,13 @@ typedef union stack_entry_s
|
||||||
}
|
}
|
||||||
stack_entry;
|
stack_entry;
|
||||||
|
|
||||||
#define STACK_SIZE (CONVOLVE_DEPTH * 3)
|
|
||||||
|
|
||||||
struct _struct_convolve_state
|
struct _struct_convolve_state
|
||||||
{
|
{
|
||||||
double left[CONVOLVE_BIG];
|
int depth, small, big, stack_size;
|
||||||
double right[CONVOLVE_SMALL * 3];
|
double *left;
|
||||||
double scratch[CONVOLVE_SMALL * 3];
|
double *right;
|
||||||
stack_entry stack[STACK_SIZE + 1];
|
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().
|
* The pointer should be freed when it is finished with, by convolve_close().
|
||||||
*/
|
*/
|
||||||
convolve_state *
|
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
|
void
|
||||||
convolve_close (convolve_state * state)
|
convolve_close (convolve_state * state)
|
||||||
{
|
{
|
||||||
|
free (state->left);
|
||||||
|
free (state->right);
|
||||||
|
free (state->scratch);
|
||||||
|
free (state->stack);
|
||||||
free (state);
|
free (state);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -273,13 +287,13 @@ convolve_match (const int *lastchoice, const short *input,
|
||||||
double *left = state->left;
|
double *left = state->left;
|
||||||
double *right = state->right;
|
double *right = state->right;
|
||||||
double *scratch = state->scratch;
|
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];
|
left[i] = input[i];
|
||||||
|
|
||||||
for (i = 0; i < CONVOLVE_SMALL; i++) {
|
for (i = 0; i < state->small; i++) {
|
||||||
double a = lastchoice[(CONVOLVE_SMALL - 1) - i];
|
double a = lastchoice[(state->small - 1) - i];
|
||||||
|
|
||||||
right[i] = a;
|
right[i] = a;
|
||||||
avg += 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
|
/* We adjust the smaller of the two input arrays to have average
|
||||||
* value 0. This makes the eventual result insensitive to both
|
* value 0. This makes the eventual result insensitive to both
|
||||||
* constant offsets and positive multipliers of the inputs. */
|
* constant offsets and positive multipliers of the inputs. */
|
||||||
avg /= CONVOLVE_SMALL;
|
avg /= state->small;
|
||||||
for (i = 0; i < CONVOLVE_SMALL; i++)
|
for (i = 0; i < state->small; i++)
|
||||||
right[i] -= avg;
|
right[i] -= avg;
|
||||||
/* End-of-stack marker. */
|
/* End-of-stack marker. */
|
||||||
top[1].b.null = scratch;
|
top[1].b.null = scratch;
|
||||||
top[1].b.main = NULL;
|
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.left = left;
|
||||||
top->v.right = right;
|
top->v.right = right;
|
||||||
top->v.out = right + CONVOLVE_SMALL;
|
top->v.out = right + state->small;
|
||||||
convolve_run (top, CONVOLVE_SMALL, scratch);
|
convolve_run (top, state->small, scratch);
|
||||||
|
|
||||||
/* The high SMALLxSMALL, of which we want the low outputs. */
|
/* The high (small x small) part, of which we want the low outputs. */
|
||||||
top->v.left = left + CONVOLVE_SMALL;
|
top->v.left = left + state->small;
|
||||||
top->v.right = right;
|
top->v.right = right;
|
||||||
top->v.out = 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
|
/* Now find the best position amoungs this. Apart from the first
|
||||||
* and last, the required convolution outputs are formed by adding
|
* and last, the required convolution outputs are formed by adding
|
||||||
* outputs from the two convolutions above. */
|
* outputs from the two convolutions above. */
|
||||||
best = right[CONVOLVE_BIG - 1];
|
best = right[state->big - 1];
|
||||||
right[CONVOLVE_BIG + CONVOLVE_SMALL + 1] = 0;
|
right[state->big + state->small - 1] = 0;
|
||||||
p = -1;
|
p = -1;
|
||||||
for (i = 0; i < CONVOLVE_SMALL; i++) {
|
for (i = 0; i < state->small; i++) {
|
||||||
double a = right[i] + right[i + CONVOLVE_BIG];
|
double a = right[i] + right[i + state->big];
|
||||||
|
|
||||||
if (a > best) {
|
if (a > best) {
|
||||||
best = a;
|
best = a;
|
||||||
|
@ -326,18 +340,18 @@ convolve_match (const int *lastchoice, const short *input,
|
||||||
{
|
{
|
||||||
/* This is some debugging code... */
|
/* This is some debugging code... */
|
||||||
best = 0;
|
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);
|
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;
|
double tot = 0;
|
||||||
unsigned int j;
|
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);
|
tot += ((double) input[i + j]) * ((double) lastchoice[j] - avg);
|
||||||
if (tot > best)
|
if (tot > best)
|
||||||
printf ("(%i)", i);
|
printf ("(%i)", i);
|
||||||
if (tot != left[i + (CONVOLVE_SMALL - 1)])
|
if (tot != left[i + (state->small - 1)])
|
||||||
printf ("!");
|
printf ("!");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -31,16 +31,10 @@
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* convolve_match takes two blocks, one twice the size of the other. The
|
/* Convolution state */
|
||||||
* 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 */
|
|
||||||
typedef struct _struct_convolve_state convolve_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);
|
void convolve_close (convolve_state * state);
|
||||||
|
|
||||||
int convolve_match (const int * lastchoice,
|
int convolve_match (const int * lastchoice,
|
||||||
|
|
|
@ -63,12 +63,12 @@ monoscope_init (guint32 resx, guint32 resy)
|
||||||
struct monoscope_state *stateptr;
|
struct monoscope_state *stateptr;
|
||||||
|
|
||||||
/* I didn't program monoscope to only do 256*128, but it works that way */
|
/* 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 (resx == scope_width, 0);
|
||||||
g_return_val_if_fail (resy == 128, 0);
|
g_return_val_if_fail (resy == scope_height, 0);
|
||||||
stateptr = calloc (1, sizeof (struct monoscope_state));
|
stateptr = calloc (1, sizeof (struct monoscope_state));
|
||||||
if (stateptr == 0)
|
if (stateptr == 0)
|
||||||
return 0;
|
return 0;
|
||||||
stateptr->cstate = convolve_init ();
|
stateptr->cstate = convolve_init (convolver_depth);
|
||||||
colors_init (stateptr->colors);
|
colors_init (stateptr->colors);
|
||||||
return stateptr;
|
return stateptr;
|
||||||
}
|
}
|
||||||
|
@ -81,9 +81,8 @@ monoscope_close (struct monoscope_state *stateptr)
|
||||||
}
|
}
|
||||||
|
|
||||||
guint32 *
|
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.
|
/* Really, we want samples evenly spread over the available data.
|
||||||
* Just taking a continuous chunk will do for now, though. */
|
* Just taking a continuous chunk will do for now, though. */
|
||||||
int i;
|
int i;
|
||||||
|
@ -95,14 +94,14 @@ monoscope_update (struct monoscope_state *stateptr, gint16 data[512])
|
||||||
int factor;
|
int factor;
|
||||||
int val;
|
int val;
|
||||||
int max = 1;
|
int max = 1;
|
||||||
short *thisEq = stateptr->copyEq;
|
gint16 *thisEq = stateptr->copyEq;
|
||||||
|
|
||||||
memcpy (thisEq, data, sizeof (short) * CONVOLVE_BIG);
|
memcpy (thisEq, data, sizeof (short) * convolver_big);
|
||||||
val = convolve_match (stateptr->avgEq, stateptr->copyEq, stateptr->cstate);
|
val = convolve_match (stateptr->avgEq, thisEq, stateptr->cstate);
|
||||||
thisEq += val;
|
thisEq += val;
|
||||||
|
|
||||||
memset (stateptr->display, 0, 256 * 128 * sizeof (guint32));
|
memset (stateptr->display, 0, scope_width * scope_height * sizeof (guint32));
|
||||||
for (i = 0; i < 256; i++) {
|
for (i = 0; i < convolver_small; i++) {
|
||||||
foo = thisEq[i] + (stateptr->avgEq[i] >> 1);
|
foo = thisEq[i] + (stateptr->avgEq[i] >> 1);
|
||||||
stateptr->avgEq[i] = foo;
|
stateptr->avgEq[i] = foo;
|
||||||
if (foo < 0)
|
if (foo < 0)
|
||||||
|
|
|
@ -4,21 +4,24 @@
|
||||||
#include <glib.h>
|
#include <glib.h>
|
||||||
#include "convolve.h"
|
#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_width 256
|
||||||
#define scope_height 128
|
#define scope_height 128
|
||||||
|
|
||||||
struct monoscope_state {
|
struct monoscope_state {
|
||||||
gint16 copyEq[CONVOLVE_BIG];
|
short copyEq[convolver_big];
|
||||||
int avgEq[CONVOLVE_SMALL]; /* a running average of the last few. */
|
int avgEq[convolver_small]; /* a running average of the last few. */
|
||||||
int avgMax; /* running average of max sample. */
|
int avgMax; /* running average of max sample. */
|
||||||
guint32 display[(scope_width + 1) * (scope_height + 1)];
|
guint32 display[scope_width * scope_height];
|
||||||
|
|
||||||
convolve_state *cstate;
|
convolve_state *cstate;
|
||||||
guint32 colors[64];
|
guint32 colors[64];
|
||||||
};
|
};
|
||||||
|
|
||||||
struct monoscope_state * monoscope_init (guint32 resx, guint32 resy);
|
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);
|
void monoscope_close (struct monoscope_state * stateptr);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
Loading…
Reference in a new issue