zynaddsubfx

ZynAddSubFX open source synthesizer
Log | Files | Refs | Submodules | LICENSE

commit fef41d030545862c9cb2018f72297e33018c791b
parent 98e0b77a1a543252307dffb4a32abb2f852c8618
Author: Hans Petter Selasky <hps@selasky.org>
Date:   Thu,  3 Oct 2019 20:15:05 +0200

Reduce number of system calls for ALSA MIDI by implementing proper polling.

Use polling with a timeout instead of polling for MIDI events thousands of
times per second with no timeout. This reduces the CPU usage for ZynAddSubFX.

Signed-off-by: Hans Petter Selasky <hps@selasky.org>

Diffstat:
Msrc/Nio/AlsaEngine.cpp | 28+++++++++++++++++++++-------
1 file changed, 21 insertions(+), 7 deletions(-)

diff --git a/src/Nio/AlsaEngine.cpp b/src/Nio/AlsaEngine.cpp @@ -14,6 +14,7 @@ #include <stdlib.h> #include <iostream> #include <cmath> +#include <poll.h> #include "../Misc/Util.h" #include "../Misc/Config.h" @@ -105,17 +106,29 @@ void *AlsaEngine::_MidiThread(void *arg) void *AlsaEngine::MidiThread(void) { snd_seq_event_t *event; - MidiEvent ev; + MidiEvent ev = {}; + struct pollfd pfd[4 /* XXX 1 should be enough */]; + int error; + set_realtime(); while(1) { if(midi.exiting) break; - if(snd_seq_event_input_pending(midi.handle, 1) <= 0) { - usleep(10); - continue; - } - if(snd_seq_event_input(midi.handle, &event) < 0) + error = snd_seq_poll_descriptors(midi.handle, pfd, 4, POLLIN); + if(error <= 0) break; + error = poll(pfd, error, 1000 /* ms */); + if(error < 0) { + if(errno == EAGAIN || errno == EINTR) + continue; + break; + } + error = snd_seq_event_input(midi.handle, &event); + if (error < 0) { + if(error == -EAGAIN || error == -EINTR) + continue; + break; + } //ensure ev is empty ev.channel = 0; ev.num = 0; @@ -228,7 +241,8 @@ bool AlsaEngine::openMidi() int alsaport; midi.handle = NULL; - if(snd_seq_open(&midi.handle, "default", SND_SEQ_OPEN_INPUT, 0) != 0) + if(snd_seq_open(&midi.handle, "default", + SND_SEQ_OPEN_INPUT, SND_SEQ_NONBLOCK) != 0) return false; string clientname = "ZynAddSubFX";