initial commit
This commit is contained in:
commit
5f4f147165
11
LICENSE
Normal file
11
LICENSE
Normal file
@ -0,0 +1,11 @@
|
||||
This work is licensed under the following terms:
|
||||
|
||||
1. Public Domain or Creative Commons Zero 1.0 Universal: This work is dedicated
|
||||
to the public domain. To the extent possible under law, the author(s) have
|
||||
waived all copyright and related or neighboring rights to this work.
|
||||
Alternatively, you may use, modify, and distribute this work under the terms
|
||||
of the Creative Commons Zero 1.0 Universal license. See the file LICENSE.CC0
|
||||
for more information
|
||||
|
||||
2. Unlicense: You may use, modify, and distribute this work under the terms of
|
||||
the Unlicense license. See file LICENSE.UNLICENSE for more information.
|
121
LICENSE.CC0
Normal file
121
LICENSE.CC0
Normal file
@ -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.
|
22
LICENSE.UNLICENSE
Normal file
22
LICENSE.UNLICENSE
Normal file
@ -0,0 +1,22 @@
|
||||
This is free and unencumbered software released into the public domain.
|
||||
|
||||
Anyone is free to copy, modify, publish, use, compile, sell, or distribute
|
||||
this software, either in source code form or as a compiled binary, for any
|
||||
purpose, commercial or non-commercial, and by any means.
|
||||
|
||||
In jurisdictions that recognize copyright laws, the author or authors of
|
||||
this software dedicate any and all copyright interest in the software to
|
||||
the public domain. We make this dedication for the benefit of the public at
|
||||
large and to the detriment of our heirs and
|
||||
successors. We intend this dedication to be an overt act of relinquishment in
|
||||
perpetuity of all present and future rights to this software under copyright
|
||||
law.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
For more information, please refer to <http://unlicense.org/>
|
13
README.md
Normal file
13
README.md
Normal file
@ -0,0 +1,13 @@
|
||||
# text-wave-file
|
||||
|
||||
A Git test.
|
||||
|
||||
```diff
|
||||
diff --git a/text-wave-file b/text-wave-file
|
||||
new file mode 100644
|
||||
index 0000000..d916dd1
|
||||
--- /dev/null
|
||||
+++ b/text-wave-file
|
||||
@@ -0,0 +1 @@
|
||||
+RIFFaaaaWAVEfmt aaaaaaaaaaaaaaaaaaaadataaaaa
|
||||
```
|
6
generate.sh
Executable file
6
generate.sh
Executable file
@ -0,0 +1,6 @@
|
||||
#!/bin/sh
|
||||
|
||||
cd ./tools || return 1
|
||||
gmake || return "$?"
|
||||
cd ..
|
||||
./tools/mock_file_generator.exe
|
1
text-wave-file
Normal file
1
text-wave-file
Normal file
@ -0,0 +1 @@
|
||||
RIFFaaaaWAVEfmt aaaaaaaaaaaaaaaaaaaadataaaaa
|
1
tools/.gitignore
vendored
Normal file
1
tools/.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
||||
/mock_file_generator.exe
|
34
tools/Makefile
Normal file
34
tools/Makefile
Normal file
@ -0,0 +1,34 @@
|
||||
# SPDX-License-Identifier: CC0-1.0 OR Unlicense
|
||||
|
||||
CC ?= gcc
|
||||
DEBUG ?= 0
|
||||
PORTABLE_OPTIMIZATION ?= 0
|
||||
|
||||
CFLAGS = -Wall -Werror -Wextra -Wpedantic -std=c99 -D_POSIX_C_SOURCE=199309L
|
||||
|
||||
ifeq ($(DEBUG), 1)
|
||||
CFLAGS += -g -DDEBUG
|
||||
else
|
||||
ifeq ($(PORTABLE_OPTIMIZATION), 1)
|
||||
CFLAGS += -O2
|
||||
else
|
||||
CFLAGS += -march=native -Ofast
|
||||
endif
|
||||
endif
|
||||
|
||||
PROJECT_NAME = mock_file_generator
|
||||
SRC = ./$(PROJECT_NAME).c
|
||||
BIN = ./$(PROJECT_NAME).exe
|
||||
|
||||
all: $(BIN)
|
||||
|
||||
$(BIN): $(SRC)
|
||||
$(CC) $(CFLAGS) $(SRC) -o $(BIN)
|
||||
ifeq ($(DEBUG), 0)
|
||||
strip $(BIN)
|
||||
endif
|
||||
|
||||
clean:
|
||||
rm $(BIN)
|
||||
|
||||
.PHONY: all clean
|
264
tools/mock_file_generator.c
Normal file
264
tools/mock_file_generator.c
Normal file
@ -0,0 +1,264 @@
|
||||
// SPDX-License-Identifier: CC0-1.0 OR Unlicense
|
||||
|
||||
#include <errno.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
/* structures */
|
||||
struct pcm_wav_parameters_t {
|
||||
uint16_t bit_depth, channels;
|
||||
uint32_t samples;
|
||||
};
|
||||
|
||||
/* typedefs */
|
||||
typedef unsigned char byte;
|
||||
typedef struct pcm_wav_parameters_t pcm_wav_parameters_t;
|
||||
typedef uint8_t chip_sample_t;
|
||||
|
||||
/* macros: definitions */
|
||||
#define BITS_PER_BYTE 8
|
||||
#define PCM_WAV_WRITE_SUCCESS true
|
||||
#define PCM_WAV_WRITE_FAILURE false
|
||||
#define FWRITE_LE_NO_MODIFICATION 0
|
||||
#define DETECTED_LITTLE_ENDIAN 0
|
||||
#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 SAMPLES 1
|
||||
#define OUTPUT_CHANNELS 1
|
||||
#define BIT_DEPTH 8
|
||||
#define SAMPLE_SIZE sizeof(chip_sample_t)
|
||||
|
||||
/* macros: lambdas */
|
||||
#define ifeq_b32_ret(lhs, rhs, value) \
|
||||
if (!memcmp(lhs, rhs, 4)) \
|
||||
return value
|
||||
|
||||
/* global variables */
|
||||
FILE* file = NULL;
|
||||
|
||||
/* function definitions */
|
||||
int detect_endianness(void);
|
||||
void fwrite_le_noerr(
|
||||
#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,
|
||||
#else
|
||||
uint8_t* bytes,
|
||||
#endif
|
||||
size_t count, size_t step);
|
||||
static void fwrite_noerr(const void* ptr, size_t size, size_t count,
|
||||
FILE* stream);
|
||||
void pcm_wav_write(FILE* file, const pcm_wav_parameters_t param,
|
||||
#if FWRITE_LE_NO_MODIFICATION
|
||||
const
|
||||
#endif
|
||||
void* data, size_t size, size_t count);
|
||||
void fclose_file(void);
|
||||
|
||||
/* function implementations */
|
||||
int detect_endianness(void) {
|
||||
volatile uint32_t native_order_value = ORDER_NATIVE_U32;
|
||||
uint8_t* as_bytes = (uint8_t*)&native_order_value;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
void reorder_le_be(
|
||||
#if FWRITE_LE_NO_MODIFICATION
|
||||
uint8_t* dest, uint8_t* src,
|
||||
#else
|
||||
uint8_t* bytes,
|
||||
#endif
|
||||
size_t count, size_t step) {
|
||||
|
||||
if (step == 1) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < count; i += step) {
|
||||
const size_t div_size = step / 2;
|
||||
for (size_t j = 0; j < div_size; j++) {
|
||||
const size_t old_pos = i + j, new_pos = i + step - j - 1;
|
||||
#if FWRITE_LE_NO_MODIFICATION
|
||||
dest[old_pos] = src[new_pos];
|
||||
dest[new_pos] = src[old_pos];
|
||||
#else
|
||||
uint8_t temp = bytes[old_pos];
|
||||
bytes[old_pos] = bytes[new_pos];
|
||||
bytes[new_pos] = temp;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void fwrite_le_noerr(
|
||||
#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)
|
||||
*/
|
||||
if (ptr == NULL) {
|
||||
errno = EINVAL;
|
||||
perror("fwrite_le");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
int endianness = detect_endianness();
|
||||
if (size == 1 || endianness == DETECTED_LITTLE_ENDIAN) {
|
||||
size_t res = fwrite(ptr, size, count, stream);
|
||||
if (res != count) {
|
||||
perror("fwrite");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
return;
|
||||
} else if (endianness == UNSUPPORTED_ENDIANNESS) {
|
||||
fprintf(stderr, "Unsupported endianness\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
// case: big-endian
|
||||
size_t bytes_count = size * count;
|
||||
#if FWRITE_LE_NO_MODIFICATION
|
||||
uint8_t* bytes = malloc(bytes_count * sizeof(uint8_t));
|
||||
if (bytes == NULL) {
|
||||
perror("malloc");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
memcpy(bytes, ptr, bytes_count);
|
||||
#endif
|
||||
|
||||
reorder_le_be(
|
||||
#if FWRITE_LE_NO_MODIFICATION
|
||||
bytes,
|
||||
#endif
|
||||
(uint8_t*)ptr, bytes_count, size);
|
||||
|
||||
size_t res = fwrite(
|
||||
#if FWRITE_LE_NO_MODIFICATION
|
||||
bytes,
|
||||
#else
|
||||
ptr,
|
||||
#endif
|
||||
size, count, stream);
|
||||
#if FWRITE_LE_NO_MODIFICATION
|
||||
free(bytes);
|
||||
#endif
|
||||
if (res != count) {
|
||||
perror("fwrite");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
|
||||
static void fwrite_noerr(const void* ptr, size_t size, size_t count,
|
||||
FILE* stream) {
|
||||
if (fwrite(ptr, size, count, stream) != count) {
|
||||
perror("fwrite");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
|
||||
void pcm_wav_write(FILE* file, const pcm_wav_parameters_t param,
|
||||
#if FWRITE_LE_NO_MODIFICATION
|
||||
const
|
||||
#endif
|
||||
void* data, size_t size, size_t count) {
|
||||
if (file == NULL || data == NULL) {
|
||||
errno = EINVAL;
|
||||
perror("pcm_wav_write");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
// * write WAVE headers
|
||||
// 1. prepare variables
|
||||
uint16_t channels = 0x6161, bit_depth = param.bit_depth,
|
||||
block_align = param.channels * bit_depth / BITS_PER_BYTE;
|
||||
uint32_t buffer_size = param.samples * (uint32_t)block_align,
|
||||
file_length = 0x61616161,
|
||||
fmt_data_length = 0x61616161 /* <--
|
||||
* length of format data before this value
|
||||
* in the file format structure
|
||||
*/
|
||||
,
|
||||
sample_rate = 0x61616161,
|
||||
byte_rate = 0x61616161;
|
||||
uint16_t fmt_type = 0x6161;
|
||||
|
||||
uint16_t mock_bit_depth = 0x6161, mock_block_align = 0x6161;
|
||||
uint32_t mock_buffer_size = 0x61616161;
|
||||
|
||||
if (buffer_size != (size * count)) {
|
||||
if (buffer_size > count)
|
||||
fputs("pcm_wav_write: Not enough data\n", stderr);
|
||||
else
|
||||
fputs("pcm_wav_write: Too much data to write\n", stderr);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
// 2. write headers
|
||||
// <L = Little-endian or B = Big-endian> : <name> : <bytes of field>
|
||||
// - RIFF chunk:
|
||||
fwrite_noerr("RIFF", 1, 4, file); // B : ChunkID : 4
|
||||
fwrite_le_noerr(&file_length, 4, 1, file); // L : ChunkSize : 4
|
||||
fwrite_noerr("WAVE", 1, 4, file); // B : Format : 4
|
||||
// - format subchunk:
|
||||
fwrite_noerr("fmt ", 1, 4, file); // B : Subchunk1ID : 4
|
||||
fwrite_le_noerr(&fmt_data_length, 4, 1, file); // L : Subchunk1Size : 4
|
||||
fwrite_le_noerr(&fmt_type, 2, 1, file); // L : AudioFormat : 2
|
||||
fwrite_le_noerr(&channels, 2, 1, file); // L : NumChannels : 2
|
||||
fwrite_le_noerr(&sample_rate, 4, 1, file); // L : SampleRate : 4
|
||||
fwrite_le_noerr(&byte_rate, 4, 1, file); // L : ByteRate : 4
|
||||
fwrite_le_noerr(&mock_block_align, 2, 1, file); // L : BlockAlign : 2
|
||||
fwrite_le_noerr(&mock_bit_depth, 2, 1, file); // L : BitsPerSample : 2
|
||||
// - data subchunk:
|
||||
fwrite_noerr("data", 1, 4, file); // B : Subchunk2ID : 4
|
||||
fwrite_le_noerr(&mock_buffer_size, 4, 1, file); // L : Subchunk2Size : 4
|
||||
|
||||
// 3. write sample data
|
||||
fwrite_le_noerr(data, sizeof(byte), buffer_size, file);
|
||||
}
|
||||
|
||||
void fclose_file(void) {
|
||||
if (file == NULL)
|
||||
return;
|
||||
|
||||
fclose(file);
|
||||
file = NULL;
|
||||
}
|
||||
|
||||
int main(void) {
|
||||
const size_t array_size = SAMPLES * OUTPUT_CHANNELS;
|
||||
chip_sample_t audio_data[array_size];
|
||||
for (size_t i = 0; i < array_size; i++) {
|
||||
audio_data[i] = (chip_sample_t) '\n';
|
||||
}
|
||||
|
||||
file = fopen("text-wave-file", "wb");
|
||||
|
||||
pcm_wav_parameters_t param = {.bit_depth = BIT_DEPTH,
|
||||
.channels = OUTPUT_CHANNELS,
|
||||
.samples = SAMPLES};
|
||||
|
||||
pcm_wav_write(file, param, audio_data, SAMPLE_SIZE, array_size);
|
||||
|
||||
fclose(file);
|
||||
|
||||
puts("Done!");
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user