MIDI dump of Yamaha TX816

Abstract

I own two Yamaha TX816 and I need to dump and reorganize the patches. My computer runs on Ubuntu 24.04, the MIDI interface is E-MU XMIDI 1X1.

Part 1 - dumping

Using Bladesk Librarian

A fantastic librarian working directly in your browser: https://bladesk.github.io/DX7II-Librarian/.
It works well with my Yamaha DX7 MK1, but failed to receive dumps from the TX816.

Using ALSA command amidi

This simple command comes with ALSA and runs into a terminal (CTRL+ALT+T to open a terminal). QJackCtl must be installed first:

$ sudo apt install qjackctl
$ amidi -l
Dir Device    Name
IO  hw:2,0,0  E-MU XMidi1X1  Midi In   
$ amidi --port=hw:2,0,0 --receive=TX816B-module1.syx
cannot open port "hw:2,0,0": Device or resource busy
What's going on?

First, let's check the system calls:

$ sudo strace amidi --port=hw:2,0,0 --receive=TX816B-module1.syx
...
openat(AT_FDCWD, "/dev/snd/controlC2", O_RDWR|O_CLOEXEC) = 4
ioctl(4, SNDRV_CTL_IOCTL_PVERSION, 0x7ffec02944fc) = 0
ioctl(4, SNDRV_CTL_IOCTL_RAWMIDI_PREFER_SUBDEVICE, 0x7ffec029455c) = 0
openat(AT_FDCWD, "/dev/snd/midiC2D0", O_RDONLY|O_NONBLOCK|O_CLOEXEC) = -1 EBUSY (Device or resource busy)
openat(AT_FDCWD, "/dev/snd/controlC2", O_RDONLY|O_CLOEXEC) = 5
ioctl(5, SNDRV_CTL_IOCTL_CARD_INFO, 0x7ffec0294350) = 0
close(5)                                = 0
openat(AT_FDCWD, "/dev/snd/midiC2D0", O_RDONLY|O_NONBLOCK|O_CLOEXEC) = -1 EBUSY (Device or resource busy)
close(4)                                = 0
...
The issue raises when amidi tries to open the device /dev/snd/midiC2D0.
$ ls -l /dev/snd
total 0
drwxr-xr-x  2 root root       80 Jan 11 15:01 by-id
drwxr-xr-x  2 root root      140 Jan 11 15:01 by-path
crw-rw----+ 1 root audio 116, 11 Jan 10 21:01 controlC0
crw-rw----+ 1 root audio 116,  4 Jan 10 21:01 controlC1
crw-rw----+ 1 root audio 116,  6 Jan 11 15:01 controlC2
crw-rw----+ 1 root audio 116, 10 Jan 10 21:01 hwC0D0
crw-rw----+ 1 root audio 116,  5 Jan 11 15:01 midiC2D0
crw-rw----+ 1 root audio 116,  8 Jan 11 14:47 pcmC0D0c
crw-rw----+ 1 root audio 116,  7 Jan 11 14:47 pcmC0D0p
crw-rw----+ 1 root audio 116,  9 Jan 11 14:47 pcmC0D2c
crw-rw----+ 1 root audio 116,  3 Jan 10 21:01 pcmC1D0c
crw-rw----+ 1 root audio 116,  2 Jan 11 14:46 pcmC1D0p
crw-rw----+ 1 root audio 116,  1 Jan 10 21:01 seq
crw-rw----+ 1 root audio 116, 33 Jan 10 21:01 timer
Is there any process using this device?
$ sudo lsof /dev/snd/midiC2D0
lsof: WARNING: can't stat() fuse.portal file system /run/user/1000/doc
      Output information may be incomplete.
lsof: WARNING: can't stat() fuse.gvfsd-fuse file system /run/user/1000/gvfs
      Output information may be incomplete.
What are these warnings? Well basically, lsof scans all filesystems and has no privilege on the fuse (Filesystem in Userspace) filesystem. Fuse and gvfs are used by Gnome. So we can safely ignore the warnings and deduce no process is currently using midiC2D0.

I spent hours tracing and digging in the sources without any success. I gave up on this.

Using ALSA command aseqdump

I had more success by slighly modifying the function dump_event in aseqdump.c to output binary instead of text:

286         case SND_SEQ_EVENT_SYSEX:
287                 {
288                         unsigned int i;
289 //                      printf("System exclusive          ");
290                         for (i = 0; i < ev->data.ext.len; ++i)
291 //                              printf(" %02X", ((unsigned char*)ev->data.ext.ptr)[i]);
292                                 printf("%c", ((unsigned char*)ev->data.ext.ptr)[i]);
293 //                      printf("\n");
294                 }
295                 break;
296         default:
297                 printf("Event type %d\n",  ev->type);
298         }

With this mod, I simply had to redirect the output of aseqdump to a file

$ ./aseqdump -p port > tx816A.module1.dump

Then, on each unit, select the module with Out slot and dump with UT(ILITY) → DU(MP) → Yes

Part 2 - Writing a librarian

Currenlty under development

I did a quick and dirty version in C, but I decided to write a better version in C++ based on RtMidi.

  • Install libasound2-dev
  • Download and extract RtMidi
I compiled the example provided in Getting started
#include "RtMidi.h"
 
int main() {
  try {
    RtMidiIn midiin;
  } catch (RtMidiError &error) {
    // Handle the exception here
    error.printMessage();
  }
  return 0;
}
g++ -Wall -D__LINUX_ALSA__ -o example example1.cpp rtmidi-6.0.0/RtMidi.cpp -lasound -lpthread

Comments

Popular Posts