Compare commits

..

No commits in common. "f3bf686a529b4f42bde189b66137103feac817af" and "4123b78a812f6f3617669ec6b8a552f4618e44c7" have entirely different histories.

4 changed files with 12 additions and 201 deletions

View file

@ -31,7 +31,6 @@ static const char *frag_src_pre =
"uniform vec4 iDate;\n" "uniform vec4 iDate;\n"
"uniform float iSampleRate;\n" "uniform float iSampleRate;\n"
"uniform vec3 iChannelResolution[4];\n" "uniform vec3 iChannelResolution[4];\n"
"uniform sampler2D iChannel0;"
"\n"; "\n";
static const char *frag_src_post = static const char *frag_src_post =

View file

@ -20,42 +20,6 @@ static GLfloat vertex_buffer[] = {
1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f,
}; };
static GLubyte audio_buffer[AUDIO_SAMPLES * AUDIO_CHANNELS];
static float audio_sample_data[AUDIO_SAMPLES];
static int try_fetch_audio(void)
{
size_t i, count = 0;
int ret;
for (;;) {
ret = read(STDIN_FILENO,
(char *)audio_sample_data + count,
sizeof(audio_sample_data) - count);
if (ret < 0) {
if (errno == EINTR)
continue;
if (errno == EAGAIN)
break;
perror("stdin");
return -1;
}
if (ret == 0)
break;
count += ret;
}
for (i = 0; i < (count / sizeof(float)); ++i) {
audio_buffer[i + AUDIO_SAMPLES] = audio_sample_data[i] * 127.0f + 127.0f;
audio_buffer[i] = 0.0f;
}
return 0;
}
static double diff_timespec(const struct timespec *time1, static double diff_timespec(const struct timespec *time1,
const struct timespec *time0) const struct timespec *time0)
{ {
@ -81,39 +45,6 @@ static void convert_for_ffmpeg(const uint8_t *in, uint8_t *out,
} }
} }
static int wait_fd_event(int fd, int events)
{
struct pollfd pfd;
int ret;
for (;;) {
pfd.fd = fd;
pfd.events = events;
pfd.revents = 0;
ret = poll(&pfd, 1, -1);
if (ret > 0) {
if (pfd.revents & events)
break;
if (pfd.revents & (POLLERR | POLLHUP)) {
fputs("poll reported error\n", stderr);
return -1;
}
}
if (ret < 0) {
if (errno == EINTR)
continue;
perror("poll");
return -1;
}
}
return 0;
}
static int write_retry(int fd, const void *buffer, size_t size) static int write_retry(int fd, const void *buffer, size_t size)
{ {
while (size > 0) { while (size > 0) {
@ -122,13 +53,6 @@ static int write_retry(int fd, const void *buffer, size_t size)
if (ret < 0) { if (ret < 0) {
if (errno == EINTR) if (errno == EINTR)
continue; continue;
if (errno == EAGAIN) {
if (wait_fd_event(fd, POLLOUT))
return -1;
continue;
}
perror("write"); perror("write");
return -1; return -1;
} }
@ -148,11 +72,10 @@ static const struct option long_opts[] = {
{ "height", required_argument, NULL, 'h' }, { "height", required_argument, NULL, 'h' },
{ "shader", required_argument, NULL, 's' }, { "shader", required_argument, NULL, 's' },
{ "to-stdout", no_argument, NULL, 'S' }, { "to-stdout", no_argument, NULL, 'S' },
{ "stdin-audio", no_argument, NULL, 'a' },
{ NULL, 0, NULL, 0 }, { NULL, 0, NULL, 0 },
}; };
static const char *short_opts = "w:h:s:Sa"; static const char *short_opts = "w:h:s:S";
static const char *usage_str = static const char *usage_str =
"shadermeh OPTIONS...\n" "shadermeh OPTIONS...\n"
@ -162,23 +85,21 @@ static const char *usage_str =
" --width, -w <pixels>\n" " --width, -w <pixels>\n"
" --height, -h <pixels>\n" " --height, -h <pixels>\n"
"\n" "\n"
" --to-stdout, -S Poop raw RGB24 frames to stdout (blocking)\n" " --to-stdout, -S\n"
" --stdin-audio, -a Read raw PCM audio from stdin (non-blocking)\n"
"\n" "\n"
" --shader, -s <shader file>\n" " --shader, -s <shader file>\n"
"\n"; "\n";
int main(int argc, char **argv) int main(int argc, char **argv)
{ {
GLuint vao, vbo, fbo, fbo_tex, sound_tex, sampler_sound;
GLuint u_iResolution, u_iTime, u_iTimeDelta, u_iFrame; GLuint u_iResolution, u_iTime, u_iTimeDelta, u_iFrame;
struct timespec start, frame_start, frame_end; struct timespec start, frame_start, frame_end;
unsigned int width, height, iFrame = 0; unsigned int width, height, iFrame = 0;
void *fb32 = NULL, *fb24 = NULL; void *fb32 = NULL, *fb24 = NULL;
const char *shader_file = NULL; const char *shader_file = NULL;
GLuint vao, vbo, fbo, fbo_tex;
GLint major, minor, prog; GLint major, minor, prog;
float iTime, iTimeDelta; float iTime, iTimeDelta;
bool have_audio = false;
bool to_stdout = false; bool to_stdout = false;
window *wnd; window *wnd;
int i; int i;
@ -205,24 +126,12 @@ int main(int argc, char **argv)
case 'S': case 'S':
to_stdout = true; to_stdout = true;
break; break;
case 'a':
have_audio = true;
break;
default: default:
fputs(usage_str, stderr); fputs(usage_str, stderr);
return EXIT_FAILURE; return EXIT_FAILURE;
} }
} }
if (have_audio) {
int flags = fcntl(STDIN_FILENO, F_GETFL, 0);
if (fcntl(STDIN_FILENO, F_SETFL, flags | O_NONBLOCK)) {
perror("making stdin non-blocking");
return EXIT_FAILURE;
}
}
if (!shader_file) { if (!shader_file) {
fputs(usage_str, stderr); fputs(usage_str, stderr);
fputs("No shader file specified!\n", stderr); fputs("No shader file specified!\n", stderr);
@ -270,8 +179,6 @@ int main(int argc, char **argv)
glGetIntegerv(GL_MAJOR_VERSION, &major); glGetIntegerv(GL_MAJOR_VERSION, &major);
glGetIntegerv(GL_MINOR_VERSION, &minor); glGetIntegerv(GL_MINOR_VERSION, &minor);
if (!to_stdout)
printf("OpenGL version %d.%d\n", major, minor); printf("OpenGL version %d.%d\n", major, minor);
/******************** initialization ********************/ /******************** initialization ********************/
@ -300,7 +207,6 @@ int main(int argc, char **argv)
if (!shader_program_get_build_status(prog)) { if (!shader_program_get_build_status(prog)) {
shader_program_print_info_log(prog); shader_program_print_info_log(prog);
goto fail_vao;
} }
glUseProgram(prog); glUseProgram(prog);
@ -309,25 +215,11 @@ int main(int argc, char **argv)
u_iResolution = glGetUniformLocation(prog, "iResolution"); u_iResolution = glGetUniformLocation(prog, "iResolution");
u_iTime = glGetUniformLocation(prog, "iTime"); u_iTime = glGetUniformLocation(prog, "iTime");
u_iTimeDelta = glGetUniformLocation(prog, "iTimeDelta"); u_iTimeDelta = glGetUniformLocation(prog, "iTimeDelta");
u_iFrame = glGetUniformLocation(prog, "iFrame"); u_iFrame = glGetUniformLocation(prog, "iFrame;");
glUniform3f(u_iResolution, width, height, 0.0f); glUniform3f(u_iResolution, width, height, 0.0f);
glUniform1i(glGetUniformLocation(prog, "iChannel0"), 0); clock_gettime(CLOCK_MONOTONIC_RAW, &start);
/************************* textures *************************/
glGenTextures(1, &sound_tex);
glBindTexture(GL_TEXTURE_2D, sound_tex);
glTexImage2D(GL_TEXTURE_2D, 0, GL_R8,
AUDIO_SAMPLES, AUDIO_CHANNELS, 0,
GL_RED, GL_UNSIGNED_BYTE, audio_buffer);
glBindTexture(GL_TEXTURE_2D, 0);
glGenSamplers(1, &sampler_sound);
glSamplerParameteri(sampler_sound, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glSamplerParameteri(sampler_sound, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glBindSampler(0, sampler_sound);
/******************** framebuffer object ********************/ /******************** framebuffer object ********************/
if (to_stdout) { if (to_stdout) {
@ -337,46 +229,20 @@ int main(int argc, char **argv)
glBindTexture(GL_TEXTURE_2D, fbo_tex); glBindTexture(GL_TEXTURE_2D, fbo_tex);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0,
GL_RGBA, GL_UNSIGNED_BYTE, NULL); GL_RGBA, GL_UNSIGNED_BYTE, NULL);
glBindTexture(GL_TEXTURE_2D, 0);
glBindFramebuffer(GL_FRAMEBUFFER, fbo); glBindFramebuffer(GL_FRAMEBUFFER, fbo);
glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
fbo_tex, 0); fbo_tex, 0);
glBindFramebuffer(GL_FRAMEBUFFER, 0);
} else { } else {
window_show(wnd); window_show(wnd);
} }
/******************** drawing loop ********************/ /******************** drawing loop ********************/
for (i = 0; i < AUDIO_SAMPLES; ++i) {
audio_sample_data[i] = (float)i / (float)AUDIO_SAMPLES;
}
clock_gettime(CLOCK_MONOTONIC_RAW, &start);
while (to_stdout || window_handle_events()) { while (to_stdout || window_handle_events()) {
/* render image to FBO */ /* render image to FBO */
clock_gettime(CLOCK_MONOTONIC_RAW, &frame_start); clock_gettime(CLOCK_MONOTONIC_RAW, &frame_start);
if (to_stdout)
glBindFramebuffer(GL_FRAMEBUFFER, fbo);
glClear(GL_COLOR_BUFFER_BIT); glClear(GL_COLOR_BUFFER_BIT);
if (have_audio) {
if (try_fetch_audio())
break;
glBindTexture(GL_TEXTURE_2D, sound_tex);
glTexImage2D(GL_TEXTURE_2D, 0, GL_R8,
AUDIO_SAMPLES, AUDIO_CHANNELS, 0,
GL_RED, GL_UNSIGNED_BYTE, audio_buffer);
}
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
glBindTexture(GL_TEXTURE_2D, 0);
if (to_stdout) { if (to_stdout) {
glFlush(); glFlush();
@ -386,14 +252,9 @@ int main(int argc, char **argv)
/* get image from FBO, dump to stdout */ /* get image from FBO, dump to stdout */
if (to_stdout) { if (to_stdout) {
glBindFramebuffer(GL_FRAMEBUFFER, 0);
glBindTexture(GL_TEXTURE_2D, fbo_tex);
glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA,
GL_UNSIGNED_BYTE, fb32); GL_UNSIGNED_BYTE, fb32);
glBindTexture(GL_TEXTURE_2D, 0);
convert_for_ffmpeg(fb32, fb24, width, height); convert_for_ffmpeg(fb32, fb24, width, height);
if (write_retry(STDOUT_FILENO, fb24, if (write_retry(STDOUT_FILENO, fb24,
@ -415,8 +276,12 @@ int main(int argc, char **argv)
} }
/******************** cleanup ********************/ /******************** cleanup ********************/
glDeleteTextures(1, &sound_tex); glUseProgram(0);
glDeleteSamplers(1, &sampler_sound); glBindBuffer(GL_ARRAY_BUFFER, 0);
glDeleteBuffers(1, &vbo);
glBindVertexArray(0);
glDeleteVertexArrays(1, &vao);
glDeleteProgram(prog);
if (to_stdout) { if (to_stdout) {
glBindFramebuffer(GL_FRAMEBUFFER, 0); glBindFramebuffer(GL_FRAMEBUFFER, 0);
@ -424,14 +289,6 @@ int main(int argc, char **argv)
glDeleteTextures(1, &fbo_tex); glDeleteTextures(1, &fbo_tex);
} }
glUseProgram(0);
glDeleteProgram(prog);
fail_vao:
glBindBuffer(GL_ARRAY_BUFFER, 0);
glDeleteBuffers(1, &vbo);
glBindVertexArray(0);
glDeleteVertexArrays(1, &vao);
window_make_current(NULL); window_make_current(NULL);
free(fb32); free(fb32);
free(fb24); free(fb24);

View file

@ -23,13 +23,8 @@
#include <unistd.h> #include <unistd.h>
#include <stdio.h> #include <stdio.h>
#include <errno.h> #include <errno.h>
#include <fcntl.h>
#include <poll.h>
#include <time.h> #include <time.h>
#define AUDIO_SAMPLES (512)
#define AUDIO_CHANNELS (2)
typedef struct { typedef struct {
Window wnd; Window wnd;
GLXContext gl; GLXContext gl;

View file

@ -1,40 +0,0 @@
// Created by inigo quilez - iq/2013
// https://www.youtube.com/c/InigoQuilez
// https://iquilezles.org/
// See also:
//
// Input - Keyboard : https://www.shadertoy.com/view/lsXGzf
// Input - Microphone : https://www.shadertoy.com/view/llSGDh
// Input - Mouse : https://www.shadertoy.com/view/Mss3zH
// Input - Sound : https://www.shadertoy.com/view/Xds3Rr
// Input - SoundCloud : https://www.shadertoy.com/view/MsdGzn
// Input - Time : https://www.shadertoy.com/view/lsXGz8
// Input - TimeDelta : https://www.shadertoy.com/view/lsKGWV
// Inout - 3D Texture : https://www.shadertoy.com/view/4llcR4
void mainImage( out vec4 fragColor, in vec2 fragCoord )
{
// create pixel coordinates
vec2 uv = fragCoord.xy / iResolution.xy;
// the sound texture is 512x2
int tx = int(uv.x * 512.0);
// first row is frequency data (48Khz/4 in 512 texels, meaning 23 Hz per texel)
float fft = texelFetch( iChannel0, ivec2(tx,0), 0 ).x;
// second row is the sound wave, one texel is one mono sample
float wave = texelFetch( iChannel0, ivec2(tx,1), 0 ).x;
// convert frequency to colors
vec3 col = vec3( fft, 4.0*fft*(1.0-fft), 1.0-fft ) * fft;
// add wave form on top
col += 1.0 - smoothstep(0.0, 0.15, abs(wave - uv.y));
// output final color
fragColor = vec4(col,1.0);
}