forked from goliath/shadermeh
Implement sound buffer texture
Texture channel 0 has a 512x2 texture with audio samples. For now, fill it with dummy data (ascending slope), so we can see some output. Signed-off-by: David Oberhollenzer <goliath@infraroot.at>
This commit is contained in:
parent
542669ef04
commit
8c47f2726c
4 changed files with 96 additions and 3 deletions
1
shader.c
1
shader.c
|
@ -31,6 +31,7 @@ static const char *frag_src_pre =
|
|||
"uniform vec4 iDate;\n"
|
||||
"uniform float iSampleRate;\n"
|
||||
"uniform vec3 iChannelResolution[4];\n"
|
||||
"uniform sampler2D iChannel0;"
|
||||
"\n";
|
||||
|
||||
static const char *frag_src_post =
|
||||
|
|
55
shadermeh.c
55
shadermeh.c
|
@ -20,6 +20,9 @@ static GLfloat vertex_buffer[] = {
|
|||
1.0f, 1.0f, 1.0f,
|
||||
};
|
||||
|
||||
static GLubyte audio_buffer[AUDIO_SAMPLES * AUDIO_CHANNELS];
|
||||
static float audio_sample_data[AUDIO_SAMPLES];
|
||||
|
||||
static double diff_timespec(const struct timespec *time1,
|
||||
const struct timespec *time0)
|
||||
{
|
||||
|
@ -72,10 +75,11 @@ static const struct option long_opts[] = {
|
|||
{ "height", required_argument, NULL, 'h' },
|
||||
{ "shader", required_argument, NULL, 's' },
|
||||
{ "to-stdout", no_argument, NULL, 'S' },
|
||||
{ "stdin-audio", no_argument, NULL, 'a' },
|
||||
{ NULL, 0, NULL, 0 },
|
||||
};
|
||||
|
||||
static const char *short_opts = "w:h:s:S";
|
||||
static const char *short_opts = "w:h:s:Sa";
|
||||
|
||||
static const char *usage_str =
|
||||
"shadermeh OPTIONS...\n"
|
||||
|
@ -85,21 +89,23 @@ static const char *usage_str =
|
|||
" --width, -w <pixels>\n"
|
||||
" --height, -h <pixels>\n"
|
||||
"\n"
|
||||
" --to-stdout, -S\n"
|
||||
" --to-stdout, -S Poop raw RGB24 frames to stdout (blocking)\n"
|
||||
" --stdin-audio, -a Read raw PCM audio from stdin (non-blocking)\n"
|
||||
"\n"
|
||||
" --shader, -s <shader file>\n"
|
||||
"\n";
|
||||
|
||||
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;
|
||||
struct timespec start, frame_start, frame_end;
|
||||
unsigned int width, height, iFrame = 0;
|
||||
void *fb32 = NULL, *fb24 = NULL;
|
||||
const char *shader_file = NULL;
|
||||
GLuint vao, vbo, fbo, fbo_tex;
|
||||
GLint major, minor, prog;
|
||||
float iTime, iTimeDelta;
|
||||
bool have_audio = false;
|
||||
bool to_stdout = false;
|
||||
window *wnd;
|
||||
int i;
|
||||
|
@ -126,6 +132,9 @@ int main(int argc, char **argv)
|
|||
case 'S':
|
||||
to_stdout = true;
|
||||
break;
|
||||
case 'a':
|
||||
have_audio = true;
|
||||
break;
|
||||
default:
|
||||
fputs(usage_str, stderr);
|
||||
return EXIT_FAILURE;
|
||||
|
@ -222,6 +231,22 @@ int main(int argc, char **argv)
|
|||
|
||||
glUniform3f(u_iResolution, width, height, 0.0f);
|
||||
|
||||
glUniform1i(glGetUniformLocation(prog, "iChannel0"), 0);
|
||||
|
||||
/************************* 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 ********************/
|
||||
if (to_stdout) {
|
||||
glGenFramebuffers(1, &fbo);
|
||||
|
@ -242,6 +267,10 @@ int main(int argc, char **argv)
|
|||
}
|
||||
|
||||
/******************** 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()) {
|
||||
|
@ -252,7 +281,24 @@ int main(int argc, char **argv)
|
|||
glBindFramebuffer(GL_FRAMEBUFFER, fbo);
|
||||
|
||||
glClear(GL_COLOR_BUFFER_BIT);
|
||||
|
||||
if (have_audio) {
|
||||
glBindTexture(GL_TEXTURE_2D, sound_tex);
|
||||
|
||||
for (i = 0; i < AUDIO_SAMPLES; ++i) {
|
||||
audio_buffer[i] = 255.0f * audio_sample_data[i];
|
||||
|
||||
audio_buffer[AUDIO_SAMPLES + i] =
|
||||
audio_buffer[i];
|
||||
}
|
||||
|
||||
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);
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
|
||||
if (to_stdout) {
|
||||
glFlush();
|
||||
|
@ -291,6 +337,9 @@ int main(int argc, char **argv)
|
|||
}
|
||||
|
||||
/******************** cleanup ********************/
|
||||
glDeleteTextures(1, &sound_tex);
|
||||
glDeleteSamplers(1, &sampler_sound);
|
||||
|
||||
if (to_stdout) {
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||
glDeleteFramebuffers(1, &fbo);
|
||||
|
|
|
@ -25,6 +25,9 @@
|
|||
#include <errno.h>
|
||||
#include <time.h>
|
||||
|
||||
#define AUDIO_SAMPLES (512)
|
||||
#define AUDIO_CHANNELS (2)
|
||||
|
||||
typedef struct {
|
||||
Window wnd;
|
||||
GLXContext gl;
|
||||
|
|
40
shaders/osci.frag
Normal file
40
shaders/osci.frag
Normal file
|
@ -0,0 +1,40 @@
|
|||
// 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);
|
||||
}
|
Loading…
Reference in a new issue