Esempio n. 1
0
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);
        }
Esempio n. 2
0
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;
		}