Add fft
This commit is contained in:
@ -108,7 +108,7 @@
|
|||||||
</GenerateManifest>
|
</GenerateManifest>
|
||||||
<ExecutablePath>$(SolutionDir);$(ExecutablePath)</ExecutablePath>
|
<ExecutablePath>$(SolutionDir);$(ExecutablePath)</ExecutablePath>
|
||||||
<TargetName>leviathan-release</TargetName>
|
<TargetName>leviathan-release</TargetName>
|
||||||
<IgnoreImportLibrary>true</IgnoreImportLibrary>
|
<IgnoreImportLibrary>false</IgnoreImportLibrary>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Heavy Release|Win32'">
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Heavy Release|Win32'">
|
||||||
<OutDir>out\</OutDir>
|
<OutDir>out\</OutDir>
|
||||||
@ -146,7 +146,7 @@
|
|||||||
<ClCompile>
|
<ClCompile>
|
||||||
<Optimization>MinSpace</Optimization>
|
<Optimization>MinSpace</Optimization>
|
||||||
<AdditionalIncludeDirectories>../;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
<AdditionalIncludeDirectories>../;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||||
<PreprocessorDefinitions>EDITOR_CONTROLS;_DEBUG;WINDOWS;DEBUG;SIMD;A32BITS;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
<PreprocessorDefinitions>_DEBUG;WINDOWS;DEBUG;SIMD;A32BITS;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
<BasicRuntimeChecks>Default</BasicRuntimeChecks>
|
<BasicRuntimeChecks>Default</BasicRuntimeChecks>
|
||||||
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
|
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
|
||||||
<PrecompiledHeaderOutputFile>
|
<PrecompiledHeaderOutputFile>
|
||||||
@ -167,9 +167,11 @@
|
|||||||
<ExceptionHandling>Sync</ExceptionHandling>
|
<ExceptionHandling>Sync</ExceptionHandling>
|
||||||
<BufferSecurityCheck>false</BufferSecurityCheck>
|
<BufferSecurityCheck>false</BufferSecurityCheck>
|
||||||
<CallingConvention>StdCall</CallingConvention>
|
<CallingConvention>StdCall</CallingConvention>
|
||||||
<OmitDefaultLibName>false</OmitDefaultLibName>
|
<OmitDefaultLibName>true</OmitDefaultLibName>
|
||||||
<LanguageStandard>
|
<LanguageStandard>
|
||||||
</LanguageStandard>
|
</LanguageStandard>
|
||||||
|
<EnableEnhancedInstructionSet>NoExtensions</EnableEnhancedInstructionSet>
|
||||||
|
<FloatingPointModel>Fast</FloatingPointModel>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<ResourceCompile>
|
<ResourceCompile>
|
||||||
<PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
<PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
@ -333,7 +335,7 @@ shader_minifier.exe -v -o src\shaders\post.inl src\shaders\post.frag</Command>
|
|||||||
<WholeProgramOptimization>false</WholeProgramOptimization>
|
<WholeProgramOptimization>false</WholeProgramOptimization>
|
||||||
<SmallerTypeCheck>false</SmallerTypeCheck>
|
<SmallerTypeCheck>false</SmallerTypeCheck>
|
||||||
<BasicRuntimeChecks>Default</BasicRuntimeChecks>
|
<BasicRuntimeChecks>Default</BasicRuntimeChecks>
|
||||||
<EnableEnhancedInstructionSet>NotSet</EnableEnhancedInstructionSet>
|
<EnableEnhancedInstructionSet>NoExtensions</EnableEnhancedInstructionSet>
|
||||||
<OmitDefaultLibName>true</OmitDefaultLibName>
|
<OmitDefaultLibName>true</OmitDefaultLibName>
|
||||||
<DisableLanguageExtensions>false</DisableLanguageExtensions>
|
<DisableLanguageExtensions>false</DisableLanguageExtensions>
|
||||||
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
|
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
|
||||||
@ -585,6 +587,7 @@ shader_minifier.exe -v -o src\shaders\post.inl src\shaders\post.frag</Command>
|
|||||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Snapshot|Win32'">true</ExcludedFromBuild>
|
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Snapshot|Win32'">true</ExcludedFromBuild>
|
||||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
|
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
|
||||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Heavy Release|Win32'">true</ExcludedFromBuild>
|
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Heavy Release|Win32'">true</ExcludedFromBuild>
|
||||||
|
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
<ClInclude Include="src\debug.h">
|
<ClInclude Include="src\debug.h">
|
||||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">false</ExcludedFromBuild>
|
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">false</ExcludedFromBuild>
|
||||||
@ -592,6 +595,7 @@ shader_minifier.exe -v -o src\shaders\post.inl src\shaders\post.frag</Command>
|
|||||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Snapshot|Win32'">false</ExcludedFromBuild>
|
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Snapshot|Win32'">false</ExcludedFromBuild>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
<ClInclude Include="src\definitions.h" />
|
<ClInclude Include="src\definitions.h" />
|
||||||
|
<ClInclude Include="src\fft.h" />
|
||||||
<ClInclude Include="src\fp.h" />
|
<ClInclude Include="src\fp.h" />
|
||||||
<ClInclude Include="src\glext.h" />
|
<ClInclude Include="src\glext.h" />
|
||||||
<ClInclude Include="src\sointu\song.h" />
|
<ClInclude Include="src\sointu\song.h" />
|
||||||
@ -605,10 +609,10 @@ shader_minifier.exe -v -o src\shaders\post.inl src\shaders\post.frag</Command>
|
|||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClCompile Include="src\editor.cpp">
|
<ClCompile Include="src\editor.cpp">
|
||||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Snapshot|Win32'">true</ExcludedFromBuild>
|
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
|
||||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
|
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
|
||||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Heavy Release|Win32'">true</ExcludedFromBuild>
|
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
<ClCompile Include="src\fft.cpp" />
|
||||||
<ClCompile Include="src\main.cpp" />
|
<ClCompile Include="src\main.cpp" />
|
||||||
<ClCompile Include="src\song.cpp">
|
<ClCompile Include="src\song.cpp">
|
||||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Editor|Win32'">false</ExcludedFromBuild>
|
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Editor|Win32'">false</ExcludedFromBuild>
|
||||||
|
|||||||
@ -4,6 +4,7 @@
|
|||||||
<ClCompile Include="src\main.cpp" />
|
<ClCompile Include="src\main.cpp" />
|
||||||
<ClCompile Include="src\song.cpp" />
|
<ClCompile Include="src\song.cpp" />
|
||||||
<ClCompile Include="src\editor.cpp" />
|
<ClCompile Include="src\editor.cpp" />
|
||||||
|
<ClCompile Include="src\fft.cpp" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClInclude Include="src\debug.h" />
|
<ClInclude Include="src\debug.h" />
|
||||||
@ -16,6 +17,8 @@
|
|||||||
</ClInclude>
|
</ClInclude>
|
||||||
<ClInclude Include="src\song.h" />
|
<ClInclude Include="src\song.h" />
|
||||||
<ClInclude Include="src\editor.h" />
|
<ClInclude Include="src\editor.h" />
|
||||||
|
<ClInclude Include="src\sointu\song.h" />
|
||||||
|
<ClInclude Include="src\fft.h" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<None Include="src\shaders\post.inl">
|
<None Include="src\shaders\post.inl">
|
||||||
|
|||||||
2
song.yml
2
song.yml
@ -27,7 +27,7 @@ score:
|
|||||||
order: [-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0, 1, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, -1, 13, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1]
|
order: [-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0, 1, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, -1, 13, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1]
|
||||||
patterns: [[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 81, 83, 84, 86], [88, 83, 84, 81, 88, 83, 84, 81, 88, 83, 84, 81, 88, 83, 84, 81], [91, 83, 84, 81, 91, 83, 84, 81, 91, 83, 84, 81, 91, 83, 84, 81], [93, 83, 84, 81, 93, 83, 84, 81, 93, 83, 84, 81, 93, 83, 84, 81], [89, 81, 83, 84, 86, 88, 89, 91, 89, 81, 83, 84, 83, 84, 86, 88], [89, 79, 81, 83, 81, 83, 84, 86, 84, 86, 88, 89, 88, 84, 86, 83], [91, 88, 89, 86, 88, 84, 86, 83, 84, 81, 83, 79, 81, 77, 79, 76], [77, 74, 76, 72, 74, 71, 72, 69, 71, 67, 69, 65, 67, 69, 71, 74], [77, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 76, 1, 77, 76], [74, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 69, 71, 72, 76], [84, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 83, 1, 1, 1], [81, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 79, 1, 1, 1], [81, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], [0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]]
|
patterns: [[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 81, 83, 84, 86], [88, 83, 84, 81, 88, 83, 84, 81, 88, 83, 84, 81, 88, 83, 84, 81], [91, 83, 84, 81, 91, 83, 84, 81, 91, 83, 84, 81, 91, 83, 84, 81], [93, 83, 84, 81, 93, 83, 84, 81, 93, 83, 84, 81, 93, 83, 84, 81], [89, 81, 83, 84, 86, 88, 89, 91, 89, 81, 83, 84, 83, 84, 86, 88], [89, 79, 81, 83, 81, 83, 84, 86, 84, 86, 88, 89, 88, 84, 86, 83], [91, 88, 89, 86, 88, 84, 86, 83, 84, 81, 83, 79, 81, 77, 79, 76], [77, 74, 76, 72, 74, 71, 72, 69, 71, 67, 69, 65, 67, 69, 71, 74], [77, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 76, 1, 77, 76], [74, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 69, 71, 72, 76], [84, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 83, 1, 1, 1], [81, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 79, 1, 1, 1], [81, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], [0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]]
|
||||||
rowsperpattern: 16
|
rowsperpattern: 16
|
||||||
length: 12
|
length: 108
|
||||||
patch:
|
patch:
|
||||||
- name: 80s lead
|
- name: 80s lead
|
||||||
numvoices: 2
|
numvoices: 2
|
||||||
|
|||||||
74
src/fft.cpp
Normal file
74
src/fft.cpp
Normal file
@ -0,0 +1,74 @@
|
|||||||
|
#include "fft.h"
|
||||||
|
#include <math.h>
|
||||||
|
|
||||||
|
static float window[FFT_SIZE];
|
||||||
|
|
||||||
|
// Call once before use
|
||||||
|
void init_hamming_window() {
|
||||||
|
for (int i = 0; i < FFT_SIZE; i++) {
|
||||||
|
window[i] = 0.54f - 0.46f * cosf(2.0f * (float)M_PI * i / (FFT_SIZE - 1));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static unsigned int bit_reverse(unsigned int x, int log2n) {
|
||||||
|
unsigned int n = 0;
|
||||||
|
for (int i = 0; i < log2n; i++) {
|
||||||
|
n <<= 1;
|
||||||
|
n |= (x & 1);
|
||||||
|
x >>= 1;
|
||||||
|
}
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
|
||||||
|
void compute_fft(float* time_data, float* freq_out) {
|
||||||
|
static float real[FFT_SIZE];
|
||||||
|
static float imag[FFT_SIZE];
|
||||||
|
|
||||||
|
int log2n = 0;
|
||||||
|
for (int t = FFT_SIZE; t > 1; t >>= 1) ++log2n;
|
||||||
|
|
||||||
|
// Apply Hamming window
|
||||||
|
for (int i = 0; i < FFT_SIZE; i++) {
|
||||||
|
real[i] = time_data[i] * window[i];
|
||||||
|
imag[i] = 0.0f;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Bit reversal
|
||||||
|
for (int i = 0; i < FFT_SIZE; ++i) {
|
||||||
|
int j = bit_reverse(i, log2n);
|
||||||
|
if (j > i) {
|
||||||
|
float tmp_re = real[i], tmp_im = imag[i];
|
||||||
|
real[i] = real[j]; imag[i] = imag[j];
|
||||||
|
real[j] = tmp_re; imag[j] = tmp_im;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Cooley-Tukey FFT
|
||||||
|
for (int s = 1; s <= log2n; ++s) {
|
||||||
|
int m = 1 << s;
|
||||||
|
for (int k = 0; k < FFT_SIZE; k += m) {
|
||||||
|
for (int j = 0; j < m / 2; ++j) {
|
||||||
|
int t = k + j;
|
||||||
|
int u = t + m / 2;
|
||||||
|
|
||||||
|
float angle = -2.0f * (float)M_PI * j / m;
|
||||||
|
float w_real = cosf(angle);
|
||||||
|
float w_imag = sinf(angle);
|
||||||
|
|
||||||
|
float re = w_real * real[u] - w_imag * imag[u];
|
||||||
|
float im = w_real * imag[u] + w_imag * real[u];
|
||||||
|
|
||||||
|
real[u] = real[t] - re;
|
||||||
|
imag[u] = imag[t] - im;
|
||||||
|
real[t] += re;
|
||||||
|
imag[t] += im;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < FFT_SIZE / 2; ++i) {
|
||||||
|
float mag = sqrtf(real[i] * real[i] + imag[i] * imag[i]) / FFT_SIZE;
|
||||||
|
|
||||||
|
freq_out[i] = mag;
|
||||||
|
}
|
||||||
|
}
|
||||||
12
src/fft.h
Normal file
12
src/fft.h
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
#pragma once
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <math.h>
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef M_PI
|
||||||
|
#define M_PI 3.14159265358979323846
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define FFT_SIZE 4096
|
||||||
|
void init_hamming_window();
|
||||||
|
void compute_fft(float* time_data, float* freq_out);
|
||||||
58
src/main.cpp
58
src/main.cpp
@ -1,6 +1,6 @@
|
|||||||
// custom build and feature flags
|
// custom build and feature flags
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
#define OPENGL_DEBUG 1
|
#define OPENGL_DEBUG 0
|
||||||
#define FULLSCREEN 0
|
#define FULLSCREEN 0
|
||||||
#define DESPERATE 0
|
#define DESPERATE 0
|
||||||
#define BREAK_COMPATIBILITY 0
|
#define BREAK_COMPATIBILITY 0
|
||||||
@ -29,6 +29,7 @@
|
|||||||
#include "shaders/post.inl"
|
#include "shaders/post.inl"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#include "fft.h"
|
||||||
|
|
||||||
#pragma data_seg(".pids")
|
#pragma data_seg(".pids")
|
||||||
// static allocation saves a few bytes
|
// static allocation saves a few bytes
|
||||||
@ -74,13 +75,13 @@ int __cdecl main(int argc, char* argv[])
|
|||||||
#if POST_PASS
|
#if POST_PASS
|
||||||
pidPost = ((PFNGLCREATESHADERPROGRAMVPROC)wglGetProcAddress("glCreateShaderProgramv"))(GL_FRAGMENT_SHADER, 1, &post_frag);
|
pidPost = ((PFNGLCREATESHADERPROGRAMVPROC)wglGetProcAddress("glCreateShaderProgramv"))(GL_FRAGMENT_SHADER, 1, &post_frag);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef SU_LOAD_GMDLS
|
#ifdef SU_LOAD_GMDLS
|
||||||
su_load_gmdls();
|
su_load_gmdls();
|
||||||
#endif // SU_LOAD_GMDLS
|
#endif // SU_LOAD_GMDLS
|
||||||
// initialize sound
|
// initialize sound
|
||||||
#ifndef EDITOR_CONTROLS
|
#ifndef EDITOR_CONTROLS
|
||||||
#if USE_AUDIO
|
#if USE_AUDIO
|
||||||
|
|
||||||
LPDIRECTSOUND direct_sound;
|
LPDIRECTSOUND direct_sound;
|
||||||
LPDIRECTSOUNDBUFFER direct_sound_buffer;
|
LPDIRECTSOUNDBUFFER direct_sound_buffer;
|
||||||
DirectSoundCreate(0, &direct_sound, 0);
|
DirectSoundCreate(0, &direct_sound, 0);
|
||||||
@ -91,6 +92,7 @@ int __cdecl main(int argc, char* argv[])
|
|||||||
LPVOID p1;
|
LPVOID p1;
|
||||||
DWORD l1;
|
DWORD l1;
|
||||||
IDirectSoundBuffer_Lock(direct_sound_buffer, 0, SU_LENGTH_IN_SAMPLES * SU_CHANNEL_COUNT * SU_SAMPLE_SIZE, &p1, &l1, NULL, NULL, 0);
|
IDirectSoundBuffer_Lock(direct_sound_buffer, 0, SU_LENGTH_IN_SAMPLES * SU_CHANNEL_COUNT * SU_SAMPLE_SIZE, &p1, &l1, NULL, NULL, 0);
|
||||||
|
|
||||||
CreateThread(0, 0, (LPTHREAD_START_ROUTINE)su_render_song, p1, 0, 0);
|
CreateThread(0, 0, (LPTHREAD_START_ROUTINE)su_render_song, p1, 0, 0);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
@ -108,13 +110,26 @@ int __cdecl main(int argc, char* argv[])
|
|||||||
|
|
||||||
long playCursor = 0;
|
long playCursor = 0;
|
||||||
long lastPlayCursor = -1;
|
long lastPlayCursor = -1;
|
||||||
// main loop
|
volatile float maximum = 0.0; // Helper variable to calculate maximum fft output for normalization
|
||||||
|
|
||||||
|
// Unlock buffer for next use
|
||||||
|
IDirectSoundBuffer_Unlock(direct_sound_buffer, p1, SU_LENGTH_IN_SAMPLES * SU_CHANNEL_COUNT * SU_SAMPLE_SIZE, NULL, NULL);
|
||||||
|
|
||||||
|
// Play sound
|
||||||
direct_sound_buffer->Play(0, 0, 0);
|
direct_sound_buffer->Play(0, 0, 0);
|
||||||
|
|
||||||
|
static float syncs[1 + SU_NUMSYNCS];
|
||||||
|
|
||||||
|
// Init FFT
|
||||||
|
init_hamming_window();
|
||||||
|
// FFT buffers
|
||||||
|
static float fft_input[FFT_SIZE];
|
||||||
|
static float fft_output[FFT_SIZE / 2]; // Magnitudes
|
||||||
|
static float fft_uniform[FFT_SIZE / 4];
|
||||||
|
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
direct_sound_buffer->GetCurrentPosition((DWORD*)&playCursor, NULL);
|
direct_sound_buffer->GetCurrentPosition((DWORD*)&playCursor, NULL);
|
||||||
float syncs[1 + SU_NUMSYNCS];
|
|
||||||
|
|
||||||
#if !(DESPERATE)
|
#if !(DESPERATE)
|
||||||
// do minimal message handling so windows doesn't kill your application
|
// do minimal message handling so windows doesn't kill your application
|
||||||
@ -144,7 +159,39 @@ int __cdecl main(int argc, char* argv[])
|
|||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
syncs[0] = (float)playCursor / (2 * sizeof(SUsample));
|
/******************
|
||||||
|
* FFT
|
||||||
|
*******************/
|
||||||
|
LPVOID audio_ptr = NULL;
|
||||||
|
DWORD audio_size = 0;
|
||||||
|
|
||||||
|
// Read audio
|
||||||
|
HRESULT hr = IDirectSoundBuffer_Lock(direct_sound_buffer, 0, FFT_SIZE * sizeof(SUsample), &audio_ptr, &audio_size, NULL, NULL, DSBLOCK_FROMWRITECURSOR);
|
||||||
|
|
||||||
|
if (SUCCEEDED(hr) && audio_ptr) {
|
||||||
|
SUsample* samples = (SUsample*)audio_ptr;
|
||||||
|
for (int i = 0; i < FFT_SIZE; ++i) {
|
||||||
|
fft_input[i] = (float)samples[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
IDirectSoundBuffer_Unlock(direct_sound_buffer, audio_ptr, audio_size, NULL, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Calculate FFT
|
||||||
|
compute_fft(fft_input, fft_output);
|
||||||
|
|
||||||
|
// Normalize output
|
||||||
|
for (int i = 0; i < (FFT_SIZE / 2); i++)
|
||||||
|
{
|
||||||
|
maximum = max(fft_output[i], maximum);
|
||||||
|
fft_output[i] = fft_output[i] / maximum;
|
||||||
|
if (i < (FFT_SIZE / 4)) // Limit uniform fft size. High frequencys contain nothing interesing.
|
||||||
|
{
|
||||||
|
fft_uniform[i] = fft_output[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
syncs[0] = (float)playCursor / (2 * sizeof(SUsample));
|
||||||
|
|
||||||
for (int i = 0; i < SU_NUMSYNCS; ++i)
|
for (int i = 0; i < SU_NUMSYNCS; ++i)
|
||||||
{
|
{
|
||||||
@ -153,6 +200,7 @@ int __cdecl main(int argc, char* argv[])
|
|||||||
|
|
||||||
PFNGLUNIFORM1FVPROC glUniform1fvProc = ((PFNGLUNIFORM1FVPROC)wglGetProcAddress("glUniform1fv"));
|
PFNGLUNIFORM1FVPROC glUniform1fvProc = ((PFNGLUNIFORM1FVPROC)wglGetProcAddress("glUniform1fv"));
|
||||||
glUniform1fvProc(0, SU_NUMSYNCS + 1, syncs);
|
glUniform1fvProc(0, SU_NUMSYNCS + 1, syncs);
|
||||||
|
glUniform1fvProc(8, FFT_SIZE / 4, fft_uniform);
|
||||||
|
|
||||||
glRects(-1, -1, 1, 1);
|
glRects(-1, -1, 1, 1);
|
||||||
|
|
||||||
|
|||||||
@ -3,6 +3,7 @@ precision mediump float;
|
|||||||
out vec4 o;
|
out vec4 o;
|
||||||
const float PI = 22./7.;
|
const float PI = 22./7.;
|
||||||
layout(location = 0) uniform float syncs[7];
|
layout(location = 0) uniform float syncs[7];
|
||||||
|
layout(location = 8) uniform float fft_output[512]; // FFT_SIZE / 4
|
||||||
float u_time = syncs[0];
|
float u_time = syncs[0];
|
||||||
|
|
||||||
vec3 render(vec2 uv, float time) {
|
vec3 render(vec2 uv, float time) {
|
||||||
@ -23,5 +24,18 @@ vec3 render(vec2 uv, float time) {
|
|||||||
void main() {
|
void main() {
|
||||||
vec2 uv = gl_FragCoord.xy * 2. / vec2(1920,1080);
|
vec2 uv = gl_FragCoord.xy * 2. / vec2(1920,1080);
|
||||||
vec3 col = render(uv, u_time);
|
vec3 col = render(uv, u_time);
|
||||||
o = vec4(col,1.0);
|
|
||||||
|
// Determine FFT bin index for current x position
|
||||||
|
int index = int(floor(uv.x*128.0));
|
||||||
|
index = clamp(index, 0, 255);
|
||||||
|
|
||||||
|
// Get the FFT energy (clamped to avoid NaNs or overflow)
|
||||||
|
float energy = clamp(fft_output[index], .0, 1.0);
|
||||||
|
|
||||||
|
float bar_height = energy;
|
||||||
|
float fade = smoothstep(bar_height, bar_height + 0.02, 1.0 - uv.y);
|
||||||
|
|
||||||
|
vec3 color = vec3(fade);
|
||||||
|
|
||||||
|
o = vec4(color, 1.0);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
// Generated with Shader Minifier 1.5.1 (https://github.com/laurentlb/Shader_Minifier/)
|
// Generated with Shader Minifier 1.5.1 (https://github.com/laurentlb/Shader_Minifier/)
|
||||||
#ifndef FRAGMENT_INL_
|
#ifndef FRAGMENT_INL_
|
||||||
# define FRAGMENT_INL_
|
# define FRAGMENT_INL_
|
||||||
|
# define VAR_fft_output "l"
|
||||||
# define VAR_o "f"
|
# define VAR_o "f"
|
||||||
# define VAR_syncs "v"
|
# define VAR_syncs "v"
|
||||||
|
|
||||||
@ -10,20 +11,13 @@ const char *fragment_frag =
|
|||||||
"out vec4 f;"
|
"out vec4 f;"
|
||||||
"const float m=22./7.;"
|
"const float m=22./7.;"
|
||||||
"layout(location=0)uniform float v[7];"
|
"layout(location=0)uniform float v[7];"
|
||||||
|
"layout(location=8)uniform float l[512];"
|
||||||
"float n=v[0];"
|
"float n=v[0];"
|
||||||
"vec3 s(vec2 f)"
|
|
||||||
"{"
|
|
||||||
"float m=v[4];"
|
|
||||||
"return f.x>=m&&f.x<=m+.01?"
|
|
||||||
"vec3(1):"
|
|
||||||
"f.x>=0.&&f.x<=.01?"
|
|
||||||
"vec3(abs(v[3]*2)):"
|
|
||||||
"vec3(.1,.2,.3)*abs(v[1]*1.2);"
|
|
||||||
"}"
|
|
||||||
"void main()"
|
"void main()"
|
||||||
"{"
|
"{"
|
||||||
"vec2 m=gl_FragCoord.xy*2./vec2(1920,1080);"
|
"vec2 m=gl_FragCoord.xy*2./vec2(1920,1080);"
|
||||||
"f=vec4(s(m),1);"
|
"float n=clamp(l[clamp(int(floor(m.x*128.)),0,255)],0.,1.);"
|
||||||
|
"f=vec4(vec3(smoothstep(n,n+.02,1.-m.y)),1);"
|
||||||
"}";
|
"}";
|
||||||
|
|
||||||
#endif // FRAGMENT_INL_
|
#endif // FRAGMENT_INL_
|
||||||
|
|||||||
@ -3,14 +3,14 @@
|
|||||||
#define SU_RENDER_H
|
#define SU_RENDER_H
|
||||||
|
|
||||||
#define SU_CHANNEL_COUNT 2
|
#define SU_CHANNEL_COUNT 2
|
||||||
#define SU_LENGTH_IN_SAMPLES 920256
|
#define SU_LENGTH_IN_SAMPLES 8282304
|
||||||
#define SU_BUFFER_LENGTH (SU_LENGTH_IN_SAMPLES*SU_CHANNEL_COUNT)
|
#define SU_BUFFER_LENGTH (SU_LENGTH_IN_SAMPLES*SU_CHANNEL_COUNT)
|
||||||
|
|
||||||
#define SU_SAMPLE_RATE 44100
|
#define SU_SAMPLE_RATE 44100
|
||||||
#define SU_BPM 138
|
#define SU_BPM 138
|
||||||
#define SU_ROWS_PER_BEAT 4
|
#define SU_ROWS_PER_BEAT 4
|
||||||
#define SU_ROWS_PER_PATTERN 16
|
#define SU_ROWS_PER_PATTERN 16
|
||||||
#define SU_LENGTH_IN_PATTERNS 12
|
#define SU_LENGTH_IN_PATTERNS 108
|
||||||
#define SU_LENGTH_IN_ROWS (SU_LENGTH_IN_PATTERNS*SU_PATTERN_SIZE)
|
#define SU_LENGTH_IN_ROWS (SU_LENGTH_IN_PATTERNS*SU_PATTERN_SIZE)
|
||||||
#define SU_SAMPLES_PER_ROW (SU_SAMPLE_RATE*60/(SU_BPM*SU_ROWS_PER_BEAT))
|
#define SU_SAMPLES_PER_ROW (SU_SAMPLE_RATE*60/(SU_BPM*SU_ROWS_PER_BEAT))
|
||||||
#define SU_NUMSYNCS 4
|
#define SU_NUMSYNCS 4
|
||||||
|
|||||||
Reference in New Issue
Block a user