Mercurial > audlegacy
comparison Plugins/Input/modplug/modplugbmp.cpp @ 278:37316876ef6e trunk
[svn] Use modplug instead of mikmod. Supports more formats & compressed files.
| author | chainsaw |
|---|---|
| date | Sat, 10 Dec 2005 14:31:13 -0800 |
| parents | |
| children | 3a2771d4140e |
comparison
equal
deleted
inserted
replaced
| 277:0cf2cc6d0fe5 | 278:37316876ef6e |
|---|---|
| 1 /* Modplug XMMS Plugin | |
| 2 * Authors: Kenton Varda <temporal@gauge3d.org> | |
| 3 * | |
| 4 * This source code is public domain. | |
| 5 */ | |
| 6 | |
| 7 #include <fstream> | |
| 8 #include <unistd.h> | |
| 9 #include <math.h> | |
| 10 | |
| 11 #include "modplugbmp.h" | |
| 12 #include <libmodplug/stdafx.h> | |
| 13 #include <libmodplug/sndfile.h> | |
| 14 #include "stddefs.h" | |
| 15 #include "archive/open.h" | |
| 16 | |
| 17 // ModplugXMMS member functions =============================== | |
| 18 | |
| 19 // operations ---------------------------------------- | |
| 20 ModplugXMMS::ModplugXMMS() | |
| 21 { | |
| 22 mSoundFile = new CSoundFile; | |
| 23 } | |
| 24 ModplugXMMS::~ModplugXMMS() | |
| 25 { | |
| 26 delete mSoundFile; | |
| 27 } | |
| 28 | |
| 29 ModplugXMMS::Settings::Settings() | |
| 30 { | |
| 31 mSurround = true; | |
| 32 mOversamp = true; | |
| 33 mReverb = false; | |
| 34 mMegabass = false; | |
| 35 mNoiseReduction = true; | |
| 36 mVolumeRamp = true; | |
| 37 mFastinfo = true; | |
| 38 mUseFilename = false; | |
| 39 | |
| 40 mChannels = 2; | |
| 41 mFrequency = 44100; | |
| 42 mBits = 16; | |
| 43 mResamplingMode = SRCMODE_POLYPHASE; | |
| 44 | |
| 45 mReverbDepth = 30; | |
| 46 mReverbDelay = 100; | |
| 47 mBassAmount = 40; | |
| 48 mBassRange = 30; | |
| 49 mSurroundDepth = 20; | |
| 50 mSurroundDelay = 20; | |
| 51 | |
| 52 mPreamp = false; | |
| 53 mPreampLevel = 0.0f; | |
| 54 | |
| 55 mLoopCount = 0; //don't loop | |
| 56 } | |
| 57 | |
| 58 void ModplugXMMS::Init(void) | |
| 59 { | |
| 60 fstream lConfigFile; | |
| 61 string lField, lValue; | |
| 62 string lConfigFilename; | |
| 63 bool lValueB; | |
| 64 char junk; | |
| 65 | |
| 66 //I chose to use a separate config file to avoid conflicts | |
| 67 lConfigFilename = g_get_home_dir(); | |
| 68 lConfigFilename += "/.bmp/modplug-bmp.conf"; | |
| 69 lConfigFile.open(lConfigFilename.c_str(), ios::in); | |
| 70 | |
| 71 if(!lConfigFile.is_open()) | |
| 72 return; | |
| 73 | |
| 74 while(!lConfigFile.eof()) | |
| 75 { | |
| 76 lConfigFile >> lField; | |
| 77 if(lField[0] == '#') //allow comments | |
| 78 { | |
| 79 do | |
| 80 { | |
| 81 lConfigFile.read(&junk, 1); | |
| 82 } | |
| 83 while(junk != '\n'); | |
| 84 } | |
| 85 else | |
| 86 { | |
| 87 if(lField == "reverb_depth") | |
| 88 lConfigFile >> mModProps.mReverbDepth; | |
| 89 else if(lField == "reverb_delay") | |
| 90 lConfigFile >> mModProps.mReverbDelay; | |
| 91 else if(lField == "megabass_amount") | |
| 92 lConfigFile >> mModProps.mBassAmount; | |
| 93 else if(lField == "megabass_range") | |
| 94 lConfigFile >> mModProps.mBassRange; | |
| 95 else if(lField == "surround_depth") | |
| 96 lConfigFile >> mModProps.mSurroundDepth; | |
| 97 else if(lField == "surround_delay") | |
| 98 lConfigFile >> mModProps.mSurroundDelay; | |
| 99 else if(lField == "preamp_volume") | |
| 100 lConfigFile >> mModProps.mPreampLevel; | |
| 101 else if(lField == "loop_count") | |
| 102 lConfigFile >> mModProps.mLoopCount; | |
| 103 else | |
| 104 { | |
| 105 lConfigFile >> lValue; | |
| 106 if(lValue == "on") | |
| 107 lValueB = true; | |
| 108 else | |
| 109 lValueB = false; | |
| 110 | |
| 111 if(lField == "surround") | |
| 112 mModProps.mSurround = lValueB; | |
| 113 else if(lField == "oversampling") | |
| 114 mModProps.mOversamp = lValueB; | |
| 115 else if(lField == "reverb") | |
| 116 mModProps.mReverb = lValueB; | |
| 117 else if(lField == "megabass") | |
| 118 mModProps.mMegabass = lValueB; | |
| 119 else if(lField == "noisereduction") | |
| 120 mModProps.mNoiseReduction = lValueB; | |
| 121 else if(lField == "volumeramping") | |
| 122 mModProps.mVolumeRamp = lValueB; | |
| 123 else if(lField == "fastinfo") | |
| 124 mModProps.mFastinfo = lValueB; | |
| 125 else if(lField == "use_filename") | |
| 126 mModProps.mUseFilename = lValueB; | |
| 127 else if(lField == "preamp") | |
| 128 mModProps.mPreamp = lValueB; | |
| 129 | |
| 130 else if(lField == "channels") | |
| 131 { | |
| 132 if(lValue == "mono") | |
| 133 mModProps.mChannels = 1; | |
| 134 else | |
| 135 mModProps.mChannels = 2; | |
| 136 } | |
| 137 else if(lField == "frequency") | |
| 138 { | |
| 139 if(lValue == "22050") | |
| 140 mModProps.mFrequency = 22050; | |
| 141 else if(lValue == "11025") | |
| 142 mModProps.mFrequency = 11025; | |
| 143 else | |
| 144 mModProps.mFrequency = 44100; | |
| 145 } | |
| 146 else if(lField == "bits") | |
| 147 { | |
| 148 if(lValue == "8") | |
| 149 mModProps.mBits = 8; | |
| 150 else | |
| 151 mModProps.mBits = 16; | |
| 152 } | |
| 153 else if(lField == "resampling") | |
| 154 { | |
| 155 if(lValue == "nearest") | |
| 156 mModProps.mResamplingMode = SRCMODE_NEAREST; | |
| 157 else if(lValue == "linear") | |
| 158 mModProps.mResamplingMode = SRCMODE_LINEAR; | |
| 159 else if(lValue == "spline") | |
| 160 mModProps.mResamplingMode = SRCMODE_SPLINE; | |
| 161 else | |
| 162 mModProps.mResamplingMode = SRCMODE_POLYPHASE; | |
| 163 } | |
| 164 } //if(numerical value) else | |
| 165 } //if(comment) else | |
| 166 } //while(!eof) | |
| 167 | |
| 168 lConfigFile.close(); | |
| 169 } | |
| 170 | |
| 171 bool ModplugXMMS::CanPlayFile(const string& aFilename) | |
| 172 { | |
| 173 string lExt; | |
| 174 uint32 lPos; | |
| 175 | |
| 176 lPos = aFilename.find_last_of('.'); | |
| 177 if((int)lPos == -1) | |
| 178 return false; | |
| 179 lExt = aFilename.substr(lPos); | |
| 180 for(uint32 i = 0; i < lExt.length(); i++) | |
| 181 lExt[i] = tolower(lExt[i]); | |
| 182 | |
| 183 if (lExt == ".669") | |
| 184 return true; | |
| 185 if (lExt == ".amf") | |
| 186 return true; | |
| 187 if (lExt == ".ams") | |
| 188 return true; | |
| 189 if (lExt == ".dbm") | |
| 190 return true; | |
| 191 if (lExt == ".dbf") | |
| 192 return true; | |
| 193 if (lExt == ".dsm") | |
| 194 return true; | |
| 195 if (lExt == ".far") | |
| 196 return true; | |
| 197 if (lExt == ".it") | |
| 198 return true; | |
| 199 if (lExt == ".mdl") | |
| 200 return true; | |
| 201 if (lExt == ".med") | |
| 202 return true; | |
| 203 if (lExt == ".mod") | |
| 204 return true; | |
| 205 if (lExt == ".mtm") | |
| 206 return true; | |
| 207 if (lExt == ".okt") | |
| 208 return true; | |
| 209 if (lExt == ".ptm") | |
| 210 return true; | |
| 211 if (lExt == ".s3m") | |
| 212 return true; | |
| 213 if (lExt == ".stm") | |
| 214 return true; | |
| 215 if (lExt == ".ult") | |
| 216 return true; | |
| 217 if (lExt == ".umx") //Unreal rocks! | |
| 218 return true; | |
| 219 if (lExt == ".xm") | |
| 220 return true; | |
| 221 if (lExt == ".j2b") | |
| 222 return true; | |
| 223 if (lExt == ".mt2") | |
| 224 return true; | |
| 225 if (lExt == ".psm") | |
| 226 return true; | |
| 227 | |
| 228 if (lExt == ".mdz") | |
| 229 return true; | |
| 230 if (lExt == ".mdr") | |
| 231 return true; | |
| 232 if (lExt == ".mdgz") | |
| 233 return true; | |
| 234 if (lExt == ".mdbz") | |
| 235 return true; | |
| 236 if (lExt == ".s3z") | |
| 237 return true; | |
| 238 if (lExt == ".s3r") | |
| 239 return true; | |
| 240 if (lExt == ".s3gz") | |
| 241 return true; | |
| 242 if (lExt == ".xmz") | |
| 243 return true; | |
| 244 if (lExt == ".xmr") | |
| 245 return true; | |
| 246 if (lExt == ".xmgz") | |
| 247 return true; | |
| 248 if (lExt == ".itz") | |
| 249 return true; | |
| 250 if (lExt == ".itr") | |
| 251 return true; | |
| 252 if (lExt == ".itgz") | |
| 253 return true; | |
| 254 if (lExt == ".dmf") | |
| 255 return true; | |
| 256 | |
| 257 if (lExt == ".zip") | |
| 258 return ContainsMod(aFilename); | |
| 259 if (lExt == ".rar") | |
| 260 return ContainsMod(aFilename); | |
| 261 if (lExt == ".gz") | |
| 262 return ContainsMod(aFilename); | |
| 263 if (lExt == ".bz2") | |
| 264 return ContainsMod(aFilename); | |
| 265 | |
| 266 return false; | |
| 267 } | |
| 268 | |
| 269 void* ModplugXMMS::PlayThread(void* arg) | |
| 270 { | |
| 271 ((ModplugXMMS*)arg)->PlayLoop(); | |
| 272 return NULL; | |
| 273 } | |
| 274 | |
| 275 void ModplugXMMS::PlayLoop() | |
| 276 { | |
| 277 uint32 lLength; | |
| 278 //the user might change the number of channels while playing. | |
| 279 // we don't want this to take effect until we are done! | |
| 280 uint8 lChannels = mModProps.mChannels; | |
| 281 | |
| 282 while(!mStopped) | |
| 283 { | |
| 284 if(!(lLength = mSoundFile->Read( | |
| 285 mBuffer, | |
| 286 mBufSize))) | |
| 287 { | |
| 288 //no more to play. Wait for output to finish and then stop. | |
| 289 while((mOutPlug->buffer_playing()) | |
| 290 && (!mStopped)) | |
| 291 usleep(10000); | |
| 292 break; | |
| 293 } | |
| 294 | |
| 295 if(mModProps.mPreamp) | |
| 296 { | |
| 297 //apply preamp | |
| 298 if(mModProps.mBits == 16) | |
| 299 { | |
| 300 uint n = mBufSize >> 1; | |
| 301 for(uint i = 0; i < n; i++) { | |
| 302 short old = ((short*)mBuffer)[i]; | |
| 303 ((short*)mBuffer)[i] *= mPreampFactor; | |
| 304 // detect overflow and clip! | |
| 305 if ((old & 0x8000) != | |
| 306 (((short*)mBuffer)[i] & 0x8000)) | |
| 307 ((short*)mBuffer)[i] = old | 0x7FFF; | |
| 308 | |
| 309 } | |
| 310 } | |
| 311 else | |
| 312 { | |
| 313 for(uint i = 0; i < mBufSize; i++) { | |
| 314 uchar old = ((uchar*)mBuffer)[i]; | |
| 315 ((uchar*)mBuffer)[i] *= mPreampFactor; | |
| 316 // detect overflow and clip! | |
| 317 if ((old & 0x80) != | |
| 318 (((uchar*)mBuffer)[i] & 0x80)) | |
| 319 ((uchar*)mBuffer)[i] = old | 0x7F; | |
| 320 } | |
| 321 } | |
| 322 } | |
| 323 | |
| 324 if(mStopped) | |
| 325 break; | |
| 326 | |
| 327 //wait for buffer space to free up. | |
| 328 while(((mOutPlug->buffer_free() | |
| 329 < (int)mBufSize)) | |
| 330 && (!mStopped)) | |
| 331 usleep(10000); | |
| 332 | |
| 333 if(mStopped) | |
| 334 break; | |
| 335 | |
| 336 mOutPlug->write_audio | |
| 337 ( | |
| 338 mBuffer, | |
| 339 mBufSize | |
| 340 ); | |
| 341 mInPlug->add_vis_pcm | |
| 342 ( | |
| 343 mPlayed, | |
| 344 mFormat, | |
| 345 lChannels, | |
| 346 mBufSize, | |
| 347 mBuffer | |
| 348 ); | |
| 349 | |
| 350 mPlayed += mBufTime; | |
| 351 } | |
| 352 | |
| 353 // mOutPlug->flush(0); | |
| 354 mOutPlug->close_audio(); | |
| 355 | |
| 356 //Unload the file | |
| 357 mSoundFile->Destroy(); | |
| 358 delete mArchive; | |
| 359 | |
| 360 if (mBuffer) | |
| 361 { | |
| 362 delete [] mBuffer; | |
| 363 mBuffer = NULL; | |
| 364 } | |
| 365 | |
| 366 mPaused = false; | |
| 367 mStopped = true; | |
| 368 | |
| 369 g_thread_exit(NULL); | |
| 370 } | |
| 371 | |
| 372 void ModplugXMMS::PlayFile(const string& aFilename) | |
| 373 { | |
| 374 mStopped = true; | |
| 375 mPaused = false; | |
| 376 | |
| 377 //open and mmap the file | |
| 378 mArchive = OpenArchive(aFilename); | |
| 379 if(mArchive->Size() == 0) | |
| 380 { | |
| 381 delete mArchive; | |
| 382 return; | |
| 383 } | |
| 384 | |
| 385 if (mBuffer) | |
| 386 delete [] mBuffer; | |
| 387 | |
| 388 //find buftime to get approx. 512 samples/block | |
| 389 mBufTime = 512000 / mModProps.mFrequency + 1; | |
| 390 | |
| 391 mBufSize = mBufTime; | |
| 392 mBufSize *= mModProps.mFrequency; | |
| 393 mBufSize /= 1000; //milliseconds | |
| 394 mBufSize *= mModProps.mChannels; | |
| 395 mBufSize *= mModProps.mBits / 8; | |
| 396 | |
| 397 mBuffer = new uchar[mBufSize]; | |
| 398 if(!mBuffer) | |
| 399 return; //out of memory! | |
| 400 | |
| 401 CSoundFile::SetWaveConfig | |
| 402 ( | |
| 403 mModProps.mFrequency, | |
| 404 mModProps.mBits, | |
| 405 mModProps.mChannels | |
| 406 ); | |
| 407 CSoundFile::SetWaveConfigEx | |
| 408 ( | |
| 409 mModProps.mSurround, | |
| 410 !mModProps.mOversamp, | |
| 411 mModProps.mReverb, | |
| 412 true, | |
| 413 mModProps.mMegabass, | |
| 414 mModProps.mNoiseReduction, | |
| 415 false | |
| 416 ); | |
| 417 | |
| 418 // [Reverb level 0(quiet)-100(loud)], [delay in ms, usually 40-200ms] | |
| 419 if(mModProps.mReverb) | |
| 420 { | |
| 421 CSoundFile::SetReverbParameters | |
| 422 ( | |
| 423 mModProps.mReverbDepth, | |
| 424 mModProps.mReverbDelay | |
| 425 ); | |
| 426 } | |
| 427 // [XBass level 0(quiet)-100(loud)], [cutoff in Hz 10-100] | |
| 428 if(mModProps.mMegabass) | |
| 429 { | |
| 430 CSoundFile::SetXBassParameters | |
| 431 ( | |
| 432 mModProps.mBassAmount, | |
| 433 mModProps.mBassRange | |
| 434 ); | |
| 435 } | |
| 436 // [Surround level 0(quiet)-100(heavy)] [delay in ms, usually 5-40ms] | |
| 437 if(mModProps.mSurround) | |
| 438 { | |
| 439 CSoundFile::SetSurroundParameters | |
| 440 ( | |
| 441 mModProps.mSurroundDepth, | |
| 442 mModProps.mSurroundDelay | |
| 443 ); | |
| 444 } | |
| 445 CSoundFile::SetResamplingMode(mModProps.mResamplingMode); | |
| 446 mSoundFile->SetRepeatCount(mModProps.mLoopCount); | |
| 447 mPreampFactor = exp(mModProps.mPreampLevel); | |
| 448 | |
| 449 mPaused = false; | |
| 450 mStopped = false; | |
| 451 | |
| 452 mSoundFile->Create | |
| 453 ( | |
| 454 (uchar*)mArchive->Map(), | |
| 455 mArchive->Size() | |
| 456 ); | |
| 457 mPlayed = 0; | |
| 458 | |
| 459 bool useFilename = mModProps.mUseFilename; | |
| 460 | |
| 461 if(!useFilename) | |
| 462 { | |
| 463 strncpy(mModName, mSoundFile->GetTitle(), 100); | |
| 464 | |
| 465 for(int i = 0; mModName[i] == ' ' || mModName[i] == 0; i++) | |
| 466 { | |
| 467 if(mModName[i] == 0) | |
| 468 { | |
| 469 useFilename = true; //mod name is blank -- use filename | |
| 470 break; | |
| 471 } | |
| 472 } | |
| 473 } | |
| 474 | |
| 475 if(useFilename) | |
| 476 { | |
| 477 strncpy(mModName, strrchr(aFilename.c_str(), '/') + 1, 100); | |
| 478 char* ext = strrchr(mModName, '.'); | |
| 479 if(ext) *ext = '\0'; | |
| 480 } | |
| 481 | |
| 482 mInPlug->set_info | |
| 483 ( | |
| 484 mModName, | |
| 485 mSoundFile->GetSongTime() * 1000, | |
| 486 mSoundFile->GetNumChannels(), | |
| 487 mModProps.mFrequency / 1000, | |
| 488 mModProps.mChannels | |
| 489 ); | |
| 490 | |
| 491 mStopped = mPaused = false; | |
| 492 | |
| 493 if(mModProps.mBits == 16) | |
| 494 mFormat = FMT_S16_NE; | |
| 495 else | |
| 496 mFormat = FMT_U8; | |
| 497 | |
| 498 mOutPlug->open_audio | |
| 499 ( | |
| 500 mFormat, | |
| 501 mModProps.mFrequency, | |
| 502 mModProps.mChannels | |
| 503 ); | |
| 504 | |
| 505 mDecodeThread = g_thread_create( | |
| 506 (GThreadFunc)PlayThread, | |
| 507 this, | |
| 508 TRUE, | |
| 509 NULL | |
| 510 ); | |
| 511 } | |
| 512 | |
| 513 void ModplugXMMS::Stop(void) | |
| 514 { | |
| 515 if(mStopped) | |
| 516 return; | |
| 517 | |
| 518 mStopped = true; | |
| 519 mPaused = false; | |
| 520 | |
| 521 g_thread_join(mDecodeThread); | |
| 522 } | |
| 523 | |
| 524 void ModplugXMMS::Pause(bool aPaused) | |
| 525 { | |
| 526 if(aPaused) | |
| 527 mPaused = true; | |
| 528 else | |
| 529 mPaused = false; | |
| 530 | |
| 531 mOutPlug->pause(aPaused); | |
| 532 } | |
| 533 | |
| 534 void ModplugXMMS::Seek(float32 aTime) | |
| 535 { | |
| 536 uint32 lMax; | |
| 537 uint32 lMaxtime; | |
| 538 float32 lPostime; | |
| 539 | |
| 540 if(aTime > (lMaxtime = mSoundFile->GetSongTime())) | |
| 541 aTime = lMaxtime; | |
| 542 lMax = mSoundFile->GetMaxPosition(); | |
| 543 lPostime = float(lMax) / lMaxtime; | |
| 544 | |
| 545 mSoundFile->SetCurrentPos(int(aTime * lPostime)); | |
| 546 | |
| 547 mOutPlug->flush(int(aTime * 1000)); | |
| 548 mPlayed = uint32(aTime * 1000); | |
| 549 } | |
| 550 | |
| 551 float32 ModplugXMMS::GetTime(void) | |
| 552 { | |
| 553 if(mStopped) | |
| 554 return -1; | |
| 555 return (float32)mOutPlug->output_time() / 1000; | |
| 556 } | |
| 557 | |
| 558 void ModplugXMMS::GetSongInfo(const string& aFilename, char*& aTitle, int32& aLength) | |
| 559 { | |
| 560 aLength = -1; | |
| 561 fstream lTestFile; | |
| 562 string lError; | |
| 563 bool lDone; | |
| 564 | |
| 565 lTestFile.open(aFilename.c_str(), ios::in); | |
| 566 if(!lTestFile) | |
| 567 { | |
| 568 lError = "**no such file: "; | |
| 569 lError += strrchr(aFilename.c_str(), '/') + 1; | |
| 570 aTitle = new char[lError.length() + 1]; | |
| 571 strcpy(aTitle, lError.c_str()); | |
| 572 return; | |
| 573 } | |
| 574 | |
| 575 lTestFile.close(); | |
| 576 | |
| 577 if(mModProps.mFastinfo) | |
| 578 { | |
| 579 if(mModProps.mUseFilename) | |
| 580 { | |
| 581 //Use filename as name | |
| 582 aTitle = new char[aFilename.length() + 1]; | |
| 583 strcpy(aTitle, strrchr(aFilename.c_str(), '/') + 1); | |
| 584 *strrchr(aTitle, '.') = '\0'; | |
| 585 return; | |
| 586 } | |
| 587 | |
| 588 fstream lModFile; | |
| 589 string lExt; | |
| 590 uint32 lPos; | |
| 591 | |
| 592 lDone = true; | |
| 593 | |
| 594 // previously ios::nocreate was used (X Standard C++ Library) | |
| 595 lModFile.open(aFilename.c_str(), ios::in); | |
| 596 | |
| 597 lPos = aFilename.find_last_of('.'); | |
| 598 if((int)lPos == 0) | |
| 599 return; | |
| 600 lExt = aFilename.substr(lPos); | |
| 601 for(uint32 i = 0; i < lExt.length(); i++) | |
| 602 lExt[i] = tolower(lExt[i]); | |
| 603 | |
| 604 if (lExt == ".mod") | |
| 605 { | |
| 606 lModFile.read(mModName, 20); | |
| 607 mModName[20] = 0; | |
| 608 } | |
| 609 else if (lExt == ".s3m") | |
| 610 { | |
| 611 lModFile.read(mModName, 28); | |
| 612 mModName[28] = 0; | |
| 613 } | |
| 614 else if (lExt == ".xm") | |
| 615 { | |
| 616 lModFile.seekg(17); | |
| 617 lModFile.read(mModName, 20); | |
| 618 mModName[20] = 0; | |
| 619 } | |
| 620 else if (lExt == ".it") | |
| 621 { | |
| 622 lModFile.seekg(4); | |
| 623 lModFile.read(mModName, 28); | |
| 624 mModName[28] = 0; | |
| 625 } | |
| 626 else | |
| 627 lDone = false; //fall back to slow info | |
| 628 | |
| 629 lModFile.close(); | |
| 630 | |
| 631 if(lDone) | |
| 632 { | |
| 633 for(int i = 0; mModName[i] != 0; i++) | |
| 634 { | |
| 635 if(mModName[i] != ' ') | |
| 636 { | |
| 637 aTitle = new char[strlen(mModName) + 1]; | |
| 638 strcpy(aTitle, mModName); | |
| 639 | |
| 640 return; | |
| 641 } | |
| 642 } | |
| 643 | |
| 644 //mod name is blank. Use filename instead. | |
| 645 aTitle = new char[aFilename.length() + 1]; | |
| 646 strcpy(aTitle, strrchr(aFilename.c_str(), '/') + 1); | |
| 647 *strrchr(aTitle, '.') = '\0'; | |
| 648 return; | |
| 649 } | |
| 650 } | |
| 651 | |
| 652 Archive* lArchive; | |
| 653 CSoundFile* lSoundFile; | |
| 654 const char* lTitle; | |
| 655 | |
| 656 //open and mmap the file | |
| 657 lArchive = OpenArchive(aFilename); | |
| 658 if(lArchive->Size() == 0) | |
| 659 { | |
| 660 lError = "**bad mod file: "; | |
| 661 lError += strrchr(aFilename.c_str(), '/') + 1; | |
| 662 aTitle = new char[lError.length() + 1]; | |
| 663 strcpy(aTitle, lError.c_str()); | |
| 664 delete lArchive; | |
| 665 return; | |
| 666 } | |
| 667 | |
| 668 lSoundFile = new CSoundFile; | |
| 669 lSoundFile->Create((uchar*)lArchive->Map(), lArchive->Size()); | |
| 670 | |
| 671 if(!mModProps.mUseFilename) | |
| 672 { | |
| 673 lTitle = lSoundFile->GetTitle(); | |
| 674 | |
| 675 for(int i = 0; lTitle[i] != 0; i++) | |
| 676 { | |
| 677 if(lTitle[i] != ' ') | |
| 678 { | |
| 679 aTitle = new char[strlen(lTitle) + 1]; | |
| 680 strcpy(aTitle, lTitle); | |
| 681 goto therest; //sorry | |
| 682 } | |
| 683 } | |
| 684 } | |
| 685 | |
| 686 //mod name is blank, or user wants the filename to be used as the title. | |
| 687 aTitle = new char[aFilename.length() + 1]; | |
| 688 strcpy(aTitle, strrchr(aFilename.c_str(), '/') + 1); | |
| 689 *strrchr(aTitle, '.') = '\0'; | |
| 690 | |
| 691 therest: | |
| 692 aLength = lSoundFile->GetSongTime() * 1000; //It wants milliseconds!?! | |
| 693 | |
| 694 //unload the file | |
| 695 lSoundFile->Destroy(); | |
| 696 delete lSoundFile; | |
| 697 delete lArchive; | |
| 698 } | |
| 699 | |
| 700 void ModplugXMMS::SetInputPlugin(InputPlugin& aInPlugin) | |
| 701 { | |
| 702 mInPlug = &aInPlugin; | |
| 703 } | |
| 704 void ModplugXMMS::SetOutputPlugin(OutputPlugin& aOutPlugin) | |
| 705 { | |
| 706 mOutPlug = &aOutPlugin; | |
| 707 } | |
| 708 | |
| 709 const ModplugXMMS::Settings& ModplugXMMS::GetModProps() | |
| 710 { | |
| 711 return mModProps; | |
| 712 } | |
| 713 | |
| 714 const char* ModplugXMMS::Bool2OnOff(bool aValue) | |
| 715 { | |
| 716 if(aValue) | |
| 717 return "on"; | |
| 718 else | |
| 719 return "off"; | |
| 720 } | |
| 721 | |
| 722 void ModplugXMMS::SetModProps(const Settings& aModProps) | |
| 723 { | |
| 724 fstream lConfigFile; | |
| 725 string lConfigFilename; | |
| 726 | |
| 727 mModProps = aModProps; | |
| 728 | |
| 729 // [Reverb level 0(quiet)-100(loud)], [delay in ms, usually 40-200ms] | |
| 730 if(mModProps.mReverb) | |
| 731 { | |
| 732 CSoundFile::SetReverbParameters | |
| 733 ( | |
| 734 mModProps.mReverbDepth, | |
| 735 mModProps.mReverbDelay | |
| 736 ); | |
| 737 } | |
| 738 // [XBass level 0(quiet)-100(loud)], [cutoff in Hz 10-100] | |
| 739 if(mModProps.mMegabass) | |
| 740 { | |
| 741 CSoundFile::SetXBassParameters | |
| 742 ( | |
| 743 mModProps.mBassAmount, | |
| 744 mModProps.mBassRange | |
| 745 ); | |
| 746 } | |
| 747 else //modplug seems to ignore the SetWaveConfigEx() setting for bass boost | |
| 748 { | |
| 749 CSoundFile::SetXBassParameters | |
| 750 ( | |
| 751 0, | |
| 752 0 | |
| 753 ); | |
| 754 } | |
| 755 // [Surround level 0(quiet)-100(heavy)] [delay in ms, usually 5-40ms] | |
| 756 if(mModProps.mSurround) | |
| 757 { | |
| 758 CSoundFile::SetSurroundParameters | |
| 759 ( | |
| 760 mModProps.mSurroundDepth, | |
| 761 mModProps.mSurroundDelay | |
| 762 ); | |
| 763 } | |
| 764 CSoundFile::SetWaveConfigEx | |
| 765 ( | |
| 766 mModProps.mSurround, | |
| 767 !mModProps.mOversamp, | |
| 768 mModProps.mReverb, | |
| 769 true, | |
| 770 mModProps.mMegabass, | |
| 771 mModProps.mNoiseReduction, | |
| 772 false | |
| 773 ); | |
| 774 CSoundFile::SetResamplingMode(mModProps.mResamplingMode); | |
| 775 mPreampFactor = exp(mModProps.mPreampLevel); | |
| 776 | |
| 777 lConfigFilename = g_get_home_dir(); | |
| 778 lConfigFilename += "/.bmp/modplug-bmp.conf"; | |
| 779 lConfigFile.open(lConfigFilename.c_str(), ios::out); | |
| 780 | |
| 781 lConfigFile << "# Modplug BMP plugin config file\n" | |
| 782 << "# Modplug (C) 1999 Olivier Lapicque\n" | |
| 783 << "# XMMS port (C) 1999 Kenton Varda\n" | |
| 784 << "# BMP port (C) 2004 Theofilos Intzoglou" << endl; | |
| 785 | |
| 786 lConfigFile << "# ---Effects---" << endl; | |
| 787 lConfigFile << "reverb " << Bool2OnOff(mModProps.mReverb) << endl; | |
| 788 lConfigFile << "reverb_depth " << mModProps.mReverbDepth << endl; | |
| 789 lConfigFile << "reverb_delay " << mModProps.mReverbDelay << endl; | |
| 790 lConfigFile << endl; | |
| 791 lConfigFile << "surround " << Bool2OnOff(mModProps.mSurround) << endl; | |
| 792 lConfigFile << "surround_depth " << mModProps.mSurroundDepth << endl; | |
| 793 lConfigFile << "surround_delay " << mModProps.mSurroundDelay << endl; | |
| 794 lConfigFile << endl; | |
| 795 lConfigFile << "megabass " << Bool2OnOff(mModProps.mMegabass) << endl; | |
| 796 lConfigFile << "megabass_amount " << mModProps.mBassAmount << endl; | |
| 797 lConfigFile << "megabass_range " << mModProps.mBassRange << endl; | |
| 798 lConfigFile << endl; | |
| 799 lConfigFile << "oversampling " << Bool2OnOff(mModProps.mOversamp) << endl; | |
| 800 lConfigFile << "noisereduction " << Bool2OnOff(mModProps.mNoiseReduction) << endl; | |
| 801 lConfigFile << "volumeramping " << Bool2OnOff(mModProps.mVolumeRamp) << endl; | |
| 802 lConfigFile << "fastinfo " << Bool2OnOff(mModProps.mFastinfo) << endl; | |
| 803 lConfigFile << "use_filename " << Bool2OnOff(mModProps.mUseFilename) << endl; | |
| 804 lConfigFile << "loop_count " << mModProps.mLoopCount << endl; | |
| 805 lConfigFile << endl; | |
| 806 lConfigFile << "preamp " << Bool2OnOff(mModProps.mPreamp) << endl; | |
| 807 lConfigFile << "preamp_volume " << mModProps.mPreampLevel << endl; | |
| 808 lConfigFile << endl; | |
| 809 | |
| 810 lConfigFile << "# ---Quality---" << endl; | |
| 811 lConfigFile << "channels "; | |
| 812 if(mModProps.mChannels == 1) | |
| 813 lConfigFile << "mono" << endl; | |
| 814 else | |
| 815 lConfigFile << "stereo" << endl; | |
| 816 lConfigFile << "bits " << (int)mModProps.mBits << endl; | |
| 817 lConfigFile << "frequency " << mModProps.mFrequency << endl; | |
| 818 lConfigFile << "resampling "; | |
| 819 switch(mModProps.mResamplingMode) | |
| 820 { | |
| 821 case SRCMODE_NEAREST: | |
| 822 lConfigFile << "nearest" << endl; | |
| 823 break; | |
| 824 case SRCMODE_LINEAR: | |
| 825 lConfigFile << "linear" << endl; | |
| 826 break; | |
| 827 case SRCMODE_SPLINE: | |
| 828 lConfigFile << "spline" << endl; | |
| 829 break; | |
| 830 default: | |
| 831 case SRCMODE_POLYPHASE: | |
| 832 lConfigFile << "fir" << endl; | |
| 833 break; | |
| 834 }; | |
| 835 | |
| 836 lConfigFile.close(); | |
| 837 } | |
| 838 | |
| 839 ModplugXMMS gModplugXMMS; |
