diff --git a/examples/audio/audio_fft_spectrum_visualizer.c b/examples/audio/audio_fft_spectrum_visualizer.c index 299b610ee..c667b5d6a 100644 --- a/examples/audio/audio_fft_spectrum_visualizer.c +++ b/examples/audio/audio_fft_spectrum_visualizer.c @@ -19,11 +19,19 @@ ********************************************************************************************/ #include "raylib.h" + #include "raymath.h" + #include #include #include +#if defined(PLATFORM_DESKTOP) + #define GLSL_VERSION 330 +#else // PLATFORM_ANDROID, PLATFORM_WEB + #define GLSL_VERSION 100 +#endif + #define MONO 1 #define SAMPLE_RATE 44100 #define SAMPLE_RATE_F 44100.0f @@ -77,7 +85,8 @@ int main(void) RenderTexture2D bufferA = LoadRenderTexture(screenWidth, screenHeight); Vector2 iResolution = { (float)screenWidth, (float)screenHeight }; - Shader shader = LoadShader(NULL, "resources/fft.glsl"); + Shader shader = LoadShader(0, TextFormat("resources/shaders/glsl%i/fft.fs", GLSL_VERSION)); + int iResolutionLocation = GetShaderLocation(shader, "iResolution"); int iChannel0Location = GetShaderLocation(shader, "iChannel0"); SetShaderValue(shader, iResolutionLocation, &iResolution, SHADER_UNIFORM_VEC2); @@ -86,6 +95,7 @@ int main(void) InitAudioDevice(); SetAudioStreamBufferSizeDefault(AUDIO_STREAM_RING_BUFFER_SIZE); + // WARNING: Memory out-of-bounds on PLATFORM_WEB Wave wav = LoadWave("resources/country.mp3"); WaveFormat(&wav, SAMPLE_RATE, PER_SAMPLE_BIT_DEPTH, MONO); @@ -95,10 +105,10 @@ int main(void) int fftHistoryLen = (int)ceilf(FFT_HISTORICAL_SMOOTHING_DUR/WINDOW_TIME) + 1; FFTData fft = { - .spectrum = malloc(sizeof(FFTComplex)*FFT_WINDOW_SIZE), - .workBuffer = malloc(sizeof(FFTComplex)*FFT_WINDOW_SIZE), - .prevMagnitudes = calloc(BUFFER_SIZE, sizeof(float)), - .fftHistory = calloc(fftHistoryLen, sizeof(float[BUFFER_SIZE])), + .spectrum = RL_CALLOC(sizeof(FFTComplex), FFT_WINDOW_SIZE), + .workBuffer = RL_CALLOC(sizeof(FFTComplex), FFT_WINDOW_SIZE), + .prevMagnitudes = RL_CALLOC(BUFFER_SIZE, sizeof(float)), + .fftHistory = RL_CALLOC(fftHistoryLen, sizeof(float[BUFFER_SIZE])), .fftHistoryLen = fftHistoryLen, .historyPos = 0, .lastFftTime = 0.0, @@ -127,15 +137,12 @@ int main(void) int right = (wav.channels == 2)? wavPCM16[wavCursor*2 + 1] : left; chunkSamples[i] = (short)((left + right)/2); - if (++wavCursor >= wav.frameCount) - wavCursor = 0; - + if (++wavCursor >= wav.frameCount) wavCursor = 0; } UpdateAudioStream(audioStream, chunkSamples, AUDIO_STREAM_RING_BUFFER_SIZE); - for (int i = 0; i < FFT_WINDOW_SIZE; i++) - audioSamples[i] = (chunkSamples[i*2] + chunkSamples[i*2 + 1])*0.5f/32767.0f; + for (int i = 0; i < FFT_WINDOW_SIZE; i++) audioSamples[i] = (chunkSamples[i*2] + chunkSamples[i*2 + 1])*0.5f/32767.0f; } CaptureFrame(&fft, audioSamples); @@ -146,14 +153,16 @@ int main(void) // Draw //---------------------------------------------------------------------------------- BeginDrawing(); - ClearBackground(BLACK); + + ClearBackground(RAYWHITE); + BeginShaderMode(shader); SetShaderValueTexture(shader, iChannel0Location, fftTexture); DrawTextureRec(bufferA.texture, (Rectangle){ 0, 0, (float)screenWidth, (float)-screenHeight }, - (Vector2){ 0, 0 }, - WHITE); + (Vector2){ 0, 0 }, WHITE); EndShaderMode(); + EndDrawing(); //------------------------------------------------------------------------------ } @@ -168,10 +177,10 @@ int main(void) UnloadWave(wav); CloseAudioDevice(); - free(fft.spectrum); - free(fft.workBuffer); - free(fft.prevMagnitudes); - free(fft.fftHistory); + RL_FREE(fft.spectrum); + RL_FREE(fft.workBuffer); + RL_FREE(fft.prevMagnitudes); + RL_FREE(fft.fftHistory); CloseWindow(); // Close window and OpenGL context //---------------------------------------------------------------------------------- diff --git a/examples/audio/resources/fft.glsl b/examples/audio/resources/fft.glsl deleted file mode 100644 index 95fd4b38f..000000000 --- a/examples/audio/resources/fft.glsl +++ /dev/null @@ -1,32 +0,0 @@ -#version 330 - -in vec2 fragTexCoord; -in vec4 fragColor; - -out vec4 finalColor; - -uniform vec2 iResolution; -uniform sampler2D iChannel0; - -const vec4 BLACK = vec4(0.0, 0.0, 0.0, 1.0); -const vec4 WHITE = vec4(1.0, 1.0, 1.0, 1.0); -const float FFT_ROW = 0.0; -const float NUM_OF_BINS = 512.0; - -void main() { - vec2 fragCoord = fragTexCoord*iResolution; - float cell_width = iResolution.x/NUM_OF_BINS; - float bin_index = floor(fragCoord.x/cell_width); - float local_x = mod(fragCoord.x, cell_width); - float bar_width = cell_width - 1.0; - vec4 color = BLACK; - if (local_x <= bar_width) { - float sample_x = (bin_index + 0.5)/NUM_OF_BINS; - vec2 sample_coord = vec2(sample_x, FFT_ROW); - float amplitude = texture(iChannel0, sample_coord).r; // only filled the red channel, all channels left open for alternative use - if (fragTexCoord.y < amplitude) { - color = WHITE; - } - } - finalColor = color; -} diff --git a/examples/audio/resources/shaders/glsl100/fft.fs b/examples/audio/resources/shaders/glsl100/fft.fs new file mode 100644 index 000000000..a97bf336b --- /dev/null +++ b/examples/audio/resources/shaders/glsl100/fft.fs @@ -0,0 +1,37 @@ +#version 100 + +precision mediump float; + +// Input vertex attributes (from vertex shader) +varying vec2 fragTexCoord; +varying vec4 fragColor; + +// Input uniform values +uniform vec2 iResolution; +uniform sampler2D iChannel0; + +const vec4 BLACK = vec4(0.0, 0.0, 0.0, 1.0); +const vec4 WHITE = vec4(1.0, 1.0, 1.0, 1.0); +const float FFT_ROW = 0.0; +const float NUM_OF_BINS = 512.0; + +void main() +{ + vec2 fragCoord = fragTexCoord*iResolution; + float cellWidth = iResolution.x/NUM_OF_BINS; + float binIndex = floor(fragCoord.x/cellWidth); + float localX = mod(fragCoord.x, cellWidth); + float barWidth = cellWidth - 1.0; + vec4 color = WHITE; + + if (localX <= barWidth) + { + float sampleX = (binIndex + 0.5)/NUM_OF_BINS; + vec2 sampleCoord = vec2(sampleX, FFT_ROW); + float amplitude = texture2D(iChannel0, sampleCoord).r; // Only filled the red channel, all channels left open for alternative use + + if (fragTexCoord.y < amplitude) color = BLACK; + } + + gl_FragColor = color; +} diff --git a/examples/audio/resources/shaders/glsl120/fft.fs b/examples/audio/resources/shaders/glsl120/fft.fs new file mode 100644 index 000000000..bab5d533b --- /dev/null +++ b/examples/audio/resources/shaders/glsl120/fft.fs @@ -0,0 +1,35 @@ +#version 120 + +// Input vertex attributes (from vertex shader) +varying vec2 fragTexCoord; +varying vec4 fragColor; + +// Input uniform values +uniform vec2 iResolution; +uniform sampler2D iChannel0; + +const vec4 BLACK = vec4(0.0, 0.0, 0.0, 1.0); +const vec4 WHITE = vec4(1.0, 1.0, 1.0, 1.0); +const float FFT_ROW = 0.0; +const float NUM_OF_BINS = 512.0; + +void main() +{ + vec2 fragCoord = fragTexCoord*iResolution; + float cellWidth = iResolution.x/NUM_OF_BINS; + float binIndex = floor(fragCoord.x/cellWidth); + float localX = mod(fragCoord.x, cellWidth); + float barWidth = cellWidth - 1.0; + vec4 color = WHITE; + + if (localX <= barWidth) + { + float sampleX = (binIndex + 0.5)/NUM_OF_BINS; + vec2 sampleCoord = vec2(sampleX, FFT_ROW); + float amplitude = texture2D(iChannel0, sampleCoord).r; // Only filled the red channel, all channels left open for alternative use + + if (fragTexCoord.y < amplitude) color = BLACK; + } + + gl_FragColor = color; +} diff --git a/examples/audio/resources/shaders/glsl330/fft.fs b/examples/audio/resources/shaders/glsl330/fft.fs new file mode 100644 index 000000000..20b2e9dfa --- /dev/null +++ b/examples/audio/resources/shaders/glsl330/fft.fs @@ -0,0 +1,35 @@ +#version 330 + +in vec2 fragTexCoord; +in vec4 fragColor; + +out vec4 finalColor; + +uniform vec2 iResolution; +uniform sampler2D iChannel0; + +const vec4 BLACK = vec4(0.0, 0.0, 0.0, 1.0); +const vec4 WHITE = vec4(1.0, 1.0, 1.0, 1.0); +const float FFT_ROW = 0.0; +const float NUM_OF_BINS = 512.0; + +void main() +{ + vec2 fragCoord = fragTexCoord*iResolution; + float cellWidth = iResolution.x/NUM_OF_BINS; + float binIndex = floor(fragCoord.x/cellWidth); + float localX = mod(fragCoord.x, cellWidth); + float barWidth = cellWidth - 1.0; + vec4 color = WHITE; + + if (localX <= barWidth) + { + float sampleX = (binIndex + 0.5)/NUM_OF_BINS; + vec2 sampleCoord = vec2(sampleX, FFT_ROW); + float amplitude = texture(iChannel0, sampleCoord).r; // Only filled the red channel, all channels left open for alternative use + + if (fragTexCoord.y < amplitude) color = BLACK; + } + + finalColor = color; +}