# HG changeset patch # User nenolod # Date 1162551252 28800 # Node ID 4b48e6e9b3cb62677075083bf9ab29597543c19a # Parent a7c8234781804211c4572f009172b4945ae796bf [svn] - rewrite line drawing algorithm for speed - use lines instead of dots by default in horizontal and vertical waveforms diff -r a7c823478180 -r 4b48e6e9b3cb ChangeLog --- a/ChangeLog Thu Nov 02 22:19:05 2006 -0800 +++ b/ChangeLog Fri Nov 03 02:54:12 2006 -0800 @@ -1,3 +1,13 @@ +2006-11-03 06:19:05 +0000 William Pitcock + revision [384] + - add fast linedrawing code + + trunk/src/paranormal/Makefile | 1 + trunk/src/paranormal/drawing.c | 74 ++++++++++++++++++++++++++++++++++++++ + trunk/src/paranormal/paranormal.c | 2 - + 3 files changed, 76 insertions(+), 1 deletion(-) + + 2006-11-03 05:44:14 +0000 William Pitcock revision [382] - fix warning (oops) diff -r a7c823478180 -r 4b48e6e9b3cb src/paranormal/drawing.c --- a/src/paranormal/drawing.c Thu Nov 02 22:19:05 2006 -0800 +++ b/src/paranormal/drawing.c Fri Nov 03 02:54:12 2006 -0800 @@ -1,3 +1,5 @@ +#include + #include "paranormal.h" #include "actuators.h" #include "pn_utils.h" @@ -12,63 +14,23 @@ gint x1 = _x1; gint y1 = _y1; + gint dx = x1 - x0; gint dy = y1 - y0; - gint dx = x1 - x0; - gint stepx, stepy; - gint fraction; - if (dy < 0) - { - dy = -dy; - stepy = -(screen->pitch >> 2); - } - else - { - stepy = screen->pitch>>2; - } - if (dx < 0) - { - dx = -dx; - stepx = -1; - } - else - { - stepx = 1; - } - dy <<= 1; - dx <<= 1; - - y0 *= screen->pitch>>2; - y1 *= screen->pitch>>2; pn_image_data->surface[0][PN_IMG_INDEX(x0, y0)] = value; - if (dx > dy) + + if (dx != 0) { - fraction = dy - (dx >> 1); + gfloat m = (gfloat) dy / (gfloat) dx; + gfloat b = y0 - m * x0; + + dx = (x1 > x0) ? 1 : - 1; while (x0 != x1) - { - if (fraction >= 0) - { - y0 += stepy; - fraction -= dx; - } - x0 += stepx; - fraction += dy; - pn_image_data->surface[0][PN_IMG_INDEX(x0, y0)] = value; - } - } - else - { - fraction = dx - (dy >> 1); - while (y0 != y1) - { - if (fraction >= 0) - { - x0 += stepx; - fraction -= dy; - } - y0 += stepy; - fraction += dx; - pn_image_data->surface[0][PN_IMG_INDEX(x0, y0)] = value; - } + { + x0 += dx; + y0 = round(m * x0 + b); + + pn_image_data->surface[0][PN_IMG_INDEX(x0, y0)] = value; + } } } diff -r a7c823478180 -r 4b48e6e9b3cb src/paranormal/wave.c --- a/src/paranormal/wave.c Thu Nov 02 22:19:05 2006 -0800 +++ b/src/paranormal/wave.c Fri Nov 03 02:54:12 2006 -0800 @@ -12,11 +12,12 @@ {"channels", "Which sound channels to use: negative = channel 1, \npositive = channel 2, " "zero = both (two wave-forms.)", OPT_TYPE_INT, {ival: -1} }, {"value", "The colour value to use.", OPT_TYPE_INT, {ival: 255} }, + {"lines", "Use lines instead of dots.", OPT_TYPE_BOOLEAN, {bval: TRUE} }, { NULL } }; static void -wave_horizontal_exec (const struct pn_actuator_option *opts, +wave_horizontal_exec_dots (const struct pn_actuator_option *opts, gpointer data) { int i; @@ -51,6 +52,71 @@ } } +void +wave_horizontal_exec_lines (const struct pn_actuator_option *opts, + gpointer data) +{ + int channel = ( opts[0].val.ival < 0 ) ? 0 : 1; + guchar value = (opts[1].val.ival < 0 || opts[1].val.ival > 255) ? 255 : opts[1].val.ival; + int *x_pos, *y_pos; /* dynamic tables which store the positions for the line */ + int *x2_pos, *y2_pos; /* dynamic tables which store the positions for the line */ + int i; + + x_pos = g_new0(int, pn_image_data->width + 1); + y_pos = g_new0(int, pn_image_data->width + 1); + x2_pos = g_new0(int, pn_image_data->width + 1); + y2_pos = g_new0(int, pn_image_data->width + 1); + + /* calculate the line. */ + for (i = 0; i < pn_image_data->width; i++) + { + if (opts[0].val.ival != 0) + { + x_pos[i] = i; + y_pos[i] = (pn_image_data->height>>1) - + CAP (pn_sound_data->pcm_data[channel][i*512/pn_image_data->width]>>8, + (pn_image_data->height>>1)-1); + } + else + { + x_pos[i] = i; + y_pos[i] = (pn_image_data->height>>2) - + CAP (pn_sound_data->pcm_data[0][i*512/pn_image_data->width]>>9, + (pn_image_data->height>>2)-1); + + x2_pos[i] = i; + y2_pos[i] = 3*(pn_image_data->height>>2) - + CAP (pn_sound_data->pcm_data[1][i*512/pn_image_data->width]>>9, + (pn_image_data->height>>2)-1); + + } + } + + /* draw the line. */ + for (i = 1; i < pn_image_data->width; i++) + { + pn_draw_line(x_pos[i - 1], y_pos[i - 1], x_pos[i], y_pos[i], value); + + if ( opts[0].val.ival == 0 ) + pn_draw_line(x2_pos[i - 1], y2_pos[i - 1], x2_pos[i], y2_pos[i], value); + } + + g_free(x_pos); + g_free(y_pos); + g_free(x2_pos); + g_free(y2_pos); +} + +static void +wave_horizontal_exec (const struct pn_actuator_option *opts, + gpointer data) +{ + if (opts[2].val.bval == TRUE) + wave_horizontal_exec_lines(opts, data); + else + wave_horizontal_exec_dots(opts, data); +} + struct pn_actuator_desc builtin_wave_horizontal = { "wave_horizontal", "Horizontal Waveform", @@ -66,11 +132,12 @@ {"channels", "Which sound channels to use: negative = channel 1, \npositive = channel 2, " "zero = both (two wave-forms.)", OPT_TYPE_INT, {ival: -1} }, {"value", "The colour value to use.", OPT_TYPE_INT, {ival: 255} }, + {"lines", "Use lines instead of dots.", OPT_TYPE_BOOLEAN, {bval: TRUE} }, { NULL } }; static void -wave_vertical_exec (const struct pn_actuator_option *opts, +wave_vertical_exec_dots (const struct pn_actuator_option *opts, gpointer data) { int i; @@ -101,6 +168,72 @@ } } +static void +wave_vertical_exec_lines (const struct pn_actuator_option *opts, + gpointer data) +{ + int channel = ( opts[0].val.ival < 0 ) ? 0 : 1; + guchar value = (opts[1].val.ival < 0 || opts[1].val.ival > 255) ? 255 : opts[1].val.ival; + int *x_pos, *y_pos; /* dynamic tables which store the positions for the line */ + int *x2_pos, *y2_pos; /* dynamic tables which store the positions for the line */ + int i; + + x_pos = g_new0(int, pn_image_data->height + 1); + y_pos = g_new0(int, pn_image_data->height + 1); + x2_pos = g_new0(int, pn_image_data->height + 1); + y2_pos = g_new0(int, pn_image_data->height + 1); + + /* calculate the line. */ + for (i = 0; i < pn_image_data->height; i++) + { + if (opts[0].val.ival != 0) + { + x_pos[i] = (pn_image_data->width>>1) - + CAP (pn_sound_data->pcm_data[channel] + [i*512/pn_image_data->height]>>8, + (pn_image_data->width>>1)-1); + y_pos[i] = i; + } + else + { + x_pos[i] = (pn_image_data->width>>2) + - CAP (pn_sound_data->pcm_data[0] + [i*512/pn_image_data->height]>>9, + (pn_image_data->width>>2)-1); + y_pos[i] = i; + + x2_pos[i] = 3*(pn_image_data->width>>2) + - CAP (pn_sound_data->pcm_data[1] + [i*512/pn_image_data->height]>>9, + (pn_image_data->width>>2)-1); + y2_pos[i] = i; + } + } + + /* draw the line. */ + for (i = 1; i < pn_image_data->width; i++) + { + pn_draw_line(x_pos[i - 1], y_pos[i - 1], x_pos[i], y_pos[i], value); + + if ( opts[0].val.ival == 0 ) + pn_draw_line(x2_pos[i - 1], y2_pos[i - 1], x2_pos[i], y2_pos[i], value); + } + + g_free(x_pos); + g_free(y_pos); + g_free(x2_pos); + g_free(y2_pos); +} + +static void +wave_vertical_exec (const struct pn_actuator_option *opts, + gpointer data) +{ + if (opts[2].val.bval == TRUE) + wave_vertical_exec_lines(opts, data); + else + wave_vertical_exec_dots(opts, data); +} struct pn_actuator_desc builtin_wave_vertical = { @@ -221,6 +354,7 @@ { "base_radius", " ", OPT_TYPE_FLOAT, { fval: 0 } }, {"value", "The colour value to use.", OPT_TYPE_INT, {ival: 255} }, +/* {"lines", "Use lines instead of dots.", OPT_TYPE_BOOLEAN, {bval: TRUE} }, */ { NULL } };