Changeset 43dd72b7 in mainline
- Timestamp:
- 2014-10-13T17:31:01Z (10 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- affbdde
- Parents:
- 18cc83c
- Location:
- uspace
- Files:
-
- 3 added
- 8 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/app/modplay/modplay.c
r18cc83c r43dd72b7 40 40 #include <stdio.h> 41 41 #include <stdlib.h> 42 #include <protracker.h>43 42 #include <trackmod.h> 44 43 … … 88 87 con = console_init(stdin, stdout); 89 88 90 rc = trackmod_ protracker_load(argv[1], &mod);89 rc = trackmod_module_load(argv[1], &mod); 91 90 if (rc != EOK) { 92 91 printf("Error loading %s.\n", argv[1]); -
uspace/lib/c/include/stddef.h
r18cc83c r43dd72b7 42 42 #endif 43 43 44 #define offsetof(type,member) ((size_t) &(((type *) 0)->member)) 44 45 45 46 #endif -
uspace/lib/trackmod/Makefile
r18cc83c r43dd72b7 32 32 SOURCES = \ 33 33 protracker.c \ 34 trackmod.c 34 trackmod.c \ 35 xm.c 35 36 36 37 include $(USPACE_PREFIX)/Makefile.common -
uspace/lib/trackmod/protracker.c
r18cc83c r43dd72b7 113 113 } 114 114 115 116 /** Decode pattern cell. 117 * 118 * @param pattern Pattern 119 * @param row Row number 120 * @param channel Channel number 121 * @param cell Place to store decoded cell 122 */ 123 static void protracker_decode_cell(uint32_t cdata, trackmod_cell_t *cell) 124 { 125 uint32_t code; 126 127 code = uint32_t_be2host(cdata); 128 cell->period = (code >> (4 * 4)) & 0xfff; 129 cell->instr = (((code >> (7 * 4)) & 0xf) << 4) | 130 ((code >> (3 * 4)) & 0xf); 131 cell->effect = code & 0xfff; 132 } 133 134 /** Load Protracker patterns. 135 * 136 * @param f File to read from 137 * @param module Module being loaded to 138 * @return EOK on success, ENOMEM if out of memory, EIO on I/O error. 139 */ 140 static int protracker_load_patterns(FILE *f, trackmod_module_t *module) 141 { 142 size_t cells; 143 size_t i, j; 144 int rc; 145 size_t nread; 146 uint32_t *buf = NULL; 147 148 cells = module->channels * protracker_pattern_rows; 149 buf = calloc(sizeof(uint32_t), cells); 150 151 if (buf == NULL) { 152 rc = ENOMEM; 153 goto error; 154 } 155 156 for (i = 0; i < module->patterns; i++) { 157 module->pattern[i].rows = protracker_pattern_rows; 158 module->pattern[i].channels = module->channels; 159 module->pattern[i].data = calloc(sizeof(trackmod_cell_t), cells); 160 if (module->pattern[i].data == NULL) { 161 rc = ENOMEM; 162 goto error; 163 } 164 165 nread = fread(buf, sizeof(uint32_t), cells, f); 166 if (nread != cells) { 167 printf("Error reading pattern.\n"); 168 rc = EIO; 169 goto error; 170 } 171 172 /* Decode cells */ 173 for (j = 0; j < cells; j++) { 174 protracker_decode_cell(buf[j], 175 &module->pattern[i].data[j]); 176 } 177 } 178 179 free(buf); 180 return EOK; 181 error: 182 free(buf); 183 return rc; 184 } 185 186 /** Load protracker samples. 187 * 188 * @param f File being read from 189 * @param sample Sample header 190 * @param module Module being loaded to 191 * @return EOk on success, ENOMEM if out of memory, EIO on I/O error. 192 */ 193 static int protracker_load_samples(FILE *f, protracker_smp_t *smp, 194 trackmod_module_t *module) 195 { 196 int rc; 197 size_t i; 198 uint8_t ftval; 199 size_t nread; 200 trackmod_sample_t *sample; 201 202 for (i = 0; i < module->instrs; i++) { 203 module->instr[i].samples = 1; 204 module->instr[i].sample = calloc(1, sizeof(trackmod_sample_t)); 205 if (module->instr[i].sample == NULL) { 206 printf("Error allocating sample.\n"); 207 rc = ENOMEM; 208 goto error; 209 } 210 211 sample = &module->instr[i].sample[0]; 212 sample->length = 213 uint16_t_be2host(smp[i].length) * 2; 214 sample->bytes_smp = 1; 215 sample->data = calloc(1, sample->length); 216 if (sample->data == NULL) { 217 printf("Error allocating sample.\n"); 218 rc = ENOMEM; 219 goto error; 220 } 221 222 nread = fread(sample->data, 1, sample->length, f); 223 if (nread != sample->length) { 224 printf("Error reading sample.\n"); 225 rc = EIO; 226 goto error; 227 } 228 229 sample->def_vol = smp[i].def_vol; 230 231 sample->loop_start = 232 uint16_t_be2host(smp[i].loop_start) * 2; 233 sample->loop_len = 234 uint16_t_be2host(smp[i].loop_len) * 2; 235 if (sample->loop_len <= 2) 236 sample->loop_type = tl_no_loop; 237 else 238 sample->loop_type = tl_forward_loop; 239 240 /* Finetune is a 4-bit signed value. */ 241 ftval = smp[i].finetune & 0x0f; 242 sample->finetune = 243 (ftval & 0x8) ? (ftval & 0x7) - 8 : ftval; 244 } 245 246 return EOK; 247 error: 248 return rc; 249 } 250 115 251 /** Load protracker module. 116 252 * … … 128 264 protracker_order_list_t *order_list; 129 265 protracker_smp_t *sample; 130 size_t nread;131 266 size_t samples; 132 267 size_t channels; 133 268 size_t patterns; 134 size_t cells;135 size_t i, j;269 size_t i; 270 size_t nread; 136 271 int rc; 137 272 … … 192 327 module->channels = channels; 193 328 194 module-> samples = samples;195 module-> sample = calloc(sizeof(trackmod_sample_t), samples);196 if (module-> sample== NULL) {329 module->instrs = samples; 330 module->instr = calloc(sizeof(trackmod_instr_t), samples); 331 if (module->instr == NULL) { 197 332 printf("Out of memory.\n"); 198 333 rc = ENOMEM; … … 221 356 } 222 357 358 /* The 'mark' byte may or may not contain a valid restart position */ 359 if (order_list->mark < order_list->order_list_len) { 360 module->restart_pos = order_list->mark; 361 } 362 223 363 /* Load patterns */ 224 225 cells = channels * protracker_pattern_rows; 226 227 for (i = 0; i < patterns; i++) { 228 module->pattern[i].rows = protracker_pattern_rows; 229 module->pattern[i].channels = channels; 230 module->pattern[i].data = calloc(sizeof(uint32_t), cells); 231 232 nread = fread(module->pattern[i].data, 233 sizeof(uint32_t), cells, f); 234 if (nread != cells) { 235 printf("Error reading pattern.\n"); 236 rc = EIO; 237 goto error; 238 } 239 240 /* Convert byte order */ 241 for (j = 0; j < cells; j++) { 242 module->pattern[i].data[j] = uint32_t_be2host( 243 module->pattern[i].data[j]); 244 } 245 } 364 rc = protracker_load_patterns(f, module); 365 if (rc != EOK) 366 goto error; 246 367 247 368 /* Load samples */ 248 for (i = 0; i < samples; i++) { 249 module->sample[i].length = 250 uint16_t_be2host(sample[i].length) * 2; 251 module->sample[i].data = calloc(1, module->sample[i].length); 252 if (module->sample[i].data == NULL) { 253 printf("Error allocating sample.\n"); 254 rc = ENOMEM; 255 goto error; 256 } 257 258 nread = fread(module->sample[i].data, 1, module->sample[i].length, 259 f); 260 if (nread != module->sample[i].length) { 261 printf("Error reading sample.\n"); 262 rc = EIO; 263 goto error; 264 } 265 266 module->sample[i].def_vol = sample[i].def_vol; 267 module->sample[i].loop_start = 268 uint16_t_be2host(sample[i].loop_start) * 2; 269 module->sample[i].loop_len = 270 uint16_t_be2host(sample[i].loop_len) * 2; 271 if (module->sample[i].loop_len <= 2) 272 module->sample[i].loop_len = 0; 273 } 369 rc = protracker_load_samples(f, sample, module); 370 if (rc != EOK) 371 goto error; 274 372 275 373 (void) fclose(f); 374 375 module->def_bpm = protracker_def_bpm; 376 module->def_tpr = protracker_def_tpr; 276 377 277 378 *rmodule = module; -
uspace/lib/trackmod/trackmod.c
r18cc83c 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; -
uspace/lib/trackmod/trackmod.h
r18cc83c r43dd72b7 40 40 41 41 extern trackmod_module_t *trackmod_module_new(void); 42 extern int trackmod_module_load(char *, trackmod_module_t **); 42 43 extern void trackmod_module_destroy(trackmod_module_t *); 43 44 extern int trackmod_modplay_create(trackmod_module_t *, unsigned, … … 45 46 extern void trackmod_modplay_destroy(trackmod_modplay_t *); 46 47 extern void trackmod_modplay_get_samples(trackmod_modplay_t *, void *, size_t); 48 extern int trackmod_sample_get_frame(trackmod_sample_t *, size_t); 47 49 48 50 #endif -
uspace/lib/trackmod/types/protracker.h
r18cc83c r43dd72b7 47 47 protracker_olist_len = 128, 48 48 /** Number of rows in a pattern */ 49 protracker_pattern_rows = 64 49 protracker_pattern_rows = 64, 50 /** Default TPR */ 51 protracker_def_tpr = 6, 52 /** Default BPM */ 53 protracker_def_bpm = 125 50 54 }; 51 55 -
uspace/lib/trackmod/types/trackmod.h
r18cc83c r43dd72b7 41 41 #include <stdint.h> 42 42 43 enum { 44 max_key = 96, 45 keyoff_note = 97 46 }; 47 48 typedef enum { 49 /** No loop */ 50 tl_no_loop, 51 /** Forward loop */ 52 tl_forward_loop, 53 /** Pingpong loop */ 54 tl_pingpong_loop 55 } trackmod_looptype_t; 56 43 57 /** Sample */ 44 58 typedef struct { 45 59 /** Length in frames */ 46 60 size_t length; 61 /** Bytes per sample */ 62 size_t bytes_smp; 47 63 /** Sample data */ 48 int8_t *data; 64 void *data; 65 /** Loop type */ 66 trackmod_looptype_t loop_type; 49 67 /** Loop start position in frames */ 50 68 size_t loop_start; 51 /** Loop length in frames or 0 - no looping*/69 /** Loop length in frames (> 0) */ 52 70 size_t loop_len; 53 71 /** Default volume (0..63) */ 54 72 uint8_t def_vol; 73 /** Relative note */ 74 int rel_note; 75 /** Finetune value (-8..7) in 1/8 semitones */ 76 int finetune; 55 77 } trackmod_sample_t; 78 79 /** Instrument */ 80 typedef struct { 81 /** Number of samples */ 82 size_t samples; 83 /** Samples */ 84 trackmod_sample_t *sample; 85 /** Sample index for each key */ 86 int key_smp[max_key]; 87 } trackmod_instr_t; 88 89 /** Pattern cell */ 90 typedef struct { 91 /** Note */ 92 unsigned note; 93 /** Sample period */ 94 unsigned period; 95 /** Instrument number */ 96 unsigned instr; 97 /** Volume */ 98 uint8_t volume; 99 /** Effect */ 100 uint16_t effect; 101 } trackmod_cell_t; 56 102 57 103 /** Pattern */ … … 62 108 size_t channels; 63 109 /** Pattern data */ 64 uint32_t *data;110 trackmod_cell_t *data; 65 111 } trackmod_pattern_t; 66 112 … … 70 116 size_t channels; 71 117 /** Number of samples */ 72 size_t samples;73 /** Samples */74 trackmod_ sample_t *sample;118 size_t instrs; 119 /** Instruments */ 120 trackmod_instr_t *instr; 75 121 /** Number of patterns */ 76 122 size_t patterns; … … 81 127 /** Order list */ 82 128 size_t *ord_list; 129 /** Restart pos */ 130 size_t restart_pos; 131 /** Default BPM */ 132 unsigned def_bpm; 133 /** Default TPR */ 134 unsigned def_tpr; 83 135 } trackmod_module_t; 84 136 … … 92 144 /** Sample position (clock ticks within frame) */ 93 145 size_t smp_clk; 94 /** Period */146 /** Current period */ 95 147 unsigned period; 148 /** Period after note was processed, zero if no note */ 149 unsigned period_new; 96 150 /** Volume */ 97 151 uint8_t volume; 152 /** Volume slide amount */ 153 int vol_slide; 154 /** Portamento amount (positive for tone and up portamento, 155 * negative for down portamento. */ 156 int portamento; 157 /** Tone portamento target period. */ 158 unsigned period_tgt; 98 159 } trackmod_chan_t; 99 160 … … 132 193 } trackmod_modplay_t; 133 194 134 /** Pattern cell (decoded) */135 typedef struct {136 /** Sample period */137 unsigned period;138 /** Sample number */139 unsigned sample;140 /** Effect */141 unsigned effect;142 } trackmod_cell_t;143 144 195 #endif 145 196
Note:
See TracChangeset
for help on using the changeset viewer.