diff --git a/leviathan.vcxproj b/leviathan.vcxproj index ce644fe..9cfaf55 100644 --- a/leviathan.vcxproj +++ b/leviathan.vcxproj @@ -176,7 +176,7 @@ 0x0409 - opengl32.lib;winmm.lib;src/sointu/song.obj;%(AdditionalDependencies) + opengl32.lib;dsound.lib;src/sointu/song.obj;%(AdditionalDependencies) out\leviathan-debug.exe true true @@ -264,7 +264,7 @@ shader_minifier.exe -v -o src\shaders\post.inl src\shaders\post.frag 0x0409 - winmm.lib;opengl32.lib;src/sointu/song.obj;%(AdditionalDependencies) + dsound.lib;opengl32.lib;src/sointu/song.obj;%(AdditionalDependencies) out/leviathan-debug.exe true true @@ -349,7 +349,7 @@ shader_minifier.exe -v -o src\shaders\post.inl src\shaders\post.frag /RANGE:opengl32 /HASHTRIES:300 /COMPMODE:SLOW /ORDERTRIES:9000 /REPORT:out.html /PROGRESSGUI /HASHSIZE:1000 /UNSAFEIMPORT /UNALIGNCODE /SATURATE /NOINITIALIZERS /TRANSFORM:CALLS /TRUNCATEFLOATS:32 %(AdditionalOptions) - opengl32.lib;winmm.lib;src/sointu/song.obj;%(AdditionalDependencies) + opengl32.lib;dsound.lib;src/sointu/song.obj;%(AdditionalDependencies) out\leviathan-release.exe @@ -441,7 +441,7 @@ shader_minifier.exe -v -o src\shaders\post.inl src\shaders\post.frag /CRINKLER /RANGE:opengl32 /HASHTRIES:1000 /COMPMODE:VERYSLOW /ORDERTRIES:30000 /REPORT:out.html /PROGRESSGUI /HASHSIZE:1000 /UNSAFEIMPORT /UNALIGNCODE /SATURATE /NOINITIALIZERS /TRANSFORM:CALLS %(AdditionalOptions) - opengl32.lib;winmm.lib;src/sointu/song.obj;%(AdditionalDependencies) + opengl32.lib;dsound.lib;src/sointu/song.obj;%(AdditionalDependencies) out\leviathan-release.exe @@ -537,8 +537,8 @@ shader_minifier.exe -v -o src\shaders\post.inl src\shaders\post.frag 0x0409 - /CRINKLER /RANGE:opengl32 /HASHTRIES:100 /COMPMODE:INSTANT /ORDERTRIES:2000 /PROGRESSGUI /HASHSIZE:100 /UNSAFEIMPORT /UNALIGNCODE /SATURATE /NOINITIALIZERS /TRANSFORM:CALLS %(AdditionalOptions) - opengl32.lib;winmm.lib;src/sointu/song.obj;%(AdditionalDependencies) + /CRINKLER /RANGE:opengl32 /HASHTRIES:100 /COMPMODE:INSTANT /ORDERTRIES:2000 /PROGRESSGUI /HASHSIZE:100 /UNSAFEIMPORT /UNALIGNCODE /SATURATE /NOINITIALIZERS /TRANSFORM:CALLS %(AdditionalOptions) + opengl32.lib;dsound.lib;src/sointu/song.obj;%(AdditionalDependencies) out\leviathan-snapshot.exe diff --git a/song.yml b/song.yml index b1fa35f..a901ad2 100644 --- a/song.yml +++ b/song.yml @@ -2,10 +2,10 @@ bpm: 138 rowsperbeat: 4 score: tracks: - - numvoices: 2 + - numvoices: 1 order: [-1, -1, -1, -1, 0, -1, 1, -1, 0, -1, 1, -1, 2, -1, 1, -1, 3, -1, 1, -1, 2, -1, 1, -1, 4, -1, 1, -1, 0, -1, -1, -1, 0, -1, -1, -1, 0, -1, -1, -1, 0, -1, -1, -1, 2, -1, -1, -1, 2, -1, -1, -1, 0, -1, -1, -1, 0, -1, -1, -1, 0, -1, -1, -1, 4, -1, 2, -1, 0, -1, -1, -1, 4, -1, 2, -1, 0, -1, -1, -1, 0, -1, -1, -1, 2, -1, 2, -1, 3, 5, 2, 6, 0, -1, -1, -1, 0, -1, 1, -1, 0, -1, 1, -1, 0, -1, 1, -1] patterns: [[33, 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], [29, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], [26, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], [31, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], [1, 1, 1, 1, 1, 1, 1, 1, 28, 1, 1, 1, 1, 1, 1, 1], [1, 1, 1, 1, 1, 1, 1, 1, 31, 1, 1, 1, 1, 1, 1, 1]] - - numvoices: 2 + - numvoices: 1 order: [-1, -1, -1, -1, 0, -1, 1, -1, 0, -1, 1, -1, 2, -1, 1, -1, 3, -1, 1, -1, 2, -1, 1, -1, 4, -1, 1, -1, 0, -1, -1, -1, 0, -1, -1, -1, 0, -1, -1, -1, 0, -1, -1, -1, 2, -1, -1, -1, 2, -1, -1, -1, 0, -1, -1, -1, 0, -1, -1, -1, 0, -1, -1, -1, 4, -1, 2, -1, 0, -1, -1, -1, 4, -1, 2, -1, 0, -1, -1, -1, 0, -1, -1, -1, 5, -1, 5, -1, 6, 7, 5, 8, 9, -1, -1, -1, 9, -1, 1, -1, 9, -1, 1, -1, 0, -1, 1, -1] patterns: [[45, 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], [41, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], [38, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], [43, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], [53, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], [50, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], [1, 1, 1, 1, 1, 1, 1, 1, 52, 1, 1, 1, 1, 1, 1, 1], [1, 1, 1, 1, 1, 1, 1, 1, 55, 1, 1, 1, 1, 1, 1, 1], [57, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]] - numvoices: 1 @@ -23,14 +23,14 @@ score: - numvoices: 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, 0, 1, -1, 2, 3, 4, 5, -1, 0, 6, -1, -1, 0, 6, -1, 7, 0, -1, -1, -1, 8, -1, -1, 9, -1, -1, -1, -1, 10, 7, 11, 12, 0, -1, -1, 13, 10, 7, 11, 7, 8, -1, 14, -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] patterns: [[83, 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, 84, 1, 81, 1], [1, 1, 1, 1, 1, 1, 1, 1, 72, 1, 74, 1, 76, 1, 1, 1], [71, 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, 72, 1, 1, 1], [69, 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, 84, 1, 1, 1], [1, 1, 1, 1, 1, 1, 1, 1, 86, 1, 1, 1, 1, 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], [88, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], [84, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], [1, 1, 1, 1, 1, 1, 1, 1, 83, 1, 1, 1, 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, 1, 0, 1, 1, 1]] - - numvoices: 4 + - numvoices: 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]] rowsperpattern: 16 length: 108 patch: - name: 80s lead - numvoices: 4 + numvoices: 2 units: - type: oscillator id: 1089 @@ -339,7 +339,7 @@ patch: id: 1131 parameters: {auxgain: 15, outgain: 15, stereo: 1} - name: HappyLead - numvoices: 4 + numvoices: 1 units: - type: oscillator id: 164 diff --git a/src/definitions.h b/src/definitions.h index ffb5025..4917166 100644 --- a/src/definitions.h +++ b/src/definitions.h @@ -7,7 +7,10 @@ #define VC_LEANMEAN #define VC_EXTRALEAN +#pragma pack(push, 8) #include +#pragma pack(pop) + #include // global resolution @@ -46,43 +49,44 @@ static DEVMODE screenSettings = { }; #if USE_AUDIO - #include - #include // this file is auto generated by sointu #include "sointu/song.h" +#ifndef DSBCAPS_TRUEPLAYPOSITION // Not defined in MinGW dsound headers, so let's add it +#define DSBCAPS_TRUEPLAYPOSITION 0x00080000 +#endif +#include +#include + + +SUsample sound_buffer[SU_LENGTH_IN_SAMPLES * SU_CHANNEL_COUNT]; +WAVEFORMATEX wave_format = { +#ifdef SU_SAMPLE_FLOAT + WAVE_FORMAT_IEEE_FLOAT, +#else + WAVE_FORMAT_PCM, +#endif + SU_CHANNEL_COUNT, + SU_SAMPLE_RATE, + SU_SAMPLE_RATE * SU_SAMPLE_SIZE * SU_CHANNEL_COUNT, + SU_SAMPLE_SIZE * SU_CHANNEL_COUNT, + SU_SAMPLE_SIZE * 8, + 0 +}; +#pragma data_seg(".descfmt") +DSBUFFERDESC buffer_description = { + sizeof(DSBUFFERDESC), + DSBCAPS_GETCURRENTPOSITION2 | DSBCAPS_GLOBALFOCUS | DSBCAPS_TRUEPLAYPOSITION, + SU_LENGTH_IN_SAMPLES * SU_SAMPLE_SIZE * SU_CHANNEL_COUNT, + 0, + &wave_format, + 0 +}; #pragma bss_seg(".syncbuf") extern "C" { int _fltused = 1; float syncBuf[SU_SYNCBUFFER_LENGTH+1]; } - - #pragma data_seg(".sointuout") - static SUsample lpSoundBuffer[(int)SU_LENGTH_IN_SAMPLES * 2]; - static HWAVEOUT hWaveOut; - - #pragma data_seg(".wavefmt") - static WAVEFORMATEX WaveFMT = - { - WAVE_FORMAT_IEEE_FLOAT, - 2, // channels - SU_SAMPLE_RATE, // samples per sec - SU_SAMPLE_RATE*sizeof(SUsample) * 2, // bytes per sec - sizeof(SUsample) * 2, // block alignment; - sizeof(SUsample) * 8, // bits per sample - 0 // extension not needed - }; - - #pragma data_seg(".wavehdr") - static WAVEHDR WaveHDR = - { - (LPSTR)lpSoundBuffer, SU_LENGTH_IN_SAMPLES * sizeof(SUsample) * 2, 0, 0, 0, 0, 0, 0 - }; - - static MMTIME MMTime = - { - TIME_SAMPLES, 0 - }; #endif // currently unused definitions diff --git a/src/main.cpp b/src/main.cpp index 7e86827..39174c3 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -41,7 +41,7 @@ static int pidPost; void entrypoint(void) #else #include "editor.h" -#include "song.h" + int __cdecl main(int argc, char* argv[]) #endif { @@ -49,7 +49,8 @@ int __cdecl main(int argc, char* argv[]) #if FULLSCREEN ChangeDisplaySettings(&screenSettings, CDS_FULLSCREEN); ShowCursor(0); - const HDC hDC = GetDC(CreateWindow((LPCSTR)0xC018, 0, WS_POPUP | WS_VISIBLE | WS_MAXIMIZE, 0, 0, 0, 0, 0, 0, 0, 0)); + HWND window = CreateWindow((LPCSTR)0xC018, 0, WS_POPUP | WS_VISIBLE | WS_MAXIMIZE, 0, 0, 0, 0, 0, 0, 0, 0); + const HDC hDC = GetDC(window); #else #ifdef EDITOR_CONTROLS HWND window = CreateWindow("static", 0, WS_POPUP | WS_VISIBLE, 0, 0, XRES, YRES, 0, 0, 0, 0); @@ -77,12 +78,21 @@ int __cdecl main(int argc, char* argv[]) // initialize sound #ifndef EDITOR_CONTROLS #if USE_AUDIO - CreateThread(0, 0, (LPTHREAD_START_ROUTINE)su_render_song, lpSoundBuffer, 0, 0); - waveOutOpen(&hWaveOut, WAVE_MAPPER, &WaveFMT, NULL, 0, CALLBACK_NULL); - waveOutPrepareHeader(hWaveOut, &WaveHDR, sizeof(WaveHDR)); - waveOutWrite(hWaveOut, &WaveHDR, sizeof(WaveHDR)); + + LPDIRECTSOUND direct_sound; + LPDIRECTSOUNDBUFFER direct_sound_buffer; + DirectSoundCreate(0, &direct_sound, 0); + + IDirectSound_SetCooperativeLevel(direct_sound, window, DSSCL_PRIORITY); + IDirectSound_CreateSoundBuffer(direct_sound, &buffer_description, &direct_sound_buffer, NULL); + + LPVOID p1; + DWORD l1; + 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); + #endif - + #else Leviathan::Editor editor = Leviathan::Editor(); editor.updateShaders(&pidMain, &pidPost, true); @@ -94,9 +104,13 @@ int __cdecl main(int argc, char* argv[]) double position = 0.0; #endif + long playCursor = 0; // main loop + direct_sound_buffer->Play(0, 0, 0); do { + + direct_sound_buffer->GetCurrentPosition((DWORD*)&playCursor, NULL); float syncs[1 + SU_NUMSYNCS]; @@ -117,7 +131,7 @@ int __cdecl main(int argc, char* argv[]) #ifndef EDITOR_CONTROLS // if you don't have an audio system figure some other way to pass time to your shader #if USE_AUDIO - waveOutGetPosition(hWaveOut, &MMTime, sizeof(MMTIME)); + // it is possible to upload your vars as vertex color attribute (gl_Color) to save one function import #if NO_UNIFORMS glColor3ui(MMTime.u.sample, 0, 0); @@ -132,13 +146,11 @@ int __cdecl main(int argc, char* argv[]) #endif - syncs[0] = MMTime.u.sample / (2 * sizeof(SUsample)); + syncs[0] = (float)playCursor / (2 * sizeof(SUsample)); for (int i = 0; i < SU_NUMSYNCS; ++i) { - syncs[i + 1] = syncBuf[ - (MMTime.u.sample >> 8) * SU_NUMSYNCS + i - ]; + syncs[i + 1] = syncBuf[(playCursor / (2 * sizeof(SUsample)) >> 8) * SU_NUMSYNCS + i]; } PFNGLUNIFORM1FVPROC glUniform1fvProc = ((PFNGLUNIFORM1FVPROC)wglGetProcAddress("glUniform1fv")); @@ -178,7 +190,7 @@ int __cdecl main(int argc, char* argv[]) } while(!GetAsyncKeyState(VK_ESCAPE) #if USE_AUDIO - && MMTime.u.sample < SU_LENGTH_IN_SAMPLES + && playCursor < SU_LENGTH_IN_SAMPLES * 2 * sizeof(SUsample) #endif ); diff --git a/src/shaders/fragment.frag b/src/shaders/fragment.frag index 9d4428a..6f0865c 100644 --- a/src/shaders/fragment.frag +++ b/src/shaders/fragment.frag @@ -3,29 +3,25 @@ precision mediump float; out vec4 o; const float PI = 22./7.; layout(location = 0) uniform float syncs[7]; -float u_time = syncs[0]/44100.; +float u_time = syncs[0]; vec3 render(vec2 uv, float time) { - - if (uv.y >= 0.0 && uv.y <= 0.01 ) { - return vec3(abs(syncs[5])); + float pos = syncs[4]; + if (uv.x >= pos && uv.x <= pos+0.01 ) { + return vec3(1.); } - if (uv.y >= -0.21 && uv.y <= -0.2 ) { - return vec3(abs(syncs[6]*1.3)); + if (uv.x >= 0.0 && uv.x <= 0.01 ) { + return vec3(abs(syncs[3]*2)); } - - return vec3(0.1, 0.2, 0.3); + return vec3(0.1, 0.2, 0.3) * abs(syncs[1]*1.2); } void main() { - vec2 u_resolution = vec2(1920,1080); - vec2 qor = gl_FragCoord.xy/u_resolution.xy; - vec2 uv = -1.0+2.0*qor; - uv.x *= uv.x/u_resolution.y; + vec2 uv = gl_FragCoord.xy * 2. / vec2(1920,1080); vec3 col = render(uv, u_time); o = vec4(col,1.0); } diff --git a/src/shaders/fragment.inl b/src/shaders/fragment.inl index fd56c00..23b7705 100644 --- a/src/shaders/fragment.inl +++ b/src/shaders/fragment.inl @@ -10,18 +10,20 @@ const char *fragment_frag = "out vec4 f;" "const float m=22./7.;" "layout(location=0)uniform float v[7];" - "float n=v[0]/441e2;" + "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()" "{" - "vec2 m=vec2(1920,1080),n=gl_FragCoord.xy/m.xy;" - "n=-1.+2.*n;" - "n.x*=n.x/m.y;" - "vec3 a=n.y>=0.&&n.y<=.01?" - "vec3(abs(v[5])):" - "n.y>=-.21&&n.y<=-.2?" - "vec3(abs(v[6]*1.3)):" - "vec3(.1,.2,.3);" - "f=vec4(a,1);" + "vec2 m=gl_FragCoord.xy*2./vec2(1920,1080);" + "f=vec4(s(m),1);" "}"; #endif // FRAGMENT_INL_ diff --git a/src/sointu/song.h b/src/sointu/song.h index c2b43bd..3518e73 100644 --- a/src/sointu/song.h +++ b/src/sointu/song.h @@ -13,7 +13,7 @@ #define SU_LENGTH_IN_PATTERNS 108 #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_NUMSYNCS 6 +#define SU_NUMSYNCS 4 #define SU_SYNCBUFFER_LENGTH ((SU_LENGTH_IN_SAMPLES+255)>>8)*SU_NUMSYNCS #include