Extend the README.
[software/sndxfer.git] / main.c
1 /* sndxfer -- transfer bytes over the audio interface
2 Copyright © 2016 Ricardo Wurmus <rekado@elephly.net>
3
4 This file is part of sndxfer.
5
6 sndxfer is free software; you can redistribute it and/or modify it
7 under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 3 of the License, or
9 (at your option) any later version.
10
11 sndxfer is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with sndxfer. If not, see <http://www.gnu.org/licenses/>.
18 */
19
20 #define ALSA_PCM_NEW_HW_PARAMS_API
21
22 #define SNDXFER_CHANNELS 2
23 #define SNDXFER_RATE 96000
24
25 #include <alsa/asoundlib.h>
26
27 int main() {
28 int err;
29 int rc;
30 int size;
31 snd_pcm_t *pcm;
32 snd_pcm_hw_params_t *params;
33 int dir;
34 snd_pcm_uframes_t frames;
35 char *buffer;
36
37 /* Open PCM device for playback. */
38 if (err = snd_pcm_open(&pcm, "plug:sndxfer",
39 SND_PCM_STREAM_PLAYBACK, 0)) {
40 fprintf(stderr, "unable to open pcm device: %s\n",
41 snd_strerror(err));
42 exit(EXIT_FAILURE);
43 }
44
45 /* Allocate a hardware parameters object. */
46 snd_pcm_hw_params_alloca (&params);
47
48 /* Fill it in with default values. */
49 snd_pcm_hw_params_any (pcm, params);
50
51 /* Set the desired hardware parameters. */
52 snd_pcm_hw_params_set_access (pcm, params, SND_PCM_ACCESS_RW_INTERLEAVED);
53 snd_pcm_hw_params_set_format (pcm, params, SND_PCM_FORMAT_S32_LE);
54 snd_pcm_hw_params_set_channels (pcm, params, SNDXFER_CHANNELS);
55 snd_pcm_hw_params_set_rate (pcm, params, SNDXFER_RATE, 0);
56
57 /* Set period size to 32 frames. */
58 frames = 32;
59 snd_pcm_hw_params_set_period_size (pcm, params, frames, 0);
60
61 /* Write the parameters to the driver */
62 if (err = snd_pcm_hw_params (pcm, params)) {
63 fprintf(stderr, "unable to set hw parameters: %s\n",
64 snd_strerror(err));
65 exit(EXIT_FAILURE);
66 }
67
68 /* Use a buffer large enough to hold one period */
69 snd_pcm_hw_params_get_period_size(params, &frames, &dir);
70 size = 4 * frames * SNDXFER_CHANNELS; //4 bytes per sample
71 buffer = (char*) malloc(size);
72
73 while (1) {
74 rc = read(0, buffer, size);
75 if (rc == 0) {
76 fprintf(stderr, "end of file on input\n");
77 break;
78 } else if (rc != size) {
79 fprintf(stderr, "short read: read %d bytes\n", rc);
80 }
81 rc = snd_pcm_writei (pcm, buffer, frames);
82 if (rc == -EPIPE) {
83 /* EPIPE means buffer underrun */
84 fprintf(stderr, "underrun occurred\n");
85 snd_pcm_prepare (pcm);
86 } else if (rc < 0) {
87 fprintf(stderr, "error from writei: %s\n", snd_strerror (rc));
88 } else if (rc != (int)frames) {
89 fprintf(stderr, "short write, write %d frames\n", rc);
90 }
91 }
92
93 snd_pcm_drain (pcm);
94 snd_pcm_close (pcm);
95 free (buffer);
96
97 return 0;
98 }