3 Ann Hell Ex Machina - Music Software
4 Copyright (C) 2003/2006 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
42 /* master output volume */
43 sample_t ss_master_volume
= 0.5;
45 /* output accounting */
46 int ss_output_clipped
= 0;
47 sample_t ss_output_lowest
= 0;
48 sample_t ss_output_highest
= 0;
50 /* optimal output volume */
51 sample_t ss_optimal_volume
;
57 usual channel mapping:
61 3 channel: left | right | center
62 quad: front left | front right | rear left | rear right
63 4 channel: left | center | right | surround
64 6 channel: left center | left | center | right center | right | surround
67 /* a copy of the output file name */
68 static char * ss_output_file_name
= NULL
;
70 /* cue file name and track */
71 char * ss_cue_file_name
= NULL
;
72 static int ss_cue_file_track
= -1;
78 void * ss_outdev_open(char * drvname
, char * file
, int freq
, int n_channels
);
79 void ss_outdev_write(void * drv
, short int * frame
);
80 void * ss_outdev_close(void * drv
);
83 static void close_on_signal(int sig_num
)
84 /* SIGINT (and other) signal handler */
86 /* close output device */
87 outdev
= ss_outdev_close(outdev
);
95 * ss_output_open - Opens an output device.
96 * @name: name of the driver
97 * @filename: name of the file or device
99 * Opens an output device. @name contains the name of the driver
100 * (i.e. "oss" or "wav"), @filename contains the (optional) name
101 * of the output file or device (i.e. a filename
102 * "wav" or "/dev/dsp" for a direct audio device like "oss").
103 * @Name can be the special pseudo-driver "default"
104 * to select the most appropriate (usually a platform-specific
105 * direct output device, or "wav" if no one exists).
106 * @filename can also be NULL; in that case, a driver dependent,
107 * default value is used.
109 * Returns zero if the output device was correctly open, or
112 int ss_output_open(char * drvname
, char * filename
)
114 if(strcmp(drvname
, "default") == 0)
117 /* reset accounting */
118 ss_output_clipped
= 0;
119 ss_output_lowest
= ss_output_highest
= 0.0;
121 /* close the device on unexpected signals */
122 signal(SIGINT
, close_on_signal
);
124 /* store a copy of the filename */
125 ss_output_file_name
= filename
;
127 return((outdev
= ss_outdev_open(drvname
,
128 filename
, ss_frequency
, ss_nchannels
)) == NULL
);
133 * ss_output_init_frame - Inits a frame
136 * Inits a frame, setting all samples to zero.
138 void ss_output_init_frame(sample_t frame
[])
142 for(n
= 0;n
< SS_MAX_CHANNELS
;n
++)
148 * ss_output_write - Outputs a frame of samples.
149 * @frame: the frame of samples
151 * Outputs a frame of samples. The output samples are
152 * intermixed if needed, have the master volume applied and trimmed
153 * before being sent to the output driver itself.
155 * If the maximum number of channels the output driver supports
156 * is lower than the global ss_nchannels, they are sequentially intermixed
157 * (for example, when outputting 4 channel data to a stereo device,
158 * 0 and 2 channels will go to left and 1 and 3 to right).
160 * Returns a negative value in case of error, or 0 otherwise.
162 int ss_output_write(sample_t frame
[])
164 int n
, clip
, ret
= 0;
166 short int is
[SS_MAX_CHANNELS
];
168 /* final corrections */
169 for(n
= clip
= 0;n
< ss_nchannels
;n
++)
173 /* store the lowest and highest
174 amplitude seen before master volume */
175 if(s
< ss_output_lowest
)
176 ss_output_lowest
= s
;
178 if(s
> ss_output_highest
)
179 ss_output_highest
= s
;
181 /* apply master volume */
182 s
*= ss_master_volume
;
184 /* clip samples to signed 16 bit boundaries */
197 /* store in buffer */
198 is
[n
] = (short int) s
;
205 ss_outdev_write(outdev
, is
);
212 * ss_output_close - Closes the output device.
214 * Closes the output driver.
216 void ss_output_close(void)
218 /* back to default signal behaviour */
219 signal(SIGINT
, SIG_DFL
);
221 /* close the device */
222 outdev
= ss_outdev_close(outdev
);
224 /* calculate optimal master volume for
226 ss_output_lowest
= fabs(ss_output_lowest
);
228 ss_optimal_volume
= ss_output_lowest
> ss_output_highest
?
229 32768.0 / ss_output_lowest
:
230 32767.0 / ss_output_highest
;
234 static int cue_file_init(void)
235 /* inits the cue file, writing the first line */
239 if(ss_output_file_name
== NULL
||
240 (f
= fopen(ss_cue_file_name
, "w")) == NULL
)
243 /* write first line */
244 fprintf(f
, "FILE \"%s\" WAVE\n", ss_output_file_name
);
247 ss_cue_file_track
= 0;
253 int cue_file_song_info(int frame
, char * author
, char * name
)
258 if(ss_cue_file_name
== NULL
)
261 /* init if it's the first time */
262 if(ss_cue_file_track
== -1)
264 /* can't open? fail */
265 if(cue_file_init() < 0)
267 ss_cue_file_name
= NULL
;
273 if((f
= fopen(ss_cue_file_name
, "a")) == NULL
)
276 s
= frame
/ ss_frequency
;
278 fprintf(f
, "TRACK %02d AUDIO\n", ss_cue_file_track
++);
279 fprintf(f
, " PERFORMER \"%s\"\n", author
);
280 fprintf(f
, " TITLE \"%s\"\n", name
);
281 fprintf(f
, " INDEX 01 %02d:%02d:00\n", s
/ 60, s
% 60);