Files: 6cd4730c51cbbdc9bcc196a95d8dd12dba65eef3 / foostudio.c
2843 bytesRaw
1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
7 | |
8 | |
9 | |
10 | |
11 | |
12 | |
13 | |
14 | |
15 | |
16 | |
17 | static unsigned int rate = 48000; |
18 | static unsigned int channels_out = 1; |
19 | static unsigned int channels_in = 1; |
20 | static unsigned int latency = 10000; // us |
21 | static int resample = 1; // allow resampling |
22 | |
23 | static snd_pcm_format_t format = SND_PCM_FORMAT_FLOAT; |
24 | |
25 | int main(int argc, char *argv[]) |
26 | { |
27 | struct ccdl ccdl; |
28 | void *tune_obj = NULL; |
29 | int err; |
30 | snd_pcm_t *pcm_out, *pcm_in; |
31 | const char *src_fname = "tune.c"; |
32 | const char *device_out = "default"; |
33 | const char *device_in = "default"; |
34 | |
35 | if (argc > 1) src_fname = argv[1]; |
36 | if (argc > 2) device_out = argv[2]; |
37 | if (argc > 3) device_in = argv[3]; |
38 | |
39 | ccdl_init(&ccdl, src_fname, "play"); |
40 | |
41 | if (ccdl_watch(&ccdl)) { |
42 | errx(1, "ccdl_watch"); |
43 | } |
44 | |
45 | err = snd_pcm_open(&pcm_out, device_out, SND_PCM_STREAM_PLAYBACK, 0); |
46 | if (err < 0) { |
47 | warnx("Playback open error: %s", snd_strerror(err)); |
48 | return 1; |
49 | } |
50 | |
51 | err = snd_pcm_open(&pcm_in, device_in, |
52 | SND_PCM_STREAM_CAPTURE, |
53 | SND_PCM_NONBLOCK); |
54 | if (err < 0) { |
55 | warnx("Capture open error: %s", snd_strerror(err)); |
56 | return 1; |
57 | } |
58 | |
59 | if ((err = snd_pcm_set_params(pcm_out, format, |
60 | SND_PCM_ACCESS_RW_INTERLEAVED, |
61 | channels_out, rate, resample, latency)) < 0) { |
62 | warnx("Playback open error: %s", snd_strerror(err)); |
63 | return 1; |
64 | } |
65 | |
66 | if ((err = snd_pcm_set_params(pcm_in, format, |
67 | SND_PCM_ACCESS_RW_INTERLEAVED, |
68 | channels_in, rate, resample, latency)) < 0) { |
69 | warnx("Capture open error: %s", snd_strerror(err)); |
70 | return 1; |
71 | } |
72 | |
73 | double time = 0; |
74 | double step = 1/(double)rate; |
75 | |
76 | while (1) { |
77 | snd_pcm_sframes_t frames, frames_in, frames_out; |
78 | frames = snd_pcm_avail_update(pcm_out); |
79 | if (frames < 0) { |
80 | err = snd_pcm_recover(pcm_out, frames, 0); |
81 | if (err) err = snd_pcm_wait(pcm_out, 1000); |
82 | if (err) warnx("snd_pcm_wait(%s)", snd_strerror(err)); |
83 | continue; |
84 | } |
85 | float buffer[frames]; |
86 | |
87 | frames_in = snd_pcm_readi(pcm_in, buffer, frames); |
88 | if (frames_in < 0) snd_pcm_recover(pcm_in, frames_in, 0); |
89 | |
90 | play_fn *play; |
91 | *(void **)(&play) = ccdl_get(&ccdl); |
92 | if (play) { |
93 | for (size_t i = 0; i < (size_t)frames; i++) { |
94 | time += step; |
95 | float frame_in = (ssize_t)i < frames_in ? buffer[i] : 0; |
96 | buffer[i] = play(&tune_obj, time, frame_in); |
97 | } |
98 | } else { |
99 | time += step * frames; |
100 | } |
101 | |
102 | frames_out = snd_pcm_writei(pcm_out, buffer, frames); |
103 | if (frames_out < 0) snd_pcm_recover(pcm_out, frames_out, 0); |
104 | } |
105 | |
106 | snd_pcm_close(pcm_out); |
107 | snd_pcm_close(pcm_in); |
108 | return ccdl_deinit(&ccdl); |
109 | } |
110 |
Built with git-ssb-web