1 /*
2 * snd_unix.c
3 *
4 * UNIX(tm) sound interface (mainly OSS)
5 */
6
7 /* $Id: snd_unix.c,v 1.4 2000/06/25 17:04:32 nyef Exp $ */
8
9 #include <stdio.h>
10 #include <sys/types.h>
11 #include <sys/stat.h>
12 #include <fcntl.h>
13 #include <sys/ioctl.h>
14 #include <unistd.h>
15
16 #include "ui.h"
17 #include "snd.h"
18 #include "unixdep.h"
19
20 #ifdef SYSTEM_LINUX
21 #include <sys/soundcard.h>
22 #define SOUND_DEVICE "/dev/dsp"
23 #endif
24
25 #ifdef SYSTEM_FREEBSD
26 #include <sys/soundcard.h>
27 #define SOUND_DEVICE "/dev/dsp"
28 #endif
29
30 #ifdef SYSTEM_NETBSD
31 #include <sys/audioio.h>
32 #define SOUND_DEVICE "/dev/sound"
33 #endif
34
35 #ifdef SYSTEM_OPENBSD
36 #error No sound support on OpenBSD systems yet
37 #endif
38
39 unsigned char final_wave[2048];
40 int waveptr;
41 int wavflag;
42 int sound_fd;
43
snd_output_4_waves(int samples,u8 * wave1,u8 * wave2,u8 * wave3,u8 * wave4)44 void snd_output_4_waves(int samples, u8 *wave1, u8 *wave2, u8 *wave3, u8 *wave4)
45 {
46 int i;
47
48 if (sound_fd) {
49 for (i = 0; i < samples; i++) {
50 final_wave[waveptr] = (wave1[i] + wave2[i] +
51 wave3[i] + wave4[i]) >> 2;
52 waveptr++;
53 if (waveptr == 2048) {
54 waveptr = 0;
55 wavflag = 2;
56 } else if (waveptr == 1024) {
57 wavflag = 1;
58 }
59 }
60
61 if (wavflag) {
62 if (write(sound_fd, &final_wave[(wavflag - 1) << 10], 1024) < 1024) {
63 deb_printf("wrote less than 1024 bytes\n");
64 }
65 wavflag = 0;
66 }
67 }
68 }
69
snd_init(void)70 void snd_init(void)
71 {
72 sound_fd = 0;
73 }
74
75 #ifdef SYSTEM_NETBSD
snd_open(int samples_per_sync,int sample_rate)76 int snd_open(int samples_per_sync, int sample_rate)
77 {
78 int result;
79 audio_info_t info;
80
81 waveptr = 0;
82 wavflag = 0;
83
84 printf("opening "SOUND_DEVICE"...");
85 sound_fd = open(SOUND_DEVICE, O_WRONLY);
86 if (sound_fd < 0) {
87 perror("failed");
88 sound_fd = 0;
89 return 0;
90 } else {
91 printf("done.\n");
92 }
93
94 AUDIO_INITINFO(&info);
95
96 printf("setting unsigned 8-bit format...");
97 info.play.encoding = AUDIO_ENCODING_ULINEAR;
98 /* this doesn't work for me, so ignore results */
99 result = ioctl(sound_fd, AUDIO_SETINFO, &info);
100 if (result < 0)
101 {
102 perror("warning: unsigned linear mode failed, using signed");
103 info.play.encoding = AUDIO_ENCODING_SLINEAR;
104 }
105
106 printf("setting sound rate to %dHz...", sample_rate);
107 info.play.sample_rate = sample_rate;
108
109 /* 8 bits per sample */
110 info.play.precision = 8;
111
112 printf("setting mono mode...");
113 info.play.channels = 1;
114 info.mode = AUMODE_PLAY_ALL;
115
116 /* "frag size" */
117 info.blocksize = 1 << 8;
118
119 /* "number of frags", hiwater mark */
120 info.hiwat = 8;
121
122 result = ioctl(sound_fd, AUDIO_SETINFO, &info);
123 if (result < 0) {
124 perror("initializing sound failed");
125 close(sound_fd);
126 sound_fd = 0;
127 return 0;
128 } else {
129 printf("done.\n");
130 }
131
132 return 1;
133 }
134
135 #else
snd_open(int samples_per_sync,int sample_rate)136 int snd_open(int samples_per_sync, int sample_rate)
137 {
138 int tmp;
139 int result;
140 int sound_rate;
141 int sound_frag;
142
143 waveptr = 0;
144 wavflag = 0;
145
146 printf("opening "SOUND_DEVICE"...");
147 sound_fd = open(SOUND_DEVICE, O_WRONLY);
148 if (sound_fd < 0) {
149 perror("failed");
150 sound_fd = 0;
151 return 0;
152 } else {
153 printf("done.\n");
154 }
155
156 printf("setting unsigned 8-bit format...");
157 tmp = AFMT_U8;
158 result = ioctl(sound_fd, SNDCTL_DSP_SETFMT, &tmp);
159 if (result < 0) {
160 perror("failed");
161 close(sound_fd);
162 sound_fd = 0;
163 return 0;
164 } else {
165 printf("done.\n");
166 }
167
168 printf("setting mono mode...");
169 tmp = 0;
170 result = ioctl(sound_fd, SNDCTL_DSP_STEREO, &tmp);
171 if (result < 0) {
172 perror("failed");
173 close(sound_fd);
174 sound_fd = 0;
175 return 0;
176 } else {
177 printf("done.\n");
178 }
179
180 sound_rate = sample_rate;
181 printf("setting sound rate to %dHz...", sound_rate);
182 result = ioctl(sound_fd, SNDCTL_DSP_SPEED, &sound_rate);
183 if (result < 0) {
184 perror("failed");
185 close(sound_fd);
186 sound_fd = 0;
187 return 0;
188 } else {
189 printf("got %dHz...done.\n", sound_rate);
190 }
191
192 /* high word of sound_frag is number of frags, low word is frag size */
193 sound_frag = 0x00080008;
194 printf("setting soundfrags...");
195 result = ioctl(sound_fd, SNDCTL_DSP_SETFRAGMENT, &sound_frag);
196 if (result < 0) {
197 perror("failed");
198 close(sound_fd);
199 sound_fd = 0;
200 return 0;
201 } else {
202 printf("done.\n");
203 }
204
205 return 1;
206 }
207 #endif
208
snd_close(void)209 void snd_close(void)
210 {
211 if (sound_fd) {
212 close(sound_fd);
213 }
214 }
215
216 /*
217 * $Log: snd_unix.c,v $
218 * Revision 1.4 2000/06/25 17:04:32 nyef
219 * fixed to automatically detect system type
220 *
221 * Revision 1.3 2000/02/14 02:04:13 nyef
222 * addded (untested) support for NetBSD
223 *
224 * Revision 1.2 1999/12/24 16:52:42 nyef
225 * changed to compile clean on FreeBSD
226 *
227 * Revision 1.1 1999/10/31 02:37:58 nyef
228 * Initial revision
229 *
230 */
231