Commit 5150ca653ef3132d6d841efbba1fb59908966663
Rename executable to foostudio
cel committed on 10/26/2016, 2:07:03 AMParent: c914c51d3db53e41365c29ba0d795df65bc1cebf
Files changed
Makefile | changed |
studio.c | deleted |
foostudio.c | added |
Makefile | ||
---|---|---|
@@ -1,10 +1,11 @@ | ||
1 … | +BIN = foostudio | |
1 | 2 … | CFLAGS = -Wall -Wextra -pedantic |
2 | 3 … | LDLIBS = -ldl -lasound -lm -lpthread |
3 | 4 … | |
4 | -studio: studio.o ccdl.o | |
5 … | +$(BIN): foostudio.o ccdl.o | |
5 | 6 … | |
6 | -studio.o ccdl.o: Makefile | |
7 … | +foostudio.o ccdl.o: Makefile | |
7 | 8 … | |
8 | 9 … | clean: |
9 | - $(RM) *.o *.so studio | |
10 … | + $(RM) $(wildcard *.o *.so) $(BIN) | |
10 | 11 … |
studio.c | ||
---|---|---|
@@ -1,232 +1,0 @@ | ||
1 | - | |
2 | - | |
3 | - | |
4 | - | |
5 | - | |
6 | - | |
7 | - | |
8 | - | |
9 | - | |
10 | - | |
11 | - | |
12 | - | |
13 | - | |
14 | -static unsigned int rate = 44100; | |
15 | -static unsigned int channels = 1; | |
16 | -static unsigned int latency = 500000; /* ring buffer length in us */ | |
17 | -static snd_pcm_format_t format = SND_PCM_FORMAT_FLOAT; | |
18 | - | |
19 | -/* | |
20 | - * Underrun and suspend recovery, from alsa-lib/test/pcm.c | |
21 | - */ | |
22 | - | |
23 | -static int xrun_recovery(snd_pcm_t *handle, int err) | |
24 | -{ | |
25 | - if (err == -EPIPE) { /* under-run */ | |
26 | - err = snd_pcm_prepare(handle); | |
27 | - if (err < 0) | |
28 | - warnx("Can't recovery from underrun, prepare failed: %s", snd_strerror(err)); | |
29 | - return 0; | |
30 | - } else if (err == -ESTRPIPE) { | |
31 | - while ((err = snd_pcm_resume(handle)) == -EAGAIN) | |
32 | - sleep(1); /* wait until the suspend flag is released */ | |
33 | - if (err < 0) { | |
34 | - err = snd_pcm_prepare(handle); | |
35 | - if (err < 0) | |
36 | - warnx("Can't recovery from suspend, prepare failed: %s", snd_strerror(err)); | |
37 | - } | |
38 | - return 0; | |
39 | - } | |
40 | - return err; | |
41 | -} | |
42 | - | |
43 | -static void generate(struct ccdl *ccdl, | |
44 | - const snd_pcm_channel_area_t *areas, | |
45 | - snd_pcm_uframes_t offset, | |
46 | - int count, double *_phase) | |
47 | -{ | |
48 | - double phase = *_phase; | |
49 | - double step = 1/(double)rate; | |
50 | - unsigned char *samples[channels]; | |
51 | - int steps[channels]; | |
52 | - unsigned int chn; | |
53 | - int format_bits = snd_pcm_format_width(format); | |
54 | - // unsigned int maxval = (1 << (format_bits - 1)) - 1; | |
55 | - int bps = format_bits / 8; /* bytes per sample */ | |
56 | - int phys_bps = snd_pcm_format_physical_width(format) / 8; | |
57 | - int big_endian = snd_pcm_format_big_endian(format) == 1; | |
58 | - int to_unsigned = snd_pcm_format_unsigned(format) == 1; | |
59 | - | |
60 | - /* verify and prepare the contents of areas */ | |
61 | - for (chn = 0; chn < channels; chn++) { | |
62 | - if ((areas[chn].first % 8) != 0) { | |
63 | - errx(1, "areas[%i].first == %i, aborting...", chn, areas[chn].first); | |
64 | - } | |
65 | - samples[chn] = /*(signed short *)*/(((unsigned char *)areas[chn].addr) + (areas[chn].first / 8)); | |
66 | - if ((areas[chn].step % 16) != 0) { | |
67 | - errx(1, "areas[%i].step == %i, aborting...", chn, areas[chn].step); | |
68 | - } | |
69 | - steps[chn] = areas[chn].step / 8; | |
70 | - samples[chn] += offset * steps[chn]; | |
71 | - } | |
72 | - | |
73 | - struct tune *tune = ccdl_get(ccdl); | |
74 | - | |
75 | - /* fill the channel areas */ | |
76 | - while (count-- > 0) { | |
77 | - union { | |
78 | - float f; | |
79 | - int i; | |
80 | - } fval; | |
81 | - int res, i; | |
82 | - if (tune && tune->play) { | |
83 | - fval.f = tune->play(tune, phase); | |
84 | - } else { | |
85 | - fval.f = 0; | |
86 | - } | |
87 | - res = fval.i; | |
88 | - if (to_unsigned) | |
89 | - res ^= 1U << (format_bits - 1); | |
90 | - for (chn = 0; chn < channels; chn++) { | |
91 | - /* Generate data in native endian format */ | |
92 | - if (big_endian) { | |
93 | - for (i = 0; i < bps; i++) | |
94 | - *(samples[chn] + phys_bps - 1 - i) = (res >> i * 8) & 0xff; | |
95 | - } else { | |
96 | - for (i = 0; i < bps; i++) | |
97 | - *(samples[chn] + i) = (res >> i * 8) & 0xff; | |
98 | - } | |
99 | - samples[chn] += steps[chn]; | |
100 | - } | |
101 | - phase += step; | |
102 | - /* | |
103 | - if (phase >= max_phase) | |
104 | - phase -= max_phase; | |
105 | - */ | |
106 | - } | |
107 | - *_phase = phase; | |
108 | -} | |
109 | - | |
110 | - | |
111 | -int main(int argc, char *argv[]) | |
112 | -{ | |
113 | - struct ccdl ccdl; | |
114 | - int err; | |
115 | - snd_pcm_t *pcm_out; | |
116 | - const char *src_fname = "tune.c"; | |
117 | - const char *device_out = "default"; | |
118 | - | |
119 | - if (argc > 1) src_fname = argv[1]; | |
120 | - if (argc > 2) device_out = argv[2]; | |
121 | - | |
122 | - ccdl_init(&ccdl, src_fname, "TUNE"); | |
123 | - | |
124 | - if (ccdl_watch(&ccdl)) { | |
125 | - errx(1, "ccdl_watch"); | |
126 | - } | |
127 | - | |
128 | - if ((err = snd_pcm_open(&pcm_out, device_out, SND_PCM_STREAM_PLAYBACK, 0)) < 0) { | |
129 | - warnx("Playback open error: %s", snd_strerror(err)); | |
130 | - return 1; | |
131 | - } | |
132 | - | |
133 | - if ((err = snd_pcm_set_params(pcm_out, | |
134 | - format, | |
135 | - SND_PCM_ACCESS_MMAP_INTERLEAVED, | |
136 | - channels, | |
137 | - rate, | |
138 | - 1, | |
139 | - latency)) < 0) { | |
140 | - warnx("Playback open error: %s", snd_strerror(err)); | |
141 | - return 1; | |
142 | - } | |
143 | - | |
144 | - snd_pcm_uframes_t buffer_size; | |
145 | - snd_pcm_uframes_t period_size; | |
146 | - if ((err = snd_pcm_get_params(pcm_out, &buffer_size, &period_size)) < 0) { | |
147 | - warnx("Playback get params error: %s", snd_strerror(err)); | |
148 | - return 1; | |
149 | - } | |
150 | - | |
151 | - double phase = 0; | |
152 | - const snd_pcm_channel_area_t *my_areas; | |
153 | - snd_pcm_uframes_t offset, frames, size; | |
154 | - snd_pcm_sframes_t avail, commitres; | |
155 | - snd_pcm_state_t state; | |
156 | - int first = 1; | |
157 | - | |
158 | - while (1) { | |
159 | - state = snd_pcm_state(pcm_out); | |
160 | - if (state == SND_PCM_STATE_XRUN) { | |
161 | - err = xrun_recovery(pcm_out, -EPIPE); | |
162 | - if (err < 0) { | |
163 | - printf("XRUN recovery failed: %s\n", snd_strerror(err)); | |
164 | - return err; | |
165 | - } | |
166 | - first = 1; | |
167 | - } else if (state == SND_PCM_STATE_SUSPENDED) { | |
168 | - err = xrun_recovery(pcm_out, -ESTRPIPE); | |
169 | - if (err < 0) { | |
170 | - printf("SUSPEND recovery failed: %s\n", snd_strerror(err)); | |
171 | - return err; | |
172 | - } | |
173 | - } | |
174 | - avail = snd_pcm_avail_update(pcm_out); | |
175 | - if (avail < 0) { | |
176 | - err = xrun_recovery(pcm_out, avail); | |
177 | - if (err < 0) { | |
178 | - printf("avail update failed: %s\n", snd_strerror(err)); | |
179 | - return err; | |
180 | - } | |
181 | - first = 1; | |
182 | - continue; | |
183 | - } | |
184 | - if ((snd_pcm_uframes_t)avail < period_size) { | |
185 | - if (first) { | |
186 | - first = 0; | |
187 | - err = snd_pcm_start(pcm_out); | |
188 | - if (err < 0) { | |
189 | - printf("Start error: %s\n", snd_strerror(err)); | |
190 | - exit(EXIT_FAILURE); | |
191 | - } | |
192 | - } else { | |
193 | - err = snd_pcm_wait(pcm_out, -1); | |
194 | - if (err < 0) { | |
195 | - if ((err = xrun_recovery(pcm_out, err)) < 0) { | |
196 | - printf("snd_pcm_wait error: %s\n", snd_strerror(err)); | |
197 | - exit(EXIT_FAILURE); | |
198 | - } | |
199 | - first = 1; | |
200 | - } | |
201 | - } | |
202 | - continue; | |
203 | - } | |
204 | - size = period_size; | |
205 | - while (size > 0) { | |
206 | - frames = size; | |
207 | - err = snd_pcm_mmap_begin(pcm_out, &my_areas, &offset, &frames); | |
208 | - if (err < 0) { | |
209 | - if ((err = xrun_recovery(pcm_out, err)) < 0) { | |
210 | - printf("MMAP begin avail error: %s\n", snd_strerror(err)); | |
211 | - exit(EXIT_FAILURE); | |
212 | - } | |
213 | - first = 1; | |
214 | - } | |
215 | - generate(&ccdl, my_areas, offset, frames, &phase); | |
216 | - // generate_sine(my_areas, offset, frames, &phase); | |
217 | - commitres = snd_pcm_mmap_commit(pcm_out, offset, frames); | |
218 | - if (commitres < 0 || (snd_pcm_uframes_t)commitres != frames) { | |
219 | - if ((err = xrun_recovery(pcm_out, commitres >= 0 ? -EPIPE : commitres)) < 0) { | |
220 | - printf("MMAP commit error: %s\n", snd_strerror(err)); | |
221 | - exit(EXIT_FAILURE); | |
222 | - } | |
223 | - first = 1; | |
224 | - } | |
225 | - size -= frames; | |
226 | - } | |
227 | - | |
228 | - } | |
229 | - | |
230 | - snd_pcm_close(pcm_out); | |
231 | - return ccdl_deinit(&ccdl); | |
232 | -} |
foostudio.c | |||
---|---|---|---|
@@ -1,0 +1,232 @@ | |||
1 … | + | ||
2 … | + | ||
3 … | + | ||
4 … | + | ||
5 … | + | ||
6 … | + | ||
7 … | + | ||
8 … | + | ||
9 … | + | ||
10 … | + | ||
11 … | + | ||
12 … | + | ||
13 … | + | ||
14 … | +static unsigned int rate = 44100; | ||
15 … | +static unsigned int channels = 1; | ||
16 … | +static unsigned int latency = 500000; /* ring buffer length in us */ | ||
17 … | +static snd_pcm_format_t format = SND_PCM_FORMAT_FLOAT; | ||
18 … | + | ||
19 … | +/* | ||
20 … | + * Underrun and suspend recovery, from alsa-lib/test/pcm.c | ||
21 … | + */ | ||
22 … | + | ||
23 … | +static int xrun_recovery(snd_pcm_t *handle, int err) | ||
24 … | +{ | ||
25 … | + if (err == -EPIPE) { /* under-run */ | ||
26 … | + err = snd_pcm_prepare(handle); | ||
27 … | + if (err < 0) | ||
28 … | + warnx("Can't recovery from underrun, prepare failed: %s", snd_strerror(err)); | ||
29 … | + return 0; | ||
30 … | + } else if (err == -ESTRPIPE) { | ||
31 … | + while ((err = snd_pcm_resume(handle)) == -EAGAIN) | ||
32 … | + sleep(1); /* wait until the suspend flag is released */ | ||
33 … | + if (err < 0) { | ||
34 … | + err = snd_pcm_prepare(handle); | ||
35 … | + if (err < 0) | ||
36 … | + warnx("Can't recovery from suspend, prepare failed: %s", snd_strerror(err)); | ||
37 … | + } | ||
38 … | + return 0; | ||
39 … | + } | ||
40 … | + return err; | ||
41 … | +} | ||
42 … | + | ||
43 … | +static void generate(struct ccdl *ccdl, | ||
44 … | + const snd_pcm_channel_area_t *areas, | ||
45 … | + snd_pcm_uframes_t offset, | ||
46 … | + int count, double *_phase) | ||
47 … | +{ | ||
48 … | + double phase = *_phase; | ||
49 … | + double step = 1/(double)rate; | ||
50 … | + unsigned char *samples[channels]; | ||
51 … | + int steps[channels]; | ||
52 … | + unsigned int chn; | ||
53 … | + int format_bits = snd_pcm_format_width(format); | ||
54 … | + // unsigned int maxval = (1 << (format_bits - 1)) - 1; | ||
55 … | + int bps = format_bits / 8; /* bytes per sample */ | ||
56 … | + int phys_bps = snd_pcm_format_physical_width(format) / 8; | ||
57 … | + int big_endian = snd_pcm_format_big_endian(format) == 1; | ||
58 … | + int to_unsigned = snd_pcm_format_unsigned(format) == 1; | ||
59 … | + | ||
60 … | + /* verify and prepare the contents of areas */ | ||
61 … | + for (chn = 0; chn < channels; chn++) { | ||
62 … | + if ((areas[chn].first % 8) != 0) { | ||
63 … | + errx(1, "areas[%i].first == %i, aborting...", chn, areas[chn].first); | ||
64 … | + } | ||
65 … | + samples[chn] = /*(signed short *)*/(((unsigned char *)areas[chn].addr) + (areas[chn].first / 8)); | ||
66 … | + if ((areas[chn].step % 16) != 0) { | ||
67 … | + errx(1, "areas[%i].step == %i, aborting...", chn, areas[chn].step); | ||
68 … | + } | ||
69 … | + steps[chn] = areas[chn].step / 8; | ||
70 … | + samples[chn] += offset * steps[chn]; | ||
71 … | + } | ||
72 … | + | ||
73 … | + struct tune *tune = ccdl_get(ccdl); | ||
74 … | + | ||
75 … | + /* fill the channel areas */ | ||
76 … | + while (count-- > 0) { | ||
77 … | + union { | ||
78 … | + float f; | ||
79 … | + int i; | ||
80 … | + } fval; | ||
81 … | + int res, i; | ||
82 … | + if (tune && tune->play) { | ||
83 … | + fval.f = tune->play(tune, phase); | ||
84 … | + } else { | ||
85 … | + fval.f = 0; | ||
86 … | + } | ||
87 … | + res = fval.i; | ||
88 … | + if (to_unsigned) | ||
89 … | + res ^= 1U << (format_bits - 1); | ||
90 … | + for (chn = 0; chn < channels; chn++) { | ||
91 … | + /* Generate data in native endian format */ | ||
92 … | + if (big_endian) { | ||
93 … | + for (i = 0; i < bps; i++) | ||
94 … | + *(samples[chn] + phys_bps - 1 - i) = (res >> i * 8) & 0xff; | ||
95 … | + } else { | ||
96 … | + for (i = 0; i < bps; i++) | ||
97 … | + *(samples[chn] + i) = (res >> i * 8) & 0xff; | ||
98 … | + } | ||
99 … | + samples[chn] += steps[chn]; | ||
100 … | + } | ||
101 … | + phase += step; | ||
102 … | + /* | ||
103 … | + if (phase >= max_phase) | ||
104 … | + phase -= max_phase; | ||
105 … | + */ | ||
106 … | + } | ||
107 … | + *_phase = phase; | ||
108 … | +} | ||
109 … | + | ||
110 … | + | ||
111 … | +int main(int argc, char *argv[]) | ||
112 … | +{ | ||
113 … | + struct ccdl ccdl; | ||
114 … | + int err; | ||
115 … | + snd_pcm_t *pcm_out; | ||
116 … | + const char *src_fname = "tune.c"; | ||
117 … | + const char *device_out = "default"; | ||
118 … | + | ||
119 … | + if (argc > 1) src_fname = argv[1]; | ||
120 … | + if (argc > 2) device_out = argv[2]; | ||
121 … | + | ||
122 … | + ccdl_init(&ccdl, src_fname, "TUNE"); | ||
123 … | + | ||
124 … | + if (ccdl_watch(&ccdl)) { | ||
125 … | + errx(1, "ccdl_watch"); | ||
126 … | + } | ||
127 … | + | ||
128 … | + if ((err = snd_pcm_open(&pcm_out, device_out, SND_PCM_STREAM_PLAYBACK, 0)) < 0) { | ||
129 … | + warnx("Playback open error: %s", snd_strerror(err)); | ||
130 … | + return 1; | ||
131 … | + } | ||
132 … | + | ||
133 … | + if ((err = snd_pcm_set_params(pcm_out, | ||
134 … | + format, | ||
135 … | + SND_PCM_ACCESS_MMAP_INTERLEAVED, | ||
136 … | + channels, | ||
137 … | + rate, | ||
138 … | + 1, | ||
139 … | + latency)) < 0) { | ||
140 … | + warnx("Playback open error: %s", snd_strerror(err)); | ||
141 … | + return 1; | ||
142 … | + } | ||
143 … | + | ||
144 … | + snd_pcm_uframes_t buffer_size; | ||
145 … | + snd_pcm_uframes_t period_size; | ||
146 … | + if ((err = snd_pcm_get_params(pcm_out, &buffer_size, &period_size)) < 0) { | ||
147 … | + warnx("Playback get params error: %s", snd_strerror(err)); | ||
148 … | + return 1; | ||
149 … | + } | ||
150 … | + | ||
151 … | + double phase = 0; | ||
152 … | + const snd_pcm_channel_area_t *my_areas; | ||
153 … | + snd_pcm_uframes_t offset, frames, size; | ||
154 … | + snd_pcm_sframes_t avail, commitres; | ||
155 … | + snd_pcm_state_t state; | ||
156 … | + int first = 1; | ||
157 … | + | ||
158 … | + while (1) { | ||
159 … | + state = snd_pcm_state(pcm_out); | ||
160 … | + if (state == SND_PCM_STATE_XRUN) { | ||
161 … | + err = xrun_recovery(pcm_out, -EPIPE); | ||
162 … | + if (err < 0) { | ||
163 … | + printf("XRUN recovery failed: %s\n", snd_strerror(err)); | ||
164 … | + return err; | ||
165 … | + } | ||
166 … | + first = 1; | ||
167 … | + } else if (state == SND_PCM_STATE_SUSPENDED) { | ||
168 … | + err = xrun_recovery(pcm_out, -ESTRPIPE); | ||
169 … | + if (err < 0) { | ||
170 … | + printf("SUSPEND recovery failed: %s\n", snd_strerror(err)); | ||
171 … | + return err; | ||
172 … | + } | ||
173 … | + } | ||
174 … | + avail = snd_pcm_avail_update(pcm_out); | ||
175 … | + if (avail < 0) { | ||
176 … | + err = xrun_recovery(pcm_out, avail); | ||
177 … | + if (err < 0) { | ||
178 … | + printf("avail update failed: %s\n", snd_strerror(err)); | ||
179 … | + return err; | ||
180 … | + } | ||
181 … | + first = 1; | ||
182 … | + continue; | ||
183 … | + } | ||
184 … | + if ((snd_pcm_uframes_t)avail < period_size) { | ||
185 … | + if (first) { | ||
186 … | + first = 0; | ||
187 … | + err = snd_pcm_start(pcm_out); | ||
188 … | + if (err < 0) { | ||
189 … | + printf("Start error: %s\n", snd_strerror(err)); | ||
190 … | + exit(EXIT_FAILURE); | ||
191 … | + } | ||
192 … | + } else { | ||
193 … | + err = snd_pcm_wait(pcm_out, -1); | ||
194 … | + if (err < 0) { | ||
195 … | + if ((err = xrun_recovery(pcm_out, err)) < 0) { | ||
196 … | + printf("snd_pcm_wait error: %s\n", snd_strerror(err)); | ||
197 … | + exit(EXIT_FAILURE); | ||
198 … | + } | ||
199 … | + first = 1; | ||
200 … | + } | ||
201 … | + } | ||
202 … | + continue; | ||
203 … | + } | ||
204 … | + size = period_size; | ||
205 … | + while (size > 0) { | ||
206 … | + frames = size; | ||
207 … | + err = snd_pcm_mmap_begin(pcm_out, &my_areas, &offset, &frames); | ||
208 … | + if (err < 0) { | ||
209 … | + if ((err = xrun_recovery(pcm_out, err)) < 0) { | ||
210 … | + printf("MMAP begin avail error: %s\n", snd_strerror(err)); | ||
211 … | + exit(EXIT_FAILURE); | ||
212 … | + } | ||
213 … | + first = 1; | ||
214 … | + } | ||
215 … | + generate(&ccdl, my_areas, offset, frames, &phase); | ||
216 … | + // generate_sine(my_areas, offset, frames, &phase); | ||
217 … | + commitres = snd_pcm_mmap_commit(pcm_out, offset, frames); | ||
218 … | + if (commitres < 0 || (snd_pcm_uframes_t)commitres != frames) { | ||
219 … | + if ((err = xrun_recovery(pcm_out, commitres >= 0 ? -EPIPE : commitres)) < 0) { | ||
220 … | + printf("MMAP commit error: %s\n", snd_strerror(err)); | ||
221 … | + exit(EXIT_FAILURE); | ||
222 … | + } | ||
223 … | + first = 1; | ||
224 … | + } | ||
225 … | + size -= frames; | ||
226 … | + } | ||
227 … | + | ||
228 … | + } | ||
229 … | + | ||
230 … | + snd_pcm_close(pcm_out); | ||
231 … | + return ccdl_deinit(&ccdl); | ||
232 … | +} | ||
Built with git-ssb-web