3 Ann Hell Ex Machina - Music Software
4 Copyright (C) 2005 Angel Ortega <angel@triptico.com>
6 ss_outdev.c - Softsynth output devices
8 This program is free software; you can redistribute it and/or
9 modify it under the terms of the GNU General Public License
10 as published by the Free Software Foundation; either version 2
11 of the License, or (at your option) any later version.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
22 http://www.triptico.com
41 static int o_unsupp(int i
, char * o
, int f
, int n
) { return(0); }
43 /************************************************/
49 static int o_arts(int i
, char * file
, int freq
, int n_channels
)
54 static arts_stream_t arts
;
56 nc
=n_channels
>= 2 ? 2 : 1;
58 if(!arts_init() && (arts
=arts_play_stream(freq
, 16, nc
, "annhell")))
60 n_channels
*= sizeof(short int);
61 nc
*= sizeof(short int);
63 while((n
=read(i
, ibuf
, n_channels
)) > 0)
64 arts_write(arts
, ibuf
, nc
);
74 #else /* CONFOPT_ARTS */
76 #define o_arts o_unsupp
78 #endif /* CONFOPT_ARTS */
80 /************************************************/
87 static int o_esd(int i
, char * file
, int freq
, int n_channels
)
94 nc
=n_channels
>= 2 ? 2 : 1;
96 format
= ESD_STREAM
| ESD_PLAY
| ESD_BITS16
;
97 format
|= nc
== 2 ? ESD_STEREO
: ESD_MONO
;
99 if(esd_open_sound(file
) >= 0 &&
100 (o
=esd_play_stream_fallback(format
, freq
, NULL
, "annhell")) >= 0)
102 n_channels
*= sizeof(short int);
103 nc
*= sizeof(short int);
105 while((n
=read(i
, ibuf
, n_channels
)) > 0)
116 #else /* CONFOPT_ESD */
118 #define o_esd o_unsupp
120 #endif /* CONFOPT_ESD */
122 /************************************************/
126 #include <dmedia/audio.h>
128 static int o_sgi(int i
, char * file
, int freq
, int n_channels
)
136 p
[0].param
=AL_MASTER_CLOCK
;
137 p
[0].value
.i
=AL_CRYSTAL_MCLK_TYPE
;
139 p
[1].value
.ll
=alDoubleToFixed((double) freq
);
141 if((ac
=alNewConfig()))
143 if(alSetChannels(ac
, n_channels
) >= 0 &&
144 alSetWidth(ac
, AL_SAMPLE_16
) >= 0 &&
145 alSetSampFmt(ac
, AL_SAMPFMT_TWOSCOMP
) >= 0 &&
146 alSetQueueSize(ac
, 2048) >=0 &&
147 alSetDevice(ac
, AL_DEFAULT_OUTPUT
) >= 0 &&
148 alSetParams(alGetDevice(ac
), p
, 2) >= 0 &&
149 (ap
=alOpenPort("annhell", "w", ac
)))
151 n_channels
*= sizeof(short int);
153 while((n
=read(i
, ibuf
, n_channels
)) > 0)
154 alWriteFrames(ap
, ibuf
, 1);
167 #else /* CONFOPT_SGI */
169 #define o_sgi o_unsupp
171 #endif /* CONFOPT_SGI */
173 /************************************************/
175 #ifdef CONFOPT_LINUX_OSS
178 #include <sys/ioctl.h>
179 #include <linux/soundcard.h>
181 static int is_little_endian(void)
184 unsigned char * c
=(unsigned char *) &s
;
190 static int o_oss(int i
, char * file
, int freq
, int n_channels
)
194 int o
, n
, nc
, fr
, st
, fm
;
196 nc
=n_channels
>= 2 ? 2 : 1;
197 fr
=(2 << 16)|(1 << 10);
199 fm
=is_little_endian() ? AFMT_S16_LE
: AFMT_S16_BE
;
201 if((o
=open(file
, O_WRONLY
)) >= 0)
203 if(ioctl(o
, SNDCTL_DSP_SETFRAGMENT
, &fr
) >= 0 &&
204 ioctl(o
, SNDCTL_DSP_RESET
, 0) >= 0 &&
205 ioctl(o
, SNDCTL_DSP_SPEED
, &freq
) >= 0 &&
206 ioctl(o
, SNDCTL_DSP_STEREO
, &st
) >= 0 &&
207 ioctl(o
, SNDCTL_DSP_SETFMT
, &fm
) >= 0)
209 n_channels
*= sizeof(short int);
210 nc
*= sizeof(short int);
212 while((n
=read(i
, ibuf
, n_channels
)) > 0)
224 #else /* CONFOPT_LINUX_OSS */
226 #define o_oss o_unsupp
228 #endif /* CONFOPT_LINUX_OSS */
230 /************************************************/
232 static void fput16(short int i
, FILE * f
)
234 fputc(i
& 0x00ff, f
);
235 fputc((i
& 0xff00) >> 8, f
);
239 static void fput32(int i
, FILE * f
)
241 fputc(i
& 0x000000ff, f
);
242 fputc((i
& 0x0000ff00) >> 8, f
);
243 fputc((i
& 0x00ff0000) >> 16, f
);
244 fputc((i
& 0xff000000) >> 24, f
);
248 static int o_wav(int i
, char * file
, int freq
, int n_channels
)
254 if((f
=fopen(file
, "w")) == NULL
) return(0);
256 /* write wav header */
258 fwrite("RIFF",1,4,f
);
259 fput32(36, f
); /* first checkpoint (offset: 4) */
260 fwrite("WAVE",1,4,f
);
261 fwrite("fmt ",1,4,f
);
262 fput32(16,f
); /* chunk size */
263 fput16(1, f
); /* 1: uncompressed PCM */
264 fput16(n_channels
, f
); /* # of channels */
265 fput32(freq
, f
); /* sample rate */
266 fput32(freq
* n_channels
* 2, f
); /* bytes per second */
267 fput16(n_channels
* 2, f
); /* 'block align' */
268 fput16(16, f
); /* 16 bits per sample */
269 fwrite("data",1,4,f
);
270 fput32(0, f
); /* second checkpoint (offset: 40) */
272 n_channels
*= sizeof(short int);
274 for(c
=0;(n
=read(i
, ibuf
, n_channels
)) > 0;c
++)
276 n
/= sizeof(short int);
282 /* rewind file and write total size */
283 fseek(f
, 4, SEEK_SET
);
284 fput32((c
* n_channels
) + 36, f
);
286 fseek(f
, 40, SEEK_SET
);
287 fput32(c
* n_channels
, f
);
299 int (* func
)(int, char *, int, int);
301 { "arts", NULL
, o_arts
},
302 { "esd", NULL
, o_esd
},
303 { "sgi", NULL
, o_sgi
},
304 { "oss", "/dev/dsp", o_oss
},
305 { "wav", "output.wav", o_wav
},
309 int ss_outdev(char * drv
, char * file
, int freq
, int n_channels
)
317 /* parent; return immediately */
326 /* find the appropriate driver */
327 for(n
=0;drivers
[n
].drvname
!= NULL
;n
++)
329 if(drv
== NULL
|| strcmp(drv
, drivers
[n
].drvname
) == 0)
331 if(drivers
[n
].func(p
[0],
332 file
? file
: drivers
[n
].deffile
,