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;