124 lines
3.2 KiB
C
124 lines
3.2 KiB
C
// gcc audiosort.c -o audiosort -O3
|
|
// this for me so i don't lose later:
|
|
// gcc audiosort.c -o audiosort -O0 -Wall -Wextra -Werror -Wno-unused-result
|
|
// requires ffmpeg
|
|
// ./audiosort <input_file> <output_file>
|
|
#include <stddef.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
|
|
#define BUFFER_SIZE 4800
|
|
#define conststrlen(s) ((sizeof(s))-1)
|
|
typedef short sample_t;
|
|
|
|
static void* safe_malloc(const size_t bytes) {
|
|
void* ptr = malloc(bytes);
|
|
if (ptr == NULL) exit(1);
|
|
return ptr;
|
|
}
|
|
|
|
#define put_some_shit(text) do { \
|
|
memcpy(ptr, text, conststrlen(text)); \
|
|
ptr += conststrlen(text); \
|
|
} while (0)
|
|
|
|
#define put_SINGLE_shit(c) do { \
|
|
*ptr++ = c; \
|
|
} while (0)
|
|
|
|
|
|
static FILE* get_input_pipe(const char* filename) {
|
|
size_t len = conststrlen("ffmpeg -i") + conststrlen(" -f s16le -ar 48000 -ac 2 -") + 1;
|
|
for (const char* s = filename; *s; s++, len += 1 + (*s == ' ')) {}
|
|
|
|
char* command = safe_malloc(len);
|
|
char* ptr = command;
|
|
|
|
put_some_shit("ffmpeg -i ");
|
|
|
|
for (const char* c = filename; *c; c++) {
|
|
if (*c == ' ') put_SINGLE_shit('\\');
|
|
put_SINGLE_shit(*c);
|
|
}
|
|
|
|
put_some_shit(" -f s16le -ar 48000 -ac 2 -");
|
|
put_SINGLE_shit('\0');
|
|
|
|
FILE* pipe = popen(command, "r");
|
|
free(command);
|
|
if (pipe == NULL) exit(1);
|
|
return pipe;
|
|
}
|
|
|
|
static FILE* get_output_pipe(const char* filename) {
|
|
size_t len = conststrlen("ffmpeg -f s16le -ar 48k -ac 2 -i pipe: -y ") + 1;
|
|
for (const char* s = filename; *s; s++, len += 1 + (*s == ' ')) {}
|
|
|
|
char* command = safe_malloc(len);
|
|
char* ptr = command;
|
|
|
|
put_some_shit("ffmpeg -f s16le -ar 48k -ac 2 -i pipe: -y ");
|
|
|
|
for (const char* c = filename; *c; c++) {
|
|
if (*c == ' ') put_SINGLE_shit('\\');
|
|
put_SINGLE_shit(*c);
|
|
}
|
|
|
|
put_SINGLE_shit('\0');
|
|
|
|
FILE* pipe = popen(command, "w");
|
|
free(command);
|
|
if (pipe == NULL) exit(1);
|
|
return pipe;
|
|
}
|
|
|
|
static int get_buffers_count(FILE* file) {
|
|
int size = 0;
|
|
int16_t buffer[BUFFER_SIZE];
|
|
while (1) {
|
|
if (fread(buffer, sizeof(sample_t), BUFFER_SIZE, file) == 0) break;
|
|
size++;
|
|
}
|
|
return size;
|
|
}
|
|
|
|
static int sample_sorter(const void* a, const void* b) {
|
|
int64_t diff = 0;
|
|
|
|
for (int i = 0; i < BUFFER_SIZE; i++) {
|
|
diff += abs((*(sample_t**)a)[i]) - abs((*(sample_t**)b)[i]);
|
|
}
|
|
|
|
return (diff > 0) - (diff < 0);
|
|
}
|
|
|
|
int main(const int argc, const char* argv[]) {
|
|
if (argc < 3) {
|
|
fprintf(stderr, "Usage: %s <input_file> <output_file>\n", argv[0]);
|
|
return 1;
|
|
}
|
|
FILE* input = get_input_pipe(argv[1]);
|
|
const int bufc = get_buffers_count(input);
|
|
pclose(input);
|
|
|
|
input = get_input_pipe(argv[1]);
|
|
sample_t** pcm = safe_malloc(sizeof(sample_t*) * bufc);
|
|
for (int i = 0; i < bufc; i++) {
|
|
pcm[i] = safe_malloc(sizeof(sample_t) * BUFFER_SIZE);
|
|
fread(pcm[i], sizeof(sample_t), BUFFER_SIZE, input);
|
|
}
|
|
pclose(input);
|
|
|
|
qsort(pcm, bufc, sizeof(sample_t*), sample_sorter);
|
|
|
|
FILE* output = get_output_pipe(argv[2]);
|
|
for (int i = 0; i < bufc; i++) {
|
|
fwrite(pcm[i], sizeof(sample_t), BUFFER_SIZE, output);
|
|
free(pcm[i]);
|
|
}
|
|
pclose(output);
|
|
free(pcm);
|
|
return 0;
|
|
}
|