Changeset 43dd72b7 in mainline for uspace/lib/trackmod/protracker.c


Ignore:
Timestamp:
2014-10-13T17:31:01Z (10 years ago)
Author:
Jiri Svoboda <jiri@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
affbdde
Parents:
18cc83c
Message:

Trackmod update: XM file format, new effects, etc.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • uspace/lib/trackmod/protracker.c

    r18cc83c r43dd72b7  
    113113}
    114114
     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 */
     123static 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 */
     140static 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;
     181error:
     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 */
     193static 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;
     247error:
     248        return rc;
     249}
     250
    115251/** Load protracker module.
    116252 *
     
    128264        protracker_order_list_t *order_list;
    129265        protracker_smp_t *sample;
    130         size_t nread;
    131266        size_t samples;
    132267        size_t channels;
    133268        size_t patterns;
    134         size_t cells;
    135         size_t i, j;
     269        size_t i;
     270        size_t nread;
    136271        int rc;
    137272
     
    192327        module->channels = channels;
    193328
    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) {
    197332                printf("Out of memory.\n");
    198333                rc = ENOMEM;
     
    221356        }
    222357
     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
    223363        /* 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;
    246367
    247368        /* 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;
    274372
    275373        (void) fclose(f);
     374
     375        module->def_bpm = protracker_def_bpm;
     376        module->def_tpr = protracker_def_tpr;
    276377
    277378        *rmodule = module;
Note: See TracChangeset for help on using the changeset viewer.