Pipes in the wav command have been documented (Closes: #1140).
[ahxm.git] / ss_input.c
blob697887bb8cc4295bdd6581929686a5d0e78e1642
1 /*
3 Ann Hell Ex Machina - Music Software
4 Copyright (C) 2003/2007 Angel Ortega <angel@triptico.com>
6 ss_input.c - Code to load softsynth sounds in different formats
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>
32 #include "ahxm.h"
34 /*******************
35 Data
36 ********************/
38 /* maximum page size */
39 int ss_page_size = 441000;
41 /*******************
42 Code
43 ********************/
45 static int fget16(FILE * f)
46 /* Reads a 16 bit integer from a file in big endian byte ordering */
48 int c;
50 c = fgetc(f);
51 c += (fgetc(f) * 256);
53 return(c);
57 static int fget32(FILE * f)
58 /* Reads a 32 bit integer from a file in big endian byte ordering */
60 int c;
62 c = fgetc(f);
63 c += (fgetc(f) * 256);
64 c += (fgetc(f) * 65536);
65 c += (fgetc(f) * 16777216);
67 return(c);
71 static sample_t load_sample(FILE * f, int bits, int sign)
72 /* loads one sample from a file */
74 int s;
76 /* if on eof, return silence */
77 if(feof(f)) return(0);
79 if(bits == 8)
81 s = fgetc(f) - 128;
82 s <<= 8;
84 else
86 if(!sign)
87 s = fget16(f) - 32768;
88 else
89 s = (short int)fget16(f);
92 return(((sample_t) s) / 32768.0);
96 void load_pcm_wave(FILE * f, struct ss_wave * w)
97 /* loads an interleaved stream from a file */
99 int n, m;
101 /* fills the channels */
102 for(m = 0;m < w->p_size;m++)
104 for(n = 0;n < w->n_channels;n++)
105 w->wave[n][m] = load_sample(f, w->bits, w->sign);
111 * ss_load_wav_file - Loads a file in .WAV format.
112 * @file: name of the file
113 * @base_freq: base frequency
114 * @min_freq: minimum frequency
115 * @max_freq: maximum frequency
116 * @loop_start: frame number of loop start (-1, no loop)
117 * @loop_end: frame number of loop end (-1, end of wave)
118 * @first_channel: first channel to start spreading
119 * @skip_channels: channels to skip when spreading
121 * Loads a file in .WAV format.
123 struct ss_wave * ss_load_wav_file(char * file,
124 double base_freq, double min_freq, double max_freq,
125 double loop_start, double loop_end,
126 int first_channel, int skip_channels)
128 FILE * f;
129 char dummydata[256];
130 int rlen, flen;
131 short int b_per_sec, n_channels;
132 char riffid[5], waveid[5], fmtid[5], dataid[5];
133 double size;
134 int s_rate, bits;
135 struct ss_wave * w;
136 int p;
138 if (*file == '|')
139 file = transconv_pipe(file + 1, ".wav", "ahxm");
140 else
142 /* find the file in the library path */
143 if((file = libpath_locate(file)) == NULL)
144 return(NULL);
146 /* try converting */
147 if((file = transconv(file, ".wav", "ahxm")) == NULL)
148 return(NULL);
151 if((f = fopen(file, "r")) == NULL)
152 return(NULL);
154 fread(riffid, 1, 4, f);
155 riffid[4] = 0;
156 fread(&rlen, 1, 4, f);
157 fread(waveid, 1, 4, f);
158 waveid[4] = 0;
160 if(strcmp(waveid,"WAVE"))
162 fclose(f);
163 return(NULL);
166 fread(fmtid, 1, 4, f);
167 fmtid[4] = 0;
168 flen = fget32(f);
170 if(flen > 240)
171 flen = 240;
173 if(fget16(f) != 1)
175 /* wicked compressed format? fail */
176 fclose(f);
177 return(NULL);
180 n_channels = fget16(f);
181 s_rate = fget32(f);
182 b_per_sec = fget32(f);
184 bits = fget16(f) / n_channels;
185 bits *= 8;
187 fread(dummydata, 1, (size_t)flen - 14, f);
188 fread(dataid, 1, 4, f);
189 dataid[4] = 0;
191 size = (double) fget32(f);
192 if(bits == 16) size /= 2;
193 size /= (double) n_channels;
195 p = size > ss_page_size ? ss_page_size : size;
197 if((w = ss_alloc_wave(size, n_channels, s_rate, p)) != NULL)
199 w->base_freq = base_freq;
200 w->min_freq = min_freq;
201 w->max_freq = max_freq;
203 w->loop_start = loop_start;
205 if(loop_end < 0)
206 w->loop_end = size;
207 else
208 w->loop_end = loop_end;
210 w->first_channel = first_channel;
211 w->skip_channels = skip_channels;
213 /* fill the info needed for paging */
214 w->filename = strdup(file);
215 w->f_pos = ftell(f);
216 w->bits = bits;
217 w->sign = 1;
219 /* set the page offset further the end, to
220 force a page reading the first time it's used */
221 w->p_offset = (int) size;
224 fclose(f);
226 return(w);
231 * ss_load_pat_file - Loads an instrument in .PAT format.
232 * @i: The instrument
233 * @filename: filename holding the instrument
235 * Loads data from a Gravis Ultrasound patch (.PAT) format and
236 * stores it as layers for an instrument.
238 * Returns -100 if the file could not be read, -101 or -102
239 * if the file is not recognized as a .PAT file, or 0 if
240 * everything went OK.
242 int ss_load_pat_file(struct ss_ins * i, char * file)
244 FILE * f;
245 char buffer[512];
246 int m, n, o;
247 int n_layers;
248 int flags, bits, sign, loop, pingpong;
249 struct ss_wave * w;
251 if((f = libpath_fopen(file, "r")) == NULL)
252 return(-100);
254 /* read signatures */
255 fread(buffer, 12, 1, f);
256 if(strcmp(buffer, "GF1PATCH110") != 0)
258 fclose(f);
259 return(-101);
262 fread(buffer, 10, 1, f);
263 if(strcmp(buffer, "ID#000002") != 0)
265 fclose(f);
266 return(-102);
269 /* skip description */
270 fread(buffer, 65, 1, f);
272 /* ignore volume */
273 fget16(f);
275 /* skip */
276 fread(buffer, 109, 1, f);
278 /* # of layers */
279 n_layers = fgetc(f);
281 /* skip */
282 fread(buffer, 40, 1, f);
284 for(n = 0;n < n_layers;n++)
286 int size, s_rate;
287 double loop_start, loop_end;
288 double min_freq, max_freq, base_freq;
290 /* layer name */
291 fread(buffer, 8, 1, f);
293 size = (double)fget32(f);
294 loop_start = (double)fget32(f);
295 loop_end = (double)fget32(f);
296 s_rate = fget16(f);
298 min_freq = ((double)fget32(f)) / 1000.0;
299 max_freq = ((double)fget32(f)) / 1000.0;
300 base_freq = ((double)fget32(f)) / 1000.0;
302 if(base_freq < 0)
303 break;
305 /* ignore fine-tune */
306 fget16(f);
308 /* ignore pan position */
309 fgetc(f);
311 /* skip envelope rate, value, tremolo and vibrato */
312 fread(buffer, 18, 1, f);
314 flags = fgetc(f);
316 bits = flags & 0x01 ? 16 : 8;
317 sign = flags & 0x02 ? 0 : 1;
318 loop = flags & 0x04 ? 1 : 0;
319 pingpong = flags & 0x08 ? 1 : 0;
321 if(bits == 16)
323 size /= 2;
324 loop_start /= 2;
325 loop_end /= 2;
328 /* skip frequency scale data */
329 fget16(f); fget16(f);
331 /* skip reserved */
332 fread(buffer, 36, 1, f);
334 if((w = ss_alloc_wave(size, 1, s_rate, -1)) == NULL)
335 break;
337 /* set the rest of values */
338 w->loop_start = loop_start;
339 w->loop_end = loop_end;
340 w->base_freq = base_freq;
341 w->min_freq = min_freq;
342 w->max_freq = max_freq;
343 w->bits = bits;
344 w->sign = sign;
346 /* load the wave */
347 ss_prepare_wave(w);
348 load_pcm_wave(f, w);
350 if(pingpong && loop)
352 int loop_size;
353 sample_t * ptr;
355 /* if ping-pong, realloc space for a reverse
356 version of the loop */
357 loop_size = (int)(loop_end - loop_start);
359 ptr = (sample_t *) malloc((size + loop_size + 1)
360 * sizeof(sample_t));
362 /* transfer start and loop */
363 for(m = 0;m <= (int)loop_end;m++)
364 ptr[m] = w->wave[0][m];
366 /* transfer a reversed version of the loop */
367 for(o = m - 1;o >= loop_start;o--, m++)
368 ptr[m] = w->wave[0][o];
370 /* transfer the end */
371 for(o = loop_end + 1;o < size;o++, m++)
372 ptr[m] = w->wave[0][o];
374 w->loop_end += (double) loop_size;
375 w->size += (double) loop_size;
376 w->p_size += loop_size;
378 /* free and swap */
379 free(w->wave[0]);
380 w->wave[0] = ptr;
383 if(loop == 0) w->loop_start = -1;
385 /* finally add layer to instrument */
386 ss_ins_add_layer(i, w);
389 fclose(f);
390 return(0);