new smoothing formula, radial module, utility module
This commit is contained in:
94
render.c
94
render.c
@@ -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]; }) },
|
||||
{
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
21
shaders/smooth_parameters.glsl
Normal file
21
shaders/smooth_parameters.glsl
Normal 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
64
shaders/util/smooth.glsl
Normal 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 */
|
||||
Reference in New Issue
Block a user