diff --git a/src/sound/i_music.cpp b/src/sound/i_music.cpp
index 342fc5bf6..fce71efbe 100644
--- a/src/sound/i_music.cpp
+++ b/src/sound/i_music.cpp
@@ -181,7 +181,11 @@ void I_ShutdownMusic(bool onexit)
 		assert (currSong == NULL);
 	}
 	Timidity::FreeAll();
-	if (onexit) WildMidi_Shutdown();
+	if (onexit)
+	{
+		WildMidi_Shutdown();
+		TimidityPP_Shutdown();
+	}
 }
 
 void I_ShutdownMusicExit()
diff --git a/src/sound/i_musicinterns.h b/src/sound/i_musicinterns.h
index 4c796ead5..95ce0e876 100644
--- a/src/sound/i_musicinterns.h
+++ b/src/sound/i_musicinterns.h
@@ -92,6 +92,7 @@ MIDIDevice *CreateWinMIDIDevice(int mididevice);
 MIDIDevice *CreateAudioToolboxMIDIDevice();
 #endif
 MIDIDevice *CreateTimidityPPMIDIDevice(const char *args);
+void TimidityPP_Shutdown();
 
 // Base class for pseudo-MIDI devices ---------------------------------------
 
diff --git a/src/sound/mididevices/music_timiditypp_mididevice.cpp b/src/sound/mididevices/music_timiditypp_mididevice.cpp
index bd9fd3175..ba9444a35 100644
--- a/src/sound/mididevices/music_timiditypp_mididevice.cpp
+++ b/src/sound/mididevices/music_timiditypp_mididevice.cpp
@@ -45,6 +45,7 @@
 #include "tmpfileplus.h"
 #include "m_misc.h"
 #include "v_text.h"
+#include "i_system.h"
 
 #include "timiditypp/timidity.h"
 #include "timiditypp/instrum.h"
@@ -64,6 +65,11 @@ public:
 	int GetDeviceType() const override { return MDEV_TIMIDITY; }
 	bool Preprocess(MIDIStreamer *song, bool looping);
 	void TimidityVolumeChanged();
+	static void ClearInstruments()
+	{
+		if (instruments != nullptr) delete instruments;
+		instruments = nullptr;
+	}
 
 protected:
 	TimidityPlus::Player *Renderer;
@@ -132,13 +138,10 @@ TimidityPPMIDIDevice::TimidityPPMIDIDevice(const char *args)
 TimidityPPMIDIDevice::~TimidityPPMIDIDevice ()
 {
 	Close();
-	/*
 	if (Renderer != nullptr)
 	{
 		delete Renderer;
 	}
-	*/
-
 }
 
 //==========================================================================
@@ -176,7 +179,7 @@ int TimidityPPMIDIDevice::Open(MidiCallback callback, void *userdata)
 	int ret = OpenStream(2, 0, callback, userdata);
 	if (ret == 0)
 	{
-		//Renderer->Reset();
+		//Renderer->playmidi_stream_init();
 	}
 	return ret;
 }
@@ -192,13 +195,9 @@ int TimidityPPMIDIDevice::Open(MidiCallback callback, void *userdata)
 //
 //==========================================================================
 
-void TimidityPPMIDIDevice::PrecacheInstruments(const uint16_t *instruments, int count)
+void TimidityPPMIDIDevice::PrecacheInstruments(const uint16_t *instrumentlist, int count)
 {
-	for (int i = 0; i < count; ++i)
-	{
-		//Renderer->MarkInstrument((instruments[i] >> 7) & 127, instruments[i] >> 14, instruments[i] & 127);
-	}
-	//Renderer->load_missing_instruments();
+	instruments->PrecacheInstruments(instrumentlist, count);
 }
 
 //==========================================================================
@@ -231,10 +230,9 @@ void TimidityPPMIDIDevice::HandleLongEvent(const uint8_t *data, int len)
 
 void TimidityPPMIDIDevice::ComputeOutput(float *buffer, int len)
 {
-	TimidityPlus::run_midi(len / 8); // bytes to samples
+	Renderer->run_midi(len);
 	memset(buffer, len, 0);	// to do
-
-	//Renderer->ComputeOutput(buffer, len);
+	Renderer->get_output(buffer, len);
 }
 
 //==========================================================================
@@ -257,6 +255,11 @@ MIDIDevice *CreateTimidityPPMIDIDevice(const char *args)
 	return new TimidityPPMIDIDevice(args);
 }
 
+void TimidityPP_Shutdown()
+{
+	TimidityPPMIDIDevice::ClearInstruments();
+}
+
 
 void TimidityPlus::ctl_cmsg(int type, int verbosity_level, const char *fmt, ...)
 {
diff --git a/src/sound/timiditypp/effect.cpp b/src/sound/timiditypp/effect.cpp
index 6eb8f2260..c76d99c7e 100644
--- a/src/sound/timiditypp/effect.cpp
+++ b/src/sound/timiditypp/effect.cpp
@@ -73,10 +73,10 @@ void Effect::effect_left_right_delay(int32_t *buff, int32_t count)
 		return;
 	if (backoff > count)
 		backoff = count;
-	if (count < audio_buffer_size * 2)
+	if (count < AUDIO_BUFFER_SIZE * 2)
 	{
-		memset(buff + count, 0, 4 * (audio_buffer_size * 2 - count));
-		count = audio_buffer_size * 2;
+		memset(buff + count, 0, 4 * (AUDIO_BUFFER_SIZE * 2 - count));
+		count = AUDIO_BUFFER_SIZE * 2;
 	}
 	memcpy(save, buff, 4 * count);
 	pi = count - backoff;
diff --git a/src/sound/timiditypp/output.h b/src/sound/timiditypp/output.h
index edbbf9b02..804f8745f 100644
--- a/src/sound/timiditypp/output.h
+++ b/src/sound/timiditypp/output.h
@@ -76,8 +76,6 @@ struct PlayMode {
 };
 
 extern PlayMode *play_mode_list[], *play_mode;
-extern int audio_buffer_bits;
-#define audio_buffer_size	(1<<audio_buffer_bits)
 
 /* 16-bit */
 extern void s32tos16(int32_t *lp, int32_t c);
diff --git a/src/sound/timiditypp/playmidi.cpp b/src/sound/timiditypp/playmidi.cpp
index bdb3d8367..9ccdc9f43 100644
--- a/src/sound/timiditypp/playmidi.cpp
+++ b/src/sound/timiditypp/playmidi.cpp
@@ -37,6 +37,7 @@
 #include "quantity.h"
 #include "c_cvars.h"
 #include "tables.h"
+#include "effect.h"
 
 CVAR(Bool, opt_modulation_wheel, true, CVAR_ARCHIVE | CVAR_GLOBALCONFIG)
 CVAR(Bool, opt_portamento, true, CVAR_ARCHIVE | CVAR_GLOBALCONFIG)
@@ -129,10 +130,12 @@ Player::Player(int freq, Instruments *instr)
 
 	reverb = new Reverb;
 	reverb->init_effect_status(play_system_mode);
+	effect = new Effect(reverb);
+
 
 	mixer = new Mixer(this);
 	recache = new Recache(this);
-	aq = new AudioQueue(play_mode, audio_buffer_size, reverb);
+	aq = new AudioQueue(play_mode, AUDIO_BUFFER_SIZE, reverb);
 	aq->setup();
 
 	for (int i = 0; i < MAX_CHANNELS; i++)
@@ -191,6 +194,7 @@ Player::~Player()
 	delete aq;
 	delete mixer;
 	delete recache;
+	delete effect;
 	delete reverb;
 }
 
@@ -5017,101 +5021,23 @@ void Player::do_compute_data(int32_t count)
 	current_sample += count;
 }
 
-int Player::check_midi_play_end(MidiEvent *e, int len)
+int Player::send_output(int32_t *samples, int32_t count)
 {
-    int i, type;
-
-    for(i = 0; i < len; i++)
-    {
-	type = e[i].type;
-	if(type == ME_NOTEON || type == ME_LAST || type == ME_WRD || type == ME_SHERRY)
-	    return 0;
-	if(type == ME_EOT)
-	    return i + 1;
-    }
-    return 0;
-}
-
-int Player::midi_play_end(void)
-{
-    int i, rc = RC_TUNE_END;
-
-    check_eot_flag = 0;
-
-    if(opt_realtime_playing && current_sample == 0)
-    {
-	reset_voices();
-	return RC_TUNE_END;
-    }
-
-    if(upper_voices > 0)
-    {
-	int fadeout_cnt;
-
-	rc = compute_data(playback_rate);
-	if(RC_IS_SKIP_FILE(rc))
-	    goto midi_end;
-
-	for(i = 0; i < upper_voices; i++)
-	    if(voice[i].status & (VOICE_ON | VOICE_SUSTAINED))
-		finish_note(i);
-	if(opt_realtime_playing)
-	    fadeout_cnt = 3;
-	else
-	    fadeout_cnt = 6;
-	for(i = 0; i < fadeout_cnt && upper_voices > 0; i++)
+	aq->add(samples, count);
+	/*
+	effect->do_effect(samples, count);
+	// pass to caller
+	for (int i = 0; i < count && output_len > 0; i++)
 	{
-	    rc = compute_data(playback_rate / 2);
-	    if(RC_IS_SKIP_FILE(rc))
-		goto midi_end;
+		*output_buffer++ = (*samples++)*(1.f / 0x80000000u);
+		*output_buffer++ = (*samples++)*(1.f / 0x80000000u);
+		output_len--;
 	}
-
-	/* kill voices */
-	kill_all_voices();
-	rc = compute_data(MAX_DIE_TIME);
-	if(RC_IS_SKIP_FILE(rc))
-	    goto midi_end;
-	upper_voices = 0;
-    }
-
-    /* clear reverb echo sound */
-    reverb->init_reverb();
-    for(i = 0; i < MAX_CHANNELS; i++)
-    {
-	channel[i].reverb_level = -1;
-	channel[i].reverb_id = -1;
-	make_rvid_flag = 1;
-    }
-
-    /* output null sound */
-    if(opt_realtime_playing)
-	rc = compute_data((int32_t)(playback_rate * PLAY_INTERLEAVE_SEC/2));
-    else
-	rc = compute_data((int32_t)(playback_rate * PLAY_INTERLEAVE_SEC));
-    if(RC_IS_SKIP_FILE(rc))
-	goto midi_end;
-
-    compute_data(0); /* flush buffer to device */
-
-	rc = aq->softFlush();
-
-  midi_end:
-    if(RC_IS_SKIP_FILE(rc))
-	aq->flush(1);
-
-    ctl_cmsg(CMSG_INFO, VERB_VERBOSE, "Playing time: ~%d seconds",
-	      current_sample/playback_rate+2);
-    ctl_cmsg(CMSG_INFO, VERB_VERBOSE, "Notes cut: %d",
-	      cut_notes);
-    ctl_cmsg(CMSG_INFO, VERB_VERBOSE, "Notes lost totally: %d",
-	      lost_notes);
-    if(RC_IS_SKIP_FILE(rc))
-	return rc;
-    return RC_TUNE_END;
+	*/
+	memset(output_buffer, 0, output_len * 8);
+	return RC_OK;
 }
 
-/* count=0 means flush remaining buffered data to output device, then
-   flush the device itself */
 int Player::compute_data(int32_t count)
 {
 	if (!count)
@@ -5126,29 +5052,19 @@ int Player::compute_data(int32_t count)
 		return RC_OK;
 	}
 
-	while ((count + buffered_count) >= audio_buffer_size)
+	while ((count + buffered_count) >= AUDIO_BUFFER_SIZE)
 	{
 		int i;
 
-		do_compute_data(audio_buffer_size - buffered_count);
-		count -= audio_buffer_size - buffered_count;
+		do_compute_data(AUDIO_BUFFER_SIZE - buffered_count);
+		count -= AUDIO_BUFFER_SIZE - buffered_count;
 
-		if (aq->add(common_buffer, audio_buffer_size) == -1)
+		if (aq->add(common_buffer, AUDIO_BUFFER_SIZE) == -1)
 			return RC_ERROR;
 
 		buffer_pointer = common_buffer;
 		buffered_count = 0;
 
-		/* check break signals */
-
-		if (upper_voices == 0 && check_eot_flag &&
-			(i = check_midi_play_end(current_event, EOT_PRESEARCH_LEN)) > 0)
-		{
-			if (i > 1)
-				ctl_cmsg(CMSG_INFO, VERB_VERBOSE,
-					"Last %d MIDI events are ignored", i - 1);
-			return midi_play_end();
-		}
 	}
 	if (count > 0)
 	{
@@ -5755,7 +5671,7 @@ int Player::play_event(MidiEvent *ev)
 				break;
 
 			case ME_EOT:
-				return midi_play_end();
+				break;
 			}
 #ifndef SUPPRESS_CHANNEL_LAYER
 		}
@@ -6101,8 +6017,7 @@ Instrument *Player::play_midi_load_instrument(int dr, int bk, int prog)
 	bool load_success;
 	// The inner workings of this function which alters the instrument data has been put into the Instruments class.
 	auto instr = instruments->play_midi_load_instrument(dr, bk, prog, &load_success);
-	if (load_success)
-		aq->add(NULL, 0);	/* Update software buffer */
+	//if (load_success) send_output(NULL, 0);	/* Update software buffer */
 	return instr;
 }
 
@@ -6150,4 +6065,11 @@ void Player::init_channel_layer(int ch)
 	channel[ch].port_select = ch >> 4;
 }
 
+void Player::get_output(float *buffer, int len)
+{
+	output_buffer = buffer;
+	output_len = len;
+	//compute_data(len);
+}
+
 }
\ No newline at end of file
diff --git a/src/sound/timiditypp/playmidi.h b/src/sound/timiditypp/playmidi.h
index 1ab0c65fb..2e9321667 100644
--- a/src/sound/timiditypp/playmidi.h
+++ b/src/sound/timiditypp/playmidi.h
@@ -511,6 +511,7 @@ struct midi_file_info
 class Recache;
 class Mixer;
 class Reverb;
+class Effect;
 class AudioQueue;
 
 class Player
@@ -532,6 +533,7 @@ private:
 	Recache *recache;
 	Mixer *mixer;
 	Reverb *reverb;
+	Effect *effect;
 	AudioQueue *aq;
 
 
@@ -559,6 +561,8 @@ private:
 	int current_freq_table;
 	int current_temper_freq_table;
 	int master_tuning;
+	float *output_buffer;
+	int output_len;
 
 	int make_rvid_flag; /* For reverb optimization */
 
@@ -666,6 +670,7 @@ private:
 	void update_legato_controls(int ch);
 	void set_master_tuning(int tune);
 	struct midi_file_info *new_midi_file_info();
+	int send_output(int32_t *samples, int32_t count);
 
 
 	void adjust_amplification(void);
@@ -734,6 +739,7 @@ public:
 	void recompute_freq(int v);
 	int get_default_mapID(int ch);
 	void init_channel_layer(int ch);
+	void get_output(float *buffer, int len);
 
 	// Only until streaming works.
 	void skip_to(int32_t until_time, MidiEvent *evt_start);
diff --git a/src/sound/timiditypp/readmidi.cpp b/src/sound/timiditypp/readmidi.cpp
index d59484bc9..4d9afa80a 100644
--- a/src/sound/timiditypp/readmidi.cpp
+++ b/src/sound/timiditypp/readmidi.cpp
@@ -1566,11 +1566,6 @@ void Player::run_midi(int samples)
 	}
 }
 
-void run_midi(int msec)
-{
-	gplayer->run_midi(msec);
-}
-
 
 void timidity_close()
 {