Fixed a bug when processing loop boundaries in SONG_EV_SS_WAV events.
[ahxm.git] / ss_input.c
blob57552cabed6096c54d9f131b80d3744f8f62f7d3
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>
32 #include "ss_core.h"
33 #include "ss_gen.h"
34 #include "ss_ins.h"
35 #include "ss_input.h"
37 /*******************
38 Data
39 ********************/
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 float load_sample(FILE * f, int bits, int sign)
72 /* loads one sample from a file */
74 int s;
76 /* Caution: no error condition is checked */
78 if(bits == 8)
80 s=fgetc(f) - 128;
81 s <<= 8;
83 else
85 if(!sign)
86 s=fget16(f) - 32768;
87 else
88 s=(short int)fget16(f);
91 return((float) s);
95 static void load_pcm_wave(FILE * f, int bits, int sign, struct ss_wave * w)
96 /* loads an interleaved stream from a file */
98 int n, i;
99 double m;
101 /* alloc buffers for channels */
102 for(n=0;n < w->n_channels;n++)
103 w->wave[n]=(float *)malloc(w->size * sizeof(float));
105 /* clean the rest of channels */
106 for(;n < CHANNELS;n++)
107 w->wave[n]=NULL;
109 /* fills the channels */
110 for(m=0;m < w->size;m++)
112 i=(int) m;
114 for(n=0;n < w->n_channels;n++)
115 w->wave[n][i]=load_sample(f, bits, sign);
121 * ss_load_wav_file - Loads a file in .WAV format.
122 * @w: the wave structure
123 * @file: name of the file
124 * @base_freq: base frequency
125 * @min_freq: minimum frequency
126 * @max_freq: maximum frequency
128 * Loads a file in .WAV format into the @w structure.
130 * Returns -100 if the file could not be opened, -101 if the file
131 * is not recognized as .WAV, -102 if the file contains anything
132 * more than uncompressed PCM data, or 0 if everything went OK.
134 int ss_load_wav_file(struct ss_wave * w, char * file, double base_freq,
135 double min_freq, double max_freq)
137 FILE * f;
138 char dummydata[256];
139 int rlen, flen;
140 short int b_per_sec, n_channels;
141 char riffid[5], waveid[5], fmtid[5], dataid[5];
142 double size;
143 int s_rate, bits;
145 if((f=fopen(file, "r")) == NULL)
146 return(-100);
148 fread(riffid, 1, 4, f);
149 riffid[4] = 0;
150 fread(&rlen, 1, 4, f);
151 fread(waveid, 1, 4, f);
152 waveid[4] = 0;
154 if(strcmp(waveid,"WAVE"))
156 fclose(f);
157 return(-101);
160 fread(fmtid, 1, 4, f);
161 fmtid[4] = 0;
162 flen=fget32(f);
164 if(flen > 240)
165 flen=240;
167 if(fget16(f) != 1)
169 /* wicked compressed format? fail */
170 fclose(f);
171 return(-102);
174 n_channels=fget16(f);
175 s_rate=fget32(f);
176 b_per_sec=fget32(f);
178 bits=fget16(f) / n_channels;
179 bits *= 8;
181 fread(dummydata, 1, (size_t)flen - 14, f);
182 fread(dataid, 1, 4, f);
183 dataid[4] = 0;
185 size=(double) fget32(f);
186 if(bits == 16) size /= 2;
187 size /= (double) n_channels;
189 /* fill the ss_wave */
190 w->size=size;
191 w->n_channels=n_channels;
192 w->s_rate=s_rate;
193 w->loop_start=-1;
194 w->loop_end=size;
195 w->base_freq=base_freq;
196 w->min_freq=min_freq;
197 w->max_freq=max_freq;
199 load_pcm_wave(f, bits, 1, w);
201 fclose(f);
203 return(0);
208 * ss_load_pat_file - Loads an instrument in .PAT format.
209 * @i: The instrument
210 * @filename: filename holding the instrument
212 * Loads data from a Gravis Ultrasound patch (.PAT) format and
213 * stores it as layers for an instrument.
215 * Returns -100 if the file could not be read, -101 or -102
216 * if the file is not recognized as a .PAT file, or 0 if
217 * everything went OK.
219 int ss_load_pat_file(struct ss_ins * i, char * file)
221 FILE * f;
222 char buffer[512];
223 int m, n, o;
224 int n_layers;
225 int flags, bits, sign, loop, pingpong;
226 struct ss_wave w;
228 if((f=fopen(file, "r")) == NULL)
229 return(-100);
231 /* read signatures */
232 fread(buffer, 12, 1, f);
233 if(strcmp(buffer, "GF1PATCH110") != 0)
235 fclose(f);
236 return(-101);
239 fread(buffer, 10, 1, f);
240 if(strcmp(buffer, "ID#000002") != 0)
242 fclose(f);
243 return(-102);
246 /* skip description */
247 fread(buffer, 65, 1, f);
249 /* ignore volume */
250 fget16(f);
252 /* skip */
253 fread(buffer, 109, 1, f);
255 /* # of layers */
256 n_layers=fgetc(f);
258 /* skip */
259 fread(buffer, 40, 1, f);
261 for(n=0;n < n_layers;n++)
263 /* layer name */
264 fread(buffer, 8, 1, f);
265 printf("name: '%s'\n", buffer);
267 w.size=(double)fget32(f);
268 w.loop_start=(double)fget32(f);
269 w.loop_end=(double)fget32(f);
270 w.s_rate=fget16(f);
272 printf("size: %d [%d-%d], s_rate: %d\n",
273 (int)w.size, (int)w.loop_start, (int)w.loop_end, w.s_rate);
275 w.min_freq=((double)fget32(f)) / 1000.0;
276 w.max_freq=((double)fget32(f)) / 1000.0;
277 w.base_freq=((double)fget32(f)) / 1000.0;
279 printf("note_freqs: %lf - %lf - %lf\n",
280 w.min_freq, w.base_freq, w.max_freq);
282 if(w.base_freq < 0)
283 break;
285 /* ignore fine-tune */
286 fget16(f);
288 /* ignore pan position */
289 fgetc(f);
291 /* skip envelope rate, value, tremolo and vibrato */
292 fread(buffer, 18, 1, f);
294 flags=fgetc(f);
295 printf("flags: 0x%02X\n", flags);
297 bits=flags & 0x01 ? 16 : 8;
298 sign=flags & 0x02 ? 0 : 1;
299 loop=flags & 0x04 ? 1 : 0;
300 pingpong=flags & 0x08 ? 1 : 0;
302 printf("bits: %d, sign: %d, loop: %d pingpong: %d\n",
303 bits, sign, loop, pingpong);
305 if(bits == 16)
307 w.size /= 2;
308 w.loop_start /= 2;
309 w.loop_end /= 2;
312 /* skip frequency scale data */
313 fget16(f); fget16(f);
315 /* skip reserved */
316 fread(buffer, 36, 1, f);
318 /* set to 1 channel (probably wrong) */
319 w.n_channels=1;
321 /* load the wave */
322 load_pcm_wave(f, bits, sign, &w);
324 if(pingpong && loop)
326 int loop_size;
327 float * ptr;
329 /* if ping-pong, realloc space for a reverse
330 version of the loop */
331 loop_size=(int)(w.loop_end - w.loop_start);
333 ptr=(float *) malloc(((int) w.size + loop_size + 1)
334 * sizeof(float));
336 /* transfer start and loop */
337 for(m=0;m <= (int)w.loop_end;m++)
338 ptr[m]=w.wave[0][m];
340 /* transfer a reversed version of the loop */
341 for(o=m-1;o >= (int)w.loop_start;o--,m++)
342 ptr[m]=w.wave[0][o];
344 /* transfer the end */
345 for(o=(int)w.loop_end + 1;o < (int)w.size;o++,m++)
346 ptr[m]=w.wave[0][o];
348 w.loop_end += (double) loop_size;
349 w.size += (double) loop_size;
351 /* free and swap */
352 free(w.wave[0]);
353 w.wave[0]=ptr;
356 if(loop == 0) w.loop_start=-1;
358 /* finally add layer to instrument */
359 ss_ins_add_layer(i, &w);
362 fclose(f);
363 return(0);