template.c: add sequential mode and set as default
This commit is contained in:
parent
67ab00c084
commit
d1906f0dc1
@ -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"]
|
||||
|
214
src/template.c
214
src/template.c
@ -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;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user