Subversion Repositories svnkaklik

Rev

Details | Last modification | View Log

Rev Author Line No. Line
516 kaklik 1
	#include <stdio.h>
2
	#include <stdlib.h>
519 kaklik 3
	#include <errno.h>
4
	#include <poll.h>
516 kaklik 5
	#include <alsa/asoundlib.h>
6
 
521 kaklik 7
/* you allocate these in heap */
8
int             restarting;
9
int             fragments = 2;
10
int             channels = 1;
11
int             buffer_size = 512;
12
int             sample_rate = 48000;
13
int             frame_size = 1024;
14
int             bits = 16;
519 kaklik 15
 
521 kaklik 16
char           *snd_device_in  = "plughw:0,0";
17
char           *snd_device_out = "plughw:0,0";
18
snd_pcm_t      *playback_handle;
19
snd_pcm_t      *capture_handle;
519 kaklik 20
 
521 kaklik 21
int err;
519 kaklik 22
 
521 kaklik 23
int configure_alsa_audio(snd_pcm_t *device, int channels)
24
{
25
    snd_pcm_hw_params_t *hw_params;
26
    int                 err;
27
    int                 tmp;
519 kaklik 28
 
521 kaklik 29
    snd_pcm_uframes_t   frames;
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",
40
                 snd_strerror(err));
41
        return 1;
42
    }
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
    }
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
    }
71
 
72
    if ((err = snd_pcm_hw_params_set_periods_near(device, hw_params, &fragments, 0)) < 0) {
73
        fprintf(stderr, "Error setting # fragments to %d: %s\n", fragments,
74
                snd_strerror(err));
75
        return 1;
76
    }
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
    }
94
    return 0;
95
}
516 kaklik 96
 
521 kaklik 97
main (void)
98
{
519 kaklik 99
 
521 kaklik 100
int i,frames, inframes, outframes, frame_size;
519 kaklik 101
 
521 kaklik 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
}
519 kaklik 106
 
521 kaklik 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
}
519 kaklik 111
 
521 kaklik 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);
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);
159
 
160
 
516 kaklik 161
 
521 kaklik 162
		snd_pcm_close(snd_device_out);
163
		snd_pcm_close(snd_device_in);
516 kaklik 164
		exit (0);
521 kaklik 165
}
519 kaklik 166