Version 1.0.2b RELEASED.
[ahxm.git] / ss_input.c
blob44000a07f1a82dd0c37bbfe7aaaecfc62c31feb9
1 /*
3 Ann Hell Ex Machina - Music Software
4 Copyright (C) 2003/2005 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>
31 #include <unistd.h>
32 #include <sys/stat.h>
33 #include <sys/types.h>
35 #include "annhell.h"
36 #include "sha1.h"
38 /*******************
39 Data
40 ********************/
42 /*******************
43 Code
44 ********************/
46 static int fget16(FILE * f)
47 /* Reads a 16 bit integer from a file in big endian byte ordering */
49 int c;
51 c = fgetc(f);
52 c += (fgetc(f) * 256);
54 return(c);
58 static int fget32(FILE * f)
59 /* Reads a 32 bit integer from a file in big endian byte ordering */
61 int c;
63 c = fgetc(f);
64 c += (fgetc(f) * 256);
65 c += (fgetc(f) * 65536);
66 c += (fgetc(f) * 16777216);
68 return(c);
72 static sample_t load_sample(FILE * f, int bits, int sign)
73 /* loads one sample from a file */
75 int s;
77 /* Caution: no error condition is checked */
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);
96 static void load_pcm_wave(FILE * f, int bits, int sign, struct ss_wave * w)
97 /* loads an interleaved stream from a file */
99 int n, i;
100 double m;
102 /* fills the channels */
103 for(m = 0;m < w->size;m++)
105 i = (int) m;
107 for(n = 0;n < w->n_channels;n++)
108 w->wave[n][i] = load_sample(f, bits, sign);
114 * ss_load_wav_file - Loads a file in .WAV format.
115 * @file: name of the file
116 * @base_freq: base frequency
117 * @min_freq: minimum frequency
118 * @max_freq: maximum frequency
119 * @loop_start: frame number of loop start (-1, no loop)
120 * @loop_end: frame number of loop end (-1, end of wave)
122 * Loads a file in .WAV format.
124 struct ss_wave * ss_load_wav_file(char * file,
125 double base_freq, double min_freq, double max_freq,
126 double loop_start, double loop_end)
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;
137 if((f = path_fopen(file, "r")) == NULL)
138 return(NULL);
140 fread(riffid, 1, 4, f);
141 riffid[4] = 0;
142 fread(&rlen, 1, 4, f);
143 fread(waveid, 1, 4, f);
144 waveid[4] = 0;
146 if(strcmp(waveid,"WAVE"))
148 fclose(f);
149 return(NULL);
152 fread(fmtid, 1, 4, f);
153 fmtid[4] = 0;
154 flen = fget32(f);
156 if(flen > 240)
157 flen = 240;
159 if(fget16(f) != 1)
161 /* wicked compressed format? fail */
162 fclose(f);
163 return(NULL);
166 n_channels = fget16(f);
167 s_rate = fget32(f);
168 b_per_sec = fget32(f);
170 bits = fget16(f) / n_channels;
171 bits *= 8;
173 fread(dummydata, 1, (size_t)flen - 14, f);
174 fread(dataid, 1, 4, f);
175 dataid[4] = 0;
177 size = (double) fget32(f);
178 if(bits == 16) size /= 2;
179 size /= (double) n_channels;
181 if((w = ss_alloc_wave(size, n_channels, s_rate)) != NULL)
183 w->base_freq = base_freq;
184 w->min_freq = min_freq;
185 w->max_freq = max_freq;
187 w->loop_start = loop_start;
189 if(loop_end < 0)
190 w->loop_end = size;
191 else
192 w->loop_end = loop_end;
194 load_pcm_wave(f, bits, 1, w);
197 fclose(f);
199 return(w);
203 static char * cached_base_name(char * file)
204 /* builds a unique cache file name using a SHA1 hash */
206 static char c_file[64];
207 unsigned char sha1[20];
208 SHA_CTX c;
209 int n;
211 SHA1_Init(&c);
212 SHA1_Update(&c, file, strlen(file));
213 SHA1_Final(sha1, &c);
215 for(n = 0;n < sizeof(sha1);n++)
217 char tmp[3];
219 snprintf(tmp, sizeof(tmp), "%02x", sha1[n]);
220 c_file[n * 2] = tmp[0];
221 c_file[(n * 2) + 1] = tmp[1];
224 c_file[n * 2] = '\0';
225 return(c_file);
229 static char * wave_file_preprocess(char * file)
230 /* preprocess the file, converting with external tools if necessary */
232 char * ext;
233 char * c_path;
234 char * c_basename;
235 char tmp[2048];
236 static char c_file[1024];
238 /* gets the file extension */
239 if((ext = strrchr(file, '.')) == NULL)
240 return(NULL);
242 /* if it's a .wav file, return as is; no
243 further processing is needed */
244 if(strcmp(ext, ".wav") == 0 || strcmp(ext, ".WAV") == 0)
245 return(file);
247 /* resolve the file name */
248 if((file = locate_file(file)) == NULL)
249 return(NULL);
251 /* build the directory cache name */
252 if((c_path = getenv("HOME")) == NULL)
253 c_path = "/tmp";
255 snprintf(tmp, sizeof(tmp), "%s/.annhellcache", c_path);
256 tmp[sizeof(tmp) - 1] = '\0';
258 /* create a suitable cached file name */
259 c_basename = cached_base_name(file);
261 snprintf(c_file, sizeof(c_file), "%s/%s.wav", tmp, c_basename);
262 c_file[sizeof(c_file) - 1] = '\0';
264 /* does the file already exist? */
265 if(access(c_file, R_OK) == 0)
266 return(c_file);
268 /* create the cache directory */
269 mkdir(tmp, 0755);
271 if(debug)
272 printf("Caching '%s' to '%s'\n", file, c_file);
274 /* try known conversions; this is an ugly hack */
276 if(strcmp(ext, ".flac") == 0 || strcmp(ext, ".FLAC") == 0)
278 /* flac file */
279 snprintf(tmp, sizeof(tmp), "flac -d -s -o '%s' '%s'",
280 c_file, file);
281 tmp[sizeof(tmp) - 1] = '\0';
283 system(tmp);
285 else
286 if(strcmp(ext, ".mp3") == 0 || strcmp(ext, ".MP3") == 0)
288 /* mp3 file */
289 snprintf(tmp, sizeof(tmp), "mpg321 -q -w '%s' '%s'",
290 c_file, file);
291 tmp[sizeof(tmp) - 1] = '\0';
293 system(tmp);
296 return(c_file);
301 * ss_load_wave_file - Loads a wave file.
302 * @file: name of the file
303 * @base_freq: base frequency
304 * @min_freq: minimum frequency
305 * @max_freq: maximum frequency
306 * @loop_start: frame number of loop start (-1, no loop)
307 * @loop_end: frame number of loop end (-1, end of wave)
309 * Loads a wave file.
311 struct ss_wave * ss_load_wave_file(char * file,
312 double base_freq, double min_freq, double max_freq,
313 double loop_start, double loop_end)
315 /* preprocess the file, given its extension */
316 if((file = wave_file_preprocess(file)) == NULL)
317 return(NULL);
319 return(ss_load_wav_file(file, base_freq, min_freq,
320 max_freq, loop_start, loop_end));
325 * ss_load_pat_file - Loads an instrument in .PAT format.
326 * @i: The instrument
327 * @filename: filename holding the instrument
329 * Loads data from a Gravis Ultrasound patch (.PAT) format and
330 * stores it as layers for an instrument.
332 * Returns -100 if the file could not be read, -101 or -102
333 * if the file is not recognized as a .PAT file, or 0 if
334 * everything went OK.
336 int ss_load_pat_file(struct ss_ins * i, char * file)
338 FILE * f;
339 char buffer[512];
340 int m, n, o;
341 int n_layers;
342 int flags, bits, sign, loop, pingpong;
343 struct ss_wave * w;
345 if((f = path_fopen(file, "r")) == NULL)
346 return(-100);
348 /* read signatures */
349 fread(buffer, 12, 1, f);
350 if(strcmp(buffer, "GF1PATCH110") != 0)
352 fclose(f);
353 return(-101);
356 fread(buffer, 10, 1, f);
357 if(strcmp(buffer, "ID#000002") != 0)
359 fclose(f);
360 return(-102);
363 /* skip description */
364 fread(buffer, 65, 1, f);
366 /* ignore volume */
367 fget16(f);
369 /* skip */
370 fread(buffer, 109, 1, f);
372 /* # of layers */
373 n_layers = fgetc(f);
375 /* skip */
376 fread(buffer, 40, 1, f);
378 for(n = 0;n < n_layers;n++)
380 int size, s_rate;
381 double loop_start, loop_end;
382 double min_freq, max_freq, base_freq;
384 /* layer name */
385 fread(buffer, 8, 1, f);
387 size = (double)fget32(f);
388 loop_start = (double)fget32(f);
389 loop_end = (double)fget32(f);
390 s_rate = fget16(f);
392 min_freq = ((double)fget32(f)) / 1000.0;
393 max_freq = ((double)fget32(f)) / 1000.0;
394 base_freq = ((double)fget32(f)) / 1000.0;
396 if(base_freq < 0)
397 break;
399 /* ignore fine-tune */
400 fget16(f);
402 /* ignore pan position */
403 fgetc(f);
405 /* skip envelope rate, value, tremolo and vibrato */
406 fread(buffer, 18, 1, f);
408 flags = fgetc(f);
410 bits = flags & 0x01 ? 16 : 8;
411 sign = flags & 0x02 ? 0 : 1;
412 loop = flags & 0x04 ? 1 : 0;
413 pingpong = flags & 0x08 ? 1 : 0;
415 if(bits == 16)
417 size /= 2;
418 loop_start /= 2;
419 loop_end /= 2;
422 /* skip frequency scale data */
423 fget16(f); fget16(f);
425 /* skip reserved */
426 fread(buffer, 36, 1, f);
428 if((w = ss_alloc_wave(size, 1, s_rate)) == NULL)
429 break;
431 /* set the rest of values */
432 w->loop_start = loop_start;
433 w->loop_end = loop_end;
434 w->base_freq = base_freq;
435 w->min_freq = min_freq;
436 w->max_freq = max_freq;
438 /* load the wave */
439 load_pcm_wave(f, bits, sign, w);
441 if(pingpong && loop)
443 int loop_size;
444 sample_t * ptr;
446 /* if ping-pong, realloc space for a reverse
447 version of the loop */
448 loop_size = (int)(loop_end - loop_start);
450 ptr = (sample_t *) malloc((size + loop_size + 1)
451 * sizeof(sample_t));
453 /* transfer start and loop */
454 for(m = 0;m <= (int)loop_end;m++)
455 ptr[m] = w->wave[0][m];
457 /* transfer a reversed version of the loop */
458 for(o = m - 1;o >= loop_start;o--, m++)
459 ptr[m] = w->wave[0][o];
461 /* transfer the end */
462 for(o = loop_end + 1;o < size;o++, m++)
463 ptr[m] = w->wave[0][o];
465 w->loop_end += (double) loop_size;
466 w->size += (double) loop_size;
468 /* free and swap */
469 free(w->wave[0]);
470 w->wave[0] = ptr;
473 if(loop == 0) w->loop_start = -1;
475 /* finally add layer to instrument */
476 ss_ins_add_layer(i, w);
479 fclose(f);
480 return(0);