arngment/main.c

105 lines
2.2 KiB
C

/*
* arngment - random music generator
*
* Written in 2020 by Lucas
*
* To the extent possible under law, the author(s) have dedicated all
* copyright and related and neighboring rights to this software to the
* public domain worldwide. This software is distributed without any
* warranty.
*
* You should have received a copy of the CC0 Public Domain Dedication
* along with this software. If not, see
* <http://creativecommons.org/publicdomain/zero/1.0/>.
*/
/* getopt, srand48, visibility for glibc */
#if !defined(__OpenBSD__)
#define _DEFAULT_SOURCE
#endif
#include <limits.h>
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <time.h>
#include <unistd.h>
#include "err.h"
#include "lrand48_uniform.h"
#include "note.h"
#include "synth.h"
#define nelems(_a) (sizeof(_a) / sizeof((_a)[0]))
#define GAIN 1.4
#define RATE 48000
static void
usage(void)
{
fprintf(stderr, "Usage: %s base_note\n", __progname);
exit(1);
}
int
main(int argc, char *argv[])
{
int16_t buf[RATE];
int scale[] = {
0, 2, 3, 5, 7, 8, 10, 12,
0, 2, 3, 5, 7, 8, 10, 12,
12, 14, 15, 17, 19, 20, 22, 24,
};
struct note base_note, note;
double l, r, t;
size_t i;
uint32_t k;
int ch;
while ((ch = getopt(argc, argv, "")) != -1)
switch (ch) {
default:
usage();
}
argc -= optind;
argv += optind;
if (argc != 1)
usage();
if (!note_parse(&base_note, argv[0]))
errx(1, "Invalid note %s", argv[0]);
srand48(time(NULL));
for (;;) {
k = lrand48_uniform(nelems(scale));
note = base_note;
note.offset += scale[k];
for (i = 0; i < RATE / 2; i += 2) {
t = i / (double)RATE;
l = synth_distortion(GAIN,
synth_sinewave(t, note_pitch(note)));
r = synth_distortion(GAIN,
synth_trianglewave(t, note_pitch(note)));
buf[i] = l * INT16_MAX;
buf[i + 1] = r * INT16_MAX;
}
k = lrand48_uniform(nelems(scale));
note = base_note;
note.offset += scale[k];
for (; i < RATE; i += 2) {
t = i / (double)RATE;
l = synth_distortion(GAIN,
synth_sinewave(t, note_pitch(note)));
r = synth_distortion(GAIN,
synth_trianglewave(t, note_pitch(note)));
buf[i] = l * INT16_MAX;
buf[i + 1] = r * INT16_MAX;
}
fwrite(buf, sizeof(buf[0]), RATE, stdout);
}
return 0;
}