comparison src/adplug/core/ksm.cxx @ 12:3da1b8942b8b trunk

[svn] - remove src/Input src/Output src/Effect src/General src/Visualization src/Container
author nenolod
date Mon, 18 Sep 2006 03:14:20 -0700
parents src/Input/adplug/core/ksm.cxx@13389e613d67
children cae46214b8bf
comparison
equal deleted inserted replaced
11:cff1d04026ae 12:3da1b8942b8b
1 /*
2 * Adplug - Replayer for many OPL2/OPL3 audio file formats.
3 * Copyright (C) 1999 - 2006 Simon Peter, <dn.tlp@gmx.net>, et al.
4 *
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
9 *
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
14 *
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18 *
19 * ksm.cpp - KSM Player for AdPlug by Simon Peter <dn.tlp@gmx.net>
20 */
21
22 #include <string.h>
23
24 #include "ksm.h"
25 #include "debug.h"
26
27 const unsigned int CksmPlayer::adlibfreq[63] = {
28 0,
29 2390,2411,2434,2456,2480,2506,2533,2562,2592,2625,2659,2695,
30 3414,3435,3458,3480,3504,3530,3557,3586,3616,3649,3683,3719,
31 4438,4459,4482,4504,4528,4554,4581,4610,4640,4673,4707,4743,
32 5462,5483,5506,5528,5552,5578,5605,5634,5664,5697,5731,5767,
33 6486,6507,6530,6552,6576,6602,6629,6658,6688,6721,6755,6791,
34 7510};
35
36 /*** public methods **************************************/
37
38 CPlayer *CksmPlayer::factory(Copl *newopl)
39 {
40 return new CksmPlayer(newopl);
41 }
42
43 bool CksmPlayer::load(const std::string &filename, const CFileProvider &fp)
44 {
45 binistream *f;
46 int i;
47 char *fn = new char[filename.length() + 9];
48
49 // file validation section
50 if(!fp.extension(filename, ".ksm")) {
51 AdPlug_LogWrite("CksmPlayer::load(,\"%s\"): File doesn't have '.ksm' "
52 "extension! Rejected!\n", filename.c_str());
53 return false;
54 }
55 AdPlug_LogWrite("*** CksmPlayer::load(,\"%s\") ***\n", filename.c_str());
56
57 // Load instruments from 'insts.dat'
58 strcpy(fn, filename.c_str());
59 for(i = strlen(fn) - 1; i >= 0; i--)
60 if(fn[i] == '/' || fn[i] == '\\')
61 break;
62 strcpy(fn + i + 1, "insts.dat");
63 AdPlug_LogWrite("Instruments file: \"%s\"\n", fn);
64 f = fp.open(fn);
65 delete [] fn;
66 if(!f) {
67 AdPlug_LogWrite("Couldn't open instruments file! Aborting!\n");
68 AdPlug_LogWrite("--- CksmPlayer::load ---\n");
69 return false;
70 }
71 loadinsts(f);
72 fp.close(f);
73
74 f = fp.open(filename); if(!f) return false;
75 for(i = 0; i < 16; i++) trinst[i] = f->readInt(1);
76 for(i = 0; i < 16; i++) trquant[i] = f->readInt(1);
77 for(i = 0; i < 16; i++) trchan[i] = f->readInt(1);
78 f->ignore(16);
79 for(i = 0; i < 16; i++) trvol[i] = f->readInt(1);
80 numnotes = f->readInt(2);
81 note = new unsigned long [numnotes];
82 for(i = 0; i < numnotes; i++) note[i] = f->readInt(4);
83 fp.close(f);
84
85 if(!trchan[11]) {
86 drumstat = 0;
87 numchans = 9;
88 } else {
89 drumstat = 32;
90 numchans = 6;
91 }
92
93 rewind(0);
94 AdPlug_LogWrite("--- CksmPlayer::load ---\n");
95 return true;
96 }
97
98 bool CksmPlayer::update()
99 {
100 int quanter,chan,drumnum,freq,track,volevel,volval;
101 unsigned int i,j,bufnum;
102 unsigned long temp,templong;
103
104 count++;
105 if (count >= countstop)
106 {
107 bufnum = 0;
108 while (count >= countstop)
109 {
110 templong = note[nownote];
111 track = (int)((templong>>8)&15);
112 if ((templong&192) == 0)
113 {
114 i = 0;
115
116 while ((i < numchans) &&
117 ((chanfreq[i] != (templong&63)) ||
118 (chantrack[i] != ((templong>>8)&15))))
119 i++;
120 if (i < numchans)
121 {
122 databuf[bufnum] = (char)0; bufnum++;
123 databuf[bufnum] = (unsigned char)(0xb0+i); bufnum++;
124 databuf[bufnum] = (unsigned char)((adlibfreq[templong&63]>>8)&223); bufnum++;
125 chanfreq[i] = 0;
126 chanage[i] = 0;
127 }
128 }
129 else
130 {
131 volevel = trvol[track];
132 if ((templong&192) == 128)
133 {
134 volevel -= 4;
135 if (volevel < 0)
136 volevel = 0;
137 }
138 if ((templong&192) == 192)
139 {
140 volevel += 4;
141 if (volevel > 63)
142 volevel = 63;
143 }
144 if (track < 11)
145 {
146 temp = 0;
147 i = numchans;
148 for(j=0;j<numchans;j++)
149 if ((countstop - chanage[j] >= temp) && (chantrack[j] == track))
150 {
151 temp = countstop - chanage[j];
152 i = j;
153 }
154 if (i < numchans)
155 {
156 databuf[bufnum] = (char)0, bufnum++;
157 databuf[bufnum] = (unsigned char)(0xb0+i); bufnum++;
158 databuf[bufnum] = (unsigned char)0; bufnum++;
159 volval = (inst[trinst[track]][1]&192)+(volevel^63);
160 databuf[bufnum] = (char)0, bufnum++;
161 databuf[bufnum] = (unsigned char)(0x40+op_table[i]+3); bufnum++;
162 databuf[bufnum] = (unsigned char)volval; bufnum++;
163 databuf[bufnum] = (char)0, bufnum++;
164 databuf[bufnum] = (unsigned char)(0xa0+i); bufnum++;
165 databuf[bufnum] = (unsigned char)(adlibfreq[templong&63]&255); bufnum++;
166 databuf[bufnum] = (char)0, bufnum++;
167 databuf[bufnum] = (unsigned char)(0xb0+i); bufnum++;
168 databuf[bufnum] = (unsigned char)((adlibfreq[templong&63]>>8)|32); bufnum++;
169 chanfreq[i] = templong&63;
170 chanage[i] = countstop;
171 }
172 }
173 else if ((drumstat&32) > 0)
174 {
175 freq = adlibfreq[templong&63];
176 switch(track)
177 {
178 case 11: drumnum = 16; chan = 6; freq -= 2048; break;
179 case 12: drumnum = 8; chan = 7; freq -= 2048; break;
180 case 13: drumnum = 4; chan = 8; break;
181 case 14: drumnum = 2; chan = 8; break;
182 case 15: drumnum = 1; chan = 7; freq -= 2048; break;
183 }
184 databuf[bufnum] = (char)0, bufnum++;
185 databuf[bufnum] = (unsigned char)(0xa0+chan); bufnum++;
186 databuf[bufnum] = (unsigned char)(freq&255); bufnum++;
187 databuf[bufnum] = (char)0, bufnum++;
188 databuf[bufnum] = (unsigned char)(0xb0+chan); bufnum++;
189 databuf[bufnum] = (unsigned char)((freq>>8)&223); bufnum++;
190 databuf[bufnum] = (char)0, bufnum++;
191 databuf[bufnum] = (unsigned char)(0xbd); bufnum++;
192 databuf[bufnum] = (unsigned char)(drumstat&(255-drumnum)); bufnum++;
193 drumstat |= drumnum;
194 if ((track == 11) || (track == 12) || (track == 14))
195 {
196 volval = (inst[trinst[track]][1]&192)+(volevel^63);
197 databuf[bufnum] = (char)0, bufnum++;
198 databuf[bufnum] = (unsigned char)(0x40+op_table[chan]+3); bufnum++;
199 databuf[bufnum] = (unsigned char)(volval); bufnum++;
200 }
201 else
202 {
203 volval = (inst[trinst[track]][6]&192)+(volevel^63);
204 databuf[bufnum] = (char)0, bufnum++;
205 databuf[bufnum] = (unsigned char)(0x40+op_table[chan]); bufnum++;
206 databuf[bufnum] = (unsigned char)(volval); bufnum++;
207 }
208 databuf[bufnum] = (char)0, bufnum++;
209 databuf[bufnum] = (unsigned char)(0xbd); bufnum++;
210 databuf[bufnum] = (unsigned char)(drumstat); bufnum++;
211 }
212 }
213 nownote++;
214 if (nownote >= numnotes) {
215 nownote = 0;
216 songend = true;
217 }
218 templong = note[nownote];
219 if (nownote == 0)
220 count = (templong>>12)-1;
221 quanter = (240/trquant[(templong>>8)&15]);
222 countstop = (((templong>>12)+(quanter>>1)) / quanter) * quanter;
223 }
224 for(i=0;i<bufnum;i+=3)
225 opl->write(databuf[i+1],databuf[i+2]);
226 }
227 return !songend;
228 }
229
230 void CksmPlayer::rewind(int subsong)
231 {
232 unsigned int i,j,k;
233 unsigned char instbuf[11];
234 unsigned long templong;
235
236 songend = false;
237 opl->init(); opl->write(1,32); opl->write(4,0); opl->write(8,0); opl->write(0xbd,drumstat);
238
239 if (trchan[11] == 1) {
240 for(i=0;i<11;i++)
241 instbuf[i] = inst[trinst[11]][i];
242 instbuf[1] = ((instbuf[1]&192)|(trvol[11])^63);
243 setinst(6,instbuf[0],instbuf[1],instbuf[2],instbuf[3],instbuf[4],instbuf[5],instbuf[6],instbuf[7],instbuf[8],instbuf[9],instbuf[10]);
244 for(i=0;i<5;i++)
245 instbuf[i] = inst[trinst[12]][i];
246 for(i=5;i<11;i++)
247 instbuf[i] = inst[trinst[15]][i];
248 instbuf[1] = ((instbuf[1]&192)|(trvol[12])^63);
249 instbuf[6] = ((instbuf[6]&192)|(trvol[15])^63);
250 setinst(7,instbuf[0],instbuf[1],instbuf[2],instbuf[3],instbuf[4],instbuf[5],instbuf[6],instbuf[7],instbuf[8],instbuf[9],instbuf[10]);
251 for(i=0;i<5;i++)
252 instbuf[i] = inst[trinst[14]][i];
253 for(i=5;i<11;i++)
254 instbuf[i] = inst[trinst[13]][i];
255 instbuf[1] = ((instbuf[1]&192)|(trvol[14])^63);
256 instbuf[6] = ((instbuf[6]&192)|(trvol[13])^63);
257 setinst(8,instbuf[0],instbuf[1],instbuf[2],instbuf[3],instbuf[4],instbuf[5],instbuf[6],instbuf[7],instbuf[8],instbuf[9],instbuf[10]);
258 }
259
260 for(i=0;i<numchans;i++)
261 {
262 chantrack[i] = 0;
263 chanage[i] = 0;
264 }
265 j = 0;
266 for(i=0;i<16;i++)
267 if ((trchan[i] > 0) && (j < numchans))
268 {
269 k = trchan[i];
270 while ((j < numchans) && (k > 0))
271 {
272 chantrack[j] = i;
273 k--;
274 j++;
275 }
276 }
277 for(i=0;i<numchans;i++)
278 {
279 for(j=0;j<11;j++)
280 instbuf[j] = inst[trinst[chantrack[i]]][j];
281 instbuf[1] = ((instbuf[1]&192)|(63-trvol[chantrack[i]]));
282 setinst(i,instbuf[0],instbuf[1],instbuf[2],instbuf[3],instbuf[4],instbuf[5],instbuf[6],instbuf[7],instbuf[8],instbuf[9],instbuf[10]);
283 chanfreq[i] = 0;
284 }
285 k = 0;
286 templong = *note;
287 count = (templong>>12)-1;
288 countstop = (templong>>12)-1;
289 nownote = 0;
290 }
291
292 std::string CksmPlayer::getinstrument(unsigned int n)
293 {
294 if(trchan[n])
295 return std::string(instname[trinst[n]]);
296 else
297 return std::string();
298 }
299
300 /*** private methods *************************************/
301
302 void CksmPlayer::loadinsts(binistream *f)
303 {
304 int i, j;
305
306 for(i = 0; i < 256; i++) {
307 f->readString(instname[i], 20);
308 for(j = 0; j < 11; j++) inst[i][j] = f->readInt(1);
309 f->ignore(2);
310 }
311 }
312
313 void CksmPlayer::setinst(int chan,
314 unsigned char v0,unsigned char v1,unsigned char v2,
315 unsigned char v3,unsigned char v4,unsigned char v5,
316 unsigned char v6,unsigned char v7,unsigned char v8,
317 unsigned char v9,unsigned char v10)
318 {
319 int offs;
320
321 opl->write(0xa0+chan,0);
322 opl->write(0xb0+chan,0);
323 opl->write(0xc0+chan,v10);
324 offs = op_table[chan];
325 opl->write(0x20+offs,v5);
326 opl->write(0x40+offs,v6);
327 opl->write(0x60+offs,v7);
328 opl->write(0x80+offs,v8);
329 opl->write(0xe0+offs,v9);
330 offs+=3;
331 opl->write(0x20+offs,v0);
332 opl->write(0x40+offs,v1);
333 opl->write(0x60+offs,v2);
334 opl->write(0x80+offs,v3);
335 opl->write(0xe0+offs,v4);
336 }