1
0

WIP: add files

This commit is contained in:
Intel A80486DX2-66 2024-05-27 08:07:42 +03:00
parent 24317101c0
commit 98ff576f19
Signed by: 80486DX2-66
GPG Key ID: 83631EF27054609B
5 changed files with 315 additions and 110 deletions

View File

@ -1,11 +1,15 @@
#!/usr/bin/python3 #!/usr/bin/python3
if __name__ == "__main__":
print(":: C bytebeat generator: compiler unit")
from argparse import ArgumentParser from argparse import ArgumentParser
from os import environ, makedirs from os import environ, makedirs
from os.path import exists, join as path_join from os.path import exists, join as path_join
from shlex import split as command_line_split from shlex import split as command_line_split
from sys import stdin, stdout, exit from sys import stdin, stdout, exit
from typing import Dict, Union from typing import Dict, Union
import re
import subprocess import subprocess
# Paths # Paths
@ -89,6 +93,26 @@ OUTPUT_FILE = fetch("OUTPUT_FILE")
if extra := fetch("CFLAGS_EXTRA"): if extra := fetch("CFLAGS_EXTRA"):
CFLAGS += " " + extra CFLAGS += " " + extra
parameter_line_regex = re.compile(r"^\/\/ *RENDER PARAMETERS *: ", re.MULTILINE)
ALLOWED_ARGUMENTS_FROM_FILE = (
"sample_rate",
"final_sample_rate",
"bit_depth",
"signed",
"channels",
"no_return",
)
DEFAULT_ARGS = {
"sample_rate": 8000,
"final_sample_rate": 0,
"bit_depth": 8,
"signed": False,
"channels": 1,
"no_return": False
}
if __name__ == "__main__": if __name__ == "__main__":
parser = ArgumentParser(description=\ parser = ArgumentParser(description=\
"Substitutes supplied C (non-JavaScript!) bytebeat into the template, " "Substitutes supplied C (non-JavaScript!) bytebeat into the template, "
@ -98,37 +122,45 @@ if __name__ == "__main__":
parser.add_argument("file", type=str, parser.add_argument("file", type=str,
help="bytebeat formula file (use `-` to read from stdin)") help="bytebeat formula file (use `-` to read from stdin)")
parser.add_argument("-o", "--output", default="output.wav", type=str, parser.add_argument("-o", "--output", default="output.wav", type=str,
help="specify output file path (default is `output.wav`") help="specify output file path : default is `output.wav`")
parser.add_argument("-r", "--sample-rate", default=8000, type=int, parser.add_argument("-r", "--sample-rate", default=None, type=int,
help="sample rate (Hz)") help="sample rate (Hz)")
parser.add_argument("-p", "--final-sample-rate", default=None, type=int, parser.add_argument("-p", "--final-sample-rate", default=None, type=int,
help="convert the output to a different sample rate (usually one that " help="convert the output to a different sample rate (usually one that "
"is set in the system, to improve sound quality) during generation " "is set in the system, to improve sound quality) during generation "
"(not just reinterpretation)") "(not just reinterpretation)")
parser.add_argument("-b", "--bit-depth", default=8, type=int, parser.add_argument("-b", "--bit-depth", default=None, type=int,
help="bit depth") help="bit depth")
parser.add_argument("-s", "--signed", default=False, action="store_true", parser.add_argument("-s", "--signed", default=None, action="store_true",
help="is signed?") help="is signed?")
parser.add_argument("-u", "--unsigned", default=None, action="store_true",
help="is unsigned? (overrides the 'is signed' parameter)")
parser.add_argument("-R", "--precalculate-ratio", default=False, parser.add_argument("-R", "--precalculate-ratio", default=False,
action="store_true", action="store_true",
help="precalculate sample ratio to speed up rendering (may produce " help="precalculate sample ratio to speed up rendering (may produce "
"inaccurate results") "inaccurate results)")
parser.add_argument("-m", "--faster-sample-ratio-math", default=False, parser.add_argument("-m", "--faster-sample-ratio-math", default=False,
action="store_true", action="store_true",
help="faster sample ratio math (implies argument -R)") help="faster sample ratio math (implies argument -R)")
parser.add_argument("-f", "--floating-point", default=False, parser.add_argument("-f", "--floating-point", default=False,
action="store_true", help="use floating point as the return type") action="store_true", help="use floating point as the return type")
parser.add_argument("-c", "--channels", default=1, type=int, parser.add_argument("-c", "--channels", default=None, type=int,
help="amount of channels") help="amount of channels")
parser.add_argument("-t", "--seconds", default=None, type=int, parser.add_argument("-t", "--seconds", default=None, type=int,
help="length in seconds (samples = sample rate * seconds) : " help="length in seconds (samples = sample rate * seconds) : "
"default = 30 seconds") "default = 30 seconds")
parser.add_argument("-l", "--samples", default=None, type=int, parser.add_argument("-l", "--samples", default=None, type=int,
help="length in samples (adds to `-t`; supports negative numbers) : " help="length in samples (adds to `-t`; supports negative numbers) : "
"default = +0 samples") "default = seconds + 0 samples")
parser.add_argument("-a", "--no-return", default=False, action="store_true", parser.add_argument("-S", "--skip-first", default=None, type=str,
help="skip first `A` seconds and `B` samples: in format `As`, `B` or "
"`AsB` : default = 0")
parser.add_argument("-k", "--repeat", default=0, type=int,
help="how many times to repeat the bytebeat : "
"default = 0")
parser.add_argument("-a", "--no-return", default=None, action="store_true",
help="do not insert return statement before the code") help="do not insert return statement before the code")
parser.add_argument("-u", "--mode", default="sequential", type=str, parser.add_argument("-U", "--mode", default="sequential", type=str,
help="mode of writing: `sequential` or `instant` (the latter is not " help="mode of writing: `sequential` or `instant` (the latter is not "
"recommended, since the whole result would be stored in RAM)") "recommended, since the whole result would be stored in RAM)")
parser.add_argument("-n", "--block-size", default=65536, type=int, parser.add_argument("-n", "--block-size", default=65536, type=int,
@ -148,7 +180,42 @@ if __name__ == "__main__":
if not bytebeat_contents: if not bytebeat_contents:
print("No valid contents") print("No valid contents")
raise SystemExit exit(1)
# - Parse arguments from file
used_parameter_line = False
for line in bytebeat_contents.splitlines():
if (match := re.search(parameter_line_regex, line)) and \
not used_parameter_line:
used_parameter_line = True
parsed_parameters = line[match.start(0):].split(",")
for parameter in parsed_parameters:
kv = [x.strip() for x in parameter.split("=")]
key = None
value = None
if len(kv) == 1:
key, value = kv[0], True
elif len(kv) == 2:
key, value = kv[0], int(kv[1])
else:
break
# Apply the argument only if it was not used by user yet and is
# allowed to be set
if (key not in args or getattr(args, key) is None) and \
key in ALLOWED_ARGUMENTS_FROM_FILE:
setattr(args, key, value)
# - Set default values
for key, value in DEFAULT_ARGS.items():
if getattr(args, key) is None:
setattr(args, key, value)
if args.unsigned is True:
args.signed = False
# - Compilation # - Compilation
makedirs(PATHS["build_dir"], exist_ok=True) makedirs(PATHS["build_dir"], exist_ok=True)
@ -162,7 +229,7 @@ if __name__ == "__main__":
final_sample_rate_code = "" final_sample_rate_code = ""
if args.faster_sample_ratio_math: if args.faster_sample_ratio_math:
args.precalculate_ratio = True args.precalculate_ratio = True
if args.precalculate_ratio and not args.final_sample_rate is None: if args.precalculate_ratio and args.final_sample_rate != 0:
if args.faster_sample_ratio_math: if args.faster_sample_ratio_math:
sample_rate_ratio = args.sample_rate / args.final_sample_rate sample_rate_ratio = args.sample_rate / args.final_sample_rate
final_sample_rate_code = f"time *= {sample_rate_ratio}L;" final_sample_rate_code = f"time *= {sample_rate_ratio}L;"
@ -172,7 +239,8 @@ if __name__ == "__main__":
args.sample_rate = args.final_sample_rate args.sample_rate = args.final_sample_rate
final_sample_rate = \ final_sample_rate = \
value if (value := args.final_sample_rate) else original_sample_rate value if (value := args.final_sample_rate) != 0 \
else original_sample_rate
samples = 0 samples = 0
while True: while True:
no_seconds = args.seconds is None or args.seconds == 0 no_seconds = args.seconds is None or args.seconds == 0
@ -182,7 +250,7 @@ if __name__ == "__main__":
if seconds_specified and args.seconds < 0: if seconds_specified and args.seconds < 0:
print("CLI: Count of seconds can't be less than zero.") print("CLI: Count of seconds can't be less than zero.")
raise SystemExit exit(1)
if no_seconds and samples_specified: if no_seconds and samples_specified:
samples = args.samples samples = args.samples
@ -195,27 +263,53 @@ if __name__ == "__main__":
continue continue
else: else:
print("CLI: Incorrect seconds/samples length format.") print("CLI: Incorrect seconds/samples length format.")
raise SystemExit exit(1)
break break
if samples <= 0: if samples <= 0:
print("CLI: Count of samples should be greater than zero.") print("CLI: Count of samples should be greater than zero.")
raise SystemExit exit(1)
if args.mode != "sequential" and args.mode != "instant": if args.mode != "sequential" and args.mode != "instant":
print("Invalid mode '%s'" % args.mode) print("Invalid mode '%s'" % args.mode)
raise SystemExit exit(1)
gen_length = args.channels * samples
ansi_escape_codes_supported = args.color == "auto" and stdout_atty or \ ansi_escape_codes_supported = args.color == "auto" and stdout_atty or \
args.color == "always" args.color == "always"
actual_sample_rate = \
value if (value := args.final_sample_rate) else args.sample_rate
# - Parse the '--skip-first' argument
if not args.skip_first is None:
encountered_s = False
for character in args.skip_first:
if character.isdigit() or character == "s" and not encountered_s:
if character == "s":
encountered_s = True
else:
print(f"Invalid --skip-first format: `{args.skip_first}`")
exit(1)
skip_first = \
[int(x) if x.isdigit() else 0 for x in args.skip_first.split("s")]
skip_first_samples = 0
if len(skip_first) == 1:
skip_first += [0]
skip_first_samples = skip_first[0] * actual_sample_rate + skip_first[1]
else:
skip_first_samples = 0
length_formula = lambda channels, samples, n: channels * (samples + n)
gen_length = length_formula(args.channels, samples, 0)
loop_end = length_formula(args.channels, samples, skip_first_samples)
rewrite_file(PATHS["substitute"], substitute_vars({ rewrite_file(PATHS["substitute"], substitute_vars({
"bytebeat_contents": bytebeat_contents, "bytebeat_contents": bytebeat_contents,
"output_file": C_str_repr(args.output), "output_file": C_str_repr(args.output),
"sample_rate": \ "sample_rate": actual_sample_rate,
value if (value := args.final_sample_rate) else args.sample_rate,
"original_sample_rate": original_sample_rate, "original_sample_rate": original_sample_rate,
"final_sample_rate_code": final_sample_rate_code, "final_sample_rate_code": final_sample_rate_code,
"bit_depth": args.bit_depth, "bit_depth": args.bit_depth,
@ -224,7 +318,11 @@ if __name__ == "__main__":
"faster_sample_ratio_math": args.precalculate_ratio, "faster_sample_ratio_math": args.precalculate_ratio,
"fp_return_type": args.floating_point, "fp_return_type": args.floating_point,
"channels": args.channels, "channels": args.channels,
"length": samples, "running_length": samples,
"loop_end": loop_end,
"loop_end_minus_1": loop_end - 1,
"initial_time": skip_first_samples,
"repeat_times": args.repeat,
"wav_product": gen_length * (args.bit_depth // 8), "wav_product": gen_length * (args.bit_depth // 8),
"gen_length": gen_length, "gen_length": gen_length,
"sequential_mode": args.mode == "sequential", "sequential_mode": args.mode == "sequential",

5
samples/beeper.c Normal file
View File

@ -0,0 +1,5 @@
// RENDER PARAMETERS: sample_rate = 44100, no_return
bb_counter_t u = t << 1;
SAMPLE_TYPE x = u & u >> 8;
return (x | 127) + 63;

3
samples/cykstep.c Normal file
View File

@ -0,0 +1,3 @@
// RENDER PARAMETERS: sample_rate = 44100, final_sample_rate = 48000, signed
t/=3,(t*(t+(444+(t/444)))&((t>>9)>4095 ? 4095 : (t>>(9+(3&t>>13)))))>>(3&t>>(5+(3&t>>13)))

5
samples/melody.c Normal file
View File

@ -0,0 +1,5 @@
// RENDER PARAMETERS: sample_rate = 44100, no_return
const long double array[] = {1, 1.25, 1.5, 2};
long double v = array[3 & (t >> 13)];
return (long double) t * v / 3.1415926535;

View File

@ -9,6 +9,10 @@
#include "`fwrite_le`" #include "`fwrite_le`"
// typedefs
typedef uintmax_t bb_counter_t;
typedef long double bb_fp_return_t;
// constants // constants
#define ANSI_ESCAPE_CODES_SUPPORTED `ansi_escape_codes_supported` #define ANSI_ESCAPE_CODES_SUPPORTED `ansi_escape_codes_supported`
@ -29,20 +33,41 @@
#define BIT_DEPTH `bit_depth` #define BIT_DEPTH `bit_depth`
#define IS_SIGNED `is_signed` #define IS_SIGNED `is_signed`
#define CHANNELS `channels` #define CHANNELS `channels`
#define LENGTH `length` #define RUNNING_LENGTH `running_length`
#if BIT_DEPTH <= 8 #if BIT_DEPTH <= 8
# define ACTUAL_BIT_DEPTH 8
# define SAMPLE_TYPE uint8_t # define SAMPLE_TYPE uint8_t
#elif BIT_DEPTH >= 16 #elif BIT_DEPTH <= 16
# define ACTUAL_BIT_DEPTH 16
# if IS_SIGNED # if IS_SIGNED
# define SAMPLE_TYPE int16_t # define SAMPLE_TYPE int16_t
# else # else
# define SAMPLE_TYPE uint16_t # define SAMPLE_TYPE uint16_t
# endif # endif
#elif BIT_DEPTH <= 32
# define ACTUAL_BIT_DEPTH 32
# if IS_SIGNED
# define SAMPLE_TYPE int32_t
# else
# define SAMPLE_TYPE uint32_t
# endif
#else
# error "Unsupported bit depth"
# define _ERROR
#endif #endif
#define PRODUCT `wav_product` #ifndef _ERROR
#define GEN_LENGTH `gen_length`
#define PRODUCT `wav_product`ULL
#define GEN_LENGTH `gen_length`ULL
#define INITIAL_TIME `initial_time`
#define LOOP_END `loop_end`ULL
#define LOOP_END_MINUS_1 `loop_end_minus_1`ULL
#define REPEAT_TIMES `repeat_times`ULL
#define FREQUENCY_OF_STATUS_REPORTING 5000 #define FREQUENCY_OF_STATUS_REPORTING 5000
#define SEQUENTIAL_MODE `sequential_mode` #define SEQUENTIAL_MODE `sequential_mode`
@ -53,8 +78,8 @@
#define FP_RETURN_TYPE `fp_return_type` #define FP_RETURN_TYPE `fp_return_type`
#define PRECALCULATED_RATIO `precalculated_ratio` #define PRECALCULATED_RATIO `precalculated_ratio`
#define BIT_DEPTH_LIMITER ((1 << BIT_DEPTH) - 1) #define BIT_DEPTH_LIMITER ((1ULL << ACTUAL_BIT_DEPTH) - 1ULL)
#define PCM_COEFFICIENT ((1 << (BIT_DEPTH - 1)) - 1) #define PCM_COEFFICIENT ((1ULL << (ACTUAL_BIT_DEPTH - 1ULL)) - 1ULL)
#define unsigned_to_signed(x) (x - PCM_COEFFICIENT) #define unsigned_to_signed(x) (x - PCM_COEFFICIENT)
#define signed_to_unsigned(x) (x + PCM_COEFFICIENT) #define signed_to_unsigned(x) (x + PCM_COEFFICIENT)
@ -78,19 +103,19 @@
// function prototypes // function prototypes
#if FP_RETURN_TYPE #if FP_RETURN_TYPE
long double bb_fp_return_t
#else #else
SAMPLE_TYPE SAMPLE_TYPE
#endif #endif
bytebeat(long double time); bytebeat(bb_counter_t time);
// function implementations // function implementations
#if FP_RETURN_TYPE #if FP_RETURN_TYPE
long double bb_fp_return_t
#else #else
SAMPLE_TYPE SAMPLE_TYPE
#endif #endif
bytebeat(long double time) bytebeat(bb_counter_t time)
{ {
#if PRECALCULATED_RATIO #if PRECALCULATED_RATIO
`final_sample_rate_code` `final_sample_rate_code`
@ -105,39 +130,10 @@ bytebeat(long double time)
`bytebeat_contents`; `bytebeat_contents`;
} }
int void
main(void) print_time(uintmax_t length) {
{ const uintmax_t seconds = length / SAMPLE_RATE,
// * log -> welcome samples = length % SAMPLE_RATE;
#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;
printf(
"\n"
"Sample rate: " INT2STR(SAMPLE_RATE) " Hz\n"
"Channels: " INT2STR(CHANNELS)
#if CHANNELS <= 2
" ("
# if CHANNELS == 2
"stereo"
# else
"mono"
# endif
")"
#endif
"\n"
"Bit depth: "
#if !IS_SIGNED
"un"
#endif
"signed " INT2STR(BIT_DEPTH) "-bit\n"
"Duration: ");
if (seconds > 0) if (seconds > 0)
if (seconds >= 3600) if (seconds >= 3600)
@ -156,6 +152,54 @@ main(void)
if (samples > 0) if (samples > 0)
printf("%" PRIuMAX " samples", samples); printf("%" PRIuMAX " samples", samples);
}
int
main(void)
{
// * log -> welcome
#if !SILENT_MODE
puts(":: C bytebeat generator: runtime unit");
fflush(stdout);
#endif
#if !SILENT_MODE
printf(
"\n"
"Sample rate: " INT2STR(SAMPLE_RATE) " Hz\n"
"Channels: " INT2STR(CHANNELS)
#if CHANNELS <= 2
" ("
# if CHANNELS == 2
"stereo"
# else
"mono"
# endif
")"
#endif
"\n"
"Bit depth: "
#if !IS_SIGNED
"un"
#endif
"signed " INT2STR(BIT_DEPTH) "-bit"
#if BIT_DEPTH != ACTUAL_BIT_DEPTH
" -> " INT2STR(ACTUAL_BIT_DEPTH) "-bit"
#endif
"\n"
"Duration: ");
print_time(RUNNING_LENGTH);
#if REPEAT_TIMES > 0
printf(", %llu times -> ", REPEAT_TIMES + 1);
print_time(RUNNING_LENGTH * (REPEAT_TIMES + 1));
#endif
#if INITIAL_TIME != 0
printf("\nStart time: ");
print_time(INITIAL_TIME);
#endif
puts( puts(
#if VERBOSE_MODE || SEQUENTIAL_MODE #if VERBOSE_MODE || SEQUENTIAL_MODE
@ -169,39 +213,47 @@ main(void)
// * write WAVE headers // * write WAVE headers
// 0. log // 0. log
#if SEQUENTIAL_MODE #if VERBOSE_MODE
puts("Writing WAVE headers..."); puts("Writing WAVE headers...");
#endif #endif
// 1. open file // 1. open file
FILE* output_file = fopen(OUTPUT_FILE, "wb"); FILE* output_file = fopen(OUTPUT_FILE,
"wb"
#if REPEAT_TIMES > 0
"+"
#endif
);
if (output_file == NULL) { if (output_file == NULL) {
fflush(stdout); fflush(stdout);
perror("fopen"); perror("fopen");
return 1; return EXIT_FAILURE;
} }
// 2. prepare variables // 2. prepare variables
uint32_t buffer_size = PRODUCT, const uint32_t header_size =
file_length =
4 * 4 /* 4 strings of 4 characters */ + 4 * 4 /* 4 strings of 4 characters */ +
5 * 4 /* 4 uint32_t values */ + 5 * 4 /* 5 uint32_t values */ +
4 * 2 /* 5 uint16_t values */ + 4 * 2 /* 4 uint16_t values */;
PRODUCT /* sample data */
uint32_t buffer_size = PRODUCT * (REPEAT_TIMES + 1),
file_length =
header_size +
buffer_size /* sample data */
/* subtract Subchunk2 headers: */ /* subtract Subchunk2 headers: */
- 4 /* a 4-character string */ - 4 /* a string of 4 characters */
- 4 /* a uint32_t value */, - 4 /* a uint32_t value */,
fmt_data_length = 16 /* <-- fmt_data_length = 16 /* <--
* length of format data before this value * length of format data before this value
* in the file format structure * in the file format structure
*/, */,
sample_rate = SAMPLE_RATE, sample_rate = SAMPLE_RATE,
byte_rate = (SAMPLE_RATE * BIT_DEPTH * CHANNELS) / 8; byte_rate = (SAMPLE_RATE * ACTUAL_BIT_DEPTH * CHANNELS) / 8;
uint16_t fmt_type = 1, // format type is PCM uint16_t fmt_type = 1, // format type is PCM
channels = CHANNELS, channels = CHANNELS,
block_align = (BIT_DEPTH * CHANNELS) / 8, block_align = (ACTUAL_BIT_DEPTH * CHANNELS) / 8,
bit_depth = BIT_DEPTH > 8 ? BIT_DEPTH : 8; bit_depth = ACTUAL_BIT_DEPTH;
// 3. write headers // 3. write headers
// <L = Little-endian or B = Big-endian> : <name> : <bytes of field> // <L = Little-endian or B = Big-endian> : <name> : <bytes of field>
@ -237,22 +289,23 @@ main(void)
size_t calc_block_size = BLOCK_SIZE; size_t calc_block_size = BLOCK_SIZE;
ALLOCATE_MEMORY(calc_block_size) ALLOCATE_MEMORY(calc_block_size)
#else #else
ALLOCATE_MEMORY(PRODUCT) ALLOCATE_MEMORY(GEN_LENGTH)
#endif #endif
#if SEQUENTIAL_MODE const uintmax_t bit_depth_limiter = BIT_DEPTH_LIMITER
const uintmax_t gen_length_minus_1 = GEN_LENGTH - 1,
bit_depth_limiter = BIT_DEPTH_LIMITER
#if FP_RETURN_TYPE #if FP_RETURN_TYPE
+ 1 + 1
#endif
#if BIT_DEPTH < 8
,
bit_depth_stretch = ((long double) BIT_DEPTH) / 8.L
#endif #endif
; ;
size_t time = 0; #if BIT_DEPTH != ACTUAL_BIT_DEPTH
const long double bit_depth_stretch =
((long double) BIT_DEPTH) / ACTUAL_BIT_DEPTH;
#endif
#if SEQUENTIAL_MODE
size_t time = INITIAL_TIME;
for (size_t seq = 0; seq < MAX; seq++) { for (size_t seq = 0; seq < MAX; seq++) {
if ((time + BLOCK_SIZE) >= GEN_LENGTH) if ((time + BLOCK_SIZE) >= GEN_LENGTH)
calc_block_size = GEN_LENGTH - time; calc_block_size = GEN_LENGTH - time;
@ -260,34 +313,34 @@ main(void)
// * bytebeat generating loop // * bytebeat generating loop
#if SEQUENTIAL_MODE #if SEQUENTIAL_MODE
for (size_t idx = 0; idx < BLOCK_SIZE && time < GEN_LENGTH; idx++, for (size_t idx = 0; idx < BLOCK_SIZE && time < LOOP_END; idx++,
time++) { time++) {
#else #else
for (size_t time = 0; time < GEN_LENGTH; time++) { for (size_t time = INITIAL_TIME; time < LOOP_END; time++) {
#endif #endif
// 1. generate audio data // 1. generate audio data
#if FP_RETURN_TYPE #if FP_RETURN_TYPE
long double bytebeat_res = bb_fp_return_t bytebeat_res =
floor(bytebeat(floor((long double) time))); floor(bytebeat(floor((bb_counter_t) time)));
#elif IS_SIGNED #elif IS_SIGNED
intmax_t bytebeat_res = intmax_t bytebeat_res =
(intmax_t) bytebeat(floor((long double) time)); (intmax_t) bytebeat(floor((bb_counter_t) time));
#else #else
uintmax_t bytebeat_res = uintmax_t bytebeat_res =
(uintmax_t) bytebeat(floor((long double) time)); (uintmax_t) bytebeat(floor((bb_counter_t) time));
#endif #endif
// 2. if signed, then wrap up to unsigned // 2. if signed and bit depth <= 8, then wrap up to unsigned
#if IS_SIGNED #if IS_SIGNED && (BIT_DEPTH <= 8)
bytebeat_res = signed_to_unsigned(bytebeat_res); bytebeat_res = signed_to_unsigned(bytebeat_res);
#endif #endif
// 3. convert audio data to sample // 3. convert audio data to sample
SAMPLE_TYPE sample_res = (SAMPLE_TYPE) SAMPLE_TYPE sample_res = (SAMPLE_TYPE)
#if FP_RETURN_TYPE #if FP_RETURN_TYPE
fmodl(bytebeat_res, bit_depth_limiter); fmod(bytebeat_res, BIT_DEPTH_LIMITER);
#else #else
((uintmax_t) bytebeat_res & bit_depth_limiter); ((uintmax_t) bytebeat_res & BIT_DEPTH_LIMITER);
#endif #endif
// 4. if bit depth is less than 8, stretch it // 4. if bit depth is less than 8, stretch it
@ -297,25 +350,27 @@ main(void)
#endif #endif
// 5. save sample into buffer // 5. save sample into buffer
buffer[
#if SEQUENTIAL_MODE #if SEQUENTIAL_MODE
buffer[idx] = sample_res; idx
#else #else
buffer[time] = sample_res; time
#endif #endif
] = sample_res;
// 6. log // 6. log
#if VERBOSE_MODE #if VERBOSE_MODE
if (time % FREQUENCY_OF_STATUS_REPORTING == 0 || if (time % FREQUENCY_OF_STATUS_REPORTING == 0 ||
time >= gen_length_minus_1 /* or if writing last sample */) { time >= LOOP_END_MINUS_1 /* or if writing last sample */) {
printf( printf(
"%sremaining samples = %18" PRIuMAX " (%3.2Lf%% done)" "%sremaining samples = %18" PRIuMAX " (%6.2Lf%% done)"
#if SEQUENTIAL_MODE #if SEQUENTIAL_MODE
" (part %" PRIuMAX "/%" PRIuMAX ")" " (part %" PRIuMAX "/%" PRIuMAX ")"
#endif #endif
, ,
_ANSI_CLEAR_STRING, _ANSI_CLEAR_STRING,
gen_length_minus_1 - time, LOOP_END_MINUS_1 - time,
((long double) time * 100) / (long double) GEN_LENGTH ((long double) time * 100) / (long double) LOOP_END_MINUS_1
#if SEQUENTIAL_MODE #if SEQUENTIAL_MODE
, (uintmax_t) seq + 1, (uintmax_t) MAX , (uintmax_t) seq + 1, (uintmax_t) MAX
#endif #endif
@ -330,13 +385,13 @@ main(void)
// 5. log // 5. log
#if !(SEQUENTIAL_MODE && VERBOSE_MODE) #if !(SEQUENTIAL_MODE && VERBOSE_MODE)
#if SEQUENTIAL_MODE # if SEQUENTIAL_MODE
if (seq == 0) if (seq == 0)
#endif # endif
puts( puts(
#if !SEQUENTIAL_MODE # if !SEQUENTIAL_MODE
"\n" "\n"
#endif # endif
"Writing out file " OUTPUT_FILE "..."); "Writing out file " OUTPUT_FILE "...");
#endif #endif
fflush(stdout); fflush(stdout);
@ -347,7 +402,7 @@ main(void)
#if SEQUENTIAL_MODE #if SEQUENTIAL_MODE
calc_block_size, calc_block_size,
#else #else
PRODUCT, GEN_LENGTH,
#endif #endif
output_file); output_file);
#if SEQUENTIAL_MODE #if SEQUENTIAL_MODE
@ -358,6 +413,43 @@ main(void)
} }
#endif #endif
#if REPEAT_TIMES > 0
// * repeat as much as needed
puts(
# if SEQUENTIAL_MODE
"\n"
# endif
"Repeating...");
for (size_t counter = 0; counter < REPEAT_TIMES; counter++) {
# if SEQUENTIAL_MODE
off_t position_read = header_size;
calc_block_size = BLOCK_SIZE;
for (size_t seq = 0, time = 0; seq < MAX; seq++, time += BLOCK_SIZE) {
bool end = false;
if ((time + BLOCK_SIZE) >= GEN_LENGTH) {
calc_block_size = GEN_LENGTH - time;
end = true;
}
fseeko(output_file, position_read, SEEK_SET);
fread(buffer, sizeof(SAMPLE_TYPE), calc_block_size, output_file);
fseeko(output_file, 0, SEEK_END);
fwrite(buffer, sizeof(SAMPLE_TYPE), calc_block_size, output_file);
if (end)
break;
position_read += calc_block_size;
}
# else
fwrite_le(buffer, sizeof(SAMPLE_TYPE), GEN_LENGTH, output_file);
# endif
}
#endif
// * free allocated heap // * free allocated heap
free(buffer); free(buffer);
@ -367,11 +459,13 @@ main(void)
// * end of program // * end of program
#if !SILENT_MODE #if !SILENT_MODE
puts( puts(
#if SEQUENTIAL_MODE && VERBOSE_MODE # if SEQUENTIAL_MODE && VERBOSE_MODE && REPEAT_TIMES == 0
"\n" "\n"
#endif # endif
"Done!"); "Done!");
#endif #endif
return EXIT_SUCCESS; return EXIT_SUCCESS;
} }
#endif /* _ERROR */