void swap_PSMSAMPLE(PSMSAMPLE* p){ p->smpid = bswapLE32(p->smpid); p->length = bswapLE32(p->length); p->loopstart = bswapLE32(p->loopstart); p->loopend = bswapLE32(p->loopend); p->samplerate = bswapLE32(p->samplerate); }
BOOL CDecompressTrack::ReadUMX(const BYTE* lpStream, DWORD dwMemLength) //--------------------------------------------------------------- { if ((!lpStream) || (dwMemLength < 0x800)) return FALSE; // Rip Mods from UMX if ((bswapLE32(*((DWORD *) (lpStream + 0x20))) < dwMemLength) && (bswapLE32(*((DWORD *) (lpStream + 0x18))) <= dwMemLength - 0x10) && (bswapLE32(*((DWORD *) (lpStream + 0x18))) >= dwMemLength - 0x200)) { for (UINT uscan = 0x40; uscan < 0x500; uscan++) { DWORD dwScan = bswapLE32(*((DWORD*) (lpStream + uscan))); // IT if (dwScan == 0x4D504D49) { DWORD dwRipOfs = uscan; return ReadIT(lpStream + dwRipOfs, dwMemLength - dwRipOfs); } // S3M if (dwScan == 0x4D524353) { DWORD dwRipOfs = uscan - 44; return ReadS3M(lpStream + dwRipOfs, dwMemLength - dwRipOfs); } // XM if (!_strnicmp((LPCSTR) (lpStream + uscan), "Extended Module", 15)) { DWORD dwRipOfs = uscan; return ReadXM(lpStream + dwRipOfs, dwMemLength - dwRipOfs); } // MOD if ((uscan > MODMAGIC_OFFSET) && (dwScan == 0x2e4b2e4d)) { DWORD dwRipOfs = uscan - MODMAGIC_OFFSET; return ReadMod(lpStream + dwRipOfs, dwMemLength - dwRipOfs); } } } return FALSE; }
int fmt_its_save_sample(disko_t *fp, song_sample_t *smp) { save_its_header(fp, smp); csf_write_sample(fp, smp, SF_LE | SF_PCMS | ((smp->flags & CHN_16BIT) ? SF_16 : SF_8) | ((smp->flags & CHN_STEREO) ? SF_SS : SF_M)); /* Write the sample pointer. In an ITS file, the sample data is right after the header, so its position in the file will be the same as the size of the header. */ unsigned int tmp = bswapLE32(sizeof(struct it_sample)); disko_seek(fp, 0x48, SEEK_SET); disko_write(fp, &tmp, 4); return SAVE_SUCCESS; }
void save_its_header(disko_t *fp, song_sample_t *smp) { struct it_sample its; memset(&its, 0, sizeof(its)); its.id = bswapLE32(0x53504D49); // IMPS strncpy((char *) its.filename, smp->filename, 12); its.gvl = smp->global_volume; if (smp->data && smp->length) its.flags |= 1; if (smp->flags & CHN_16BIT) its.flags |= 2; if (smp->flags & CHN_STEREO) its.flags |= 4; if (smp->flags & CHN_LOOP) its.flags |= 16; if (smp->flags & CHN_SUSTAINLOOP) its.flags |= 32; if (smp->flags & CHN_PINGPONGLOOP) its.flags |= 64; if (smp->flags & CHN_PINGPONGSUSTAIN) its.flags |= 128; its.vol = smp->volume / 4; strncpy((char *) its.name, smp->name, 25); its.name[25] = 0; its.cvt = 1; // signed samples its.dfp = smp->panning / 4; if (smp->flags & CHN_PANNING) its.dfp |= 0x80; its.length = bswapLE32(smp->length); its.loopbegin = bswapLE32(smp->loop_start); its.loopend = bswapLE32(smp->loop_end); its.C5Speed = bswapLE32(smp->c5speed); its.susloopbegin = bswapLE32(smp->sustain_start); its.susloopend = bswapLE32(smp->sustain_end); //its.samplepointer = 42; - this will be filled in later its.vis = smp->vib_speed; its.vir = smp->vib_rate; its.vid = smp->vib_depth; switch (smp->vib_type) { case VIB_RANDOM: its.vit = 3; break; case VIB_SQUARE: its.vit = 2; break; case VIB_RAMP_DOWN: its.vit = 1; break; default: case VIB_SINE: its.vit = 0; break; } disko_write(fp, &its, sizeof(its)); }
/* --------------------------------------------------------------------- */ int fmt_its_read_info(dmoz_file_t *file, const uint8_t *data, size_t length) { struct it_sample *its; if (!(length > 80 && memcmp(data, "IMPS", 4) == 0)) return 0; its = (struct it_sample *)data; file->smp_length = bswapLE32(its->length); file->smp_flags = 0; if (its->flags & 2) { file->smp_flags |= CHN_16BIT; } if (its->flags & 16) { file->smp_flags |= CHN_LOOP; if (its->flags & 64) file->smp_flags |= CHN_PINGPONGLOOP; } if (its->flags & 32) { file->smp_flags |= CHN_SUSTAINLOOP; if (its->flags & 128) file->smp_flags |= CHN_PINGPONGSUSTAIN; } if (its->dfp & 128) file->smp_flags |= CHN_PANNING; if (its->flags & 4) file->smp_flags |= CHN_STEREO; file->smp_defvol = its->vol; file->smp_gblvol = its->gvl; file->smp_vibrato_speed = its->vis; file->smp_vibrato_depth = its->vid & 0x7f; file->smp_vibrato_rate = its->vir; file->smp_loop_start = bswapLE32(its->loopbegin); file->smp_loop_end = bswapLE32(its->loopend); file->smp_speed = bswapLE32(its->C5Speed); file->smp_sustain_start = bswapLE32(its->susloopbegin); file->smp_sustain_end = bswapLE32(its->susloopend); file->smp_filename = mem_alloc(13); memcpy(file->smp_filename, its->filename, 12); file->smp_filename[12] = 0; file->description = "Impulse Tracker Sample"; file->title = mem_alloc(26); memcpy(file->title, data + 20, 25); file->title[25] = 0; file->type = TYPE_SAMPLE_EXTD; return 1; }
BOOL CSoundFile::ReadAMF(LPCBYTE lpStream, const DWORD dwMemLength) //----------------------------------------------------------- { const AMFFILEHEADER *pfh = (AMFFILEHEADER *)lpStream; DWORD dwMemPos; if ((!lpStream) || (dwMemLength < 2048)) return FALSE; if ((!strncmp((LPCTSTR)lpStream, "ASYLUM Music Format V1.0", 25)) && (dwMemLength > 4096)) { UINT numorders, numpats, numsamples; dwMemPos = 32; numpats = lpStream[dwMemPos+3]; numorders = lpStream[dwMemPos+4]; numsamples = 64; dwMemPos += 6; if ((!numpats) || (numpats > MAX_PATTERNS) || (!numorders) || (numpats*64*32 + 294 + 37*64 >= dwMemLength)) return FALSE; m_nType = MOD_TYPE_AMF0; m_nChannels = 8; m_nInstruments = 0; m_nSamples = 31; m_nDefaultTempo = 125; m_nDefaultSpeed = 6; for (UINT iOrd=0; iOrd<MAX_ORDERS; iOrd++) { Order[iOrd] = (iOrd < numorders) ? lpStream[dwMemPos+iOrd] : 0xFF; } dwMemPos = 294; // ??? for (UINT iSmp=0; iSmp<numsamples; iSmp++) { MODINSTRUMENT *psmp = &Ins[iSmp+1]; memcpy(m_szNames[iSmp+1], lpStream+dwMemPos, 22); m_szNames[iSmp+1][21] = '\0'; psmp->nFineTune = MOD2XMFineTune(lpStream[dwMemPos+22]); psmp->nVolume = lpStream[dwMemPos+23]; psmp->nGlobalVol = 64; if (psmp->nVolume > 0x40) psmp->nVolume = 0x40; psmp->nVolume <<= 2; psmp->nLength = bswapLE32(*((LPDWORD)(lpStream+dwMemPos+25))); psmp->nLoopStart = bswapLE32(*((LPDWORD)(lpStream+dwMemPos+29))); psmp->nLoopEnd = psmp->nLoopStart + bswapLE32(*((LPDWORD)(lpStream+dwMemPos+33))); if ((psmp->nLoopEnd > psmp->nLoopStart) && (psmp->nLoopEnd <= psmp->nLength)) { psmp->uFlags = CHN_LOOP; } else { psmp->nLoopStart = psmp->nLoopEnd = 0; } if ((psmp->nLength) && (iSmp>31)) m_nSamples = iSmp+1; dwMemPos += 37; } for (UINT iPat=0; iPat<numpats; iPat++) { MODCOMMAND *p = AllocatePattern(64, m_nChannels); if (!p) break; Patterns[iPat] = p; PatternSize[iPat] = 64; const UCHAR *pin = lpStream + dwMemPos; for (UINT i=0; i<8*64; i++) { p->note = 0; if (pin[0]) { p->note = pin[0] + 13; } p->instr = pin[1]; p->command = pin[2]; p->param = pin[3]; if (p->command > 0x0F) { #ifdef AMFLOG Log("0x%02X.0x%02X ?", p->command, p->param); #endif p->command = 0; } ConvertModCommand(p); pin += 4; p++; } dwMemPos += 64*32; } // Read samples for (UINT iData=0; iData<m_nSamples; iData++) { MODINSTRUMENT *psmp = &Ins[iData+1]; if (psmp->nLength) { if (dwMemPos > dwMemLength) return FALSE; dwMemPos += ReadSample(psmp, RS_PCM8S, (LPCSTR)(lpStream+dwMemPos), dwMemLength-dwMemPos); } } return TRUE; } //////////////////////////// // DSM/AMF USHORT *ptracks[MAX_PATTERNS]; DWORD sampleseekpos[MAX_SAMPLES]; if ((pfh->szAMF[0] != 'A') || (pfh->szAMF[1] != 'M') || (pfh->szAMF[2] != 'F') || (pfh->version < 10) || (pfh->version > 14) || (!bswapLE16(pfh->numtracks)) || (!pfh->numorders) || (pfh->numorders > MAX_PATTERNS) || (!pfh->numsamples) || (pfh->numsamples >= MAX_SAMPLES) || (pfh->numchannels < 4) || (pfh->numchannels > 32)) return FALSE; memcpy(m_szNames[0], pfh->title, 32); m_szNames[0][31] = '\0'; dwMemPos = sizeof(AMFFILEHEADER); m_nType = MOD_TYPE_AMF; m_nChannels = pfh->numchannels; m_nSamples = pfh->numsamples; m_nInstruments = 0; // Setup Channel Pan Positions if (pfh->version >= 11) { signed char *panpos = (signed char *)(lpStream + dwMemPos); UINT nchannels = (pfh->version >= 13) ? 32 : 16; for (UINT i=0; i<nchannels; i++) { int pan = (panpos[i] + 64) * 2; if (pan < 0) pan = 0; if (pan > 256) { pan = 128; ChnSettings[i].dwFlags |= CHN_SURROUND; } ChnSettings[i].nPan = pan; } dwMemPos += nchannels; } else { for (UINT i=0; i<16; i++) { ChnSettings[i].nPan = (lpStream[dwMemPos+i] & 1) ? 0x30 : 0xD0; } dwMemPos += 16; } // Get Tempo/Speed m_nDefaultTempo = 125; m_nDefaultSpeed = 6; if (pfh->version >= 13) { if (lpStream[dwMemPos] >= 32) m_nDefaultTempo = lpStream[dwMemPos]; if (lpStream[dwMemPos+1] <= 32) m_nDefaultSpeed = lpStream[dwMemPos+1]; dwMemPos += 2; } // Setup sequence list for (UINT iOrd=0; iOrd<MAX_ORDERS; iOrd++) { Order[iOrd] = 0xFF; if (iOrd < pfh->numorders) { Order[iOrd] = iOrd; PatternSize[iOrd] = 64; if (pfh->version >= 14) { PatternSize[iOrd] = bswapLE16(*(USHORT *)(lpStream+dwMemPos)); dwMemPos += 2; } ptracks[iOrd] = (USHORT *)(lpStream+dwMemPos); dwMemPos += m_nChannels * sizeof(USHORT); } } if (dwMemPos + m_nSamples * (sizeof(AMFSAMPLE)+8) > dwMemLength) return TRUE; // Read Samples UINT maxsampleseekpos = 0; for (UINT iIns=0; iIns<m_nSamples; iIns++) { MODINSTRUMENT *pins = &Ins[iIns+1]; const AMFSAMPLE *psh = (AMFSAMPLE *)(lpStream + dwMemPos); dwMemPos += sizeof(AMFSAMPLE); memcpy(m_szNames[iIns+1], psh->samplename, 32); m_szNames[iIns+1][31] = '\0'; memcpy(pins->name, psh->filename, 13); pins->name[12] = '\0'; pins->nLength = bswapLE32(psh->length); pins->nC4Speed = bswapLE16(psh->c2spd); pins->nGlobalVol = 64; pins->nVolume = psh->volume * 4; if (pfh->version >= 11) { pins->nLoopStart = bswapLE32(*(DWORD *)(lpStream+dwMemPos)); pins->nLoopEnd = bswapLE32(*(DWORD *)(lpStream+dwMemPos+4)); dwMemPos += 8; } else { pins->nLoopStart = bswapLE16(*(WORD *)(lpStream+dwMemPos)); pins->nLoopEnd = pins->nLength; dwMemPos += 2; } sampleseekpos[iIns] = 0; if ((psh->type) && (bswapLE32(psh->offset) < dwMemLength-1)) { sampleseekpos[iIns] = bswapLE32(psh->offset); if (bswapLE32(psh->offset) > maxsampleseekpos) maxsampleseekpos = bswapLE32(psh->offset); if ((pins->nLoopEnd > pins->nLoopStart + 2) && (pins->nLoopEnd <= pins->nLength)) pins->uFlags |= CHN_LOOP; } } // Read Track Mapping Table USHORT *pTrackMap = (USHORT *)(lpStream+dwMemPos); UINT realtrackcnt = 0; dwMemPos += pfh->numtracks * sizeof(USHORT); for (UINT iTrkMap=0; iTrkMap<pfh->numtracks; iTrkMap++) { if (realtrackcnt < pTrackMap[iTrkMap]) realtrackcnt = pTrackMap[iTrkMap]; } // Store tracks positions BYTE **pTrackData = new BYTE *[realtrackcnt]; memset(pTrackData, 0, sizeof(BYTE *) * realtrackcnt); for (UINT iTrack=0; iTrack<realtrackcnt; iTrack++) if (dwMemPos <= dwMemLength - 3) { UINT nTrkSize = bswapLE16(*(USHORT *)(lpStream+dwMemPos)); nTrkSize += (UINT)lpStream[dwMemPos+2] << 16; if (dwMemPos + nTrkSize * 3 + 3 <= dwMemLength) { pTrackData[iTrack] = (BYTE *)(lpStream + dwMemPos); } dwMemPos += nTrkSize * 3 + 3; } // Create the patterns from the list of tracks for (UINT iPat=0; iPat<pfh->numorders; iPat++) { MODCOMMAND *p = AllocatePattern(PatternSize[iPat], m_nChannels); if (!p) break; Patterns[iPat] = p; for (UINT iChn=0; iChn<m_nChannels; iChn++) { UINT nTrack = bswapLE16(ptracks[iPat][iChn]); if ((nTrack) && (nTrack <= pfh->numtracks)) { UINT realtrk = bswapLE16(pTrackMap[nTrack-1]); if (realtrk) { realtrk--; if ((realtrk < realtrackcnt) && (pTrackData[realtrk])) { AMF_Unpack(p+iChn, pTrackData[realtrk], PatternSize[iPat], m_nChannels); } } } } } delete[] pTrackData; // Read Sample Data for (UINT iSeek=1; iSeek<=maxsampleseekpos; iSeek++) { if (dwMemPos >= dwMemLength) break; for (UINT iSmp=0; iSmp<m_nSamples; iSmp++) if (iSeek == sampleseekpos[iSmp]) { MODINSTRUMENT *pins = &Ins[iSmp+1]; dwMemPos += ReadSample(pins, RS_PCM8U, (LPCSTR)(lpStream+dwMemPos), dwMemLength-dwMemPos); break; } } return TRUE; }
static int load_s3i_sample(const uint8_t *data, size_t length, song_sample_t *smp) { const struct s3i_header* header = (const struct s3i_header*) data; /* fprintf(stderr, "%X-%X-%X-%X-%X\n", (((char*)&(header->type ))-((char*)&(header->type))), (((char*)&(header->length ))-((char*)&(header->type))), (((char*)&(header->c2spd ))-((char*)&(header->type))), (((char*)&(header->samplename))-((char*)&(header->type))), (((char*)&(header->samplesig))-((char*)&(header->type))) ); fprintf(stderr, "Considering %d byte sample (%.4s), %d\n", (int)length, header->samplesig, header->length); */ if(length < 0x50) return 0; // too small if (strncmp(header->samplesig, "SCRS", 4) != 0 && strncmp(header->samplesig, "SCRI", 4) != 0) return 0; // It should be either SCRS or SCRI. size_t samp_length = bswapLE32(header->length); int bytes_per_sample = (header->type == 1 ? ((header->flags & 2) ? 2 : 1) : 0); // no sample data if (length < 0x50 + smp->length * bytes_per_sample) return 0; smp->length = samp_length; smp->global_volume = 64; smp->volume = header->volume*256/64; smp->loop_start = header->loopbeg; smp->loop_end = header->loopend; smp->c5speed = header->c2spd; smp->flags = 0; if (header->flags & 1) smp->flags |= CHN_LOOP; if (header->flags & 2) smp->flags |= CHN_STEREO; if (header->flags & 4) smp->flags |= CHN_16BIT; if (header->type == 2) { smp->flags |= CHN_ADLIB; smp->flags &= ~(CHN_LOOP|CHN_16BIT); memcpy(smp->adlib_bytes, &header->length, 11); smp->length = 1; smp->loop_start = 0; smp->loop_end = 0; smp->data = csf_allocate_sample(1); } int format = SF_M | SF_LE; // endianness; channels format |= (smp->flags & CHN_16BIT) ? (SF_16 | SF_PCMS) : (SF_8 | SF_PCMU); // bits; encoding csf_read_sample((song_sample_t *) smp, format, (const char *) (data + 0x50), (uint32_t) (length - 0x50)); strncpy(smp->filename, header->dosfn, 11); strncpy(smp->name, header->samplename, 25); return 1; }
void swap_PSMPATTERN(PSMPATTERN* p){ p->size = bswapLE32(p->size); p->name = bswapLE32(p->name); p->rows = bswapLE16(p->rows); }
void swap_PSMCHUNK(PSMCHUNK* p){ p->id = bswapLE32(p->id); p->len = bswapLE32(p->len); p->listid = bswapLE32(p->listid); }
int fmt_s3m_load_song(song_t *song, slurp_t *fp, unsigned int lflags) { uint16_t nsmp, nord, npat; int misc = S3M_UNSIGNED | S3M_CHANPAN; // temporary flags, these are both generally true int n; song_note_t *note; /* junk variables for reading stuff into */ uint16_t tmp; uint8_t c; uint32_t tmplong; uint8_t b[4]; /* parapointers */ uint16_t para_smp[MAX_SAMPLES]; uint16_t para_pat[MAX_PATTERNS]; uint32_t para_sdata[MAX_SAMPLES] = { 0 }; uint32_t smp_flags[MAX_SAMPLES] = { 0 }; song_sample_t *sample; uint16_t trkvers; uint16_t flags; uint16_t special; uint32_t adlib = 0; // bitset int uc; const char *tid = NULL; /* check the tag */ slurp_seek(fp, 44, SEEK_SET); slurp_read(fp, b, 4); if (memcmp(b, "SCRM", 4) != 0) return LOAD_UNSUPPORTED; /* read the title */ slurp_rewind(fp); slurp_read(fp, song->title, 25); song->title[25] = 0; /* skip the last three bytes of the title, the supposed-to-be-0x1a byte, the tracker ID, and the two useless reserved bytes */ slurp_seek(fp, 7, SEEK_CUR); slurp_read(fp, &nord, 2); slurp_read(fp, &nsmp, 2); slurp_read(fp, &npat, 2); nord = bswapLE16(nord); nsmp = bswapLE16(nsmp); npat = bswapLE16(npat); if (nord > MAX_ORDERS || nsmp > MAX_SAMPLES || npat > MAX_PATTERNS) return LOAD_FORMAT_ERROR; song->flags = SONG_ITOLDEFFECTS; slurp_read(fp, &flags, 2); /* flags (don't really care) */ flags = bswapLE16(flags); slurp_read(fp, &trkvers, 2); trkvers = bswapLE16(trkvers); slurp_read(fp, &tmp, 2); /* file format info */ if (tmp == bswapLE16(1)) misc &= ~S3M_UNSIGNED; /* signed samples (ancient s3m) */ slurp_seek(fp, 4, SEEK_CUR); /* skip the tag */ song->initial_global_volume = slurp_getc(fp) << 1; // In the case of invalid data, ST3 uses the speed/tempo value that's set in the player prior to // loading the song, but that's just crazy. song->initial_speed = slurp_getc(fp) ?: 6; song->initial_tempo = slurp_getc(fp); if (song->initial_tempo <= 32) { // (Yes, 32 is ignored by Scream Tracker.) song->initial_tempo = 125; } song->mixing_volume = slurp_getc(fp); if (song->mixing_volume & 0x80) { song->mixing_volume ^= 0x80; } else { song->flags |= SONG_NOSTEREO; } uc = slurp_getc(fp); /* ultraclick removal (useless) */ if (slurp_getc(fp) != 0xfc) misc &= ~S3M_CHANPAN; /* stored pan values */ /* Interesting: Impulse Tracker appears to leave some junk data in this unused section, and what's more, it always seems to follow the same general pattern. So it's actually possible to identify whether a song was saved in IT, then loaded and re-saved in ST3. */ slurp_seek(fp, 8, SEEK_CUR); slurp_read(fp, &special, 2); // field not used by st3 special = bswapLE16(special); /* channel settings */ for (n = 0; n < 32; n++) { /* Channel 'type': 0xFF is a disabled channel, which shows up as (--) in ST3. Any channel with the high bit set is muted. 00-07 are L1-L8, 08-0F are R1-R8, 10-18 are adlib channels A1-A9. Hacking at a file with a hex editor shows some perhaps partially-implemented stuff: types 19-1D show up in ST3 as AB, AS, AT, AC, and AH; 20-2D are the same as 10-1D except with 'B' insted of 'A'. None of these appear to produce any sound output, apart from 19 which plays adlib instruments briefly before cutting them. (Weird!) Also, 1E/1F and 2E/2F display as "??"; and pressing 'A' on a disabled (--) channel will change its type to 1F. Values past 2F seem to display bits of the UI like the copyright and help, strange! These out-of-range channel types will almost certainly hang or crash ST3 or produce other strange behavior. Simply put, don't do it. :) */ c = slurp_getc(fp); if (c & 0x80) { song->channels[n].flags |= CHN_MUTE; // ST3 doesn't even play effects in muted channels -- throw them out? c &= ~0x80; } if (c < 0x08) { // L1-L8 (panned to 3 in ST3) song->channels[n].panning = 14; } else if (c < 0x10) { // R1-R8 (panned to C in ST3) song->channels[n].panning = 50; } else if (c < 0x19) { // A1-A9 song->channels[n].panning = 32; adlib |= 1 << n; } else { // Disabled 0xff/0x7f, or broken song->channels[n].panning = 32; song->channels[n].flags |= CHN_MUTE; } song->channels[n].volume = 64; } for (; n < 64; n++) { song->channels[n].panning = 32; song->channels[n].volume = 64; song->channels[n].flags = CHN_MUTE; } /* orderlist */ slurp_read(fp, song->orderlist, nord); memset(song->orderlist + nord, ORDER_LAST, MAX_ORDERS - nord); /* load the parapointers */ slurp_read(fp, para_smp, 2 * nsmp); slurp_read(fp, para_pat, 2 * npat); /* default pannings */ if (misc & S3M_CHANPAN) { for (n = 0; n < 32; n++) { c = slurp_getc(fp); if (c & 0x20) song->channels[n].panning = ((c & 0xf) << 2) + 2; } } //mphack - fix the pannings for (n = 0; n < 64; n++) song->channels[n].panning *= 4; /* samples */ for (n = 0, sample = song->samples + 1; n < nsmp; n++, sample++) { uint8_t type; slurp_seek(fp, (para_smp[n]) << 4, SEEK_SET); type = slurp_getc(fp); slurp_read(fp, sample->filename, 12); sample->filename[12] = 0; slurp_read(fp, b, 3); // data pointer for pcm, irrelevant otherwise switch (type) { case S3I_TYPE_PCM: para_sdata[n] = b[1] | (b[2] << 8) | (b[0] << 16); slurp_read(fp, &tmplong, 4); sample->length = bswapLE32(tmplong); slurp_read(fp, &tmplong, 4); sample->loop_start = bswapLE32(tmplong); slurp_read(fp, &tmplong, 4); sample->loop_end = bswapLE32(tmplong); sample->volume = slurp_getc(fp) * 4; //mphack slurp_getc(fp); /* unused byte */ slurp_getc(fp); /* packing info (never used) */ c = slurp_getc(fp); /* flags */ if (c & 1) sample->flags |= CHN_LOOP; smp_flags[n] = (SF_LE | ((misc & S3M_UNSIGNED) ? SF_PCMU : SF_PCMS) | ((c & 4) ? SF_16 : SF_8) | ((c & 2) ? SF_SS : SF_M)); break; default: //printf("s3m: mystery-meat sample type %d\n", type); case S3I_TYPE_NONE: slurp_seek(fp, 12, SEEK_CUR); sample->volume = slurp_getc(fp) * 4; //mphack slurp_seek(fp, 3, SEEK_CUR); break; case S3I_TYPE_ADMEL: slurp_read(fp, sample->adlib_bytes, 12); sample->volume = slurp_getc(fp) * 4; //mphack // next byte is "dsk", what is that? slurp_seek(fp, 3, SEEK_CUR); sample->flags |= CHN_ADLIB; // dumb hackaround that ought to some day be fixed: sample->length = 1; sample->data = csf_allocate_sample(1); break; } slurp_read(fp, &tmplong, 4); sample->c5speed = bswapLE32(tmplong); if (type == S3I_TYPE_ADMEL) { if (sample->c5speed < 1000 || sample->c5speed > 0xFFFF) { sample->c5speed = 8363; } } slurp_seek(fp, 12, SEEK_CUR); /* wasted space */ slurp_read(fp, sample->name, 25); sample->name[25] = 0; sample->vib_type = 0; sample->vib_rate = 0; sample->vib_depth = 0; sample->vib_speed = 0; sample->global_volume = 64; } /* sample data */ if (!(lflags & LOAD_NOSAMPLES)) { for (n = 0, sample = song->samples + 1; n < nsmp; n++, sample++) { if (!sample->length || (sample->flags & CHN_ADLIB)) continue; slurp_seek(fp, para_sdata[n] << 4, SEEK_SET); csf_read_sample(sample, smp_flags[n], fp->data + fp->pos, fp->length - fp->pos); } } if (!(lflags & LOAD_NOPATTERNS)) { for (n = 0; n < npat; n++) { int row = 0; long end; para_pat[n] = bswapLE16(para_pat[n]); if (!para_pat[n]) continue; slurp_seek(fp, para_pat[n] << 4, SEEK_SET); slurp_read(fp, &tmp, 2); end = (para_pat[n] << 4) + bswapLE16(tmp) + 2; song->patterns[n] = csf_allocate_pattern(64); while (row < 64 && slurp_tell(fp) < end) { int mask = slurp_getc(fp); uint8_t chn = (mask & 31); if (mask == EOF) { log_appendf(4, " Warning: Pattern %d: file truncated", n); break; } if (!mask) { /* done with the row */ row++; continue; } note = song->patterns[n] + 64 * row + chn; if (mask & 32) { /* note/instrument */ note->note = slurp_getc(fp); note->instrument = slurp_getc(fp); //if (note->instrument > 99) // note->instrument = 0; switch (note->note) { default: // Note; hi=oct, lo=note note->note = (note->note >> 4) * 12 + (note->note & 0xf) + 13; break; case 255: note->note = NOTE_NONE; break; case 254: note->note = (adlib & (1 << chn)) ? NOTE_OFF : NOTE_CUT; break; } } if (mask & 64) { /* volume */ note->voleffect = VOLFX_VOLUME; note->volparam = slurp_getc(fp); if (note->volparam == 255) { note->voleffect = VOLFX_NONE; note->volparam = 0; } else if (note->volparam > 64) { // some weirdly saved s3m? note->volparam = 64; } } if (mask & 128) { note->effect = slurp_getc(fp); note->param = slurp_getc(fp); csf_import_s3m_effect(note, 0); if (note->effect == FX_SPECIAL) { // mimic ST3's SD0/SC0 behavior if (note->param == 0xd0) { note->note = NOTE_NONE; note->instrument = 0; note->voleffect = VOLFX_NONE; note->volparam = 0; note->effect = FX_NONE; note->param = 0; } else if (note->param == 0xc0) { note->effect = FX_NONE; note->param = 0; } } } /* ... next note, same row */ } } }
int load_its_sample(const uint8_t *header, const uint8_t *data, size_t length, song_sample_t *smp) { struct it_sample *its = (struct it_sample *)header; uint32_t format; uint32_t bp; if (length < 80 || strncmp((const char *) header, "IMPS", 4) != 0) return 0; /* alright, let's get started */ smp->length = bswapLE32(its->length); if ((its->flags & 1) == 0) { // sample associated with header return 0; } // endianness (always little) format = SF_LE; if (its->flags & 8) { // no such thing as compressed stereo // (TODO perhaps test with various players to see how this is implemented) format |= SF_M; // compression algorithm format |= (its->cvt & 4) ? SF_IT215 : SF_IT214; } else { // channels format |= (its->flags & 4) ? SF_SS : SF_M; // signedness (or delta?) format |= (its->cvt & 4) ? SF_PCMD : (its->cvt & 1) ? SF_PCMS : SF_PCMU; } // bit width format |= (its->flags & 2) ? SF_16 : SF_8; smp->global_volume = its->gvl; if (its->flags & 16) { smp->flags |= CHN_LOOP; if (its->flags & 64) smp->flags |= CHN_PINGPONGLOOP; } if (its->flags & 32) { smp->flags |= CHN_SUSTAINLOOP; if (its->flags & 128) smp->flags |= CHN_PINGPONGSUSTAIN; } smp->volume = its->vol * 4; strncpy(smp->name, (const char *) its->name, 25); smp->panning = (its->dfp & 127) * 4; if (its->dfp & 128) smp->flags |= CHN_PANNING; smp->loop_start = bswapLE32(its->loopbegin); smp->loop_end = bswapLE32(its->loopend); smp->c5speed = bswapLE32(its->C5Speed); smp->sustain_start = bswapLE32(its->susloopbegin); smp->sustain_end = bswapLE32(its->susloopend); int vibs[] = {VIB_SINE, VIB_RAMP_DOWN, VIB_SQUARE, VIB_RANDOM}; smp->vib_type = vibs[its->vit & 3]; smp->vib_rate = its->vir; smp->vib_depth = its->vid; smp->vib_speed = its->vis; // sanity checks // (I should probably have more of these in general) if (smp->loop_start > smp->length) { smp->loop_start = smp->length; smp->flags &= ~(CHN_LOOP | CHN_PINGPONGLOOP); } if (smp->loop_end > smp->length) { smp->loop_end = smp->length; smp->flags &= ~(CHN_LOOP | CHN_PINGPONGLOOP); } if (smp->sustain_start > smp->length) { smp->sustain_start = smp->length; smp->flags &= ~(CHN_SUSTAINLOOP | CHN_PINGPONGSUSTAIN); } if (smp->sustain_end > smp->length) { smp->sustain_end = smp->length; smp->flags &= ~(CHN_SUSTAINLOOP | CHN_PINGPONGSUSTAIN); } bp = bswapLE32(its->samplepointer); // dumb casts :P return csf_read_sample((song_sample_t *) smp, format, (const char *) (data + bp), (uint32_t) (length - bp)); }
BOOL CSoundFile::ReadPTM(const BYTE *lpStream, DWORD dwMemLength) //--------------------------------------------------------------- { DWORD dwMemPos; UINT nOrders; if ((!lpStream) || (dwMemLength < sizeof(PTMFILEHEADER))) return FALSE; PTMFILEHEADER pfh = *(LPPTMFILEHEADER)lpStream; pfh.norders = bswapLE16(pfh.norders); pfh.nsamples = bswapLE16(pfh.nsamples); pfh.npatterns = bswapLE16(pfh.npatterns); pfh.nchannels = bswapLE16(pfh.nchannels); pfh.fileflags = bswapLE16(pfh.fileflags); pfh.reserved2 = bswapLE16(pfh.reserved2); pfh.ptmf_id = bswapLE32(pfh.ptmf_id); for (UINT j=0; j<128; j++) { pfh.patseg[j] = bswapLE16(pfh.patseg[j]); } if ((pfh.ptmf_id != 0x464d5450) || (!pfh.nchannels) || (pfh.nchannels > 32) || (pfh.norders > 256) || (!pfh.norders) || (!pfh.nsamples) || (pfh.nsamples > 255) || (!pfh.npatterns) || (pfh.npatterns > 128) || (SIZEOF_PTMFILEHEADER+pfh.nsamples*SIZEOF_PTMSAMPLE >= (int)dwMemLength)) return FALSE; memcpy(m_szNames[0], pfh.songname, 28); m_szNames[0][28] = 0; m_nType = MOD_TYPE_PTM; m_nChannels = pfh.nchannels; m_nSamples = (pfh.nsamples < MAX_SAMPLES) ? pfh.nsamples : MAX_SAMPLES-1; dwMemPos = SIZEOF_PTMFILEHEADER; nOrders = (pfh.norders < MAX_ORDERS) ? pfh.norders : MAX_ORDERS-1; memcpy(Order, pfh.orders, nOrders); for (UINT ipan=0; ipan<m_nChannels; ipan++) { ChnSettings[ipan].nVolume = 64; ChnSettings[ipan].nPan = ((pfh.chnpan[ipan] & 0x0F) << 4) + 4; } for (UINT ismp=0; ismp<m_nSamples; ismp++, dwMemPos += SIZEOF_PTMSAMPLE) { MODINSTRUMENT *pins = &Ins[ismp+1]; PTMSAMPLE *psmp = (PTMSAMPLE *)(lpStream+dwMemPos); lstrcpyn(m_szNames[ismp+1], psmp->samplename, 28); memcpy(pins->name, psmp->filename, 12); pins->name[12] = 0; pins->nGlobalVol = 64; pins->nPan = 128; pins->nVolume = psmp->volume << 2; pins->nC4Speed = bswapLE16(psmp->nC4Spd) << 1; pins->uFlags = 0; if ((psmp->sampletype & 3) == 1) { UINT smpflg = RS_PCM8D; pins->nLength = BS2WORD(psmp->length); pins->nLoopStart = BS2WORD(psmp->loopbeg); pins->nLoopEnd = BS2WORD(psmp->loopend); DWORD samplepos = BS2WORD(psmp->fileofs); if (psmp->sampletype & 4) pins->uFlags |= CHN_LOOP; if (psmp->sampletype & 8) pins->uFlags |= CHN_PINGPONGLOOP; if (psmp->sampletype & 16) { pins->uFlags |= CHN_16BIT; pins->nLength >>= 1; pins->nLoopStart >>= 1; pins->nLoopEnd >>= 1; smpflg = RS_PTM8DTO16; } if ((pins->nLength) && (samplepos) && (samplepos < dwMemLength)) { ReadSample(pins, smpflg, (LPSTR)(lpStream+samplepos), dwMemLength-samplepos); } }
BOOL CSoundFile::ReadXM(const BYTE *lpStream, DWORD dwMemLength) //-------------------------------------------------------------- { XMSAMPLEHEADER xmsh; XMSAMPLESTRUCT xmss; DWORD dwMemPos, dwHdrSize; WORD norders=0, restartpos=0, channels=0, patterns=0, instruments=0; WORD xmflags=0, deftempo=125, defspeed=6; BOOL InstUsed[256]; BYTE channels_used[MAX_CHANNELS]; BYTE pattern_map[256]; BOOL samples_used[MAX_SAMPLES]; UINT unused_samples; tagXMFILEHEADER xmhead; m_nChannels = 0; if ((!lpStream) || (dwMemLength < 0x200)) return FALSE; if (strncmp((LPCSTR)lpStream, "Extended Module:", 16)) return FALSE; memcpy(m_szNames[0], lpStream+17, 20); xmhead = *(tagXMFILEHEADER *)(lpStream+60); dwHdrSize = bswapLE32(xmhead.size); norders = bswapLE16(xmhead.norder); if ((!norders) || (norders > MAX_ORDERS)) return FALSE; restartpos = bswapLE16(xmhead.restartpos); channels = bswapLE16(xmhead.channels); if ((!channels) || (channels > 64)) return FALSE; m_nType = MOD_TYPE_XM; m_nMinPeriod = 27; m_nMaxPeriod = 54784; m_nChannels = channels; if (restartpos < norders) m_nRestartPos = restartpos; patterns = bswapLE16(xmhead.patterns); if (patterns > 256) patterns = 256; instruments = bswapLE16(xmhead.instruments); if (instruments >= MAX_INSTRUMENTS) instruments = MAX_INSTRUMENTS-1; m_nInstruments = instruments; m_nSamples = 0; xmflags = bswapLE16(xmhead.flags); if (xmflags & 1) m_dwSongFlags |= SONG_LINEARSLIDES; if (xmflags & 0x1000) m_dwSongFlags |= SONG_EXFILTERRANGE; defspeed = bswapLE16(xmhead.speed); deftempo = bswapLE16(xmhead.tempo); if ((deftempo >= 32) && (deftempo < 256)) m_nDefaultTempo = deftempo; if ((defspeed > 0) && (defspeed < 40)) m_nDefaultSpeed = defspeed; memcpy(Order, lpStream+80, norders); memset(InstUsed, 0, sizeof(InstUsed)); if (patterns > MAX_PATTERNS) { UINT i, j; for (i=0; i<norders; i++) { if (Order[i] < patterns) InstUsed[Order[i]] = TRUE; } j = 0; for (i=0; i<256; i++) { if (InstUsed[i]) pattern_map[i] = j++; } for (i=0; i<256; i++) { if (!InstUsed[i]) { pattern_map[i] = (j < MAX_PATTERNS) ? j : 0xFE; j++; } } for (i=0; i<norders; i++) { Order[i] = pattern_map[Order[i]]; } } else { for (UINT i=0; i<256; i++) pattern_map[i] = i; } memset(InstUsed, 0, sizeof(InstUsed)); dwMemPos = dwHdrSize + 60; if (dwMemPos + 8 >= dwMemLength) return TRUE; // Reading patterns memset(channels_used, 0, sizeof(channels_used)); for (UINT ipat=0; ipat<patterns; ipat++) { UINT ipatmap = pattern_map[ipat]; DWORD dwSize = 0; WORD rows=64, packsize=0; dwSize = bswapLE32(loadDWORD(lpStream+dwMemPos)); while ((dwMemPos + dwSize >= dwMemLength) || (dwSize & 0xFFFFFF00)) { if (dwMemPos + 4 >= dwMemLength) break; dwMemPos++; dwSize = bswapLE32(loadDWORD(lpStream+dwMemPos)); } rows = bswapLE16(loadWORD(lpStream+dwMemPos+5)); if ((!rows) || (rows > 256)) rows = 64; packsize = bswapLE16(loadWORD(lpStream+dwMemPos+7)); if (dwMemPos + dwSize + 4 > dwMemLength) return TRUE; dwMemPos += dwSize; if (dwMemPos + packsize + 4 > dwMemLength) return TRUE; MODCOMMAND *p; if (ipatmap < MAX_PATTERNS) { PatternSize[ipatmap] = rows; if ((Patterns[ipatmap] = AllocatePattern(rows, m_nChannels)) == NULL) return TRUE; if (!packsize) continue; p = Patterns[ipatmap]; } else p = NULL; const BYTE *src = lpStream+dwMemPos; UINT j=0; for (UINT row=0; row<rows; row++) { for (UINT chn=0; chn<m_nChannels; chn++) { if ((p) && (j < packsize)) { BYTE b = src[j++]; UINT vol = 0; if (b & 0x80) { if (b & 1) p->note = src[j++]; if (b & 2) p->instr = src[j++]; if (b & 4) vol = src[j++]; if (b & 8) p->command = src[j++]; if (b & 16) p->param = src[j++]; } else { p->note = b; p->instr = src[j++]; vol = src[j++]; p->command = src[j++]; p->param = src[j++]; } if (p->note == 97) p->note = 0xFF; else if ((p->note) && (p->note < 97)) p->note += 12; if (p->note) channels_used[chn] = 1; if (p->command | p->param) ConvertModCommand(p); if (p->instr == 0xff) p->instr = 0; if (p->instr) InstUsed[p->instr] = TRUE; if ((vol >= 0x10) && (vol <= 0x50)) { p->volcmd = VOLCMD_VOLUME; p->vol = vol - 0x10; } else if (vol >= 0x60) { UINT v = vol & 0xF0; vol &= 0x0F; p->vol = vol; switch(v) { // 60-6F: Volume Slide Down case 0x60: p->volcmd = VOLCMD_VOLSLIDEDOWN; break; // 70-7F: Volume Slide Up: case 0x70: p->volcmd = VOLCMD_VOLSLIDEUP; break; // 80-8F: Fine Volume Slide Down case 0x80: p->volcmd = VOLCMD_FINEVOLDOWN; break; // 90-9F: Fine Volume Slide Up case 0x90: p->volcmd = VOLCMD_FINEVOLUP; break; // A0-AF: Set Vibrato Speed case 0xA0: p->volcmd = VOLCMD_VIBRATOSPEED; break; // B0-BF: Vibrato case 0xB0: p->volcmd = VOLCMD_VIBRATO; break; // C0-CF: Set Panning case 0xC0: p->volcmd = VOLCMD_PANNING; p->vol = (vol << 2) + 2; break; // D0-DF: Panning Slide Left case 0xD0: p->volcmd = VOLCMD_PANSLIDELEFT; break; // E0-EF: Panning Slide Right case 0xE0: p->volcmd = VOLCMD_PANSLIDERIGHT; break; // F0-FF: Tone Portamento case 0xF0: p->volcmd = VOLCMD_TONEPORTAMENTO; break; } } p++; } else if (j < packsize) { BYTE b = src[j++]; if (b & 0x80) { if (b & 1) j++; if (b & 2) j++; if (b & 4) j++; if (b & 8) j++; if (b & 16) j++; } else j += 4; } else break; } } dwMemPos += packsize; } // Wrong offset check while (dwMemPos + 4 < dwMemLength) { DWORD d = bswapLE32(loadDWORD(lpStream+dwMemPos)); if (d < 0x300) break; dwMemPos++; } memset(samples_used, 0, sizeof(samples_used)); unused_samples = 0; // Reading instruments for (UINT iIns=1; iIns<=instruments; iIns++) { XMINSTRUMENTHEADER *pih; BYTE flags[32]; DWORD samplesize[32]; UINT samplemap[32]; WORD nsamples; if (dwMemPos + sizeof(XMINSTRUMENTHEADER) >= dwMemLength) return TRUE; pih = (XMINSTRUMENTHEADER *)(lpStream+dwMemPos); if (dwMemPos + bswapLE32(pih->size) > dwMemLength) return TRUE; if ((Headers[iIns] = new INSTRUMENTHEADER) == NULL) continue; memset(Headers[iIns], 0, sizeof(INSTRUMENTHEADER)); memcpy(Headers[iIns]->name, pih->name, 22); if ((nsamples = pih->samples) > 0) { if (dwMemPos + sizeof(XMSAMPLEHEADER) > dwMemLength) return TRUE; memcpy(&xmsh, lpStream+dwMemPos+sizeof(XMINSTRUMENTHEADER), sizeof(XMSAMPLEHEADER)); xmsh.shsize = bswapLE32(xmsh.shsize); for (int i = 0; i < 24; ++i) { xmsh.venv[i] = bswapLE16(xmsh.venv[i]); xmsh.penv[i] = bswapLE16(xmsh.penv[i]); } xmsh.volfade = bswapLE16(xmsh.volfade); xmsh.res = bswapLE16(xmsh.res); dwMemPos += bswapLE32(pih->size); } else { if (bswapLE32(pih->size)) dwMemPos += bswapLE32(pih->size); else dwMemPos += sizeof(XMINSTRUMENTHEADER); continue; } memset(samplemap, 0, sizeof(samplemap)); if (nsamples > 32) return TRUE; UINT newsamples = m_nSamples; for (UINT nmap=0; nmap<nsamples; nmap++) { UINT n = m_nSamples+nmap+1; if (n >= MAX_SAMPLES) { n = m_nSamples; while (n > 0) { if (!Ins[n].pSample) { for (UINT xmapchk=0; xmapchk < nmap; xmapchk++) { if (samplemap[xmapchk] == n) goto alreadymapped; } for (UINT clrs=1; clrs<iIns; clrs++) if (Headers[clrs]) { INSTRUMENTHEADER *pks = Headers[clrs]; for (UINT ks=0; ks<128; ks++) { if (pks->Keyboard[ks] == n) pks->Keyboard[ks] = 0; } } break; } alreadymapped: n--; } #ifndef MODPLUG_FASTSOUNDLIB // Damn! more than 200 samples: look for duplicates if (!n) { if (!unused_samples) { unused_samples = DetectUnusedSamples(samples_used); if (!unused_samples) unused_samples = 0xFFFF; } if ((unused_samples) && (unused_samples != 0xFFFF)) { for (UINT iext=m_nSamples; iext>=1; iext--) if (!samples_used[iext]) { unused_samples--; samples_used[iext] = TRUE; DestroySample(iext); n = iext; for (UINT mapchk=0; mapchk<nmap; mapchk++) { if (samplemap[mapchk] == n) samplemap[mapchk] = 0; } for (UINT clrs=1; clrs<iIns; clrs++) if (Headers[clrs]) { INSTRUMENTHEADER *pks = Headers[clrs]; for (UINT ks=0; ks<128; ks++) { if (pks->Keyboard[ks] == n) pks->Keyboard[ks] = 0; } } memset(&Ins[n], 0, sizeof(Ins[0])); break; } } } #endif // MODPLUG_FASTSOUNDLIB } if (newsamples < n) newsamples = n; samplemap[nmap] = n; } m_nSamples = newsamples; // Reading Volume Envelope INSTRUMENTHEADER *penv = Headers[iIns]; penv->nMidiProgram = pih->type; penv->nFadeOut = xmsh.volfade; penv->nPan = 128; penv->nPPC = 5*12; if (xmsh.vtype & 1) penv->dwFlags |= ENV_VOLUME; if (xmsh.vtype & 2) penv->dwFlags |= ENV_VOLSUSTAIN; if (xmsh.vtype & 4) penv->dwFlags |= ENV_VOLLOOP; if (xmsh.ptype & 1) penv->dwFlags |= ENV_PANNING; if (xmsh.ptype & 2) penv->dwFlags |= ENV_PANSUSTAIN; if (xmsh.ptype & 4) penv->dwFlags |= ENV_PANLOOP; if (xmsh.vnum > 12) xmsh.vnum = 12; if (xmsh.pnum > 12) xmsh.pnum = 12; penv->nVolEnv = xmsh.vnum; if (!xmsh.vnum) penv->dwFlags &= ~ENV_VOLUME; if (!xmsh.pnum) penv->dwFlags &= ~ENV_PANNING; penv->nPanEnv = xmsh.pnum; penv->nVolSustainBegin = penv->nVolSustainEnd = xmsh.vsustain; if (xmsh.vsustain >= 12) penv->dwFlags &= ~ENV_VOLSUSTAIN; penv->nVolLoopStart = xmsh.vloops; penv->nVolLoopEnd = xmsh.vloope; if (penv->nVolLoopEnd >= 12) penv->nVolLoopEnd = 0; if (penv->nVolLoopStart >= penv->nVolLoopEnd) penv->dwFlags &= ~ENV_VOLLOOP; penv->nPanSustainBegin = penv->nPanSustainEnd = xmsh.psustain; if (xmsh.psustain >= 12) penv->dwFlags &= ~ENV_PANSUSTAIN; penv->nPanLoopStart = xmsh.ploops; penv->nPanLoopEnd = xmsh.ploope; if (penv->nPanLoopEnd >= 12) penv->nPanLoopEnd = 0; if (penv->nPanLoopStart >= penv->nPanLoopEnd) penv->dwFlags &= ~ENV_PANLOOP; penv->nGlobalVol = 64; for (UINT ienv=0; ienv<12; ienv++) { penv->VolPoints[ienv] = (WORD)xmsh.venv[ienv*2]; penv->VolEnv[ienv] = (BYTE)xmsh.venv[ienv*2+1]; penv->PanPoints[ienv] = (WORD)xmsh.penv[ienv*2]; penv->PanEnv[ienv] = (BYTE)xmsh.penv[ienv*2+1]; if (ienv) { if (penv->VolPoints[ienv] < penv->VolPoints[ienv-1]) { penv->VolPoints[ienv] &= 0xFF; penv->VolPoints[ienv] += penv->VolPoints[ienv-1] & 0xFF00; if (penv->VolPoints[ienv] < penv->VolPoints[ienv-1]) penv->VolPoints[ienv] += 0x100; } if (penv->PanPoints[ienv] < penv->PanPoints[ienv-1]) { penv->PanPoints[ienv] &= 0xFF; penv->PanPoints[ienv] += penv->PanPoints[ienv-1] & 0xFF00; if (penv->PanPoints[ienv] < penv->PanPoints[ienv-1]) penv->PanPoints[ienv] += 0x100; } } } for (UINT j=0; j<96; j++) { penv->NoteMap[j+12] = j+1+12; if (xmsh.snum[j] < nsamples) penv->Keyboard[j+12] = samplemap[xmsh.snum[j]]; } // Reading samples for (UINT ins=0; ins<nsamples; ins++) { if ((dwMemPos + sizeof(xmss) > dwMemLength) || (dwMemPos + xmsh.shsize > dwMemLength)) return TRUE; memcpy(&xmss, lpStream+dwMemPos, sizeof(xmss)); xmss.samplen = bswapLE32(xmss.samplen); xmss.loopstart = bswapLE32(xmss.loopstart); xmss.looplen = bswapLE32(xmss.looplen); dwMemPos += xmsh.shsize; flags[ins] = (xmss.type & 0x10) ? RS_PCM16D : RS_PCM8D; if (xmss.type & 0x20) flags[ins] = (xmss.type & 0x10) ? RS_STPCM16D : RS_STPCM8D; samplesize[ins] = xmss.samplen; if (!samplemap[ins]) continue; 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; } if (xmss.samplen > MAX_SAMPLE_LENGTH) xmss.samplen = MAX_SAMPLE_LENGTH; if (xmss.loopstart >= xmss.samplen) xmss.type &= ~3; xmss.looplen += xmss.loopstart; if (xmss.looplen > xmss.samplen) xmss.looplen = xmss.samplen; if (!xmss.looplen) xmss.type &= ~3; UINT imapsmp = samplemap[ins]; memcpy(m_szNames[imapsmp], xmss.name, 22); m_szNames[imapsmp][22] = 0; MODINSTRUMENT *pins = &Ins[imapsmp]; pins->nLength = (xmss.samplen > MAX_SAMPLE_LENGTH) ? MAX_SAMPLE_LENGTH : xmss.samplen; pins->nLoopStart = xmss.loopstart; pins->nLoopEnd = xmss.looplen; if (pins->nLoopEnd > pins->nLength) pins->nLoopEnd = pins->nLength; if (pins->nLoopStart >= pins->nLoopEnd) { pins->nLoopStart = pins->nLoopEnd = 0; } if (xmss.type & 3) pins->uFlags |= CHN_LOOP; if (xmss.type & 2) pins->uFlags |= CHN_PINGPONGLOOP; pins->nVolume = xmss.vol << 2; if (pins->nVolume > 256) pins->nVolume = 256; pins->nGlobalVol = 64; if ((xmss.res == 0xAD) && (!(xmss.type & 0x30))) { flags[ins] = RS_ADPCM4; samplesize[ins] = (samplesize[ins]+1)/2 + 16; } pins->nFineTune = xmss.finetune; pins->RelativeTone = (int)xmss.relnote; pins->nPan = xmss.pan; pins->uFlags |= CHN_PANNING; pins->nVibType = xmsh.vibtype; pins->nVibSweep = xmsh.vibsweep; pins->nVibDepth = xmsh.vibdepth; pins->nVibRate = xmsh.vibrate; memcpy(pins->name, xmss.name, 22); pins->name[21] = 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); }
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; }
static uint32_t BS2WORD(uint16_t w[2]) { uint32_t u32 = (w[1] << 16) + w[0]; return(bswapLE32(u32)); }