// 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; }
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)); }
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; }
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; }
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; }
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; }
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; }
void I_UnRegisterSong(INT32 handle) { UNREFERENCED_PARAMETER(handle); if (music_stream) FMR(FMOD_Sound_Release(music_stream)); music_stream = NULL; }
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; }
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; }
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; }
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; }
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)); }
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; }
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; }
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; }
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; }
// 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) }
// 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; }
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; }
FMRadioResult FMRadioGetFrequency(FMRadio* r, uint32_t* khz) { *khz = FMR(r)->Frequency; return kFMRadioNoError; }
static bool FMRadioGetAudioState(FMRadio* r, struct video_audio* vaRef) { return ioctl(FMR(r)->FileDescriptor, VIDIOCGAUDIO, vaRef) >= 0; }
static bool FMRadioGetTuningState(FMRadio* r, struct video_tuner* vtRef) { return ioctl(FMR(r)->FileDescriptor, VIDIOCGTUNER, vtRef) >= 0; }
FMRadioResult FMRadioGetTurnedOn(FMRadio* r, bool* on) { *on = FMR(r)->On; return kFMRadioNoError; }
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; }
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; }
FMRadioResult FMRadioSetVolume(FMRadio* r, uint16_t volume) { FMLog("Set radio volume to %d", (int) volume); FMR(r)->Volume = volume; return kFMRadioNoError; }
void I_UpdateSound(void) { FMR(FMOD_System_Update(fsys)); }
FMRadioResult FMRadioGetVolume(FMRadio* r, uint16_t* volume) { *volume = FMR(r)->Volume; return kFMRadioNoError; }