@@ -50,6 +50,9 @@ LOGMODULE ("mididevice");
50
50
#define MIDI_CC_DETUNE_LEVEL 94
51
51
#define MIDI_CC_ALL_SOUND_OFF 120
52
52
#define MIDI_CC_ALL_NOTES_OFF 123
53
+ #define MIDI_CC_NRPN_PARAM_MSB 99
54
+ #define MIDI_CC_NRPN_PARAM_LSB 98
55
+ #define MIDI_CC_NRPN_DATA_LSB 38
53
56
#define MIDI_PROGRAM_CHANGE 0b1100
54
57
#define MIDI_PITCH_BEND 0b1110
55
58
@@ -58,6 +61,13 @@ LOGMODULE ("mididevice");
58
61
#define MIDI_TIMING_CLOCK 0xF8
59
62
#define MIDI_ACTIVE_SENSING 0xFE
60
63
64
+ #define MIDI_NRPN_PROGRAM_CHANGE 21
65
+ #define MIDI_NRPN_SAVE_PERFORMANCE 22
66
+
67
+ uint8_t scale (uint8_t max, uint8_t value) {
68
+ return (uint8_t )((((unsigned )value) * max) / 127 );
69
+ }
70
+
61
71
CMIDIDevice::TDeviceMap CMIDIDevice::s_DeviceMap;
62
72
63
73
CMIDIDevice::CMIDIDevice (CMiniDexed *pSynthesizer, CConfig *pConfig, CUserInterface *pUI)
@@ -68,6 +78,8 @@ CMIDIDevice::CMIDIDevice (CMiniDexed *pSynthesizer, CConfig *pConfig, CUserInter
68
78
for (unsigned nTG = 0 ; nTG < CConfig::ToneGenerators; nTG++)
69
79
{
70
80
m_ChannelMap[nTG] = Disabled;
81
+ m_NRPNoffset[nTG] = 0 ;
82
+ m_NRPNop[nTG] = 0 ;
71
83
}
72
84
}
73
85
@@ -347,6 +359,181 @@ void CMIDIDevice::MIDIMessageHandler (const u8 *pMessage, size_t nLength, unsign
347
359
m_pSynthesizer->notesOff (pMessage[2 ], nTG);
348
360
}
349
361
break ;
362
+
363
+ case MIDI_CC_NRPN_PARAM_MSB:
364
+ if (pMessage[2 ] <= 6 ) {
365
+ m_NRPNop[nTG] = pMessage[2 ];
366
+ }
367
+ break ;
368
+
369
+ case MIDI_CC_NRPN_PARAM_LSB:
370
+ m_NRPNoffset[nTG] = pMessage[2 ];
371
+ break ;
372
+
373
+ case MIDI_CC_NRPN_DATA_LSB:
374
+ switch (m_NRPNoffset[nTG])
375
+ {
376
+ case MIDI_NRPN_PROGRAM_CHANGE:
377
+ m_pSynthesizer->ProgramChange (pMessage[2 ], nTG);
378
+ break ;
379
+ case MIDI_NRPN_SAVE_PERFORMANCE:
380
+ m_pSynthesizer->SavePerformance ();
381
+ break ;
382
+ default :
383
+ if (m_NRPNop[nTG] < 6 )
384
+ {
385
+ switch (m_NRPNoffset[nTG]) {
386
+ case DEXED_OP_EG_R1:
387
+ m_pSynthesizer->m_pTG [nTG]->setOPRate (m_NRPNop[nTG], 0 , scale (99 , pMessage[2 ]));
388
+ break ;
389
+ case DEXED_OP_EG_R2:
390
+ m_pSynthesizer->m_pTG [nTG]->setOPRate (m_NRPNop[nTG], 1 , scale (99 , pMessage[2 ]));
391
+ break ;
392
+ case DEXED_OP_EG_R3:
393
+ m_pSynthesizer->m_pTG [nTG]->setOPRate (m_NRPNop[nTG], 2 , scale (99 , pMessage[2 ]));
394
+ break ;
395
+ case DEXED_OP_EG_R4:
396
+ m_pSynthesizer->m_pTG [nTG]->setOPRate (m_NRPNop[nTG], 3 , scale (99 , pMessage[2 ]));
397
+ break ;
398
+ case DEXED_OP_EG_L1:
399
+ m_pSynthesizer->m_pTG [nTG]->setOPLevel (m_NRPNop[nTG], 0 , scale (99 , pMessage[2 ]));
400
+ break ;
401
+ case DEXED_OP_EG_L2:
402
+ m_pSynthesizer->m_pTG [nTG]->setOPLevel (m_NRPNop[nTG], 1 , scale (99 , pMessage[2 ]));
403
+ break ;
404
+ case DEXED_OP_EG_L3:
405
+ m_pSynthesizer->m_pTG [nTG]->setOPLevel (m_NRPNop[nTG], 2 , scale (99 , pMessage[2 ]));
406
+ break ;
407
+ case DEXED_OP_EG_L4:
408
+ m_pSynthesizer->m_pTG [nTG]->setOPLevel (m_NRPNop[nTG], 3 , scale (99 , pMessage[2 ]));
409
+ break ;
410
+ case DEXED_OP_LEV_SCL_BRK_PT:
411
+ m_pSynthesizer->m_pTG [nTG]->setOPKeyboardLevelScalingBreakPoint (m_NRPNop[nTG], scale (99 , pMessage[2 ]));
412
+ break ;
413
+ case DEXED_OP_SCL_LEFT_DEPTH:
414
+ m_pSynthesizer->m_pTG [nTG]->setOPKeyboardLevelScalingDepthLeft (m_NRPNop[nTG], scale (99 , pMessage[2 ]));
415
+ break ;
416
+ case DEXED_OP_SCL_RGHT_DEPTH:
417
+ m_pSynthesizer->m_pTG [nTG]->setOPKeyboardLevelScalingDepthRight (m_NRPNop[nTG], scale (99 , pMessage[2 ]));
418
+ break ;
419
+ case DEXED_OP_SCL_LEFT_CURVE:
420
+ m_pSynthesizer->m_pTG [nTG]->setOPKeyboardLevelScalingCurveLeft (m_NRPNop[nTG], scale (3 , pMessage[2 ]));
421
+ break ;
422
+ case DEXED_OP_SCL_RGHT_CURVE:
423
+ m_pSynthesizer->m_pTG [nTG]->setOPKeyboardLevelScalingCurveRight (m_NRPNop[nTG], scale (3 , pMessage[2 ]));
424
+ break ;
425
+ case DEXED_OP_OSC_RATE_SCALE:
426
+ m_pSynthesizer->m_pTG [nTG]->setOPKeyboardRateScale (m_NRPNop[nTG], scale (7 , pMessage[2 ]));
427
+ break ;
428
+ case DEXED_OP_AMP_MOD_SENS:
429
+ m_pSynthesizer->m_pTG [nTG]->setOPAmpModulationSensity (m_NRPNop[nTG], scale (3 , pMessage[2 ]));
430
+ break ;
431
+ case DEXED_OP_KEY_VEL_SENS:
432
+ m_pSynthesizer->m_pTG [nTG]->setOPKeyboardVelocitySensity (m_NRPNop[nTG], scale (7 , pMessage[2 ]));
433
+ break ;
434
+ case DEXED_OP_OUTPUT_LEV:
435
+ m_pSynthesizer->m_pTG [nTG]->setOPOutputLevel (m_NRPNop[nTG], scale (99 , pMessage[2 ]));
436
+ break ;
437
+ case DEXED_OP_OSC_MODE:
438
+ m_pSynthesizer->m_pTG [nTG]->setOPMode (m_NRPNop[nTG], scale (1 , pMessage[2 ]));
439
+ break ;
440
+ case DEXED_OP_FREQ_COARSE:
441
+ m_pSynthesizer->m_pTG [nTG]->setOPFrequencyCoarse (m_NRPNop[nTG], scale (31 , pMessage[2 ]));
442
+ break ;
443
+ case DEXED_OP_FREQ_FINE:
444
+ m_pSynthesizer->m_pTG [nTG]->setOPFrequencyFine (m_NRPNop[nTG], scale (99 , pMessage[2 ]));
445
+ break ;
446
+ case DEXED_OP_OSC_DETUNE:
447
+ m_pSynthesizer->m_pTG [nTG]->setOPDetune (m_NRPNop[nTG], scale (14 , pMessage[2 ]));
448
+ break ;
449
+ }
450
+ // TODO: send partial update, but this will do for now
451
+ SendSystemExclusiveVoice (0 , 0 , nTG);
452
+ }
453
+ if (m_NRPNop[nTG] == 6 ) {
454
+ switch (m_NRPNoffset[nTG]) {
455
+ case DEXED_PITCH_EG_R1:
456
+ m_pSynthesizer->m_pTG [nTG]->setPitchRate (0 , scale (99 , pMessage[2 ]));
457
+ break ;
458
+ case DEXED_PITCH_EG_R2:
459
+ m_pSynthesizer->m_pTG [nTG]->setPitchRate (1 , scale (99 , pMessage[2 ]));
460
+
461
+ break ;
462
+ case DEXED_PITCH_EG_R3:
463
+ m_pSynthesizer->m_pTG [nTG]->setPitchRate (2 , scale (99 , pMessage[2 ]));
464
+
465
+ break ;
466
+ case DEXED_PITCH_EG_R4:
467
+ m_pSynthesizer->m_pTG [nTG]->setPitchRate (3 , scale (99 , pMessage[2 ]));
468
+
469
+ break ;
470
+ case DEXED_PITCH_EG_L1:
471
+ m_pSynthesizer->m_pTG [nTG]->setPitchLevel (0 , scale (99 , pMessage[2 ]));
472
+
473
+ break ;
474
+ case DEXED_PITCH_EG_L2:
475
+ m_pSynthesizer->m_pTG [nTG]->setPitchLevel (1 , scale (99 , pMessage[2 ]));
476
+
477
+ break ;
478
+ case DEXED_PITCH_EG_L3:
479
+ m_pSynthesizer->m_pTG [nTG]->setPitchLevel (2 , scale (99 , pMessage[2 ]));
480
+
481
+ break ;
482
+ case DEXED_PITCH_EG_L4:
483
+ m_pSynthesizer->m_pTG [nTG]->setPitchLevel (3 , scale (99 , pMessage[2 ]));
484
+
485
+ break ;
486
+ case DEXED_ALGORITHM:
487
+ m_pSynthesizer->m_pTG [nTG]->setAlgorithm (scale (31 , pMessage[2 ]));
488
+
489
+ break ;
490
+ case DEXED_FEEDBACK:
491
+ m_pSynthesizer->m_pTG [nTG]->setFeedback (scale (7 , pMessage[2 ]));
492
+
493
+ break ;
494
+ case DEXED_OSC_KEY_SYNC:
495
+ m_pSynthesizer->m_pTG [nTG]->setOscillatorSync (scale (1 , pMessage[2 ]));
496
+
497
+ break ;
498
+ case DEXED_LFO_SPEED:
499
+ m_pSynthesizer->m_pTG [nTG]->setLFOSpeed (scale (99 , pMessage[2 ]));
500
+
501
+ break ;
502
+ case DEXED_LFO_DELAY:
503
+ m_pSynthesizer->m_pTG [nTG]->setLFODelay (scale (99 , pMessage[2 ]));
504
+
505
+ break ;
506
+ case DEXED_LFO_PITCH_MOD_DEP:
507
+ m_pSynthesizer->m_pTG [nTG]->setLFOPitchModulationDepth (scale (99 , pMessage[2 ]));
508
+
509
+ break ;
510
+ case DEXED_LFO_AMP_MOD_DEP:
511
+ m_pSynthesizer->m_pTG [nTG]->setLFOAmpModulationDepth (scale (99 , pMessage[2 ]));
512
+
513
+ break ;
514
+ case DEXED_LFO_SYNC:
515
+ m_pSynthesizer->m_pTG [nTG]->setLFOSync (scale (1 , pMessage[2 ]));
516
+
517
+ break ;
518
+ case DEXED_LFO_WAVE:
519
+ m_pSynthesizer->m_pTG [nTG]->setLFOWaveform (scale (4 , pMessage[2 ]));
520
+
521
+ break ;
522
+ case DEXED_LFO_PITCH_MOD_SENS:
523
+ m_pSynthesizer->m_pTG [nTG]->setLFOPitchModulationSensitivity (scale (7 , pMessage[2 ]));
524
+
525
+ break ;
526
+ case DEXED_TRANSPOSE:
527
+ m_pSynthesizer->m_pTG [nTG]->setTranspose (scale (48 , pMessage[2 ]));
528
+
529
+ break ;
530
+ }
531
+ // TODO: send partial update, but this will do for now
532
+ SendSystemExclusiveVoice (0 , 0 , nTG);
533
+ }
534
+ }
535
+ break ;
536
+
350
537
}
351
538
break ;
352
539
0 commit comments