summaryrefslogtreecommitdiff
path: root/saw.c
diff options
context:
space:
mode:
Diffstat (limited to 'saw.c')
-rwxr-xr-xsaw.c911
1 files changed, 162 insertions, 749 deletions
diff --git a/saw.c b/saw.c
index 7dd8dc5..0a033ed 100755
--- a/saw.c
+++ b/saw.c
@@ -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,