Subversion Repositories svnkaklik

Rev

Rev 519 | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log

Rev 519 Rev 521
Line 2... Line 2...
2
	#include <stdlib.h>
2
	#include <stdlib.h>
3
	#include <errno.h>
3
	#include <errno.h>
4
	#include <poll.h>
4
	#include <poll.h>
5
	#include <alsa/asoundlib.h>
5
	#include <alsa/asoundlib.h>
6
 
6
 
-
 
7
/* you allocate these in heap */
7
	int exact_rate;
8
int             restarting;
8
	int rate = 44100;	      
9
int             fragments = 2;
9
	snd_pcm_t *playback_handle;
10
int             channels = 1;
-
 
11
int             buffer_size = 512;
-
 
12
int             sample_rate = 48000;
-
 
13
int             frame_size = 1024;
10
	short buf[4096];
14
int             bits = 16;
11
 
15
 
-
 
16
char           *snd_device_in  = "plughw:0,0";
-
 
17
char           *snd_device_out = "plughw:0,0";
-
 
18
snd_pcm_t      *playback_handle;
12
	FILE *random;
19
snd_pcm_t      *capture_handle;
13
 
20
 
-
 
21
int err;
14
	
22
 
15
	int
-
 
16
	playback_callback (snd_pcm_sframes_t nframes)
23
int configure_alsa_audio(snd_pcm_t *device, int channels)
17
	{
24
{
-
 
25
    snd_pcm_hw_params_t *hw_params;
18
		int err;
26
    int                 err;
-
 
27
    int                 tmp;
19
 
28
 
20
		printf ("playback callback called with %u frames\n", nframes);
29
    snd_pcm_uframes_t   frames;
21
 
30
 
-
 
31
    /* allocate memory for hardware parameter structure */ 
-
 
32
    if ((err = snd_pcm_hw_params_malloc(&hw_params)) < 0) {
-
 
33
        fprintf (stderr, "cannot allocate parameter structure (%s)\n",
-
 
34
                 snd_strerror(err));
-
 
35
        return 1;
-
 
36
    }
-
 
37
    /* fill structure from current audio parameters */
-
 
38
    if ((err = snd_pcm_hw_params_any(device, hw_params)) < 0) {
-
 
39
        fprintf (stderr, "cannot initialize parameter structure (%s)\n",
22
		fread(buf,1,4096,random);
40
                 snd_strerror(err));
-
 
41
        return 1;
-
 
42
    }
23
	
43
 
-
 
44
    /* set access type, sample rate, sample format, channels */
-
 
45
    if ((err = snd_pcm_hw_params_set_access(device, hw_params, SND_PCM_ACCESS_RW_INTERLEAVED)) < 0) {
-
 
46
        fprintf (stderr, "cannot set access type: %s\n",
-
 
47
                 snd_strerror(err));
-
 
48
        return 1;
-
 
49
    }
-
 
50
    // bits = 16
-
 
51
    if ((err = snd_pcm_hw_params_set_format(device, hw_params, SND_PCM_FORMAT_S16_LE)) < 0) {
-
 
52
        fprintf (stderr, "cannot set sample format: %s\n",
-
 
53
                 snd_strerror(err));
-
 
54
        return 1;
-
 
55
    }
-
 
56
    tmp = sample_rate;    
-
 
57
    if ((err = snd_pcm_hw_params_set_rate_near(device, hw_params, &tmp, 0)) < 0) {
-
 
58
        fprintf (stderr, "cannot set sample rate: %s\n",
-
 
59
                 snd_strerror(err));
-
 
60
        return 1;
-
 
61
    }
24
		/* ... fill buf with data ... */
62
    if (tmp != sample_rate) {
-
 
63
        fprintf(stderr, "Could not set requested sample rate, asked for %d got %d\n", sample_rate, tmp);
-
 
64
        sample_rate = tmp;
-
 
65
    }
-
 
66
    if ((err = snd_pcm_hw_params_set_channels(device, hw_params, channels)) < 0) {
-
 
67
        fprintf (stderr, "cannot set channel count: %s\n",
-
 
68
                 snd_strerror(err));
-
 
69
        return 1;
-
 
70
    }
25
	
71
 
26
		if ((err = snd_pcm_writei (playback_handle, buf, nframes)) < 0) {
72
    if ((err = snd_pcm_hw_params_set_periods_near(device, hw_params, &fragments, 0)) < 0) {
27
			fprintf (stderr, "write failed (%s)\n", snd_strerror (err));
73
        fprintf(stderr, "Error setting # fragments to %d: %s\n", fragments,
-
 
74
                snd_strerror(err));
-
 
75
        return 1;
28
		}
76
    }
29
	
77
 
-
 
78
    frame_size = channels * (bits / 8);
-
 
79
    frames = buffer_size / frame_size * fragments;
-
 
80
    if ((err = snd_pcm_hw_params_set_buffer_size_near(device, hw_params, &frames)) < 0) {
-
 
81
        fprintf(stderr, "Error setting buffer_size %d frames: %s\n", frames,
-
 
82
                snd_strerror(err));
-
 
83
        return 1;
-
 
84
    }
-
 
85
    if (buffer_size != frames * frame_size / fragments) {
-
 
86
        fprintf(stderr, "Could not set requested buffer size, asked for %d got %d\n", buffer_size, frames * frame_size / fragments);
-
 
87
        buffer_size = frames * frame_size / fragments;
-
 
88
    }
-
 
89
    if ((err = snd_pcm_hw_params(device, hw_params)) < 0) {
-
 
90
        fprintf(stderr, "Error setting HW params: %s\n",
-
 
91
                snd_strerror(err));
-
 
92
        return 1;
-
 
93
    }
30
		return err;
94
    return 0;
31
	}
95
}
32
	      
96
	      
33
	main (int argc, char *argv[])
97
main (void)
34
	{
98
{
35
	
99
	
-
 
100
int i,frames, inframes, outframes, frame_size;
-
 
101
 
-
 
102
if ((err = snd_pcm_open(&playback_handle, snd_device_out, SND_PCM_STREAM_PLAYBACK, 0)) < 0) {
-
 
103
    fprintf(stderr, "cannot open output audio device %s: %s\n", snd_device_in, snd_strerror(err));
-
 
104
    exit(1);
-
 
105
}
-
 
106
 
-
 
107
if ((err = snd_pcm_open(&capture_handle, snd_device_in, SND_PCM_STREAM_CAPTURE, 0)) < 0) {
-
 
108
    fprintf(stderr, "cannot open input audio device %s: %s\n", snd_device_out, snd_strerror(err));
-
 
109
    exit(1);
-
 
110
}
-
 
111
 
-
 
112
configure_alsa_audio(snd_device_in,  channels);
-
 
113
configure_alsa_audio(snd_device_out, channels);
-
 
114
 
-
 
115
restarting = 1;
-
 
116
 
-
 
117
while (1) {
-
 
118
    frame_size = channels * (bits / 8);
36
		random = fopen("/dev/urandom","r");
119
    frames = buffer_size / frame_size;
-
 
120
 
-
 
121
    if (restarting) {
-
 
122
        restarting = 0;
-
 
123
        /* drop any output we might got and stop */
-
 
124
        snd_pcm_drop(capture_handle);
-
 
125
        snd_pcm_drop(playback_handle);
-
 
126
        /* prepare for use */
-
 
127
        snd_pcm_prepare(capture_handle);
-
 
128
        snd_pcm_prepare(playback_handle);
-
 
129
 
-
 
130
    /* fill the whole output buffer */
-
 
131
    for (i = 0; i < fragments; i += 1)
-
 
132
    snd_pcm_writei(playback_handle, rdbuf, frames);
-
 
133
    }
-
 
134
 
-
 
135
    while ((inframes = snd_pcm_readi(capture_handle, rdbuf, frames)) < 0) {
-
 
136
        if (inframes == -EAGAIN)
-
 
137
            continue;
-
 
138
    // by the way, writing to terminal emulator is costly if you use
-
 
139
    // bad emulators like gnome-terminal, so don't do this.
-
 
140
        fprintf(stderr, "Input buffer overrun\n");
-
 
141
        restarting = 1;
-
 
142
        snd_pcm_prepare(capture_handle);
-
 
143
    }
-
 
144
    if (inframes != frames)
-
 
145
        fprintf(stderr, "Short read from capture device: %d, expecting %d\n", inframes, frames);
-
 
146
 
-
 
147
    /* now processes the frames */
-
 
148
    do_something(rdbuf, inframes);
-
 
149
 
-
 
150
    while ((outframes = snd_pcm_writei(playback_handle, rdbuf, inframes)) < 0) {
-
 
151
        if (outframes == -EAGAIN)
-
 
152
            continue;
-
 
153
        fprintf(stderr, "Output buffer underrun\n");
-
 
154
        restarting = 1;
-
 
155
        snd_pcm_prepare(playback_handle);
-
 
156
    }
-
 
157
    if (outframes != inframes)
-
 
158
        fprintf(stderr, "Short write to playback device: %d, expecting %d\n", outframes, frames);
37
 
159
 
38
		snd_pcm_hw_params_t *hw_params;
-
 
39
		snd_pcm_sw_params_t *sw_params;
-
 
40
		snd_pcm_sframes_t frames_to_deliver;
-
 
41
		int nfds;
-
 
42
		int err;
-
 
43
		struct pollfd *pfds;
-
 
44
	
-
 
45
		if ((err = snd_pcm_open (&playback_handle, argv[1], SND_PCM_STREAM_PLAYBACK, 0)) < 0) {
-
 
46
			fprintf (stderr, "cannot open audio device %s (%s)\n", 
-
 
47
				 argv[1],
-
 
48
				 snd_strerror (err));
-
 
49
			exit (1);
-
 
50
		}
-
 
51
		   
-
 
52
		if ((err = snd_pcm_hw_params_malloc (&hw_params)) < 0) {
-
 
53
			fprintf (stderr, "cannot allocate hardware parameter structure (%s)\n",
-
 
54
				 snd_strerror (err));
-
 
55
			exit (1);
-
 
56
		}
-
 
57
				 
-
 
58
		if ((err = snd_pcm_hw_params_any (playback_handle, hw_params)) < 0) {
-
 
59
			fprintf (stderr, "cannot initialize hardware parameter structure (%s)\n",
-
 
60
				 snd_strerror (err));
-
 
61
			exit (1);
-
 
62
		}
-
 
63
	
-
 
64
		if ((err = snd_pcm_hw_params_set_access (playback_handle, hw_params, SND_PCM_ACCESS_RW_INTERLEAVED)) < 0) {
-
 
65
			fprintf (stderr, "cannot set access type (%s)\n",
-
 
66
				 snd_strerror (err));
-
 
67
			exit (1);
-
 
68
		}
-
 
69
	
-
 
70
		if ((err = snd_pcm_hw_params_set_format (playback_handle, hw_params, SND_PCM_FORMAT_S16_LE)) < 0) {
-
 
71
			fprintf (stderr, "cannot set sample format (%s)\n",
-
 
72
				 snd_strerror (err));
-
 
73
			exit (1);
-
 
74
		}
-
 
75
 
-
 
76
		exact_rate = rate;
-
 
77
		if ((err = snd_pcm_hw_params_set_rate_near (playback_handle, hw_params, &exact_rate, 0)) < 0) {
-
 
78
			fprintf (stderr, "cannot set sample rate (%s)\n",
-
 
79
				 snd_strerror (err));
-
 
80
			exit (1);
-
 
81
		}
-
 
82
 
160
 
83
	
161
	
84
		if ((err = snd_pcm_hw_params_set_channels (playback_handle, hw_params, 2)) < 0) {
-
 
85
			fprintf (stderr, "cannot set channel count (%s)\n",
-
 
86
				 snd_strerror (err));
-
 
87
			exit (1);
-
 
88
		}
-
 
89
	
-
 
90
		if ((err = snd_pcm_hw_params (playback_handle, hw_params)) < 0) {
-
 
91
			fprintf (stderr, "cannot set parameters (%s)\n",
-
 
92
				 snd_strerror (err));
-
 
93
			exit (1);
-
 
94
		}
-
 
95
	
-
 
96
		snd_pcm_hw_params_free (hw_params);
162
		snd_pcm_close(snd_device_out);
97
	
-
 
98
		/* tell ALSA to wake us up whenever 4096 or more frames
-
 
99
		   of playback data can be delivered. Also, tell
-
 
100
		   ALSA that we'll start the device ourselves.
-
 
101
		*/
-
 
102
	
-
 
103
		if ((err = snd_pcm_sw_params_malloc (&sw_params)) < 0) {
-
 
104
			fprintf (stderr, "cannot allocate software parameters structure (%s)\n",
-
 
105
				 snd_strerror (err));
-
 
106
			exit (1);
-
 
107
		}
-
 
108
		if ((err = snd_pcm_sw_params_current (playback_handle, sw_params)) < 0) {
-
 
109
			fprintf (stderr, "cannot initialize software parameters structure (%s)\n",
-
 
110
				 snd_strerror (err));
-
 
111
			exit (1);
-
 
112
		}
-
 
113
		if ((err = snd_pcm_sw_params_set_avail_min (playback_handle, sw_params, 4096)) < 0) {
-
 
114
			fprintf (stderr, "cannot set minimum available count (%s)\n",
-
 
115
				 snd_strerror (err));
-
 
116
			exit (1);
-
 
117
		}
-
 
118
		if ((err = snd_pcm_sw_params_set_start_threshold (playback_handle, sw_params, 0U)) < 0) {
-
 
119
			fprintf (stderr, "cannot set start mode (%s)\n",
-
 
120
				 snd_strerror (err));
-
 
121
			exit (1);
-
 
122
		}
-
 
123
		if ((err = snd_pcm_sw_params (playback_handle, sw_params)) < 0) {
-
 
124
			fprintf (stderr, "cannot set software parameters (%s)\n",
-
 
125
				 snd_strerror (err));
-
 
126
			exit (1);
-
 
127
		}
-
 
128
	
-
 
129
		/* the interface will interrupt the kernel every 4096 frames, and ALSA
-
 
130
		   will wake up this program very soon after that.
-
 
131
		*/
-
 
132
	
-
 
133
		if ((err = snd_pcm_prepare (playback_handle)) < 0) {
-
 
134
			fprintf (stderr, "cannot prepare audio interface for use (%s)\n",
-
 
135
				 snd_strerror (err));
-
 
136
			exit (1);
-
 
137
		}
-
 
138
	
-
 
139
		while (1) {
-
 
140
	
-
 
141
			/* wait till the interface is ready for data, or 1 second
-
 
142
			   has elapsed.
-
 
143
			*/
-
 
144
	
-
 
145
			if ((err = snd_pcm_wait (playback_handle, 1000)) < 0) {
-
 
146
			        fprintf (stderr, "poll failed (%s)\n", strerror (errno));
-
 
147
			        break;
-
 
148
			}	           
-
 
149
	
-
 
150
			/* find out how much space is available for playback data */
-
 
151
	
-
 
152
			if ((frames_to_deliver = snd_pcm_avail_update (playback_handle)) < 0) {
-
 
153
				if (frames_to_deliver == -EPIPE) {
-
 
154
					fprintf (stderr, "an xrun occured\n");
-
 
155
					break;
-
 
156
				} else {
-
 
157
					fprintf (stderr, "unknown ALSA avail update return value (%d)\n", 
-
 
158
						 frames_to_deliver);
-
 
159
					break;
-
 
160
				}
-
 
161
			}
-
 
162
	
-
 
163
			frames_to_deliver = frames_to_deliver > 4096 ? 4096 : frames_to_deliver;
-
 
164
	
-
 
165
			/* deliver the data */
-
 
166
	
-
 
167
			if (playback_callback (frames_to_deliver) != frames_to_deliver) {
-
 
168
			        fprintf (stderr, "playback callback failed\n");
-
 
169
				break;
-
 
170
			}
-
 
171
		}
-
 
172
	
-
 
173
		snd_pcm_close (playback_handle);
163
		snd_pcm_close(snd_device_in);
174
		fclose(random);
-
 
175
		exit (0);
164
		exit (0);
176
	}
165
}
177
 
166