summaryrefslogtreecommitdiff
path: root/core/multimedia/opieplayer/modplug/load_stm.cpp
authorllornkcor <llornkcor>2002-07-20 22:07:31 (UTC)
committer llornkcor <llornkcor>2002-07-20 22:07:31 (UTC)
commit2342d48be31847e7ead9d1cc682452e8f0122351 (patch) (unidiff)
tree8329bb94e9d429c905a0ef6b881cf1c0f775bf14 /core/multimedia/opieplayer/modplug/load_stm.cpp
parent0f24c1fb86d3bb58d8696358b824c0e01752b10d (diff)
downloadopie-2342d48be31847e7ead9d1cc682452e8f0122351.zip
opie-2342d48be31847e7ead9d1cc682452e8f0122351.tar.gz
opie-2342d48be31847e7ead9d1cc682452e8f0122351.tar.bz2
initial commit of modplugin
Diffstat (limited to 'core/multimedia/opieplayer/modplug/load_stm.cpp') (more/less context) (ignore whitespace changes)
-rw-r--r--core/multimedia/opieplayer/modplug/load_stm.cpp189
1 files changed, 189 insertions, 0 deletions
diff --git a/core/multimedia/opieplayer/modplug/load_stm.cpp b/core/multimedia/opieplayer/modplug/load_stm.cpp
new file mode 100644
index 0000000..3f79c27
--- a/dev/null
+++ b/core/multimedia/opieplayer/modplug/load_stm.cpp
@@ -0,0 +1,189 @@
1/*
2 * This program is free software; you can redistribute it and modify it
3 * under the terms of the GNU General Public License as published by the
4 * Free Software Foundation; either version 2 of the license or (at your
5 * option) any later version.
6 *
7 * Authors: Olivier Lapicque <olivierl@jps.net>
8*/
9
10#include "stdafx.h"
11#include "sndfile.h"
12
13//#pragma warning(disable:4244)
14
15#pragma pack(1)
16
17typedef struct tagSTMNOTE
18{
19 BYTE note;
20 BYTE insvol;
21 BYTE volcmd;
22 BYTE cmdinf;
23} Q_PACKED STMNOTE;
24
25
26// Raw STM sampleinfo struct:
27typedef struct tagSTMSAMPLE
28{
29 CHAR filename[14];// Can't have long comments - just filename comments :)
30 WORD reserved; // ISA in memory when in ST 2
31 WORD length; // Sample length
32 WORD loopbeg; // Loop start point
33 WORD loopend; // Loop end point
34 BYTE volume; // Volume
35 BYTE reserved2; // More reserved crap
36 WORD c2spd; // Good old c2spd
37 BYTE reserved3[6];// Yet more of PSi's reserved crap
38} Q_PACKED STMSAMPLE;
39
40
41// Raw STM header struct:
42typedef struct tagSTMHEADER
43{
44 char songname[20]; // changed from CHAR
45 char trackername[8];// !SCREAM! for ST 2.xx // changed from CHAR
46 CHAR unused; // 0x1A
47 CHAR filetype; // 1=song, 2=module (only 2 is supported, of course) :)
48 CHAR ver_major; // Like 2
49 CHAR ver_minor; // "ditto"
50 BYTE inittempo; // initspeed= stm inittempo>>4
51 BYTE numpat; // number of patterns
52 BYTE globalvol; // <- WoW! a RiGHT TRiANGLE =8*)
53 BYTE reserved[13]; // More of PSi's internal crap
54 STMSAMPLE sample[31];// STM sample data
55 BYTE patorder[128]; // Docs say 64 - actually 128
56} Q_PACKED STMHEADER;
57
58#pragma pack()
59
60
61
62BOOL CSoundFile::ReadSTM(const BYTE *lpStream, DWORD dwMemLength)
63//---------------------------------------------------------------
64{
65 STMHEADER *phdr = (STMHEADER *)lpStream;
66 DWORD dwMemPos = 0;
67
68 if ((!lpStream) || (dwMemLength < sizeof(STMHEADER))) return FALSE;
69 if ((phdr->filetype != 2) || (phdr->unused != 0x1A)
70 || ((strnicmp(phdr->trackername, "!SCREAM!", 8))
71 && (strnicmp(phdr->trackername, "BMOD2STM", 8)))) return FALSE;
72 memcpy(m_szNames[0], phdr->songname, 20);
73 // Read STM header
74 m_nType = MOD_TYPE_STM;
75 m_nSamples = 31;
76 m_nChannels = 4;
77 m_nInstruments = 0;
78 m_nMinPeriod = 64;
79 m_nMaxPeriod = 0x7FFF;
80 m_nDefaultSpeed = phdr->inittempo >> 4;
81 if (m_nDefaultSpeed < 1) m_nDefaultSpeed = 1;
82 m_nDefaultTempo = 125;
83 m_nDefaultGlobalVolume = phdr->globalvol << 2;
84 if (m_nDefaultGlobalVolume > 256) m_nDefaultGlobalVolume = 256;
85 memcpy(Order, phdr->patorder, 128);
86 // Setting up channels
87 for (UINT nSet=0; nSet<4; nSet++)
88 {
89 ChnSettings[nSet].dwFlags = 0;
90 ChnSettings[nSet].nVolume = 64;
91 ChnSettings[nSet].nPan = (nSet & 1) ? 0x40 : 0xC0;
92 }
93 // Reading samples
94 for (UINT nIns=0; nIns<31; nIns++)
95 {
96 MODINSTRUMENT *pIns = &Ins[nIns+1];
97 STMSAMPLE *pStm = &phdr->sample[nIns]; // STM sample data
98 memcpy(pIns->name, pStm->filename, 13);
99 memcpy(m_szNames[nIns+1], pStm->filename, 12);
100 pIns->nC4Speed = pStm->c2spd;
101 pIns->nGlobalVol = 64;
102 pIns->nVolume = pStm->volume << 2;
103 if (pIns->nVolume > 256) pIns->nVolume = 256;
104 pIns->nLength = pStm->length;
105 if ((pIns->nLength < 4) || (!pIns->nVolume)) pIns->nLength = 0;
106 pIns->nLoopStart = pStm->loopbeg;
107 pIns->nLoopEnd = pStm->loopend;
108 if ((pIns->nLoopEnd > pIns->nLoopStart) && (pIns->nLoopEnd != 0xFFFF)) pIns->uFlags |= CHN_LOOP;
109 }
110 dwMemPos = sizeof(STMHEADER);
111 for (UINT nOrd=0; nOrd<MAX_ORDERS; nOrd++) if (Order[nOrd] >= 99) Order[nOrd] = 0xFF;
112 UINT nPatterns = phdr->numpat;
113 for (UINT nPat=0; nPat<nPatterns; nPat++)
114 {
115 if (dwMemPos + 64*4*4 > dwMemLength) return TRUE;
116 PatternSize[nPat] = 64;
117 if ((Patterns[nPat] = AllocatePattern(64, m_nChannels)) == NULL) return TRUE;
118 MODCOMMAND *m = Patterns[nPat];
119 STMNOTE *p = (STMNOTE *)(lpStream + dwMemPos);
120 for (UINT n=0; n<64*4; n++, p++, m++)
121 {
122 UINT note,ins,vol,cmd;
123 // extract the various information from the 4 bytes that
124 // make up a single note
125 note = p->note;
126 ins = p->insvol >> 3;
127 vol = (p->insvol & 0x07) + (p->volcmd >> 1);
128 cmd = p->volcmd & 0x0F;
129 if ((ins) && (ins < 32)) m->instr = ins;
130 // special values of [SBYTE0] are handled here ->
131 // we have no idea if these strange values will ever be encountered
132 // but it appears as though stms sound correct.
133 if ((note == 0xFE) || (note == 0xFC)) m->note = 0xFE; else
134 // if note < 251, then all three bytes are stored in the file
135 if (note < 0xFC) m->note = (note >> 4)*12 + (note&0xf) + 37;
136 if (vol <= 64) { m->volcmd = VOLCMD_VOLUME; m->vol = vol; }
137 m->param = p->cmdinf;
138 switch(cmd)
139 {
140 // Axx set speed to xx
141 case 1:m->command = CMD_SPEED; m->param >>= 4; break;
142 // Bxx position jump
143 case 2:m->command = CMD_POSITIONJUMP; break;
144 // Cxx patternbreak to row xx
145 case 3: m->command = CMD_PATTERNBREAK; m->param = (m->param & 0xF0) * 10 + (m->param & 0x0F);break;
146 // Dxy volumeslide
147 case 4:m->command = CMD_VOLUMESLIDE; break;
148 // Exy toneslide down
149 case 5:m->command = CMD_PORTAMENTODOWN; break;
150 // Fxy toneslide up
151 case 6:m->command = CMD_PORTAMENTOUP; break;
152 // Gxx Tone portamento,speed xx
153 case 7:m->command = CMD_TONEPORTAMENTO; break;
154 // Hxy vibrato
155 case 8:m->command = CMD_VIBRATO; break;
156 // Ixy tremor, ontime x, offtime y
157 case 9:m->command = CMD_TREMOR; break;
158 // Jxy arpeggio
159 case 10: m->command = CMD_ARPEGGIO; break;
160 // Kxy Dual command H00 & Dxy
161 case 11: m->command = CMD_VIBRATOVOL; break;
162 // Lxy Dual command G00 & Dxy
163 case 12: m->command = CMD_TONEPORTAVOL; break;
164 // Xxx amiga command 8xx
165 case 0x18:m->command = CMD_PANNING8; break;
166 default:
167 m->command = m->param = 0;
168 }
169 }
170 dwMemPos += 64*4*4;
171 }
172 // Reading Samples
173 for (UINT nSmp=1; nSmp<=31; nSmp++)
174 {
175 MODINSTRUMENT *pIns = &Ins[nSmp];
176 dwMemPos = (dwMemPos + 15) & (~15);
177 if (pIns->nLength)
178 {
179 UINT nPos = ((UINT)phdr->sample[nSmp-1].reserved) << 4;
180 if ((nPos >= sizeof(STMHEADER)) && (nPos+pIns->nLength <= dwMemLength)) dwMemPos = nPos;
181 if (dwMemPos < dwMemLength)
182 {
183 dwMemPos += ReadSample(pIns, RS_PCM8S, (LPSTR)(lpStream+dwMemPos),dwMemLength-dwMemPos);
184 }
185 }
186 }
187 return TRUE;
188}
189