diff src/Input/modplug/modplugbmp.cxx @ 0:13389e613d67 trunk

[svn] - initial import of audacious-plugins tree (lots to do)
author nenolod
date Mon, 18 Sep 2006 01:11:49 -0700
parents
children 088092a52fea
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/Input/modplug/modplugbmp.cxx	Mon Sep 18 01:11:49 2006 -0700
@@ -0,0 +1,800 @@
+/* Modplug XMMS Plugin
+ * Authors: Kenton Varda <temporal@gauge3d.org>
+ *
+ * This source code is public domain.
+ */
+
+#include <fstream>
+#include <unistd.h>
+#include <math.h>
+
+#include "modplugbmp.h"
+#include <libmodplug/stdafx.h>
+#include <libmodplug/sndfile.h>
+#include "stddefs.h"
+#include "archive/open.h"
+#include "libaudacious/configdb.h"
+#include "libaudacious/vfs.h"
+extern "C" {
+#include "audacious/output.h"
+}
+
+// ModplugXMMS member functions ===============================
+
+// operations ----------------------------------------
+ModplugXMMS::ModplugXMMS()
+{
+	mSoundFile = new CSoundFile;
+}
+ModplugXMMS::~ModplugXMMS()
+{
+	delete mSoundFile;
+}
+
+ModplugXMMS::Settings::Settings()
+{
+	mSurround       = true;
+	mOversamp       = true;
+	mReverb         = false;
+	mMegabass       = false;
+	mNoiseReduction = true;
+	mVolumeRamp     = true;
+	mFastinfo       = true;
+	mUseFilename    = false;
+	mGrabAmigaMOD   = true;
+
+	mChannels       = 2;
+	mFrequency      = 44100;
+	mBits           = 16;
+	mResamplingMode = SRCMODE_POLYPHASE;
+
+	mReverbDepth    = 30;
+	mReverbDelay    = 100;
+	mBassAmount     = 40;
+	mBassRange      = 30;
+	mSurroundDepth  = 20;
+	mSurroundDelay  = 20;
+	
+	mPreamp         = false;
+	mPreampLevel    = 0.0f;
+	
+	mLoopCount      = 0;   //don't loop
+}
+
+void ModplugXMMS::Init(void)
+{
+	ConfigDb *db;
+	
+	db = bmp_cfg_db_open();
+
+	bmp_cfg_db_get_bool(db,"modplug","Surround", &mModProps.mSurround);
+        bmp_cfg_db_get_bool(db,"modplug","Oversampling", &mModProps.mOversamp);
+        bmp_cfg_db_get_bool(db,"modplug","Megabass", &mModProps.mMegabass);
+        bmp_cfg_db_get_bool(db,"modplug","NoiseReduction", &mModProps.mNoiseReduction);
+        bmp_cfg_db_get_bool(db,"modplug","VolumeRamp", &mModProps.mVolumeRamp);
+        bmp_cfg_db_get_bool(db,"modplug","Reverb", &mModProps.mReverb);
+        bmp_cfg_db_get_bool(db,"modplug","FastInfo", &mModProps.mFastinfo);
+        bmp_cfg_db_get_bool(db,"modplug","UseFileName", &mModProps.mUseFilename);
+        bmp_cfg_db_get_bool(db,"modplug","GrabAmigaMOD", &mModProps.mGrabAmigaMOD);
+        bmp_cfg_db_get_bool(db,"modplug","PreAmp", &mModProps.mPreamp);
+        bmp_cfg_db_get_float(db,"modplug","PreAmpLevel", &mModProps.mPreampLevel);
+        bmp_cfg_db_get_int(db,"modplug", "Channels", &mModProps.mChannels);
+        bmp_cfg_db_get_int(db,"modplug", "Bits", &mModProps.mBits);
+        bmp_cfg_db_get_int(db,"modplug", "Frequency", &mModProps.mFrequency);
+        bmp_cfg_db_get_int(db,"modplug", "ResamplineMode", &mModProps.mResamplingMode);
+        bmp_cfg_db_get_int(db,"modplug", "ReverbDepth", &mModProps.mReverbDepth);
+        bmp_cfg_db_get_int(db,"modplug", "ReverbDelay", &mModProps.mReverbDelay);
+        bmp_cfg_db_get_int(db,"modplug", "BassAmount", &mModProps.mBassAmount);
+        bmp_cfg_db_get_int(db,"modplug", "BassRange", &mModProps.mBassRange);
+        bmp_cfg_db_get_int(db,"modplug", "SurroundDepth", &mModProps.mSurroundDepth);
+        bmp_cfg_db_get_int(db,"modplug", "SurroundDelay", &mModProps.mSurroundDelay);
+        bmp_cfg_db_get_int(db,"modplug", "LoopCount", &mModProps.mLoopCount);
+
+	bmp_cfg_db_close(db);
+}
+
+bool ModplugXMMS::CanPlayFile(const string& aFilename)
+{
+	string lExt;
+	uint32 lPos;
+
+	VFSFile *file;
+	gchar magic[4];
+
+	if ((file = vfs_fopen(aFilename.c_str(), "rb"))) {
+	vfs_fread(magic, 1, 4, file);
+	if (!memcmp(magic, UMX_MAGIC, 4)) {
+		vfs_fclose(file);
+		return 1;
+	}
+	if (!memcmp(magic, XM_MAGIC, 4)) {
+		vfs_fclose(file);
+		return 1;
+	}
+	if (!memcmp(magic, M669_MAGIC, 4)) {
+		vfs_fclose(file);
+		return 1;
+	}
+	if (!memcmp(magic, IT_MAGIC, 4)) {
+		vfs_fclose(file);
+		return 1;
+	}
+	if (!memcmp(magic, MTM_MAGIC, 4)) {
+		vfs_fclose(file);
+		return 1;
+	}
+	if (!memcmp(magic, PSM_MAGIC, 4)) {
+		vfs_fclose(file);
+		return 1;
+	}
+	vfs_fseek(file, 44, SEEK_SET);
+	vfs_fread(magic, 1, 4, file);
+	if (!memcmp(magic, S3M_MAGIC, 4)) {
+		vfs_fclose(file);
+		return 1;
+	}
+	if(mModProps.mGrabAmigaMOD) {
+	vfs_fseek(file, 1080, SEEK_SET);
+	vfs_fread(magic, 1, 4, file);
+	if (!memcmp(magic, MOD_MAGIC_PROTRACKER4, 4)) {
+		vfs_fclose(file);
+		return 1;
+	}
+	if (!memcmp(magic, MOD_MAGIC_PROTRACKER4X, 4)) {
+		vfs_fclose(file);
+		return 1;
+	}
+	if (!memcmp(magic, MOD_MAGIC_NOISETRACKER, 4)) {
+		vfs_fclose(file);
+		return 1;
+	}
+	if (!memcmp(magic, MOD_MAGIC_STARTRACKER4, 4)) {
+		vfs_fclose(file);
+		return 1;
+	}
+	if (!memcmp(magic, MOD_MAGIC_STARTRACKER8, 4)) {
+		vfs_fclose(file);
+		return 1;
+	}
+	if (!memcmp(magic, MOD_MAGIC_STARTRACKER4X, 4)) {
+		vfs_fclose(file);
+		return 1;
+	}
+	if (!memcmp(magic, MOD_MAGIC_STARTRACKER8X, 4)) {
+		vfs_fclose(file);
+		return 1;
+	}
+	if (!memcmp(magic, MOD_MAGIC_FASTTRACKER4, 4)) {
+		vfs_fclose(file);
+		return 1;
+	}
+	if (!memcmp(magic, MOD_MAGIC_FASTTRACKER6, 4)) {
+		vfs_fclose(file);
+		return 1;
+	}
+	if (!memcmp(magic, MOD_MAGIC_FASTTRACKER8, 4)) {
+		vfs_fclose(file);
+		return 1;
+	}
+	if (!memcmp(magic, MOD_MAGIC_OKTALYZER8, 4)) {
+		vfs_fclose(file);
+		return 1;
+	}
+	if (!memcmp(magic, MOD_MAGIC_OKTALYZER8X, 4)) {
+		vfs_fclose(file);
+		return 1;
+	}
+	if (!memcmp(magic, MOD_MAGIC_TAKETRACKER16, 4)) {
+		vfs_fclose(file);
+		return 1;
+	}
+	if (!memcmp(magic, MOD_MAGIC_TAKETRACKER32, 4)) {
+		vfs_fclose(file);
+		return 1;
+	}
+	} /* end of if(mModProps.mGrabAmigaMOD) */
+
+	/* We didn't find the magic bytes, fall back to extension check */
+	vfs_fclose(file);
+	} /* end of vfs_open main if statement */
+
+	lPos = aFilename.find_last_of('.');
+	if((int)lPos == -1)
+		return false;
+	lExt = aFilename.substr(lPos);
+	for(uint32 i = 0; i < lExt.length(); i++)
+		lExt[i] = tolower(lExt[i]);
+
+	if (lExt == ".amf")
+		return true;
+	if (lExt == ".ams")
+		return true;
+	if (lExt == ".dbm")
+		return true;
+	if (lExt == ".dbf")
+		return true;
+	if (lExt == ".dsm")
+		return true;
+	if (lExt == ".far")
+		return true;
+	if (lExt == ".mdl")
+		return true;
+	if (lExt == ".stm")
+		return true;
+	if (lExt == ".ult")
+		return true;
+	if (lExt == ".j2b")
+		return true;
+	if (lExt == ".mt2")
+		return true;
+
+	if (lExt == ".mdz")
+		return true;
+	if (lExt == ".mdr")
+		return true;
+	if (lExt == ".mdgz")
+		return true;
+	if (lExt == ".mdbz")
+		return true;
+	if (lExt == ".s3z")
+		return true;
+	if (lExt == ".s3r")
+		return true;
+	if (lExt == ".s3gz")
+		return true;
+	if (lExt == ".xmz")
+		return true;
+	if (lExt == ".xmr")
+		return true;
+	if (lExt == ".xmgz")
+		return true;
+	if (lExt == ".itz")
+		return true;
+	if (lExt == ".itr")
+		return true;
+	if (lExt == ".itgz")
+		return true;
+	if (lExt == ".dmf")
+		return true;
+	
+	if (lExt == ".zip")
+		return ContainsMod(aFilename);
+	if (lExt == ".gz")
+		return ContainsMod(aFilename);
+	if (lExt == ".bz2")
+		return ContainsMod(aFilename);
+
+	return false;
+}
+
+void* ModplugXMMS::PlayThread(void* arg)
+{
+	((ModplugXMMS*)arg)->PlayLoop();
+	return NULL;
+}
+
+void ModplugXMMS::PlayLoop()
+{
+	uint32 lLength;
+	//the user might change the number of channels while playing.
+	// we don't want this to take effect until we are done!
+	uint8 lChannels = mModProps.mChannels;
+
+	while(!mStopped)
+	{
+		if(!(lLength = mSoundFile->Read(
+				mBuffer,
+				mBufSize)))
+		{
+			//no more to play.  Wait for output to finish and then stop.
+			while((mOutPlug->buffer_playing())
+			   && (!mStopped))
+				usleep(10000);
+			break;
+		}
+		
+		if(mModProps.mPreamp)
+		{
+			//apply preamp
+			if(mModProps.mBits == 16)
+			{
+				uint n = mBufSize >> 1;
+				for(uint i = 0; i < n; i++) {
+					short old = ((short*)mBuffer)[i];
+					((short*)mBuffer)[i] *= (short int)mPreampFactor;
+					// detect overflow and clip!
+					if ((old & 0x8000) != 
+					 (((short*)mBuffer)[i] & 0x8000))
+					  ((short*)mBuffer)[i] = old | 0x7FFF;
+						
+				}
+			}
+			else
+			{
+				for(uint i = 0; i < mBufSize; i++) {
+					uchar old = ((uchar*)mBuffer)[i];
+					((uchar*)mBuffer)[i] *= (short int)mPreampFactor;
+					// detect overflow and clip!
+					if ((old & 0x80) != 
+					 (((uchar*)mBuffer)[i] & 0x80))
+					  ((uchar*)mBuffer)[i] = old | 0x7F;
+				}
+			}
+		}
+		
+		if(mStopped)
+			break;
+	
+		//wait for buffer space to free up.
+		while(((mOutPlug->buffer_free()
+		    < (int)mBufSize))
+		   && (!mStopped))
+			usleep(10000);
+			
+		if(mStopped)
+			break;
+		
+		produce_audio
+		(
+			mPlayed,
+			mFormat,
+			lChannels,
+			mBufSize,
+			mBuffer,
+			NULL
+		);
+
+		mPlayed += mBufTime;
+	}
+
+//	mOutPlug->flush(0);
+	mOutPlug->close_audio();
+
+	//Unload the file
+	mSoundFile->Destroy();
+	delete mArchive;
+
+	if (mBuffer)
+	{
+		delete [] mBuffer;
+		mBuffer = NULL;
+	}
+
+	mPaused = false;
+	mStopped = true;
+
+	g_thread_exit(NULL);
+}
+
+void ModplugXMMS::PlayFile(const string& aFilename)
+{
+	mStopped = true;
+	mPaused = false;
+	
+	//open and mmap the file
+	mArchive = OpenArchive(aFilename);
+	if(mArchive->Size() == 0)
+	{
+		delete mArchive;
+		return;
+	}
+	
+	if (mBuffer)
+		delete [] mBuffer;
+	
+	//find buftime to get approx. 512 samples/block
+	mBufTime = 512000 / mModProps.mFrequency + 1;
+
+	mBufSize = mBufTime;
+	mBufSize *= mModProps.mFrequency;
+	mBufSize /= 1000;    //milliseconds
+	mBufSize *= mModProps.mChannels;
+	mBufSize *= mModProps.mBits / 8;
+
+	mBuffer = new uchar[mBufSize];
+	if(!mBuffer)
+		return;             //out of memory!
+
+	CSoundFile::SetWaveConfig
+	(
+		mModProps.mFrequency,
+		mModProps.mBits,
+		mModProps.mChannels
+	);
+	CSoundFile::SetWaveConfigEx
+	(
+		mModProps.mSurround,
+		!mModProps.mOversamp,
+		mModProps.mReverb,
+		true,
+		mModProps.mMegabass,
+		mModProps.mNoiseReduction,
+		false
+	);
+	
+	// [Reverb level 0(quiet)-100(loud)], [delay in ms, usually 40-200ms]
+	if(mModProps.mReverb)
+	{
+		CSoundFile::SetReverbParameters
+		(
+			mModProps.mReverbDepth,
+			mModProps.mReverbDelay
+		);
+	}
+	// [XBass level 0(quiet)-100(loud)], [cutoff in Hz 10-100]
+	if(mModProps.mMegabass)
+	{
+		CSoundFile::SetXBassParameters
+		(
+			mModProps.mBassAmount,
+			mModProps.mBassRange
+		);
+	}
+	// [Surround level 0(quiet)-100(heavy)] [delay in ms, usually 5-40ms]
+	if(mModProps.mSurround)
+	{
+		CSoundFile::SetSurroundParameters
+		(
+			mModProps.mSurroundDepth,
+			mModProps.mSurroundDelay
+		);
+	}
+	CSoundFile::SetResamplingMode(mModProps.mResamplingMode);
+	mSoundFile->SetRepeatCount(mModProps.mLoopCount);
+	mPreampFactor = exp(mModProps.mPreampLevel);
+	
+	mPaused = false;
+	mStopped = false;
+
+	mSoundFile->Create
+	(
+		(uchar*)mArchive->Map(),
+		mArchive->Size()
+	);
+	mPlayed = 0;
+	
+	bool useFilename = mModProps.mUseFilename;
+	
+	if(!useFilename)
+	{
+		strncpy(mModName, mSoundFile->GetTitle(), 100);
+		
+		for(int i = 0; mModName[i] == ' ' || mModName[i] == 0; i++)
+		{
+			if(mModName[i] == 0)
+			{
+				useFilename = true;  //mod name is blank -- use filename
+				break;
+			}
+		}
+	}
+	
+	if(useFilename)
+	{
+		strncpy(mModName, strrchr(aFilename.c_str(), '/') + 1, 100);
+		char* ext = strrchr(mModName, '.');
+		if(ext) *ext = '\0';
+	}
+	
+	mInPlug->set_info
+	(
+		mModName,
+		mSoundFile->GetSongTime() * 1000,
+		mSoundFile->GetNumChannels() * 1000,
+		mModProps.mFrequency,
+		mModProps.mChannels
+	);
+
+	mStopped = mPaused = false;
+
+	if(mModProps.mBits == 16)
+		mFormat = FMT_S16_NE;
+	else
+		mFormat = FMT_U8;
+
+	mOutPlug->open_audio
+	(
+		mFormat,
+		mModProps.mFrequency,
+		mModProps.mChannels
+	);
+
+	mDecodeThread = g_thread_create(
+		(GThreadFunc)PlayThread,
+		this,
+		TRUE,
+		NULL
+	);
+}
+
+void ModplugXMMS::Stop(void)
+{
+	if(mStopped)
+		return;
+
+	mStopped = true;
+	mPaused = false;
+	
+	g_thread_join(mDecodeThread);
+}
+
+void ModplugXMMS::Pause(bool aPaused)
+{
+	if(aPaused)
+		mPaused = true;
+	else
+		mPaused = false;
+	
+	mOutPlug->pause(aPaused);
+}
+
+void ModplugXMMS::Seek(float32 aTime)
+{
+	uint32  lMax;
+	uint32  lMaxtime;
+	float32 lPostime;
+	
+	if(aTime > (lMaxtime = mSoundFile->GetSongTime()))
+		aTime = lMaxtime;
+	lMax = mSoundFile->GetMaxPosition();
+	lPostime = float(lMax) / lMaxtime;
+
+	mSoundFile->SetCurrentPos(int(aTime * lPostime));
+
+	mOutPlug->flush(int(aTime * 1000));
+	mPlayed = uint32(aTime * 1000);
+}
+
+float32 ModplugXMMS::GetTime(void)
+{
+	if(mStopped)
+		return -1;
+	return (float32)mOutPlug->output_time() / 1000;
+}
+
+void ModplugXMMS::GetSongInfo(const string& aFilename, char*& aTitle, int32& aLength)
+{
+	aLength = -1;
+	fstream lTestFile;
+	string lError;
+	bool lDone;
+	
+	lTestFile.open(aFilename.c_str(), ios::in);
+	if(!lTestFile)
+	{
+		lError = "**no such file: ";
+		lError += strrchr(aFilename.c_str(), '/') + 1;
+		aTitle = new char[lError.length() + 1];
+		strcpy(aTitle, lError.c_str());
+		return;
+	}
+	
+	lTestFile.close();
+
+	if(mModProps.mFastinfo)
+	{
+		if(mModProps.mUseFilename)
+		{
+			//Use filename as name
+			aTitle = new char[aFilename.length() + 1];
+			strcpy(aTitle, strrchr(aFilename.c_str(), '/') + 1);
+			*strrchr(aTitle, '.') = '\0';
+			return;
+		}
+		
+		fstream lModFile;
+		string lExt;
+		uint32 lPos;
+		
+		lDone = true;
+
+		// previously ios::nocreate was used (X Standard C++ Library)
+		lModFile.open(aFilename.c_str(), ios::in);
+
+		lPos = aFilename.find_last_of('.');
+		if((int)lPos == 0)
+			return;
+		lExt = aFilename.substr(lPos);
+		for(uint32 i = 0; i < lExt.length(); i++)
+			lExt[i] = tolower(lExt[i]);
+
+		if (lExt == ".mod")
+		{
+			lModFile.read(mModName, 20);
+			mModName[20] = 0;
+		}
+		else if (lExt == ".s3m")
+		{
+			lModFile.read(mModName, 28);
+			mModName[28] = 0;
+		}
+		else if (lExt == ".xm")
+		{
+			lModFile.seekg(17);
+			lModFile.read(mModName, 20);
+			mModName[20] = 0;
+		}
+		else if (lExt == ".it")
+		{
+			lModFile.seekg(4);
+			lModFile.read(mModName, 28);
+			mModName[28] = 0;
+		}
+		else
+			lDone = false;     //fall back to slow info
+
+		lModFile.close();
+
+		if(lDone)
+		{
+			for(int i = 0; mModName[i] != 0; i++)
+			{
+				if(mModName[i] != ' ')
+				{
+					aTitle = new char[strlen(mModName) + 1];
+					strcpy(aTitle, mModName);
+					
+					return;
+				}
+			}
+			
+			//mod name is blank.  Use filename instead.
+			aTitle = new char[aFilename.length() + 1];
+			strcpy(aTitle, strrchr(aFilename.c_str(), '/') + 1);
+			*strrchr(aTitle, '.') = '\0';
+			return;
+		}
+	}
+		
+	Archive* lArchive;
+	CSoundFile* lSoundFile;
+	const char* lTitle;
+
+	//open and mmap the file
+	lArchive = OpenArchive(aFilename);
+	if(lArchive->Size() == 0)
+	{
+		lError = "**bad mod file: ";
+		lError += strrchr(aFilename.c_str(), '/') + 1;
+		aTitle = new char[lError.length() + 1];
+		strcpy(aTitle, lError.c_str());
+		delete lArchive;
+		return;
+	}
+
+	lSoundFile = new CSoundFile;
+	lSoundFile->Create((uchar*)lArchive->Map(), lArchive->Size());
+
+	if(!mModProps.mUseFilename)
+	{
+		lTitle = lSoundFile->GetTitle();
+		
+		for(int i = 0; lTitle[i] != 0; i++)
+		{
+			if(lTitle[i] != ' ')
+			{
+				aTitle = new char[strlen(lTitle) + 1];
+				strcpy(aTitle, lTitle);
+				goto therest;     //sorry
+			}
+		}
+	}
+	
+	//mod name is blank, or user wants the filename to be used as the title.
+	aTitle = new char[aFilename.length() + 1];
+	strcpy(aTitle, strrchr(aFilename.c_str(), '/') + 1);
+	*strrchr(aTitle, '.') = '\0';
+
+therest:
+	aLength = lSoundFile->GetSongTime() * 1000;                   //It wants milliseconds!?!
+
+	//unload the file
+	lSoundFile->Destroy();
+	delete lSoundFile;
+	delete lArchive;
+}
+
+void ModplugXMMS::SetInputPlugin(InputPlugin& aInPlugin)
+{
+	mInPlug = &aInPlugin;
+}
+void ModplugXMMS::SetOutputPlugin(OutputPlugin& aOutPlugin)
+{
+	mOutPlug = &aOutPlugin;
+}
+
+const ModplugXMMS::Settings& ModplugXMMS::GetModProps()
+{
+	return mModProps;
+}
+
+const char* ModplugXMMS::Bool2OnOff(bool aValue)
+{
+	if(aValue)
+		return "on";
+	else
+		return "off";
+}
+
+void ModplugXMMS::SetModProps(const Settings& aModProps)
+{
+	ConfigDb *db;
+	mModProps = aModProps;
+
+	// [Reverb level 0(quiet)-100(loud)], [delay in ms, usually 40-200ms]
+	if(mModProps.mReverb)
+	{
+		CSoundFile::SetReverbParameters
+		(
+			mModProps.mReverbDepth,
+			mModProps.mReverbDelay
+		);
+	}
+	// [XBass level 0(quiet)-100(loud)], [cutoff in Hz 10-100]
+	if(mModProps.mMegabass)
+	{
+		CSoundFile::SetXBassParameters
+		(
+			mModProps.mBassAmount,
+			mModProps.mBassRange
+		);
+	}
+	else //modplug seems to ignore the SetWaveConfigEx() setting for bass boost
+	{
+		CSoundFile::SetXBassParameters
+		(
+			0,
+			0
+		);
+	}
+	// [Surround level 0(quiet)-100(heavy)] [delay in ms, usually 5-40ms]
+	if(mModProps.mSurround)
+	{
+		CSoundFile::SetSurroundParameters
+		(
+			mModProps.mSurroundDepth,
+			mModProps.mSurroundDelay
+		);
+	}
+	CSoundFile::SetWaveConfigEx
+	(
+		mModProps.mSurround,
+		!mModProps.mOversamp,
+		mModProps.mReverb,
+		true,
+		mModProps.mMegabass,
+		mModProps.mNoiseReduction,
+		false
+	);
+	CSoundFile::SetResamplingMode(mModProps.mResamplingMode);
+	mPreampFactor = exp(mModProps.mPreampLevel);
+
+	db = bmp_cfg_db_open();
+
+	bmp_cfg_db_set_bool(db,"modplug","Surround", mModProps.mSurround);
+        bmp_cfg_db_set_bool(db,"modplug","Oversampling", mModProps.mOversamp);
+        bmp_cfg_db_set_bool(db,"modplug","Megabass", mModProps.mMegabass);
+        bmp_cfg_db_set_bool(db,"modplug","NoiseReduction", mModProps.mNoiseReduction);
+        bmp_cfg_db_set_bool(db,"modplug","VolumeRamp", mModProps.mVolumeRamp);
+        bmp_cfg_db_set_bool(db,"modplug","Reverb", mModProps.mReverb);
+        bmp_cfg_db_set_bool(db,"modplug","FastInfo", mModProps.mFastinfo);
+        bmp_cfg_db_set_bool(db,"modplug","UseFileName", mModProps.mUseFilename);
+        bmp_cfg_db_set_bool(db,"modplug","GrabAmigaMOD", mModProps.mGrabAmigaMOD);
+        bmp_cfg_db_set_bool(db,"modplug","PreAmp", mModProps.mPreamp);
+        bmp_cfg_db_set_float(db,"modplug","PreAmpLevel", mModProps.mPreampLevel);
+        bmp_cfg_db_set_int(db,"modplug", "Channels", mModProps.mChannels);
+        bmp_cfg_db_set_int(db,"modplug", "Bits", mModProps.mBits);
+        bmp_cfg_db_set_int(db,"modplug", "Frequency", mModProps.mFrequency);
+        bmp_cfg_db_set_int(db,"modplug", "ResamplineMode", mModProps.mResamplingMode);
+        bmp_cfg_db_set_int(db,"modplug", "ReverbDepth", mModProps.mReverbDepth);
+        bmp_cfg_db_set_int(db,"modplug", "ReverbDelay", mModProps.mReverbDelay);
+        bmp_cfg_db_set_int(db,"modplug", "BassAmount", mModProps.mBassAmount);
+        bmp_cfg_db_set_int(db,"modplug", "BassRange", mModProps.mBassRange);
+        bmp_cfg_db_set_int(db,"modplug", "SurroundDepth", mModProps.mSurroundDepth);
+        bmp_cfg_db_set_int(db,"modplug", "SurroundDelay", mModProps.mSurroundDelay);
+        bmp_cfg_db_set_int(db,"modplug", "LoopCount", mModProps.mLoopCount);
+
+	bmp_cfg_db_close(db);
+}
+
+ModplugXMMS gModplugXMMS;