@@ -329,7 +329,127 @@ void CMIDIDevice::MIDIMessageHandler (const u8 *pMessage, size_t nLength, unsign
329
329
if (m_ChannelMap[nTG] == ucSysExChannel || m_ChannelMap[nTG] == OmniMode)
330
330
{
331
331
LOGNOTE (" MIDI-SYSEX: channel: %u, len: %u, TG: %u" ,m_ChannelMap[nTG],nLength,nTG);
332
- HandleSystemExclusive (pMessage, nLength, nCable, nTG);
332
+
333
+ // Check for TX216/TX816 style performance sysex messages
334
+
335
+ if (pMessage[3 ] == 0x04 )
336
+ {
337
+ // TX816/TX216 Performance SysEx message
338
+ uint8_t mTG = pMessage[2 ] & 0x0F ; // mTG = module/tone generator number (0-7)
339
+ uint8_t par = pMessage[4 ];
340
+ uint8_t val = pMessage[5 ];
341
+
342
+ // For parameter 1 (Set MIDI Channel), only process for the TG with the number in pMessage[2]
343
+ if (par == 1 ) {
344
+ if (nTG != mTG ) continue ;
345
+ } else {
346
+ // For all other parameters, process for all TGs listening on the MIDI channel mTG or OmniMode
347
+ if (!(m_ChannelMap[nTG] == mTG || m_ChannelMap[nTG] == OmniMode)) continue ;
348
+ }
349
+ LOGNOTE (" MIDI-SYSEX: Assuming TX216/TX816 style performance sysex message because 4th byte is 0x04" );
350
+
351
+ switch (par)
352
+ {
353
+ case 1 : // MIDI Channel
354
+ LOGNOTE (" MIDI-SYSEX: Set TG%d to MIDI Channel %d" , mTG , val & 0x0F );
355
+ m_pSynthesizer->SetMIDIChannel (val & 0x0F , mTG );
356
+ break ;
357
+ case 2 : // Poly/Mono
358
+ LOGNOTE (" MIDI-SYSEX: Set Poly/Mono %d to %d" , nTG, val & 0x0F );
359
+ m_pSynthesizer->setMonoMode (val ? true : false , nTG);
360
+ break ;
361
+ case 3 : // Pitch Bend Range
362
+ LOGNOTE (" MIDI-SYSEX: Set Pitch Bend Range %d to %d" , nTG, val & 0x0F );
363
+ m_pSynthesizer->setPitchbendRange (val, nTG);
364
+ break ;
365
+ case 4 : // Pitch Bend Step
366
+ LOGNOTE (" MIDI-SYSEX: Set Pitch Bend Step %d to %d" , nTG, val & 0x0F );
367
+ m_pSynthesizer->setPitchbendStep (val, nTG);
368
+ break ;
369
+ case 5 : // Portamento Time
370
+ LOGNOTE (" MIDI-SYSEX: Set Portamento Time %d to %d" , nTG, val & 0x0F );
371
+ m_pSynthesizer->setPortamentoTime (val, nTG);
372
+ break ;
373
+ case 6 : // Portamento/Glissando
374
+ LOGNOTE (" MIDI-SYSEX: Set Portamento/Glissando %d to %d" , nTG, val & 0x0F );
375
+ m_pSynthesizer->setPortamentoGlissando (val, nTG);
376
+ break ;
377
+ case 7 : // Portamento Mode
378
+ LOGNOTE (" MIDI-SYSEX: Set Portamento Mode %d to %d" , nTG, val & 0x0F );
379
+ m_pSynthesizer->setPortamentoMode (val, nTG);
380
+ break ;
381
+ case 9 : // Mod Wheel Sensitivity
382
+ {
383
+ int scaled = (val * 99 ) / 15 ;
384
+ LOGNOTE (" MIDI-SYSEX: Set Mod Wheel Sensitivity %d to %d (scaled %d)" , nTG, val & 0x0F , scaled);
385
+ m_pSynthesizer->setModWheelRange (scaled, nTG);
386
+ }
387
+ break ;
388
+ case 10 : // Mod Wheel Assign
389
+ LOGNOTE (" MIDI-SYSEX: Set Mod Wheel Assign %d to %d" , nTG, val & 0x0F );
390
+ m_pSynthesizer->setModWheelTarget (val, nTG);
391
+ break ;
392
+ case 11 : // Foot Controller Sensitivity
393
+ {
394
+ int scaled = (val * 99 ) / 15 ;
395
+ LOGNOTE (" MIDI-SYSEX: Set Foot Controller Sensitivity %d to %d (scaled %d)" , nTG, val & 0x0F , scaled);
396
+ m_pSynthesizer->setFootControllerRange (scaled, nTG);
397
+ }
398
+ break ;
399
+ case 12 : // Foot Controller Assign
400
+ LOGNOTE (" MIDI-SYSEX: Set Foot Controller Assign %d to %d" , nTG, val & 0x0F );
401
+ m_pSynthesizer->setFootControllerTarget (val, nTG);
402
+ break ;
403
+ case 13 : // Aftertouch Sensitivity
404
+ {
405
+ int scaled = (val * 99 ) / 15 ;
406
+ LOGNOTE (" MIDI-SYSEX: Set Aftertouch Sensitivity %d to %d (scaled %d)" , nTG, val & 0x0F , scaled);
407
+ m_pSynthesizer->setAftertouchRange (scaled, nTG);
408
+ }
409
+ break ;
410
+ case 14 : // Aftertouch Assign
411
+ LOGNOTE (" MIDI-SYSEX: Set Aftertouch Assign %d to %d" , nTG, val & 0x0F );
412
+ m_pSynthesizer->setAftertouchTarget (val, nTG);
413
+ break ;
414
+ case 15 : // Breath Controller Sensitivity
415
+ {
416
+ int scaled = (val * 99 ) / 15 ;
417
+ LOGNOTE (" MIDI-SYSEX: Set Breath Controller Sensitivity %d to %d (scaled %d)" , nTG, val & 0x0F , scaled);
418
+ m_pSynthesizer->setBreathControllerRange (scaled, nTG);
419
+ }
420
+ break ;
421
+ case 16 : // Breath Controller Assign
422
+ LOGNOTE (" MIDI-SYSEX: Set Breath Controller Assign %d to %d" , nTG, val & 0x0F );
423
+ m_pSynthesizer->setBreathControllerTarget (val, nTG);
424
+ break ;
425
+ case 26 : // Audio Output Level Attenuator
426
+ {
427
+ LOGNOTE (" MIDI-SYSEX: Set Audio Output Level Attenuator %d to %d" , nTG, val & 0x0F );
428
+ // Example: F0 43 10 04 1A 00 F7 to F0 43 10 04 1A 07 F7
429
+ unsigned attenVal = val & 0x07 ;
430
+ // unsigned newVolume = (unsigned)(127.0 * pow(attenVal / 7.0, 2.0) + 0.5); // Logarithmic mapping
431
+ // But on the T816, there is an exponential (not logarithmic!) mapping, and 0 results in the same volume as 1:
432
+ // 7=127, 6=63, 5=31, 4=15, 3=7, 2=3, 1=1, 0=1
433
+ unsigned newVolume = (attenVal == 0 ) ? 0 : (127 >> (7 - attenVal));
434
+ if (newVolume == 0 ) newVolume = 1 ; // 0 is like 1 to avoid silence
435
+ m_pSynthesizer->SetVolume (newVolume, nTG);
436
+ }
437
+ break ;
438
+ case 64 : // Master Tuning
439
+ LOGNOTE (" MIDI-SYSEX: Set Master Tuning" );
440
+ // TX812 scales from -75 to +75 cents.
441
+ m_pSynthesizer->SetMasterTune (maplong (val, 1 , 127 , -37 , 37 ), nTG); // Would need 37.5 here, due to wrong constrain on dexed_synth module?
442
+ break ;
443
+ default :
444
+ // Unknown or unsupported parameter
445
+ LOGNOTE (" MIDI-SYSEX: Unknown parameter %d for TG %d" , par, nTG);
446
+ break ;
447
+ }
448
+ }
449
+ else
450
+ {
451
+ HandleSystemExclusive (pMessage, nLength, nCable, nTG);
452
+ }
333
453
}
334
454
}
335
455
else
@@ -431,15 +551,15 @@ void CMIDIDevice::MIDIMessageHandler (const u8 *pMessage, size_t nLength, unsign
431
551
case MIDI_CC_SOSTENUTO:
432
552
m_pSynthesizer->setSostenuto (pMessage[2 ] >= 64 , nTG);
433
553
break ;
434
-
554
+
435
555
case MIDI_CC_PORTAMENTO:
436
556
m_pSynthesizer->setPortamentoMode (pMessage[2 ] >= 64 , nTG);
437
557
break ;
438
558
439
559
case MIDI_CC_HOLD2:
440
560
m_pSynthesizer->setHoldMode (pMessage[2 ] >= 64 , nTG);
441
561
break ;
442
-
562
+
443
563
case MIDI_CC_RESONANCE:
444
564
m_pSynthesizer->SetResonance (maplong (pMessage[2 ], 0 , 127 , 0 , 99 ), nTG);
445
565
break ;
@@ -455,11 +575,12 @@ void CMIDIDevice::MIDIMessageHandler (const u8 *pMessage, size_t nLength, unsign
455
575
case MIDI_CC_DETUNE_LEVEL:
456
576
if (pMessage[2 ] == 0 )
457
577
{
458
- // " 0 to 127, with 0 being no celeste ( detune) effect applied at all."
578
+ // 0 to 127, with 0 being no detune effect applied at all
459
579
m_pSynthesizer->SetMasterTune (0 , nTG);
460
580
}
461
581
else
462
582
{
583
+ // Scale to -99 to +99 cents
463
584
m_pSynthesizer->SetMasterTune (maplong (pMessage[2 ], 1 , 127 , -99 , 99 ), nTG);
464
585
}
465
586
break ;
@@ -594,10 +715,12 @@ bool CMIDIDevice::HandleMIDISystemCC(const u8 ucCC, const u8 ucCCval)
594
715
if (ucCC == MIDISystemCCMap[m_nMIDISystemCCDetune][tg]) {
595
716
if (ucCCval == 0 )
596
717
{
718
+ // 0 to 127, with 0 being no detune effect applied at all
597
719
m_pSynthesizer->SetMasterTune (0 , tg);
598
720
}
599
721
else
600
722
{
723
+ // Scale to -99 to +99 cents
601
724
m_pSynthesizer->SetMasterTune (maplong (ucCCval, 1 , 127 , -99 , 99 ), tg);
602
725
}
603
726
return true ;
@@ -649,62 +772,6 @@ void CMIDIDevice::HandleSystemExclusive(const uint8_t* pMessage, const size_t nL
649
772
case -11 :
650
773
LOGERR (" Unknown SysEx message." );
651
774
break ;
652
- case 64 :
653
- LOGDBG (" SysEx Function parameter change: %d Value %d" ,pMessage[4 ],pMessage[5 ]);
654
- m_pSynthesizer->setMonoMode (pMessage[5 ],nTG);
655
- break ;
656
- case 65 :
657
- LOGDBG (" SysEx Function parameter change: %d Value %d" ,pMessage[4 ],pMessage[5 ]);
658
- m_pSynthesizer->setPitchbendRange (pMessage[5 ],nTG);
659
- break ;
660
- case 66 :
661
- LOGDBG (" SysEx Function parameter change: %d Value %d" ,pMessage[4 ],pMessage[5 ]);
662
- m_pSynthesizer->setPitchbendStep (pMessage[5 ],nTG);
663
- break ;
664
- case 67 :
665
- LOGDBG (" SysEx Function parameter change: %d Value %d" ,pMessage[4 ],pMessage[5 ]);
666
- m_pSynthesizer->setPortamentoMode (pMessage[5 ],nTG);
667
- break ;
668
- case 68 :
669
- LOGDBG (" SysEx Function parameter change: %d Value %d" ,pMessage[4 ],pMessage[5 ]);
670
- m_pSynthesizer->setPortamentoGlissando (pMessage[5 ],nTG);
671
- break ;
672
- case 69 :
673
- LOGDBG (" SysEx Function parameter change: %d Value %d" ,pMessage[4 ],pMessage[5 ]);
674
- m_pSynthesizer->setPortamentoTime (pMessage[5 ],nTG);
675
- break ;
676
- case 70 :
677
- LOGDBG (" SysEx Function parameter change: %d Value %d" ,pMessage[4 ],pMessage[5 ]);
678
- m_pSynthesizer->setModWheelRange (pMessage[5 ],nTG);
679
- break ;
680
- case 71 :
681
- LOGDBG (" SysEx Function parameter change: %d Value %d" ,pMessage[4 ],pMessage[5 ]);
682
- m_pSynthesizer->setModWheelTarget (pMessage[5 ],nTG);
683
- break ;
684
- case 72 :
685
- LOGDBG (" SysEx Function parameter change: %d Value %d" ,pMessage[4 ],pMessage[5 ]);
686
- m_pSynthesizer->setFootControllerRange (pMessage[5 ],nTG);
687
- break ;
688
- case 73 :
689
- LOGDBG (" SysEx Function parameter change: %d Value %d" ,pMessage[4 ],pMessage[5 ]);
690
- m_pSynthesizer->setFootControllerTarget (pMessage[5 ],nTG);
691
- break ;
692
- case 74 :
693
- LOGDBG (" SysEx Function parameter change: %d Value %d" ,pMessage[4 ],pMessage[5 ]);
694
- m_pSynthesizer->setBreathControllerRange (pMessage[5 ],nTG);
695
- break ;
696
- case 75 :
697
- LOGDBG (" SysEx Function parameter change: %d Value %d" ,pMessage[4 ],pMessage[5 ]);
698
- m_pSynthesizer->setBreathControllerTarget (pMessage[5 ],nTG);
699
- break ;
700
- case 76 :
701
- LOGDBG (" SysEx Function parameter change: %d Value %d" ,pMessage[4 ],pMessage[5 ]);
702
- m_pSynthesizer->setAftertouchRange (pMessage[5 ],nTG);
703
- break ;
704
- case 77 :
705
- LOGDBG (" SysEx Function parameter change: %d Value %d" ,pMessage[4 ],pMessage[5 ]);
706
- m_pSynthesizer->setAftertouchTarget (pMessage[5 ],nTG);
707
- break ;
708
775
case 100 :
709
776
// load sysex-data into voice memory
710
777
LOGDBG (" One Voice bulk upload" );
@@ -756,4 +823,4 @@ void CMIDIDevice::SendSystemExclusiveVoice(uint8_t nVoice, const unsigned nCable
756
823
Iterator->second ->Send (voicedump, sizeof (voicedump)*sizeof (uint8_t ));
757
824
// LOGDBG("Send SYSEX voice dump %u to \"%s\"",nVoice,Iterator->first.c_str());
758
825
}
759
- }
826
+ }
0 commit comments