From a62c598c3937489fd38da40257df1fe0be4cafe1 Mon Sep 17 00:00:00 2001 From: Intel A80486DX2-66 Date: Sat, 1 Jun 2024 10:01:38 +0300 Subject: [PATCH 01/49] fwrite_le.*: rename `ifeq_u32_ret` to `ifeq_b32_ret` --- include/fwrite_le.h | 2 +- src/fwrite_le.c | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/include/fwrite_le.h b/include/fwrite_le.h index ec04e87..69e52b1 100644 --- a/include/fwrite_le.h +++ b/include/fwrite_le.h @@ -15,7 +15,7 @@ #define ORDER_NATIVE_U32 0x01234567 #define ORDER_LITTLE_ENDIAN_S4 "\x67\x45\x23\x01" #define ORDER_BIG_ENDIAN_S4 "\x01\x23\x45\x67" -#define ifeq_u32_ret(lhs, rhs, value) if (!memcmp(lhs, rhs, 4)) return value; +#define ifeq_b32_ret(lhs, rhs, value) if (!memcmp(lhs, rhs, 4)) return value; int detect_endianness(void); size_t fwrite_le(void* ptr, size_t size, size_t count, FILE* stream); diff --git a/src/fwrite_le.c b/src/fwrite_le.c index 0fe8ec6..473124c 100644 --- a/src/fwrite_le.c +++ b/src/fwrite_le.c @@ -4,8 +4,8 @@ int detect_endianness(void) { volatile uint32_t native_order_value = ORDER_NATIVE_U32; uint8_t* as_bytes = (uint8_t*)&native_order_value; - ifeq_u32_ret(as_bytes, ORDER_LITTLE_ENDIAN_S4, DETECTED_LITTLE_ENDIAN); - ifeq_u32_ret(as_bytes, ORDER_BIG_ENDIAN_S4, DETECTED_BIG_ENDIAN ); + ifeq_b32_ret(as_bytes, ORDER_LITTLE_ENDIAN_S4, DETECTED_LITTLE_ENDIAN); + ifeq_b32_ret(as_bytes, ORDER_BIG_ENDIAN_S4, DETECTED_BIG_ENDIAN ); return UNSUPPORTED_ENDIANNESS; } From b68475b10d28455fc449b94e77f31974dffc3e83 Mon Sep 17 00:00:00 2001 From: Intel A80486DX2-66 Date: Sat, 1 Jun 2024 11:36:33 +0300 Subject: [PATCH 02/49] dual-license under Unlicense and CC0 --- COPYING | 121 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ README.md | 4 +- 2 files changed, 124 insertions(+), 1 deletion(-) create mode 100644 COPYING diff --git a/COPYING b/COPYING new file mode 100644 index 0000000..0e259d4 --- /dev/null +++ b/COPYING @@ -0,0 +1,121 @@ +Creative Commons Legal Code + +CC0 1.0 Universal + + CREATIVE COMMONS CORPORATION IS NOT A LAW FIRM AND DOES NOT PROVIDE + LEGAL SERVICES. DISTRIBUTION OF THIS DOCUMENT DOES NOT CREATE AN + ATTORNEY-CLIENT RELATIONSHIP. CREATIVE COMMONS PROVIDES THIS + INFORMATION ON AN "AS-IS" BASIS. CREATIVE COMMONS MAKES NO WARRANTIES + REGARDING THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS + PROVIDED HEREUNDER, AND DISCLAIMS LIABILITY FOR DAMAGES RESULTING FROM + THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS PROVIDED + HEREUNDER. + +Statement of Purpose + +The laws of most jurisdictions throughout the world automatically confer +exclusive Copyright and Related Rights (defined below) upon the creator +and subsequent owner(s) (each and all, an "owner") of an original work of +authorship and/or a database (each, a "Work"). + +Certain owners wish to permanently relinquish those rights to a Work for +the purpose of contributing to a commons of creative, cultural and +scientific works ("Commons") that the public can reliably and without fear +of later claims of infringement build upon, modify, incorporate in other +works, reuse and redistribute as freely as possible in any form whatsoever +and for any purposes, including without limitation commercial purposes. +These owners may contribute to the Commons to promote the ideal of a free +culture and the further production of creative, cultural and scientific +works, or to gain reputation or greater distribution for their Work in +part through the use and efforts of others. + +For these and/or other purposes and motivations, and without any +expectation of additional consideration or compensation, the person +associating CC0 with a Work (the "Affirmer"), to the extent that he or she +is an owner of Copyright and Related Rights in the Work, voluntarily +elects to apply CC0 to the Work and publicly distribute the Work under its +terms, with knowledge of his or her Copyright and Related Rights in the +Work and the meaning and intended legal effect of CC0 on those rights. + +1. Copyright and Related Rights. A Work made available under CC0 may be +protected by copyright and related or neighboring rights ("Copyright and +Related Rights"). Copyright and Related Rights include, but are not +limited to, the following: + + i. the right to reproduce, adapt, distribute, perform, display, + communicate, and translate a Work; + ii. moral rights retained by the original author(s) and/or performer(s); +iii. publicity and privacy rights pertaining to a person's image or + likeness depicted in a Work; + iv. rights protecting against unfair competition in regards to a Work, + subject to the limitations in paragraph 4(a), below; + v. rights protecting the extraction, dissemination, use and reuse of data + in a Work; + vi. database rights (such as those arising under Directive 96/9/EC of the + European Parliament and of the Council of 11 March 1996 on the legal + protection of databases, and under any national implementation + thereof, including any amended or successor version of such + directive); and +vii. other similar, equivalent or corresponding rights throughout the + world based on applicable law or treaty, and any national + implementations thereof. + +2. Waiver. To the greatest extent permitted by, but not in contravention +of, applicable law, Affirmer hereby overtly, fully, permanently, +irrevocably and unconditionally waives, abandons, and surrenders all of +Affirmer's Copyright and Related Rights and associated claims and causes +of action, whether now known or unknown (including existing as well as +future claims and causes of action), in the Work (i) in all territories +worldwide, (ii) for the maximum duration provided by applicable law or +treaty (including future time extensions), (iii) in any current or future +medium and for any number of copies, and (iv) for any purpose whatsoever, +including without limitation commercial, advertising or promotional +purposes (the "Waiver"). Affirmer makes the Waiver for the benefit of each +member of the public at large and to the detriment of Affirmer's heirs and +successors, fully intending that such Waiver shall not be subject to +revocation, rescission, cancellation, termination, or any other legal or +equitable action to disrupt the quiet enjoyment of the Work by the public +as contemplated by Affirmer's express Statement of Purpose. + +3. Public License Fallback. Should any part of the Waiver for any reason +be judged legally invalid or ineffective under applicable law, then the +Waiver shall be preserved to the maximum extent permitted taking into +account Affirmer's express Statement of Purpose. In addition, to the +extent the Waiver is so judged Affirmer hereby grants to each affected +person a royalty-free, non transferable, non sublicensable, non exclusive, +irrevocable and unconditional license to exercise Affirmer's Copyright and +Related Rights in the Work (i) in all territories worldwide, (ii) for the +maximum duration provided by applicable law or treaty (including future +time extensions), (iii) in any current or future medium and for any number +of copies, and (iv) for any purpose whatsoever, including without +limitation commercial, advertising or promotional purposes (the +"License"). The License shall be deemed effective as of the date CC0 was +applied by Affirmer to the Work. Should any part of the License for any +reason be judged legally invalid or ineffective under applicable law, such +partial invalidity or ineffectiveness shall not invalidate the remainder +of the License, and in such case Affirmer hereby affirms that he or she +will not (i) exercise any of his or her remaining Copyright and Related +Rights in the Work or (ii) assert any associated claims and causes of +action with respect to the Work, in either case contrary to Affirmer's +express Statement of Purpose. + +4. Limitations and Disclaimers. + + a. No trademark or patent rights held by Affirmer are waived, abandoned, + surrendered, licensed or otherwise affected by this document. + b. Affirmer offers the Work as-is and makes no representations or + warranties of any kind concerning the Work, express, implied, + statutory or otherwise, including without limitation warranties of + title, merchantability, fitness for a particular purpose, non + infringement, or the absence of latent or other defects, accuracy, or + the present or absence of errors, whether or not discoverable, all to + the greatest extent permissible under applicable law. + c. Affirmer disclaims responsibility for clearing rights of other persons + that may apply to the Work or any use thereof, including without + limitation any person's Copyright and Related Rights in the Work. + Further, Affirmer disclaims responsibility for obtaining any necessary + consents, permissions or other rights required for any use of the + Work. + d. Affirmer understands and acknowledges that Creative Commons is not a + party to this document and has no duty or obligation with respect to + this CC0 or use of the Work. diff --git a/README.md b/README.md index 03c5e51..2d3809e 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,5 @@ # C-JS-bytebeat-render -a bytebeat rendering engine in C (no support of JavaScript bytebeat yet) +Dual-licensed under the [Unlicense](http://unlicense.org) (`LICENSE`) or Creative Commons Zero 1.0 Universal (`COPYING`). + +**Description:** a bytebeat rendering engine in C (no support of JavaScript bytebeat yet) From 68788a2db2f1d8d756ec437cea859fb0bb9a24f5 Mon Sep 17 00:00:00 2001 From: Intel A80486DX2-66 Date: Sat, 1 Jun 2024 11:55:44 +0300 Subject: [PATCH 03/49] template.c: fix and improve code explanation --- src/template.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/template.c b/src/template.c index 6af8835..39356bd 100644 --- a/src/template.c +++ b/src/template.c @@ -185,12 +185,12 @@ main(void) uint32_t buffer_size = PRODUCT, file_length = 4 * 4 /* 4 strings of 4 characters */ + - 5 * 4 /* 4 uint32_t values */ + - 4 * 2 /* 5 uint16_t values */ + + 5 * 4 /* 5 uint32_t values */ + + 4 * 2 /* 4 uint16_t values */ + PRODUCT /* sample data */ /* subtract Subchunk2 headers: */ - - 4 /* a 4-character string */ + - 4 /* a string of 4 characters */ - 4 /* a uint32_t value */, fmt_data_length = 16 /* <-- * length of format data before this value From e4c0554420c8683a4f8f7206d5e54f58fece87ce Mon Sep 17 00:00:00 2001 From: Intel A80486DX2-66 Date: Sun, 2 Jun 2024 14:21:01 +0300 Subject: [PATCH 04/49] template.c: remove string junk: fixup --- src/template.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/template.c b/src/template.c index 39356bd..0c84574 100644 --- a/src/template.c +++ b/src/template.c @@ -157,12 +157,9 @@ main(void) if (samples > 0) printf("%" PRIuMAX " samples", samples); - puts( #if VERBOSE_MODE || SEQUENTIAL_MODE - "\n" + puts("\n"); #endif - "" - ); fflush(stdout); #endif From 81bb2e80b4ca411f2414b642bc3a863342950c7d Mon Sep 17 00:00:00 2001 From: Intel A80486DX2-66 Date: Sun, 2 Jun 2024 19:33:30 +0300 Subject: [PATCH 05/49] bytebeat_compiler.py: add intro --- bytebeat_compiler.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/bytebeat_compiler.py b/bytebeat_compiler.py index 1761328..9150a70 100644 --- a/bytebeat_compiler.py +++ b/bytebeat_compiler.py @@ -1,5 +1,8 @@ #!/usr/bin/python3 +if __name__ == "__main__": + print(":: C bytebeat generator: compiler unit") + from argparse import ArgumentParser from os import environ, makedirs from os.path import exists, join as path_join From 31244bd18ded15c28b25743668ba32052aa5e233 Mon Sep 17 00:00:00 2001 From: Intel A80486DX2-66 Date: Sun, 2 Jun 2024 19:34:49 +0300 Subject: [PATCH 06/49] bytebeat_compiler.py: search for compiler, fix section names and reformat --- bytebeat_compiler.py | 41 ++++++++++++++++++++++++++++++++++++++--- 1 file changed, 38 insertions(+), 3 deletions(-) diff --git a/bytebeat_compiler.py b/bytebeat_compiler.py index 9150a70..3823f2d 100644 --- a/bytebeat_compiler.py +++ b/bytebeat_compiler.py @@ -4,9 +4,10 @@ if __name__ == "__main__": print(":: C bytebeat generator: compiler unit") from argparse import ArgumentParser -from os import environ, makedirs +from os import environ, makedirs, name as os_name from os.path import exists, join as path_join from shlex import split as command_line_split +from shutil import which from sys import stdin, stdout, exit from typing import Dict, Union import subprocess @@ -86,12 +87,27 @@ preprocessor_bool = lambda value: "1" if value else "0" C_str_repr = lambda s: '"' + s.replace("\\", "\\\\").replace(r'"', r'\"') + '"' CC = fetch("CC") + +CC_SEARCH_LIST = [ + "gcc", + "clang", + "tcc" +] +if os_name == "nt": + CC_SEARCH_LIST = [ + "msc", + *CC_SEARCH_LIST + ] + CFLAGS = fetch("CFLAGS") INPUT_FILE = fetch("INPUT_FILE") OUTPUT_FILE = fetch("OUTPUT_FILE") if extra := fetch("CFLAGS_EXTRA"): CFLAGS += " " + extra +is_cmd_available = lambda cmd: which(cmd) is not None +is_cmd_unavailable = lambda cmd: which(cmd) is None + if __name__ == "__main__": parser = ArgumentParser(description=\ "Substitutes supplied C (non-JavaScript!) bytebeat into the template, " @@ -238,10 +254,28 @@ if __name__ == "__main__": "ansi_escape_codes_supported": ansi_escape_codes_supported }, read_file(PATHS["template"]), args.show_substituted_values)) - # Compile by invoking the shell script + if is_cmd_unavailable(CC): + print(f"Compiler {CC} not available, searching:") + + still_unavailable = True + for compiler in CC_SEARCH_LIST: + print(f"* Trying CC={compiler}", end="") + if is_cmd_available(compiler): + print(": OK") + CC = compiler + still_unavailable = False + break + else: + print() + + if still_unavailable: + print("Could not find an available compiler. Please specify it by " + "setting\nenvironmental variable CC.") + exit(2) + + # Compile print("Compiling") - # Let the system execute aliases by calling os.system command = [ CC, *command_line_split(CFLAGS), @@ -251,4 +285,5 @@ if __name__ == "__main__": "-I" + PATHS["include_directory"] ] print(" ".join(command), flush=True) + exit(subprocess.run(command).returncode) From 009d6365e7efa7262776d3c6e11ff5dbb08dc95c Mon Sep 17 00:00:00 2001 From: Intel A80486DX2-66 Date: Sun, 2 Jun 2024 23:29:29 +0300 Subject: [PATCH 07/49] template.c: merge exact, neighbor conditional compilation --- src/template.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/template.c b/src/template.c index 0c84574..c39b4a6 100644 --- a/src/template.c +++ b/src/template.c @@ -112,9 +112,7 @@ main(void) #if !SILENT_MODE puts(":: C bytebeat generator runtime unit"); fflush(stdout); -#endif -#if !SILENT_MODE const uintmax_t seconds = LENGTH / SAMPLE_RATE, samples = LENGTH % SAMPLE_RATE; From 9d295685a5e09c024a8e05f31f7da8e1a1c981b7 Mon Sep 17 00:00:00 2001 From: Intel A80486DX2-66 Date: Mon, 3 Jun 2024 00:19:08 +0300 Subject: [PATCH 08/49] template.c: silent mode fixes --- src/template.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/template.c b/src/template.c index c39b4a6..be6e0be 100644 --- a/src/template.c +++ b/src/template.c @@ -164,7 +164,7 @@ main(void) // * write WAVE headers // 0. log -#if SEQUENTIAL_MODE +#if !SILENT_MODE && SEQUENTIAL_MODE puts("Writing WAVE headers..."); #endif @@ -219,8 +219,10 @@ main(void) size_t BLOCK_SIZE = BLOCK_SIZE_BYTES / (sizeof(SAMPLE_TYPE) / sizeof(uint8_t)); if (BLOCK_SIZE < 1) { +# if !SILENT_MODE printf("The block size " INT2STR(BLOCK_SIZE_BYTES) " is too small, " "should be at least %" PRIuMAX " bytes\n", MINIMUM_BLOCK_SIZE); +# endif return EXIT_FAILURE; } From c78966cad0269ce32442e74d73e39f2cc00da2ce Mon Sep 17 00:00:00 2001 From: Intel A80486DX2-66 Date: Mon, 3 Jun 2024 00:21:26 +0300 Subject: [PATCH 09/49] template.c: reformat --- src/template.c | 42 +++++++++++++++++++++--------------------- 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/src/template.c b/src/template.c index be6e0be..2a0fc9a 100644 --- a/src/template.c +++ b/src/template.c @@ -120,20 +120,20 @@ main(void) "\n" "Sample rate: " INT2STR(SAMPLE_RATE) " Hz\n" "Channels: " INT2STR(CHANNELS) -#if CHANNELS <= 2 +# if CHANNELS <= 2 " (" -# if CHANNELS == 2 +# if CHANNELS == 2 "stereo" -# else +# else "mono" -# endif +# endif ")" -#endif +# endif "\n" "Bit depth: " -#if !IS_SIGNED +# if !IS_SIGNED "un" -#endif +# endif "signed " INT2STR(BIT_DEPTH) "-bit\n" "Duration: "); @@ -155,9 +155,9 @@ main(void) if (samples > 0) printf("%" PRIuMAX " samples", samples); -#if VERBOSE_MODE || SEQUENTIAL_MODE +# if VERBOSE_MODE || SEQUENTIAL_MODE puts("\n"); -#endif +# endif fflush(stdout); #endif @@ -306,16 +306,16 @@ main(void) time >= gen_length_minus_1 /* or if writing last sample */) { printf( "%sremaining samples = %18" PRIuMAX " (%3.2Lf%% done)" -#if SEQUENTIAL_MODE +# if SEQUENTIAL_MODE " (part %" PRIuMAX "/%" PRIuMAX ")" -#endif +# endif , _ANSI_CLEAR_STRING, gen_length_minus_1 - time, ((long double) time * 100) / (long double) GEN_LENGTH -#if SEQUENTIAL_MODE +# if SEQUENTIAL_MODE , (uintmax_t) seq + 1, (uintmax_t) MAX -#endif +# endif ); fflush(stdout); } @@ -326,16 +326,16 @@ main(void) printf(_ANSI_CLEAR_STRING); // 5. log -#if !(SEQUENTIAL_MODE && VERBOSE_MODE) -#if SEQUENTIAL_MODE +# if !(SEQUENTIAL_MODE && VERBOSE_MODE) +# if SEQUENTIAL_MODE if (seq == 0) -#endif +# endif puts( -#if !SEQUENTIAL_MODE +# if !SEQUENTIAL_MODE "\n" -#endif +# endif "Writing out file " OUTPUT_FILE "..."); -#endif +# endif fflush(stdout); #endif @@ -364,9 +364,9 @@ main(void) // * end of program #if !SILENT_MODE puts( -#if SEQUENTIAL_MODE && VERBOSE_MODE +# if SEQUENTIAL_MODE && VERBOSE_MODE "\n" -#endif +# endif "Done!"); #endif From 3033eb2b69bc357cbb1bb785bb614cd429addc88 Mon Sep 17 00:00:00 2001 From: Intel A80486DX2-66 Date: Mon, 3 Jun 2024 00:28:36 +0300 Subject: [PATCH 10/49] template.c: use `EXIT_FAILURE` instead of `1` --- src/template.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/template.c b/src/template.c index 2a0fc9a..10a6aa5 100644 --- a/src/template.c +++ b/src/template.c @@ -173,7 +173,7 @@ main(void) if (output_file == NULL) { fflush(stdout); perror("fopen"); - return 1; + return EXIT_FAILURE; } // 2. prepare variables From 8e0169affb4ecbbb4b81937089cce1a889355074 Mon Sep 17 00:00:00 2001 From: Intel A80486DX2-66 Date: Mon, 3 Jun 2024 00:29:45 +0300 Subject: [PATCH 11/49] template.c: output all errors to STDERR --- src/template.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/template.c b/src/template.c index 10a6aa5..b567b4f 100644 --- a/src/template.c +++ b/src/template.c @@ -220,8 +220,9 @@ main(void) sizeof(uint8_t)); if (BLOCK_SIZE < 1) { # if !SILENT_MODE - printf("The block size " INT2STR(BLOCK_SIZE_BYTES) " is too small, " - "should be at least %" PRIuMAX " bytes\n", MINIMUM_BLOCK_SIZE); + fprintf(stderr, "The block size " INT2STR(BLOCK_SIZE_BYTES) " is too " + "small, should be at least %" PRIuMAX " bytes\n", + MINIMUM_BLOCK_SIZE); # endif return EXIT_FAILURE; } From 11740eed72bb92b88c08e52c7d53405c56d9d3c4 Mon Sep 17 00:00:00 2001 From: Intel A80486DX2-66 Date: Sun, 16 Jun 2024 09:54:46 +0300 Subject: [PATCH 12/49] EXAMPLE_USAGE.md: update the output --- EXAMPLE_USAGE.md | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/EXAMPLE_USAGE.md b/EXAMPLE_USAGE.md index 6976b9d..2be7e89 100644 --- a/EXAMPLE_USAGE.md +++ b/EXAMPLE_USAGE.md @@ -2,7 +2,9 @@ ```text $ echo 't&((t>>7)-t)&t>>8' | python ./bytebeat_compiler.py - -p 44100 -v && ./build/render_bytebeat +:: C bytebeat generator: compiler unit Compiling +cc -Ofast -march=native -mtune=native -Wall -Wextra -Wpedantic -pedantic -Wno-unused-variable -Wno-unused-but-set-variable -Wno-dangling-else -Wno-parentheses -std=c99 ./build/substituted.c ./src/fwrite_le.c -o ./build/render_bytebeat -I./include :: C bytebeat generator runtime unit Sample rate: 44100 Hz @@ -10,8 +12,8 @@ Channels: 1 (mono) Bit depth: unsigned 8-bit Duration: 30 seconds -remaining samples = 0 (100.00% done) -Writing out file output.wav... +Writing WAVE headers... +remaining samples = 0 (100.00% done) (part 21/21) Done! $ From 05ccd4bca756db669fd60d678a7485354eaab424 Mon Sep 17 00:00:00 2001 From: Intel A80486DX2-66 Date: Tue, 18 Jun 2024 18:14:05 +0300 Subject: [PATCH 13/49] fwrite_le.h: move `#include`s inside the `#ifdef` block --- include/fwrite_le.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/include/fwrite_le.h b/include/fwrite_le.h index 69e52b1..76127a3 100644 --- a/include/fwrite_le.h +++ b/include/fwrite_le.h @@ -1,11 +1,11 @@ +#ifndef _FWRITE_LE_H +#define _FWRITE_LE_H + #include #include #include #include -#ifndef _FWRITE_LE_H -#define _FWRITE_LE_H - #define FWRITE_LE_NO_MODIFICATION 0 #define DETECTED_LITTLE_ENDIAN 0 From 3acee16d796d67cc2441620b8fa553c445f1f397 Mon Sep 17 00:00:00 2001 From: Intel A80486DX2-66 Date: Tue, 18 Jun 2024 18:15:32 +0300 Subject: [PATCH 14/49] fwrite_le.*: make use of `const` for `ptr` --- include/fwrite_le.h | 6 +++++- src/fwrite_le.c | 6 +++++- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/include/fwrite_le.h b/include/fwrite_le.h index 76127a3..6eb6fd1 100644 --- a/include/fwrite_le.h +++ b/include/fwrite_le.h @@ -18,7 +18,11 @@ #define ifeq_b32_ret(lhs, rhs, value) if (!memcmp(lhs, rhs, 4)) return value; int detect_endianness(void); -size_t fwrite_le(void* ptr, size_t size, size_t count, FILE* stream); +size_t fwrite_le( +#if FWRITE_LE_NO_MODIFICATION + const +#endif + void* ptr, size_t size, size_t count, FILE* stream); void reorder_le_be( #if FWRITE_LE_NO_MODIFICATION uint8_t* dest, uint8_t* src, diff --git a/src/fwrite_le.c b/src/fwrite_le.c index 473124c..e9beb3f 100644 --- a/src/fwrite_le.c +++ b/src/fwrite_le.c @@ -37,7 +37,11 @@ void reorder_le_be( } } -size_t fwrite_le(void* ptr, size_t size, size_t count, FILE* stream) { +size_t fwrite_le( +#if FWRITE_LE_NO_MODIFICATION + const +#endif + void* ptr, size_t size, size_t count, FILE* stream) { /* * warning: this function modifies `void* ptr` by default! * (if FWRITE_LE_NO_MODIFICATION in the header is 0) From 46b8287278f97dc8196809db1decc724f3898858 Mon Sep 17 00:00:00 2001 From: Intel A80486DX2-66 Date: Fri, 5 Jul 2024 15:21:01 +0300 Subject: [PATCH 15/49] fwrite_le.h: reduce scope of private macros --- include/fwrite_le.h | 5 ----- src/fwrite_le.c | 5 +++++ 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/include/fwrite_le.h b/include/fwrite_le.h index 6eb6fd1..58d6ef6 100644 --- a/include/fwrite_le.h +++ b/include/fwrite_le.h @@ -12,11 +12,6 @@ #define DETECTED_BIG_ENDIAN 1 #define UNSUPPORTED_ENDIANNESS -1 -#define ORDER_NATIVE_U32 0x01234567 -#define ORDER_LITTLE_ENDIAN_S4 "\x67\x45\x23\x01" -#define ORDER_BIG_ENDIAN_S4 "\x01\x23\x45\x67" -#define ifeq_b32_ret(lhs, rhs, value) if (!memcmp(lhs, rhs, 4)) return value; - int detect_endianness(void); size_t fwrite_le( #if FWRITE_LE_NO_MODIFICATION diff --git a/src/fwrite_le.c b/src/fwrite_le.c index e9beb3f..4a3b4cc 100644 --- a/src/fwrite_le.c +++ b/src/fwrite_le.c @@ -1,5 +1,10 @@ #include "fwrite_le.h" +#define ORDER_NATIVE_U32 0x01234567 +#define ORDER_LITTLE_ENDIAN_S4 "\x67\x45\x23\x01" +#define ORDER_BIG_ENDIAN_S4 "\x01\x23\x45\x67" +#define ifeq_b32_ret(lhs, rhs, value) if (!memcmp(lhs, rhs, 4)) return value; + int detect_endianness(void) { volatile uint32_t native_order_value = ORDER_NATIVE_U32; uint8_t* as_bytes = (uint8_t*)&native_order_value; From 7e68c5e6995ca7a44f346462410d310364d181f8 Mon Sep 17 00:00:00 2001 From: Intel A80486DX2-66 Date: Sat, 6 Jul 2024 17:33:56 +0300 Subject: [PATCH 16/49] README.md: reformat --- README.md | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 2d3809e..ec7e123 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,7 @@ # C-JS-bytebeat-render -Dual-licensed under the [Unlicense](http://unlicense.org) (`LICENSE`) or Creative Commons Zero 1.0 Universal (`COPYING`). +Dual-licensed under the [Unlicense](http://unlicense.org) (`LICENSE`) or +Creative Commons Zero 1.0 Universal (`COPYING`). -**Description:** a bytebeat rendering engine in C (no support of JavaScript bytebeat yet) +**Description:** a bytebeat rendering engine in C (no support of JavaScript +bytebeat yet) From c1ea01869f5e9d5ff02a616449321b98a940f62e Mon Sep 17 00:00:00 2001 From: Intel A80486DX2-66 Date: Sat, 6 Jul 2024 17:35:27 +0300 Subject: [PATCH 17/49] README.md: improve license information and reformat --- README.md | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index ec7e123..c8d1de5 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,10 @@ # C-JS-bytebeat-render -Dual-licensed under the [Unlicense](http://unlicense.org) (`LICENSE`) or -Creative Commons Zero 1.0 Universal (`COPYING`). - **Description:** a bytebeat rendering engine in C (no support of JavaScript bytebeat yet) + +## License + +Dual-licensed under the [Unlicense](http://unlicense.org) +([`LICENSE`](LICENSE)) and Creative Commons Zero 1.0 Universal +([`COPYING`](COPYING)). From f1f5c2a859df38e26487912141c227ab0e5c1e47 Mon Sep 17 00:00:00 2001 From: Intel A80486DX2-66 Date: Sat, 13 Jul 2024 22:35:33 +0300 Subject: [PATCH 18/49] template.c: extract `BITS_PER_BYTE` Additionally, do not cast values to `long double` to calculate for `uintmax_t bit_depth_stretch` --- src/template.c | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/src/template.c b/src/template.c index b567b4f..dde3ae4 100644 --- a/src/template.c +++ b/src/template.c @@ -31,7 +31,9 @@ #define CHANNELS `channels` #define LENGTH `length` -#if BIT_DEPTH <= 8 +#define BITS_PER_BYTE 8 + +#if BIT_DEPTH <= BITS_PER_BYTE # define SAMPLE_TYPE uint8_t #elif BIT_DEPTH >= 16 # if IS_SIGNED @@ -192,11 +194,11 @@ main(void) * in the file format structure */, sample_rate = SAMPLE_RATE, - byte_rate = (SAMPLE_RATE * BIT_DEPTH * CHANNELS) / 8; + byte_rate = (SAMPLE_RATE * BIT_DEPTH * CHANNELS) / BITS_PER_BYTE; uint16_t fmt_type = 1, // format type is PCM channels = CHANNELS, - block_align = (BIT_DEPTH * CHANNELS) / 8, - bit_depth = BIT_DEPTH > 8 ? BIT_DEPTH : 8; + block_align = (BIT_DEPTH * CHANNELS) / BITS_PER_BYTE, + bit_depth = BIT_DEPTH > BITS_PER_BYTE ? BIT_DEPTH : BITS_PER_BYTE; // 3. write headers // : : @@ -244,9 +246,9 @@ main(void) #if FP_RETURN_TYPE + 1 #endif -#if BIT_DEPTH < 8 +#if BIT_DEPTH < BITS_PER_BYTE , - bit_depth_stretch = ((long double) BIT_DEPTH) / 8.L + bit_depth_stretch = BIT_DEPTH / BITS_PER_BYTE #endif ; @@ -288,8 +290,8 @@ main(void) ((uintmax_t) bytebeat_res & bit_depth_limiter); #endif - // 4. if bit depth is less than 8, stretch it -#if BIT_DEPTH < 8 + // 4. if bit depth is less than BITS_PER_BYTE, stretch it +#if BIT_DEPTH < BITS_PER_BYTE sample_res = (SAMPLE_TYPE) ((long double) sample_res * bit_depth_stretch); #endif From ba5d489352059246cc6201fc99b0be06b84918ab Mon Sep 17 00:00:00 2001 From: Intel A80486DX2-66 Date: Sat, 13 Jul 2024 22:39:36 +0300 Subject: [PATCH 19/49] template.c: simplify `file_length` calculation --- src/template.c | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/src/template.c b/src/template.c index dde3ae4..b7fc4fa 100644 --- a/src/template.c +++ b/src/template.c @@ -181,14 +181,11 @@ main(void) // 2. prepare variables uint32_t buffer_size = PRODUCT, file_length = - 4 * 4 /* 4 strings of 4 characters */ + - 5 * 4 /* 5 uint32_t values */ + - 4 * 2 /* 4 uint16_t values */ + - PRODUCT /* sample data */ - - /* subtract Subchunk2 headers: */ - - 4 /* a string of 4 characters */ - - 4 /* a uint32_t value */, + /* file length without "RIFF" chunk */ + 3 * 4 /* 3 strings of 4 characters: "WAVE", "fmt ", "data" */ + + 4 * 4 /* 4 uint32_t values */ + + 4 * 2 /* 4 uint16_t values */ + + PRODUCT /* sample data */, fmt_data_length = 16 /* <-- * length of format data before this value * in the file format structure From fc5612219dbbafd25d8882516da8d7e4582feee8 Mon Sep 17 00:00:00 2001 From: Intel A80486DX2-66 Date: Sun, 14 Jul 2024 00:11:31 +0300 Subject: [PATCH 20/49] fwrite_le.c: use `malloc` instead of `calloc` --- src/fwrite_le.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/fwrite_le.c b/src/fwrite_le.c index 4a3b4cc..7e0eb43 100644 --- a/src/fwrite_le.c +++ b/src/fwrite_le.c @@ -65,9 +65,9 @@ size_t fwrite_le( // case: big-endian size_t bytes_count = size * count; #if FWRITE_LE_NO_MODIFICATION - uint8_t* bytes = calloc(bytes_count, sizeof(uint8_t)); + uint8_t* bytes = malloc(bytes_count * sizeof(uint8_t)); if (bytes == NULL) { - perror("calloc"); + perror("malloc"); exit(EXIT_FAILURE); } memcpy(bytes, ptr, bytes_count); From cd927b83fb376806e864c6d406bf3892e98ae223 Mon Sep 17 00:00:00 2001 From: Intel A80486DX2-66 Date: Sun, 14 Jul 2024 00:13:25 +0300 Subject: [PATCH 21/49] bytebeat_compiler.py: extract `BITS_PER_BYTE` --- bytebeat_compiler.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/bytebeat_compiler.py b/bytebeat_compiler.py index 3823f2d..e7fa949 100644 --- a/bytebeat_compiler.py +++ b/bytebeat_compiler.py @@ -12,6 +12,9 @@ from sys import stdin, stdout, exit from typing import Dict, Union import subprocess +# Definitions +BITS_PER_BYTE = 8 + # Paths PATHS = { "src_dir": "src", @@ -244,7 +247,7 @@ if __name__ == "__main__": "fp_return_type": args.floating_point, "channels": args.channels, "length": samples, - "wav_product": gen_length * (args.bit_depth // 8), + "wav_product": gen_length * (args.bit_depth // BITS_PER_BYTE), "gen_length": gen_length, "sequential_mode": args.mode == "sequential", "block_size": args.block_size, From 7335bb94985a86bb63593123142b4215029e1a14 Mon Sep 17 00:00:00 2001 From: Intel A80486DX2-66 Date: Sun, 14 Jul 2024 23:39:06 +0300 Subject: [PATCH 22/49] add SPDX license identifiers --- include/fwrite_le.h | 2 ++ src/fwrite_le.c | 2 ++ src/template.c | 2 ++ 3 files changed, 6 insertions(+) diff --git a/include/fwrite_le.h b/include/fwrite_le.h index 58d6ef6..40a90f5 100644 --- a/include/fwrite_le.h +++ b/include/fwrite_le.h @@ -1,3 +1,5 @@ +// SPDX-License-Identifier: CC0-1.0 OR Unlicense + #ifndef _FWRITE_LE_H #define _FWRITE_LE_H diff --git a/src/fwrite_le.c b/src/fwrite_le.c index 7e0eb43..9919a25 100644 --- a/src/fwrite_le.c +++ b/src/fwrite_le.c @@ -1,3 +1,5 @@ +// SPDX-License-Identifier: CC0-1.0 OR Unlicense + #include "fwrite_le.h" #define ORDER_NATIVE_U32 0x01234567 diff --git a/src/template.c b/src/template.c index b7fc4fa..21bf901 100644 --- a/src/template.c +++ b/src/template.c @@ -1,3 +1,5 @@ +// SPDX-License-Identifier: CC0-1.0 OR Unlicense + #include #include #include From ee2e5c123aaa106c94d5a3680ff0efa3f3420433 Mon Sep 17 00:00:00 2001 From: Intel A80486DX2-66 Date: Fri, 26 Jul 2024 14:25:21 +0300 Subject: [PATCH 23/49] *.py: use a better shebang --- bytebeat_compiler.py | 2 +- gitignore_clean.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/bytebeat_compiler.py b/bytebeat_compiler.py index e7fa949..a481916 100644 --- a/bytebeat_compiler.py +++ b/bytebeat_compiler.py @@ -1,4 +1,4 @@ -#!/usr/bin/python3 +#!/usr/bin/env python3 if __name__ == "__main__": print(":: C bytebeat generator: compiler unit") diff --git a/gitignore_clean.py b/gitignore_clean.py index 7ea6759..ce46552 100644 --- a/gitignore_clean.py +++ b/gitignore_clean.py @@ -1,4 +1,4 @@ -#!/usr/bin/python3 +#!/usr/bin/env python3 from re import sub as re_sub from glob import glob From 1ba391a7094e7cfd08f9d6097bb818d0560e1824 Mon Sep 17 00:00:00 2001 From: Intel A80486DX2-66 Date: Fri, 26 Jul 2024 17:07:07 +0300 Subject: [PATCH 24/49] remove gitignore_clean.py --- gitignore_clean.py | 65 ---------------------------------------------- 1 file changed, 65 deletions(-) delete mode 100644 gitignore_clean.py diff --git a/gitignore_clean.py b/gitignore_clean.py deleted file mode 100644 index ce46552..0000000 --- a/gitignore_clean.py +++ /dev/null @@ -1,65 +0,0 @@ -#!/usr/bin/env python3 - -from re import sub as re_sub -from glob import glob -from os import remove as os_remove -from os.path import isdir as path_isdir, isfile as path_isfile, abspath -from shutil import rmtree - -GITIGNORE_PATH = "./.gitignore" -DRY_RUN = False - -remove_comments = lambda s: re_sub(r"(? Date: Fri, 16 Aug 2024 19:57:19 +0300 Subject: [PATCH 25/49] README.md: swap license order and rephrase to clarify 'or' option --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index c8d1de5..b516218 100644 --- a/README.md +++ b/README.md @@ -5,6 +5,6 @@ bytebeat yet) ## License -Dual-licensed under the [Unlicense](http://unlicense.org) -([`LICENSE`](LICENSE)) and Creative Commons Zero 1.0 Universal -([`COPYING`](COPYING)). +Dual-licensed under the Creative Commons Zero 1.0 Universal +([`COPYING`](COPYING)) or [Unlicense](http://unlicense.org) +([`LICENSE`](LICENSE)). From bbf75baed2fc0dc027df6ba5b5d589e303ade6a5 Mon Sep 17 00:00:00 2001 From: Intel A80486DX2-66 Date: Fri, 16 Aug 2024 20:13:31 +0300 Subject: [PATCH 26/49] README.md: Unlicense: update the protocol of the link --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index b516218..ea53e0c 100644 --- a/README.md +++ b/README.md @@ -6,5 +6,5 @@ bytebeat yet) ## License Dual-licensed under the Creative Commons Zero 1.0 Universal -([`COPYING`](COPYING)) or [Unlicense](http://unlicense.org) +([`COPYING`](COPYING)) or [Unlicense](https://unlicense.org) ([`LICENSE`](LICENSE)). From 7340e1a576b8e6e84f2d04f0df30597e962328d9 Mon Sep 17 00:00:00 2001 From: Intel A80486DX2-66 Date: Fri, 16 Aug 2024 20:15:05 +0300 Subject: [PATCH 27/49] README.md: add links to both licenses --- README.md | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index ea53e0c..99871d9 100644 --- a/README.md +++ b/README.md @@ -5,6 +5,8 @@ bytebeat yet) ## License -Dual-licensed under the Creative Commons Zero 1.0 Universal -([`COPYING`](COPYING)) or [Unlicense](https://unlicense.org) -([`LICENSE`](LICENSE)). +Dual-licensed under the [Creative Commons Zero 1.0 Universal][CC0-1.0] +([`COPYING`](COPYING)) or [Unlicense][Unlicense] ([`LICENSE`](LICENSE)). + +[CC0-1.0]: https://creativecommons.org/publicdomain/zero/1.0/legalcode +[Unlicense]: https://unlicense.org From ffe0f40ea1962e9c4895e2ae737411151b848ae5 Mon Sep 17 00:00:00 2001 From: Intel A80486DX2-66 Date: Tue, 20 Aug 2024 18:46:47 +0300 Subject: [PATCH 28/49] use directory `bin` instead of `build` --- .gitignore | 4 ++-- bytebeat_compiler.py | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/.gitignore b/.gitignore index 6ba3514..4eaafe7 100644 --- a/.gitignore +++ b/.gitignore @@ -52,6 +52,6 @@ Module.symvers Mkfile.old dkms.conf -# ---> products -build/ +# ---> Program output +bin/ *.wav diff --git a/bytebeat_compiler.py b/bytebeat_compiler.py index a481916..14619c7 100644 --- a/bytebeat_compiler.py +++ b/bytebeat_compiler.py @@ -18,7 +18,7 @@ BITS_PER_BYTE = 8 # Paths PATHS = { "src_dir": "src", - "build_dir": "build", + "bin_dir": "bin", "template": "template.c", "substitute": "substituted.c", "output": "render_bytebeat", @@ -29,8 +29,8 @@ PATHS = { # Resolve paths PATHS["template"] = path_join(PATHS["src_dir"], PATHS["template"]) -PATHS["substitute"] = path_join(PATHS["build_dir"], PATHS["substitute"]) -PATHS["output"] = path_join(PATHS["build_dir"], PATHS["output"]) +PATHS["substitute"] = path_join(PATHS["bin_dir"], PATHS["substitute"]) +PATHS["output"] = path_join(PATHS["bin_dir"], PATHS["output"]) PATHS["fwrite_le"] = path_join(PATHS["src_dir"], PATHS["fwrite_le"]) # Add `.` directory before all paths for compilation @@ -173,7 +173,7 @@ if __name__ == "__main__": raise SystemExit # - Compilation - makedirs(PATHS["build_dir"], exist_ok=True) + makedirs(PATHS["bin_dir"], exist_ok=True) if not args.no_return: # Insert `return` statement # XXX: The bytebeat code is enclosed in parentheses to allow for the From 021064a23f7ed09308202600b2ed121a963378a3 Mon Sep 17 00:00:00 2001 From: Intel A80486DX2-66 Date: Tue, 20 Aug 2024 19:45:44 +0300 Subject: [PATCH 29/49] fwrite_le.c: remove superfluous semicolon --- src/fwrite_le.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/fwrite_le.c b/src/fwrite_le.c index 9919a25..48ea672 100644 --- a/src/fwrite_le.c +++ b/src/fwrite_le.c @@ -5,7 +5,7 @@ #define ORDER_NATIVE_U32 0x01234567 #define ORDER_LITTLE_ENDIAN_S4 "\x67\x45\x23\x01" #define ORDER_BIG_ENDIAN_S4 "\x01\x23\x45\x67" -#define ifeq_b32_ret(lhs, rhs, value) if (!memcmp(lhs, rhs, 4)) return value; +#define ifeq_b32_ret(lhs, rhs, value) if (!memcmp(lhs, rhs, 4)) return value int detect_endianness(void) { volatile uint32_t native_order_value = ORDER_NATIVE_U32; From dd8b77ab92e85b677af57651a057b6458736b066 Mon Sep 17 00:00:00 2001 From: Intel A80486DX2-66 Date: Tue, 20 Aug 2024 21:57:54 +0300 Subject: [PATCH 30/49] README.md: revert the name --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 99871d9..2fbed64 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# C-JS-bytebeat-render +# C-bytebeat-render **Description:** a bytebeat rendering engine in C (no support of JavaScript bytebeat yet) From 45be617943a55fa101666a379b6e72e5a4857dd2 Mon Sep 17 00:00:00 2001 From: Intel A80486DX2-66 Date: Tue, 20 Aug 2024 21:58:09 +0300 Subject: [PATCH 31/49] README.md: extend description --- README.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/README.md b/README.md index 2fbed64..1e96959 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,6 @@ # C-bytebeat-render -**Description:** a bytebeat rendering engine in C (no support of JavaScript -bytebeat yet) +**Description:** a bytebeat rendering engine in C for C-compatible bytebeat ## License From c4254b75b47026a4c983e9fea55fe922b0dde82a Mon Sep 17 00:00:00 2001 From: Intel A80486DX2-66 Date: Mon, 26 Aug 2024 17:26:37 +0300 Subject: [PATCH 32/49] b/c...py: run the runtime unit after compiling --- EXAMPLE_USAGE.md | 2 +- bytebeat_compiler.py | 6 ++++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/EXAMPLE_USAGE.md b/EXAMPLE_USAGE.md index 2be7e89..b8ddede 100644 --- a/EXAMPLE_USAGE.md +++ b/EXAMPLE_USAGE.md @@ -1,7 +1,7 @@ ## Example usage ```text -$ echo 't&((t>>7)-t)&t>>8' | python ./bytebeat_compiler.py - -p 44100 -v && ./build/render_bytebeat +$ echo 't&((t>>7)-t)&t>>8' | python ./bytebeat_compiler.py - -p 44100 -v :: C bytebeat generator: compiler unit Compiling cc -Ofast -march=native -mtune=native -Wall -Wextra -Wpedantic -pedantic -Wno-unused-variable -Wno-unused-but-set-variable -Wno-dangling-else -Wno-parentheses -std=c99 ./build/substituted.c ./src/fwrite_le.c -o ./build/render_bytebeat -I./include diff --git a/bytebeat_compiler.py b/bytebeat_compiler.py index 14619c7..70a9e1a 100644 --- a/bytebeat_compiler.py +++ b/bytebeat_compiler.py @@ -289,4 +289,10 @@ if __name__ == "__main__": ] print(" ".join(command), flush=True) + if subprocess.run(command).returncode != 0: + exit(1) + + command = [OUTPUT_FILE] + print(" ".join(command), flush=True) + exit(subprocess.run(command).returncode) From dee6773080f854539256af7c2eb44d91c4868142 Mon Sep 17 00:00:00 2001 From: Intel A80486DX2-66 Date: Mon, 26 Aug 2024 17:29:17 +0300 Subject: [PATCH 33/49] b/c...py: use `EXIT_SUCCESS` and `EXIT_FAILURE` --- bytebeat_compiler.py | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/bytebeat_compiler.py b/bytebeat_compiler.py index 70a9e1a..6468f1c 100644 --- a/bytebeat_compiler.py +++ b/bytebeat_compiler.py @@ -14,6 +14,8 @@ import subprocess # Definitions BITS_PER_BYTE = 8 +EXIT_FAILURE = 1 +EXIT_SUCCESS = 0 # Paths PATHS = { @@ -289,10 +291,13 @@ if __name__ == "__main__": ] print(" ".join(command), flush=True) - if subprocess.run(command).returncode != 0: - exit(1) + if subprocess.run(command).returncode != EXIT_SUCCESS: + exit(EXIT_FAILURE) command = [OUTPUT_FILE] print(" ".join(command), flush=True) - exit(subprocess.run(command).returncode) + if subprocess.run(command).returncode != EXIT_SUCCESS: + exit(EXIT_FAILURE) + + exit(EXIT_SUCCESS) From 75ede327d6748472cc4165ed27751089523ec776 Mon Sep 17 00:00:00 2001 From: Intel A80486DX2-66 Date: Mon, 26 Aug 2024 17:36:09 +0300 Subject: [PATCH 34/49] b/c...py: extract function `run_command` --- bytebeat_compiler.py | 20 ++++++++------------ 1 file changed, 8 insertions(+), 12 deletions(-) diff --git a/bytebeat_compiler.py b/bytebeat_compiler.py index 6468f1c..c351fab 100644 --- a/bytebeat_compiler.py +++ b/bytebeat_compiler.py @@ -88,6 +88,11 @@ def substitute_vars(replacements: Dict[str, Union[bool, str]], text: str, print() return text +def run_command(*command: list[str]) -> None: + print(" ".join(command), flush=True) + if subprocess.run(command).returncode != EXIT_SUCCESS: + exit(EXIT_FAILURE) + preprocessor_bool = lambda value: "1" if value else "0" C_str_repr = lambda s: '"' + s.replace("\\", "\\\\").replace(r'"', r'\"') + '"' @@ -281,23 +286,14 @@ if __name__ == "__main__": # Compile print("Compiling") - command = [ + run_command( CC, *command_line_split(CFLAGS), INPUT_FILE, PATHS["fwrite_le"], "-o", OUTPUT_FILE, "-I" + PATHS["include_directory"] - ] - print(" ".join(command), flush=True) - - if subprocess.run(command).returncode != EXIT_SUCCESS: - exit(EXIT_FAILURE) - - command = [OUTPUT_FILE] - print(" ".join(command), flush=True) - - if subprocess.run(command).returncode != EXIT_SUCCESS: - exit(EXIT_FAILURE) + ) + run_command(OUTPUT_FILE) exit(EXIT_SUCCESS) From e7e290b2f46c220badff6739ea90df4f541e0b5d Mon Sep 17 00:00:00 2001 From: Intel A80486DX2-66 Date: Mon, 26 Aug 2024 17:38:58 +0300 Subject: [PATCH 35/49] b/c...py: notify the user when reading STDIN Notify the user when the script reads bytebeat code from STDIN --- bytebeat_compiler.py | 1 + 1 file changed, 1 insertion(+) diff --git a/bytebeat_compiler.py b/bytebeat_compiler.py index c351fab..89e19c8 100644 --- a/bytebeat_compiler.py +++ b/bytebeat_compiler.py @@ -66,6 +66,7 @@ def rewrite_file(path: str, content: str): def read_from_file_or_stdin(path: str) -> str: if path == "-": + print("Reading from STDIN...", flush=True) return "\n".join(stdin) elif exists(path): return read_file(path) From c6558c8c468fffe3d9f457d2576a176ea1066a95 Mon Sep 17 00:00:00 2001 From: Intel A80486DX2-66 Date: Mon, 26 Aug 2024 17:42:36 +0300 Subject: [PATCH 36/49] bytebeat_compiler.py: make use of `shlex.join` When printing a command that is going to be ran, use `shlex.join(...)` instead of `" ".join(...)` --- bytebeat_compiler.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/bytebeat_compiler.py b/bytebeat_compiler.py index 89e19c8..c6065ee 100644 --- a/bytebeat_compiler.py +++ b/bytebeat_compiler.py @@ -6,7 +6,7 @@ if __name__ == "__main__": from argparse import ArgumentParser from os import environ, makedirs, name as os_name from os.path import exists, join as path_join -from shlex import split as command_line_split +from shlex import join as command_line_join, split as command_line_split from shutil import which from sys import stdin, stdout, exit from typing import Dict, Union @@ -90,7 +90,7 @@ def substitute_vars(replacements: Dict[str, Union[bool, str]], text: str, return text def run_command(*command: list[str]) -> None: - print(" ".join(command), flush=True) + print(command_line_join(command), flush=True) if subprocess.run(command).returncode != EXIT_SUCCESS: exit(EXIT_FAILURE) From ee404d1ad2d66c123d22254b596966c0569229eb Mon Sep 17 00:00:00 2001 From: Intel A80486DX2-66 Date: Mon, 26 Aug 2024 19:26:00 +0300 Subject: [PATCH 37/49] bytebeat_compiler.py: do not use `sys.exit` --- bytebeat_compiler.py | 30 +++++++++++------------------- 1 file changed, 11 insertions(+), 19 deletions(-) diff --git a/bytebeat_compiler.py b/bytebeat_compiler.py index c6065ee..f554a37 100644 --- a/bytebeat_compiler.py +++ b/bytebeat_compiler.py @@ -8,7 +8,7 @@ from os import environ, makedirs, name as os_name from os.path import exists, join as path_join from shlex import join as command_line_join, split as command_line_split from shutil import which -from sys import stdin, stdout, exit +from sys import stdin, stdout from typing import Dict, Union import subprocess @@ -71,8 +71,7 @@ def read_from_file_or_stdin(path: str) -> str: elif exists(path): return read_file(path) else: - print("The specified file doesn't exist") - raise SystemExit + raise SystemExit(f"The specified file {path} doesn't exist") def substitute_vars(replacements: Dict[str, Union[bool, str]], text: str, verbose: bool) -> str: @@ -92,7 +91,7 @@ def substitute_vars(replacements: Dict[str, Union[bool, str]], text: str, def run_command(*command: list[str]) -> None: print(command_line_join(command), flush=True) if subprocess.run(command).returncode != EXIT_SUCCESS: - exit(EXIT_FAILURE) + raise SystemExit(EXIT_FAILURE) preprocessor_bool = lambda value: "1" if value else "0" C_str_repr = lambda s: '"' + s.replace("\\", "\\\\").replace(r'"', r'\"') + '"' @@ -177,8 +176,7 @@ if __name__ == "__main__": bytebeat_contents = read_from_file_or_stdin(args.file).strip() if not bytebeat_contents: - print("No valid contents") - raise SystemExit + raise SystemExit("No valid contents") # - Compilation makedirs(PATHS["bin_dir"], exist_ok=True) @@ -211,8 +209,7 @@ if __name__ == "__main__": samples_specified = not no_samples if seconds_specified and args.seconds < 0: - print("CLI: Count of seconds can't be less than zero.") - raise SystemExit + raise SystemExit("CLI: Count of seconds can't be less than zero.") if no_seconds and samples_specified: samples = args.samples @@ -224,17 +221,14 @@ if __name__ == "__main__": args.seconds = 30 # default continue else: - print("CLI: Incorrect seconds/samples length format.") - raise SystemExit + raise SystemExit("CLI: Incorrect seconds/samples length format.") break if samples <= 0: - print("CLI: Count of samples should be greater than zero.") - raise SystemExit + raise SystemExit("CLI: Count of samples should be greater than zero.") if args.mode != "sequential" and args.mode != "instant": - print("Invalid mode '%s'" % args.mode) - raise SystemExit + raise SystemExit(f"Invalid mode '{args.mode}'") gen_length = args.channels * samples @@ -280,9 +274,9 @@ if __name__ == "__main__": print() if still_unavailable: - print("Could not find an available compiler. Please specify it by " - "setting\nenvironmental variable CC.") - exit(2) + raise SystemExit("Could not find an available compiler. Please " + "specify it by setting\nenvironmental variable " + "CC.") # Compile print("Compiling") @@ -296,5 +290,3 @@ if __name__ == "__main__": "-I" + PATHS["include_directory"] ) run_command(OUTPUT_FILE) - - exit(EXIT_SUCCESS) From 1e4f9ac26f23a69dd46b5d6fae0ba5504948417d Mon Sep 17 00:00:00 2001 From: Intel A80486DX2-66 Date: Mon, 26 Aug 2024 21:39:36 +0300 Subject: [PATCH 38/49] bytebeat_compiler.py: fix grammar --- bytebeat_compiler.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/bytebeat_compiler.py b/bytebeat_compiler.py index f554a37..c925b8f 100644 --- a/bytebeat_compiler.py +++ b/bytebeat_compiler.py @@ -176,7 +176,7 @@ if __name__ == "__main__": bytebeat_contents = read_from_file_or_stdin(args.file).strip() if not bytebeat_contents: - raise SystemExit("No valid contents") + raise SystemExit("Empty file or STDIN") # - Compilation makedirs(PATHS["bin_dir"], exist_ok=True) @@ -260,7 +260,7 @@ if __name__ == "__main__": }, read_file(PATHS["template"]), args.show_substituted_values)) if is_cmd_unavailable(CC): - print(f"Compiler {CC} not available, searching:") + print(f"Compiler {CC} is not available, searching:") still_unavailable = True for compiler in CC_SEARCH_LIST: @@ -275,7 +275,7 @@ if __name__ == "__main__": if still_unavailable: raise SystemExit("Could not find an available compiler. Please " - "specify it by setting\nenvironmental variable " + "specify it by setting\nan environmental variable " "CC.") # Compile From 429d43f8c15527f921cf2850f4d10b752d658279 Mon Sep 17 00:00:00 2001 From: Intel A80486DX2-66 Date: Mon, 26 Aug 2024 21:40:33 +0300 Subject: [PATCH 39/49] bytebeat_compiler.py: remove generated files --- bytebeat_compiler.py | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/bytebeat_compiler.py b/bytebeat_compiler.py index c925b8f..d4823a7 100644 --- a/bytebeat_compiler.py +++ b/bytebeat_compiler.py @@ -4,7 +4,8 @@ if __name__ == "__main__": print(":: C bytebeat generator: compiler unit") from argparse import ArgumentParser -from os import environ, makedirs, name as os_name +from os import environ, listdir, makedirs, name as os_name, \ + remove as delete_file, rmdir from os.path import exists, join as path_join from shlex import join as command_line_join, split as command_line_split from shutil import which @@ -93,6 +94,10 @@ def run_command(*command: list[str]) -> None: if subprocess.run(command).returncode != EXIT_SUCCESS: raise SystemExit(EXIT_FAILURE) +def delete_empty_dir(path: str) -> None: + if exists(path) and len(listdir(path)) == 0: + rmdir(path) + preprocessor_bool = lambda value: "1" if value else "0" C_str_repr = lambda s: '"' + s.replace("\\", "\\\\").replace(r'"', r'\"') + '"' @@ -171,6 +176,9 @@ if __name__ == "__main__": parser.add_argument("--color", default="auto", type=str, help="ANSI escape codes. Set to 'always' to enable them, 'none' to " "disable. Default: 'auto'.") + parser.add_argument("--keep-files", default=False, action="store_true", + help="keep generated files: substituted source code of runtime unit " + "and the executable it will be compiled to.") args = parser.parse_args() bytebeat_contents = read_from_file_or_stdin(args.file).strip() @@ -290,3 +298,8 @@ if __name__ == "__main__": "-I" + PATHS["include_directory"] ) run_command(OUTPUT_FILE) + + if not args.keep_files: + delete_file(PATHS["substitute"]) + delete_file(OUTPUT_FILE) + delete_empty_dir(PATHS["bin_dir"]) From d0185392c9d316705ed26eef8163381873add7bb Mon Sep 17 00:00:00 2001 From: Intel A80486DX2-66 Date: Mon, 26 Aug 2024 22:04:51 +0300 Subject: [PATCH 40/49] EXAMPLE_USAGE.md: update program output --- EXAMPLE_USAGE.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/EXAMPLE_USAGE.md b/EXAMPLE_USAGE.md index b8ddede..b05f3a7 100644 --- a/EXAMPLE_USAGE.md +++ b/EXAMPLE_USAGE.md @@ -3,8 +3,10 @@ ```text $ echo 't&((t>>7)-t)&t>>8' | python ./bytebeat_compiler.py - -p 44100 -v :: C bytebeat generator: compiler unit +Reading from STDIN... Compiling -cc -Ofast -march=native -mtune=native -Wall -Wextra -Wpedantic -pedantic -Wno-unused-variable -Wno-unused-but-set-variable -Wno-dangling-else -Wno-parentheses -std=c99 ./build/substituted.c ./src/fwrite_le.c -o ./build/render_bytebeat -I./include +cc -Ofast -march=native -mtune=native -Wall -Wextra -Wpedantic -pedantic -Wno-unused-variable -Wno-unused-but-set-variable -Wno-dangling-else -Wno-parentheses -std=c99 ./bin/substituted.c ./src/fwrite_le.c -o ./bin/render_bytebeat -I./include +./bin/render_bytebeat :: C bytebeat generator runtime unit Sample rate: 44100 Hz @@ -13,8 +15,6 @@ Bit depth: unsigned 8-bit Duration: 30 seconds Writing WAVE headers... -remaining samples = 0 (100.00% done) (part 21/21) -Done! -$ +Done! ``` From 3b81fe5eb5b4e4baf7b56cc601927cbba40b54f6 Mon Sep 17 00:00:00 2001 From: Intel A80486DX2-66 Date: Mon, 26 Aug 2024 22:05:56 +0300 Subject: [PATCH 41/49] EXAMPLE_USAGE.md: use "--verbose" instead of "-v" --- EXAMPLE_USAGE.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/EXAMPLE_USAGE.md b/EXAMPLE_USAGE.md index b05f3a7..ce9b232 100644 --- a/EXAMPLE_USAGE.md +++ b/EXAMPLE_USAGE.md @@ -1,7 +1,7 @@ ## Example usage ```text -$ echo 't&((t>>7)-t)&t>>8' | python ./bytebeat_compiler.py - -p 44100 -v +$ echo 't&((t>>7)-t)&t>>8' | python ./bytebeat_compiler.py - -p 44100 --verbose :: C bytebeat generator: compiler unit Reading from STDIN... Compiling From f70ef4c74d2caeb4cfbf5d7f518c3db4eb9bc447 Mon Sep 17 00:00:00 2001 From: Intel A80486DX2-66 Date: Mon, 26 Aug 2024 22:34:39 +0300 Subject: [PATCH 42/49] b/c...py: compile into a temporary directory Generate intermediate files into a temporary directory --- bytebeat_compiler.py | 106 ++++++++++++++++++++++--------------------- 1 file changed, 54 insertions(+), 52 deletions(-) diff --git a/bytebeat_compiler.py b/bytebeat_compiler.py index d4823a7..b87ea38 100644 --- a/bytebeat_compiler.py +++ b/bytebeat_compiler.py @@ -4,12 +4,12 @@ if __name__ == "__main__": print(":: C bytebeat generator: compiler unit") from argparse import ArgumentParser -from os import environ, listdir, makedirs, name as os_name, \ - remove as delete_file, rmdir -from os.path import exists, join as path_join +from os import environ, makedirs, name as os_name, rename +from os.path import basename, exists, join as path_join from shlex import join as command_line_join, split as command_line_split from shutil import which from sys import stdin, stdout +from tempfile import TemporaryDirectory from typing import Dict, Union import subprocess @@ -32,8 +32,8 @@ PATHS = { # Resolve paths PATHS["template"] = path_join(PATHS["src_dir"], PATHS["template"]) -PATHS["substitute"] = path_join(PATHS["bin_dir"], PATHS["substitute"]) -PATHS["output"] = path_join(PATHS["bin_dir"], PATHS["output"]) +PATHS["substitute_kept"] = path_join(PATHS["bin_dir"], PATHS["substitute"]) +PATHS["output_kept"] = path_join(PATHS["bin_dir"], PATHS["output"]) PATHS["fwrite_le"] = path_join(PATHS["src_dir"], PATHS["fwrite_le"]) # Add `.` directory before all paths for compilation @@ -47,8 +47,8 @@ DEFAULT_PARAMETERS = { "CFLAGS": "-Ofast -march=native -mtune=native -Wall -Wextra -Wpedantic " "-pedantic -Wno-unused-variable -Wno-unused-but-set-variable " "-Wno-dangling-else -Wno-parentheses -std=c99", - "INPUT_FILE": PATHS["substitute"], - "OUTPUT_FILE": PATHS["output"] + "INPUT_FILE": PATHS["substitute_kept"], + "OUTPUT_FILE": PATHS["output_kept"] } stdout_atty = hasattr(stdout, "isatty") and stdout.isatty() @@ -94,10 +94,6 @@ def run_command(*command: list[str]) -> None: if subprocess.run(command).returncode != EXIT_SUCCESS: raise SystemExit(EXIT_FAILURE) -def delete_empty_dir(path: str) -> None: - if exists(path) and len(listdir(path)) == 0: - rmdir(path) - preprocessor_bool = lambda value: "1" if value else "0" C_str_repr = lambda s: '"' + s.replace("\\", "\\\\").replace(r'"', r'\"') + '"' @@ -187,8 +183,6 @@ if __name__ == "__main__": raise SystemExit("Empty file or STDIN") # - Compilation - makedirs(PATHS["bin_dir"], exist_ok=True) - if not args.no_return: # Insert `return` statement # XXX: The bytebeat code is enclosed in parentheses to allow for the # use of commas as a comma operator, enabling more formulas to function. @@ -243,30 +237,6 @@ if __name__ == "__main__": ansi_escape_codes_supported = args.color == "auto" and stdout_atty or \ args.color == "always" - rewrite_file(PATHS["substitute"], substitute_vars({ - "bytebeat_contents": bytebeat_contents, - "output_file": C_str_repr(args.output), - "sample_rate": \ - value if (value := args.final_sample_rate) else args.sample_rate, - "original_sample_rate": original_sample_rate, - "final_sample_rate_code": final_sample_rate_code, - "bit_depth": args.bit_depth, - "is_signed": args.signed, - "precalculated_ratio": args.precalculate_ratio, - "faster_sample_ratio_math": args.precalculate_ratio, - "fp_return_type": args.floating_point, - "channels": args.channels, - "length": samples, - "wav_product": gen_length * (args.bit_depth // BITS_PER_BYTE), - "gen_length": gen_length, - "sequential_mode": args.mode == "sequential", - "block_size": args.block_size, - "silent_mode": args.silent, - "verbose_mode": args.verbose and not args.silent, - "fwrite_le": PATHS["fwrite_le_header"], - "ansi_escape_codes_supported": ansi_escape_codes_supported - }, read_file(PATHS["template"]), args.show_substituted_values)) - if is_cmd_unavailable(CC): print(f"Compiler {CC} is not available, searching:") @@ -286,20 +256,52 @@ if __name__ == "__main__": "specify it by setting\nan environmental variable " "CC.") - # Compile - print("Compiling") + with TemporaryDirectory() as tmpdirname: + temporary_path = lambda path: path_join(tmpdirname, basename(path)) - run_command( - CC, - *command_line_split(CFLAGS), - INPUT_FILE, - PATHS["fwrite_le"], - "-o", OUTPUT_FILE, - "-I" + PATHS["include_directory"] - ) - run_command(OUTPUT_FILE) + substitute_temp = temporary_path(INPUT_FILE) + rewrite_file(substitute_temp, substitute_vars({ + "bytebeat_contents": bytebeat_contents, + "output_file": C_str_repr(args.output), + "sample_rate": \ + value if (value := args.final_sample_rate) else \ + args.sample_rate, + "original_sample_rate": original_sample_rate, + "final_sample_rate_code": final_sample_rate_code, + "bit_depth": args.bit_depth, + "is_signed": args.signed, + "precalculated_ratio": args.precalculate_ratio, + "faster_sample_ratio_math": args.precalculate_ratio, + "fp_return_type": args.floating_point, + "channels": args.channels, + "length": samples, + "wav_product": gen_length * (args.bit_depth // BITS_PER_BYTE), + "gen_length": gen_length, + "sequential_mode": args.mode == "sequential", + "block_size": args.block_size, + "silent_mode": args.silent, + "verbose_mode": args.verbose and not args.silent, + "fwrite_le": PATHS["fwrite_le_header"], + "ansi_escape_codes_supported": ansi_escape_codes_supported + }, read_file(PATHS["template"]), args.show_substituted_values)) - if not args.keep_files: - delete_file(PATHS["substitute"]) - delete_file(OUTPUT_FILE) - delete_empty_dir(PATHS["bin_dir"]) + # Compile + print("Compiling") + + output_file_temp = temporary_path(OUTPUT_FILE) + + run_command( + CC, + *command_line_split(CFLAGS), + substitute_temp, + PATHS["fwrite_le"], + "-o", output_file_temp, + "-I" + PATHS["include_directory"] + ) + run_command(output_file_temp) + + if args.keep_files: + makedirs(PATHS["bin_dir"], exist_ok=True) + + rename(substitute_temp, INPUT_FILE) + rename(output_file_temp, OUTPUT_FILE) From 974f7eb53bce421b8dc1529b8d76b1ef761cecc6 Mon Sep 17 00:00:00 2001 From: Intel A80486DX2-66 Date: Mon, 26 Aug 2024 22:44:58 +0300 Subject: [PATCH 43/49] b/c...py: secure input and output files Do not use environmental variables `INPUT_FILE` and `OUTPUT_FILE` --- bytebeat_compiler.py | 22 +++++++++------------- 1 file changed, 9 insertions(+), 13 deletions(-) diff --git a/bytebeat_compiler.py b/bytebeat_compiler.py index b87ea38..9c00769 100644 --- a/bytebeat_compiler.py +++ b/bytebeat_compiler.py @@ -5,7 +5,7 @@ if __name__ == "__main__": from argparse import ArgumentParser from os import environ, makedirs, name as os_name, rename -from os.path import basename, exists, join as path_join +from os.path import exists, join as path_join from shlex import join as command_line_join, split as command_line_split from shutil import which from sys import stdin, stdout @@ -46,9 +46,7 @@ DEFAULT_PARAMETERS = { "CC": "cc", "CFLAGS": "-Ofast -march=native -mtune=native -Wall -Wextra -Wpedantic " "-pedantic -Wno-unused-variable -Wno-unused-but-set-variable " - "-Wno-dangling-else -Wno-parentheses -std=c99", - "INPUT_FILE": PATHS["substitute_kept"], - "OUTPUT_FILE": PATHS["output_kept"] + "-Wno-dangling-else -Wno-parentheses -std=c99" } stdout_atty = hasattr(stdout, "isatty") and stdout.isatty() @@ -111,8 +109,6 @@ if os_name == "nt": ] CFLAGS = fetch("CFLAGS") -INPUT_FILE = fetch("INPUT_FILE") -OUTPUT_FILE = fetch("OUTPUT_FILE") if extra := fetch("CFLAGS_EXTRA"): CFLAGS += " " + extra @@ -123,8 +119,8 @@ if __name__ == "__main__": parser = ArgumentParser(description=\ "Substitutes supplied C (non-JavaScript!) bytebeat into the template, " "then attempts to compile the instance of the template. Accepts " - "environmental variables `CC`, `CFLAGS`, `INPUT_FILE`, `OUTPUT_FILE`. " - "`CFLAGS_EXTRA` can be used to add to default `CFLAGS`.") + "environmental variables `CC`, `CFLAGS`. `CFLAGS_EXTRA` can be used to " + "add to default `CFLAGS`.") parser.add_argument("file", type=str, help="bytebeat formula file (use `-` to read from stdin)") parser.add_argument("-o", "--output", default="output.wav", type=str, @@ -257,9 +253,9 @@ if __name__ == "__main__": "CC.") with TemporaryDirectory() as tmpdirname: - temporary_path = lambda path: path_join(tmpdirname, basename(path)) + temporary_path = lambda path: path_join(tmpdirname, path) - substitute_temp = temporary_path(INPUT_FILE) + substitute_temp = temporary_path(PATHS["substitute"]) rewrite_file(substitute_temp, substitute_vars({ "bytebeat_contents": bytebeat_contents, "output_file": C_str_repr(args.output), @@ -288,7 +284,7 @@ if __name__ == "__main__": # Compile print("Compiling") - output_file_temp = temporary_path(OUTPUT_FILE) + output_file_temp = temporary_path(PATHS["output"]) run_command( CC, @@ -303,5 +299,5 @@ if __name__ == "__main__": if args.keep_files: makedirs(PATHS["bin_dir"], exist_ok=True) - rename(substitute_temp, INPUT_FILE) - rename(output_file_temp, OUTPUT_FILE) + rename(substitute_temp, PATHS["substitute_kept"]) + rename(output_file_temp, PATHS["output_kept"]) From be5c7186ecea674531268fb52f33b0b1f1885422 Mon Sep 17 00:00:00 2001 From: Intel A80486DX2-66 Date: Mon, 26 Aug 2024 22:54:02 +0300 Subject: [PATCH 44/49] bytebeat_compiler.py: fix extra dots in paths --- bytebeat_compiler.py | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/bytebeat_compiler.py b/bytebeat_compiler.py index 9c00769..277067c 100644 --- a/bytebeat_compiler.py +++ b/bytebeat_compiler.py @@ -30,17 +30,16 @@ PATHS = { "include_directory": "include" } +# Add `.` directory before all paths for compilation +for key in ["src_dir", "bin_dir", "include_directory"]: + PATHS[key] = path_join(".", PATHS[key]) + # Resolve paths PATHS["template"] = path_join(PATHS["src_dir"], PATHS["template"]) PATHS["substitute_kept"] = path_join(PATHS["bin_dir"], PATHS["substitute"]) PATHS["output_kept"] = path_join(PATHS["bin_dir"], PATHS["output"]) PATHS["fwrite_le"] = path_join(PATHS["src_dir"], PATHS["fwrite_le"]) -# Add `.` directory before all paths for compilation -for key in ["template", "substitute", "output", "fwrite_le", - "include_directory"]: - PATHS[key] = path_join(".", PATHS[key]) - # Default parameters DEFAULT_PARAMETERS = { "CC": "cc", From 23801c4eaa4bb2b0dab346595b2d995710e3b1ef Mon Sep 17 00:00:00 2001 From: Intel A80486DX2-66 Date: Mon, 26 Aug 2024 22:58:40 +0300 Subject: [PATCH 45/49] b/c...py: do not use a temp. dir if keeping files Do not use a temporary directory if keeping files --- bytebeat_compiler.py | 98 ++++++++++++++++++++++++-------------------- 1 file changed, 53 insertions(+), 45 deletions(-) diff --git a/bytebeat_compiler.py b/bytebeat_compiler.py index 277067c..9045ef3 100644 --- a/bytebeat_compiler.py +++ b/bytebeat_compiler.py @@ -4,7 +4,7 @@ if __name__ == "__main__": print(":: C bytebeat generator: compiler unit") from argparse import ArgumentParser -from os import environ, makedirs, name as os_name, rename +from os import environ, makedirs, name as os_name from os.path import exists, join as path_join from shlex import join as command_line_join, split as command_line_split from shutil import which @@ -91,6 +91,24 @@ def run_command(*command: list[str]) -> None: if subprocess.run(command).returncode != EXIT_SUCCESS: raise SystemExit(EXIT_FAILURE) +def compile_substituted_file(input_file: str, output_file: str) -> None: + print("Compiling") + + run_command( + CC, + *command_line_split(CFLAGS), + input_file, + PATHS["fwrite_le"], + "-o", output_file, + "-I" + PATHS["include_directory"] + ) + run_command(output_file) + +def main_workflow(input_file: str, output_file: str, \ + substitute_contents: Dict[str, str]) -> None: + rewrite_file(input_file, substitute_contents) + compile_substituted_file(input_file, output_file) + preprocessor_bool = lambda value: "1" if value else "0" C_str_repr = lambda s: '"' + s.replace("\\", "\\\\").replace(r'"', r'\"') + '"' @@ -251,52 +269,42 @@ if __name__ == "__main__": "specify it by setting\nan environmental variable " "CC.") - with TemporaryDirectory() as tmpdirname: - temporary_path = lambda path: path_join(tmpdirname, path) + substitute_contents = substitute_vars({ + "bytebeat_contents": bytebeat_contents, + "output_file": C_str_repr(args.output), + "sample_rate": \ + value if (value := args.final_sample_rate) else args.sample_rate, + "original_sample_rate": original_sample_rate, + "final_sample_rate_code": final_sample_rate_code, + "bit_depth": args.bit_depth, + "is_signed": args.signed, + "precalculated_ratio": args.precalculate_ratio, + "faster_sample_ratio_math": args.precalculate_ratio, + "fp_return_type": args.floating_point, + "channels": args.channels, + "length": samples, + "wav_product": gen_length * (args.bit_depth // BITS_PER_BYTE), + "gen_length": gen_length, + "sequential_mode": args.mode == "sequential", + "block_size": args.block_size, + "silent_mode": args.silent, + "verbose_mode": args.verbose and not args.silent, + "fwrite_le": PATHS["fwrite_le_header"], + "ansi_escape_codes_supported": ansi_escape_codes_supported + }, read_file(PATHS["template"]), args.show_substituted_values) - substitute_temp = temporary_path(PATHS["substitute"]) - rewrite_file(substitute_temp, substitute_vars({ - "bytebeat_contents": bytebeat_contents, - "output_file": C_str_repr(args.output), - "sample_rate": \ - value if (value := args.final_sample_rate) else \ - args.sample_rate, - "original_sample_rate": original_sample_rate, - "final_sample_rate_code": final_sample_rate_code, - "bit_depth": args.bit_depth, - "is_signed": args.signed, - "precalculated_ratio": args.precalculate_ratio, - "faster_sample_ratio_math": args.precalculate_ratio, - "fp_return_type": args.floating_point, - "channels": args.channels, - "length": samples, - "wav_product": gen_length * (args.bit_depth // BITS_PER_BYTE), - "gen_length": gen_length, - "sequential_mode": args.mode == "sequential", - "block_size": args.block_size, - "silent_mode": args.silent, - "verbose_mode": args.verbose and not args.silent, - "fwrite_le": PATHS["fwrite_le_header"], - "ansi_escape_codes_supported": ansi_escape_codes_supported - }, read_file(PATHS["template"]), args.show_substituted_values)) + if args.keep_files: + makedirs(PATHS["bin_dir"], exist_ok=True) - # Compile - print("Compiling") + substitute_file = PATHS["substitute_kept"] + output_file = PATHS["output_kept"] - output_file_temp = temporary_path(PATHS["output"]) + main_workflow(substitute_file, output_file, substitute_contents) + else: + with TemporaryDirectory() as tmpdirname: + temporary_path = lambda path: path_join(tmpdirname, path) - run_command( - CC, - *command_line_split(CFLAGS), - substitute_temp, - PATHS["fwrite_le"], - "-o", output_file_temp, - "-I" + PATHS["include_directory"] - ) - run_command(output_file_temp) + substitute_temp = temporary_path(PATHS["substitute"]) + output_temp = temporary_path(PATHS["output"]) - if args.keep_files: - makedirs(PATHS["bin_dir"], exist_ok=True) - - rename(substitute_temp, PATHS["substitute_kept"]) - rename(output_file_temp, PATHS["output_kept"]) + main_workflow(substitute_temp, output_temp, substitute_contents) From 0b0a6a4e0ba02abd1fb3d697466757fbd58db4ee Mon Sep 17 00:00:00 2001 From: Intel A80486DX2-66 Date: Mon, 26 Aug 2024 23:26:59 +0300 Subject: [PATCH 46/49] b/c...py: use `os.getcwd()` instead of `.` --- bytebeat_compiler.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/bytebeat_compiler.py b/bytebeat_compiler.py index 9045ef3..62de40c 100644 --- a/bytebeat_compiler.py +++ b/bytebeat_compiler.py @@ -4,7 +4,7 @@ if __name__ == "__main__": print(":: C bytebeat generator: compiler unit") from argparse import ArgumentParser -from os import environ, makedirs, name as os_name +from os import getcwd, environ, makedirs, name as os_name, rename from os.path import exists, join as path_join from shlex import join as command_line_join, split as command_line_split from shutil import which @@ -30,9 +30,10 @@ PATHS = { "include_directory": "include" } -# Add `.` directory before all paths for compilation +# Add current directory before all paths for compilation +CURRENT_DIRECTORY = getcwd() for key in ["src_dir", "bin_dir", "include_directory"]: - PATHS[key] = path_join(".", PATHS[key]) + PATHS[key] = path_join(CURRENT_DIRECTORY, PATHS[key]) # Resolve paths PATHS["template"] = path_join(PATHS["src_dir"], PATHS["template"]) From c043d0ce944b84e1bce578284f953c5bbdd714d3 Mon Sep 17 00:00:00 2001 From: Intel A80486DX2-66 Date: Mon, 26 Aug 2024 23:28:52 +0300 Subject: [PATCH 47/49] bytebeat_compiler.py: reformat command printing --- bytebeat_compiler.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bytebeat_compiler.py b/bytebeat_compiler.py index 62de40c..0b541e1 100644 --- a/bytebeat_compiler.py +++ b/bytebeat_compiler.py @@ -88,7 +88,7 @@ def substitute_vars(replacements: Dict[str, Union[bool, str]], text: str, return text def run_command(*command: list[str]) -> None: - print(command_line_join(command), flush=True) + print("[>]", command_line_join(command), flush=True) if subprocess.run(command).returncode != EXIT_SUCCESS: raise SystemExit(EXIT_FAILURE) From 6bc53a0169ee7483c488f0248bd37c79480a7d29 Mon Sep 17 00:00:00 2001 From: Intel A80486DX2-66 Date: Mon, 26 Aug 2024 23:29:52 +0300 Subject: [PATCH 48/49] b/c...py: type hint function `rewrite_file` completely --- bytebeat_compiler.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bytebeat_compiler.py b/bytebeat_compiler.py index 0b541e1..af8ded5 100644 --- a/bytebeat_compiler.py +++ b/bytebeat_compiler.py @@ -60,7 +60,7 @@ def fetch(name: str): def read_file(path: str) -> str: return open(path, "r", encoding="utf-8-sig").read() -def rewrite_file(path: str, content: str): +def rewrite_file(path: str, content: str) -> int: return open(path, "w", encoding="utf-8").write(content) def read_from_file_or_stdin(path: str) -> str: From 63c5e5a62882d5f05d820839aceca9cf79a452b6 Mon Sep 17 00:00:00 2001 From: Intel A80486DX2-66 Date: Mon, 26 Aug 2024 23:31:30 +0300 Subject: [PATCH 49/49] b/c...py: rename `rewrite_file` to `overwrite_file` --- bytebeat_compiler.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/bytebeat_compiler.py b/bytebeat_compiler.py index af8ded5..e2107bc 100644 --- a/bytebeat_compiler.py +++ b/bytebeat_compiler.py @@ -60,7 +60,7 @@ def fetch(name: str): def read_file(path: str) -> str: return open(path, "r", encoding="utf-8-sig").read() -def rewrite_file(path: str, content: str) -> int: +def overwrite_file(path: str, content: str) -> int: return open(path, "w", encoding="utf-8").write(content) def read_from_file_or_stdin(path: str) -> str: @@ -107,7 +107,7 @@ def compile_substituted_file(input_file: str, output_file: str) -> None: def main_workflow(input_file: str, output_file: str, \ substitute_contents: Dict[str, str]) -> None: - rewrite_file(input_file, substitute_contents) + overwrite_file(input_file, substitute_contents) compile_substituted_file(input_file, output_file) preprocessor_bool = lambda value: "1" if value else "0"