1 #include <stdlib.h>
2 #include <stdint.h>
3 #include <stdio.h>
4 #include <unistd.h>
5 #include <stdbool.h>
6 #include <pthread.h>
7 #include <time.h>
8 #include <math.h>
9
10 #include <arcan_shmif.h>
11
12 static shmif_pixel palette[] = {
13 SHMIF_RGBA(0xff, 0x00, 0x00, 0xff),
14 SHMIF_RGBA(0x00, 0xff, 0x00, 0xff),
15 SHMIF_RGBA(0x00, 0x00, 0xff, 0xff),
16 SHMIF_RGBA(0xff, 0xff, 0x00, 0xff),
17 SHMIF_RGBA(0xff, 0x00, 0xff, 0xff),
18 SHMIF_RGBA(0x00, 0xff, 0xff, 0xff),
19 SHMIF_RGBA(0xff, 0xff, 0xff, 0xff)
20 };
21
22 static float tones[] = {
23 16.35, 18.35, 20.60, 21.83, 24.50, 27.50, 30.87, 32.70,
24 30.87, 27.50, 24.50, 21.83, 20.60, 18.35
25 };
26
27 static int pi = 0;
28 static int ti = 0;
29 static float pos = 0;
30
time_ms()31 static long long time_ms()
32 {
33 struct timespec tp;
34 clock_gettime(CLOCK_MONOTONIC_RAW, &tp);
35 return (tp.tv_sec * 1000) + (tp.tv_nsec / 1000000);
36 }
37
aprod(void * data)38 static void* aprod(void* data)
39 {
40 struct arcan_shmif_cont* cont = data;
41 size_t bps = ARCAN_SHMIF_ACHANNELS * sizeof(shmif_asample);
42
43 while (1){
44 size_t nsamp = (cont->abufsize - cont->abufused) / (bps * 2);
45 float stepv = 2.0 * 3.14 * ((5 * tones[ti]) / (float)cont->samplerate);
46 for (size_t b = 0; b < cont->abuf_cnt; b++){
47 for (size_t i = 0; i < nsamp; i++){
48 cont->audp[i*2+0] = 32767.0 * sinf(pos);
49 cont->audp[i*2+1] = 32767.0 * sinf(pos);
50 pos += stepv;
51 }
52 cont->abufused = nsamp * bps;
53 arcan_shmif_signal(cont, SHMIF_SIGAUD);
54 }
55 }
56
57 return NULL;
58 }
59
step(struct arcan_shmif_cont * cont)60 static void step(struct arcan_shmif_cont* cont)
61 {
62 printf("pre;%lld;%d;%d\n", time_ms(), pi, ti);
63 pi = (pi + 1) % (sizeof(palette) / sizeof(palette[0]));
64 ti = (ti + 1) % (sizeof(tones) / sizeof(tones[0]));
65 size_t count = cont->pitch * cont->h;
66 for (size_t i = 0; i < count; i++)
67 cont->vidp[i] = palette[pi];
68
69 /* will create pop:ing as any queued buffers are dropped */
70 arcan_shmif_enqueue(cont, &(arcan_event){
71 .tgt.kind = ARCAN_EVENT(FLUSHAUD)
72 });
73 arcan_shmif_signal(cont, SHMIF_SIGVID);
74 printf("post;%lld;%d;%d\n", time_ms(), pi, ti);
75 }
76
main(int argc,char ** argv)77 int main(int argc, char** argv)
78 {
79 struct arg_arr* aarr;
80 if (argc != 7){
81 printf("usage: \n\tavlat w h vbuf_count abuf_count abuf_sz samplerate\n");
82 return EXIT_FAILURE;
83 }
84
85 int w = strtoul(argv[1], NULL, 10);
86 int h = strtoul(argv[2], NULL, 10);
87
88 struct shmif_resize_ext ext_sz = {
89 .vbuf_cnt = strtoul(argv[3], NULL, 10),
90 .abuf_cnt = strtoul(argv[4], NULL, 10),
91 .abuf_sz = strtoul(argv[5], NULL, 10),
92 .samplerate = strtoul(argv[6], NULL, 10)
93 };
94
95 struct arcan_shmif_cont cont = arcan_shmif_open(
96 SEGID_APPLICATION, SHMIF_ACQUIRE_FATALFAIL, &aarr);
97
98 if (!arcan_shmif_resize_ext(&cont, w, h, ext_sz)){
99 printf("failed to set buffer properties\n");
100 return EXIT_FAILURE;
101 }
102
103 printf("context: %d * %d, %d bytes @ %d Hz",
104 (int)cont.w, (int)cont.h, (int)cont.abufsize, (int)cont.samplerate);
105
106 step(&cont);
107 ti = 0;
108
109 pthread_t athread;
110 pthread_create(&athread, NULL, aprod, (void*) &cont);
111
112 arcan_event ev;
113 while (arcan_shmif_wait(&cont, &ev)){
114 if (ev.category == EVENT_TARGET)
115 switch (ev.tgt.kind){
116 case TARGET_COMMAND_EXIT:
117 return EXIT_SUCCESS;
118 break;
119 default:
120 break;
121 }
122 else if (ev.category == EVENT_IO){
123 switch (ev.io.datatype){
124 case EVENT_IDATATYPE_TRANSLATED:
125 if (ev.io.input.translated.active)
126 step(&cont);
127 break;
128 case EVENT_IDATATYPE_DIGITAL:
129 if (ev.io.input.digital.active)
130 step(&cont);
131 break;
132 default:
133 break;
134 }
135 }
136 }
137
138 return EXIT_SUCCESS;
139 }
140