Esempio n. 1
0
// Callback hook to read streaming GME data.
static FMOD_RESULT F_CALLBACK GMEReadCallback(FMOD_SOUND *sound, void *data, unsigned int datalen)
{
	Music_Emu *emu;
	void *emuvoid = NULL;
	// get our emu
	FMR(FMOD_Sound_GetUserData(sound, &emuvoid));
	emu = emuvoid;
	// no emu? no play.
	if (!emu)
		return FMOD_ERR_FILE_EOF;
	if (gme_track_ended(emu))
	{
		// don't delete the primary music stream
		if (emu == gme)
			return FMOD_ERR_FILE_EOF;
		// do delete sfx streams
		FMR(FMOD_Sound_SetUserData(sound, NULL));
		gme_delete(emu);
		return FMOD_ERR_FILE_EOF;
	}
	// play beautiful musics theme of ancient land.
	if (gme_play(emu, datalen/2, data))
		return FMOD_ERR_FILE_BAD;
	// O.K
	return FMOD_OK;
}
Esempio n. 2
0
void I_StopSound(INT32 handle)
{
	FMOD_CHANNEL *chan;
	FMR(FMOD_System_GetChannel(fsys, handle, &chan));
	if (music_stream && chan == music_channel)
		return;
	FMR(FMOD_Channel_Stop(chan));
}
Esempio n. 3
0
FMRadioResult FMRadioSetTurnedOn(FMRadio* r, bool on) {
	if (FMR(r)->On != on) {
		FMR(r)->On = on;
		if (on) {
			FMR(r)->Volume = 1;
			FMR(r)->Frequency = 92345;
		}
	}
	
	FMLog("Set radio with unique pointer %p on state to %d", r, (int) on);
	return kFMRadioNoError;
}
Esempio n. 4
0
boolean I_PlaySong(INT32 handle, boolean looping)
{
	if (1337 == handle)
	{
		midimode = true;
		if (looping)
			FMR(FMOD_Sound_SetMode(music_stream, FMOD_LOOP_NORMAL));
		FMR(FMOD_System_PlaySound(fsys, FMOD_CHANNEL_FREE, music_stream, false, &music_channel));
		FMR_MUSIC(FMOD_Channel_SetVolume(music_channel, midi_volume / 31.0));
		FMR_MUSIC(FMOD_Channel_SetPriority(music_channel, 0));
	}
	return true;
}
Esempio n. 5
0
INT32 I_StartSound(sfxenum_t id, UINT8 vol, UINT8 sep, UINT8 pitch, UINT8 priority)
{
	FMOD_SOUND *sound;
	FMOD_CHANNEL *chan;
	INT32 i;
	float frequency;

	sound = (FMOD_SOUND *)S_sfx[id].data;
	I_Assert(sound != NULL);

	FMR(FMOD_System_PlaySound(fsys, FMOD_CHANNEL_FREE, sound, true, &chan));

	if (sep == 0)
		sep = 1;

	FMR(FMOD_Channel_SetVolume(chan, (vol / 255.0) * (sfx_volume / 31.0)));
	FMR(FMOD_Channel_SetPan(chan, (sep - 128) / 127.0));

	FMR(FMOD_Sound_GetDefaults(sound, &frequency, NULL, NULL, NULL));
	FMR(FMOD_Channel_SetFrequency(chan, (pitch / 128.0) * frequency));

	FMR(FMOD_Channel_SetPriority(chan, priority));
	//UNREFERENCED_PARAMETER(priority);
	//FMR(FMOD_Channel_SetPriority(chan, 1 + ((0xff-vol)>>1))); // automatic priority 1 - 128 based on volume (priority 0 is music)

	FMR(FMOD_Channel_GetIndex(chan, &i));
	FMR(FMOD_Channel_SetPaused(chan, false));
	return i;
}
Esempio n. 6
0
void I_StartupSound(void)
{
	I_Assert(!sound_started);
	sound_started = true;

	FMR(FMOD_System_Create(&fsys));
	FMR(FMOD_System_SetDSPBufferSize(fsys, 44100 / 30, 2));
	FMR(FMOD_System_Init(fsys, 64, FMOD_INIT_VOL0_BECOMES_VIRTUAL, NULL));
	music_stream = NULL;
#ifdef HAVE_LIBGME
	gme = NULL;
#endif
	current_track = -1;
}
Esempio n. 7
0
boolean I_SetSongSpeed(float speed)
{
	FMOD_RESULT e;
	float frequency;
	if (!music_stream)
		return false;
	if (speed > 250.0f)
		speed = 250.0f; //limit speed up to 250x

#ifdef HAVE_LIBGME
	// Try to set GME speed
	if (gme)
	{
		gme_set_tempo(gme, speed);
		return true;
	}
#endif

	// Try to set Mod/Midi speed
	e = FMOD_Sound_SetMusicSpeed(music_stream, speed);

	if (e == FMOD_ERR_FORMAT)
	{
		// Just change pitch instead for Ogg/etc.
		FMR(FMOD_Sound_GetDefaults(music_stream, &frequency, NULL, NULL, NULL));
		FMR_MUSIC(FMOD_Channel_SetFrequency(music_channel, speed*frequency));
	}
	else
		FMR_MUSIC(e);

	return true;
}
Esempio n. 8
0
void I_UnRegisterSong(INT32 handle)
{
	UNREFERENCED_PARAMETER(handle);
	if (music_stream)
		FMR(FMOD_Sound_Release(music_stream));
	music_stream = NULL;
}
Esempio n. 9
0
FMRadioResult FMRadioSetVolume(FMRadio* r, uint16_t volume) {
    struct video_audio va;
    if (!FMRadioGetAudioState(r, &va))
        return kFMRadioErrorPOSIX;

    va.volume = volume;
    return (ioctl(FMR(r)->FileDescriptor, VIDIOCSAUDIO, &va) >= 0)? kFMRadioNoError : kFMRadioErrorPOSIX;
}
Esempio n. 10
0
FMRadioResult FMRadioSetFrequency(FMRadio* r, uint32_t khz) {
	if (khz < 80000 || khz > 110000)
		return kFMRadioFrequencyOutOfRange;
	
	FMLog("Set radio frequency to %ld KHz", (long) khz);
	FMR(r)->Frequency = khz;
	return kFMRadioNoError;
}
Esempio n. 11
0
INT32 I_RegisterSong(void *data, size_t len)
{
	FMOD_CREATESOUNDEXINFO fmt;
	memset(&fmt, 0, sizeof(FMOD_CREATESOUNDEXINFO));
	fmt.cbsize = sizeof(FMOD_CREATESOUNDEXINFO);
	fmt.length = len;
	FMR(FMOD_System_CreateStream(fsys, (char *)data, FMOD_OPENMEMORY_POINT, &fmt, &music_stream));
	return 1337;
}
Esempio n. 12
0
void FMRadioClose(FMRadio* f) {
    close(FMR(f)->FileDescriptor);

    if (f != &FMDefaultRadio) {
        // in case of multiple radios, we'd free() this instance.
        // but we have just one, so TODO in the case we want to refactor for multiple ones.
    } else
        FMIsOpen = false;
}
Esempio n. 13
0
void I_ShutdownSound(void)
{
	I_Assert(sound_started);
	sound_started = false;

#ifdef HAVE_LIBGME
	if (gme)
		gme_delete(gme);
#endif
	FMR(FMOD_System_Release(fsys));
}
Esempio n. 14
0
boolean I_SoundIsPlaying(INT32 handle)
{
	FMOD_CHANNEL *chan;
	FMOD_BOOL playing;
	FMOD_RESULT e;
	FMR(FMOD_System_GetChannel(fsys, handle, &chan));
	if (music_stream && chan == music_channel)
		return false;
	e = FMOD_Channel_IsPlaying(chan, &playing);
	switch(e)
	{
	case FMOD_ERR_INVALID_HANDLE: // Sound effect finished.
	case FMOD_ERR_CHANNEL_STOLEN: // Sound effect interrupted. -- technically impossible due to GetChannel by handle. :(
		return false; // therefore, it's not playing anymore.
	default:
		FMR(e);
		break;
	}
	return (boolean)playing;
}
Esempio n. 15
0
void I_StopDigSong(void)
{
	if (music_stream)
		FMR(FMOD_Sound_Release(music_stream));
	music_stream = NULL;
#ifdef HAVE_LIBGME
	if (gme)
		gme_delete(gme);
	gme = NULL;
#endif
	current_track = -1;
}
Esempio n. 16
0
FMRadioResult FMRadioGetFrequency(FMRadio* r, uint32_t* khz) {
    struct video_tuner vt;
    if (!FMRadioGetTuningState(r, &vt))
        return kFMRadioErrorPOSIX;

    unsigned long frequency;
    if (ioctl(FMR(r)->FileDescriptor, VIDIOCGFREQ, &frequency) < 0)
        return kFMRadioErrorPOSIX;

    if (vt.flags & VIDEO_TUNER_LOW)
        frequency *= 1000;

    *khz = (uint32_t) frequency;
    return kFMRadioNoError;
}
Esempio n. 17
0
FMRadioResult FMRadioSetFrequency(FMRadio* r, uint32_t khz) {
    struct video_tuner vt;
    if (!FMRadioGetTuningState(r, &vt))
        return kFMRadioErrorPOSIX;

    // C type rather than exact-sized as this is what VIDIOCSFREQ expects.
    unsigned long frequency = khz;
    if (vt.flags & VIDEO_TUNER_LOW == 0) // "LOW" unset means the radio wants a MHz value.
        frequency /= 1000;

    if (frequency < vt.rangelow || frequency > vt.rangehigh)
        return kFMRadioFrequencyOutOfRange;

    return (ioctl(FMR(r)->FileDescriptor, VIDIOCSFREQ, &frequency) >= 0)? kFMRadioNoError : kFMRadioErrorPOSIX;
}
Esempio n. 18
0
// seems to never be called on an invalid channel (calls I_SoundIsPlaying first?)
// so I'm not gonna worry about it.
void I_UpdateSoundParams(INT32 handle, UINT8 vol, UINT8 sep, UINT8 pitch)
{
	FMOD_CHANNEL *chan;
	FMOD_SOUND *sound;
	float frequency;

	FMR(FMOD_System_GetChannel(fsys, handle, &chan));
	FMR(FMOD_Channel_SetVolume(chan, (vol / 255.0) * (sfx_volume / 31.0)));
	FMR(FMOD_Channel_SetPan(chan, (sep - 128) / 127.0));

	FMR(FMOD_Channel_GetCurrentSound(chan, &sound));
	FMR(FMOD_Sound_GetDefaults(sound, &frequency, NULL, NULL, NULL));
	FMR(FMOD_Channel_SetFrequency(chan, (pitch / 128.0) * frequency));

	//FMR(FMOD_Channel_SetPriority(chan, 1 + ((0xff-vol)>>1))); // automatic priority 1 - 128 based on volume (priority 0 is music)
}
Esempio n. 19
0
// convert doom format sound (signed 8bit)
// to an fmod format sound (unsigned 8bit)
// and return the FMOD_SOUND.
static inline FMOD_SOUND *ds2fmod(char *stream)
{
	FMOD_SOUND *sound;
	UINT16 ver;
	UINT16 freq;
	UINT32 samples;
	FMOD_CREATESOUNDEXINFO fmt;
	UINT32 i;
	UINT8 *p;

	// lump header
	ver = READUINT16(stream); // sound version format?
	if (ver != 3) // It should be 3 if it's a doomsound...
		return NULL; // onos! it's not a doomsound!
	freq = READUINT16(stream);
	samples = READUINT32(stream);
	//CONS_Printf("FMT: v%d f%d, s%d, b%d\n", ver, freq, samples, bps);

	memset(&fmt, 0, sizeof(FMOD_CREATESOUNDEXINFO));
	fmt.cbsize = sizeof(FMOD_CREATESOUNDEXINFO);

	// convert to unsigned
	fmt.format = FMOD_SOUND_FORMAT_PCM8; // 8bit
	fmt.length = samples*1; // 1 bps
	fmt.numchannels = 1; // mono
	fmt.defaultfrequency = freq;

	// Make a duplicate of the stream to change format.
	p = Z_Malloc(fmt.length, PU_SOUND, NULL);
	for (i = 0; i < fmt.length; i++)
		p[i] = (UINT8)(stream[i]+0x80); // convert from signed to unsigned
	stream = (char *)p;

	// Create FMOD_SOUND.
	FMR(FMOD_System_CreateSound(fsys, stream, FMOD_CREATESAMPLE|FMOD_OPENMEMORY|FMOD_OPENRAW|FMOD_SOFTWARE|FMOD_LOWMEM, &fmt, &sound));

	Z_Free(stream); // FMOD made its own copy, so we don't need this anymore.
	return sound;
}
Esempio n. 20
0
FMRadioResult FMRadioSetTurnedOn(FMRadio* r, bool on) {
    struct video_audio va;
    if (!FMRadioGetAudioState(r, &va)) // we init from the current state.
        return kFMRadioErrorPOSIX;

    // we mimic the default-setting in fmtools.
    va.balance = kFMRadioDefaultBalance;
    va.audio = 0; // we assume radios only have one channel.

    if (on) {

        va.volume = 1;
        va.flags = 0;
        va.mode = VIDEO_SOUND_STEREO;

    } else {

        va.volume = 0;
        va.flags = VIDEO_AUDIO_MUTE;

    }

    return (ioctl(FMR(r)->FileDescriptor, VIDIOCSAUDIO, &va) >= 0)? kFMRadioNoError : kFMRadioErrorPOSIX;
}
Esempio n. 21
0
FMRadioResult FMRadioGetFrequency(FMRadio* r, uint32_t* khz) {
	*khz = FMR(r)->Frequency;
	return kFMRadioNoError;
}
Esempio n. 22
0
static bool FMRadioGetAudioState(FMRadio* r, struct video_audio* vaRef) {
    return ioctl(FMR(r)->FileDescriptor, VIDIOCGAUDIO, vaRef) >= 0;
}
Esempio n. 23
0
static bool FMRadioGetTuningState(FMRadio* r, struct video_tuner* vtRef) {
    return ioctl(FMR(r)->FileDescriptor, VIDIOCGTUNER, vtRef) >= 0;
}
Esempio n. 24
0
FMRadioResult FMRadioGetTurnedOn(FMRadio* r, bool* on) {
	*on = FMR(r)->On;
	return kFMRadioNoError;
}
Esempio n. 25
0
boolean I_StartDigSong(const char *musicname, boolean looping)
{
	char *data;
	size_t len;
	FMOD_CREATESOUNDEXINFO fmt;
	lumpnum_t lumpnum = W_CheckNumForName(va("O_%s",musicname));

	if (lumpnum == LUMPERROR)
	{
		lumpnum = W_CheckNumForName(va("D_%s",musicname));
		if (lumpnum == LUMPERROR)
			return false;
		midimode = true;
	}
	else
		midimode = false;

	data = (char *)W_CacheLumpNum(lumpnum, PU_MUSIC);
	len = W_LumpLength(lumpnum);

	memset(&fmt, 0, sizeof(FMOD_CREATESOUNDEXINFO));
	fmt.cbsize = sizeof(FMOD_CREATESOUNDEXINFO);

#ifdef HAVE_LIBGME
	if ((UINT8)data[0] == 0x1F
		&& (UINT8)data[1] == 0x8B)
	{
#ifdef HAVE_ZLIB
		UINT8 *inflatedData;
		size_t inflatedLen;
		z_stream stream;
		int zErr; // Somewhere to handle any error messages zlib tosses out

		memset(&stream, 0x00, sizeof (z_stream)); // Init zlib stream
		// Begin the inflation process
		inflatedLen = *(UINT32 *)(data + (len-4)); // Last 4 bytes are the decompressed size, typically
		inflatedData = (UINT8 *)Z_Calloc(inflatedLen, PU_MUSIC, NULL); // Make room for the decompressed data
		stream.total_in = stream.avail_in = len;
		stream.total_out = stream.avail_out = inflatedLen;
		stream.next_in = (UINT8 *)data;
		stream.next_out = inflatedData;

		zErr = inflateInit2(&stream, 32 + MAX_WBITS);
		if (zErr == Z_OK) // We're good to go
		{
			zErr = inflate(&stream, Z_FINISH);
			if (zErr == Z_STREAM_END) {
				// Run GME on new data
				if (!gme_open_data(inflatedData, inflatedLen, &gme, 44100))
				{
					gme_equalizer_t gmeq = {GME_TREBLE, GME_BASS, 0,0,0,0,0,0,0,0};
					Z_Free(inflatedData); // GME supposedly makes a copy for itself, so we don't need this lying around
					Z_Free(data); // We don't need this, either.
					gme_start_track(gme, 0);
					current_track = 0;
					gme_set_equalizer(gme,&gmeq);
					fmt.format = FMOD_SOUND_FORMAT_PCM16;
					fmt.defaultfrequency = 44100;
					fmt.numchannels = 2;
					fmt.length = -1;
					fmt.decodebuffersize = (44100 * 2) / 35;
					fmt.pcmreadcallback = GMEReadCallback;
					fmt.userdata = gme;
					FMR(FMOD_System_CreateStream(fsys, NULL, FMOD_OPENUSER | (looping ? FMOD_LOOP_NORMAL : 0), &fmt, &music_stream));
					FMR(FMOD_System_PlaySound(fsys, FMOD_CHANNEL_FREE, music_stream, false, &music_channel));
					FMR(FMOD_Channel_SetVolume(music_channel, music_volume / 31.0));
					FMR(FMOD_Channel_SetPriority(music_channel, 0));
					return true;
				}
			}
			else
			{
				const char *errorType;
				switch (zErr)
				{
					case Z_ERRNO:
						errorType = "Z_ERRNO"; break;
					case Z_STREAM_ERROR:
						errorType = "Z_STREAM_ERROR"; break;
					case Z_DATA_ERROR:
						errorType = "Z_DATA_ERROR"; break;
					case Z_MEM_ERROR:
						errorType = "Z_MEM_ERROR"; break;
					case Z_BUF_ERROR:
						errorType = "Z_BUF_ERROR"; break;
					case Z_VERSION_ERROR:
						errorType = "Z_VERSION_ERROR"; break;
					default:
						errorType = "unknown error";
				}
				CONS_Alert(CONS_ERROR,"Encountered %s when running inflate: %s\n", errorType, stream.msg);
			}
			(void)inflateEnd(&stream);
		}
		else // Hold up, zlib's got a problem
		{
			const char *errorType;
			switch (zErr)
			{
				case Z_ERRNO:
					errorType = "Z_ERRNO"; break;
				case Z_STREAM_ERROR:
					errorType = "Z_STREAM_ERROR"; break;
				case Z_DATA_ERROR:
					errorType = "Z_DATA_ERROR"; break;
				case Z_MEM_ERROR:
					errorType = "Z_MEM_ERROR"; break;
				case Z_BUF_ERROR:
					errorType = "Z_BUF_ERROR"; break;
				case Z_VERSION_ERROR:
					errorType = "Z_VERSION_ERROR"; break;
				default:
					errorType = "unknown error";
			}
			CONS_Alert(CONS_ERROR,"Encountered %s when running inflateInit: %s\n", errorType, stream.msg);
		}
		Z_Free(inflatedData); // GME didn't open jack, but don't let that stop us from freeing this up
#else
		//CONS_Alert(CONS_ERROR,"Cannot decompress VGZ; no zlib support\n");
#endif
	}
	else if (!gme_open_data(data, len, &gme, 44100))
	{
		gme_equalizer_t gmeq = {GME_TREBLE, GME_BASS, 0,0,0,0,0,0,0,0};
		Z_Free(data); // We don't need this anymore.
		gme_start_track(gme, 0);
		current_track = 0;
		gme_set_equalizer(gme,&gmeq);
		fmt.format = FMOD_SOUND_FORMAT_PCM16;
		fmt.defaultfrequency = 44100;
		fmt.numchannels = 2;
		fmt.length = -1;
		fmt.decodebuffersize = (44100 * 2) / 35;
		fmt.pcmreadcallback = GMEReadCallback;
		fmt.userdata = gme;
		FMR(FMOD_System_CreateStream(fsys, NULL, FMOD_OPENUSER | (looping ? FMOD_LOOP_NORMAL : 0), &fmt, &music_stream));
		FMR(FMOD_System_PlaySound(fsys, FMOD_CHANNEL_FREE, music_stream, false, &music_channel));
		FMR(FMOD_Channel_SetVolume(music_channel, music_volume / 31.0));
		FMR(FMOD_Channel_SetPriority(music_channel, 0));
		return true;
	}
#endif

	fmt.length = len;
	{
		FMOD_RESULT e = FMOD_System_CreateStream(fsys, data, FMOD_OPENMEMORY_POINT|(looping ? FMOD_LOOP_NORMAL : 0), &fmt, &music_stream);
		if (e != FMOD_OK)
		{
			if (e == FMOD_ERR_FORMAT)
				CONS_Alert(CONS_WARNING, "Failed to play music lump %s due to invalid format.\n", W_CheckNameForNum(lumpnum));
			else
				FMR(e);
			return false;
		}
	}
	FMR(FMOD_System_PlaySound(fsys, FMOD_CHANNEL_FREE, music_stream, false, &music_channel));
	if (midimode)
		FMR(FMOD_Channel_SetVolume(music_channel, midi_volume / 31.0));
	else
		FMR(FMOD_Channel_SetVolume(music_channel, music_volume / 31.0));
	FMR(FMOD_Channel_SetPriority(music_channel, 0));
	current_track = 0;

	// Try to find a loop point in streaming music formats (ogg, mp3)
	if (looping)
	{
		FMOD_RESULT e;
		FMOD_TAG tag;
		unsigned int loopstart, loopend;

		// A proper LOOPPOINT is its own tag, stupid.
		e = FMOD_Sound_GetTag(music_stream, "LOOPPOINT", 0, &tag);
		if (e != FMOD_ERR_TAGNOTFOUND)
		{
			FMR(e);
			loopstart = atoi((char *)tag.data); // assumed to be a string data tag.
			FMR(FMOD_Sound_GetLoopPoints(music_stream, NULL, FMOD_TIMEUNIT_PCM, &loopend, FMOD_TIMEUNIT_PCM));
			if (loopstart > 0)
				FMR(FMOD_Sound_SetLoopPoints(music_stream, loopstart, FMOD_TIMEUNIT_PCM, loopend, FMOD_TIMEUNIT_PCM));
			return true;
		}

		// Use LOOPMS for time in miliseconds.
		e = FMOD_Sound_GetTag(music_stream, "LOOPMS", 0, &tag);
		if (e != FMOD_ERR_TAGNOTFOUND)
		{
			FMR(e);
			loopstart = atoi((char *)tag.data); // assumed to be a string data tag.
			FMR(FMOD_Sound_GetLoopPoints(music_stream, NULL, FMOD_TIMEUNIT_MS, &loopend, FMOD_TIMEUNIT_PCM));
			if (loopstart > 0)
				FMR(FMOD_Sound_SetLoopPoints(music_stream, loopstart, FMOD_TIMEUNIT_MS, loopend, FMOD_TIMEUNIT_PCM));
			return true;
		}

		// Try to fetch it from the COMMENT tag, like A.J. Freda
		e = FMOD_Sound_GetTag(music_stream, "COMMENT", 0, &tag);
		if (e != FMOD_ERR_TAGNOTFOUND)
		{
			char *loopText;
			// Handle any errors that arose, first
			FMR(e);
			// Figure out where the number starts
			loopText = strstr((char *)tag.data,"LOOPPOINT=");
			if (loopText != NULL)
			{
				// Skip the "LOOPPOINT=" part.
				loopText += 10;
				// Convert it to our looppoint
				// FMOD seems to ensure the tag is properly NULL-terminated.
				// atoi will stop when it reaches anything that's not a number.
				loopstart = atoi(loopText);
				// Now do the rest like above
				FMR(FMOD_Sound_GetLoopPoints(music_stream, NULL, FMOD_TIMEUNIT_PCM, &loopend, FMOD_TIMEUNIT_PCM));
				if (loopstart > 0)
					FMR(FMOD_Sound_SetLoopPoints(music_stream, loopstart, FMOD_TIMEUNIT_PCM, loopend, FMOD_TIMEUNIT_PCM));
			}
			return true;
		}
	}

	// No special loop point, but we're playing so it's all good.
	return true;
}
Esempio n. 26
0
void *I_GetSfx(sfxinfo_t *sfx)
{
	FMOD_SOUND *sound;
	char *lump;
	FMOD_CREATESOUNDEXINFO fmt;
#ifdef HAVE_LIBGME
	Music_Emu *emu;
	gme_info_t *info;
#endif

	if (sfx->lumpnum == LUMPERROR)
		sfx->lumpnum = S_GetSfxLumpNum(sfx);
	sfx->length = W_LumpLength(sfx->lumpnum);

	lump = W_CacheLumpNum(sfx->lumpnum, PU_SOUND);
	sound = ds2fmod(lump);
	if (sound)
	{
		Z_Free(lump);
		return sound;
	}

	// It's not a doom sound.
	// Try to read it as an FMOD sound?

	memset(&fmt, 0, sizeof(FMOD_CREATESOUNDEXINFO));
	fmt.cbsize = sizeof(FMOD_CREATESOUNDEXINFO);
	fmt.length = sfx->length;

#ifdef HAVE_LIBGME
	// VGZ format
	if ((UINT8)lump[0] == 0x1F
		&& (UINT8)lump[1] == 0x8B)
	{
#ifdef HAVE_ZLIB
		UINT8 *inflatedData;
		size_t inflatedLen;
		z_stream stream;
		int zErr; // Somewhere to handle any error messages zlib tosses out

		memset(&stream, 0x00, sizeof (z_stream)); // Init zlib stream
		// Begin the inflation process
		inflatedLen = *(UINT32 *)(lump + (sfx->length-4)); // Last 4 bytes are the decompressed size, typically
		inflatedData = (UINT8 *)Z_Malloc(inflatedLen, PU_SOUND, NULL); // Make room for the decompressed data
		stream.total_in = stream.avail_in = sfx->length;
		stream.total_out = stream.avail_out = inflatedLen;
		stream.next_in = (UINT8 *)lump;
		stream.next_out = inflatedData;

		zErr = inflateInit2(&stream, 32 + MAX_WBITS);
		if (zErr == Z_OK) // We're good to go
		{
			zErr = inflate(&stream, Z_FINISH);
			if (zErr == Z_STREAM_END) {
				// Run GME on new data
				if (!gme_open_data(inflatedData, inflatedLen, &emu, 44100))
				{
					Z_Free(inflatedData); // GME supposedly makes a copy for itself, so we don't need this lying around
					Z_Free(lump); // We're done with the uninflated lump now, too.

					gme_start_track(emu, 0);
					gme_track_info(emu, &info, 0);

					fmt.format = FMOD_SOUND_FORMAT_PCM16;
					fmt.defaultfrequency = 44100;
					fmt.numchannels = 2;
					fmt.length = ((UINT32)info->play_length * 441 / 10) * 4;
					fmt.decodebuffersize = (44100 * 2) / 35;
					fmt.pcmreadcallback = GMEReadCallback;
					fmt.userdata = emu;

					FMR(FMOD_System_CreateSound(fsys, NULL, FMOD_CREATESAMPLE|FMOD_OPENUSER|FMOD_SOFTWARE|FMOD_LOWMEM, &fmt, &sound));
					return sound;
				}
			}
			else
			{
				const char *errorType;
				switch (zErr)
				{
					case Z_ERRNO:
						errorType = "Z_ERRNO"; break;
					case Z_STREAM_ERROR:
						errorType = "Z_STREAM_ERROR"; break;
					case Z_DATA_ERROR:
						errorType = "Z_DATA_ERROR"; break;
					case Z_MEM_ERROR:
						errorType = "Z_MEM_ERROR"; break;
					case Z_BUF_ERROR:
						errorType = "Z_BUF_ERROR"; break;
					case Z_VERSION_ERROR:
						errorType = "Z_VERSION_ERROR"; break;
					default:
						errorType = "unknown error";
				}
				CONS_Alert(CONS_ERROR,"Encountered %s when running inflate: %s\n", errorType, stream.msg);
			}
			(void)inflateEnd(&stream);
		}
		else // Hold up, zlib's got a problem
		{
			const char *errorType;
			switch (zErr)
			{
				case Z_ERRNO:
					errorType = "Z_ERRNO"; break;
				case Z_STREAM_ERROR:
					errorType = "Z_STREAM_ERROR"; break;
				case Z_DATA_ERROR:
					errorType = "Z_DATA_ERROR"; break;
				case Z_MEM_ERROR:
					errorType = "Z_MEM_ERROR"; break;
				case Z_BUF_ERROR:
					errorType = "Z_BUF_ERROR"; break;
				case Z_VERSION_ERROR:
					errorType = "Z_VERSION_ERROR"; break;
				default:
					errorType = "unknown error";
			}
			CONS_Alert(CONS_ERROR,"Encountered %s when running inflateInit: %s\n", errorType, stream.msg);
		}
		Z_Free(inflatedData); // GME didn't open jack, but don't let that stop us from freeing this up
#else
		//CONS_Alert(CONS_ERROR,"Cannot decompress VGZ; no zlib support\n");
#endif
	}
	// Try to read it as a GME sound
	else if (!gme_open_data(lump, sfx->length, &emu, 44100))
	{
		Z_Free(lump);

		gme_start_track(emu, 0);
		gme_track_info(emu, &info, 0);

		fmt.format = FMOD_SOUND_FORMAT_PCM16;
		fmt.defaultfrequency = 44100;
		fmt.numchannels = 2;
		fmt.length = ((UINT32)info->play_length * 441 / 10) * 4;
		fmt.decodebuffersize = (44100 * 2) / 35;
		fmt.pcmreadcallback = GMEReadCallback;
		fmt.userdata = emu;

		gme_free_info(info);

		FMR(FMOD_System_CreateSound(fsys, NULL, FMOD_CREATESAMPLE|FMOD_OPENUSER|FMOD_SOFTWARE|FMOD_LOWMEM, &fmt, &sound));
		return sound;
	}
#endif

	// Ogg, Mod, Midi, etc.
	FMR(FMOD_System_CreateSound(fsys, lump, FMOD_CREATESAMPLE|FMOD_OPENMEMORY|FMOD_SOFTWARE|FMOD_LOWMEM, &fmt, &sound));
	Z_Free(lump); // We're done with the lump now, at least.
	return sound;
}
Esempio n. 27
0
FMRadioResult FMRadioSetVolume(FMRadio* r, uint16_t volume) {
	FMLog("Set radio volume to %d", (int) volume);
	FMR(r)->Volume = volume;
	return kFMRadioNoError;
}
Esempio n. 28
0
void I_UpdateSound(void)
{
	FMR(FMOD_System_Update(fsys));
}
Esempio n. 29
0
FMRadioResult FMRadioGetVolume(FMRadio* r, uint16_t* volume) {
	*volume = FMR(r)->Volume;
	return kFMRadioNoError;
}