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