1 /* Sysdep Irix_al sound dsp driver
2
3 Copyright 2001 by Brandon Corey
4
5 This file and the acompanying files in this directory are free software;
6 you can redistribute them and/or modify them under the terms of the GNU
7 Library General Public License as published by the Free Software Foundation;
8 either version 2 of the License, or (at your option) any later version.
9
10 These files are distributed in the hope that they will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Library General Public License for more details.
14
15 You should have received a copy of the GNU Library General Public
16 License along with these files; see the file COPYING.LIB. If not,
17 write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, USA.
19
20 Addendum: This file may also be used under the terms of the MAME license, by
21 permission of Brandon Corey. (For the text of the license, see
22 http://www.mame.net/readme.html.)
23 */
24 /* Changelog
25 Version 0.1, April 15, 2001
26 - initial release
27 Version 0.2, April 15, 2001
28 - added sample frequency code so that a sample frequency other than the
29 system default is usable
30 */
31
32 /* Notes/Future
33 1) I've only compiled this with MIPSPro, although it should work with gcc.
34 If someone could test that and email me, I'd appreciate it.
35 2) Will add mixer support for the next version
36 3) Use IRIX_DEBUG and IRIX_DEBUG_VERBOSE for Extra Info
37 4) Use FORCEMONO to force MONO output
38 5) Use FORCE8BIT to force 8 Bit output
39
40 Email: brandon@blackboxcentral.com
41 */
42
43 /* #define IRIX_DEBUG */
44 /* #define IRIX_DEBUG_VERBOSE */
45 /* #define FORCEMONO */
46 /* #define FORCE8BIT */
47 /* #define SYSDEP_DSP_IRIX */
48
49 #ifdef SYSDEP_DSP_IRIX
50 #include <stdlib.h>
51 #include <unistd.h>
52 #include <sys/ioctl.h>
53 #include <dmedia/audio.h>
54 #include "sysdep/sysdep_dsp.h"
55 #include "sysdep/sysdep_dsp_priv.h"
56 #include "sysdep/plugin_manager.h"
57
58 /* our per instance private data struct */
59 struct irix_dsp_priv_data {
60 ALport devAudio;
61 ALconfig devAudioConfig;
62 unsigned int buffer_samples;
63 int sampwidth;
64 int sampchan;
65 int port_status;
66 };
67
68 /* public methods prototypes (static but exported through the sysdep_dsp or
69 plugin struct) */
70 static void *irix_dsp_create(const void *flags);
71 static void irix_dsp_destroy(struct sysdep_dsp_struct *dsp);
72 static int irix_dsp_get_freespace(struct sysdep_dsp_struct *dsp);
73 static int irix_dsp_write(struct sysdep_dsp_struct *dsp, unsigned char *data,
74 int count);
75
76 /* public variables */
77 const struct plugin_struct sysdep_dsp_irix = {
78 "irix_al",
79 "sysdep_dsp",
80 "IrixAL DSP plugin",
81 NULL, /* no options */
82 NULL, /* no init */
83 NULL, /* no exit */
84 irix_dsp_create,
85 3 /* high priority as direct device access */
86 };
87
88
89 /* public methods (static but exported through the sysdep_dsp or plugin
90 struct) */
irix_dsp_create(const void * flags)91 static void *irix_dsp_create(const void *flags)
92 {
93 ALpv pvs[4];
94 long tempbits, tempchan;
95 long oldrate;
96 long ratechange = 0;
97 struct irix_dsp_priv_data *priv = NULL;
98 struct sysdep_dsp_struct *dsp = NULL;
99 const struct sysdep_dsp_create_params *params = flags;
100
101 /* allocate the dsp struct */
102 if (!(dsp = calloc(1, sizeof(struct sysdep_dsp_struct))))
103 {
104 fprintf(stderr, "Error: malloc failed for struct sysdep_dsp_struct.\n");
105 return NULL;
106 }
107
108 /* alloc private data */
109 if(!(priv = calloc(1, sizeof(struct irix_dsp_priv_data))))
110 {
111 fprintf(stderr, "Error: malloc failed for struct irix_dsp_priv_data.\n");
112 irix_dsp_destroy(dsp);
113 return NULL;
114 }
115
116 /* fill in the functions and some data */
117 priv->port_status = -1;
118 dsp->_priv = priv;
119 dsp->get_freespace = irix_dsp_get_freespace;
120 dsp->write = irix_dsp_write;
121 dsp->destroy = irix_dsp_destroy;
122 dsp->hw_info.type = params->type;
123 dsp->hw_info.samplerate = params->samplerate;
124
125 /* open the sound device */
126 pvs[0].param = AL_MAX_PORTS;
127 pvs[1].param = AL_UNUSED_PORTS;
128 if (alGetParams(AL_SYSTEM,pvs,2) < 0) {
129 fprintf(stderr, "alGetParams failed: %s\n", alGetErrorString(oserror()));
130 irix_dsp_destroy(dsp);
131 return NULL;
132 }
133
134 if (pvs[1].value.i < 1) {
135 fprintf(stderr, "No available audio ports.\n");
136 irix_dsp_destroy(dsp);
137 return NULL;
138 }
139
140 pvs[0].param = AL_RATE;
141 if (alGetParams(AL_DEFAULT_OUTPUT,pvs,1) < 0) {
142 fprintf(stderr, "alGetParams failed: %s\n", alGetErrorString(oserror()));
143 irix_dsp_destroy(dsp);
144 return NULL;
145 }
146
147 /* If samplerate is different than systems, override */
148 oldrate = pvs[0].value.i;
149 if (pvs[0].value.i != dsp->hw_info.samplerate)
150 {
151 ratechange = 1;
152 fprintf(stderr, "System sample rate was %dHz, forcing %dHz instead.\n",
153 pvs[0].value.i, dsp->hw_info.samplerate);
154 }
155
156 /* create a clean config descriptor */
157 if ( (priv->devAudioConfig = alNewConfig() ) == (ALconfig) NULL ) {
158 fprintf(stderr, "Cannot get a Descriptor. Exiting..\n");
159 irix_dsp_destroy(dsp);
160 return NULL;
161 }
162
163 #ifdef FORCE8BIT
164 dsp->hw_info.type &= ~SYSDEP_DSP_16BIT;
165 #endif
166 #ifdef FORCEMONO
167 dsp->hw_info.type &= ~SYSDEP_DSP_STEREO;
168 #endif
169
170 priv->buffer_samples = dsp->hw_info.samplerate * params->bufsize;
171
172 tempchan = (dsp->hw_info.type & SYSDEP_DSP_STEREO)? 2:1;
173 tempbits = (dsp->hw_info.type & SYSDEP_DSP_16BIT)? 2:1;
174
175 priv->buffer_samples = priv->buffer_samples * tempchan;
176
177 priv->sampwidth = tempbits;
178 priv->sampchan = tempchan;
179
180 #ifdef IRIX_DEBUG
181 fprintf(stderr, "Sample Rate Requested: %d\n", dsp->hw_info.samplerate);
182 fprintf(stderr, "Buffer Size Requested: %d\n", priv->buffer_samples);
183 #endif
184
185 fprintf(stderr, "Setting sound to %dHz, %d bit, %s\n",dsp->hw_info.samplerate,
186 tempbits * 8, (tempchan == 2) ? "stereo" : "mono");
187
188 /* channel specific audio parameters */
189 alSetChannels(priv->devAudioConfig, tempchan); /* channels */
190 alSetQueueSize(priv->devAudioConfig,(long) priv->buffer_samples); /* buffer size */
191 alSetSampFmt(priv->devAudioConfig, AL_SAMPFMT_TWOSCOMP); /* BTC */
192 alSetWidth(priv->devAudioConfig, tempbits); /* bitrate */
193
194 /* global audio parameters */
195 pvs[0].param = AL_MASTER_CLOCK;
196 pvs[0].value.i = AL_CRYSTAL_MCLK_TYPE;
197 pvs[1].param = AL_RATE;
198 pvs[1].value.i = dsp->hw_info.samplerate;
199 if (alSetParams(AL_DEFAULT_OUTPUT,pvs,2) < 0) {
200 fprintf(stderr, "Error: Cannot configure the sound system.\n");
201 irix_dsp_destroy(dsp);
202 return(NULL);
203 }
204
205 /* Get new sample rate */
206 pvs[0].param = AL_RATE;
207 if (alGetParams(AL_DEFAULT_OUTPUT,pvs,1) < 0) {
208 fprintf(stderr, "failed\n");
209 irix_dsp_destroy(dsp);
210 return NULL;
211 }
212
213 /* Verify rate was changed */
214 if ((ratechange == 1) && (oldrate == pvs[0].value.i))
215 fprintf(stderr, "Error changing sample rate, using default of: %dHz.\n",
216 pvs[0].value.i);
217
218 /* Open the audio port with the parameters we setup */
219 if ( (priv->devAudio=alOpenPort("audio_fd","w",priv->devAudioConfig) ) == (ALport) NULL ) {
220 fprintf(stderr, "Error: Cannot get an audio channel descriptor.\n");
221 irix_dsp_destroy(dsp);
222 return NULL;
223 }
224
225 /* since we don't have FD's with DMEDIA, we use this to inform us of success */
226 priv->port_status = 0;
227
228 return dsp;
229 }
230
irix_dsp_destroy(struct sysdep_dsp_struct * dsp)231 static void irix_dsp_destroy(struct sysdep_dsp_struct *dsp)
232 {
233 struct irix_dsp_priv_data *priv = dsp->_priv;
234
235 #ifdef IRIX_DEBUG
236 fprintf(stderr, "Destroying sound channel.\n");
237 #endif
238
239 if(priv)
240 {
241 if(priv->port_status >= 0) alClosePort(priv->devAudio);
242 alFreeConfig(priv->devAudioConfig);
243
244 free(priv);
245 }
246 free(dsp);
247 }
248
249
irix_dsp_get_freespace(struct sysdep_dsp_struct * dsp)250 static int irix_dsp_get_freespace(struct sysdep_dsp_struct *dsp)
251 {
252 struct irix_dsp_priv_data *priv = dsp->_priv;
253
254 return alGetFillable(priv->devAudio);
255 }
256
257
irix_dsp_write(struct sysdep_dsp_struct * dsp,unsigned char * data,int count)258 static int irix_dsp_write(struct sysdep_dsp_struct *dsp, unsigned char *data,
259 int count)
260 {
261 unsigned char *outbuf=data;
262 int result;
263 struct irix_dsp_priv_data *priv = dsp->_priv;
264 int playcnt;
265 int maxsize;
266
267 maxsize = alGetFillable(priv->devAudio);
268
269 /* count = count * priv->sampchan; */
270
271 if (count <= maxsize) playcnt = count;
272 else playcnt = maxsize;
273
274 outbuf += (priv->sampwidth - 1);
275
276 for (;outbuf<(data+count);outbuf+=priv->sampwidth) *outbuf ^= 0x80;
277
278 result = alWriteFrames(priv->devAudio, (void *)data, playcnt);
279
280 if (result < 0) {
281 fprintf(stderr, "Error %d: failure writing to irix stream\n",oserror());
282 return -1;
283 }
284
285
286 #ifdef IRIX_DEBUG_VERBOSE
287 fprintf(stderr, "Wrote %d samples OK.\n",playcnt);
288 #endif
289
290 /* return playcnt / priv->sampchan; */
291 return playcnt;
292 }
293
294 #endif /* ifdef SYSDEP_DSP_IRIX */
295
296