00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00012
00013
00014
00015
00016
00018
00019 #include "stdafx.h"
00020 #include "sndfile.h"
00021
00022
00023
00024 #define DBM_FILE_MAGIC 0x304d4244
00025 #define DBM_ID_NAME 0x454d414e
00026 #define DBM_NAMELEN 0x2c000000
00027 #define DBM_ID_INFO 0x4f464e49
00028 #define DBM_INFOLEN 0x0a000000
00029 #define DBM_ID_SONG 0x474e4f53
00030 #define DBM_ID_INST 0x54534e49
00031 #define DBM_ID_VENV 0x564e4556
00032 #define DBM_ID_PATT 0x54544150
00033 #define DBM_ID_SMPL 0x4c504d53
00034
00035 #pragma pack(1)
00036
00037 typedef struct DBMFILEHEADER
00038 {
00039 DWORD dbm_id;
00040 WORD trkver;
00041 WORD reserved;
00042 DWORD name_id;
00043 DWORD name_len;
00044 CHAR songname[44];
00045 DWORD info_id;
00046 DWORD info_len;
00047 WORD instruments;
00048 WORD samples;
00049 WORD songs;
00050 WORD patterns;
00051 WORD channels;
00052 DWORD song_id;
00053 DWORD song_len;
00054 CHAR songname2[44];
00055 WORD orders;
00056
00057 } Q_PACKED DBMFILEHEADER;
00058
00059 typedef struct DBMINSTRUMENT
00060 {
00061 CHAR name[30];
00062 WORD sampleno;
00063 WORD volume;
00064 DWORD finetune;
00065 DWORD loopstart;
00066 DWORD looplen;
00067 WORD panning;
00068 WORD flags;
00069 } Q_PACKED DBMINSTRUMENT;
00070
00071 typedef struct DBMENVELOPE
00072 {
00073 WORD instrument;
00074 BYTE flags;
00075 BYTE numpoints;
00076 BYTE sustain1;
00077 BYTE loopbegin;
00078 BYTE loopend;
00079 BYTE sustain2;
00080 WORD volenv[2*32];
00081 } Q_PACKED DBMENVELOPE;
00082
00083 typedef struct DBMPATTERN
00084 {
00085 WORD rows;
00086 DWORD packedsize;
00087 BYTE patterndata[2];
00088 } Q_PACKED DBMPATTERN;
00089
00090 typedef struct DBMSAMPLE
00091 {
00092 DWORD flags;
00093 DWORD samplesize;
00094 BYTE sampledata[2];
00095 } Q_PACKED DBMSAMPLE;
00096
00097 #pragma pack()
00098
00099
00100 BOOL CSoundFile::ReadDBM(const BYTE *lpStream, DWORD dwMemLength)
00101
00102 {
00103 DBMFILEHEADER *pfh = (DBMFILEHEADER *)lpStream;
00104 DWORD dwMemPos;
00105 UINT nOrders, nSamples, nInstruments, nPatterns;
00106
00107 if ((!lpStream) || (dwMemLength <= sizeof(DBMFILEHEADER)) || (!pfh->channels)
00108 || (pfh->dbm_id != DBM_FILE_MAGIC) || (!pfh->songs) || (pfh->song_id != DBM_ID_SONG)
00109 || (pfh->name_id != DBM_ID_NAME) || (pfh->name_len != DBM_NAMELEN)
00110 || (pfh->info_id != DBM_ID_INFO) || (pfh->info_len != DBM_INFOLEN)) return FALSE;
00111 dwMemPos = sizeof(DBMFILEHEADER);
00112 nOrders = bswapBE16(pfh->orders);
00113 if (dwMemPos + 2 * nOrders + 8*3 >= dwMemLength) return FALSE;
00114 nInstruments = bswapBE16(pfh->instruments);
00115 nSamples = bswapBE16(pfh->samples);
00116 nPatterns = bswapBE16(pfh->patterns);
00117 m_nType = MOD_TYPE_DBM;
00118 m_nChannels = bswapBE16(pfh->channels);
00119 if (m_nChannels < 4) m_nChannels = 4;
00120 if (m_nChannels > 64) m_nChannels = 64;
00121 memcpy(m_szNames[0], (pfh->songname[0]) ? pfh->songname : pfh->songname2, 32);
00122 m_szNames[0][31] = 0;
00123 for (UINT iOrd=0; iOrd < nOrders; iOrd++)
00124 {
00125 Order[iOrd] = lpStream[dwMemPos+iOrd*2+1];
00126 if (iOrd >= MAX_ORDERS-2) break;
00127 }
00128 dwMemPos += 2*nOrders;
00129 while (dwMemPos + 10 < dwMemLength)
00130 {
00131 DWORD chunk_id = ((LPDWORD)(lpStream+dwMemPos))[0];
00132 DWORD chunk_size = bswapBE32(((LPDWORD)(lpStream+dwMemPos))[1]);
00133 DWORD chunk_pos;
00134
00135 dwMemPos += 8;
00136 chunk_pos = dwMemPos;
00137 if ((dwMemPos + chunk_size > dwMemLength) || (chunk_size > dwMemLength)) break;
00138 dwMemPos += chunk_size;
00139
00140 if (chunk_id == DBM_ID_INST)
00141 {
00142 if (nInstruments >= MAX_INSTRUMENTS) nInstruments = MAX_INSTRUMENTS-1;
00143 for (UINT iIns=0; iIns<nInstruments; iIns++)
00144 {
00145 MODINSTRUMENT *psmp;
00146 INSTRUMENTHEADER *penv;
00147 DBMINSTRUMENT *pih;
00148 UINT nsmp;
00149
00150 if (chunk_pos + sizeof(DBMINSTRUMENT) > dwMemPos) break;
00151 if ((penv = new INSTRUMENTHEADER) == NULL) break;
00152 pih = (DBMINSTRUMENT *)(lpStream+chunk_pos);
00153 nsmp = bswapBE16(pih->sampleno);
00154 psmp = ((nsmp) && (nsmp < MAX_SAMPLES)) ? &Ins[nsmp] : NULL;
00155 memset(penv, 0, sizeof(INSTRUMENTHEADER));
00156 memcpy(penv->name, pih->name, 30);
00157 if (psmp)
00158 {
00159 memcpy(m_szNames[nsmp], pih->name, 30);
00160 m_szNames[nsmp][30] = 0;
00161 }
00162 Headers[iIns+1] = penv;
00163 penv->nFadeOut = 1024;
00164 penv->nGlobalVol = 64;
00165 penv->nPan = bswapBE16(pih->panning);
00166 if ((penv->nPan) && (penv->nPan < 256))
00167 penv->dwFlags = ENV_SETPANNING;
00168 else
00169 penv->nPan = 128;
00170 penv->nPPC = 5*12;
00171 for (UINT i=0; i<120; i++)
00172 {
00173 penv->Keyboard[i] = nsmp;
00174 penv->NoteMap[i] = i+1;
00175 }
00176
00177 if (psmp)
00178 {
00179 DWORD sflags = bswapBE16(pih->flags);
00180 psmp->nVolume = bswapBE16(pih->volume) * 4;
00181 if ((!psmp->nVolume) || (psmp->nVolume > 256)) psmp->nVolume = 256;
00182 psmp->nGlobalVol = 64;
00183 psmp->nC4Speed = bswapBE32(pih->finetune);
00184 int f2t = FrequencyToTranspose(psmp->nC4Speed);
00185 psmp->RelativeTone = f2t >> 7;
00186 psmp->nFineTune = f2t & 0x7F;
00187 if ((pih->looplen) && (sflags & 3))
00188 {
00189 psmp->nLoopStart = bswapBE32(pih->loopstart);
00190 psmp->nLoopEnd = psmp->nLoopStart + bswapBE32(pih->looplen);
00191 psmp->uFlags |= CHN_LOOP;
00192 psmp->uFlags &= ~CHN_PINGPONGLOOP;
00193 if (sflags & 2) psmp->uFlags |= CHN_PINGPONGLOOP;
00194 }
00195 }
00196 chunk_pos += sizeof(DBMINSTRUMENT);
00197 m_nInstruments = iIns+1;
00198 }
00199 } else
00200
00201 if (chunk_id == DBM_ID_VENV)
00202 {
00203 UINT nEnvelopes = lpStream[chunk_pos+1];
00204
00205 chunk_pos += 2;
00206 for (UINT iEnv=0; iEnv<nEnvelopes; iEnv++)
00207 {
00208 DBMENVELOPE *peh;
00209 UINT nins;
00210
00211 if (chunk_pos + sizeof(DBMENVELOPE) > dwMemPos) break;
00212 peh = (DBMENVELOPE *)(lpStream+chunk_pos);
00213 nins = bswapBE16(peh->instrument);
00214 if ((nins) && (nins < MAX_INSTRUMENTS) && (Headers[nins]) && (peh->numpoints))
00215 {
00216 INSTRUMENTHEADER *penv = Headers[nins];
00217
00218 if (peh->flags & 1) penv->dwFlags |= ENV_VOLUME;
00219 if (peh->flags & 2) penv->dwFlags |= ENV_VOLSUSTAIN;
00220 if (peh->flags & 4) penv->dwFlags |= ENV_VOLLOOP;
00221 penv->nVolEnv = peh->numpoints + 1;
00222 if (penv->nVolEnv > MAX_ENVPOINTS) penv->nVolEnv = MAX_ENVPOINTS;
00223 penv->nVolLoopStart = peh->loopbegin;
00224 penv->nVolLoopEnd = peh->loopend;
00225 penv->nVolSustainBegin = penv->nVolSustainEnd = peh->sustain1;
00226 for (UINT i=0; i<penv->nVolEnv; i++)
00227 {
00228 penv->VolPoints[i] = bswapBE16(peh->volenv[i*2]);
00229 penv->VolEnv[i] = (BYTE)bswapBE16(peh->volenv[i*2+1]);
00230 }
00231 }
00232 chunk_pos += sizeof(DBMENVELOPE);
00233 }
00234 } else
00235
00236 if (chunk_id == DBM_ID_PATT)
00237 {
00238 if (nPatterns > MAX_PATTERNS) nPatterns = MAX_PATTERNS;
00239 for (UINT iPat=0; iPat<nPatterns; iPat++)
00240 {
00241 DBMPATTERN *pph;
00242 DWORD pksize;
00243 UINT nRows;
00244
00245 if (chunk_pos + sizeof(DBMPATTERN) > dwMemPos) break;
00246 pph = (DBMPATTERN *)(lpStream+chunk_pos);
00247 pksize = bswapBE32(pph->packedsize);
00248 if ((chunk_pos + pksize + 6 > dwMemPos) || (pksize > dwMemPos)) break;
00249 nRows = bswapBE16(pph->rows);
00250 if ((nRows >= 4) && (nRows <= 256))
00251 {
00252 MODCOMMAND *m = AllocatePattern(nRows, m_nChannels);
00253 if (m)
00254 {
00255 LPBYTE pkdata = (LPBYTE)&pph->patterndata;
00256 UINT row = 0;
00257 UINT i = 0;
00258
00259 PatternSize[iPat] = nRows;
00260 Patterns[iPat] = m;
00261 while ((i+3<pksize) && (row < nRows))
00262 {
00263 UINT ch = pkdata[i++];
00264
00265 if (ch)
00266 {
00267 BYTE b = pkdata[i++];
00268 ch--;
00269 if (ch < m_nChannels)
00270 {
00271 if (b & 0x01)
00272 {
00273 UINT note = pkdata[i++];
00274
00275 if (note == 0x1F) note = 0xFF; else
00276 if ((note) && (note < 0xFE))
00277 {
00278 note = ((note >> 4)*12) + (note & 0x0F) + 13;
00279 }
00280 m[ch].note = note;
00281 }
00282 if (b & 0x02) m[ch].instr = pkdata[i++];
00283 if (b & 0x3C)
00284 {
00285 UINT cmd1 = 0xFF, param1 = 0, cmd2 = 0xFF, param2 = 0;
00286 if (b & 0x04) cmd1 = (UINT)pkdata[i++];
00287 if (b & 0x08) param1 = pkdata[i++];
00288 if (b & 0x10) cmd2 = (UINT)pkdata[i++];
00289 if (b & 0x20) param2 = pkdata[i++];
00290 if (cmd1 == 0x0C)
00291 {
00292 m[ch].volcmd = VOLCMD_VOLUME;
00293 m[ch].vol = param1;
00294 cmd1 = 0xFF;
00295 } else
00296 if (cmd2 == 0x0C)
00297 {
00298 m[ch].volcmd = VOLCMD_VOLUME;
00299 m[ch].vol = param2;
00300 cmd2 = 0xFF;
00301 }
00302 if ((cmd1 > 0x13) || ((cmd1 >= 0x10) && (cmd2 < 0x10)))
00303 {
00304 cmd1 = cmd2;
00305 param1 = param2;
00306 cmd2 = 0xFF;
00307 }
00308 if (cmd1 <= 0x13)
00309 {
00310 m[ch].command = cmd1;
00311 m[ch].param = param1;
00312 ConvertModCommand(&m[ch]);
00313 }
00314 }
00315 } else
00316 {
00317 if (b & 0x01) i++;
00318 if (b & 0x02) i++;
00319 if (b & 0x04) i++;
00320 if (b & 0x08) i++;
00321 if (b & 0x10) i++;
00322 if (b & 0x20) i++;
00323 }
00324 } else
00325 {
00326 row++;
00327 m += m_nChannels;
00328 }
00329 }
00330 }
00331 }
00332 chunk_pos += 6 + pksize;
00333 }
00334 } else
00335
00336 if (chunk_id == DBM_ID_SMPL)
00337 {
00338 if (nSamples >= MAX_SAMPLES) nSamples = MAX_SAMPLES-1;
00339 m_nSamples = nSamples;
00340 for (UINT iSmp=1; iSmp<=nSamples; iSmp++)
00341 {
00342 MODINSTRUMENT *pins;
00343 DBMSAMPLE *psh;
00344 DWORD samplesize;
00345 DWORD sampleflags;
00346
00347 if (chunk_pos + sizeof(DBMSAMPLE) >= dwMemPos) break;
00348 psh = (DBMSAMPLE *)(lpStream+chunk_pos);
00349 chunk_pos += 8;
00350 samplesize = bswapBE32(psh->samplesize);
00351 sampleflags = bswapBE32(psh->flags);
00352 pins = &Ins[iSmp];
00353 pins->nLength = samplesize;
00354 if (sampleflags & 2)
00355 {
00356 pins->uFlags |= CHN_16BIT;
00357 samplesize <<= 1;
00358 }
00359 if ((chunk_pos+samplesize > dwMemPos) || (samplesize > dwMemLength)) break;
00360 if (sampleflags & 3)
00361 {
00362 ReadSample(pins, (pins->uFlags & CHN_16BIT) ? RS_PCM16M : RS_PCM8S,
00363 (LPSTR)(psh->sampledata), samplesize);
00364 }
00365 chunk_pos += samplesize;
00366 }
00367 }
00368 }
00369 return TRUE;
00370 }
00371