From ac87bfc370ec15c9c81f8738659fb2582b14b792 Mon Sep 17 00:00:00 2001 From: Jeremy Simon Date: Thu, 28 Feb 2002 21:10:42 +0000 Subject: adding modplug Original commit message from CVS: adding modplug --- gst/modplug/libmodplug/load_dsm.cpp | 236 ++++++++++++++++++++++++++++++++++++ 1 file changed, 236 insertions(+) create mode 100644 gst/modplug/libmodplug/load_dsm.cpp (limited to 'gst/modplug/libmodplug/load_dsm.cpp') diff --git a/gst/modplug/libmodplug/load_dsm.cpp b/gst/modplug/libmodplug/load_dsm.cpp new file mode 100644 index 00000000..4f51469f --- /dev/null +++ b/gst/modplug/libmodplug/load_dsm.cpp @@ -0,0 +1,236 @@ +/* + * This source code is public domain. + * + * Authors: Olivier Lapicque +*/ + +////////////////////////////////////////////// +// DSIK Internal Format (DSM) module loader // +////////////////////////////////////////////// +#include "stdafx.h" +#include "sndfile.h" + +#pragma pack(1) + +#define DSMID_RIFF 0x46464952 // "RIFF" +#define DSMID_DSMF 0x464d5344 // "DSMF" +#define DSMID_SONG 0x474e4f53 // "SONG" +#define DSMID_INST 0x54534e49 // "INST" +#define DSMID_PATT 0x54544150 // "PATT" + + +typedef struct DSMNOTE +{ + BYTE note,ins,vol,cmd,inf; +} DSMNOTE; + + +typedef struct DSMINST +{ + DWORD id_INST; + DWORD inst_len; + CHAR filename[13]; + BYTE flags; + BYTE flags2; + BYTE volume; + DWORD length; + DWORD loopstart; + DWORD loopend; + DWORD reserved1; + WORD c2spd; + WORD reserved2; + CHAR samplename[28]; +} DSMINST; + + +typedef struct DSMFILEHEADER +{ + DWORD id_RIFF; // "RIFF" + DWORD riff_len; + DWORD id_DSMF; // "DSMF" + DWORD id_SONG; // "SONG" + DWORD song_len; +} DSMFILEHEADER; + + +typedef struct DSMSONG +{ + CHAR songname[28]; + WORD reserved1; + WORD flags; + DWORD reserved2; + WORD numord; + WORD numsmp; + WORD numpat; + WORD numtrk; + BYTE globalvol; + BYTE mastervol; + BYTE speed; + BYTE bpm; + BYTE panpos[16]; + BYTE orders[128]; +} DSMSONG; + +typedef struct DSMPATT +{ + DWORD id_PATT; + DWORD patt_len; + BYTE dummy1; + BYTE dummy2; +} DSMPATT; + +#pragma pack() + + +BOOL CSoundFile::ReadDSM(LPCBYTE lpStream, DWORD dwMemLength) +//----------------------------------------------------------- +{ + DSMFILEHEADER *pfh = (DSMFILEHEADER *)lpStream; + DSMSONG *psong; + DWORD dwMemPos; + UINT nPat, nSmp; + + if ((!lpStream) || (dwMemLength < 1024) || (pfh->id_RIFF != DSMID_RIFF) + || (pfh->riff_len + 8 > dwMemLength) || (pfh->riff_len < 1024) + || (pfh->id_DSMF != DSMID_DSMF) || (pfh->id_SONG != DSMID_SONG) + || (pfh->song_len > dwMemLength)) return FALSE; + psong = (DSMSONG *)(lpStream + sizeof(DSMFILEHEADER)); + dwMemPos = sizeof(DSMFILEHEADER) + pfh->song_len; + m_nType = MOD_TYPE_DSM; + m_nChannels = psong->numtrk; + if (m_nChannels < 4) m_nChannels = 4; + if (m_nChannels > 16) m_nChannels = 16; + m_nSamples = psong->numsmp; + if (m_nSamples > MAX_SAMPLES) m_nSamples = MAX_SAMPLES; + m_nDefaultSpeed = psong->speed; + m_nDefaultTempo = psong->bpm; + m_nDefaultGlobalVolume = psong->globalvol << 2; + if ((!m_nDefaultGlobalVolume) || (m_nDefaultGlobalVolume > 256)) m_nDefaultGlobalVolume = 256; + m_nSongPreAmp = psong->mastervol & 0x7F; + for (UINT iOrd=0; iOrdnumord) ? psong->orders[iOrd] : 0xFF); + } + for (UINT iPan=0; iPan<16; iPan++) + { + ChnSettings[iPan].nPan = 0x80; + if (psong->panpos[iPan] <= 0x80) + { + ChnSettings[iPan].nPan = psong->panpos[iPan] << 1; + } + } + memcpy(m_szNames[0], psong->songname, 28); + nPat = 0; + nSmp = 1; + while (dwMemPos < dwMemLength - 8) + { + DSMPATT *ppatt = (DSMPATT *)(lpStream + dwMemPos); + DSMINST *pins = (DSMINST *)(lpStream+dwMemPos); + // Reading Patterns + if (ppatt->id_PATT == DSMID_PATT) + { + dwMemPos += 8; + if (dwMemPos + ppatt->patt_len >= dwMemLength) break; + DWORD dwPos = dwMemPos; + dwMemPos += ppatt->patt_len; + MODCOMMAND *m = AllocatePattern(64, m_nChannels); + if (!m) break; + PatternSize[nPat] = 64; + Patterns[nPat] = m; + UINT row = 0; + while ((row < 64) && (dwPos + 2 <= dwMemPos)) + { + UINT flag = lpStream[dwPos++]; + if (flag) + { + UINT ch = (flag & 0x0F) % m_nChannels; + if (flag & 0x80) + { + UINT note = lpStream[dwPos++]; + if (note) + { + if (note <= 12*9) note += 12; + m[ch].note = (BYTE)note; + } + } + if (flag & 0x40) + { + m[ch].instr = lpStream[dwPos++]; + } + if (flag & 0x20) + { + m[ch].volcmd = VOLCMD_VOLUME; + m[ch].vol = lpStream[dwPos++]; + } + if (flag & 0x10) + { + UINT command = lpStream[dwPos++]; + UINT param = lpStream[dwPos++]; + switch(command) + { + // 4-bit Panning + case 0x08: + switch(param & 0xF0) + { + case 0x00: param <<= 4; break; + case 0x10: command = 0x0A; param = (param & 0x0F) << 4; break; + case 0x20: command = 0x0E; param = (param & 0x0F) | 0xA0; break; + case 0x30: command = 0x0E; param = (param & 0x0F) | 0x10; break; + case 0x40: command = 0x0E; param = (param & 0x0F) | 0x20; break; + default: command = 0; + } + break; + // Portamentos + case 0x11: + case 0x12: + command &= 0x0F; + break; + // 3D Sound (?) + case 0x13: + command = 'X' - 55; + param = 0x91; + break; + default: + // Volume + Offset (?) + command = ((command & 0xF0) == 0x20) ? 0x09 : 0; + } + m[ch].command = (BYTE)command; + m[ch].param = (BYTE)param; + if (command) ConvertModCommand(&m[ch]); + } + } else + { + m += m_nChannels; + row++; + } + } + nPat++; + } else + // Reading Samples + if ((nSmp <= m_nSamples) && (pins->id_INST == DSMID_INST)) + { + if (dwMemPos + pins->inst_len >= dwMemLength - 8) break; + DWORD dwPos = dwMemPos + sizeof(DSMINST); + dwMemPos += 8 + pins->inst_len; + memcpy(m_szNames[nSmp], pins->samplename, 28); + MODINSTRUMENT *psmp = &Ins[nSmp]; + memcpy(psmp->name, pins->filename, 13); + psmp->nGlobalVol = 64; + psmp->nC4Speed = pins->c2spd; + psmp->uFlags = (WORD)((pins->flags & 1) ? CHN_LOOP : 0); + psmp->nLength = pins->length; + psmp->nLoopStart = pins->loopstart; + psmp->nLoopEnd = pins->loopend; + psmp->nVolume = (WORD)(pins->volume << 2); + if (psmp->nVolume > 256) psmp->nVolume = 256; + UINT smptype = (pins->flags & 2) ? RS_PCM8S : RS_PCM8U; + ReadSample(psmp, smptype, (LPCSTR)(lpStream+dwPos), dwMemLength - dwPos); + nSmp++; + } else + { + break; + } + } + return TRUE; +} + -- cgit v1.2.1