new smoothing formula, radial module, utility module

This commit is contained in:
Jarcode
2017-12-03 19:40:23 -08:00
parent 058d34ae52
commit b8d84e78b4
7 changed files with 206 additions and 69 deletions

View File

@@ -359,7 +359,7 @@ struct gl_data {
int fcounter, ucounter, kcounter;
bool print_fps, avg_window, interpolate, force_geometry;
void** t_data;
float gravity_step, target_spu, fr, ur;
float gravity_step, target_spu, fr, ur, smooth_distance, smooth_ratio;
float* interpolate_buf[6];
int geometry[4];
};
@@ -433,6 +433,59 @@ static struct gl_bind_src bind_sources[] = {
*udata = u; \
} else u = (typeof(u)) *udata;
/* type generic clamp/min/max, like in GLSL */
#define clamp(v, min, max) \
({ \
__auto_type _v = v; \
if (_v < min) _v = min; \
else if (_v > max) _v = max; \
_v; \
})
#define min(a0, b0) \
({ \
__auto_type _a = a0; \
__auto_type _b = b0; \
_a < _b ? _a : _b; \
})
#define max(a0, b0) \
({ \
__auto_type _a = a0; \
__auto_type _b = b0; \
_a > _b ? _a : _b; \
})
#define E 2.7182818284590452353
void transform_smooth(struct gl_data* d, void** udaa, void* data) {
struct gl_sampler_data* s = (struct gl_sampler_data*) data;
float* b = s->buf;
size_t
sz = s->sz,
asz = (size_t) ceil(s->sz / d->smooth_ratio);
for (int t = 0; t < asz; ++t) {
float
db = log(t), /* buffer index on log scale */
v = b[t], /* value at this position */
avg = 0; /* adj value averages (weighted) */
/* Calculate real indexes for sampling at this position, since the
distance is specified in scalar values */
int smin = (int) floor(powf(E, max(db - d->smooth_distance, 0)));
int smax = min((int) ceil(powf(E, db + d->smooth_distance)), sz - 1);
int count = 0;
for (int s = smin; s <= smax; ++s) {
if (b[s]) {
avg += b[s] /* / abs(powf(10, db + (t - s))) */;
count++;
}
}
avg /= count;
b[t] = avg;
}
}
void transform_gravity(struct gl_data* d, void** udata, void* data) {
struct gl_sampler_data* s = (struct gl_sampler_data*) data;
float* b = s->buf;
@@ -574,7 +627,8 @@ static struct gl_transform transform_functions[] = {
{ .name = "fft", .type = BIND_SAMPLER1D, .apply = transform_fft },
{ .name = "wrange", .type = BIND_SAMPLER1D, .apply = transform_wrange },
{ .name = "avg", .type = BIND_SAMPLER1D, .apply = transform_average },
{ .name = "gravity", .type = BIND_SAMPLER1D, .apply = transform_gravity }
{ .name = "gravity", .type = BIND_SAMPLER1D, .apply = transform_gravity },
{ .name = "smooth", .type = BIND_SAMPLER1D, .apply = transform_smooth }
};
static struct gl_bind_src* lookup_bind_src(const char* str) {
@@ -601,21 +655,23 @@ struct renderer* rd_new(const char** paths, const char* entry, const char* force
struct gl_data* gl = r->gl;
*gl = (struct gl_data) {
.stages = NULL,
.rate = 0,
.tcounter = 0.0D,
.fcounter = 0,
.ucounter = 0,
.kcounter = 0,
.fr = 1.0F,
.ur = 1.0F,
.print_fps = true,
.bufscale = 1,
.avg_frames = 4,
.avg_window = true,
.gravity_step = 0.1,
.interpolate = true,
.force_geometry = false
.stages = NULL,
.rate = 0,
.tcounter = 0.0D,
.fcounter = 0,
.ucounter = 0,
.kcounter = 0,
.fr = 1.0F,
.ur = 1.0F,
.print_fps = true,
.bufscale = 1,
.avg_frames = 4,
.avg_window = true,
.gravity_step = 0.1,
.interpolate = true,
.force_geometry = false,
.smooth_distance = 0.01,
.smooth_ratio = 4
};
#ifdef GLAD_DEBUG
@@ -747,6 +803,10 @@ struct renderer* rd_new(const char** paths, const char* entry, const char* force
.handler = RHANDLER(name, args, { gl->avg_window = *(bool*) args[0]; }) },
{ .name = "setgravitystep", .fmt = "f",
.handler = RHANDLER(name, args, { gl->gravity_step = *(float*) args[0]; }) },
{ .name = "setsmooth", .fmt = "f",
.handler = RHANDLER(name, args, { gl->smooth_distance = *(float*) args[0]; }) },
{ .name = "setsmoothratio", .fmt = "f",
.handler = RHANDLER(name, args, { gl->smooth_ratio = *(float*) args[0]; }) },
{ .name = "setinterpolate", .fmt = "b",
.handler = RHANDLER(name, args, { gl->interpolate = *(bool*) args[0]; }) },
{

View File

@@ -1,25 +1,14 @@
/* Distance (in pixels) for each fragment to sample the audio data */
#define SAMPLE_RANGE 0.2
/* Amount of samples for each fragment, using the above range for each sample */
#define SAMPLE_AMT 22
/* Inverse horizontal scale, larger means less higher frequencies displayed */
#define WSCALE 11
/* Vertical scale, larger values will amplify output */
#define VSCALE 2800
#define VSCALE 450
/* Rendering direction, either -1 (outwards) or 1 (inwards). */
#define DIRECTION 1
/* Smoothing factor, in normalized width */
#define SMOOTH 0.008
/* Whether to apply a window function to samples or not (0 or 1). Slightly
slower but removes some jagged results. Has a side effect of reducing the
graph magnitude, so you should increase the `VSCALE` macro to compensate. */
#define WINDOW_SAMPLES 1
/* Rendering direction, either -1 (inwards) or 1 (outwards). */
#define DIRECTION -1
/* Graph color logic. The shader uses the `COLOR` macro definition for output. */
/* The `RCOL_OFF`, `LCOL_OFF` AND `LSTEP` definitions are used to calculate
the `COLOR` macro definition for output. You can remove all these values
any simply define the `COLOR` macro yourself. */
/* right color offset */
#define RCOL_OFF (gl_FragCoord.x / 3000)
@@ -29,6 +18,5 @@
#define LSTEP (gl_FragCoord.y / 170)
/* actual color definition */
#define COLOR vec4((0.3 + RCOL_OFF) + LSTEP, 0.6 - LSTEP, (0.3 + LCOL_OFF) + LSTEP, 1)
/* outline color */
#define OUTLINE vec4(0.15, 0.15, 0.15, 1)

View File

@@ -69,6 +69,7 @@ uniform sampler1D audio_r;
out vec4 fragment;
#include "../graph.glsl"
#include "../util/smooth.glsl"
/* distance from center */
#define CDIST (abs((screen.x / 2) - gl_FragCoord.x) / screen.x)
@@ -79,36 +80,23 @@ out vec4 fragment;
#define LEFT_IDX (gl_FragCoord.x)
#define RIGHT_IDX (-gl_FragCoord.x + screen.x)
/* distance from base frequencies */
#define BDIST CDIST
#define BDIST FDIST
/* distance from high frequencies */
#define HDIST FDIST
#define HDIST CDIST
#else
#define LEFT_IDX (half_w - gl_FragCoord.x)
#define RIGHT_IDX (gl_FragCoord.x - half_w)
#define BDIST FDIST
#define HDIST CDIST
#define BDIST CDIST
#define HDIST FDIST
#endif
#define TWOPI 6.28318530718
#define window(t, sz) (0.53836 - (0.46164 * cos(TWOPI * t / (sz - 1))))
float half_w;
void render_side(sampler1D tex, float idx) {
float s = 0;
int t;
/* perform samples */
for (t = -SAMPLE_AMT; t <= SAMPLE_AMT; ++t) {
#if WINDOW_SAMPLES != 0
#define WFACTOR window(t + SAMPLE_AMT, float((SAMPLE_AMT * 2) + 1))
#else
#define WFACTOR int(1)
#endif
s += (texture(tex, log((idx + (t * SAMPLE_RANGE)) / half_w) / WSCALE).r) * WFACTOR;
#undef WFACTOR
}
/* compute average on samples */
s /= float(SAMPLE_AMT * 2) + 1;
void render_side(in sampler1D tex, float idx) {
highp float pixel = 1.0F / float(screen.x);
float s = smooth_audio_adj(tex, audio_sz, idx / half_w, SMOOTH, pixel);
/* scale the data upwards so we can see it */
s *= VSCALE;
/* clamp far ends of the screen down to make the ends of the graph smoother */

View File

@@ -13,9 +13,13 @@
#define BAR_OUTLINE OUTLINE
/* outline width (in pixels, set to 0 to disable outline drawing) */
#define BAR_OUTLINE_WIDTH 0
/* Inverse horizontal scale, larger means less higher frequencies displayed */
#define WSCALE 11
/* Amplify magnitude of the results each bar displays */
#define AMPLIFY 200
#define AMPLIFY 300
/* Bar color */
#define COLOR (vec4(0.8, 0.2, 0.2, 1) * ((d / 40) + 1))
/* Angle (in radians) for how much to rotate the visualizer */
#define ROTATE (PI / 2)
/* Whether to switch left/right audio buffers */
#define INVERT 0
/* Smoothing factor, in normalized width */
#define SMOOTH 0.025

View File

@@ -12,9 +12,13 @@ uniform int audio_sz;
#request setgravitystep 5.2
#request setsmooth 0.0025
#request setsmoothratio 1
#request uniform "audio_l" audio_l
#request transform audio_l "window"
#request transform audio_l "fft"
// #request transform audio_l "smooth"
#request transform audio_l "gravity"
#request transform audio_l "avg"
uniform sampler1D audio_l;
@@ -22,6 +26,7 @@ uniform sampler1D audio_l;
#request uniform "audio_r" audio_r
#request transform audio_r "window"
#request transform audio_r "fft"
// #request transform audio_r "smooth"
#request transform audio_r "gravity"
#request transform audio_r "avg"
uniform sampler1D audio_r;
@@ -29,6 +34,7 @@ uniform sampler1D audio_r;
out vec4 fragment;
#include "../radial.glsl"
#include "../util/smooth.glsl"
#define TWOPI 6.28318530718
#define PI 3.14159265359
@@ -36,21 +42,27 @@ out vec4 fragment;
void main() {
float /* translate (x, y) to use (0, 0) as the center of the screen */
dx = gl_FragCoord.x - (screen.x / 2),
dy = (screen.y / 2) - gl_FragCoord.y;
dy = gl_FragCoord.y - (screen.y / 2);
float theta = atan(dy, dx); /* fragment angle with the center of the screen as the origin */
float d = sqrt((dx * dx) + (dy * dy)); /* distance */
if (d > C_RADIUS - (float(C_LINE) / 2F) && d < C_RADIUS + (float(C_LINE) / 2F)) {
fragment = OUTLINE;
return;
} else if (d > C_RADIUS) {
float section = (TWOPI / NBARS); /* range (radians) for each bar */
float m = mod(theta, section); /* position in section (radians) */
float center = ((TWOPI / NBARS) / 2F); /* center line angle */
float ym = d * sin(center - m); /* distance from center line (cartesian coords) */
if (abs(ym) < BAR_WIDTH / 2) { /* if within width, draw audio */
/* texture lookup */
float v = texture(theta > 0 ? audio_l : audio_r,
log(int(abs(theta) / section) / float(NBARS / 2)) / WSCALE).r * AMPLIFY;
const float section = (TWOPI / NBARS); /* range (radians) for each bar */
const float center = ((TWOPI / NBARS) / 2F); /* center line angle */
float m = mod(theta, section); /* position in section (radians) */
float ym = d * sin(center - m); /* distance from center line (cartesian coords) */
if (abs(ym) < BAR_WIDTH / 2) { /* if within width, draw audio */
float idx = theta + ROTATE; /* position (radians) in texture */
float dir = mod(abs(idx), TWOPI); /* absolute position, [0, 2pi) */
if (dir > PI)
idx = -sign(idx) * (TWOPI - dir); /* Re-correct position values to [-pi, pi) */
if (INVERT > 0)
idx = -idx; /* Invert if needed */
float pos = int(abs(idx) / section) / float(NBARS / 2);
float v = smooth_audio(idx > 0 ? audio_l : audio_r, audio_sz, pos, SMOOTH) * AMPLIFY * (1 + pos);
d -= C_RADIUS + (float(C_LINE) / 2F); /* offset to fragment distance from inner circle */
if (d <= v - BAR_OUTLINE_WIDTH) {
#if BAR_OUTLINE_WIDTH > 0

View File

@@ -0,0 +1,21 @@
/* Settings for smoothing functions commonly used to display FFT output */
/* The type of formula to use for weighting values when smoothing.
Possible values:
- circular heavily rounded points
- sinusoidal rounded at both low and high weighted values
like a sine wave
- linear not rounded at all, just use linear distance
*/
#define ROUND_FORMULA circular
/* Factor used to scale frequencies. Lower values allows lower
frequencies to occupy more space. */
#define SAMPLE_SCALE 8
/* The frequency range to sample. 1.0 would be the entire FFT output,
and lower values reduce the displayed frequencies in a log-like
scale. */
#define SAMPLE_RANGE 0.9

64
shaders/util/smooth.glsl Normal file
View File

@@ -0,0 +1,64 @@
#ifndef _SMOOTH_GLSL /* include gaurd */
#define _SMOOTH_GLSL
#ifndef TWOPI
#define TWOPI 6.28318530718
#endif
#ifndef PI
#define PI 3.14159265359
#endif
#include "../smooth_parameters.glsl"
/* window value t that resides in range [0, sz)*/
#define window(t, sz) (0.53836 - (0.46164 * cos(TWOPI * t / (sz - 1))))
/* this does nothing, but we keep it as an option for config */
#define linear(x) (x)
/* take value x that scales linearly between [0, 1) and return its sinusoidal curve */
#define sinusoidal(x) ((0.5 * sin((PI * (x)) - (PI / 2))) + 0.5)
/* take value x that scales linearly between [0, 1) and return its circlar curve */
#define circular(x) sqrt(1 - (((x) - 1) * ((x) - 1)))
float scale_audio(float idx) {
return -log((-(SAMPLE_RANGE) * idx) + 1) / (SAMPLE_SCALE);
}
float iscale_audio(float idx) {
return -log((SAMPLE_RANGE) * idx) / (SAMPLE_SCALE);
}
float smooth_audio(in sampler1D tex, int tex_sz, highp float idx, float r) {
float
smin = scale_audio(clamp(idx - r, 0, 1)) * tex_sz,
smax = scale_audio(clamp(idx + r, 0, 1)) * tex_sz,
avg = 0, s, weight = 0;
float m = ((smax - smin) / 2.0F);
float rm = smin + m; /* middle */
for (s = smin; s <= smax; s += 1.0F) {
float w = ROUND_FORMULA(clamp((m - abs(rm - s)) / m, 0, 1));
weight += w;
avg += texture(tex, float(s) / float(tex_sz)).r * w;
}
avg /= weight;
avg *= max(idx + 0.7, 1);
return avg;
}
/* Applies the audio smooth sampling function three times to the adjacent values */
float smooth_audio_adj(in sampler1D tex, int tex_sz, highp float idx, float r, highp float pixel) {
float
al = smooth_audio(tex, tex_sz, max(idx - pixel, 0.0F), r),
am = smooth_audio(tex, tex_sz, idx, r),
ar = smooth_audio(tex, tex_sz, min(idx + pixel, 1.0F), r);
return (al + am + ar) / 3.0F;
}
#ifdef TWOPI
#undef TWOPI
#endif
#ifdef PI
#undef PI
#endif
#endif /* _SMOOTH_GLSL */