diff options
Diffstat (limited to 'saw.c')
-rwxr-xr-x | saw.c | 911 |
1 files changed, 162 insertions, 749 deletions
@@ -17,37 +17,6 @@ #/ #/ ---------------------------------------------------------------- #/ -#/ NOTE Automatic self-compilation -#/ -#/ If you have a Linux shell, you can build the project by running -#/ > ./saw.c -#/ -#/ Or you can build the project easily using those two commands: -#/ > gcc -o buildme -DBUILDME=1 saw.c -#/ > ./buildme -#/ Or, on Windows, with MSVC compiler: -#/ > cl.exe -Febuildme.exe -DBUILDME=1 saw.c -#/ > buildme.exe -#/ -#/ NOTE Manual compilation -#/ -#/ - Code generation -#/ > gcc -o build_codegen -DCODEGEN=1 saw.c -#/ > ./build_codegen -#/ -#/ - Dependencies -#/ > gcc -c -o build/thirdparty.o -DDEPENDENCIES=1 saw.c -#/ -#/ - Test suite -#/ > gcc -o build/test_suite -DTESTS=1 -#/ > build/test_suite -#/ -#/ - Executable -#/ > gcc -o build/saw -DEXE=1 -#/ > build/saw -#/ -#/ ---------------------------------------------------------------- -#/ #/ To-Do list #/ #/ - Code @@ -58,7 +27,7 @@ #/ - Transactional undo and redo #/ - Rational bezier curves #/ - Biquad filter -#/ - Fourier transform +#/ - Fourier transform (Cooley-Tukey FFT) #/ - Parallel computation #/ - Module code compilation #/ - Sound @@ -120,7 +89,6 @@ #/ Bugs #/ #/ - Sampler clicking -#/ - Windows and macOS compilation issues #/ - Different build types don't work without manual full rebuild because they store object files in the same folder #/ #/ Done features @@ -152,14 +120,133 @@ #/ #/ ---------------------------------------------------------------- #/ -#/ (C) 2024 Mitya Selivanov <guattari.tech>, MIT License +#/ Primary design +#/ +#/ Work in progress, not an actual final design. +#/ +#/ +#/ Basic UI +#/ +#/ - Bus list +#/ - Bus units +#/ - Track editor +#/ - Sheet editor +#/ +#/ +---------+ +-----------------------------------+ +-[ Bus A ]-------+ +#/ [+]Bus A ^ | [ track 1 ====== ] ^ [+] Arpeggiator ^ +#/ |---------| | | | [x] ** *** | +#/ [+]Bus B | | [ track 2 ============== ] | | [ ] <--> ++ | +#/ |---------| | | |-----------------| +#/ [+]Master v | v [+] Synth | +#/ [+]-------+ +<--------------------------------->+ | ^ ^ ^ [ ] | +#/ | / \ / \ / [x] | +#/ +----[ track 2 ]--------------------------------+ | V V [o] | +#/ |F > ^ |-----------------| +#/ |E > x x x x x | [+] Reverb | +#/ |D > x x x x x | | <-----> [x] [u] | +#/ |C > x x x x x x x v | v +#/ +--|<------------------------------------------>+ [+]---------------+ +#/ +#/ +#/ Modularity +#/ +#/ Music and audio features will be implemented as a separate library with no external dependencies. +#/ UI and audio devices will be distinct modules which can be replaced. +#/ +#/ +#/ Sheet data +#/ +#/ /---------------------\ +#/ | | +#/ | Note | +#/ | | +#/ | time : i64 | +#/ | duration : i64 | +#/ | frequency : f64 | +#/ | amplitude : f64 | +#/ | flavor : f64 | +#/ | | +#/ \---------------------/ +#/ +#/ Unlike MIDI, we will allow to set any floating-point value for the note frequency. +#/ Time is defined as a sample index and therefore is relative to the sample rate. +#/ +#/ +#/ Processing +#/ +#/ A unit is a processing entity. +#/ +#/ for each unit: +#/ output[channel, time] = eval(inputs, channel, sample_rate, time) +#/ +#/ Unlike VST, time for a processing routine is one of explicit parameters. +#/ The processing routine can access any samples of inputs. +#/ This approach allows to evaluate samples non-sequentially, and even do some tricks like time-reverse effects. +#/ Changing the sample rate is also quite simple. +#/ +#/ +#/ Global matrix +#/ +#/ /---------------------------\ +#/ | Matrix | +#/ | | +#/ | (connections data) | +#/ | A.out[0] -> B.in[0] |-----------------+ +#/ | B.out[0] -> Master.in[0] |----------------+| +#/ | B.out[1] -> Master.in[1] | || +#/ \---------------------------/ || +#/ ^ | ^^ ||(in[0], in[1]) +#/ | | || || +#/ | | ||(out[0], out[1]) vv +#/ /----------\ | | /----------\ /-----------\ +#/ | Module A |---+ +-->| Module B | | Master | +#/ | (sheet) | (out[0]) (in[0]) | (synth) | | (limiter) | +#/ \----------/ \----------/ \-----------/ +#/ +#/ The global matrix manages the information about connections between units. +#/ Each unit can communicate to others through the global matrix. +#/ Each unit can have inputs and outputs for sheet and signal channels. +#/ +#/ To get data from a producing unit, the receiving unit will request the data from the global matrix using the input index. +#/ The global matrix will resolve the producing unit by input index, and request data from it. +#/ The evaluation startes from the master and gradually reaches all required units. +#/ +#/ +#/ Global modifiers +#/ +#/ Special units can affect all regular units, filtered by some criteria. +#/ This will allow to do some global changes, e.g. change the musical scale of the entire composition. +#/ +#/ +#/ Customization +#/ +#/ In the matrix mode, any inputs and outputs can be connected. +#/ A custom unit can be created with code editor and evaluation/JIT-compilation. +#/ +#/ ---------------------------------------------------------------- +#/ +#/ (C) 2024 Mitya Selivanov <guattari.tech> #/ #/ ================================================================ #/ #/ Self-compilation shell script #/ SRC=${0##*./} -gcc -o buildme -DBUILDME=1 $SRC && ./buildme $@ && rm buildme +BIN=${SRC%.*} +gcc \ + -Wall -Wextra -Werror -pedantic \ + -Wno-old-style-declaration \ + -Wno-missing-braces \ + -Wno-unused-variable \ + -Wno-unused-but-set-variable \ + -Wno-unused-parameter \ + -Wno-overlength-strings \ + -O3 \ + -fsanitize=undefined,address,leak \ + -D REDUCED_SYSTEM_LAYER_EXAMPLE \ + -lX11 -lm \ + -o $BIN $SRC && \ + ./$BIN $@ && rm $BIN exit $? # */ #endif // ================================================================ @@ -169,8 +256,6 @@ exit $? # */ // ================================================================ // Define one of the options for the linter #if !CODEGEN && \ - !BUILDME && \ - !DEPENDENCIES && \ !EXE && \ !TESTS #define BUILDME 1 @@ -178,45 +263,41 @@ exit $? # */ #define _GNU_SOURCE // ================================================================ // -// BUILD SYSTEM +// Types // // ================================================================ - -#if CODEGEN || BUILDME - -enum { - LINUX, - WINDOWS, - MACOS, -}; - -#if defined(_WIN32) && !defined(__CYGWIN__) -#define DLM "\\" -#define OS WINDOWS -#elif defined(__APPLE__) -#define DLM "/" -#define OS MACOS -#else // assume Linux -#define DLM "/" -#define OS LINUX -#endif - -#define FONT_TEXT "fonts" DLM "domitian_roman.ttf" -#define FONT_ICONS "fonts" DLM "font_awesome_6_free_solid_900.ttf" -#define INL_FONTS "build_fonts.inl.c" -#define SOURCE "saw.c" -#define PROJECT "saw" - -typedef int i32; -typedef long long i64; +#ifndef TYPES_HEADER_GUARD_ +#define TYPES_HEADER_GUARD_ + +typedef signed char i8; +typedef signed short i16; +typedef signed i32; +typedef signed long long i64; +typedef unsigned char u8; +typedef unsigned short u16; typedef unsigned u32; typedef unsigned long long u64; typedef char c8; +typedef int c32; typedef signed char b8; +typedef float f32; +typedef double f64; + +#endif // TYPES_HEADER_GUARD_ +// ================================================================ +// +// CODE GENERATION +// +// ================================================================ +#if CODEGEN #include <stdio.h> #include <stdlib.h> +#define FONT_TEXT "Domitian Roman.ttf" +#define FONT_ICONS "FontAwesome 6 Free Solid 900.ttf" +#define INL_FONTS "fonts.inl.c" + enum { MAX_LENGTH = 200, }; @@ -259,7 +340,7 @@ i64 print_bytes(FILE *out, FILE *in) { return size; } -void codegen() { +i32 main(void) { printf("Code generation\n"); fflush(stdout); @@ -271,7 +352,6 @@ void codegen() { } fprintf(out, "// Saw generated code\n\n"); - fprintf(out, "#include \"kit/types.h\"\n\n"); { FILE *in = fopen(FONT_TEXT, "rb"); @@ -311,685 +391,26 @@ void codegen() { } fclose(out); -} - -#endif - -#if CODEGEN - -int main(int argc, char **argv) { - (void) argc; - (void) argv; - - codegen(); - return 0; -} - -#elif BUILDME - -#include <string.h> -#include <stdarg.h> - -#if defined(_WIN32) && !defined(__CYGWIN__) -# define WIN32_LEAN_AND_MEAN -# define NOMINMAX -# include <windows.h> -#else -# include <sys/stat.h> -#endif - -#define REQUIRE_MATH 1 -#define REQUIRE_DL 0 -#define REQUIRE_THREADS 0 -#define REQUIRE_SOCKETS 0 -#define REQUIRE_GRAPHICS 1 -#define REQUIRE_OPENGL 1 -#define REQUIRE_VULKAN 0 -#if defined(__linux__) || defined(__EMSCRIPTEN__) -// Static C runtime is too unstable on Linux. Sad -#define STATIC_RUNTIME 0 -#else -#define STATIC_RUNTIME 1 -#endif -// TODO Add command line option for the C runtime. - -enum { - BUFFER_COUNT = 16, - BUFFER_SIZE = 512, - STRING_COUNT = 64, - STRING_SIZE = 512, -}; - -c8 _buffers[BUFFER_COUNT][BUFFER_SIZE]; -i32 _buffer_index = 0; - -c8 _strings[STRING_COUNT][STRING_SIZE]; -i32 _string_index; - -c8 *build_type = "debug"; -c8 *compiler_c = ""; -c8 *destination = ""; -c8 *extra_options = ""; -c8 *extra_link_options = ""; -c8 *postfix_obj = ".o"; -c8 *postfix_exe = ""; -c8 *flag_obj = "-c -o "; -c8 *flag_exe = "-o "; -c8 *flags = ""; -c8 *link_flags = ""; - -b8 rebuild_all = 0; -b8 rebuild_exe = 0; -b8 run_codegen = 0; -b8 run_tests = 1; -b8 run_exe = 0; - -void print_help(void) { - printf( - "Build tool for C projects\n\n" - "Usage: ./saw.c [OPTIONS]\n\n" - " -h --help - Print this help\n" - " -t --type - Set build type: debug, release\n" - " -c --compiler - Set compiler to use: gcc, clang, cl, emcc\n" - " -d --destination - Set destination path\n" - " -o --options - Set additional compiler options\n" - " -l --link - Set additional linker options\n" - " -e --rebuild - Rebuild executable\n" - " -r --rebuildall - Rebuild dependencies\n" - " -g --codegen - Run code generation\n" - " -s --skiptests - Do not run tests\n" - " -x --run - Run the executable\n\n" - ); - fflush(stdout); -} - -c8 lowercase_char(c8 c) { - if (c >= 'A' && c <= 'Z') - return c + ('a' - 'A'); - return c; -} - -c8 *lowercase(c8 *s) { - i32 i = 0; - for (; s[i] != '\0'; ++i) { - if (i + 1 >= BUFFER_SIZE) { - printf("Buffer overflow\n"); - exit(-1); - } - _buffers[_buffer_index][i] = lowercase_char(s[i]); - } - _buffers[_buffer_index][i] = '\0'; - c8 *result = _buffers[_buffer_index]; - _buffer_index = (_buffer_index + 1) % BUFFER_COUNT; - return result; -} - -void fmt_v(c8 *format, va_list args) { - vsprintf(_buffers[_buffer_index], format, args); -} - -c8 *fmt(c8 *format, ...) { - va_list args; - va_start(args, format); - fmt_v(format, args); - c8 *result = _buffers[_buffer_index]; - _buffer_index = (_buffer_index + 1) % BUFFER_COUNT; - va_end(args); - return result; -} - -void fmt_dup_v(c8 *format, va_list args) { - vsprintf(_strings[_string_index], format, args); -} - -c8 *fmt_dup(c8 *format, ...) { - va_list args; - va_start(args, format); - if (_string_index >= STRING_COUNT) { - printf("Buffer overflow\n"); - exit(-1); - } - fmt_v(format, args); - c8 *result = _strings[_string_index++]; - va_end(args); - return result; -} - -b8 str_eq_lower(c8 *a, c8 *b) { - return strcmp(lowercase(a), lowercase(b)) == 0; -} - -b8 str_eq(c8 *a, c8 *b) { - return strcmp(a, b) == 0; -} - -b8 check_compiler(c8 *name) { - if (str_eq_lower(name, "cl") || str_eq_lower(name, "cl.exe")) { - i32 s = system(fmt("%s", name)); - if (WEXITSTATUS(s) != 0) - return 0; - return 1; - } - i32 s = system(fmt("%s --version", name)); - if (WEXITSTATUS(s) != 0) - return 0; - return 1; -} - -b8 file_exists(c8 *name) { -#if defined(_WIN32) && !defined(__CYGWIN__) - if (PathFileExistsA(buf)) - return 1; -#else - struct stat info; - if (stat(name, &info) == 0 && (S_ISREG(info.st_mode) || S_ISDIR(info.st_mode))) - return 1; -#endif - return 0; -} - -typedef struct { - u64 seconds; - u32 nanoseconds; -} Timestamp; - -Timestamp file_timestamp(c8 *name) { - Timestamp time = { - .seconds = 0, - .nanoseconds = 0, - }; - -#if defined(_WIN32) && !defined(__CYGWIN__) - HANDLE f = CreateFileA(buf, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); - FILETIME ft; - if (f != INVALID_HANDLE_VALUE && GetFileTime(f, NULL, NULL, &ft) != 0) { - u64 nsec100 = (((u64) ft.dwHighDateTime) << 32) | (u64) ft.dwLowDateTime; - time = (Timestamp) { - .seconds = (u64) (nsec100 / 10000000), - .nanoseconds = (u32) (100 * (nsec100 % 10000000)), - }; - } - if (f != INVALID_HANDLE_VALUE) - CloseHandle(f); -#else - struct stat info; - if (stat(name, &info) == 0 && (S_ISREG(info.st_mode) || S_ISDIR(info.st_mode))) - time = (Timestamp) { - #ifdef st_mtime - .seconds = (u64) info.st_mtim.tv_sec, - .nanoseconds = (u32) info.st_mtim.tv_nsec, - #else - .seconds = (u64) info.st_mtime, - .nanoseconds = 0, - #endif - }; -#endif - - return time; -} - -b8 time_less(Timestamp a, Timestamp b) { - if (a.seconds == b.seconds) - return a.nanoseconds < b.nanoseconds; - return a.seconds < b.seconds; -} - -void create_folder_recursive(c8 *path) { - #if defined(_WIN32) && !defined(__CYGWIN__) - system(fmt("if not exist %s mkdir %s", destination, destination)); - #else - system(fmt("mkdir %s -p", destination)); - #endif -} - -i32 main(i32 argc, c8 **argv) { - // Handle command line arguments - // - - for (i32 i = 1; i < argc; ++i) { - if (str_eq_lower(argv[i], "?")) { - print_help(); - return 0; - } else if (argv[i][0] == '-') { - if (argv[i][1] == '-') { - c8 *opt = argv[i] + 2; - if (str_eq_lower(opt, "help")) { - print_help(); - return 0; - } - else if (str_eq_lower(opt, "type")) - build_type = argv[++i]; - else if (str_eq_lower(opt, "compiler")) - compiler_c = argv[++i]; - else if (str_eq_lower(opt, "destination")) - destination = argv[++i]; - else if (str_eq_lower(opt, "options")) - extra_options = argv[++i]; - else if (str_eq_lower(opt, "link")) - extra_link_options = argv[++i]; - else if (str_eq_lower(opt, "rebuild")) - rebuild_exe = 1; - else if (str_eq_lower(opt, "rebuildall")) - rebuild_all = 1; - else if (str_eq_lower(opt, "codegen")) - run_codegen = 1; - else if (str_eq_lower(opt, "skiptests")) - run_tests = 0; - else if (str_eq_lower(opt, "run")) - run_exe = 1; - else - printf("Unknown option ignored `%s`\n", argv[i]); - } else { - i32 consumed = 0; - for (i32 j = 1; argv[i][j] != '\0'; ++j) { - switch (argv[i][j]) { - case 'h': - case 'H': - print_help(); - return 0; - - case 't': build_type = argv[i + (++consumed)]; break; - case 'c': compiler_c = argv[i + (++consumed)]; break; - case 'd': destination = argv[i + (++consumed)]; break; - case 'o': extra_options = argv[i + (++consumed)]; break; - case 'l': extra_link_options = argv[i + (++consumed)]; break; - case 'e': rebuild_exe = 1; break; - case 'r': rebuild_all = 1; break; - case 'g': run_codegen = 1; break; - case 's': run_tests = 0; break; - case 'x': run_exe = 1; break; - - default: - printf("Unknown option ignored `-%c`\n", argv[i][j]); - } - } - i += consumed; - } - } else - printf("Unknown option ignored `%s`\n", argv[i]); - } - - fflush(stdout); - - // Find the C compiler - // - - if (compiler_c[0] != '\0') { - if (check_compiler(compiler_c)) - printf("C compiler found - %s\n", compiler_c); - else { - printf("C compiler not found\n"); - return 1; - } - } else - switch (OS) { - case LINUX: - if (check_compiler("gcc")) { - compiler_c = "gcc"; - printf("C compiler found - GCC\n"); - } else if (check_compiler("clang")) { - compiler_c = "clang"; - printf("C compiler found - Clang"); - } else if (check_compiler("cc")) { - compiler_c = "cc"; - printf("C compiler found - cc"); - } - break; - - case WINDOWS: - if (check_compiler("cl")) { - compiler_c = "cl"; - printf("C compiler found - MSVC\n"); - } else if (check_compiler("gcc")) { - compiler_c = "gcc"; - printf("C compiler found - GCC\n"); - } else if (check_compiler("clang")) { - compiler_c = "clang"; - printf("C compiler found - Clang"); - } - break; - - case MACOS: - if (check_compiler("clang")) { - compiler_c = "clang"; - printf("C compiler found - Clang"); - } else if (check_compiler("gcc")) { - compiler_c = "gcc"; - printf("C compiler found - GCC\n"); - } else if (check_compiler("cc")) { - compiler_c = "cc"; - printf("C compiler found - cc"); - } - break; - - default:; - } - - if (compiler_c[0] == '\0') { - printf("C compiler not found\n"); - return 1; - } - - fflush(stdout); - - // Prepare compilation options - // - - if (OS == WINDOWS) - postfix_exe = ".exe"; - - if (str_eq(compiler_c, "cc")) { - destination[0] == '\0' && (destination = "build_cc"); - } else if (str_eq(compiler_c, "gcc")) { - destination[0] == '\0' && (destination = "build_gcc"); - } else if (str_eq(compiler_c, "clang")) { - destination[0] == '\0' && (destination = "build_clang"); - } else if (str_eq_lower(compiler_c, "cl") || str_eq_lower(compiler_c, "cl.exe")) { - destination[0] == '\0' && (destination = "build_cl"); - postfix_obj = ".obj"; - flag_obj = "-c -Fo"; - flag_exe = "-Fe"; - } else if (str_eq(compiler_c, "emcc")) { - destination[0] == '\0' && (destination = "build_emcc"); - postfix_exe = ".js"; - run_tests = 0; - } - - if (str_eq_lower(compiler_c, "cl") || str_eq_lower(compiler_c, "cl.exe")) { - if (str_eq_lower(build_type, "release")) - flags = "-O2 -DNDEBUG"; - else - flags = "-Od"; - } else if (str_eq(compiler_c, "clang")) { - if (str_eq_lower(build_type, "release")) - flags = "-O3 -DNDEBUG"; - else - flags = "-O0"; - } else { - if (str_eq_lower(build_type, "release")) - flags = "-O3 -DNDEBUG"; - else if (OS != WINDOWS && str_eq(compiler_c, "gcc") && !STATIC_RUNTIME) - flags = "-Wall -Wextra -Wno-missing-braces -Wno-missing-field-initializers -Werror -pedantic -O0 -fsanitize=undefined,address,leak -mshstk"; - else - flags = "-Wall -Wextra -Wno-missing-braces -Wno-missing-field-initializers -Werror -pedantic -O0"; - } - - if (OS == WINDOWS) { - if (str_eq_lower(compiler_c, "cl") || str_eq_lower(compiler_c, "cl.exe")) { - if (str_eq_lower(build_type, "debug")) - link_flags = -#if REQUIRE_SOCKETS - "Ws2_32.lib " -#endif - "Shlwapi.lib Advapi32.lib " -#if STATIC_RUNTIME - "/MTd " -#endif - ""; - else - link_flags = -#if REQUIRE_SOCKETS - "Ws2_32.lib " -#endif - "Shlwapi.lib Advapi32.lib " -#if STATIC_RUNTIME - "/MT " -#endif - ""; - } else - link_flags = -#if REQUIRE_SOCKETS - "-lWs2_32 " -#endif - "-lShlwapi -lAdvapi32" -#if STATIC_RUNTIME - "-static " -#endif - ""; - } - - if (OS == LINUX) - link_flags = -#if REQUIRE_THREADS - "-pthread " -#endif -#if REQUIRE_MATH - "-lm " -#endif -#if REQUIRE_DL - "-ldl " -#endif -#if REQUIRE_GRAPHICS - "-lX11 -lXi -lXcursor " -#endif -#if REQUIRE_OPENGL - "-lGL " -#endif -#if REQUIRE_VULKAN - "-lvulkan " -#endif -#if STATIC_RUNTIME - "-static " -#endif - ""; - - if (str_eq(compiler_c, "emcc")) - link_flags = -#if REQUIRE_OPENGL - "-sFULL_ES3=1 " -#endif - ""; - - if (extra_options[0] != '\0') - flags = fmt_dup("%s %s", flags, extra_options); - if (extra_link_options[0] != '\0') - link_flags = fmt_dup("%s %s", link_flags, extra_link_options); - - // Prepare destination folder - // - - destination[0] == '\0' && (destination = "build"); - create_folder_recursive(destination); - - // Check timestamps - // - - Timestamp time_font_text = file_timestamp(FONT_TEXT); - Timestamp time_font_icons = file_timestamp(FONT_ICONS); - Timestamp time_fonts = file_timestamp(INL_FONTS); - Timestamp time_source = file_timestamp(SOURCE); - Timestamp time_tests = file_timestamp(fmt("%s" DLM "test_suite", destination)); - Timestamp time_exe = file_timestamp(fmt("%s" DLM PROJECT, destination)); - - if (time_less(time_fonts, time_font_text) || - time_less(time_fonts, time_font_icons)) - run_codegen = 1; - - if (!file_exists(fmt("%s" DLM "thirdparty%s", destination, postfix_obj))) { - rebuild_all = 1; - rebuild_exe = 1; - } - - if (time_less(time_tests, time_source) || - time_less(time_exe, time_source)) - rebuild_exe = 1; - - // Print info - // - - printf("\nCompiler options: %s\n", flags); - printf( "Link options: %s\n\n", link_flags); - fflush(stdout); - - // Build the project - // - - if (run_codegen) - codegen(); - - if (rebuild_all) { - printf("Rebuild dependencies\n"); - fflush(stdout); - - i32 s = system(fmt( - "%s %s -DDEPENDENCIES=1 " - "%s%s" DLM "thirdparty%s " - SOURCE - " %s", - compiler_c, flags, - flag_obj, destination, postfix_obj, - link_flags) - ); - - if (WEXITSTATUS(s) != 0) - return 1; - fflush(stdout); - } - - if (rebuild_exe) { - printf("Build the test suite\n"); - fflush(stdout); - - i32 s = system(fmt( - "%s %s -DTESTS=1 " - "%s%s" DLM "test_suite%s " - SOURCE - " %s", - compiler_c, flags, - flag_exe, destination, postfix_exe, - link_flags) - ); - - if (WEXITSTATUS(s) != 0) - return 1; - fflush(stdout); - - printf("Build " PROJECT " executable\n"); - fflush(stdout); - - s = system(fmt( - "%s %s -DEXE=1 " - "%s%s" DLM PROJECT "%s " - "%s" DLM "thirdparty%s " - SOURCE - " %s", - compiler_c, flags, - flag_exe, destination, postfix_exe, - destination, postfix_obj, - link_flags) - ); - - if (WEXITSTATUS(s) != 0) - return 1; - fflush(stdout); - } - - if (run_tests) { - printf("Run tests\n"); - fflush(stdout); - - i32 s = system(fmt("\"%s" DLM "test_suite\"", destination)); - - if (WEXITSTATUS(s) != 0) - return -1; - } - - if (run_exe) - system(fmt("\"%s" DLM PROJECT "\"", destination)); - - printf("All done\n"); return 0; } - -// ================================================================ -// -// DEPENDENCIES -// -// ================================================================ - -#elif DEPENDENCIES - -#if defined(__EMSCRIPTEN__) -# define SOKOL_GLES3 -# define NANOVG_GLES3 1 -#else -# define SOKOL_GLCORE33 -# define NANOVG_GL3 1 -#endif - -#ifdef __GNUC__ -# pragma GCC diagnostic push -# pragma GCC diagnostic ignored "-Wpedantic" -#endif -#define SOKOL_APP_IMPL -// hotfix for weird GCC bug -#ifdef __linux__ -# include <emmintrin.h> -#endif -#include "kit/_lib.c" -#include "sokol/sokol_app.h" -#ifdef __GNUC__ -# pragma GCC diagnostic pop -#endif - -#ifdef __GNUC__ -# pragma GCC diagnostic push -# pragma GCC diagnostic ignored "-Wunused-result" -#endif -#define MINIAUDIO_IMPLEMENTATION -#include "miniaudio/miniaudio.h" -#ifdef __GNUC__ -# pragma GCC diagnostic pop -#endif - -#include "nanovg/nanovg.c" -#include "nanovg/nanovg_gl.c" - // ================================================================ // // EXECUTABLE // // ================================================================ - #elif EXE - // ================================================================ // // Headers // // ================================================================ -#include "kit/math.h" -#include "kit/time.h" -#include "kit/string_ref.h" -#include "kit/mersenne_twister_64.h" -#include "kit/secure_random.h" -#include "kit/file.h" -#include "kit/input_buffer.h" -#include "kit/threads.h" -#include "kit/status.h" - -#if defined(__EMSCRIPTEN__) -# include <GLES3/gl3.h> -# define SOKOL_GLES3 -# define NANOVG_GLES3 1 -#else -# include <GL/gl.h> -# define SOKOL_GLCORE33 -# define NANOVG_GL3 1 -#endif - -#include "sokol/sokol_app.h" -#include "nanovg/nanovg.h" -#include "nanovg/nanovg_gl.h" -#include "miniaudio/miniaudio.h" - #include <stdio.h> #include <stdlib.h> // ttf_text, TTF_TEXT_SIZE // ttf_icons, TTF_ICONS_SIZE -#include "build_fonts.inl.c" +#include "fonts.inl.c" // ================================================================ // @@ -1002,13 +423,13 @@ i32 main(i32 argc, c8 **argv) { #define VERSION_MAJOR 0 #define VERSION_MINOR 0 -#define VERSION_BABY 3 +#define VERSION_BABY 4 #define VERSION_DEV 1 // Configuration // -#define EPS 0.00001 +#define EPS 1e-7 #define REFERENCE_PITCH 440.0 // A_4 #define EQUAL_TEMPERAMENT_FACTOR 1.05946309436 // 2^(1/12) #define GLOBAL_VOLUME 2.0 @@ -1020,19 +441,11 @@ enum { REFERENCE_PITCH_INDEX = 5 * 12, // index of A_4 -#ifdef __EMSCRIPTEN__ - TRACK_COUNT = 8, - ROLL_COUNT = 16, - PITCH_COUNT = 80, - VOICE_COUNT = 16, - SHEET_SIZE = 200, -#else TRACK_COUNT = 16, ROLL_COUNT = 64, PITCH_COUNT = 100, VOICE_COUNT = 64, SHEET_SIZE = 200, -#endif ROLL_DEFAULT_RATE = 8, ROLL_DEFAULT_UI_OFFSET_Y = 2000, @@ -1762,7 +1175,7 @@ void audio_render(void) { mtx_unlock(&playback_mutex); } -#ifndef __EMSCRIPTEN__ +#ifndef __wasm__ if (frame_count == 0 && !playback_on) // Sleep for 1/5 of the buffer duration thrd_sleep( @@ -2513,7 +1926,7 @@ void ui_end(void) { ui_input_active = -1; -#ifndef __EMSCRIPTEN__ +#ifndef __wasm__ sapp_lock_mouse(0); #endif } @@ -2577,7 +1990,7 @@ void ui_value_float(f64 x0, f64 y0, f64 width, f64 height, ui_input_active = ui_input_index; ui_input_buffer = *data * scale; -#ifndef __EMSCRIPTEN__ +#ifndef __wasm__ sapp_lock_mouse(1); #endif } @@ -2590,7 +2003,7 @@ void ui_value_float(f64 x0, f64 y0, f64 width, f64 height, } else { ui_input_active = -1; -#ifndef __EMSCRIPTEN__ +#ifndef __wasm__ sapp_lock_mouse(0); #endif } @@ -2665,7 +2078,7 @@ void ui_value_int(f64 x0, f64 y0, f64 width, f64 height, ui_input_active = ui_input_index; ui_input_buffer = (f64) *data * scale; -#ifndef __EMSCRIPTEN__ +#ifndef __wasm__ sapp_lock_mouse(1); #endif } @@ -2678,7 +2091,7 @@ void ui_value_int(f64 x0, f64 y0, f64 width, f64 height, } else { ui_input_active = -1; -#ifndef __EMSCRIPTEN__ +#ifndef __wasm__ sapp_lock_mouse(0); #endif } @@ -2754,7 +2167,7 @@ void ui_value_list(f64 x0, f64 y0, f64 width, f64 height, ui_input_active = ui_input_index; ui_input_buffer = (f64) *data * scale; -#ifndef __EMSCRIPTEN__ +#ifndef __wasm__ sapp_lock_mouse(1); #endif } @@ -2767,7 +2180,7 @@ void ui_value_list(f64 x0, f64 y0, f64 width, f64 height, } else { ui_input_active = -1; -#ifndef __EMSCRIPTEN__ +#ifndef __wasm__ sapp_lock_mouse(0); #endif } @@ -4501,7 +3914,7 @@ void cleanup(void) { DA_DESTROY(drop_file_data); } -#ifdef __EMSCRIPTEN__ +#ifdef __wasm__ void fetch_drop(sapp_html5_fetch_response const *response) { assert(response != NULL); @@ -4670,7 +4083,7 @@ void handle_event(sapp_event const *event) { // Read the file data into the buffer // -#ifdef __EMSCRIPTEN__ +#ifdef __wasm__ i64 size = sapp_html5_get_dropped_file_size(0); #else i64 size = file_info(str(len, file_name)).size; @@ -4692,7 +4105,7 @@ void handle_event(sapp_event const *event) { break; } -#ifdef __EMSCRIPTEN__ +#ifdef __wasm__ sapp_html5_fetch_dropped_file(&(sapp_html5_fetch_request) { .dropped_file_index = 0, .callback = fetch_drop, |