Updated gravity transform, cleaned up graph shader
This commit is contained in:
2
glava.c
2
glava.c
@@ -68,7 +68,7 @@ int main(int argc, char** argv) {
|
||||
audio.modified = false; /* set this flag to false until the next time we read */
|
||||
}
|
||||
pthread_mutex_unlock(&audio.mutex);
|
||||
|
||||
|
||||
/* Only render if needed (ie. stop rendering when fullscreen windows are focused) */
|
||||
if (xwin_should_render()) {
|
||||
rd_update(r, lb, rb, r->bufsize_request, modified);
|
||||
|
||||
32
render.c
32
render.c
@@ -350,10 +350,10 @@ struct gl_data {
|
||||
int lww, lwh; /* last window height */
|
||||
int rate; /* framerate */
|
||||
double tcounter;
|
||||
int fcounter;
|
||||
int fcounter, ucounter;
|
||||
bool print_fps, avg_window;
|
||||
void** t_data;
|
||||
float gravity_step;
|
||||
float gravity_step, target_spu;
|
||||
};
|
||||
|
||||
#ifdef GLAD_DEBUG
|
||||
@@ -388,7 +388,6 @@ static struct gl_bind_src bind_sources[] = {
|
||||
#define window(t, sz) (0.53836 - (0.46164 * cos(TWOPI * (double) t / (double)(sz - 1))))
|
||||
#define ALLOC_ONCE(u, udata, ...) \
|
||||
if (*udata == NULL) { \
|
||||
printf("alloc"); \
|
||||
u = malloc(sizeof(*u)); \
|
||||
*u = (typeof(*u)) __VA_ARGS__; \
|
||||
*udata = u; \
|
||||
@@ -563,6 +562,7 @@ struct renderer* rd_new(int x, int y, int w, int h, const char* data) {
|
||||
.rate = 0,
|
||||
.tcounter = 0.0D,
|
||||
.fcounter = 0,
|
||||
.ucounter = 0,
|
||||
.print_fps = true,
|
||||
.bufscale = 1,
|
||||
.avg_frames = 4,
|
||||
@@ -805,7 +805,7 @@ struct renderer* rd_new(int x, int y, int w, int h, const char* data) {
|
||||
loading_module = false;
|
||||
|
||||
/* Iterate through shader passes in the shader directory and build textures, framebuffers, and
|
||||
shader programs with each fragment shader. */
|
||||
shader programs with each fragment shader. */
|
||||
|
||||
struct gl_sfbo* stages;
|
||||
size_t count = 0;
|
||||
@@ -870,7 +870,7 @@ struct renderer* rd_new(int x, int y, int w, int h, const char* data) {
|
||||
s->shader = id;
|
||||
|
||||
/* Only setup a framebuffer and texture if this isn't the final step,
|
||||
as it can rendered directly */
|
||||
as it can rendered directly */
|
||||
if (idx != count)
|
||||
setup_sfbo(&stages[idx - 1], w, h);
|
||||
|
||||
@@ -892,10 +892,15 @@ struct renderer* rd_new(int x, int y, int w, int h, const char* data) {
|
||||
++idx;
|
||||
} while (found);
|
||||
}
|
||||
|
||||
|
||||
gl->stages = stages;
|
||||
gl->stages_sz = count;
|
||||
|
||||
/* target seconds per update */
|
||||
gl->target_spu = (float) (r->samplesize_request / 4) / (float) r->rate_request;
|
||||
/* multiply gravity step by time occurred for each step */
|
||||
gl->gravity_step *= gl->target_spu;
|
||||
|
||||
gl->audio_tex_r = create_1d_tex();
|
||||
gl->audio_tex_l = create_1d_tex();
|
||||
|
||||
@@ -1000,16 +1005,18 @@ void rd_update(struct renderer* r, float* lb, float* rb, size_t bsz, bool modifi
|
||||
/* Handle transformations and bindings for 1D samplers */
|
||||
void handle_1d_tex(GLuint tex, float* buf, size_t sz, int offset) {
|
||||
|
||||
/* Only apply transformations if the buffers we given are newly copied from PA */
|
||||
/* Only apply transformations if the buffers we
|
||||
were given are newly copied from PA */
|
||||
if (modified) {
|
||||
size_t t;
|
||||
struct gl_sampler_data d = {
|
||||
.buf = buf, .sz = sz
|
||||
};
|
||||
|
||||
|
||||
for (t = 0; t < bind->t_sz; ++t) {
|
||||
bind->transformations[t](gl, &gl->t_data[c], &d);
|
||||
++c; /* index for transformation data (note: change if new transform types are added) */
|
||||
++c; /* Index for transformation data (note: change if new
|
||||
transform types are added) */
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1077,11 +1084,16 @@ void rd_update(struct renderer* r, float* lb, float* rb, size_t bsz, bool modifi
|
||||
/* print FPS counter (if needed) */
|
||||
if (gl->print_fps) {
|
||||
++gl->fcounter;
|
||||
if (modified)
|
||||
++gl->ucounter;
|
||||
gl->tcounter += duration;
|
||||
if (gl->tcounter >= 1.0D) {
|
||||
printf("FPS: %.2f\n", ((double) gl->fcounter / gl->tcounter));
|
||||
printf("FPS: %.2f, UPS: %.2f\n",
|
||||
((double) gl->fcounter / gl->tcounter),
|
||||
((double) gl->ucounter / gl->tcounter));
|
||||
gl->tcounter = 0;
|
||||
gl->fcounter = 0;
|
||||
gl->ucounter = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,10 +7,50 @@ uniform ivec2 screen; /* screen dimensions */
|
||||
#request uniform "audio_sz" audio_sz
|
||||
uniform int audio_sz;
|
||||
|
||||
#request setavgframes 4
|
||||
/* How many frames to queue and run through the average function */
|
||||
#request setavgframes 6
|
||||
|
||||
/* Whether to window frames ran through the average function (new & old frames
|
||||
are weighted less). This massively helps smoothing out spikes in the animation */
|
||||
#request setavgwindow true
|
||||
// #request interpolate true
|
||||
#request setgravitystep 0.06
|
||||
|
||||
/* Gravity step, higher values means faster drops. The step is applied in a rate
|
||||
independant method like so:
|
||||
|
||||
val -= (gravitystep) * (seconds per update) */
|
||||
#request setgravitystep 5.2
|
||||
|
||||
/* When we transform our audio, we need to go through the following steps:
|
||||
|
||||
transform -> "window"
|
||||
First, apply a window function to taper off the ends of the spectrum, helping
|
||||
avoid artifacts in the FFT output.
|
||||
|
||||
transform -> "fft"
|
||||
Apply the Fast Fourier Transform algorithm to separate raw audio data (waves)
|
||||
into their respective spectrums.
|
||||
|
||||
transform -> "fft"
|
||||
As part of the FFT process, we return spectrum magnitude on a log(n) scale,
|
||||
as this is how the (decibel) dB scale functions.
|
||||
|
||||
transform -> "gravity"
|
||||
To help make our data more pleasing to look at, we apply our data received over
|
||||
time to a buffer, taking the max of either the existing value in the buffer or
|
||||
the data from the input. We then reduce the data by the 'gravity step', and
|
||||
return the storage buffer.
|
||||
|
||||
This makes frequent and abrupt changes in frequency less distracting, and keeps
|
||||
short frequency responses on the screen longer.
|
||||
|
||||
transform -> "avg"
|
||||
As a final step, we take the average of several data frames (specified by
|
||||
'setavgframes') and return the result to further help smooth the resulting
|
||||
animation. In order to mitigate abrupt changes to the average, the values
|
||||
at each end of the average buffer can be weighted less with a window function
|
||||
(the same window function used at the start of this step!). It can be disabled
|
||||
with 'setavgwindow'.
|
||||
*/
|
||||
|
||||
#request uniform "audio_l" audio_l
|
||||
#request transform audio_l "window"
|
||||
|
||||
37
shaders/graph/2.frag
Normal file
37
shaders/graph/2.frag
Normal file
@@ -0,0 +1,37 @@
|
||||
|
||||
layout(pixel_center_integer) in vec4 gl_FragCoord;
|
||||
|
||||
#request uniform "prev" tex
|
||||
uniform sampler2D tex; /* screen texture */
|
||||
#request uniform "screen" screen
|
||||
uniform ivec2 screen; /* screen dimensions */
|
||||
|
||||
out vec4 fragment; /* output */
|
||||
|
||||
#define OUTLINE vec4(0.15, 0.15, 0.15, 1)
|
||||
|
||||
void main() {
|
||||
fragment = texture(tex, vec2(gl_FragCoord.x / screen.x, gl_FragCoord.y / screen.y));
|
||||
|
||||
vec4
|
||||
a0 = texture(tex, vec2((gl_FragCoord.x + 1) / screen.x, (gl_FragCoord.y + 0) / screen.y)),
|
||||
a1 = texture(tex, vec2((gl_FragCoord.x + 1) / screen.x, (gl_FragCoord.y + 1) / screen.y)),
|
||||
a2 = texture(tex, vec2((gl_FragCoord.x + 0) / screen.x, (gl_FragCoord.y + 1) / screen.y)),
|
||||
a3 = texture(tex, vec2((gl_FragCoord.x + 1) / screen.x, (gl_FragCoord.y + 0) / screen.y)),
|
||||
|
||||
a4 = texture(tex, vec2((gl_FragCoord.x - 1) / screen.x, (gl_FragCoord.y - 0) / screen.y)),
|
||||
a5 = texture(tex, vec2((gl_FragCoord.x - 1) / screen.x, (gl_FragCoord.y - 1) / screen.y)),
|
||||
a6 = texture(tex, vec2((gl_FragCoord.x - 0) / screen.x, (gl_FragCoord.y - 1) / screen.y)),
|
||||
a7 = texture(tex, vec2((gl_FragCoord.x - 1) / screen.x, (gl_FragCoord.y - 0) / screen.y));
|
||||
|
||||
vec4 avg = (a0 + a1 + a2 + a3 + a4 + a5 + a6 + a7) / 8.0;
|
||||
if (avg.a > 0){
|
||||
if (fragment.a <= 0) {
|
||||
/* outline */
|
||||
fragment = OUTLINE;
|
||||
} else if (avg.a < 1 && gl_FragCoord.y != 0) {
|
||||
/* creates a nice 'glint' along the edge of the spectrum */
|
||||
fragment.rgb *= avg.a * 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,28 +0,0 @@
|
||||
|
||||
layout(pixel_center_integer) in vec4 gl_FragCoord;
|
||||
|
||||
#request uniform "prev" tex
|
||||
uniform sampler2D tex; /* screen texture */
|
||||
#request uniform "screen" screen
|
||||
uniform ivec2 screen; /* screen dimensions */
|
||||
|
||||
out vec4 fragment; /* output */
|
||||
|
||||
void main() {
|
||||
fragment = texture(tex, vec2(gl_FragCoord.x / screen.x, gl_FragCoord.y / screen.y));
|
||||
|
||||
float a0 = texture(tex, vec2((gl_FragCoord.x + 1) / screen.x, (gl_FragCoord.y + 0) / screen.y)).a;
|
||||
float a1 = texture(tex, vec2((gl_FragCoord.x + 1) / screen.x, (gl_FragCoord.y + 1) / screen.y)).a;
|
||||
float a2 = texture(tex, vec2((gl_FragCoord.x + 0) / screen.x, (gl_FragCoord.y + 1) / screen.y)).a;
|
||||
float a3 = texture(tex, vec2((gl_FragCoord.x + 1) / screen.x, (gl_FragCoord.y + 0) / screen.y)).a;
|
||||
|
||||
float a4 = texture(tex, vec2((gl_FragCoord.x - 1) / screen.x, (gl_FragCoord.y - 0) / screen.y)).a;
|
||||
float a5 = texture(tex, vec2((gl_FragCoord.x - 1) / screen.x, (gl_FragCoord.y - 1) / screen.y)).a;
|
||||
float a6 = texture(tex, vec2((gl_FragCoord.x - 0) / screen.x, (gl_FragCoord.y - 1) / screen.y)).a;
|
||||
float a7 = texture(tex, vec2((gl_FragCoord.x - 1) / screen.x, (gl_FragCoord.y - 0) / screen.y)).a;
|
||||
|
||||
float avg = (a0 + a1 + a2 + a3 + a4 + a5 + a6 + a7) / 8.0;
|
||||
if (gl_FragCoord.y > 1) {
|
||||
fragment *= avg;
|
||||
}
|
||||
}
|
||||
@@ -33,7 +33,12 @@
|
||||
simple set to zero (or lower) to disable the frame limiter. */
|
||||
#request setframerate 0
|
||||
|
||||
/* Enable/disable printing framerate every second */
|
||||
/* Enable/disable printing framerate every second. 'FPS' stands
|
||||
for 'Frames Per Second', and 'UPS' stands for 'Updates Per
|
||||
Second'. Updates are performed when new data is submitted
|
||||
by pulseaudio, and require transformations to be re-applied
|
||||
(thus being a good measure of how much work your CPU has to
|
||||
perform over time) */
|
||||
#request setprintframes true
|
||||
|
||||
/* Audio buffer size to be used for processing and shaders.
|
||||
|
||||
Reference in New Issue
Block a user