From ced8100a2c03de2a8792a35e9c5ce31c5c000a82 Mon Sep 17 00:00:00 2001 From: atsb <44937323+atsb@users.noreply.github.com> Date: Tue, 13 Jun 2023 15:51:15 +0200 Subject: [PATCH] Fixes 1. Fixes for stuttering and reverting some GL changes that caused it 2. Added back a callback to SDL2 but implemented error handling for fluidsynth to prevent crashes 3. Fixed the 'moving too fast skips linedefs' bug, by adding a MS delay upon activation (100ms) --- src/engine/gl_main.c | 2 +- src/engine/i_audio.c | 212 +++++++++++++++++++++---------------------- src/engine/p_spec.c | 33 ++++++- 3 files changed, 130 insertions(+), 117 deletions(-) diff --git a/src/engine/gl_main.c b/src/engine/gl_main.c index db00a92c..9653b064 100644 --- a/src/engine/gl_main.c +++ b/src/engine/gl_main.c @@ -607,7 +607,7 @@ static void SetVsyncActive(void) { if (v_vsync.value > 0) { - SDL_GL_SetSwapInterval(-1); + SDL_GL_SetSwapInterval(1); } #if defined(__APPLE__) if (v_vsync.value > 0) diff --git a/src/engine/i_audio.c b/src/engine/i_audio.c index bb04bf77..b9783b59 100644 --- a/src/engine/i_audio.c +++ b/src/engine/i_audio.c @@ -1,4 +1,4 @@ -// Emacs style mode select -*- C++ -*- +// Emacs style mode select -*- C -*- //----------------------------------------------------------------------------- // // Copyright(C) 2007-2012 Samuel Villarreal @@ -57,50 +57,6 @@ // 20120203 villsa - cvar for soundfont location CVAR(s_soundfont, doomsnd.sf2); -// 20120203 villsa - cvar for audio driver -#ifdef _WIN32 -CVAR_CMD(s_driver, dsound) -#elif __linux__ -CVAR_CMD(s_driver, alsa) -#elif __APPLE__ -CVAR_CMD(s_driver, coreaudio) -#else -CVAR_CMD(s_driver, sndio) -#endif -{ - char* driver = cvar->string; - - // this is absolutely horrible - if (!dstrcmp(cvar->defvalue, "default")) { - cvar->defvalue = DEFAULT_FLUID_DRIVER; - } - - // same as above - if (!dstrcmp(driver, "default")) { - CON_CvarSet(cvar->name, DEFAULT_FLUID_DRIVER); - return; - } - - if (!dstrcmp(driver, "jack") || - !dstrcmp(driver, "alsa") || - !dstrcmp(driver, "oss") || - !dstrcmp(driver, "alsa") || - !dstrcmp(driver, "coreaudio") || - !dstrcmp(driver, "dsound") || - !dstrcmp(driver, "portaudio") || - !dstrcmp(driver, "sndio") || - !dstrcmp(driver, "sndman") || - !dstrcmp(driver, "dart") || - !dstrcmp(driver, "file") - ) { - return; - } - - CON_Warnf("Invalid driver name\n"); - CON_Warnf("Valid driver names: jack, alsa, oss, pulseaudio, coreaudio, dsound, portaudio, sndio, sndman, dart, file\n"); - CON_CvarSet(cvar->name, DEFAULT_FLUID_DRIVER); -} - // // Mutex // @@ -117,18 +73,26 @@ static SDL_sem* semaphore = NULL; #define SEMAPHORE_UNLOCK() SDL_SemPost(semaphore); } // 20120205 villsa - bool to determine if sequencer is ready or not -static int seqready = 0; +static boolean seqready = false; // // DEFINES // -#define MIDI_CHANNELS 240 +#define MIDI_CHANNELS 128 #define MIDI_MESSAGE 0x07 #define MIDI_END 0x2f #define MIDI_SET_TEMPO 0x51 #define MIDI_SEQUENCER 0x7f +#define SAMPLE_RATE 44100 +#define SAMPLE_SIZE 2 //4: Float Buffer 2: Signed Int Buffer +#define NUM_FRAMES SAMPLE_RATE +#define SAMPLES 4096 +#define NUM_CHANNELS 2 +#define NUM_SAMPLES (NUM_FRAMES * NUM_CHANNELS) +#define TIME_INTERVAL 1000000 //1500000:duration us + // // MIDI DATA DEFINITIONS // @@ -150,9 +114,9 @@ typedef struct { word ntracks; word delta; byte* data; - int length; + int length; track_t* tracks; - int tempo; + int tempo; double timediv; } song_t; @@ -201,18 +165,18 @@ typedef struct { byte velocity; byte* pos; byte* jump; - int tics; - int nexttic; - int lasttic; - int starttic; - Uint32 starttime; - Uint32 curtime; + int tics; + int nexttic; + int lasttic; + int starttic; + unsigned int starttime; + unsigned int curtime; chanstate_e state; - int paused; + boolean paused; // read by audio thread but only // modified by game code - int stop; + boolean stop; float basevol; } channel_t; @@ -228,7 +192,8 @@ static channel_t playlist[MIDI_CHANNELS]; // channels active in sequencer // by the audio thread. // -typedef enum { +typedef int seqsignal_e; +enum { SEQ_SIGNAL_IDLE = 0, // idles. does nothing SEQ_SIGNAL_SHUTDOWN, // signal the sequencer to shutdown, cleaning up anything in the process SEQ_SIGNAL_READY, // sequencer will read and play any midi track fed to it @@ -238,7 +203,7 @@ typedef enum { SEQ_SIGNAL_STOPALL, SEQ_SIGNAL_SETGAIN, // signal the sequencer to update output gain MAXSIGNALTYPES -} seqsignal_e; +}; typedef union { sndsrc_t* valsrc; @@ -283,6 +248,20 @@ static doomseq_t doomseq = { 0 }; // doom sequencer typedef void(*eventhandler)(doomseq_t*, channel_t*); typedef int(*signalhandler)(doomseq_t*); +// +// Audio_Play +// +// Callback for SDL +// +void Audio_Play(void* userdata, Uint8* stream, int len) +{ + fluid_synth_t* synth = (fluid_synth_t*)userdata; + if (fluid_synth_write_s16(synth, len / (2 * sizeof(short)), (short*)stream, 0, NUM_CHANNELS, (short*)stream, 1, NUM_CHANNELS) != FLUID_OK) { + I_Printf("ERROR: Writing audio with fluid_synth_write_s16 failed!\n"); + } +} + + // // Seq_SetGain // @@ -294,11 +273,24 @@ static void Seq_SetGain(doomseq_t* seq) { fluid_synth_set_gain(seq->synth, seq->gain); } +// +// Seq_SetReverb +// + +static void Seq_SetReverb(doomseq_t* seq, + float size, + float damp, + float width, + float level) { + fluid_synth_set_reverb(seq->synth, size, damp, width, level); + fluid_synth_set_reverb_on(seq->synth, 1); +} + // // Seq_SetConfig // -static void Seq_SetConfig(doomseq_t* seq, char* setting, int value) { +static void Seq_SetConfig(doomseq_t* seq, const char* setting, int value) { fluid_settings_setint(seq->settings, setting, value); } @@ -320,19 +312,6 @@ static void Seq_SetStatus(doomseq_t* seq, int status) { MUTEX_UNLOCK() } -// -// Seq_WaitOnSignal -// - -/*static void Seq_WaitOnSignal(doomseq_t* seq) -{ - while(1) - { - if(seq->signal == SEQ_SIGNAL_READY) - break; - } -}*/ - // // Chan_SetMusicVolume // @@ -384,7 +363,7 @@ static byte Chan_GetNextMidiByte(channel_t* chan) { // Checks if the midi reader has reached the end // -static int Chan_CheckTrackEnd(channel_t* chan) { +static boolean Chan_CheckTrackEnd(channel_t* chan) { return ((int)(chan->pos - chan->song->data) >= chan->song->length); } @@ -460,7 +439,7 @@ static void Song_ClearPlaylist(void) { // Chan_RemoveTrackFromPlaylist // -static int Chan_RemoveTrackFromPlaylist(doomseq_t* seq, channel_t* chan) { +static boolean Chan_RemoveTrackFromPlaylist(doomseq_t* seq, channel_t* chan) { if (!chan->song || !chan->track) { return false; } @@ -498,13 +477,12 @@ static int Chan_RemoveTrackFromPlaylist(doomseq_t* seq, channel_t* chan) { // // Add a song to the playlist for the sequencer to play. // Sets any default values to the channel in the process -// Both start sound and start music refer to this +// static channel_t* Song_AddTrackToPlaylist(doomseq_t* seq, song_t* song, track_t* track) { int i; for (i = 0; i < MIDI_CHANNELS; i++) { - if (playlist[i].song == NULL) { playlist[i].song = song; playlist[i].track = track; @@ -779,6 +757,11 @@ static int Signal_Pause(doomseq_t* seq) { SEMAPHORE_LOCK() for (i = 0; i < MIDI_CHANNELS; i++) { c = &playlist[i]; + + if (c->song && !c->paused) { + c->paused = true; + Chan_StopTrack(seq, c); + } } SEMAPHORE_UNLOCK() @@ -799,6 +782,11 @@ static int Signal_Resume(doomseq_t* seq) { SEMAPHORE_LOCK() for (i = 0; i < MIDI_CHANNELS; i++) { c = &playlist[i]; + + if (c->song && c->paused) { + c->paused = false; + fluid_synth_noteon(seq->synth, c->track->channel, c->key, c->velocity); + } } SEMAPHORE_UNLOCK() @@ -836,7 +824,7 @@ static const signalhandler seqsignallist[MAXSIGNALTYPES] = { // Chan_CheckState // -static int Chan_CheckState(doomseq_t* seq, channel_t* chan) { +static boolean Chan_CheckState(doomseq_t* seq, channel_t* chan) { if (chan->state == CHAN_STATE_ENDED) { return true; } @@ -991,7 +979,7 @@ static void Seq_RunSong(doomseq_t* seq, int msecs) { // Allocate data for all tracks for a midi song // -static int Song_RegisterTracks(song_t* song) { +static boolean Song_RegisterTracks(song_t* song) { int i; byte* data; @@ -1023,7 +1011,7 @@ static int Song_RegisterTracks(song_t* song) { // Allocate data for all midi songs // -static int Seq_RegisterSongs(doomseq_t* seq) { +static boolean Seq_RegisterSongs(doomseq_t* seq) { int i; int start; int end; @@ -1088,17 +1076,17 @@ static int Seq_RegisterSongs(doomseq_t* seq) { // Seq_Shutdown // -static void Seq_Shutdown(doomseq_t* seq) { +static void Seq_Shutdown(doomseq_t* seq) +{ +#ifndef _WIN32 + // Close SDL Audio Device + SDL_CloseAudioDevice(1); +#else // // signal the sequencer to shut down // Seq_SetStatus(seq, SEQ_SIGNAL_SHUTDOWN); -#ifdef _WIN32 - // - // Screw the shutdown, the OS will handle it :P - // -#else // // wait until the audio thread is finished // @@ -1107,7 +1095,7 @@ static void Seq_Shutdown(doomseq_t* seq) { // // fluidsynth cleanup stuff // - delete_fluid_audio_driver(seq->driver); + SDL_CloseAudioDevice(1); delete_fluid_synth(seq->synth); delete_fluid_settings(seq->settings); @@ -1125,10 +1113,10 @@ static void Seq_Shutdown(doomseq_t* seq) { static int SDLCALL Thread_PlayerHandler(void* param) { doomseq_t* seq = (doomseq_t*)param; - long long start = SDL_GetTicks(); - long long delay = 0; + long start = SDL_GetTicks(); + long delay = 0; int status; - long long count = 0; + int count = 0; signalhandler signal; while (1) { @@ -1174,7 +1162,7 @@ static int SDLCALL Thread_PlayerHandler(void* param) { // void I_InitSequencer(void) { - int sffound; + boolean sffound; char* sfpath; CON_DPrintf("--------Initializing Software Synthesizer--------\n"); @@ -1223,13 +1211,6 @@ void I_InitSequencer(void) { Seq_SetConfig(&doomseq, "synth.midi-channels", 0x10 + MIDI_CHANNELS); Seq_SetConfig(&doomseq, "synth.polyphony", 128); // [Immorpher] high polyphony slows down the game - - // 20120105 bkw: On Linux, always use alsa (fluidsynth default is to use - // JACK, if it's compiled in. We don't want to start jackd for a game). - fluid_settings_setstr(doomseq.settings, "audio.driver", s_driver.string); - - CON_DPrintf("Audio driver: %s\n", s_driver.string); - // // init synth // @@ -1239,15 +1220,6 @@ void I_InitSequencer(void) { return; } - // - // init audio driver - // - doomseq.driver = new_fluid_audio_driver(doomseq.settings, doomseq.synth); - if (doomseq.driver == NULL) { - CON_Warnf("I_InitSequencer: failed to create audio driver"); - return; - } - // // load soundfont // @@ -1284,6 +1256,7 @@ void I_InitSequencer(void) { Seq_SetStatus(&doomseq, SEQ_SIGNAL_READY); Seq_SetGain(&doomseq); + Seq_SetReverb(&doomseq, 0.65f, 0.0f, 2.0f, 1.0f); // // if something went terribly wrong, then shutdown everything @@ -1305,6 +1278,25 @@ void I_InitSequencer(void) { Song_ClearPlaylist(); + if (SDL_Init(SDL_INIT_AUDIO | SDL_INIT_TIMER)) { + printf("Could not initialize SDL - %s\n", SDL_GetError()); + } + + SDL_AudioDeviceID audio_device; + SDL_AudioSpec required_spec; + SDL_memset(&required_spec, 0, sizeof(required_spec)); + required_spec.format = AUDIO_S16; + required_spec.freq = SAMPLE_RATE; + required_spec.samples = SAMPLES; + required_spec.channels = NUM_CHANNELS; + required_spec.callback = Audio_Play; + required_spec.userdata = doomseq.synth; + audio_device = SDL_OpenAudioDevice(NULL, 0, &required_spec, NULL, 0); + + SDL_Delay(1); + + SDL_PauseAudioDevice(audio_device, SDL_FALSE); + // 20120205 villsa - sequencer is now ready seqready = true; } @@ -1359,7 +1351,7 @@ void I_UpdateChannel(int c, int volume, int pan) { // // I_ShutdownSound -// Shutdown sound when player exits the game / error occurs +// void I_ShutdownSound(void) { if (doomseq.synth) { @@ -1388,14 +1380,12 @@ void I_SetSoundVolume(float volume) { // void I_ResetSound(void) { - if (!seqready) { return; } Seq_SetStatus(&doomseq, SEQ_SIGNAL_RESET); //Seq_WaitOnSignal(&doomseq); - } // @@ -1533,4 +1523,4 @@ void I_StartSound(int sfx_id, sndsrc_t* origin, int volume, int pan, int reverb) for (i = 16; i < MIDI_CHANNELS + 15; i++) { fluid_synth_set_interp_method(doomseq.synth, i, FLUID_INTERP_LINEAR); } -} +} \ No newline at end of file diff --git a/src/engine/p_spec.c b/src/engine/p_spec.c index 27ca6f9c..61970e0b 100644 --- a/src/engine/p_spec.c +++ b/src/engine/p_spec.c @@ -55,6 +55,12 @@ #include "sc_main.h" #include "p_setup.h" +#ifdef __OpenBSD__ +#include +#else +#include +#endif + short globalint = 0; static byte tryopentype[3]; @@ -1668,15 +1674,32 @@ int P_DoSpecialLine(mobj_t* thing, line_t* line, int side) { // P_InitSpecialLine // +// Constant for the minimum delay between triggering the same line (in ms) +#define MIN_SPECIAL_LINE_DELAY 100 + boolean P_InitSpecialLine(mobj_t* thing, line_t* line, int side) { + static unsigned int lastTriggerTime = 0; + int ok = 0; int use = line->special & MLU_REPEAT; - if (line->special & MLU_MACRO) { - ok = P_StartMacro(thing, line); - } - else { - ok = P_DoSpecialLine(thing, line, side); + // Calculate the time difference since the last trigger + unsigned int currentTime = SDL_GetTicks(); + unsigned int timeDifference = currentTime - lastTriggerTime; + + // Check if enough time has passed since the last trigger + if (timeDifference >= MIN_SPECIAL_LINE_DELAY) { + if (line->special & MLU_MACRO) { + ok = P_StartMacro(thing, line); + } + else { + ok = P_DoSpecialLine(thing, line, side); + } + + if (ok) { + // Update the last trigger time + lastTriggerTime = currentTime; + } } if (!ok) {