first commit
[shitsynth.git] / shitsynth.c
blob8fa58bf8dc4d6a06553ad8006bf5587a314ba2e9
1 #define _POSIX_C_SOURCE 200809L
2 #include <sys/types.h>
3 #include <sys/stat.h>
4 #include <sys/ioctl.h>
5 #include <unistd.h>
6 #include <fcntl.h>
7 #include <sys/soundcard.h>
8 #include <assert.h>
9 #include <errno.h>
10 #include <stdlib.h>
11 #include <string.h>
12 #include <strings.h>
13 #include <error.h>
14 #include <stdint.h>
15 #include <stdio.h>
16 #include <math.h>
17 #include <sys/mman.h>
18 #include <unistd.h>
19 #include <stdbool.h>
21 /* Stupid declarations */
23 #define BIT_RATE 48000
25 typedef int16_t sample_t;
26 #define SAMPLE_MIN -32768
27 #define SAMPLE_MAX 32767
29 typedef void(*synth_t)(uint_least16_t freq, sample_t *buf, size_t count);
31 int F;
33 uint_least16_t note(int_least8_t X) {
34 return 440 * pow(2, X / 12.0);
37 /* Synthesizers */
39 void void_synth(uint_least16_t freq, sample_t *buf, size_t count) {
40 memset(buf, 0, count * sizeof(sample_t));
43 void square_synth(uint_least16_t freq, sample_t *buf, size_t count) {
44 sample_t a = SAMPLE_MAX;
45 uint_least16_t period = BIT_RATE / freq;
47 for (size_t i = 0; i < count; i++) {
48 if (!(i%period)) a = (a == SAMPLE_MAX) ? SAMPLE_MIN : SAMPLE_MAX;
49 buf[i] = a;
53 /* Signal manipulating tools */
55 void attenuate(sample_t *track, size_t len, double level) {
56 for (size_t i = 0; i < len; i++) {
57 track[i] *= level;
61 void mix(sample_t *dest, sample_t *src, size_t len) {
62 for (size_t i = 0; i < len; i++) {
63 dest[i] += src[i];
67 /* Misc stuff */
69 void play(sample_t *what, size_t len) {
70 write(F, what, len * sizeof(sample_t));
73 void show(sample_t *what, size_t len) {
74 for (size_t i = 0; i < len; i++) {
75 printf("%hd ", what[i]);
79 void oss_init() {
80 int i;
81 F = open("/dev/dsp", O_WRONLY);
82 if (F == -1) {
83 error(1, errno, NULL);
86 i = 1;
87 ioctl(F, SNDCTL_DSP_CHANNELS, &i);
88 i = AFMT_S16_NE;
89 ioctl(F, SNDCTL_DSP_SETFMT, &i);
90 i = BIT_RATE;
91 ioctl(F, SNDCTL_DSP_SPEED, &i);
94 void interpret_track(char *instr, size_t instrlen, char *what, uint_least16_t *off, int_least16_t size) {
95 char n = what[*off];
96 assert(instr);
97 sample_t *b1 = malloc(size * sizeof(sample_t));
99 for (size_t len = strchr(what + *off, '\n') - what; *off < len; (*off)++) {
100 if (n == ' ') {
101 void_synth(0, b1, size);
102 } else {
103 if (strncmp(instr, "square", labellen) == 0) {
104 square_synth(note((what[off] - 'e') * 2), b1, size);
105 } else {
106 assert(false);
108 char *fail;
109 uint_least8_t track = strtol(label, &fail, 10);
110 assert(fail != label);
112 //TODO
115 play(b1, size);
119 void interpret(char *what, size_t len, int_least16_t size) {
120 uint_least16_t off = 0;
121 sample_t *b1 = malloc(size * sizeof(sample_t));
123 assert(what);
124 assert(size);
125 //if (size > ) { /* size is per note */
126 //} else { /* size is per code chunk */
129 char *label = NULL;
130 while (off < len) {
131 char n = what[off];
132 putchar(n);
133 putchar('\n');
134 fdatasync(1);
136 size_t labellen;
138 if (off == 0 || what[off - 1] == '\n') {
139 if (n == '>') { // define the subroutine
140 //TODO
141 } else if (n == '<') { // use the subroutine
142 label = what + off + 1;
143 labellen = strchr(label, '>') - label;
144 off += labellen + 1;
145 } else {
146 assert(false);
149 } else {
151 off++;
155 int main() {
156 int i;
157 int songf = open("song", O_RDONLY);
158 size_t songlen;
159 char *song, *songfile;
160 //size_t chunk = BIT_RATE * 0.04;
161 sample_t *b1;
163 assert(songf != -1);
165 songlen = lseek(songf, 0, SEEK_END);
166 assert(songlen);
167 lseek(songf, 0, SEEK_SET);
168 songfile = mmap(NULL, songlen, PROT_READ, MAP_SHARED, songf, 0);
169 assert(songfile != MAP_FAILED);
171 double notelength;
172 sscanf(songfile, "%lf", &notelength);
173 printf("Notelength: %lf\n", notelength);
174 assert(notelength > 0);
175 size_t notelen = notelength * BIT_RATE; // :]
177 song = strchr(songfile, '\n') + 1;
179 oss_init();
181 b1 = malloc(notelen * sizeof(sample_t));
183 // show(b1, chunk);
184 off_t songptr = 0;
185 char *programs[16] = {0};
187 interpret(song, songlen, notelen);
189 return 0;