runner.c 1.52 KB
Newer Older
PoroCYon's avatar
initial  
PoroCYon committed
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66

#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>

#define __stdcall /* this isn't windows. */

#ifdef __cplusplus
#define EXTERN_C extern "C" /* C++ suxx */
#else
#define EXTERN_C
#endif

#include "4klang.h"

#ifdef FLOAT_32BIT
#define APLAY_SAMPLE_FORMAT "FLOAT_LE"
#else
/*
 * If you encounter this error, you should look at your 4klang.h file and check
 * the line above the "#define SAMPLE_TYPE" one. This macro definition can be
 * used to give the APLAY_SAMPLE_FORMAT the correct string value. Consult the
 * aplay(1) manpage for the details. For example, signed 16-bit int is S16_LE.
 */
#error "This 4klang sample type isn't \"supported\" yet."
#endif

#define STRINGIFY(s) _STRINGIFIER(s)
#define _STRINGIFIER(s) #s

static SAMPLE_TYPE output_buffer[MAX_SAMPLES*2];

static char*const aplay_args[] = {
	"/usr/bin/aplay",
		"-c2",
		"-f" APLAY_SAMPLE_FORMAT,
		"-r" STRINGIFY(SAMPLE_RATE),
	NULL
};

int main() {
	// pipefds[0]: read end
	// pipefds[1]: write end
	int pipefds[2];
	pipe(pipefds);

	pid_t childpid = fork();
	if (!childpid) {
		// child process
		dup2(pipefds[0], STDIN_FILENO);
		execv("/usr/bin/aplay", aplay_args);
	} else if (childpid > 0) {
		_4klang_render(output_buffer);
		ssize_t writesz = 65536 /* pipe buffer size */, readsz;
		const char* outbuf = (const char*)output_buffer;
		do {
			readsz = write(pipefds[1], outbuf, writesz);
			outbuf += writesz;
		} while (readsz == writesz);
		waitpid(childpid, NULL, 0);
	} else {
		dprintf(STDERR_FILENO, "Err: couldn't fork.\n");
	}
}