Code cleaning to ss_gen.c.
[ahxm.git] / ss_output.c
blobbdf582dea542b4566a852487017ec9f9aa4ff9c2
1 /*
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
26 #include "config.h"
28 #include <stdio.h>
29 #include <stdlib.h>
30 #include <string.h>
31 #include <math.h>
33 #include "ss_core.h"
34 #include "ss_output.h"
37 /*******************
38 Data
39 ********************/
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[] = {
65 &_out_driver_arts,
66 &_out_driver_esd,
67 &_out_driver_oss,
68 &_out_driver_sgi,
69 &_out_driver_wav,
70 &_out_driver_raw,
71 &_out_driver_pipe,
72 NULL
75 /* driver in use */
76 static struct _output_driver * drv=NULL;
78 /* buffer */
79 static short int * out_buffer=NULL;
80 static int out_buffer_size=0;
81 static int out_buffer_index=0;
84 /*******************
85 Code
86 ********************/
88 /**
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)
110 int n;
111 int bs=0;
113 /* if driver is already selected, fail */
114 if(drv != NULL)
115 return(-1);
117 /* "default" and NULL name is the same */
118 if(name != NULL && strcmp(name, "default") == 0)
119 name=NULL;
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)
126 continue;
128 /* test if a specific driver is requested */
129 if(name != NULL && strcmp(name, drv->name) != 0)
130 continue;
132 if(ss_debug)
133 printf("Trying output driver '%s'... ", drv->name);
135 /* try to open */
136 if((bs = drv->open(filename ? filename :
137 drv->default_file)) >= 0)
139 if(ss_debug) printf("OK!\n");
140 break;
143 printf("Fail!\n");
146 /* out of drivers; fail */
147 if(drv == NULL)
148 return(-2);
150 /* if the driver requests a buffer, assign; otherwise,
151 alloc a minimal buffer to write a frame */
152 if(bs)
153 out_buffer_size=bs;
154 else
155 out_buffer_size=ss_nchannels;
157 /* free previously allocated buffer, in any */
158 if(out_buffer != NULL)
159 free(out_buffer);
161 /* alloc output buffer */
162 if((out_buffer = (short *)
163 malloc(out_buffer_size * sizeof(short int))) == NULL)
165 drv=NULL;
166 return(-3);
169 /* reset accounting */
170 ss_output_frames=ss_output_clipped=0;
171 ss_output_lowest=ss_output_highest=0.0;
173 out_buffer_index=0;
175 return(0);
179 void ss_output_init_frame(float samples[])
181 int n;
183 for(n=0;n < SS_MAX_CHANNELS;n++)
184 samples[n] = 0.0;
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[])
205 int n,clip,ret=0;
206 float s[SS_MAX_CHANNELS];
208 /* clean samples first */
209 for(n=0;n < ss_nchannels;n++)
210 s[n]=0.0;
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 */
231 if(s[n] < -32768)
233 s[n]=-32768;
234 clip++;
237 if(s[n] > 32767)
239 s[n]=32767;
240 clip++;
243 /* store in buffer */
244 out_buffer[out_buffer_index++]=(short int) s[n];
247 /* update accounting */
248 ss_output_frames++;
250 if(clip)
251 ss_output_clipped++;
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);
257 out_buffer_index=0;
260 return(ret);
265 * ss_output_close - Closes the output device.
267 * Closes the output driver.
269 int ss_output_close(void)
271 int r;
273 /* flush buffer */
274 if(out_buffer_index)
275 drv->write(out_buffer, out_buffer_index);
277 r=drv->close();
278 drv=NULL;
280 /* calculate optimal master volume for
281 zero saturation */
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;
288 return(r);