diff --git a/Makefile b/Makefile index 27c87e3..2dc7129 100644 --- a/Makefile +++ b/Makefile @@ -1,5 +1,5 @@ CFLAGS = -std=c11 -pedantic -Wall -Wextra -O2 -Ofast -D_DEFAULT_SOURCE -D_FORTIFY_SOURCE=2 -LDFLAGS = -lX11 -lGL -lGLEW -lm -lrt +LDFLAGS = -lX11 -lGL -lGLEW -lm -lrt -lfftw3 shadermeh: shadermeh.o window.o shader.o diff --git a/shadermeh.c b/shadermeh.c index 6dd8681..3b1bf32 100644 --- a/shadermeh.c +++ b/shadermeh.c @@ -10,6 +10,7 @@ #include #define HAVE_ARCH_STRUCT_FLOCK #include +#include static GLfloat vertex_buffer[] = { -1.0f, -1.0f, 0.0f, /* lower left corner */ @@ -87,12 +88,46 @@ static int write_retry(int fd, const void *buffer, size_t size) #define SND_BUFFER_SIZE 512 +#define BBUFFER_S ((sizeof(float) * SND_BUFFER_SIZE)) + +/* Read all available input. This function presumes fd to be O_NONBLOCK */ static int read_audio_buffers(int fd, float buffer[SND_BUFFER_SIZE], unsigned int sampling_rate){ + + float temp_buf[sampling_rate]; + size_t n = 0; + memset(temp_buf, 0, sizeof(temp_buf)); + while(true){ + + int new_n = read(fd, temp_buf, sizeof(temp_buf)); + if(new_n < 0){ + if(errno == EAGAIN || errno == EWOULDBLOCK){ + break; + } + perror("Read to audio buffer failed"); + return -1; + }else if(new_n == 0){ + break; + } else if(n < sizeof(temp_buf)){ + n = new_n; + break; + } + /* Fall through and read the remaining buffer + * (last ditch effort to clear pipe) + */ + } + if(n < BBUFFER_S){ + memmove(buffer, buffer+n, BBUFFER_S - n); + memcpy(buffer+ BBUFFER_S - n, temp_buf, n); + }else{ + memcpy(buffer, (temp_buf+n-BBUFFER_S), BBUFFER_S); + } return 0; } +/* normalize the given input buffer from -1…1 in range (what alsa provides) to + * 0…1 in range (what the shadertoy shaders */ static void normalize_audio_buffers(float buffer_in[SND_BUFFER_SIZE], float buffer_out[SND_BUFFER_SIZE]){ @@ -151,6 +186,13 @@ int main(int argc, char **argv) */ float in_samples[SND_BUFFER_SIZE]; /* Raw input floats from -1...1 */ float norm_samples[SND_BUFFER_SIZE]; /* Normalized samples from 0...1 */ + fftw_complex fftw_in[SND_BUFFER_SIZE]; + fftw_complex fftw_out[SND_BUFFER_SIZE]; + fftw_plan plan = fftw_plan_dft_1d(SND_BUFFER_SIZE, + fftw_in, + fftw_out, + FFTW_FORWARD, + FFTW_ESTIMATE); /******************** parse options ************************/ width = 800; @@ -236,8 +278,8 @@ int main(int argc, char **argv) } } } - if (sampling_rate != 0 && !isatty(STDIN_FILENO)){ - fputs("Sampling rate specified and STDIN not a tty! " + if (sampling_rate != 0 && isatty(STDIN_FILENO)){ + fputs("Sampling rate specified and STDIN a tty! " "You habe been warnded!\n", stderr); } if(sampling_rate != 0){ @@ -367,6 +409,12 @@ int main(int argc, char **argv) break; } normalize_audio_buffers(in_samples, norm_samples); + memset(fftw_in, 0, sizeof(fftw_in)); + memset(fftw_out, 0, sizeof(fftw_out)); + for(size_t i = 0; i < SND_BUFFER_SIZE; i++){ + fftw_in[i][0] = norm_samples[i]; + } + fftw_execute(plan); } /* update timers */ @@ -399,5 +447,6 @@ int main(int argc, char **argv) free(fb32); free(fb24); window_destroy(wnd); + fftw_destroy_plan(plan); return EXIT_SUCCESS; }