Error code unification.
[ahxm.git] / wav.c
bloba80928f8f2a49a7e75a8f25a2d06aa7f4fbcf3b6
1 /*
3 wav.c
5 Copyright (C) 2003 Angel Ortega <angel@triptico.com>
7 This program is free software; you can redistribute it and/or
8 modify it under the terms of the GNU General Public License
9 as published by the Free Software Foundation; either version 2
10 of the License, or (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
21 http://www.triptico.com
25 #include <stdio.h>
26 #include <string.h>
27 #include <stdlib.h>
28 #include <math.h>
30 #include "output.h"
32 /*******************
33 Data
34 ********************/
36 /* main output frequency */
37 int _frequency=44100;
39 struct channel
41 int * wave;
42 double vol;
43 double dvol;
47 /* digital synth generators */
48 struct generator
50 int in_use; /* 2 - playing, 1 - released, 0 - free */
52 int * lwave; /* left channel wave */
53 int * rwave; /* right channel wave */
54 int size; /* size in samples */
55 double loop_start; /* start of loop (-1, no loop) */
56 double loop_end; /* end of loop */
57 double inc; /* increment */
58 double lvol; /* left volume */
59 double rvol; /* right volume */
61 double cursor; /* offset of next sample */
62 int sustain; /* number of samples to play after release */
63 double dlvol; /* delta of left volume (sustain) */
64 double drvol; /* delta of right volume (sustain) */
67 #define NUM_GENERATORS 64
68 struct generator _generators[NUM_GENERATORS];
71 /* note frequencies */
73 double _middle_A_freq=440.0;
75 #define NUM_NOTES 128
76 double _note_freq[NUM_NOTES];
79 /*******************
80 Code
81 ********************/
83 void build_note_freq(void)
85 int n;
87 for(n=0;n < NUM_NOTES;n++)
88 _note_freq[n]=(_middle_A_freq / 32.0) *
89 pow(2.0, (((double)n - 9.0) / 12.0));
93 #define TIME2SAMPLES(s) ((s) * _frequency)
95 int * wave_resample(int * wave, int freq, int * size)
97 double ratio;
98 int new_size;
99 int * new_wave;
100 int n;
101 double i;
103 ratio=(double) freq / (double) _frequency;
104 new_size=(int)((double) (*size) / ratio);
106 new_wave=(int *)malloc(new_size * sizeof(int));
108 printf("wave_resample: ratio %f\n", (float)ratio);
110 for(n=i=0;n < new_size;n++,i+=ratio)
111 new_wave[n]=wave[(int)i];
113 *size=new_size;
115 /* free the old wave */
116 free(wave);
118 return(new_wave);
122 int load_sample(FILE * f, int bits)
124 short int s;
126 if(bits==8)
128 s=fgetc(f)-128;
129 s<<=8;
131 else
133 s=fgetc(f);
134 s|=(((unsigned char)fgetc(f)) << 8);
137 return(s);
141 void load_pcm_wave(FILE * f, int * size, int bits, int channels,
142 int frequency, int ** lwave, int ** rwave)
144 int n;
145 int * ls;
146 int * rs;
148 ls=(int *)malloc(*size * sizeof(int));
150 if(channels==2)
151 rs=(int *)malloc(*size * sizeof(int));
152 else
153 rs=ls;
155 for(n=0;n < *size;n++)
157 ls[n]=load_sample(f, bits);
159 if(channels==2)
160 rs[n]=load_sample(f, bits);
163 /* resample if needed */
164 if(frequency != _frequency)
166 ls=wave_resample(ls, frequency, size);
168 if(channels==2)
169 rs=wave_resample(rs, frequency, size);
170 else
171 rs=ls;
174 *lwave=ls;
175 *rwave=rs;
179 int load_wavfile(char * filename, int * size, int ** lwave, int ** rwave)
181 FILE * f;
182 char dummydata[256];
183 int rlen,flen;
184 short int b_per_sec,num_channels,tag;
185 char riffid[5],waveid[5],fmtid[5],dataid[5];
186 int wav_frequency, wav_bits;
187 int * ls;
188 int * rs;
190 if((f=fopen(filename,"rb"))==NULL)
191 return(0);
193 fread(riffid,1,4,f);
194 riffid[4] = 0;
195 fread(&rlen,1,4,f);
196 fread(waveid,1,4,f);
197 waveid[4] = 0;
199 if(strcmp(waveid,"WAVE"))
201 fclose(f);
202 return(0);
205 fread(fmtid,1,4,f);
206 fmtid[4] = 0;
207 flen=fget32(f);
209 if(flen>240)
210 flen=240;
212 fread(&tag,1,2,f);
214 num_channels=fget16(f);
215 wav_frequency=fget32(f);
216 b_per_sec=fget32(f);
218 wav_bits=fget16(f) / num_channels;
219 wav_bits*=8;
221 fread(dummydata,1,(size_t)flen-14,f);
222 fread(dataid,1,4,f);
223 dataid[4] = 0;
225 *size=fget32(f);
226 if(wav_bits==16) (*size)/=2;
227 if(num_channels==2) (*size)/=2;
229 load_pcm_wave(f, size, wav_bits, num_channels,
230 wav_frequency, &ls, &rs);
232 fclose(f);
234 *lwave=ls;
235 *rwave=rs;
237 return(1);
241 void generator_startup(void)
243 memset(_generators, '\0', sizeof(_generators));
245 build_note_freq();
249 int generator_play(struct generator * g, int * lwave, int * rwave,
250 int size, double inc, int loop_start, int loop_end,
251 double lvol, double rvol, int sustain)
253 if(g->in_use) return(0);
255 g->in_use=2;
256 g->lwave=lwave;
257 g->rwave=rwave;
258 g->size=size;
259 g->loop_start=(double) loop_start;
260 g->loop_end=(double) loop_end;
261 g->inc=inc;
262 g->lvol=lvol;
263 g->rvol=rvol;
264 g->sustain=sustain;
266 g->cursor=0;
268 return(1);
272 int generator_release(struct generator * g)
274 if(g->in_use != 2) return(0);
276 /* if no sustain, generator can be immediately reused */
277 if(g->sustain == 0)
279 g->in_use=0;
280 return(1);
283 /* generator is released */
284 g->in_use=1;
286 /* calculates delta volume values */
287 g->dlvol=g->lvol / (double) g->sustain;
288 g->drvol=g->rvol / (double) g->sustain;
290 /* put generator in auto-stop */
291 /* g->loop_start=-1; */
292 g->loop_end=(double) g->size;
294 return(1);
298 void machine(struct generator * g, int * left, int * right)
300 int l,r;
302 /* return if generator is not active */
303 if(! g->in_use) return;
305 /* get sample */
306 l=g->lwave[(int)g->cursor];
307 r=g->rwave[(int)g->cursor];
309 /* increment pointer */
310 g->cursor+=g->inc;
312 /* test boundaries */
313 if(g->cursor > g->loop_end)
315 /* auto-stop? */
316 if(g->loop_start == -1)
317 g->in_use=0;
318 else
319 g->cursor=g->loop_start;
322 l=(int)((double)l * g->lvol);
323 r=(int)((double)r * g->rvol);
325 if(g->in_use == 1 && g->sustain != -1)
327 /* sustain mode */
328 g->lvol -= g->dlvol;
329 g->rvol -= g->drvol;
331 if(--g->sustain == 0)
332 g->in_use=0;
335 *left+=l;
336 *right+=r;
340 void sample_trim(int * left, int * right)
342 if(*left < -32768) *left=-32768;
343 if(*left > 32767) *left=32767;
344 if(*right < -32768) *right=-32768;
345 if(*right > 32767) *right=32767;
349 int main(void)
351 int * ls;
352 int * rs;
353 int size;
354 FILE * f;
355 int n, m;
357 generator_startup();
359 load_wavfile("samples/amen1.wav", &size, &ls, &rs);
361 generator_play(&_generators[0], ls, rs, size, 1, 0, size, 0.2, 1, 4410);
363 load_wavfile("samples/01c1.wav", &size, &ls, &rs);
364 generator_play(&_generators[1], ls, rs, size,
365 _note_freq[24] / _note_freq[36], 0, size, 1, 1, 44100 / 3);
367 load_wavfile("samples/05c3.wav", &size, &ls, &rs);
369 generator_play(&_generators[2], ls, rs, size,
370 _note_freq[36] / _note_freq[36], 0, size, 0.5, 0.5, 0);
372 generator_play(&_generators[3], ls, rs, size,
373 _note_freq[39] / _note_freq[36], 0, size, 0.5, 0.5, 0);
375 generator_play(&_generators[4], ls, rs, size,
376 _note_freq[43] / _note_freq[36], 0, size, 0.5, 0.5, 0);
378 load_wavfile("samples/as-al017.wav", &size, &ls, &rs);
379 generator_play(&_generators[5], ls, rs, size, 1, 0, size, 2, 2, 0);
382 f=popen("sox -V -t raw -s -r 44100 -c 2 -w - qq.wav","w");
385 if(output_open("sgi", "qq.wav") < 0)
387 printf("Error: can't init driver\n");
388 return(1);
391 for(n=TIME2SAMPLES(15);n > 0;n--)
393 int l,r;
395 l=r=0;
397 for(m=0;m < NUM_GENERATORS;m++)
398 machine(&_generators[m], &l, &r);
400 sample_trim(&l, &r);
402 output_write(l, r);
404 if(n < TIME2SAMPLES(14))
405 generator_release(&_generators[1]);
408 output_close();
410 return(0);