Diffstat (limited to 'core/multimedia/opieplayer/modplug/load_ams.cpp') (more/less context) (ignore whitespace changes)
-rw-r--r-- | core/multimedia/opieplayer/modplug/load_ams.cpp | 2 |
1 files changed, 1 insertions, 1 deletions
diff --git a/core/multimedia/opieplayer/modplug/load_ams.cpp b/core/multimedia/opieplayer/modplug/load_ams.cpp index 3dd1c2b..ad1cc01 100644 --- a/core/multimedia/opieplayer/modplug/load_ams.cpp +++ b/core/multimedia/opieplayer/modplug/load_ams.cpp @@ -245,387 +245,387 @@ BOOL CSoundFile::ReadAMS(LPCBYTE lpStream, DWORD dwMemLength) UINT flags = (Ins[iSmp].uFlags & CHN_16BIT) ? RS_AMS16 : RS_AMS8; dwMemPos += ReadSample(&Ins[iSmp], flags, (LPSTR)(lpStream+dwMemPos), dwMemLength-dwMemPos); } return TRUE; } ///////////////////////////////////////////////////////////////////// // AMS 2.2 loader #pragma pack(1) typedef struct AMS2FILEHEADER { DWORD dwHdr1; // AMShdr WORD wHdr2; BYTE b1A; // 0x1A BYTE titlelen; // 30-bytes max CHAR szTitle[30]; // [titlelen] } Q_PACKED AMS2FILEHEADER; typedef struct AMS2SONGHEADER { WORD version; BYTE instruments; WORD patterns; WORD orders; WORD bpm; BYTE speed; BYTE channels; BYTE commands; BYTE rows; WORD flags; } Q_PACKED AMS2SONGHEADER; typedef struct AMS2INSTRUMENT { BYTE samples; BYTE notemap[120]; } Q_PACKED AMS2INSTRUMENT; typedef struct AMS2ENVELOPE { BYTE speed; BYTE sustain; BYTE loopbegin; BYTE loopend; BYTE points; BYTE info[3]; } Q_PACKED AMS2ENVELOPE; typedef struct AMS2SAMPLE { DWORD length; DWORD loopstart; DWORD loopend; WORD frequency; BYTE finetune; WORD c4speed; CHAR transpose; BYTE volume; BYTE flags; } Q_PACKED AMS2SAMPLE; #pragma pack() BOOL CSoundFile::ReadAMS2(LPCBYTE lpStream, DWORD dwMemLength) //------------------------------------------------------------ { AMS2FILEHEADER *pfh = (AMS2FILEHEADER *)lpStream; AMS2SONGHEADER *psh; DWORD dwMemPos; BYTE smpmap[16]; BYTE packedsamples[MAX_SAMPLES]; if ((pfh->dwHdr1 != 0x68534D41) || (pfh->wHdr2 != 0x7264) || (pfh->b1A != 0x1A) || (pfh->titlelen > 30)) return FALSE; dwMemPos = pfh->titlelen + 8; psh = (AMS2SONGHEADER *)(lpStream + dwMemPos); if (((psh->version & 0xFF00) != 0x0200) || (!psh->instruments) || (psh->instruments > MAX_INSTRUMENTS) || (!psh->patterns) || (!psh->orders)) return FALSE; dwMemPos += sizeof(AMS2SONGHEADER); if (pfh->titlelen) { memcpy(m_szNames, pfh->szTitle, pfh->titlelen); m_szNames[0][pfh->titlelen] = 0; } m_nType = MOD_TYPE_AMS; m_nChannels = 32; m_nDefaultTempo = psh->bpm >> 8; m_nDefaultSpeed = psh->speed; m_nInstruments = psh->instruments; m_nSamples = 0; if (psh->flags & 0x40) m_dwSongFlags |= SONG_LINEARSLIDES; for (UINT nIns=1; nIns<=m_nInstruments; nIns++) { UINT insnamelen = lpStream[dwMemPos]; CHAR *pinsname = (CHAR *)(lpStream+dwMemPos+1); dwMemPos += insnamelen + 1; AMS2INSTRUMENT *pins = (AMS2INSTRUMENT *)(lpStream + dwMemPos); dwMemPos += sizeof(AMS2INSTRUMENT); if (dwMemPos + 1024 >= dwMemLength) return TRUE; AMS2ENVELOPE *volenv, *panenv, *pitchenv; volenv = (AMS2ENVELOPE *)(lpStream+dwMemPos); dwMemPos += 5 + volenv->points*3; panenv = (AMS2ENVELOPE *)(lpStream+dwMemPos); dwMemPos += 5 + panenv->points*3; pitchenv = (AMS2ENVELOPE *)(lpStream+dwMemPos); dwMemPos += 5 + pitchenv->points*3; INSTRUMENTHEADER *penv = new INSTRUMENTHEADER; if (!penv) return TRUE; memset(smpmap, 0, sizeof(smpmap)); memset(penv, 0, sizeof(INSTRUMENTHEADER)); for (UINT ismpmap=0; ismpmap<pins->samples; ismpmap++) { if ((ismpmap >= 16) || (m_nSamples+1 >= MAX_SAMPLES)) break; m_nSamples++; smpmap[ismpmap] = m_nSamples; } penv->nGlobalVol = 64; penv->nPan = 128; penv->nPPC = 60; Headers[nIns] = penv; if (insnamelen) { if (insnamelen > 31) insnamelen = 31; memcpy(penv->name, pinsname, insnamelen); penv->name[insnamelen] = 0; } for (UINT inotemap=0; inotemap<120; inotemap++) { penv->NoteMap[inotemap] = inotemap+1; penv->Keyboard[inotemap] = smpmap[pins->notemap[inotemap] & 0x0F]; } // Volume Envelope { UINT pos = 0; penv->nVolEnv = (volenv->points > 16) ? 16 : volenv->points; penv->nVolSustainBegin = penv->nVolSustainEnd = volenv->sustain; penv->nVolLoopStart = volenv->loopbegin; penv->nVolLoopEnd = volenv->loopend; for (UINT i=0; i<penv->nVolEnv; i++) { penv->VolEnv[i] = (BYTE)((volenv->info[i*3+2] & 0x7F) >> 1); pos += volenv->info[i*3] + ((volenv->info[i*3+1] & 1) << 8); penv->VolPoints[i] = (WORD)pos; } } penv->nFadeOut = (((lpStream[dwMemPos+2] & 0x0F) << 8) | (lpStream[dwMemPos+1])) << 3; UINT envflags = lpStream[dwMemPos+3]; if (envflags & 0x01) penv->dwFlags |= ENV_VOLLOOP; if (envflags & 0x02) penv->dwFlags |= ENV_VOLSUSTAIN; if (envflags & 0x04) penv->dwFlags |= ENV_VOLUME; dwMemPos += 5; // Read Samples for (UINT ismp=0; ismp<pins->samples; ismp++) { MODINSTRUMENT *psmp = ((ismp < 16) && (smpmap[ismp])) ? &Ins[smpmap[ismp]] : NULL; UINT smpnamelen = lpStream[dwMemPos]; if ((psmp) && (smpnamelen) && (smpnamelen <= 22)) { memcpy(m_szNames[smpmap[ismp]], lpStream+dwMemPos+1, smpnamelen); } dwMemPos += smpnamelen + 1; if (psmp) { AMS2SAMPLE *pams = (AMS2SAMPLE *)(lpStream+dwMemPos); psmp->nGlobalVol = 64; psmp->nPan = 128; psmp->nLength = pams->length; psmp->nLoopStart = pams->loopstart; psmp->nLoopEnd = pams->loopend; psmp->nC4Speed = pams->c4speed; psmp->RelativeTone = pams->transpose; psmp->nVolume = pams->volume / 2; packedsamples[smpmap[ismp]] = pams->flags; if (pams->flags & 0x04) psmp->uFlags |= CHN_16BIT; if (pams->flags & 0x08) psmp->uFlags |= CHN_LOOP; if (pams->flags & 0x10) psmp->uFlags |= CHN_PINGPONGLOOP; } dwMemPos += sizeof(AMS2SAMPLE); } } if (dwMemPos + 256 >= dwMemLength) return TRUE; // Comments { UINT composernamelen = lpStream[dwMemPos]; if (composernamelen) { m_lpszSongComments = new char[composernamelen+1]; // changed from CHAR if (m_lpszSongComments) { memcpy(m_lpszSongComments, lpStream+dwMemPos+1, composernamelen); m_lpszSongComments[composernamelen] = 0; } } dwMemPos += composernamelen + 1; // channel names for (UINT i=0; i<32; i++) { UINT chnnamlen = lpStream[dwMemPos]; if ((chnnamlen) && (chnnamlen < MAX_CHANNELNAME)) { memcpy(ChnSettings[i].szName, lpStream+dwMemPos+1, chnnamlen); } dwMemPos += chnnamlen + 1; if (dwMemPos + chnnamlen + 256 >= dwMemLength) return TRUE; } // packed comments (ignored) UINT songtextlen = *((LPDWORD)(lpStream+dwMemPos)); dwMemPos += songtextlen; if (dwMemPos + 256 >= dwMemLength) return TRUE; } // Order List { for (UINT i=0; i<MAX_ORDERS; i++) { Order[i] = 0xFF; if (dwMemPos + 2 >= dwMemLength) return TRUE; if (i < psh->orders) { Order[i] = lpStream[dwMemPos]; dwMemPos += 2; } } } // Pattern Data for (UINT ipat=0; ipat<psh->patterns; ipat++) { if (dwMemPos+8 >= dwMemLength) return TRUE; UINT packedlen = *((LPDWORD)(lpStream+dwMemPos)); UINT numrows = 1 + (UINT)(lpStream[dwMemPos+4]); //UINT patchn = 1 + (UINT)(lpStream[dwMemPos+5] & 0x1F); //UINT patcmds = 1 + (UINT)(lpStream[dwMemPos+5] >> 5); UINT patnamlen = lpStream[dwMemPos+6]; dwMemPos += 4; if ((ipat < MAX_PATTERNS) && (packedlen < dwMemLength-dwMemPos) && (numrows >= 8)) { if ((patnamlen) && (patnamlen < MAX_PATTERNNAME)) { char s[MAX_PATTERNNAME]; // changed from CHAR memcpy(s, lpStream+dwMemPos+3, patnamlen); s[patnamlen] = 0; SetPatternName(ipat, s); } PatternSize[ipat] = numrows; Patterns[ipat] = AllocatePattern(numrows, m_nChannels); if (!Patterns[ipat]) return TRUE; // Unpack Pattern Data LPCBYTE psrc = lpStream + dwMemPos; UINT pos = 3 + patnamlen; UINT row = 0; while ((pos < packedlen) && (row < numrows)) { MODCOMMAND *m = Patterns[ipat] + row * m_nChannels; UINT byte1 = psrc[pos++]; UINT ch = byte1 & 0x1F; // Read Note + Instr if (!(byte1 & 0x40)) { UINT byte2 = psrc[pos++]; UINT note = byte2 & 0x7F; if (note) m[ch].note = (note > 1) ? (note-1) : 0xFF; m[ch].instr = psrc[pos++]; // Read Effect while (byte2 & 0x80) { byte2 = psrc[pos++]; if (byte2 & 0x40) { m[ch].volcmd = VOLCMD_VOLUME; m[ch].vol = byte2 & 0x3F; } else { UINT command = byte2 & 0x3F; UINT param = psrc[pos++]; if (command == 0x0C) { m[ch].volcmd = VOLCMD_VOLUME; m[ch].vol = param / 2; } else if (command < 0x10) { m[ch].command = command; m[ch].param = param; ConvertModCommand(&m[ch]); } else { // TODO: AMS effects } } } } if (byte1 & 0x80) row++; } } dwMemPos += packedlen; } // Read Samples for (UINT iSmp=1; iSmp<=m_nSamples; iSmp++) if (Ins[iSmp].nLength) { if (dwMemPos >= dwMemLength - 9) return TRUE; UINT flags; if (packedsamples[iSmp] & 0x03) { flags = (Ins[iSmp].uFlags & CHN_16BIT) ? RS_AMS16 : RS_AMS8; } else { flags = (Ins[iSmp].uFlags & CHN_16BIT) ? RS_PCM16S : RS_PCM8S; } dwMemPos += ReadSample(&Ins[iSmp], flags, (LPSTR)(lpStream+dwMemPos), dwMemLength-dwMemPos); } return TRUE; } ///////////////////////////////////////////////////////////////////// // AMS Sample unpacking void AMSUnpack(const char *psrc, UINT inputlen, char *pdest, UINT dmax, char packcharacter) { UINT tmplen = dmax; signed char *amstmp = new signed char[tmplen]; if (!amstmp) return; // Unpack Loop { signed char *p = amstmp; UINT i=0, j=0; while ((i < inputlen) && (j < tmplen)) { signed char ch = psrc[i++]; if (ch == packcharacter) { BYTE ch2 = psrc[i++]; if (ch2) { ch = psrc[i++]; while (ch2--) { p[j++] = ch; if (j >= tmplen) break; } } else p[j++] = packcharacter; } else p[j++] = ch; } } // Bit Unpack Loop { signed char *p = amstmp; UINT bitcount = 0x80, dh; UINT k=0; for (UINT i=0; i<dmax; i++) { BYTE al = *p++; dh = 0; for (UINT count=0; count<8; count++) { UINT bl = al & bitcount; bl = ((bl|(bl<<8)) >> ((dh+8-count) & 7)) & 0xFF; bitcount = ((bitcount|(bitcount<<8)) >> 1) & 0xFF; pdest[k++] |= bl; if (k >= dmax) { k = 0; dh++; } } bitcount = ((bitcount|(bitcount<<8)) >> dh) & 0xFF; } } // Delta Unpack { signed char old = 0; for (UINT i=0; i<dmax; i++) { int pos = ((LPBYTE)pdest)[i]; if ((pos != 128) && (pos & 0x80)) pos = -(pos & 0x7F); old -= (signed char)pos; pdest[i] = old; } } - delete amstmp; + delete [] amstmp; } |