1
0

template.c: add sequential mode and set as default

This commit is contained in:
Intel A80486DX2-66 2024-01-10 04:07:15 +03:00
parent 67ab00c084
commit d1906f0dc1
Signed by: 80486DX2-66
GPG Key ID: 83631EF27054609B
2 changed files with 154 additions and 70 deletions

View File

@ -124,6 +124,11 @@ if __name__ == "__main__":
"default = +0 samples")
parser.add_argument("-a", "--no-return", default=False, action="store_true",
help="do not insert return statement before the code")
parser.add_argument("-u", "--mode", default="sequential", type=str,
help="mode of writing: `sequential` or `instant` (the latter is not "
"recommended, since the whole result would be stored in RAM)")
parser.add_argument("-n", "--block-size", default=65536, type=int,
help="sequential mode only: block size of each sequence, bytes")
parser.add_argument("-q", "--silent", default=False, action="store_true",
help="do not output anything during generation")
parser.add_argument("-v", "--verbose", default=False, action="store_true",
@ -186,6 +191,9 @@ if __name__ == "__main__":
print("CLI: Count of samples should be greater than zero.")
raise SystemExit
if args.mode != "sequential" and args.mode != "instant":
print("Invalid mode '%s'" % args.mode)
rewrite_file(PATHS["substitute"], substitute_vars({
"bytebeat_contents": bytebeat_contents,
"output_file": C_str_repr(args.output),
@ -199,6 +207,8 @@ if __name__ == "__main__":
"fp_return_type": args.floating_point,
"channels": args.channels,
"length": samples,
"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"]

View File

@ -41,6 +41,9 @@ const char* ANSI_CLEAR = __ANSI_CLEAR_STRING;
#define PRODUCT (LENGTH * CHANNELS)
#define FREQUENCY_OF_STATUS_REPORTING 5000
#define SEQUENTIAL_MODE `sequential_mode`
#define BLOCK_SIZE_BYTES `block_size`
#define FP_RETURN_TYPE `fp_return_type`
#define PRECALCULATED_RATIO `precalculated_ratio`
@ -71,8 +74,12 @@ bytebeat(long double w)
{
#if PRECALCULATED_RATIO
`final_sample_rate_code`
#else
#elif ORIGINAL_SAMPLE_RATE != SAMPLE_RATE
# if SAMPLE_RATE > ORIGINAL_SAMPLE_RATE
w /= ((long double) SAMPLE_RATE) / ((long double) ORIGINAL_SAMPLE_RATE);
# else
w *= ((long double) ORIGINAL_SAMPLE_RATE / ((long double) SAMPLE_RATE));
# endif
#endif
uintmax_t t = (uintmax_t) w;
`bytebeat_contents`;
@ -122,7 +129,7 @@ main(void)
printf("%" PRIuMAX " samples", samples);
printf(
#if VERBOSE_MODE
#if VERBOSE_MODE || SEQUENTIAL_MODE
"\n"
#endif
"\n"
@ -132,6 +139,11 @@ main(void)
#endif
// * write WAVE headers
// 0. log
#if SEQUENTIAL_MODE
printf("Writing WAVE headers...\n");
#endif
// 1. open file
FILE* output_file = fopen(OUTPUT_FILE, "wb");
if (output_file == NULL) {
@ -146,10 +158,10 @@ main(void)
5 * 4 /* 4 uint32_t values */ +
4 * 2 /* 5 uint16_t values */ +
PRODUCT /* sample data */,
fmt_data_length = 16 /*
* length of format data before this value
* in the file format structure
*/,
fmt_data_length = 16 /* <--
* length of format data before this value
* in the file format structure
*/,
sample_rate = SAMPLE_RATE,
byte_rate = (SAMPLE_RATE * BIT_DEPTH * CHANNELS) / 8;
uint16_t fmt_type = 1, // format type is PCM
@ -174,93 +186,155 @@ main(void)
fwrite_le(&buffer_size, 4, 1, output_file); // L : Subchunk2Size : 4
// 4. write sample data
// * allocate heap for sample data
SAMPLE_TYPE* buffer = calloc(PRODUCT, sizeof(SAMPLE_TYPE));
if (buffer == NULL) {
perror("calloc");
return 1;
#if SEQUENTIAL_MODE
const size_t BLOCK_SIZE = BLOCK_SIZE_BYTES / (sizeof(SAMPLE_TYPE) /
sizeof(uint8_t));
if (BLOCK_SIZE < 1) {
printf("The block size %" PRIuMAX " is too small, should be at least "
"%" PRIuMAX " bytes\n", (uintmax_t) BLOCK_SIZE_BYTES,
(uintmax_t) (sizeof(SAMPLE_TYPE) / sizeof(uint8_t)));
exit(EXIT_FAILURE);
}
const size_t MAX = (PRODUCT + (BLOCK_SIZE - 1)) / BLOCK_SIZE;
// * bytebeat generating loop
const uintmax_t product_minus_1 = PRODUCT - 1,
bit_depth_limiter = BIT_DEPTH_LIMITER
#if FP_RETURN_TYPE
+ 1
#endif
#if BIT_DEPTH < 8
,
bit_depth_stretch = ((long double) BIT_DEPTH) / 8.L
#endif
;
for (size_t w = 0; w < PRODUCT; w++) {
// 1. generate audio data
#if FP_RETURN_TYPE
long double bytebeat_res = floor(bytebeat((long double) floor(w)));
#elif IS_SIGNED
intmax_t bytebeat_res = (intmax_t) bytebeat(floor((long double) w));
size_t w = 0;
for (size_t seq = 0; seq < MAX; seq++) {
#else
uintmax_t bytebeat_res = (uintmax_t) bytebeat(floor((long double) w));
do {
#endif
size_t calc_block_size = BLOCK_SIZE;
if ((w + BLOCK_SIZE) >= PRODUCT)
calc_block_size = PRODUCT - w;
// 2. if signed, then wrap up into unsigned
#if IS_SIGNED
bytebeat_res = signed_to_unsigned(bytebeat_res);
#endif
// 3. convert audio data to sample
SAMPLE_TYPE sample_res = (SAMPLE_TYPE)
#if FP_RETURN_TYPE
fmodl(bytebeat_res, bit_depth_limiter);
// * allocate heap for sample data
SAMPLE_TYPE* buffer = calloc(
#if SEQUENTIAL_MODE
calc_block_size,
#else
((uintmax_t) bytebeat_res & bit_depth_limiter);
PRODUCT,
#endif
sizeof(SAMPLE_TYPE));
// 4. if bit depth is less than 8, stretch it
#if BIT_DEPTH < 8
sample_res = (SAMPLE_TYPE)
((long double) sample_res * bit_depth_stretch);
#endif
// 5. save sample into buffer
buffer[w] = sample_res;
// 6. log
#if VERBOSE_MODE
if (w % FREQUENCY_OF_STATUS_REPORTING == 0 ||
w >= product_minus_1 /* or if writing last sample */) {
printf(
"%sremaining samples = %18" PRIuMAX " (%.2Lf%% done)",
ANSI_CLEAR,
product_minus_1 - w,
((long double) w * 100) / (long double) PRODUCT);
fflush(stdout);
if (buffer == NULL) {
perror("calloc");
return 1;
}
// * bytebeat generating loop
const uintmax_t product_minus_1 = PRODUCT - 1,
bit_depth_limiter = BIT_DEPTH_LIMITER
#if FP_RETURN_TYPE
+ 1
#endif
}
#if BIT_DEPTH < 8
,
bit_depth_stretch = ((long double) BIT_DEPTH) / 8.L
#endif
;
#if SEQUENTIAL_MODE
size_t idx = 0;
for (; idx < BLOCK_SIZE && w < PRODUCT; idx++, w++) {
#else
for (size_t w = 0; w < PRODUCT; w++) {
#endif
// 1. generate audio data
#if FP_RETURN_TYPE
long double bytebeat_res = floor(bytebeat((long double) floor(w)));
#elif IS_SIGNED
intmax_t bytebeat_res = (intmax_t) bytebeat(floor((long double) w));
#else
uintmax_t bytebeat_res = (uintmax_t) bytebeat(floor((long double) w));
#endif
// 2. if signed, then wrap up into unsigned
#if IS_SIGNED
bytebeat_res = signed_to_unsigned(bytebeat_res);
#endif
// 3. convert audio data to sample
SAMPLE_TYPE sample_res = (SAMPLE_TYPE)
#if FP_RETURN_TYPE
fmodl(bytebeat_res, bit_depth_limiter);
#else
((uintmax_t) bytebeat_res & bit_depth_limiter);
#endif
// 4. if bit depth is less than 8, stretch it
#if BIT_DEPTH < 8
sample_res = (SAMPLE_TYPE)
((long double) sample_res * bit_depth_stretch);
#endif
// 5. save sample into buffer
#if SEQUENTIAL_MODE
buffer[idx] = sample_res;
#else
buffer[w] = sample_res;
#endif
// 6. log
#if VERBOSE_MODE
if (w % FREQUENCY_OF_STATUS_REPORTING == 0 ||
w >= product_minus_1 /* or if writing last sample */) {
printf(
"%sremaining samples = %18" PRIuMAX " (%.2Lf%% done)",
ANSI_CLEAR,
product_minus_1 - w,
((long double) w * 100) / (long double) PRODUCT);
fflush(stdout);
}
#endif
}
#if !SILENT_MODE
printf("%s", ANSI_CLEAR);
printf("%s", ANSI_CLEAR);
// 5. log
printf("\nWriting out file " OUTPUT_FILE "...\n");
fflush(stdout);
// 5. log
#if SEQUENTIAL_MODE
printf("Writing out file " OUTPUT_FILE " (part %" PRIuMAX "/%"
PRIuMAX ", %.2Lf%%)...\n", (uintmax_t) seq + 1,
(uintmax_t) MAX,
((long double) seq * 100.L) / ((long double) MAX));
#else
printf("\nWriting out file " OUTPUT_FILE "...\n");
#endif
fflush(stdout);
#endif
// * save the sample data into the file
fwrite_le(buffer, sizeof(SAMPLE_TYPE), buffer_size, output_file);
// * save the sample data into the file
fwrite_le(buffer, sizeof(SAMPLE_TYPE),
#if SEQUENTIAL_MODE
calc_block_size,
#else
PRODUCT,
#endif
output_file);
#if SEQUENTIAL_MODE
fflush(output_file);
#endif
#if SEQUENTIAL_MODE
// * free allocated heap
free(buffer);
#endif
}
#if !SEQUENTIAL_MODE
while (0);
#endif
// 6. close file
fclose(output_file);
#if !SEQUENTIAL_MODE
// * free allocated heap
free(buffer);
#endif
// * end of program
#if !SILENT_MODE
printf("Done!\n");
#endif
// * free allocated heap
free(buffer);
return 0;
}