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
39 char * drvname
; /* driver name */
40 int (*open
)(char *, int, int); /* open function */
41 void (*write
)(int *, int); /* write frame function */
42 void (*close
)(void); /* close function */
43 char * deffile
; /* default file or device */
44 int max_channels
; /* maximum channels (0, unlimited) */
47 struct ss_outdrv
* drv
=NULL
;
57 static arts_stream_t arts
;
59 static int d_arts_open(char * file
, int freq
, int n_channels
)
64 (arts
=arts_play_stream(freq
, 16, n_channels
, "annhell")))
71 static void d_arts_write(int frame
[], int size
)
73 arts_write(arts
, frame
, size
);
77 static void d_arts_close(void)
82 struct ss_outdrv outdrv_arts
=
83 { "arts", d_arts_open
, d_arts_write
, d_arts_close
, NULL
, 2 };
85 #else /* CONFOPT_ARTS */
87 struct ss_outdrv outdrv_arts
=
88 { "arts", NULL
, NULL
, NULL
, NULL
, 2 };
90 #endif /* CONFOPT_ARTS */
92 /************************************************/
101 static int d_esd_open(char * file
, int freq
, int n_channels
)
106 format
= ESD_STREAM
| ESD_PLAY
| ESD_BITS16
;
107 format
|= n_channels
== 2 ? ESD_STEREO
: ESD_MONO
;
109 if(esd_open_sound(file
) >= 0 &&
110 (esd_fd
=esd_play_stream_fallback(format
, freq
, NULL
, "annhell")) >= 0)
116 static void d_esd_write(int frame
[], int size
)
118 write(esd_fd
, frame
, size
);
122 static void d_esd_close(void)
127 struct ss_outdrv outdrv_esd
=
128 { "esd", d_esd_open
, d_esd_write
, d_esd_close
, NULL
, 2 };
130 #else /* CONFOPT_ESD */
132 struct ss_outdrv outdrv_esd
=
133 { "esd", NULL
, NULL
, NULL
, NULL
, 2 };
135 #endif /* CONFOPT_ESD */
137 /************************************************/
141 #include <dmedia/audio.h>
146 static int d_sgi_open(char * file
, int freq
, int n_channels
)
151 p
[0].param
=AL_MASTER_CLOCK
;
152 p
[0].value
.i
=AL_CRYSTAL_MCLK_TYPE
;
154 p
[1].value
.ll
=alDoubleToFixed((double) freq
);
156 if((ac
=alNewConfig()))
158 if(alSetChannels(ac
, n_channels
) >= 0 &&
159 alSetWidth(ac
, AL_SAMPLE_16
) >= 0 &&
160 alSetSampFmt(ac
, AL_SAMPFMT_TWOSCOMP
) >= 0 &&
161 alSetQueueSize(ac
, 2048) >=0 &&
162 alSetDevice(ac
, AL_DEFAULT_OUTPUT
) >= 0 &&
163 alSetParams(alGetDevice(ac
), p
, 2) >= 0 &&
164 (ap
=alOpenPort("annhell", "w", ac
)))
172 static int d_sgi_write(int frame
[], int size
)
174 alWriteFrames(ap
, frame
, 1);
178 static int d_sgi_close(void)
184 struct ss_outdrv outdrv_sgi
=
185 { "sgi", d_sgi_open
, d_sgi_write
, d_sgi_close
, NULL
, 0 };
187 #else /* CONFOPT_SGI */
189 struct ss_outdrv outdrv_sgi
=
190 { "sgi", NULL
, NULL
, NULL
, NULL
, 0 };
193 #endif /* CONFOPT_SGI */
195 /************************************************/
197 #ifdef CONFOPT_LINUX_OSS
200 #include <sys/ioctl.h>
201 #include <linux/soundcard.h>
203 static int is_little_endian(void)
206 unsigned char * c
=(unsigned char *) &s
;
213 static int d_oss_open(char * file
, int freq
, int n_channels
)
218 fr
=(2 << 16)|(1 << 10);
219 st
=n_channels
== 2 ? 1 : 0;
220 fm
=is_little_endian() ? AFMT_S16_LE
: AFMT_S16_BE
;
222 if((oss_fd
=open(file
, O_WRONLY
)) >= 0)
224 if(ioctl(oss_fd
, SNDCTL_DSP_SETFRAGMENT
, &fr
) >= 0 &&
225 ioctl(oss_fd
, SNDCTL_DSP_RESET
, 0) >= 0 &&
226 ioctl(oss_fd
, SNDCTL_DSP_SPEED
, &freq
) >= 0 &&
227 ioctl(oss_fd
, SNDCTL_DSP_STEREO
, &st
) >= 0 &&
228 ioctl(oss_fd
, SNDCTL_DSP_SETFMT
, &fm
) >= 0)
236 static void d_oss_write(int frame
[], int size
)
238 write(oss_fd
, frame
, size
);
242 static void d_oss_close(void)
247 struct ss_outdrv outdrv_oss
=
248 { "oss", d_oss_open
, d_oss_write
, d_oss_close
, "/dev/dsp", 2 };
250 #else /* CONFOPT_LINUX_OSS */
252 struct ss_outdrv outdrv_oss
=
253 { "oss", NULL
, NULL
, NULL
, NULL
, 2 };
255 #endif /* CONFOPT_LINUX_OSS */
257 /************************************************/
259 static void fput16(short int i
, FILE * f
)
261 fputc(i
& 0x00ff, f
);
262 fputc((i
& 0xff00) >> 8, f
);
266 static void fput32(int i
, FILE * f
)
268 fputc(i
& 0x000000ff, f
);
269 fputc((i
& 0x0000ff00) >> 8, f
);
270 fputc((i
& 0x00ff0000) >> 16, f
);
271 fputc((i
& 0xff000000) >> 24, f
);
274 static FILE * wav_fd
;
275 static int wav_frames
;
277 static int d_wav_open(char * file
, int freq
, int n_channels
)
279 if((wav_fd
=fopen(file
, "w")) == NULL
) return(0);
281 /* write wav header */
283 fwrite("RIFF", 1, 4, wav_fd
);
284 fput32(36, wav_fd
); /* first checkpoint (offset: 4) */
285 fwrite("WAVE", 1, 4, wav_fd
);
286 fwrite("fmt ", 1, 4, wav_fd
);
287 fput32(16, wav_fd
); /* chunk size */
288 fput16(1, wav_fd
); /* 1: uncompressed PCM */
289 fput16(n_channels
, wav_fd
); /* # of channels */
290 fput32(freq
, wav_fd
); /* sample rate */
291 fput32(freq
* n_channels
* 2, wav_fd
); /* bytes per second */
292 fput16(n_channels
* 2, wav_fd
); /* 'block align' */
293 fput16(16, wav_fd
); /* 16 bits per sample */
294 fwrite("data", 1, 4, wav_fd
);
295 fput32(0, wav_fd
); /* second checkpoint (offset: 40) */
303 static void d_wav_write(int frame
[], int size
)
307 size
/= sizeof(short int);
309 for(n
=0;n
< size
;n
++)
310 fput16(frame
[n
], wav_fd
);
316 static void d_wav_close(void)
318 /* rewind file and write total size */
319 fseek(wav_fd
, 4, SEEK_SET
);
320 fput32((wav_frames
* n_channels
) + 36, wav_fd
);
322 fseek(wav_fd
, 40, SEEK_SET
);
323 fput32(wav_frames
* n_channels
, wav_fd
);
328 struct ss_outdrv outdrv_wav
=
329 { "wav", d_wav_open
, d_wav_write
, d_wav_close
, "output.wav", 0 };
331 static struct ss_outdrvs
[] = {
340 int ss_outdev(char * drv
, char * file
, int freq
, int n_channels
)
348 /* parent; return immediately */
355 /* closes the writing part of the pipe */
358 /* detaches from group */
361 /* find the appropriate driver */
362 for(n
=0;drivers
[n
].drvname
!= NULL
;n
++)
364 if(drv
== NULL
|| strcmp(drv
, drivers
[n
].drvname
) == 0)
366 if(drivers
[n
].func(p
[0],
367 file
? file
: drivers
[n
].deffile
,