Mercurial > audlegacy
annotate Plugins/Input/adplug/core/ksm.cpp @ 919:c19c3ea7d29d trunk
[svn] - fading fix
| author | nenolod |
|---|---|
| date | Thu, 06 Apr 2006 11:03:26 -0700 |
| parents | ddb6e5dac908 |
| children | 6ad7eb96dd26 |
| rev | line source |
|---|---|
| 359 | 1 /* |
| 2 * Adplug - Replayer for many OPL2/OPL3 audio file formats. | |
| 3 * Copyright (C) 1999 - 2003 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 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()); | |
| 792 | 53 delete [] fn; |
| 359 | 54 return false; |
| 55 } | |
| 56 AdPlug_LogWrite("*** CksmPlayer::load(,\"%s\") ***\n", filename.c_str()); | |
| 57 | |
| 58 // Load instruments from 'insts.dat' | |
| 59 strcpy(fn, filename.c_str()); | |
| 60 for(i = strlen(fn) - 1; i >= 0; i--) | |
| 61 if(fn[i] == '/' || fn[i] == '\\') | |
| 62 break; | |
| 63 strcpy(fn + i + 1, "insts.dat"); | |
| 64 AdPlug_LogWrite("Instruments file: \"%s\"\n", fn); | |
| 65 f = fp.open(fn); | |
| 66 delete [] fn; | |
| 67 if(!f) { | |
| 68 AdPlug_LogWrite("Couldn't open instruments file! Aborting!\n"); | |
| 69 AdPlug_LogWrite("--- CksmPlayer::load ---\n"); | |
| 70 return false; | |
| 71 } | |
| 72 loadinsts(f); | |
| 73 fp.close(f); | |
| 74 | |
| 75 f = fp.open(filename); if(!f) return false; | |
| 76 for(i = 0; i < 16; i++) trinst[i] = f->readInt(1); | |
| 77 for(i = 0; i < 16; i++) trquant[i] = f->readInt(1); | |
| 78 for(i = 0; i < 16; i++) trchan[i] = f->readInt(1); | |
| 79 f->ignore(16); | |
| 80 for(i = 0; i < 16; i++) trvol[i] = f->readInt(1); | |
| 81 numnotes = f->readInt(2); | |
| 82 note = new unsigned long [numnotes]; | |
| 83 for(i = 0; i < numnotes; i++) note[i] = f->readInt(4); | |
| 84 fp.close(f); | |
| 85 | |
| 86 if(!trchan[11]) { | |
| 87 drumstat = 0; | |
| 88 numchans = 9; | |
| 89 } else { | |
| 90 drumstat = 32; | |
| 91 numchans = 6; | |
| 92 } | |
| 93 | |
| 94 rewind(0); | |
| 95 AdPlug_LogWrite("--- CksmPlayer::load ---\n"); | |
| 96 return true; | |
| 97 } | |
| 98 | |
| 99 bool CksmPlayer::update() | |
| 100 { | |
|
637
2b06eb5e472d
[svn] Sync with upstream. Drop hardware OPL2/3 support, it throws warnings and is not used on most modern machines. Added var inits where GCC 4.0 thought it was a good idea.
chainsaw
parents:
359
diff
changeset
|
101 int quanter,chan=0,drumnum=0,freq,track,volevel,volval; |
| 359 | 102 unsigned int i,j,bufnum; |
| 103 unsigned long temp,templong; | |
| 104 | |
| 105 count++; | |
| 106 if (count >= countstop) | |
| 107 { | |
| 108 bufnum = 0; | |
| 109 while (count >= countstop) | |
| 110 { | |
| 111 templong = note[nownote]; | |
| 112 track = (int)((templong>>8)&15); | |
| 113 if ((templong&192) == 0) | |
| 114 { | |
| 115 i = 0; | |
| 116 while (((chanfreq[i] != (templong&63)) || (chantrack[i] != ((templong>>8)&15))) && (i < numchans)) | |
| 117 i++; | |
| 118 if (i < numchans) | |
| 119 { | |
| 120 databuf[bufnum] = (char)0; bufnum++; | |
| 121 databuf[bufnum] = (unsigned char)(0xb0+i); bufnum++; | |
| 122 databuf[bufnum] = (unsigned char)((adlibfreq[templong&63]>>8)&223); bufnum++; | |
| 123 chanfreq[i] = 0; | |
| 124 chanage[i] = 0; | |
| 125 } | |
| 126 } | |
| 127 else | |
| 128 { | |
| 129 volevel = trvol[track]; | |
| 130 if ((templong&192) == 128) | |
| 131 { | |
| 132 volevel -= 4; | |
| 133 if (volevel < 0) | |
| 134 volevel = 0; | |
| 135 } | |
| 136 if ((templong&192) == 192) | |
| 137 { | |
| 138 volevel += 4; | |
| 139 if (volevel > 63) | |
| 140 volevel = 63; | |
| 141 } | |
| 142 if (track < 11) | |
| 143 { | |
| 144 temp = 0; | |
| 145 i = numchans; | |
| 146 for(j=0;j<numchans;j++) | |
| 147 if ((countstop - chanage[j] >= temp) && (chantrack[j] == track)) | |
| 148 { | |
| 149 temp = countstop - chanage[j]; | |
| 150 i = j; | |
| 151 } | |
| 152 if (i < numchans) | |
| 153 { | |
| 154 databuf[bufnum] = (char)0, bufnum++; | |
| 155 databuf[bufnum] = (unsigned char)(0xb0+i); bufnum++; | |
| 156 databuf[bufnum] = (unsigned char)0; bufnum++; | |
| 157 volval = (inst[trinst[track]][1]&192)+(volevel^63); | |
| 158 databuf[bufnum] = (char)0, bufnum++; | |
| 159 databuf[bufnum] = (unsigned char)(0x40+op_table[i]+3); bufnum++; | |
| 160 databuf[bufnum] = (unsigned char)volval; bufnum++; | |
| 161 databuf[bufnum] = (char)0, bufnum++; | |
| 162 databuf[bufnum] = (unsigned char)(0xa0+i); bufnum++; | |
| 163 databuf[bufnum] = (unsigned char)(adlibfreq[templong&63]&255); bufnum++; | |
| 164 databuf[bufnum] = (char)0, bufnum++; | |
| 165 databuf[bufnum] = (unsigned char)(0xb0+i); bufnum++; | |
| 166 databuf[bufnum] = (unsigned char)((adlibfreq[templong&63]>>8)|32); bufnum++; | |
| 167 chanfreq[i] = templong&63; | |
| 168 chanage[i] = countstop; | |
| 169 } | |
| 170 } | |
| 171 else if ((drumstat&32) > 0) | |
| 172 { | |
| 173 freq = adlibfreq[templong&63]; | |
| 174 switch(track) | |
| 175 { | |
| 176 case 11: drumnum = 16; chan = 6; freq -= 2048; break; | |
| 177 case 12: drumnum = 8; chan = 7; freq -= 2048; break; | |
| 178 case 13: drumnum = 4; chan = 8; break; | |
| 179 case 14: drumnum = 2; chan = 8; break; | |
| 180 case 15: drumnum = 1; chan = 7; freq -= 2048; break; | |
| 181 } | |
| 182 databuf[bufnum] = (char)0, bufnum++; | |
| 183 databuf[bufnum] = (unsigned char)(0xa0+chan); bufnum++; | |
| 184 databuf[bufnum] = (unsigned char)(freq&255); bufnum++; | |
| 185 databuf[bufnum] = (char)0, bufnum++; | |
| 186 databuf[bufnum] = (unsigned char)(0xb0+chan); bufnum++; | |
| 187 databuf[bufnum] = (unsigned char)((freq>>8)&223); bufnum++; | |
| 188 databuf[bufnum] = (char)0, bufnum++; | |
| 189 databuf[bufnum] = (unsigned char)(0xbd); bufnum++; | |
| 190 databuf[bufnum] = (unsigned char)(drumstat&(255-drumnum)); bufnum++; | |
| 191 drumstat |= drumnum; | |
| 192 if ((track == 11) || (track == 12) || (track == 14)) | |
| 193 { | |
| 194 volval = (inst[trinst[track]][1]&192)+(volevel^63); | |
| 195 databuf[bufnum] = (char)0, bufnum++; | |
| 196 databuf[bufnum] = (unsigned char)(0x40+op_table[chan]+3); bufnum++; | |
| 197 databuf[bufnum] = (unsigned char)(volval); bufnum++; | |
| 198 } | |
| 199 else | |
| 200 { | |
| 201 volval = (inst[trinst[track]][6]&192)+(volevel^63); | |
| 202 databuf[bufnum] = (char)0, bufnum++; | |
| 203 databuf[bufnum] = (unsigned char)(0x40+op_table[chan]); bufnum++; | |
| 204 databuf[bufnum] = (unsigned char)(volval); bufnum++; | |
| 205 } | |
| 206 databuf[bufnum] = (char)0, bufnum++; | |
| 207 databuf[bufnum] = (unsigned char)(0xbd); bufnum++; | |
| 208 databuf[bufnum] = (unsigned char)(drumstat); bufnum++; | |
| 209 } | |
| 210 } | |
| 211 nownote++; | |
| 212 if (nownote >= numnotes) { | |
| 213 nownote = 0; | |
| 214 songend = true; | |
| 215 } | |
| 216 templong = note[nownote]; | |
| 217 if (nownote == 0) | |
| 218 count = (templong>>12)-1; | |
| 219 quanter = (240/trquant[(templong>>8)&15]); | |
| 220 countstop = (((templong>>12)+(quanter>>1)) / quanter) * quanter; | |
| 221 } | |
| 222 for(i=0;i<bufnum;i+=3) | |
| 223 opl->write(databuf[i+1],databuf[i+2]); | |
| 224 } | |
| 225 return !songend; | |
| 226 } | |
| 227 | |
| 228 void CksmPlayer::rewind(int subsong) | |
| 229 { | |
| 230 unsigned int i,j,k; | |
| 231 unsigned char instbuf[11]; | |
| 232 unsigned long templong; | |
| 233 | |
| 234 songend = false; | |
| 235 opl->init(); opl->write(1,32); opl->write(4,0); opl->write(8,0); opl->write(0xbd,drumstat); | |
| 236 | |
| 237 if (trchan[11] == 1) { | |
| 238 for(i=0;i<11;i++) | |
| 239 instbuf[i] = inst[trinst[11]][i]; | |
| 240 instbuf[1] = ((instbuf[1]&192)|(trvol[11])^63); | |
| 241 setinst(6,instbuf[0],instbuf[1],instbuf[2],instbuf[3],instbuf[4],instbuf[5],instbuf[6],instbuf[7],instbuf[8],instbuf[9],instbuf[10]); | |
| 242 for(i=0;i<5;i++) | |
| 243 instbuf[i] = inst[trinst[12]][i]; | |
| 244 for(i=5;i<11;i++) | |
| 245 instbuf[i] = inst[trinst[15]][i]; | |
| 246 instbuf[1] = ((instbuf[1]&192)|(trvol[12])^63); | |
| 247 instbuf[6] = ((instbuf[6]&192)|(trvol[15])^63); | |
| 248 setinst(7,instbuf[0],instbuf[1],instbuf[2],instbuf[3],instbuf[4],instbuf[5],instbuf[6],instbuf[7],instbuf[8],instbuf[9],instbuf[10]); | |
| 249 for(i=0;i<5;i++) | |
| 250 instbuf[i] = inst[trinst[14]][i]; | |
| 251 for(i=5;i<11;i++) | |
| 252 instbuf[i] = inst[trinst[13]][i]; | |
| 253 instbuf[1] = ((instbuf[1]&192)|(trvol[14])^63); | |
| 254 instbuf[6] = ((instbuf[6]&192)|(trvol[13])^63); | |
| 255 setinst(8,instbuf[0],instbuf[1],instbuf[2],instbuf[3],instbuf[4],instbuf[5],instbuf[6],instbuf[7],instbuf[8],instbuf[9],instbuf[10]); | |
| 256 } | |
| 257 | |
| 258 for(i=0;i<numchans;i++) | |
| 259 { | |
| 260 chantrack[i] = 0; | |
| 261 chanage[i] = 0; | |
| 262 } | |
| 263 j = 0; | |
| 264 for(i=0;i<16;i++) | |
| 265 if ((trchan[i] > 0) && (j < numchans)) | |
| 266 { | |
| 267 k = trchan[i]; | |
| 268 while ((j < numchans) && (k > 0)) | |
| 269 { | |
| 270 chantrack[j] = i; | |
| 271 k--; | |
| 272 j++; | |
| 273 } | |
| 274 } | |
| 275 for(i=0;i<numchans;i++) | |
| 276 { | |
| 277 for(j=0;j<11;j++) | |
| 278 instbuf[j] = inst[trinst[chantrack[i]]][j]; | |
| 279 instbuf[1] = ((instbuf[1]&192)|(63-trvol[chantrack[i]])); | |
| 280 setinst(i,instbuf[0],instbuf[1],instbuf[2],instbuf[3],instbuf[4],instbuf[5],instbuf[6],instbuf[7],instbuf[8],instbuf[9],instbuf[10]); | |
| 281 chanfreq[i] = 0; | |
| 282 } | |
| 283 k = 0; | |
| 284 templong = *note; | |
| 285 count = (templong>>12)-1; | |
| 286 countstop = (templong>>12)-1; | |
| 287 nownote = 0; | |
| 288 } | |
| 289 | |
| 290 std::string CksmPlayer::getinstrument(unsigned int n) | |
| 291 { | |
| 292 if(trchan[n]) | |
| 293 return std::string(instname[trinst[n]]); | |
| 294 else | |
| 295 return std::string(); | |
| 296 } | |
| 297 | |
| 298 /*** private methods *************************************/ | |
| 299 | |
| 300 void CksmPlayer::loadinsts(binistream *f) | |
| 301 { | |
| 302 int i, j; | |
| 303 | |
| 304 for(i = 0; i < 256; i++) { | |
| 305 f->readString(instname[i], 20); | |
| 306 for(j = 0; j < 11; j++) inst[i][j] = f->readInt(1); | |
| 307 f->ignore(2); | |
| 308 } | |
| 309 } | |
| 310 | |
| 311 void CksmPlayer::setinst(int chan, | |
| 312 unsigned char v0,unsigned char v1,unsigned char v2, | |
| 313 unsigned char v3,unsigned char v4,unsigned char v5, | |
| 314 unsigned char v6,unsigned char v7,unsigned char v8, | |
| 315 unsigned char v9,unsigned char v10) | |
| 316 { | |
| 317 int offs; | |
| 318 | |
| 319 opl->write(0xa0+chan,0); | |
| 320 opl->write(0xb0+chan,0); | |
| 321 opl->write(0xc0+chan,v10); | |
| 322 offs = op_table[chan]; | |
| 323 opl->write(0x20+offs,v5); | |
| 324 opl->write(0x40+offs,v6); | |
| 325 opl->write(0x60+offs,v7); | |
| 326 opl->write(0x80+offs,v8); | |
| 327 opl->write(0xe0+offs,v9); | |
| 328 offs+=3; | |
| 329 opl->write(0x20+offs,v0); | |
| 330 opl->write(0x40+offs,v1); | |
| 331 opl->write(0x60+offs,v2); | |
| 332 opl->write(0x80+offs,v3); | |
| 333 opl->write(0xe0+offs,v4); | |
| 334 } |
