Hi Clemens,
you may remember me from the yahoogroup/googlegroup midi email list which is now defunct.
I've finally decided to dump windows and move onto Linux 🙂 Should have a long time ago.
I have a chromebox (ChromeOS' Crostini) and a raspberry pi 4, fyi.
I've hit google, but am still finding it difficult to find the APIs I need to open and use midi.
I understand there's ALSA and Jack that can both open midi devices.
I think Jack typically needs to be installed, but ALSA is the base os API and PulseAudio is the
main audio API but it won't do midi.
Can you please point me to the best API on linux to list midi devices?
And will I be able to get away with not installing Jack or is that pretty much a necessity?
Thanks in advance. Cuz I know that if anyone knows midi it's you.
(I'll get into audio APIs later on.)
...Steve
(oops i thought this was a private message)
but, if you have pointers for me, i wanna hear em 🙂
Clemens can answer any question under the sun about midi tho.
You don't tell the language(s) and type of programs that you intend to develop, but anyway,..
The ALSA Library sequencer interface or the raw MIDI interface contain the native Linux API for MIDI. The ALSA sequencer has more features. You probably won't need Jack.
To enumerate MIDI devices in C, just look to the sources of the ALSA sequencer command line utils "aplaymidi" and "arecordmidi", function "list_ports()" list_ports() or the ALSA raw "amidi", function device_list().
If you prefer to write graphic programs with Qt and C++, I'm the author of the Drumstick libraries. Drumstick::ALSA is a C++/Qt wrapper around the ALSA Sequencer interface. You may want to look at the "sysinfo" utility source code, function queryClients() or several other examples.
Thank you Pedro - that's exactly what I was looking for.
My current code uses c++ and win32 api and I'll be moving to c++ and Qt fyi.
If I could bug you one more time (sorry:)... When I get my software synth going, do you think i'll still be able to avoid Jack?
It will need to do realtime-ish audio rendering.
ALSA can handle that on it's own? PulseAudio is also usually installed by default. Could it handle realtime audio if ALSA can't?
thank you so much. I think you've worked on FluidSynth, haven't you 🙂 That is some good stuff.
Now that we know that your application is a software synth, this clarifies your question(s). When you say that you need to do realtime audio rendering, I assume that you also want low latency. That is what most soft synths struggle to achieve (and users demand). The key for that feature is to keep small audio buffers, without buffer underruns or overruns. The smaller the audio buffers are, the lower latency you get.
ALSA provides the drivers for Audio and MIDI devices in the Linux kernel. So, if you have an audio interface or MIDI device attached to your Linux (or Android) computer, then you are using the ALSA drivers. To access the audio and MIDI devices from userspace applications there is a library that provides the API functions that are documented on the other answer. On top of ALSA there are other APIs like Jack and PulseAudio. Jack fanatics claim that it can always achieve lower latency than ALSA. This is kind of a hoax. It is true that Jack can achieve excellent low latency for routing audio between applications. But if you simply want to produce audio in your soundcard from your program, then there is no difference between using ALSA or Jack, because the size of the audio buffers will be equivalent. Of course, if your application is a soft synth, then you may add the requirement of routing audio to other applications with low latency, for instance: record the audio streams of your synth into a DAW application. In that scenario you may choose Jack. There is also a Jack MIDI API, most of the time on top of the ALSA sequencer. I find little use for it, because the ALSA sequencer API already offers MIDI routing, virtual MIDI ports, and everything that you may need.
PulseAudio is another layer on top of ALSA. The goals are different than Jack, but it can route audio streams between applications as well (with higher latency, usually). The advantage is that all Linux distros install it by default, so a typical audio application for normal users should use PulseAudio by default. You mention fluidsynth (yes, I have contributed to this program, and also to Qsynth). It has support for several audio APIs in Linux: ALSA, Jack and PulseAudio. Go ahead and compare yourself the size of buffers and latency when using each system before believing the propaganda. By the way, I've published another open source soft synth here: Linux-SonivoxEas. It is a port of the Android MIDI synth to Linux using ALSA sequencer for MIDI input and PulseAudio for output. Just grab the AppImage and try it yourself as well, experimenting with the buffer size. The same synth is used by VMPK by default in Linux, because its simplicity.
perfecttt !!
ok, it sounds like ALSA will take care of everything for me. thank you so much!
My app ( https://pianocheetah.app) is mainly a weird midi sequencer.
(using a weird pseudo piano roll notation and for "my" piano practice)
But it also can send midi directly to a softsynth i have.
I'll enjoy looking into your softsynth and seeing how they compare.
I set mine up to use straight .WAV files for instrument ranges (of key/velo).
So goal 1 is getting the sequencer working. goal 2 is the softsynth.
I'll probably use rawmidi as my code has had to live on win32 🙁
It already keeps queues and understands midi file format and
deals with each port's in and out devices and allll that stuff.
ok! I'm all set! I think this is gonna be fun!!
Good thing I'll be laid off pretty soon - lots of time for myyyyy coding :)))
Well, I'm makin progress, but it's been kinda slow.
My latest problem is listing midi devices using ALSA apis on ChromeOS 64 bit Crostini (based on Debian).
I currently get this:
sh@penguin:~/src/build-tmidi-Desktop_Qt_6_0_0_GCC_64bit-Release$ ./tmidi
Sat.17:10:31.004 card=0 name=hw:0
Sat.17:10:31.021 ALSA snd_ctl_rawmidi_next_device error: -25=Inappropriate ioctl for device
My little test program is...
[code type=cpp]
// tmidi - dump alsa info (from good ole amidi.c)
#include "../stv/os.h"
#include
__attribute__((noreturn))
void DieSnd (char *msg, int err)
{ DBG ("ALSA `s error: `d=`s", msg, err, snd_strerror (err)); exit (99); }
static void list_dev (snd_ctl_t *ctl, int card, int dev)
{ int err;
unsigned int isub, osub, nsub, sub;
snd_rawmidi_info_t *inf;
const char *name, *subname;
snd_rawmidi_info_alloca (& inf);
snd_rawmidi_info_set_device (inf, SC(unsigned int,dev));
isub = 0;
snd_rawmidi_info_set_stream (inf, SND_RAWMIDI_STREAM_INPUT);
if (! snd_ctl_rawmidi_info (ctl, inf))
isub = snd_rawmidi_info_get_subdevices_count (inf);
osub = 0;
snd_rawmidi_info_set_stream (inf, SND_RAWMIDI_STREAM_OUTPUT);
if (! snd_ctl_rawmidi_info (ctl, inf))
osub = snd_rawmidi_info_get_subdevices_count (inf);
nsub = (isub > osub) ? isub : osub;
if (! nsub) return;
for (sub = 0; sub < nsub; sub++) {
snd_rawmidi_info_set_stream (
inf, sub < isub ? SND_RAWMIDI_STREAM_INPUT
: SND_RAWMIDI_STREAM_OUTPUT);
snd_rawmidi_info_set_subdevice (inf, sub);
if ((err = snd_ctl_rawmidi_info (ctl, inf)))
DieSnd (CC("snd_ctl_rawmidi_info"), err);
name = snd_rawmidi_info_get_name (inf);
subname = snd_rawmidi_info_get_subdevice_name (inf);
DBG(" card=`d dev=`d sub=`d name=`s subname=`s",
card, dev, sub, name, subname);
if ((sub == 0) && (subname [0] == '\0')) {
DBG ("`s (`c`c hw:`d,`d)", name,
sub < isub ? 'I':' ',
sub < osub ? 'O':' ', card, dev);
if (nsub > 1) DBG (" (`d subdevices)", nsub);
break;
}
else
DBG ("`s (`c`c hw:`d,`d,`d name=`s)", subname,
sub < isub ? 'I':' ',
sub < osub ? 'O':' ', card, dev, sub, name);
}
}
int main ()
{ int err, card, dev;
TStr name;
snd_ctl_t *ctl;
for (card = -1;;) {
if ((err = snd_card_next (& card))) DieSnd (CC("snd_card_next"), err);
if (card < 0) break;
StrFmt (name, "hw:`d", card);
DBG("card=`d name=`s", card, name);;
if ((err = snd_ctl_open (& ctl, name, 0)))
DieSnd (CC("snd_ctl_open"), err);
for (dev = -1;;) {
if ((err = snd_ctl_rawmidi_next_device (ctl, & dev)))
DieSnd (CC("snd_ctl_rawmidi_next_device"), err);
if (dev < 0) break;
list_dev (ctl, card, dev);
}
snd_ctl_close (ctl);
}
return 0;
}
[/code]
.......and in general, where is the best place to ask linux midi and audio questions.
My OSs are chromeos and raspberry pi, my language c++, my ui library qt
thanks for any tips 🙂
Line 72 appears to be incomplete; is this really the source code you're using?
For ALSA API questions, the best place is the alsa-users mailing list.
oh yeah, hmm, the paste probably got messed up the the forum software.
ok I'll see ya over on that list. thanks!