[1] | 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 | }
|
---|