-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathDAC.c
184 lines (159 loc) · 4.45 KB
/
DAC.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
/* DAC.c
* miscellaneous routines for handling sound driver /dev/dsp device
* Jim Jackson
*
* Covered by GNU Public license - see file COPYING
*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <ctype.h>
#include <sys/time.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/soundcard.h>
/* DACopen(device,mode,&samplerate,&fmt,&stereo)
* opens device for mode (r/w) at samplerate samples/sec in 8/16 bit fmt
* and in stereo. Sets these params to best match possible.
*
* getfragsize(fd)
* get fragment size of a DSP buffer
*
* getfreeobufs(fd)
* return number of free output fragment buffers free at moment
*
* getfullibufs(fd)
* return number of full input fragment buffers full at moment
*
* setfragsize(fd,N,bfps,S,afmt,stereo)
* set number of buffers to N and size such that we get aprox bfps buffers
* played per second. S samples per sec of mono/stereo, 8/16 bit samples.
*
* is16bit(fd)
* returns true if file fd is a 16 sound device
*
* isstereo(fd)
* returns true if file fd is a stereo sound device (To Be Done)
*/
/* is16bit(fd) return true if fd is a dsp device supporting 16 bit
* sampling. Return false if not.
*/
is16bit(fd)
int fd;
{
int fmts;
if (ioctl(fd, SNDCTL_DSP_GETFMTS , &fmts) < 0) {
return(0);
}
return(fmts&AFMT_S16_LE);
}
/* getfragsize(fd) return fragsize of DSP buufer for fd
* or return -1 on error.
*/
getfragsize(fd)
int fd;
{
int n;
if (ioctl(fd, SNDCTL_DSP_GETBLKSIZE, &n)<0) return(-1);
return(n);
}
/* getfreeobufs(fd) return number of empty output fragment buffers
* available or return -1 on error.
*/
getfreeobufs(fd)
int fd;
{
int n;
audio_buf_info osp;
if (ioctl(fd,SNDCTL_DSP_GETOSPACE, &osp)<0) return(-1);
return(osp.fragments);
}
/* getfullibufs(fd) return number of full input fragment buffers
* available or return -1 on error.
*/
getfullibufs(fd)
int fd;
{
int n;
count_info isp;
if (ioctl(fd,SNDCTL_DSP_GETIPTR, &isp)<0) return(-1);
return(isp.bytes);
}
/* printibufs(fd) print input audio_buf_info
* return -1 on error.
*/
printibufs(fd)
int fd;
{
int n;
count_info isp;
if (ioctl(fd,SNDCTL_DSP_GETIPTR, &isp)<0) return(-1);
printf("Count Info: bytes=%d, blocks=%d, ptr=%0Xx\n",
isp.bytes, isp.blocks, isp.ptr);
return(0);
}
/* setfragsize(fd,N,bfps,S,afmt,stereo)
* calculate buffer size to ensure aproximately
* bfps buffers per second, then set N buffs of this size
* afmt is 8 or 16 bit samples, stereo is true if 2 chans
* return -1 if error - see errno, else return fragsize
* set.
*/
setfragsize(fd,N,bfps,S,afmt,stereo)
int fd,N,bfps,S,afmt,stereo;
{
int fr,n;
if (N<1) {
errno=EINVAL; return(-1);
}
n=S/bfps; /* n is samplerate / buffers/sec */
for (fr=5; (2<<fr) < n ; fr++) { }
/* adjust for stereo and 16 bits */
fr=(N<<16)+fr+((stereo)?1:0)+((afmt==AFMT_S16_LE)?1:0);
if (ioctl(fd, SNDCTL_DSP_SETFRAGMENT , &fr) < 0) return(-1);
if (ioctl(fd, SNDCTL_DSP_GETBLKSIZE , &n) < 0) return(-1);
return(n);
}
/*
* DACopen(char *fnm, char *mode, int *samples, int *fmt, int *stereo)
*
* open dspfile for read "r" or write "w", and set samples per sec
* as sampling rate - note we get pointer for samples so we can
* return the actual samplerate set.
* If stereo mode is unspecified (-1) then set stereo if possible,
* if fmt is unspecified (AFMT_QUERY) then set 16 bit if possible
* otherwise we set mono and/or 8 bit.
* Actual settings are returned in fmt and stereo.
* return file descriptor or -1 on error.
*/
DACopen(fnm,mode,samples,fmt,stereo)
char *fnm;
char *mode;
int *samples,*fmt,*stereo;
{
int fd;
int m,i;
if (*mode=='r') m=O_RDONLY;
else if (*mode=='w') m=O_WRONLY;
else {
errno=EINVAL; return(-1);
}
if ((fd = open (fnm,m,0)) >= 0) { /* params must be set in this order */
if ((*fmt==AFMT_QUERY) && is16bit(fd)) *fmt=AFMT_S16_LE;
if (ioctl(fd, SNDCTL_DSP_SETFMT, fmt)>=0) {
if (*stereo==-1) {
*stereo=1;
if (ioctl(fd, SNDCTL_DSP_STEREO, stereo)<0) *stereo=0;
}
if (ioctl(fd, SNDCTL_DSP_STEREO, stereo)>=0) {
if (ioctl(fd, SNDCTL_DSP_SPEED, samples)>=0) {
return(fd);
}
}
}
}
return(-1);
}