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