1 | /***********************************************************************/
|
---|
2 | /* */
|
---|
3 | /* str.c - plays sound/noisetracker files on a SparcStation */
|
---|
4 | /* modified for thomson 6bit D/A */
|
---|
5 | /* corrected core dump on */
|
---|
6 | /* Authors : Liam Corner - zenith@dcs.warwick.ac.uk */
|
---|
7 | /* Marc Espie - espie@dmi.ens.fr */
|
---|
8 | /* Version : 1.20 - 3 November 1991 */
|
---|
9 | /* */
|
---|
10 | /* */
|
---|
11 | /***********************************************************************/
|
---|
12 |
|
---|
13 |
|
---|
14 | #include <stdio.h>
|
---|
15 | #include <stdlib.h>
|
---|
16 | #include <malloc.h>
|
---|
17 |
|
---|
18 |
|
---|
19 | /**********************************************************/
|
---|
20 | /* uS is the number of uSeconds that a byte is played for */
|
---|
21 | /* Sparc plays at 8000 bytes/sec => 1 byte = 125 uSec */
|
---|
22 | /* VSYNC is the number of bytes played in 1/50 sec */
|
---|
23 | /* ie 0.02/(uS * 10**-6) */
|
---|
24 | /**********************************************************/
|
---|
25 | #define uS 125
|
---|
26 | #define VSYNC 160
|
---|
27 | #define AUDIO "./out.raw"
|
---|
28 |
|
---|
29 | #define MIN(A,B) ((A)<(B) ? (A) : (B))
|
---|
30 | #define MAX(A,B) ((A)>(B) ? (A) : (B))
|
---|
31 |
|
---|
32 |
|
---|
33 | typedef struct { /***********************************/
|
---|
34 | signed char *info; /* Sample */
|
---|
35 | int length; /* Length of sample */
|
---|
36 | float volume; /* Fractional volume 0-1 (min-max) */
|
---|
37 | int rep_start; /* Byte offset of repeat start */
|
---|
38 | int rep_end; /* Byte offset of repeat end */
|
---|
39 | } Voice; /***********************************/
|
---|
40 |
|
---|
41 |
|
---|
42 | typedef struct { /**************************/
|
---|
43 | char sample [64][4]; /* Sample number */
|
---|
44 | char effect [64][4]; /* Effect number */
|
---|
45 | unsigned char params [64][4]; /* Effect parameters */
|
---|
46 | int period [64][4]; /* Period (pitch) of note */
|
---|
47 | } Pattern; /**************************/
|
---|
48 |
|
---|
49 |
|
---|
50 | typedef struct { /***********************************************/
|
---|
51 | char samp; /* Sample number of current note */
|
---|
52 | int pitch; /* Current channel pitch (index to step_table) */
|
---|
53 | int slide; /* Step size of pitch slide (if any) */
|
---|
54 | int doslide;
|
---|
55 | unsigned int pointer; /* Current sample position */
|
---|
56 | unsigned int step; /* Sample offset increment (gives pitch) */
|
---|
57 | float volume; /* Fractional volume of current note */
|
---|
58 | float volslide;
|
---|
59 | int doslidevol;
|
---|
60 | int doporta;
|
---|
61 | int pitchgoal;
|
---|
62 | int portarate;
|
---|
63 | } Channel; /***********************************************/
|
---|
64 |
|
---|
65 |
|
---|
66 | #define MX_CHUNKS_IN_SONG 80000
|
---|
67 | #define MX_CHUNKS_NB 80000
|
---|
68 | int song_chunks_index=0;
|
---|
69 | int song_chunks[MX_CHUNKS_IN_SONG];
|
---|
70 | int nb_chunk=0;
|
---|
71 | char chunks[MX_CHUNKS_NB][VSYNC];
|
---|
72 | int cur_chunk_index=0;
|
---|
73 | char cur_chunk[VSYNC*10];
|
---|
74 |
|
---|
75 | int cmp_chunks(char *a, char *b, int size,int mask) {
|
---|
76 | int i;
|
---|
77 | int diff;
|
---|
78 | // 1st pass ok if equal with mask
|
---|
79 | for (i=0;i<size;i++) {
|
---|
80 | if ((a[i]&mask) != (b[i]&mask)) break;
|
---|
81 | }
|
---|
82 | // 2nd pass... very lossy :)
|
---|
83 | if (i==size) return 0;
|
---|
84 | diff=0;
|
---|
85 | for (i=0;i<size;i++) {
|
---|
86 | if ((a[i]&mask) != (b[i]&mask)) diff++;
|
---|
87 | if (diff>32) return -1;
|
---|
88 | }
|
---|
89 |
|
---|
90 | return 0;
|
---|
91 | }
|
---|
92 |
|
---|
93 | void insert_cur_chunk(void) {
|
---|
94 | int i;
|
---|
95 | for (i=0;i<nb_chunk;i++) {
|
---|
96 | // if (memcmp(cur_chunk,chunks[i],VSYNC)==0) break;
|
---|
97 | if (cmp_chunks(cur_chunk,chunks[i],VSYNC,0xFF)==0) break;
|
---|
98 | }
|
---|
99 | if (i==nb_chunk) {
|
---|
100 | memcpy(chunks[i],cur_chunk,VSYNC);
|
---|
101 | song_chunks[song_chunks_index]=i;
|
---|
102 | song_chunks_index++;
|
---|
103 | nb_chunk++;
|
---|
104 |
|
---|
105 | } else {
|
---|
106 | song_chunks[song_chunks_index]=i;
|
---|
107 | song_chunks_index++;
|
---|
108 | if (song_chunks_index>=MX_CHUNKS_NB)
|
---|
109 | {
|
---|
110 | fprintf(stderr,"Argh I'm dead... %d %d\n",song_chunks_index,i);
|
---|
111 | exit(-1);
|
---|
112 | }
|
---|
113 | }
|
---|
114 | }
|
---|
115 |
|
---|
116 | void rebuild_from_chunks(char * fname) {
|
---|
117 | FILE *f;
|
---|
118 | int i,j;
|
---|
119 |
|
---|
120 | f=fopen(fname,"w");
|
---|
121 |
|
---|
122 | for (i=0;i<song_chunks_index;i++) {
|
---|
123 | fwrite(chunks[song_chunks[i]],1,VSYNC,f);
|
---|
124 | }
|
---|
125 |
|
---|
126 | fclose(f);
|
---|
127 | }
|
---|
128 |
|
---|
129 | /*
|
---|
130 | reconstruit des fichiers par banque de 16ko
|
---|
131 | fichier 0 : patterns bank+offset (/128)
|
---|
132 | fichiers 1 à n : chunks
|
---|
133 | */
|
---|
134 |
|
---|
135 | void build_outfiles(char * base) {
|
---|
136 | int ficnum,i,j,k;
|
---|
137 | FILE *f;
|
---|
138 | char str[1024];
|
---|
139 |
|
---|
140 | ficnum=0;
|
---|
141 |
|
---|
142 | sprintf(str,"%s%02d.BIN",base,ficnum);
|
---|
143 | f=fopen(str,"w");
|
---|
144 |
|
---|
145 | for (j=0;j<song_chunks_index;j++) {
|
---|
146 | fputc((song_chunks[j]/64)+6,f);
|
---|
147 | fputc(song_chunks[j]&0x3F,f);
|
---|
148 | }
|
---|
149 |
|
---|
150 | fclose(f);
|
---|
151 |
|
---|
152 | ficnum++;
|
---|
153 |
|
---|
154 | for (j=0;j<(nb_chunk/64)+1;j++) {
|
---|
155 | sprintf(str,"%s%02d.BIN",base,ficnum);
|
---|
156 | f=fopen(str,"w");
|
---|
157 | for (k=0;k<64;k++) {
|
---|
158 | for (i=0;i<160;i++) {
|
---|
159 | char c1;
|
---|
160 | c1=chunks[j*64+k][i];
|
---|
161 | fputc(c1,f);
|
---|
162 | }
|
---|
163 | for (i=160;i<256;i++) {
|
---|
164 | fputc(0,f);
|
---|
165 | }
|
---|
166 | } // of for k
|
---|
167 |
|
---|
168 | fclose(f);
|
---|
169 | ficnum++;
|
---|
170 | } // of for j
|
---|
171 | }
|
---|
172 |
|
---|
173 | /****************************************************************************/
|
---|
174 | /* Skips the next 'n' input bytes - because fseek won't work on stdin */
|
---|
175 | /****************************************************************************/
|
---|
176 | void byteskip (fp, bytes)
|
---|
177 | FILE *fp;
|
---|
178 | int bytes;
|
---|
179 | {
|
---|
180 | int loop;
|
---|
181 |
|
---|
182 | for (loop = 0; loop < bytes; loop++)
|
---|
183 | getc(fp);
|
---|
184 | }
|
---|
185 |
|
---|
186 |
|
---|
187 |
|
---|
188 | char *getstring(f, len)
|
---|
189 | FILE *f;
|
---|
190 | int len;
|
---|
191 | {
|
---|
192 | static char s[150];
|
---|
193 | int i;
|
---|
194 |
|
---|
195 | for (i = 0; i < len; i++)
|
---|
196 | s[i] = fgetc(f);
|
---|
197 | s[len] = '\0';
|
---|
198 | return s;
|
---|
199 | }
|
---|
200 |
|
---|
201 | #define OLD 0
|
---|
202 | #define NEW 1
|
---|
203 |
|
---|
204 | int main (argc, argv)
|
---|
205 | int argc;
|
---|
206 | char **argv;
|
---|
207 | {
|
---|
208 | FILE *fp, *audio;
|
---|
209 | int loop;
|
---|
210 | int notes, note, channel, vsync;
|
---|
211 | int pat, pat_num;
|
---|
212 | int byte, bytes;
|
---|
213 | int step_table[1024];
|
---|
214 | int speed=6; /* Default speed is 6 */
|
---|
215 | int end_pattern=0;
|
---|
216 | char songlength;
|
---|
217 | char tune[128];
|
---|
218 | char num_patterns=0;
|
---|
219 | unsigned char ulaw;
|
---|
220 | float dummy1, dummy2;
|
---|
221 | Voice voices[32];
|
---|
222 | Pattern patterns[64];
|
---|
223 | Channel ch[4];
|
---|
224 | int nvoices;
|
---|
225 | int effect;
|
---|
226 |
|
---|
227 | int type; /* module type: old or new */
|
---|
228 | char *command; /* the actual command name used */
|
---|
229 |
|
---|
230 | command = argv[0];
|
---|
231 |
|
---|
232 | type = NEW;
|
---|
233 |
|
---|
234 |
|
---|
235 | if (type == OLD)
|
---|
236 | nvoices = 15;
|
---|
237 | else
|
---|
238 | nvoices = 31;
|
---|
239 |
|
---|
240 | if (argc>2)
|
---|
241 | {
|
---|
242 | fprintf(stderr,"Usage: %s [<filename>]\n", command);
|
---|
243 | exit(1);
|
---|
244 | }
|
---|
245 |
|
---|
246 | /***********************************************************************/
|
---|
247 | /* Creates a table of the byte_step << 16 for a given pitch */
|
---|
248 | /* The step and pointer are stored << 16 to get accuracy without floats*/
|
---|
249 | /* eg to get double pitch only play every other byte */
|
---|
250 | /* so step of 0x10000 is normal pitch, 0x8000 is half, */
|
---|
251 | /* 0x20000 is double. Pointer is >> 16 when accessed, */
|
---|
252 | /* so 0x10000 is 1st byte, 0x20000 2nd etc */
|
---|
253 | /* I have no idea where the other numbers are from, I copied them from */
|
---|
254 | /* a SoundTracker player for the Acorn Archimedes */
|
---|
255 | /* */
|
---|
256 | /* Actually, these other numbers are highly dependent on the amiga hw. */
|
---|
257 | /***********************************************************************/
|
---|
258 | step_table[0] = 0;
|
---|
259 | for (loop = 1; loop < 1024; loop++)
|
---|
260 | {
|
---|
261 | dummy1 = 3575872 / loop;
|
---|
262 | dummy2 = (dummy1 / (1000000 /uS) ) * 60000;
|
---|
263 | step_table[loop] = (int)dummy2;
|
---|
264 | }
|
---|
265 |
|
---|
266 | if (argc < 2)
|
---|
267 | fp = stdin;
|
---|
268 | else
|
---|
269 | fp = fopen(argv[1], "r");
|
---|
270 | if (fp == NULL)
|
---|
271 | {
|
---|
272 | fprintf(stderr, "%s: unable to open tune file %s\n",
|
---|
273 | command, argv[1]);
|
---|
274 | exit(1);
|
---|
275 | }
|
---|
276 |
|
---|
277 | /* read song name */
|
---|
278 | printf("Module : %s\n\n", getstring(fp, 20));
|
---|
279 |
|
---|
280 | /* Reads in the sample-information tables */
|
---|
281 | for (loop = 1; loop <= nvoices; loop++)
|
---|
282 | {
|
---|
283 | printf("%6d : %s\n", loop, getstring(fp, 22));
|
---|
284 | voices[loop].length = ( (getc(fp) << 8) | getc(fp) ) * 2;
|
---|
285 | getc(fp);
|
---|
286 | voices[loop].volume = getc(fp);
|
---|
287 | voices[loop].volume = MIN(voices[loop].volume, 64);
|
---|
288 | voices[loop].volume /= 64; /* Volume is a fraction */
|
---|
289 | voices[loop].rep_start = ( (getc(fp) << 8) | getc(fp) ) * 2;
|
---|
290 | voices[loop].rep_end = ( (getc(fp) << 8) | getc(fp) ) * 2;
|
---|
291 | if (voices[loop].rep_end <= 4)
|
---|
292 | voices[loop].rep_end = 0;
|
---|
293 | else
|
---|
294 | {
|
---|
295 | /* If there is a repeat then end=start+length, but must be */
|
---|
296 | /* less than the sample length. Not sure if this is 100% */
|
---|
297 | /* correct, but it seems to work OK :-) */
|
---|
298 | if (voices[loop].rep_end + voices[loop].rep_start - 1
|
---|
299 | > voices[loop].length)
|
---|
300 | voices[loop].rep_start >>= 1;
|
---|
301 | voices[loop].rep_end += voices[loop].rep_start;
|
---|
302 | voices[loop].rep_end = MIN(voices[loop].rep_end,
|
---|
303 | voices[loop].length);
|
---|
304 | }
|
---|
305 | }
|
---|
306 | voices[0].length = 0;
|
---|
307 |
|
---|
308 | songlength = getc(fp);
|
---|
309 | byteskip(fp, 1);
|
---|
310 |
|
---|
311 | /* Reads in the tune */
|
---|
312 | for (loop = 0; loop < 128; loop++)
|
---|
313 | {
|
---|
314 | tune[loop] = getc(fp);
|
---|
315 | if (tune[loop] > num_patterns)
|
---|
316 | num_patterns = tune[loop];
|
---|
317 | }
|
---|
318 | num_patterns++;
|
---|
319 |
|
---|
320 | /* skip over sig (usually M.K.) */
|
---|
321 | if (type == NEW)
|
---|
322 | byteskip(fp,4);
|
---|
323 |
|
---|
324 | /* Reads in the patterns */
|
---|
325 | for (pat_num = 0; pat_num < num_patterns; pat_num++)
|
---|
326 | {
|
---|
327 | /* 64 notes per pattern */
|
---|
328 | for (notes = 0; notes < 64; notes++)
|
---|
329 | {
|
---|
330 | /* 4 channels per note */
|
---|
331 | for (channel = 0; channel < 4; channel++)
|
---|
332 | {
|
---|
333 | note = (getc(fp) << 24) | (getc(fp) << 16) |
|
---|
334 | (getc(fp) << 8) | getc(fp);
|
---|
335 | (patterns[pat_num]).effect[notes][channel] =
|
---|
336 | (note & 0xF00) >> 8;
|
---|
337 | (patterns[pat_num]).params[notes][channel] = note & 0xFF;
|
---|
338 | (patterns[pat_num]).sample[notes][channel] =
|
---|
339 | ( (note & 0xF000) >> 12) | ( (note >> 24) & 0x10);
|
---|
340 | (patterns[pat_num]).period[notes][channel] =
|
---|
341 | MIN( (note & 0xFFF0000) >> 16, 1023);
|
---|
342 | }
|
---|
343 | }
|
---|
344 | }
|
---|
345 |
|
---|
346 | /* Stores the samples voices as an array of char */
|
---|
347 | for (loop = 1; loop <= nvoices; loop++)
|
---|
348 | {
|
---|
349 | voices[loop].info = malloc(voices[loop].length);
|
---|
350 | if (voices[loop].info == NULL)
|
---|
351 | {
|
---|
352 | fprintf(stderr, "%s: unable to allocate memory\n", command);
|
---|
353 | exit(1);
|
---|
354 | }
|
---|
355 | fread(voices[loop].info, 1, voices[loop].length, fp);
|
---|
356 | }
|
---|
357 | // audio = fopen(AUDIO, "w");
|
---|
358 | // if (audio == NULL)
|
---|
359 | // {
|
---|
360 | // fprintf(stderr, "%s: unable to access %s\n", command, AUDIO);
|
---|
361 | // exit(1);
|
---|
362 | // }
|
---|
363 |
|
---|
364 | for (loop = 0; loop < 4; loop++)
|
---|
365 | {
|
---|
366 | ch[loop].samp=0; /* GFE : added this to avoid nasty core dumps :) */
|
---|
367 | ch[loop].pointer = 0;
|
---|
368 | ch[loop].step = 0;
|
---|
369 | ch[loop].volume = 0;
|
---|
370 | ch[loop].pitch = 0;
|
---|
371 | }
|
---|
372 |
|
---|
373 | printf("\nPosition (%d):", songlength);
|
---|
374 | fflush(stdout);
|
---|
375 |
|
---|
376 | for (pat_num = 0; pat_num < songlength; pat_num++)
|
---|
377 | {
|
---|
378 | printf("\r\t\t%3d", pat_num);
|
---|
379 | fflush(stdout);
|
---|
380 | pat = tune[pat_num];
|
---|
381 | end_pattern = 0;
|
---|
382 | for (notes = 0; notes < 64; notes++)
|
---|
383 | {
|
---|
384 | for (channel = 0; channel < 4; channel++)
|
---|
385 | {
|
---|
386 | int samp, pitch, cmd, para;
|
---|
387 |
|
---|
388 | samp = patterns[pat].sample[notes][channel];
|
---|
389 | pitch = patterns[pat].period[notes][channel];
|
---|
390 | cmd = patterns[pat].effect[notes][channel];
|
---|
391 | para = patterns[pat].params[notes][channel];
|
---|
392 | if (samp)
|
---|
393 | {
|
---|
394 | ch[channel].samp = samp;
|
---|
395 | /* load new instrument */
|
---|
396 | ch[channel].volume = voices[ch[channel].samp].volume;
|
---|
397 | }
|
---|
398 | /* If sample number=0 and no new period */
|
---|
399 | /* continue last note */
|
---|
400 | if (pitch && cmd != 3)
|
---|
401 | {
|
---|
402 | ch[channel].pointer = 0;
|
---|
403 | ch[channel].step = step_table[pitch];
|
---|
404 | ch[channel].pitch = pitch;
|
---|
405 | }
|
---|
406 | ch[channel].doslide = 0;
|
---|
407 | ch[channel].doslidevol = 0;
|
---|
408 | ch[channel].doporta = 0;
|
---|
409 | switch(cmd) /* Do effects */
|
---|
410 | {
|
---|
411 | case 0xF :
|
---|
412 | speed = para;
|
---|
413 | break;
|
---|
414 | case 0xD :
|
---|
415 | end_pattern = 1;
|
---|
416 | break;
|
---|
417 | case 0xC :
|
---|
418 | ch[channel].volume= MIN(para, 64);
|
---|
419 | ch[channel].volume /= 64;
|
---|
420 | break;
|
---|
421 | /* volume_slicur_chunk_indexde */
|
---|
422 | case 0xB :
|
---|
423 | pat_num = (para & 0xF) + (10 * (para >> 4));
|
---|
424 | break;
|
---|
425 | case 0xA :
|
---|
426 | ch[channel].doslidevol = 1;
|
---|
427 | if (para)
|
---|
428 | {
|
---|
429 | if (para & 15)
|
---|
430 | ch[channel].volslide = - para / 64;
|
---|
431 | else
|
---|
432 | ch[channel].volslide = (para >> 4)/64;
|
---|
433 | }
|
---|
434 | break;
|
---|
435 | case 3 :
|
---|
436 | ch[channel].doporta = 1;
|
---|
437 | if (para)
|
---|
438 | ch[channel].portarate = para;
|
---|
439 | if (pitch)
|
---|
440 | ch[channel].pitchgoal = pitch;
|
---|
441 | break;
|
---|
442 | case 2 :
|
---|
443 | ch[channel].doslide = 1;
|
---|
444 | if (para)
|
---|
445 | ch[channel].slide = para;
|
---|
446 | break;
|
---|
447 | case 1 :
|
---|
448 | ch[channel].doslide = 1;
|
---|
449 | if (para)
|
---|
450 | ch[channel].slide = -para;
|
---|
451 | break;
|
---|
452 | case 0 :
|
---|
453 | break;
|
---|
454 | default :
|
---|
455 | /* printf(" [%d][%d] ", cmd, para); */
|
---|
456 | break;
|
---|
457 | }
|
---|
458 | }
|
---|
459 | /* 1 vsync = 0.02 sec */
|
---|
460 | for (vsync = 0; vsync < speed; vsync++)
|
---|
461 | {
|
---|
462 | /* 160*125uSec = 0.02 */
|
---|
463 | for (bytes = 0; bytes < VSYNC; bytes++)
|
---|
464 | {
|
---|
465 | byte = 0;
|
---|
466 | for (channel = 0; channel < 4; channel++)
|
---|
467 | {
|
---|
468 | if (ch[channel].samp == 0)
|
---|
469 | continue;
|
---|
470 | /* If at end of sample jump to rep_start position */
|
---|
471 | if (voices[ch[channel].samp].rep_end)
|
---|
472 | {
|
---|
473 | if ((ch[channel].pointer >> 16) >=
|
---|
474 | voices[ch[channel].samp].rep_end)
|
---|
475 | ch[channel].pointer +=
|
---|
476 | (voices[ch[channel].samp].rep_start -
|
---|
477 | voices[ch[channel].samp].length)<< 16;
|
---|
478 | }
|
---|
479 | else
|
---|
480 | if ((ch[channel].pointer >> 16) >=
|
---|
481 | voices[ch[channel].samp].length)
|
---|
482 | continue;
|
---|
483 | /* byte = sum of (sample byte * volume) for each */
|
---|
484 | /* of 4 channels which mixes the sounds */
|
---|
485 | if ((ch[channel].pointer >> 16) <
|
---|
486 | voices[ch[channel].samp].length)
|
---|
487 | {
|
---|
488 | byte += (int) ( (voices[ch[channel].samp]
|
---|
489 | .info[ch[channel].pointer >> 16])
|
---|
490 | * (ch[channel].volume));
|
---|
491 | ch[channel].pointer += ch[channel].step;
|
---|
492 | }
|
---|
493 | } // of for channel
|
---|
494 |
|
---|
495 | // clip
|
---|
496 | if (byte>127) byte=127;
|
---|
497 | if (byte<-128) byte=-128;
|
---|
498 |
|
---|
499 | // make unsigned
|
---|
500 | byte+=128;
|
---|
501 | byte /= 4;
|
---|
502 |
|
---|
503 | // fputc(byte, audio); /* and play the note */
|
---|
504 | cur_chunk[cur_chunk_index]=byte;
|
---|
505 | cur_chunk_index++;
|
---|
506 | } // of for bytes
|
---|
507 | insert_cur_chunk();
|
---|
508 | cur_chunk_index=0;
|
---|
509 | /* Do end of vsync */
|
---|
510 | if (vsync == 0)
|
---|
511 | continue;
|
---|
512 | for (channel = 0; channel < 4; channel++)
|
---|
513 | {
|
---|
514 | if (ch[channel].doslide) /* effects */
|
---|
515 | {
|
---|
516 | ch[channel].pitch += ch[channel].slide;
|
---|
517 | ch[channel].pitch = MIN(ch[channel].pitch, 1023);
|
---|
518 | ch[channel].pitch = MAX(ch[channel].pitch, 113);
|
---|
519 | ch[channel].step = step_table[ch[channel].pitch];
|
---|
520 | }
|
---|
521 | if (ch[channel].doslidevol)
|
---|
522 | {
|
---|
523 | ch[channel].volume += ch[channel].volslide;
|
---|
524 | if (ch[channel].volume < 0.0)
|
---|
525 | ch[channel].volume = 0.0;
|
---|
526 | else if (ch[channel].volume >= 1.0)
|
---|
527 | ch[channel].volume = 1.0;
|
---|
528 | }
|
---|
529 | if (ch[channel].doporta)
|
---|
530 | {
|
---|
531 | if (ch[channel].pitch < ch[channel].pitchgoal)
|
---|
532 | {
|
---|
533 | ch[channel].pitch += ch[channel].portarate;
|
---|
534 | if (ch[channel].pitch > ch[channel].pitchgoal)
|
---|
535 | ch[channel].pitch = ch[channel].pitchgoal;
|
---|
536 | }
|
---|
537 | else if (ch[channel].pitch > ch[channel].pitchgoal)
|
---|
538 | {
|
---|
539 | ch[channel].pitch -= ch[channel].portarate;
|
---|
540 | if (ch[channel].pitch < ch[channel].pitchgoal)
|
---|
541 | ch[channel].pitch = ch[channel].pitchgoal;
|
---|
542 | }
|
---|
543 | }
|
---|
544 | }
|
---|
545 | }
|
---|
546 | if (end_pattern == 1)
|
---|
547 | break;
|
---|
548 | } // of for notes
|
---|
549 | for (loop = 0; loop < 4; loop++)
|
---|
550 | {
|
---|
551 | ch[loop].samp=0; /* GFE : added this to avoid nasty core dumps :) */
|
---|
552 | ch[loop].pointer = 0;
|
---|
553 | ch[loop].step = 0;
|
---|
554 | ch[loop].volume = 0;
|
---|
555 | ch[loop].pitch = 0;
|
---|
556 | }
|
---|
557 | } // of for pattern
|
---|
558 |
|
---|
559 | // fclose(audio);
|
---|
560 | rebuild_from_chunks("out2.raw");
|
---|
561 | build_outfiles("MOD");
|
---|
562 | printf("\n");
|
---|
563 | fprintf(stdout,"%d chunks %d chunks in song\n",nb_chunk,song_chunks_index);
|
---|
564 | return (0);
|
---|
565 | }
|
---|