Changes in uspace/lib/trackmod/trackmod.c [7e69e0e:43dd72b7] in mainline
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/lib/trackmod/trackmod.c
r7e69e0e r43dd72b7 40 40 41 41 #include "macros.h" 42 #include "protracker.h" 42 43 #include "trackmod.h" 44 #include "xm.h" 43 45 44 46 /** Tunables */ … … 52 54 base_clock = 8363 * 428, 53 55 /** Maximum sample volume */ 54 vol_max = 6 3,55 /** Default TPR*/56 def_tpr = 6,57 /** Default BPM*/58 def_bpm = 12556 vol_max = 64, 57 /** Minimum period */ 58 period_min = 113, 59 /** Maxium period */ 60 period_max = 856 59 61 }; 60 62 63 /** Table for finetune computation. 64 * 65 * Finetune is a number ft in [-8 .. 7]. The pitch should be adjusted by 66 * ft/8 semitones. To adjust pitch by 1/8 semitone down we can mutiply the 67 * period by 2^(1/12/8) =. 1.0072, one semitone up: 2^-(1/12/8) =. 0.9928, 68 * to adjust by ft/8 semitones, multiply by 2^(-ft/12/8). 69 * 70 * finetune_factor[ft] := 10000 * 2^(-ft/12/8) 71 * res_period = clip(period * fineture_factor[ft+8] / 10000) 72 */ 73 static unsigned finetune_factor[16] = { 74 10595, 10518, 10443, 10368, 10293, 10219, 10145, 10072, 75 10000, 9928, 9857, 9786, 9715, 9645, 9576, 9507 76 }; 77 78 static unsigned period_table[12 * 8] = { 79 907,900,894,887,881,875,868,862,856,850,844,838,832,826,820,814, 80 808,802,796,791,785,779,774,768,762,757,752,746,741,736,730,725, 81 720,715,709,704,699,694,689,684,678,675,670,665,660,655,651,646, 82 640,636,632,628,623,619,614,610,604,601,597,592,588,584,580,575, 83 570,567,563,559,555,551,547,543,538,535,532,528,524,520,516,513, 84 508,505,502,498,494,491,487,484,480,477,474,470,467,463,460,457 85 }; 86 61 87 static size_t trackmod_get_next_ord_idx(trackmod_modplay_t *); 62 88 … … 70 96 } 71 97 98 /** Destroy instrument. 99 * 100 * @param instr Intrument 101 */ 102 static void trackmod_instr_destroy(trackmod_instr_t *instr) 103 { 104 size_t i; 105 106 for (i = 0; i < instr->samples; i++) 107 trackmod_sample_destroy(&instr->sample[i]); 108 } 109 72 110 /** Destroy pattern. 73 111 * … … 97 135 98 136 /* Destroy samples */ 99 if (module-> sample!= NULL) {100 for (i = 0; i < module-> samples; i++)101 trackmod_ sample_destroy(&module->sample[i]);102 free(module-> sample);137 if (module->instr != NULL) { 138 for (i = 0; i < module->instrs; i++) 139 trackmod_instr_destroy(&module->instr[i]); 140 free(module->instr); 103 141 } 104 142 … … 114 152 } 115 153 154 int trackmod_module_load(char *fname, trackmod_module_t **rmodule) 155 { 156 int rc; 157 158 rc = trackmod_xm_load(fname, rmodule); 159 if (rc == EOK) 160 return EOK; 161 162 rc = trackmod_protracker_load(fname, rmodule); 163 return rc; 164 } 165 166 116 167 /** Return current pattern. 117 168 * … … 137 188 size_t row, size_t channel, trackmod_cell_t *cell) 138 189 { 139 uint32_t code; 140 141 code = pattern->data[row * pattern->channels + channel]; 142 cell->period = (code >> (4 * 4)) & 0xfff; 143 cell->sample = (((code >> (7 * 4)) & 0xf) << 4) | 144 ((code >> (3 * 4)) & 0xf); 145 cell->effect = code & 0xfff; 146 } 147 148 /** Process note (period, sample index) 190 *cell = pattern->data[row * pattern->channels + channel]; 191 } 192 193 /** Compute floor(a / b), and the remainder. 194 * 195 * Unlike standard integer division this rounds towars negative infinity, 196 * not towards zero. 197 * 198 * @param a Dividend 199 * @param b Divisor 200 * @param quot Place to store 'quotient' (floor (a/b)) 201 * @param rem Place to store 'remainder' (a - floor(a/b) * b) 202 */ 203 static void divmod_floor(int a, int b, int *quot, int *rem) 204 { 205 if (b < 0) { 206 a = -a; 207 b = -b; 208 } 209 210 if (a >= 0) { 211 *quot = a / b; 212 *rem = a % b; 213 } else { 214 *quot = - (-a + (b - 1)) / b; 215 *rem = a - (*quot * b); 216 } 217 } 218 219 /** Process note (period) 149 220 * 150 221 * @param modplay Module playback … … 156 227 { 157 228 trackmod_chan_t *chan = &modplay->chan[i]; 158 size_t smpidx; 159 160 smpidx = (cell->sample - 1) % modplay->module->samples; 161 chan->sample = &modplay->module->sample[smpidx]; 229 int period; 230 int pitch; 231 int octave; 232 int opitch; 233 234 if (chan->sample == NULL) 235 return; 236 237 if (cell->period == 0) { 238 pitch = 8 * (cell->note + chan->sample->rel_note) + 239 chan->sample->finetune; 240 divmod_floor(pitch, 8 * 12, &octave, &opitch); 241 242 if (octave >= 0) 243 period = period_table[opitch] * 8 / (1 << octave); 244 else 245 period = period_table[opitch] * 8 * (1 << (-octave)); 246 } else { 247 period = cell->period; 248 period = period * 249 finetune_factor[chan->sample->finetune + 8] / 10000; 250 if (period > period_max) 251 period = period_max; 252 if (period < period_min) 253 period = period_min; 254 } 255 256 chan->period_new = period; 257 } 258 259 /** Process instrument number (this is what triggers the note playback) 260 * 261 * @param modplay Module playback 262 * @param i Channel number 263 * @param cell Cell 264 */ 265 static void trackmod_process_instr(trackmod_modplay_t *modplay, size_t i, 266 trackmod_cell_t *cell) 267 { 268 trackmod_chan_t *chan = &modplay->chan[i]; 269 trackmod_instr_t *instr; 270 size_t iidx; 271 size_t sidx; 272 273 if (cell->instr == 0) 274 return; 275 276 iidx = (cell->instr - 1) % modplay->module->instrs; 277 instr = &modplay->module->instr[iidx]; 278 sidx = instr->key_smp[cell->note] % instr->samples; 279 chan->sample = &instr->sample[sidx]; 162 280 chan->smp_pos = 0; 163 281 chan->lsmp = 0; 164 chan->period = cell->period; 282 165 283 chan->volume = modplay->chan[i].sample->def_vol; 284 } 285 286 /** Process keyoff note 287 * 288 * @param modplay Module playback 289 * @param i Channel number 290 * @param cell Cell 291 */ 292 static void trackmod_process_keyoff_note(trackmod_modplay_t *modplay, size_t i) 293 { 294 trackmod_chan_t *chan = &modplay->chan[i]; 295 296 chan->sample = NULL; 297 chan->period = 0; 298 chan->smp_pos = 0; 299 chan->lsmp = 0; 166 300 } 167 301 … … 175 309 uint8_t param) 176 310 { 177 modplay->chan[chan].volume = param & vol_max;311 modplay->chan[chan].volume = param % (vol_max + 1); 178 312 } 179 313 … … 189 323 size_t next_idx; 190 324 trackmod_pattern_t *next_pat; 325 unsigned row; 326 327 /* Strangely the parameter is BCD */ 328 row = (param >> 4) * 10 + (param & 0xf); 191 329 192 330 next_idx = trackmod_get_next_ord_idx(modplay); … … 194 332 195 333 modplay->pat_break = true; 196 modplay->pat_break_row = param% next_pat->rows;334 modplay->pat_break_row = row % next_pat->rows; 197 335 } 198 336 … … 212 350 } 213 351 352 /** Process Fine volume slide down effect. 353 * 354 * @param modplay Module playback 355 * @param chan Channel number 356 * @param param Effect parameter 357 */ 358 static void trackmod_effect_fine_vol_slide_down(trackmod_modplay_t *modplay, 359 size_t chan, uint8_t param) 360 { 361 int nv; 362 363 nv = modplay->chan[chan].volume - param; 364 if (nv < 0) 365 nv = 0; 366 modplay->chan[chan].volume = nv; 367 } 368 369 /** Process Fine volume slide up effect. 370 * 371 * @param modplay Module playback 372 * @param chan Channel number 373 * @param param Effect parameter 374 */ 375 static void trackmod_effect_fine_vol_slide_up(trackmod_modplay_t *modplay, 376 size_t chan, uint8_t param) 377 { 378 int nv; 379 380 nv = modplay->chan[chan].volume + param; 381 if (nv > vol_max) 382 nv = vol_max; 383 modplay->chan[chan].volume = nv; 384 } 385 386 /** Process Volume slide effect. 387 * 388 * @param modplay Module playback 389 * @param chan Channel number 390 * @param param Effect parameter 391 */ 392 static void trackmod_effect_vol_slide(trackmod_modplay_t *modplay, 393 size_t chan, uint8_t param) 394 { 395 if ((param & 0xf0) != 0) 396 modplay->chan[chan].vol_slide = param >> 4; 397 else 398 modplay->chan[chan].vol_slide = -(int)(param & 0xf); 399 } 400 401 /** Process Volume slide down effect. 402 * 403 * @param modplay Module playback 404 * @param chan Channel number 405 * @param param Effect parameter 406 */ 407 static void trackmod_effect_vol_slide_down(trackmod_modplay_t *modplay, 408 size_t chan, uint8_t param4) 409 { 410 modplay->chan[chan].vol_slide = -(int)param4; 411 } 412 413 /** Process Volume slide up effect. 414 * 415 * @param modplay Module playback 416 * @param chan Channel number 417 * @param param Effect parameter 418 */ 419 static void trackmod_effect_vol_slide_up(trackmod_modplay_t *modplay, 420 size_t chan, uint8_t param4) 421 { 422 modplay->chan[chan].vol_slide = param4; 423 } 424 425 /** Process Fine portamento down effect. 426 * 427 * @param modplay Module playback 428 * @param chan Channel number 429 * @param param Effect parameter 430 */ 431 static void trackmod_effect_fine_porta_down(trackmod_modplay_t *modplay, 432 size_t chan, uint8_t param) 433 { 434 int np; 435 436 np = modplay->chan[chan].period + param; 437 if (np > period_max) 438 np = period_max; 439 modplay->chan[chan].period = np; 440 } 441 442 /** Process Fine portamento up effect. 443 * 444 * @param modplay Module playback 445 * @param chan Channel number 446 * @param param Effect parameter 447 */ 448 static void trackmod_effect_fine_porta_up(trackmod_modplay_t *modplay, 449 size_t chan, uint8_t param) 450 { 451 int np; 452 453 np = modplay->chan[chan].period - param; 454 if (np < period_min) 455 np = period_min; 456 modplay->chan[chan].period = np; 457 } 458 459 /** Process Portamento down effect. 460 * 461 * @param modplay Module playback 462 * @param chan Channel number 463 * @param param Effect parameter 464 */ 465 static void trackmod_effect_porta_down(trackmod_modplay_t *modplay, 466 size_t chan, uint8_t param) 467 { 468 modplay->chan[chan].portamento = -(int)param; 469 } 470 471 /** Process Portamento up effect. 472 * 473 * @param modplay Module playback 474 * @param chan Channel number 475 * @param param Effect parameter 476 */ 477 static void trackmod_effect_porta_up(trackmod_modplay_t *modplay, 478 size_t chan, uint8_t param) 479 { 480 modplay->chan[chan].portamento = param; 481 } 482 483 /** Process Tone portamento effect. 484 * 485 * @param modplay Module playback 486 * @param chan Channel number 487 * @param param Effect parameter 488 */ 489 static void trackmod_effect_tone_porta(trackmod_modplay_t *modplay, 490 size_t chan, uint8_t param) 491 { 492 /* Set up tone portamento effect */ 493 modplay->chan[chan].portamento = param; 494 if (modplay->chan[chan].period_new != 0) 495 modplay->chan[chan].period_tgt = modplay->chan[chan].period_new; 496 497 /* Prevent going directly to new period */ 498 modplay->chan[chan].period_new = 0; 499 } 500 501 /** Process volume column. 502 * 503 * @param modplay Module playback 504 * @param chan Channel number 505 * @param cell Cell 506 */ 507 static void trackmod_process_volume(trackmod_modplay_t *modplay, size_t chan, 508 trackmod_cell_t *cell) 509 { 510 uint8_t param4; 511 512 if (cell->volume >= 0x10 && cell->volume <= 0x10 + vol_max) 513 trackmod_effect_set_volume(modplay, chan, cell->volume - 0x10); 514 515 param4 = cell->volume & 0xf; 516 517 switch (cell->volume & 0xf0) { 518 case 0x60: 519 trackmod_effect_vol_slide_down(modplay, chan, param4); 520 break; 521 case 0x70: 522 trackmod_effect_vol_slide_up(modplay, chan, param4); 523 break; 524 case 0x80: 525 trackmod_effect_fine_vol_slide_down(modplay, chan, param4); 526 break; 527 case 0x90: 528 trackmod_effect_fine_vol_slide_up(modplay, chan, param4); 529 break; 530 case 0xf0: 531 trackmod_effect_tone_porta(modplay, chan, param4 << 4); 532 break; 533 default: 534 break; 535 } 536 } 537 214 538 /** Process effect. 215 539 * … … 222 546 { 223 547 uint8_t param8; 548 uint8_t param4; 224 549 225 550 param8 = cell->effect & 0xff; 226 551 227 552 switch (cell->effect & 0xf00) { 553 case 0x100: 554 trackmod_effect_porta_up(modplay, chan, param8); 555 break; 556 case 0x200: 557 trackmod_effect_porta_down(modplay, chan, param8); 558 break; 559 case 0x300: 560 trackmod_effect_tone_porta(modplay, chan, param8); 561 break; 562 case 0xa00: 563 trackmod_effect_vol_slide(modplay, chan, param8); 564 break; 228 565 case 0xc00: 229 566 trackmod_effect_set_volume(modplay, chan, param8); … … 238 575 break; 239 576 } 577 578 param4 = cell->effect & 0xf; 579 580 switch (cell->effect & 0xff0) { 581 case 0xe10: 582 trackmod_effect_fine_porta_up(modplay, chan, param4); 583 break; 584 case 0xe20: 585 trackmod_effect_fine_porta_down(modplay, chan, param4); 586 break; 587 case 0xea0: 588 trackmod_effect_fine_vol_slide_up(modplay, chan, param4); 589 break; 590 case 0xeb0: 591 trackmod_effect_fine_vol_slide_down(modplay, chan, param4); 592 break; 593 } 240 594 } 241 595 … … 249 603 trackmod_cell_t *cell) 250 604 { 251 if (cell->period != 0 && cell->sample != 0) 605 modplay->chan[chan].period_new = 0; 606 607 trackmod_process_instr(modplay, chan, cell); 608 609 if (cell->period != 0 || (cell->note != 0 && cell->note != keyoff_note)) { 252 610 trackmod_process_note(modplay, chan, cell); 253 611 } else if (cell->note == keyoff_note && cell->instr == 0) { 612 trackmod_process_keyoff_note(modplay, chan); 613 } 614 615 trackmod_process_volume(modplay, chan, cell); 254 616 trackmod_process_effect(modplay, chan, cell); 617 618 if (modplay->chan[chan].period_new != 0) 619 modplay->chan[chan].period = modplay->chan[chan].period_new; 255 620 } 256 621 … … 267 632 pattern = trackmod_cur_pattern(modplay); 268 633 634 if (modplay->debug) 635 printf("%02zx: ", modplay->row); 636 269 637 for (i = 0; i < modplay->module->channels; i++) { 270 638 trackmod_pattern_get_cell(pattern, modplay->row, i, &cell); 271 if (modplay->debug) 272 printf("%4d %02x %03x |", cell.period, cell.sample, cell.effect); 639 640 if (modplay->debug) { 641 printf("%4d %02x %02x %03x |", cell.period ? 642 cell.period : cell.note, cell.instr, 643 cell.volume, cell.effect); 644 } 645 273 646 trackmod_process_cell(modplay, i, &cell); 274 647 } … … 289 662 ord_idx = modplay->ord_idx + 1; 290 663 if (ord_idx >= modplay->module->ord_list_len) 291 ord_idx = 0; /* XXX */664 ord_idx = modplay->module->restart_pos; 292 665 293 666 return ord_idx; … … 313 686 } 314 687 688 /** Clear effects at end of row. */ 689 static void trackmod_clear_effects(trackmod_modplay_t *modplay) 690 { 691 size_t i; 692 693 for (i = 0; i < modplay->module->channels; i++) { 694 modplay->chan[i].vol_slide = 0; 695 modplay->chan[i].portamento = 0; 696 } 697 } 698 699 /** Process effects at beginning of tick. */ 700 static void trackmod_process_tick(trackmod_modplay_t *modplay) 701 { 702 trackmod_chan_t *chan; 703 size_t i; 704 int nv; 705 int np; 706 707 for (i = 0; i < modplay->module->channels; i++) { 708 chan = &modplay->chan[i]; 709 710 /* Volume slides */ 711 nv = (int)chan->volume + chan->vol_slide; 712 if (nv < 0) 713 nv = 0; 714 if (nv > vol_max) 715 nv = vol_max; 716 717 chan->volume = nv; 718 719 /* Portamentos */ 720 if (chan->period_tgt == 0) { 721 /* Up or down portamento */ 722 np = (int)chan->period - chan->portamento; 723 } else { 724 /* Tone portamento */ 725 if (chan->period_tgt < chan->period) 726 np = max((int)chan->period_tgt, (int)chan->period - chan->portamento); 727 else 728 np = min((int)chan->period_tgt, (int)chan->period + chan->portamento); 729 } 730 731 /* if (np < period_min) 732 np = period_min; 733 if (np > period_max) 734 np = period_max; 735 */ 736 modplay->chan[i].period = np; 737 } 738 } 739 315 740 /** Advance to next row. 316 741 * … … 320 745 { 321 746 trackmod_pattern_t *pattern; 747 748 /* Clear effect state at end of row */ 749 trackmod_clear_effects(modplay); 322 750 323 751 pattern = trackmod_cur_pattern(modplay); … … 328 756 trackmod_next_pattern(modplay); 329 757 758 trackmod_process_tick(modplay); 330 759 trackmod_process_row(modplay); 331 760 } … … 341 770 if (modplay->tick >= modplay->tpr) 342 771 trackmod_next_row(modplay); 772 else 773 trackmod_process_tick(modplay); 343 774 } 344 775 … … 366 797 modplay->smp = 0; 367 798 368 modplay->tpr = def_tpr;369 modplay->bpm = def_bpm;799 modplay->tpr = module->def_tpr; 800 modplay->bpm = module->def_bpm; 370 801 371 802 modplay->chan = calloc(module->channels, … … 374 805 goto error; 375 806 807 trackmod_process_tick(modplay); 376 808 trackmod_process_row(modplay); 377 809 … … 416 848 } 417 849 850 /** Get sample frame. 851 * 852 * Get frame at the specified sample position. 853 * 854 * @param sample Sample 855 * @param pos Position (frame index) 856 * @return Frame value 857 */ 858 int trackmod_sample_get_frame(trackmod_sample_t *sample, size_t pos) 859 { 860 int8_t *i8p; 861 int16_t *i16p; 862 863 if (sample->bytes_smp == 1) { 864 i8p = (int8_t *)sample->data; 865 return i8p[pos]; 866 } else { 867 /* chan->sample->bytes_smp == 2 */ 868 i16p = (int16_t *)sample->data; 869 return i16p[pos] / 256; /* XXX Retain full precision */ 870 } 871 } 872 418 873 /** Advance sample position to next frame. 419 874 * … … 422 877 static void chan_smp_next_frame(trackmod_chan_t *chan) 423 878 { 424 chan->lsmp = chan->sample->data[chan->smp_pos];879 chan->lsmp = trackmod_sample_get_frame(chan->sample, chan->smp_pos); 425 880 ++chan->smp_pos; 426 881 427 if (chan->sample->loop_len == 0) { 428 /* No looping */ 882 switch (chan->sample->loop_type) { 883 case tl_pingpong_loop: 884 /** XXX Pingpong loop */ 885 case tl_no_loop: 886 /* No loop */ 429 887 if (chan->smp_pos >= chan->sample->length) { 430 888 chan->sample = NULL; 431 889 chan->smp_pos = 0; 432 890 } 433 } else { 434 /** Looping */ 891 break; 892 case tl_forward_loop: 893 /** Forward loop */ 435 894 if (chan->smp_pos >= chan->sample->loop_start + 436 895 chan->sample->loop_len) { … … 455 914 trackmod_chan_t *chan = &modplay->chan[cidx]; 456 915 457 if (chan->sample == NULL )916 if (chan->sample == NULL || chan->period == 0) 458 917 return 0; 459 918 … … 464 923 */ 465 924 sl = (int)chan->lsmp * amp_factor * chan->volume / vol_max; 466 sn = (int) chan->sample->data[chan->smp_pos] * amp_factor*467 chan->volume / vol_max;925 sn = (int)trackmod_sample_get_frame(chan->sample, chan->smp_pos) * 926 amp_factor * chan->volume / vol_max; 468 927 469 928 period = (int)chan->period;
Note:
See TracChangeset
for help on using the changeset viewer.