The @ command (track) in the arpeggiator has been changed to /, as it
[ahxm.git] / ss_output.c
blobda2061d92a5cc5c79037bcf0e85270e3189aeb17
1 /*
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
26 #include "config.h"
28 #include <stdio.h>
29 #include <stdlib.h>
30 #include <unistd.h>
31 #include <string.h>
32 #include <math.h>
34 #include <signal.h>
36 #include "annhell.h"
38 /*******************
39 Data
40 ********************/
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;
53 /* driver data */
54 static void * outdev;
57 usual channel mapping:
59 mono: all
60 stereo: left | right
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
65 home cinema 5.1: front l | center | front r | real l | rear r | subwoofer
67 Converting from wav to 5.1 ac3:
69 ffmpeg -ac 6 -ab 192 -ar 44100 -i input.wav output.ac3
72 /* a copy of the output file name */
73 static char * ss_output_file_name = NULL;
75 /* cue file name and track */
76 char * ss_cue_file_name = NULL;
77 static int ss_cue_file_track = -1;
79 /*******************
80 Code
81 ********************/
83 void * ss_outdev_open(char * drvname, char * file, int freq, int n_channels);
84 void ss_outdev_write(void * drv, short int * frame);
85 void * ss_outdev_close(void * drv);
88 static void close_on_signal(int sig_num)
89 /* SIGINT (and other) signal handler */
91 /* close output device */
92 outdev = ss_outdev_close(outdev);
94 /* exit */
95 exit(0);
99 /**
100 * ss_output_open - Opens an output device.
101 * @name: name of the driver
102 * @filename: name of the file or device
104 * Opens an output device. @name contains the name of the driver
105 * (i.e. "oss" or "wav"), @filename contains the (optional) name
106 * of the output file or device (i.e. a filename
107 * "wav" or "/dev/dsp" for a direct audio device like "oss").
108 * @Name can be the special pseudo-driver "default"
109 * to select the most appropriate (usually a platform-specific
110 * direct output device, or "wav" if no one exists).
111 * @filename can also be NULL; in that case, a driver dependent,
112 * default value is used.
114 * Returns zero if the output device was correctly open, or
115 * nonzero otherwise.
117 int ss_output_open(char * drvname, char * filename)
119 if(strcmp(drvname, "default") == 0)
120 drvname = NULL;
122 /* reset accounting */
123 ss_output_clipped = 0;
124 ss_output_lowest = ss_output_highest = 0.0;
126 /* close the device on unexpected signals */
127 signal(SIGINT, close_on_signal);
129 /* store a copy of the filename */
130 ss_output_file_name = filename;
132 return((outdev = ss_outdev_open(drvname,
133 filename, ss_frequency, ss_nchannels)) == NULL);
138 * ss_output_init_frame - Inits a frame
139 * @frame: the frame
141 * Inits a frame, setting all samples to zero.
143 void ss_output_init_frame(sample_t frame[])
145 int n;
147 for(n = 0;n < SS_MAX_CHANNELS;n++)
148 frame[n] = 0.0;
153 * ss_output_write - Outputs a frame of samples.
154 * @frame: the frame of samples
156 * Outputs a frame of samples. The output samples are
157 * intermixed if needed, have the master volume applied and trimmed
158 * before being sent to the output driver itself.
160 * If the maximum number of channels the output driver supports
161 * is lower than the global ss_nchannels, they are sequentially intermixed
162 * (for example, when outputting 4 channel data to a stereo device,
163 * 0 and 2 channels will go to left and 1 and 3 to right).
165 * Returns a negative value in case of error, or 0 otherwise.
167 int ss_output_write(sample_t frame[])
169 int n, clip, ret = 0;
170 sample_t s;
171 short int is[SS_MAX_CHANNELS];
173 /* final corrections */
174 for(n = clip = 0;n < ss_nchannels;n++)
176 s = frame[n];
178 /* store the lowest and highest
179 amplitude seen before master volume */
180 if(s < ss_output_lowest)
181 ss_output_lowest = s;
183 if(s > ss_output_highest)
184 ss_output_highest = s;
186 /* apply master volume */
187 s *= ss_master_volume;
189 /* clip samples to signed 16 bit boundaries */
190 if(s < -32768)
192 s = -32768;
193 clip++;
196 if(s > 32767)
198 s = 32767;
199 clip++;
202 /* store in buffer */
203 is[n] = (short int) s;
206 if(clip)
207 ss_output_clipped++;
209 /* finally write */
210 ss_outdev_write(outdev, is);
212 return(ret);
217 * ss_output_close - Closes the output device.
219 * Closes the output driver.
221 void ss_output_close(void)
223 /* back to default signal behaviour */
224 signal(SIGINT, SIG_DFL);
226 /* close the device */
227 outdev = ss_outdev_close(outdev);
229 /* calculate optimal master volume for
230 zero saturation */
231 ss_output_lowest = fabs(ss_output_lowest);
233 ss_optimal_volume = ss_output_lowest > ss_output_highest ?
234 32768.0 / ss_output_lowest :
235 32767.0 / ss_output_highest;
239 static int cue_file_init(void)
240 /* inits the cue file, writing the first line */
242 FILE * f;
244 if(ss_output_file_name == NULL ||
245 (f = fopen(ss_cue_file_name, "w")) == NULL)
246 return(-2);
248 /* write first line */
249 fprintf(f, "FILE \"%s\" WAVE\n", ss_output_file_name);
250 fclose(f);
252 ss_cue_file_track = 0;
254 return(0);
258 int cue_file_song_info(int frame, char * author, char * name)
260 int s;
261 FILE * f;
263 if(ss_cue_file_name == NULL)
264 return(0);
266 /* init if it's the first time */
267 if(ss_cue_file_track == -1)
269 /* can't open? fail */
270 if(cue_file_init() < 0)
272 ss_cue_file_name = NULL;
273 return(-1);
277 /* open or fail */
278 if((f = fopen(ss_cue_file_name, "a")) == NULL)
279 return(-1);
281 s = frame / ss_frequency;
283 fprintf(f, "TRACK %02d AUDIO\n", ss_cue_file_track++);
284 fprintf(f, " PERFORMER \"%s\"\n", author);
285 fprintf(f, " TITLE \"%s\"\n", name);
286 fprintf(f, " INDEX 01 %02d:%02d:00\n", s / 60, s % 60);
288 fclose(f);
289 return(0);