From 2342d48be31847e7ead9d1cc682452e8f0122351 Mon Sep 17 00:00:00 2001 From: llornkcor Date: Sat, 20 Jul 2002 22:07:31 +0000 Subject: initial commit of modplugin --- (limited to 'core/multimedia/opieplayer/modplug/load_dbm.cpp') diff --git a/core/multimedia/opieplayer/modplug/load_dbm.cpp b/core/multimedia/opieplayer/modplug/load_dbm.cpp new file mode 100644 index 0000000..258fd88 --- a/dev/null +++ b/core/multimedia/opieplayer/modplug/load_dbm.cpp @@ -0,0 +1,371 @@ +/* + * This program is free software; you can redistribute it and modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the license or (at your + * option) any later version. + * + * Authors: Olivier Lapicque , + * Adam Goode (endian and char fixes for PPC) +*/ + +/////////////////////////////////////////////////////////////// +// +// DigiBooster Pro Module Loader (*.dbm) +// +// Note: this loader doesn't handle multiple songs +// +/////////////////////////////////////////////////////////////// + +#include "stdafx.h" +#include "sndfile.h" + +//#pragma warning(disable:4244) + +#define DBM_FILE_MAGIC 0x304d4244 +#define DBM_ID_NAME 0x454d414e +#define DBM_NAMELEN 0x2c000000 +#define DBM_ID_INFO 0x4f464e49 +#define DBM_INFOLEN 0x0a000000 +#define DBM_ID_SONG 0x474e4f53 +#define DBM_ID_INST 0x54534e49 +#define DBM_ID_VENV 0x564e4556 +#define DBM_ID_PATT 0x54544150 +#define DBM_ID_SMPL 0x4c504d53 + +#pragma pack(1) + +typedef struct DBMFILEHEADER +{ + DWORD dbm_id; // "DBM0" = 0x304d4244 + WORD trkver; // Tracker version: 02.15 + WORD reserved; + DWORD name_id; // "NAME" = 0x454d414e + DWORD name_len; // name length: always 44 + CHAR songname[44]; + DWORD info_id; // "INFO" = 0x4f464e49 + DWORD info_len; // 0x0a000000 + WORD instruments; + WORD samples; + WORD songs; + WORD patterns; + WORD channels; + DWORD song_id; // "SONG" = 0x474e4f53 + DWORD song_len; + CHAR songname2[44]; + WORD orders; +// WORD orderlist[0]; // orderlist[orders] in words +} Q_PACKED DBMFILEHEADER; + +typedef struct DBMINSTRUMENT +{ + CHAR name[30]; + WORD sampleno; + WORD volume; + DWORD finetune; + DWORD loopstart; + DWORD looplen; + WORD panning; + WORD flags; +} Q_PACKED DBMINSTRUMENT; + +typedef struct DBMENVELOPE +{ + WORD instrument; + BYTE flags; + BYTE numpoints; + BYTE sustain1; + BYTE loopbegin; + BYTE loopend; + BYTE sustain2; + WORD volenv[2*32]; +} Q_PACKED DBMENVELOPE; + +typedef struct DBMPATTERN +{ + WORD rows; + DWORD packedsize; + BYTE patterndata[2]; // [packedsize] +} Q_PACKED DBMPATTERN; + +typedef struct DBMSAMPLE +{ + DWORD flags; + DWORD samplesize; + BYTE sampledata[2]; // [samplesize] +} Q_PACKED DBMSAMPLE; + +#pragma pack() + + +BOOL CSoundFile::ReadDBM(const BYTE *lpStream, DWORD dwMemLength) +//--------------------------------------------------------------- +{ + DBMFILEHEADER *pfh = (DBMFILEHEADER *)lpStream; + DWORD dwMemPos; + UINT nOrders, nSamples, nInstruments, nPatterns; + + if ((!lpStream) || (dwMemLength <= sizeof(DBMFILEHEADER)) || (!pfh->channels) + || (pfh->dbm_id != DBM_FILE_MAGIC) || (!pfh->songs) || (pfh->song_id != DBM_ID_SONG) + || (pfh->name_id != DBM_ID_NAME) || (pfh->name_len != DBM_NAMELEN) + || (pfh->info_id != DBM_ID_INFO) || (pfh->info_len != DBM_INFOLEN)) return FALSE; + dwMemPos = sizeof(DBMFILEHEADER); + nOrders = bswapBE16(pfh->orders); + if (dwMemPos + 2 * nOrders + 8*3 >= dwMemLength) return FALSE; + nInstruments = bswapBE16(pfh->instruments); + nSamples = bswapBE16(pfh->samples); + nPatterns = bswapBE16(pfh->patterns); + m_nType = MOD_TYPE_DBM; + m_nChannels = bswapBE16(pfh->channels); + if (m_nChannels < 4) m_nChannels = 4; + if (m_nChannels > 64) m_nChannels = 64; + memcpy(m_szNames[0], (pfh->songname[0]) ? pfh->songname : pfh->songname2, 32); + m_szNames[0][31] = 0; + for (UINT iOrd=0; iOrd < nOrders; iOrd++) + { + Order[iOrd] = lpStream[dwMemPos+iOrd*2+1]; + if (iOrd >= MAX_ORDERS-2) break; + } + dwMemPos += 2*nOrders; + while (dwMemPos + 10 < dwMemLength) + { + DWORD chunk_id = ((LPDWORD)(lpStream+dwMemPos))[0]; + DWORD chunk_size = bswapBE32(((LPDWORD)(lpStream+dwMemPos))[1]); + DWORD chunk_pos; + + dwMemPos += 8; + chunk_pos = dwMemPos; + if ((dwMemPos + chunk_size > dwMemLength) || (chunk_size > dwMemLength)) break; + dwMemPos += chunk_size; + // Instruments + if (chunk_id == DBM_ID_INST) + { + if (nInstruments >= MAX_INSTRUMENTS) nInstruments = MAX_INSTRUMENTS-1; + for (UINT iIns=0; iIns dwMemPos) break; + if ((penv = new INSTRUMENTHEADER) == NULL) break; + pih = (DBMINSTRUMENT *)(lpStream+chunk_pos); + nsmp = bswapBE16(pih->sampleno); + psmp = ((nsmp) && (nsmp < MAX_SAMPLES)) ? &Ins[nsmp] : NULL; + memset(penv, 0, sizeof(INSTRUMENTHEADER)); + memcpy(penv->name, pih->name, 30); + if (psmp) + { + memcpy(m_szNames[nsmp], pih->name, 30); + m_szNames[nsmp][30] = 0; + } + Headers[iIns+1] = penv; + penv->nFadeOut = 1024; // ??? + penv->nGlobalVol = 64; + penv->nPan = bswapBE16(pih->panning); + if ((penv->nPan) && (penv->nPan < 256)) + penv->dwFlags = ENV_SETPANNING; + else + penv->nPan = 128; + penv->nPPC = 5*12; + for (UINT i=0; i<120; i++) + { + penv->Keyboard[i] = nsmp; + penv->NoteMap[i] = i+1; + } + // Sample Info + if (psmp) + { + DWORD sflags = bswapBE16(pih->flags); + psmp->nVolume = bswapBE16(pih->volume) * 4; + if ((!psmp->nVolume) || (psmp->nVolume > 256)) psmp->nVolume = 256; + psmp->nGlobalVol = 64; + psmp->nC4Speed = bswapBE32(pih->finetune); + int f2t = FrequencyToTranspose(psmp->nC4Speed); + psmp->RelativeTone = f2t >> 7; + psmp->nFineTune = f2t & 0x7F; + if ((pih->looplen) && (sflags & 3)) + { + psmp->nLoopStart = bswapBE32(pih->loopstart); + psmp->nLoopEnd = psmp->nLoopStart + bswapBE32(pih->looplen); + psmp->uFlags |= CHN_LOOP; + psmp->uFlags &= ~CHN_PINGPONGLOOP; + if (sflags & 2) psmp->uFlags |= CHN_PINGPONGLOOP; + } + } + chunk_pos += sizeof(DBMINSTRUMENT); + m_nInstruments = iIns+1; + } + } else + // Volume Envelopes + if (chunk_id == DBM_ID_VENV) + { + UINT nEnvelopes = lpStream[chunk_pos+1]; + + chunk_pos += 2; + for (UINT iEnv=0; iEnv dwMemPos) break; + peh = (DBMENVELOPE *)(lpStream+chunk_pos); + nins = bswapBE16(peh->instrument); + if ((nins) && (nins < MAX_INSTRUMENTS) && (Headers[nins]) && (peh->numpoints)) + { + INSTRUMENTHEADER *penv = Headers[nins]; + + if (peh->flags & 1) penv->dwFlags |= ENV_VOLUME; + if (peh->flags & 2) penv->dwFlags |= ENV_VOLSUSTAIN; + if (peh->flags & 4) penv->dwFlags |= ENV_VOLLOOP; + penv->nVolEnv = peh->numpoints + 1; + if (penv->nVolEnv > MAX_ENVPOINTS) penv->nVolEnv = MAX_ENVPOINTS; + penv->nVolLoopStart = peh->loopbegin; + penv->nVolLoopEnd = peh->loopend; + penv->nVolSustainBegin = penv->nVolSustainEnd = peh->sustain1; + for (UINT i=0; inVolEnv; i++) + { + penv->VolPoints[i] = bswapBE16(peh->volenv[i*2]); + penv->VolEnv[i] = (BYTE)bswapBE16(peh->volenv[i*2+1]); + } + } + chunk_pos += sizeof(DBMENVELOPE); + } + } else + // Packed Pattern Data + if (chunk_id == DBM_ID_PATT) + { + if (nPatterns > MAX_PATTERNS) nPatterns = MAX_PATTERNS; + for (UINT iPat=0; iPat dwMemPos) break; + pph = (DBMPATTERN *)(lpStream+chunk_pos); + pksize = bswapBE32(pph->packedsize); + if ((chunk_pos + pksize + 6 > dwMemPos) || (pksize > dwMemPos)) break; + nRows = bswapBE16(pph->rows); + if ((nRows >= 4) && (nRows <= 256)) + { + MODCOMMAND *m = AllocatePattern(nRows, m_nChannels); + if (m) + { + LPBYTE pkdata = (LPBYTE)&pph->patterndata; + UINT row = 0; + UINT i = 0; + + PatternSize[iPat] = nRows; + Patterns[iPat] = m; + while ((i+3> 4)*12) + (note & 0x0F) + 13; + } + m[ch].note = note; + } + if (b & 0x02) m[ch].instr = pkdata[i++]; + if (b & 0x3C) + { + UINT cmd1 = 0xFF, param1 = 0, cmd2 = 0xFF, param2 = 0; + if (b & 0x04) cmd1 = (UINT)pkdata[i++]; + if (b & 0x08) param1 = pkdata[i++]; + if (b & 0x10) cmd2 = (UINT)pkdata[i++]; + if (b & 0x20) param2 = pkdata[i++]; + if (cmd1 == 0x0C) + { + m[ch].volcmd = VOLCMD_VOLUME; + m[ch].vol = param1; + cmd1 = 0xFF; + } else + if (cmd2 == 0x0C) + { + m[ch].volcmd = VOLCMD_VOLUME; + m[ch].vol = param2; + cmd2 = 0xFF; + } + if ((cmd1 > 0x13) || ((cmd1 >= 0x10) && (cmd2 < 0x10))) + { + cmd1 = cmd2; + param1 = param2; + cmd2 = 0xFF; + } + if (cmd1 <= 0x13) + { + m[ch].command = cmd1; + m[ch].param = param1; + ConvertModCommand(&m[ch]); + } + } + } else + { + if (b & 0x01) i++; + if (b & 0x02) i++; + if (b & 0x04) i++; + if (b & 0x08) i++; + if (b & 0x10) i++; + if (b & 0x20) i++; + } + } else + { + row++; + m += m_nChannels; + } + } + } + } + chunk_pos += 6 + pksize; + } + } else + // Reading Sample Data + if (chunk_id == DBM_ID_SMPL) + { + if (nSamples >= MAX_SAMPLES) nSamples = MAX_SAMPLES-1; + m_nSamples = nSamples; + for (UINT iSmp=1; iSmp<=nSamples; iSmp++) + { + MODINSTRUMENT *pins; + DBMSAMPLE *psh; + DWORD samplesize; + DWORD sampleflags; + + if (chunk_pos + sizeof(DBMSAMPLE) >= dwMemPos) break; + psh = (DBMSAMPLE *)(lpStream+chunk_pos); + chunk_pos += 8; + samplesize = bswapBE32(psh->samplesize); + sampleflags = bswapBE32(psh->flags); + pins = &Ins[iSmp]; + pins->nLength = samplesize; + if (sampleflags & 2) + { + pins->uFlags |= CHN_16BIT; + samplesize <<= 1; + } + if ((chunk_pos+samplesize > dwMemPos) || (samplesize > dwMemLength)) break; + if (sampleflags & 3) + { + ReadSample(pins, (pins->uFlags & CHN_16BIT) ? RS_PCM16M : RS_PCM8S, + (LPSTR)(psh->sampledata), samplesize); + } + chunk_pos += samplesize; + } + } + } + return TRUE; +} + -- cgit v0.9.0.2