3 Ann Hell Ex Machina - Music Software
4 Copyright (C) 2003/2005 Angel Ortega <angel@triptico.com>
6 ss_output.c - Softsynth output interface
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
34 #include "ss_output.h"
41 /* master output volume */
42 float ss_master_volume
=1.0;
44 /* output accounting */
45 int ss_output_frames
=0;
46 int ss_output_clipped
=0;
47 float ss_output_lowest
=0;
48 float ss_output_highest
=0;
50 /* optimal output volume */
51 float ss_optimal_volume
;
54 /* the output drivers */
56 extern struct _output_driver _out_driver_arts
;
57 extern struct _output_driver _out_driver_esd
;
58 extern struct _output_driver _out_driver_oss
;
59 extern struct _output_driver _out_driver_sgi
;
60 extern struct _output_driver _out_driver_wav
;
61 extern struct _output_driver _out_driver_raw
;
62 extern struct _output_driver _out_driver_pipe
;
64 static struct _output_driver
* _drivers
[] = {
76 static struct _output_driver
* drv
=NULL
;
79 static short int * out_buffer
=NULL
;
80 static int out_buffer_size
=0;
81 static int out_buffer_index
=0;
89 * ss_output_open - Opens an output device.
90 * @name: name of the driver
91 * @filename: name of the file or device
93 * Opens an output device. @name contains the name of the driver
94 * (i.e. "raw" or "wav"), @filename contains the (optional) name
95 * of the output file or device (i.e. a filename for "raw" or
96 * "wav" or "/dev/dsp" for a direct audio device like "oss").
97 * @Name can be the special pseudo-driver "default"
98 * to select the most appropriate (usually a platform-specific
99 * direct output device, or "wav" if no one exists).
100 * @filename can also be NULL; in that case, a driver dependent,
101 * default value is used.
103 * The _n_channels global variable can be changed on output if
104 * the driver doesn't support so much channels.
106 * Returns a negative number in case of error, or zero otherwise.
108 int ss_output_open(char * name
, char * filename
)
113 /* if driver is already selected, fail */
117 /* "default" and NULL name is the same */
118 if(name
!= NULL
&& strcmp(name
, "default") == 0)
121 /* travel all drivers searching for a valid one */
122 for(n
=0;(drv
=_drivers
[n
]) != NULL
;n
++)
124 /* skip non-supported drivers */
125 if(drv
->open
== NULL
)
128 /* test if a specific driver is requested */
129 if(name
!= NULL
&& strcmp(name
, drv
->name
) != 0)
133 printf("Trying output driver '%s'... ", drv
->name
);
136 if((bs
= drv
->open(filename
? filename
:
137 drv
->default_file
)) >= 0)
139 if(ss_debug
) printf("OK!\n");
146 /* out of drivers; fail */
150 /* if the driver requests a buffer, assign; otherwise,
151 alloc a minimal buffer to write a frame */
155 out_buffer_size
=ss_nchannels
;
157 /* free previously allocated buffer, in any */
158 if(out_buffer
!= NULL
)
161 /* alloc output buffer */
162 if((out_buffer
= (short *)
163 malloc(out_buffer_size
* sizeof(short int))) == NULL
)
169 /* reset accounting */
170 ss_output_frames
=ss_output_clipped
=0;
171 ss_output_lowest
=ss_output_highest
=0.0;
179 void ss_output_init_frame(float samples
[])
183 for(n
=0;n
< SS_MAX_CHANNELS
;n
++)
189 * ss_output_write - Outputs a frame of samples.
190 * @samples: the frame of samples
192 * Outputs a frame of samples. The output samples are
193 * intermixed if needed, have the master volume applied and trimmed
194 * before being sent to the output driver itself.
196 * If the maximum number of channels the output driver supports
197 * is lower than the global _n_channels, they are sequentially intermixed
198 * (for example, when outputting 4 channel data to a stereo device,
199 * 0 and 2 channels will go to left and 1 and 3 to right).
201 * Returns a negative value in case of error, or 0 otherwise.
203 int ss_output_write(float samples
[])
206 float s
[SS_MAX_CHANNELS
];
208 /* clean samples first */
209 for(n
=0;n
< ss_nchannels
;n
++)
212 /* move samples, 'down-channeling' if needed */
213 for(n
=0;n
< SS_MAX_CHANNELS
;n
++)
214 s
[n
% ss_nchannels
] += samples
[n
];
216 /* final corrections */
217 for(n
=clip
=0;n
< ss_nchannels
;n
++)
219 /* store the lowest and highest
220 amplitude seen before master volume */
221 if(s
[n
] < ss_output_lowest
)
222 ss_output_lowest
=s
[n
];
224 if(s
[n
] > ss_output_highest
)
225 ss_output_highest
=s
[n
];
227 /* apply master volume */
228 s
[n
] *= ss_master_volume
;
230 /* clip samples to signed 16 bit boundaries */
243 /* store in buffer */
244 out_buffer
[out_buffer_index
++]=(short int) s
[n
];
247 /* update accounting */
253 /* really write if buffer full */
254 if(out_buffer_index
>= out_buffer_size
- ss_nchannels
)
256 ret
=drv
->write(out_buffer
, out_buffer_index
);
265 * ss_output_close - Closes the output device.
267 * Closes the output driver.
269 int ss_output_close(void)
275 drv
->write(out_buffer
, out_buffer_index
);
280 /* calculate optimal master volume for
282 ss_output_lowest
=fabs(ss_output_lowest
);
284 ss_optimal_volume
= ss_output_lowest
> ss_output_highest
?
285 32768.0 / ss_output_lowest
:
286 32767.0 / ss_output_highest
;