Using Mikmod Directly


Sephnroth

Member
Joined
Dec 25, 2005
Messages
151
Age
39
Location
UK
Website
Visit site
I may be doing something stupid (likely) so bare with me.

I cannot get mikmod working on the gp2x. Well, according to my status messages things are working in a sense, but I cant get any sound audiable.

To start with I can only seem to do MikMod_RegisterAllDrivers(), if I try to load one specific driver it blows up in some nonsensical error - MikMod_strerror(MikMod_errno) returns: 0x1.f0ef40000000fp-1021

..yeah, thanks for that wonderful error message.

If I do a driver info thing after registering all drivers I can see that the drivers it loads are:

1 Raw disk writer (music.raw) v1.1
2 Wav disk writer (music.wav) v1.2
3 Piped Output driver v0.2
4 Standard output driver v1.1
5 Nosound Driver v3.0.

which explains why theres no audio output. theres apprantly no oss or alsa on the gp2x? I also cannot for the life of me find a function that will let me tell mikmod which of the loaded drivers to use. Not so great. But Im guessing its using the raw disk writer because every time I run the program it creates a music.raw.

Right I thought. I'll try and write the contents of music.raw directly to /dev/dsp to see what happens - and then I learned that music.raw was apprantly just created and never written to because it was always 0 bytes! Im so lost with this (first attempt at using this library) that i've come here for help and i'll paste all my functions for people to inspect and suggest the best way of doing it - alot of it was guess work.

First off you need to understand that I have encased these functions in my Dark2x sdk (sdl-and-other-things wrapper) and the functions take a numerical id for objects which is why the top half of most functions is spent working out the id. Also, the function LoopSDK() gets called every cpu cycle, the actual program loop for things using the sdk is while (LoopSDK()) { game stuff } - so i figured that was a good place for my mikmod_update call. Code as follows:

Code:
int dbxInitMikmodPlayer(int nFormats) {

	MikMod_RegisterAllDrivers();	
	//MikMod_RegisterDriver(&drv_stdout); //this explodes mikmod

	if (nFormats & MOD_FORMAT_ALL) {
		MikMod_RegisterAllLoaders();
	} else {
		if (nFormats & MOD_FORMAT_699) { MikMod_RegisterLoader(&load_669); }
		if (nFormats & MOD_FORMAT_AMF) { MikMod_RegisterLoader(&load_amf); }
		//if (nFormats & MOD_FORMAT_ASY) { MikMod_RegisterLoader(&load_asy); }
		if (nFormats & MOD_FORMAT_DSM) { MikMod_RegisterLoader(&load_dsm); }
		if (nFormats & MOD_FORMAT_FAR) { MikMod_RegisterLoader(&load_far); }
		if (nFormats & MOD_FORMAT_GDM) { MikMod_RegisterLoader(&load_gdm); }
		if (nFormats & MOD_FORMAT_IT) { MikMod_RegisterLoader(&load_it); }
		if (nFormats & MOD_FORMAT_IMF) { MikMod_RegisterLoader(&load_imf); }
		if (nFormats & MOD_FORMAT_MED) { MikMod_RegisterLoader(&load_med); }
		if (nFormats & MOD_FORMAT_M15) { MikMod_RegisterLoader(&load_m15); }
		if (nFormats & MOD_FORMAT_MOD) { MikMod_RegisterLoader(&load_mod); }
		if (nFormats & MOD_FORMAT_MTM) { MikMod_RegisterLoader(&load_mtm); }
		if (nFormats & MOD_FORMAT_OKT) { MikMod_RegisterLoader(&load_okt); }
		if (nFormats & MOD_FORMAT_STM) { MikMod_RegisterLoader(&load_stm); }
		if (nFormats & MOD_FORMAT_STX) { MikMod_RegisterLoader(&load_stx); }
		if (nFormats & MOD_FORMAT_S3M) { MikMod_RegisterLoader(&load_s3m); }
		if (nFormats & MOD_FORMAT_ULT) { MikMod_RegisterLoader(&load_ult); }
		if (nFormats & MOD_FORMAT_UNI) { MikMod_RegisterLoader(&load_uni); }
		if (nFormats & MOD_FORMAT_XM) { MikMod_RegisterLoader(&load_xm); }
	}
	
	md_mode |= DMODE_SOFT_MUSIC;

	if (MikMod_Init("")) {
		printf("Failed to init MikMod! \"%a\"\n", MikMod_strerror(MikMod_errno));
	} else {
		printf("MikMod initialised.\n Availiable drivers:\n %s.\n", MikMod_InfoDriver());
	}

	bMikmodInit = true;
	return 1;
}

int dbxLoadMusic_MikMod(int nMusicID, char *szFilename) {
	int nWorkingID = -1;

	for (int n = 0; n < nMikmodTotal; n++) {
		if (dxMikModules[n].id == nMusicID) {
			nWorkingID = n;
		}
	}

	if (nWorkingID == -1) {
		nMikmodTotal++;

		if (dxMikModules == NULL) {
			dxMikModules = (tdbxMikModule*)malloc(sizeof(tdbxMikModule));
		} else {
			dxMikModules = (tdbxMikModule*)realloc(dxMikModules, sizeof(tdbxMikModule) * nMikmodTotal);
		}

		nWorkingID = nMikmodTotal - 1;
	}

	dxMikModules[nWorkingID].id = nWorkingID;
	dxMikModules[nWorkingID].playing = false;
	dxMikModules[nWorkingID].mik_mod = Player_Load(szFilename, 64, 0);

	if (!dxMikModules[nWorkingID].mik_mod) {
		printf("Failed to load mod file! \"%a\"\n", MikMod_strerror(MikMod_errno));
	} else {
		printf("Loaded mod file: %s\n", szFilename);
	}

	return 1;
}

int dbxPlayMusic_MikMod(int nMusicID) {
	int nWorkingID = -1;

	for (int n = 0; n < nMikmodTotal; n++) {
		if (dxMikModules[n].id == nMusicID) {
			nWorkingID = n;
		}
	}

	if (nWorkingID == -1) {
		return -1;
	}

	Player_Start(dxMikModules[nWorkingID].mik_mod);
	Player_SetVolume(128);
	return 1;
}

and now the relevent part of LoopSDK() (too big to all go here, so only included the mikmod part)

Code:
if (bMikmodInit) {
	if (SDL_GetTicks() - nMikmodLastUpdate > nMikmodUpdateFreq) {
		nMikmodLastUpdate = SDL_GetTicks();
							
		SDL_RWops *rw = SDL_RWFromFile("music.raw", "rb");
		int len = SDL_RWseek(rw, 0, SEEK_END);
		SDL_RWseek(rw, 0, SEEK_SET);

		unsigned char *audio = (unsigned char*)malloc(len);
		SDL_RWread(rw, audio, 1, len);
		SDL_RWclose(rw);

		int dsp = open("/dev/dsp", O_RDWR);
		write(dsp, audio, len);
		close(dsp);

		printf("mikmod - wrote %d bytes to /dev/dsp\n", len);
		MikMod_Update();
		free(audio);
	}
}

thats all my code. I fully admit that i had no idea what i was doing with MikMod_Update(); and its music.raw and completly guessed at how to write the data to /dev/dsp - but it seems irrelevent when that printf in there tells me that its written 0 bytes. nMikmodUpdateFreq i've tried on 10000 like on the mikmod website tutorial and 1000, no difference at all.

I call all my code like this:
Code:
	dbxInitMikmodPlayer(MOD_FORMAT_XM);
	dbxLoadMusic_MikMod(1, "Sound/bgm/noname.xm");
	dbxPlayMusic_MikMod(1);

and the output I see in my terminal window is:

MikMod initialised.
Availiable drivers:
1 Raw disk writer (music.raw) v1.1
2 Wav disk writer (music.wav) v1.2
3 Piped Output driver v0.2
4 Standard output driver v1.1
5 Nosound Driver v3.0.
Loaded mod file: Sound/bgm/noname.xm
mikmod - wrote 0 bytes to /dev/dsp
mikmod - wrote 0 bytes to /dev/dsp
mikmod - wrote 0 bytes to /dev/dsp
...
etc

completly out of ideas on how to make it work, been fiddling for ages - i've gone this route becase SDL_Mixer completly destroys my FPS when playing complex xm files even in low quality - someone suggested using mikmod directly would be faster. With this code so far my FPS hasnt actually taken a hit yet, but i havnt heard crap all either :/ How do I make this thing go?

All help appreiciated, thanks :)


EDIT:

what would be optimal i think is if I could use the pipe driver to pipe the audio output directly to dev/dsp and do away with sd card read/writes. this is what I first tried, but as loading individual drivers is exploding in that weird error for me I quickly got stuck with the music.raw - if anyone has any idea how to use the pipe properly then I think thats the best idea (right?)
 
Back
Top