1 /* gAlan - Graphical Audio Language
2 * Copyright (C) 1999 Tony Garnock-Jones
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23 #include <sys/types.h>
24 #include <sys/ioctl.h>
25 #include <sys/soundcard.h>
33 #include "generator.h"
40 #define SIG_LEFT_FRONT_CHANNEL 0
41 #define SIG_RIGHT_FRONT_CHANNEL 1
42 #define SIG_LEFT_REAR_CHANNEL 2
43 #define SIG_RIGHT_REAR_CHANNEL 3
45 #define DEFAULT_FRAGMENT_EXPONENT 12
47 typedef signed short OUTPUTSAMPLE
;
49 typedef struct EmuData
{
50 int audiofd1
, audiofd2
;
55 PRIVATE
int instance_count
= 0;
56 PRIVATE
int audio_fragment_exponent
= DEFAULT_FRAGMENT_EXPONENT
;
58 PRIVATE
void audio_play_fragment(int audiofd
, SAMPLE
*left
, SAMPLE
*right
, int length
) {
60 int buflen
= length
* sizeof(OUTPUTSAMPLE
) * 2;
66 outbuf
= malloc(buflen
);
67 RETURN_UNLESS(outbuf
!= NULL
);
69 for (i
= 0; i
< length
; i
++) {
70 outbuf
[i
<<1] = (OUTPUTSAMPLE
) MIN(MAX(left
[i
] * 32767, -32768), 32767);
71 outbuf
[(i
<<1) + 1] = (OUTPUTSAMPLE
) MIN(MAX(right
[i
] * 32767, -32768), 32767);
74 write(audiofd
, outbuf
, buflen
);
78 PRIVATE
int open_audiofd(int nr
) {
82 audiofd
= open(nr
==0 ? "/dev/dsp" : "/dev/dsp1", O_WRONLY
);
83 RETURN_VAL_UNLESS(audiofd
!= -1, -1);
85 i
= (4 << 16) | audio_fragment_exponent
; /* 4 buffers */
86 RETURN_VAL_UNLESS(ioctl(audiofd
, SNDCTL_DSP_SETFRAGMENT
, &i
) != -1, -1);
89 RETURN_VAL_UNLESS(ioctl(audiofd
, SNDCTL_DSP_SETFMT
, &i
) != -1, -1);
92 RETURN_VAL_UNLESS(ioctl(audiofd
, SNDCTL_DSP_STEREO
, &i
) != -1, -1);
95 RETURN_VAL_UNLESS(ioctl(audiofd
, SNDCTL_DSP_SPEED
, &i
) != -1, -1);
100 PRIVATE
void clock_handler(AClock
*clock
, AClockReason reason
) {
101 EmuData
*data
= clock
->gen
->data
;
105 gdk_input_remove(data
->input_tag
);
106 data
->input_tag
= -1;
110 if (data
->input_tag
== -1)
111 data
->input_tag
= gdk_input_add(data
->audiofd1
, GDK_INPUT_WRITE
,
112 (GdkInputFunction
) gen_clock_mainloop
, NULL
);
116 g_message("Unreachable code reached (emu_output)... reason = %d", reason
);
121 PRIVATE
void realtime_handler(Generator
*g
, AEvent
*event
) {
122 EmuData
*data
= g
->data
;
124 switch (event
->kind
) {
126 SAMPLE
*lf_buf
, *rf_buf
, *lr_buf
, *rr_buf
;
127 int bufbytes
= event
->d
.integer
* sizeof(SAMPLE
);
129 lf_buf
= safe_malloc(bufbytes
);
130 rf_buf
= safe_malloc(bufbytes
);
131 lr_buf
= safe_malloc(bufbytes
);
132 rr_buf
= safe_malloc(bufbytes
);
134 if (!gen_read_realtime_input(g
, SIG_LEFT_FRONT_CHANNEL
, -1, lf_buf
, event
->d
.integer
))
135 memset(lf_buf
, 0, bufbytes
);
137 if (!gen_read_realtime_input(g
, SIG_RIGHT_FRONT_CHANNEL
, -1, rf_buf
, event
->d
.integer
))
138 memset(rf_buf
, 0, bufbytes
);
140 if (!gen_read_realtime_input(g
, SIG_LEFT_REAR_CHANNEL
, -1, lr_buf
, event
->d
.integer
))
141 memset(lr_buf
, 0, bufbytes
);
143 if (!gen_read_realtime_input(g
, SIG_RIGHT_REAR_CHANNEL
, -1, rr_buf
, event
->d
.integer
))
144 memset(rr_buf
, 0, bufbytes
);
146 audio_play_fragment(data
->audiofd1
, lf_buf
, rf_buf
, event
->d
.integer
);
147 audio_play_fragment(data
->audiofd2
, lr_buf
, rr_buf
, event
->d
.integer
);
157 g_warning("emu_output module doesn't care for events of kind %d.", event
->kind
);
162 PRIVATE
int init_instance(Generator
*g
) {
166 if (instance_count
> 1)
167 /* Not allowed more than one of these things. */
170 data
= safe_malloc(sizeof(EmuData
));
172 data
->audiofd1
= open_audiofd(0);
174 if (data
->audiofd1
< 0) {
176 popup_msgbox("Error", MSGBOX_OK
, 120000, MSGBOX_OK
,
177 "Could not open audio device, %s.", "/dev/dsp");
181 data
->audiofd2
= open_audiofd(1);
183 if (data
->audiofd2
< 0) {
185 popup_msgbox("Error", MSGBOX_OK
, 120000, MSGBOX_OK
,
186 "Could not open audio device, %s.", "/dev/dsp1");
190 data
->input_tag
= -1;
191 data
->clock
= gen_register_clock(g
, "Emu Output Clock", clock_handler
);
195 gen_register_realtime_fn(g
, realtime_handler
);
196 gen_select_clock(data
->clock
); /* a not unreasonable assumption? */
201 PRIVATE
void destroy_instance(Generator
*g
) {
202 EmuData
*data
= g
->data
;
204 gen_deregister_realtime_fn(g
, realtime_handler
);
207 gen_deregister_clock(data
->clock
);
208 if (data
->input_tag
!= -1)
209 gdk_input_remove(data
->input_tag
);
210 close(data
->audiofd1
);
211 close(data
->audiofd2
);
219 PRIVATE InputSignalDescriptor input_sigs
[] = {
220 { "Left Front Channel", SIG_FLAG_REALTIME
},
221 { "Right Front Channel", SIG_FLAG_REALTIME
},
222 { "Left Rear Channel", SIG_FLAG_REALTIME
},
223 { "Right Rear Channel", SIG_FLAG_REALTIME
},
227 PRIVATE
void setup_class(void) {
231 char *name
= prefs_get_item("output_emu_fragment_size");
233 if (name
== NULL
|| sscanf(name
, "%d", &audio_fragment_exponent
) != 1) {
234 audio_fragment_exponent
= DEFAULT_FRAGMENT_EXPONENT
;
237 audio_fragment_exponent
= MAX(audio_fragment_exponent
, 7);
239 prefs_register_option("output_emu_fragment_size", "7");
240 prefs_register_option("output_emu_fragment_size", "8");
241 prefs_register_option("output_emu_fragment_size", "9");
242 prefs_register_option("output_emu_fragment_size", "10");
243 prefs_register_option("output_emu_fragment_size", "11");
244 prefs_register_option("output_emu_fragment_size", "12");
245 prefs_register_option("output_emu_fragment_size", "13");
246 prefs_register_option("output_emu_fragment_size", "14");
247 prefs_register_option("output_emu_fragment_size", "15");
248 prefs_register_option("output_emu_fragment_size", "16");
250 k
= gen_new_generatorclass("emu_out", FALSE
, 0, 0,
251 input_sigs
, NULL
, NULL
,
252 init_instance
, destroy_instance
,
253 (AGenerator_pickle_t
) init_instance
, NULL
);
255 gencomp_register_generatorclass(k
, FALSE
, "Outputs/Emu10k1 Output",
256 PIXMAPDIRIFY("oss_output.xpm"),
260 #include "emu10k1-include/dsp.h"
262 //PRIVATE void dspstuff( void ) {
263 // struct dsp_patch_manager mgr;
264 // int inputs[2] = {0,1};
265 // int outputs[2] = {0,1};
266 // mgr.mixer_fd = open( "/dev/mixer", O_RDWR, 0 );
267 // mgr.dsp_fd = open( "/dev/dsp", O_RDWR, 0 );
269 // dsp_unload_all( &mgr );
270 // dsp_add_route( &mgr, 0, 0 );
271 // dsp_add_route( &mgr, 1, 1 );
272 // dsp_read_patch( &mgr, "/usr/local/share/emu10k1/chorus_2.bin", inputs, outputs, 2,2,1,"brr",0 );
276 extern void init_emuiocomp( void );
277 extern void init_emupatchcomp( void );
278 extern void done_emuiocomp( void );
279 PUBLIC
void init_plugin(void) {