I think I found the problem with MT-32 emulation. Data which are coming from MPU-401 interface are sent directly into ALSA:
Code: Select all
int rdLen = read(fdSerial, buf, sizeof(buf));
if (rdLen > 0)
{
write_alsa_packet(buf, rdLen);
}
ALSA recognizes SysEx message, and notifies MUNT via event:
Code: Select all
case SND_SEQ_EVENT_SYSEX:
debug_msg("SysEx (fragment) of size %d\n", seq_ev->data.ext.len);
ev->type = EVENT_SYSEX;
ev->sysex_len = seq_ev->data.ext.len;
ev->sysex = malloc(seq_ev->data.ext.len);
memcpy(ev->sysex, seq_ev->data.ext.ptr, ev->sysex_len);
return;
This in turn produces event for MUNT SysEx message processor, parseStream.
Code: Select all
case EVENT_SYSEX:
/* record it if needed */
if (consumer_types & CONSUME_SYSEX)
{
fwrite((unsigned char *)newev.sysex, 1, newev.sysex_len, recsyx_file);
fflush(recsyx_file);
}
sysexHandler->parseStream((MT32Emu::Bit8u *) newev.sysex, newev.sysex_len);
free(newev.sysex);
break;
The problem is, somewhere between MidiLink and parseStream, a segment is lost.
Code: Select all
[-118448687] SEQU OUT [64] --> f0 41 10 16 12 03 01 10 5e 64 07 01 5e 64 07 01 5e 64 07 01 5e 64 07 01 5e 64 07 01 5e 64 07 01 5e 64 07 01 5e 64 07 01 5e 64 07 01 5e 64 07 01 5e 64 07 01 40 64 07 01 40 64 07 01 4a 64 06 01
[-118448666] SEQU OUT [64] --> 41 64 07 01 4b 64 08 01 45 64 06 01 44 64 0b 01 46 64 06 01 44 64 0b 01 5d 64 06 01 43 64 08 01 47 64 06 01 43 64 08 01 42 64 03 01 48 64 06 01 42 64 03 01 49 64 08 01 5e 64 07 01 5e 64 07 01
[-118448646] SEQU OUT [64] --> 56 64 09 01 5e 64 07 01 4c 64 07 01 5e 64 07 01 5e 64 07 01 5e 64 07 01 52 64 02 01 53 64 04 01 4d 64 08 01 4e 64 09 01 4f 64 0a 01 50 64 07 01 51 64 05 01 54 64 02 01 55 64 02 01 5b 64 09 01
[-118448625] SEQU OUT [64] --> 58 64 04 01 5a 64 09 01 59 64 09 01 5c 64 0a 01 5e 64 07 01 57 64 0c 01 5e 64 07 01 5e 64 07 01 5e 64 07 01 5e 64 07 01 5e 64 07 01 5e 64 07 01 5e 64 07 01 5e 64 07 01 5e 64 07 01 5e 64 07 01
SysEx (fragment) of size 256
Send data to MUNT parseStream
Data to parse: F0 41 10 16 12 03 01 10 5E 64 07 01 5E 64 07 01 5E 64 07 01 5E 64 07 01 5E 64 07 01 5E 64 07 01 5E 64 07 01 5E 64 07 01 5E 64 07 01 5E 64 07 01 5E 64 07 01 40 64 07 01 40 64 07 01 4A 64 06 01 41 64 07 01 4B 64 08 01 45 64 06 01 44 64 0B 01 46 64 06 01 44 64 0B 01 5D 64 06 01 43 64 08 01 47 64 06 01 43 64 08 01 42 64 03 01 48 64 06 01 42 64 03 01 49 64 08 01 5E 64 07 01 5E 64 07 01 56 64 09 01 5E 64 07 01 4C 64 07 01 5E 64 07 01 5E 64 07 01 5E 64 07 01 52 64 02 01 53 64 04 01 4D 64 08 01 4E 64 09 01 4F 64 0A 01 50 64 07 01 51 64 05 01 54 64 02 01 55 64 02 01 5B 64 09 01 58 64 04 01 5A 64 09 01 59 64 09 01 5C 64 0A 01 5E 64 07 01 57 64 0C 01 5E 64 07 01 5E 64 07 01 5E 64 07 01 5E 64 07 01 5E 64 07 01 5E 64 07 01 5E 64 07 01 5E 64 07 01 5E 64 07 01 5E 64 07 01
SysexHandler: parseSysex: Copying incomplete SysEx size 256 into buffer...
SysexHandler: End of parseStream
[-118448621] SEQU OUT [10] --> 5e 64 07 01 5e 64 07 01 2f f7
[-118448520] SEQU OUT [64] --> f0 41 10 16 12 05 00 00 02 00 18 32 0c 00 01 00 02 15 18 32 0c 00 01 00 02 01 18 32 0c 00 01 00 02 02 18 32 0c 00 01 00 02 11 18 32 0c 00 01 00 02 0b 18 32 0c 00 01 00 02 0f 18 32 0c 00 01 00
[-118448500] SEQU OUT [64] --> 02 05 18 32 0c 00 01 00 02 12 18 32 0c 00 01 00 02 16 18 32 0c 00 01 00 02 14 18 32 0c 00 01 00 02 08 18 32 0c 00 01 00 02 04 18 32 0c 00 01 00 02 03 18 32 0c 00 01 00 02 06 18 32 0c 00 01 00
[-118448479] SEQU OUT [64] --> 02 07 18 32 0c 00 01 00 02 09 18 32 0c 00 01 00 02 13 18 32 0c 00 01 00 02 1b 18 32 0c 00 01 00 02 1a 18 32 0c 00 01 00 02 19 18 32 0c 00 01 00 02 17 18 32 0c 00 01 00 00 16 18 32 0c 00 01 00
[-118448459] SEQU OUT [64] --> 02 18 18 32 0c 00 01 00 00 18 18 32 0c 00 01 00 02 10 18 32 0c 00 01 00 02 0e 18 32 0c 00 01 00 02 0a 18 32 0c 00 01 00 02 0d 18 32 0c 00 01 00 02 0c 18 32 0c 00 01 00 00 1e 18 32 0c 00 01 00
SysEx (fragment) of size 256
Send data to MUNT parseStream
Data to parse: F0 41 10 16 12 05 00 00 02 00 18 32 0C 00 01 00 02 15 18 32 0C 00 01 00 02 01 18 32 0C 00 01 00 02 02 18 32 0C 00 01 00 02 11 18 32 0C 00 01 00 02 0B 18 32 0C 00 01 00 02 0F 18 32 0C 00 01 00 02 05 18 32 0C 00 01 00 02 12 18 32 0C 00 01 00 02 16 18 32 0C 00 01 00 02 14 18 32 0C 00 01 00 02 08 18 32 0C 00 01 00 02 04 18 32 0C 00 01 00 02 03 18 32 0C 00 01 00 02 06 18 32 0C 00 01 00 02 07 18 32 0C 00 01 00 02 09 18 32 0C 00 01 00 02 13 18 32 0C 00 01 00 02 1B 18 32 0C 00 01 00 02 1A 18 32 0C 00 01 00 02 19 18 32 0C 00 01 00 02 17 18 32 0C 00 01 00 00 16 18 32 0C 00 01 00 02 18 18 32 0C 00 01 00 00 18 18 32 0C 00 01 00 02 10 18 32 0C 00 01 00 02 0E 18 32 0C 00 01 00 02 0A 18 32 0C 00 01 00 02 0D 18 32 0C 00 01 00 02 0C 18 32 0C 00 01 00 00 1E 18 32 0C 00 01 00
SysexHandler: parseSysexFragment: Nextbyte: F0 at 1
SysexHandler: parseSysexFragment: No end. SysEx message was 256 bytes long, last byte was 0xF0
As you can see, there are 256 bytes sent into parseStream, and MUNT gets them correctly. Then, there is a 10 byte final sequence for that 256 bytes, in form of 5e 64 07 01 5e 64 07 01 2f f7. This part never reaches parseStream, and MUNT continues the SysEx message with start of second SysEx message, bytes f0 41 10 16 12 05 00 00 02 00 18 32 0c....... Because it sees F0, which is start byte of next SysEx message, it fails, and ignores that whole SysEx message in buffer.
I don't know yet, where is exact root cause, but this is problem which affects any game, which produces larger SysEx messages. If the music sounds "incorrect", MT-32 emulation failed to get proper SysEx programming due to this error.
It may be, that ALSA does not correctly recognize that SysEx continues from MidiLink stream, and fails to produce correct event (SND_SEQ_EVENT_SYSEX), and sends those bytes as some other data.
I apologize for a lengthy post, but I hope this will eventually put some clarification for those, who are wondering about "wrong" MT-32 sound.