int fmt_pat_load_instrument(const uint8_t *data, size_t length, int slot) { struct GF1PatchHeader header; struct GF1PatchSampleHeader gfsamp; struct instrumentloader ii; song_instrument_t *g; song_sample_t *smp; unsigned int pos, rs; int lo, hi, tmp, i, nsamp, n; if (length < sizeof(header) || !slot) return 0; memcpy(&header, data, sizeof(header)); if ((memcmp(header.sig, "GF1PATCH", 8) != 0) || (memcmp(header.ver, "110\0", 4) != 0 && memcmp(header.ver, "100\0", 4) != 0) || (memcmp(header.id, "ID#000002\0", 10) != 0)) { return 0; } header.waveforms = bswapLE16(header.waveforms); header.mastervol = bswapLE16(header.mastervol); header.datasize = bswapLE32(header.datasize); header.insID = bswapLE16(header.insID); header.inssize = bswapLE32(header.inssize); header.layersize = bswapLE32(header.layersize); g = instrument_loader_init(&ii, slot); memcpy(g->name, header.insname, 16); g->name[15] = '\0'; nsamp = CLAMP(header.smpnum, 1, 16); pos = sizeof(header); for (i = 0; i < 120; i++) { g->sample_map[i] = 0; g->note_map[i] = i + 1; } for (i = 0; i < nsamp; i++) { memcpy(&gfsamp, data + pos, sizeof(gfsamp)); pos += sizeof(gfsamp); n = instrument_loader_sample(&ii, i + 1) - 1; smp = song_get_sample(n); gfsamp.samplesize = bswapLE32(gfsamp.samplesize); gfsamp.loopstart = bswapLE32(gfsamp.loopstart); gfsamp.loopend = bswapLE32(gfsamp.loopend); gfsamp.samplerate = bswapLE16(gfsamp.samplerate); gfsamp.lofreq = bswapLE32(gfsamp.lofreq); gfsamp.hifreq = bswapLE32(gfsamp.hifreq); gfsamp.rtfreq = bswapLE32(gfsamp.rtfreq); gfsamp.tune = bswapLE16(gfsamp.tune); gfsamp.scalefreq = bswapLE16(gfsamp.scalefac); lo = CLAMP(gusfreq(gfsamp.lofreq), 0, 95); hi = CLAMP(gusfreq(gfsamp.hifreq), 0, 95); if (lo > hi) { tmp = lo; lo = hi; hi = tmp; } for (; lo < hi; lo++) { g->sample_map[lo + 12] = n; } if (gfsamp.smpmode & 1) { gfsamp.samplesize >>= 1; gfsamp.loopstart >>= 1; gfsamp.loopend >>= 1; } smp->length = gfsamp.samplesize; smp->loop_start = smp->sustain_start = gfsamp.loopstart; smp->loop_end = smp->sustain_end = gfsamp.loopend; smp->c5speed = gfsamp.samplerate; smp->flags = 0; rs = SF_M | SF_LE; // channels; endianness rs |= (gfsamp.smpmode & 1) ? SF_16 : SF_8; // bit width rs |= (gfsamp.smpmode & 2) ? SF_PCMU : SF_PCMS; // encoding if (gfsamp.smpmode & 32) { if (gfsamp.smpmode & 4) smp->flags |= CHN_SUSTAINLOOP; if (gfsamp.smpmode & 8) smp->flags |= CHN_PINGPONGSUSTAIN; } else { if (gfsamp.smpmode & 4) smp->flags |= CHN_LOOP; if (gfsamp.smpmode & 8) smp->flags |= CHN_PINGPONGLOOP; } memcpy(smp->filename, gfsamp.wavename, 7); smp->filename[8] = '\0'; strcpy(smp->name, smp->filename); smp->vib_speed = gfsamp.vib_speed; smp->vib_rate = gfsamp.vib_rate; smp->vib_depth = gfsamp.vib_depth; pos += csf_read_sample(current_song->samples + n, rs, data + pos, length - pos); }
int fmt_xi_load_instrument(const uint8_t *data, size_t length, int slot) { const struct xi_file_header *xi = (const struct xi_file_header *) data; struct xi_sample_header xmsh; struct instrumentloader ii; song_instrument_t *g; const uint8_t *sampledata, *end; int k, prevtick; if (!slot) return 0; if (!validate_xi(xi, length)) return 0; end = data + length; song_delete_instrument(slot); g = instrument_loader_init(&ii, slot); memcpy(g->name, xi->name, 22); g->name[22] = '\0'; xmsh = xi->xish; for (k = 0; k < 96; k++) { if (xmsh.snum[k] > 15) xmsh.snum[k] = 15; xmsh.snum[k] = instrument_loader_sample(&ii, xmsh.snum[k] + 1); g->note_map[k + 12] = k + 1 + 12; if (xmsh.snum[k]) g->sample_map[k + 12] = xmsh.snum[k]; } for (k = 0; k < 12; k++) { g->note_map[k] = 0; g->sample_map[k] = 0; g->note_map[k + 108] = 0; g->sample_map[k + 108] = 0; } // bswap all volume and panning envelope points for (k = 0; k < 48; k++) xmsh.env[k] = bswapLE16(xmsh.env[k]); // Set up envelope types in instrument if (xmsh.vtype & 0x01) g->flags |= ENV_VOLUME; if (xmsh.vtype & 0x02) g->flags |= ENV_VOLSUSTAIN; if (xmsh.vtype & 0x04) g->flags |= ENV_VOLLOOP; if (xmsh.ptype & 0x01) g->flags |= ENV_PANNING; if (xmsh.ptype & 0x02) g->flags |= ENV_PANSUSTAIN; if (xmsh.ptype & 0x04) g->flags |= ENV_PANLOOP; prevtick = -1; // Copy envelopes into instrument for (k = 0; k < xmsh.vnum; k++) { if (xmsh.venv[k].ticks < prevtick) prevtick++; else prevtick = xmsh.venv[k].ticks; g->vol_env.ticks[k] = prevtick; g->vol_env.values[k] = xmsh.venv[k].val; } prevtick = -1; for (k = 0; k < xmsh.pnum; k++) { if (xmsh.penv[k].ticks < prevtick) prevtick++; else prevtick = xmsh.penv[k].ticks; g->pan_env.ticks[k] = prevtick; g->pan_env.values[k] = xmsh.penv[k].val; } g->vol_env.loop_start = xmsh.vloops; g->vol_env.loop_end = xmsh.vloope; g->vol_env.sustain_start = xmsh.vsustain; g->vol_env.nodes = xmsh.vnum; g->pan_env.loop_start = xmsh.ploops; g->pan_env.loop_end = xmsh.ploope; g->pan_env.sustain_start = xmsh.psustain; g->pan_env.nodes = xmsh.pnum; xmsh.volfade = bswapLE16(xmsh.volfade); xmsh.nsamples = bswapLE16(xmsh.nsamples); // Sample data begins at the end of the sample headers sampledata = (const uint8_t *) (xi->sheader + xmsh.nsamples); for (k = 0; k < xmsh.nsamples; k++) { struct xm_sample_header xmss = xi->sheader[k]; song_sample_t *smp; unsigned int rs, samplesize, n; xmss.samplen = bswapLE32(xmss.samplen); xmss.loopstart = bswapLE32(xmss.loopstart); xmss.looplen = bswapLE32(xmss.looplen); rs = SF_LE | SF_PCMD; // endianness; encoding rs |= (xmss.type & 0x20) ? SF_SS : SF_M; // channels rs |= (xmss.type & 0x10) ? SF_16 : SF_8; // bits if (xmss.type & 0x10) { xmss.looplen >>= 1; xmss.loopstart >>= 1; xmss.samplen >>= 1; } if (xmss.type & 0x20) { xmss.looplen >>= 1; xmss.loopstart >>= 1; xmss.samplen >>= 1; }