@@ -454,6 +454,238 @@ type MonoMachineParameter =
454
454
| EffectDelayFeedback
455
455
| EffectDelayFilterBase
456
456
| EffectDelayFilterWidth
457
- | LFOPage
458
- | LFODest
459
- | LFOTrig
457
+ | LFOPage of OneToThree
458
+ | LFODest of OneToThree
459
+ | LFOTrig of OneToThree
460
+ | LFOWave of OneToThree
461
+ | LFOMultiplier of OneToThree
462
+ | LFOSpeed of OneToThree
463
+ | LFOInterlace of OneToThree
464
+ | LFODepth of OneToThree
465
+
466
+
467
+ module MonoMachineControlChangeLogic =
468
+
469
+ let getLFOCCPageBase lfoPage =
470
+ match lfoPage with
471
+ | OneToThree.One -> 88 uy
472
+ | OneToThree.Two -> 104 uy
473
+ | OneToThree.Three-> 112 uy
474
+
475
+ let isCCLFOPageForPage page cc =
476
+ let baseCC = getLFOCCPageBase page
477
+ cc >= baseCC && cc < baseCC + 8 uy
478
+
479
+ let getLfoParameter cc =
480
+ let page = OneToThree.One
481
+ let pageBase = getLFOCCPageBase page
482
+ if isCCLFOPageForPage page cc then
483
+ match cc - pageBase with
484
+ | 0 uy -> LFOPage page |> Some
485
+ | 1 uy -> LFODest page |> Some
486
+ | 2 uy -> LFOTrig page |> Some
487
+ | 3 uy -> LFOWave page |> Some
488
+ | 4 uy -> LFOMultiplier page |> Some
489
+ | 5 uy -> LFOSpeed page |> Some
490
+ | 6 uy -> LFOInterlace page |> Some
491
+ | 7 uy -> LFODepth page |> Some
492
+ | _ -> None
493
+ else
494
+ None
495
+
496
+
497
+
498
+ let getCC parameter =
499
+ match parameter with
500
+ | SynthParam1 -> 48 uy | SynthParam2 -> 49 uy | SynthParam3 -> 50 uy | SynthParam4 -> 51 uy
501
+ | SynthParam5 -> 52 uy | SynthParam6 -> 53 uy | SynthParam7 -> 54 uy | SynthParam8 -> 55 uy
502
+ | AmplAttack -> 56 uy | AmplHold -> 57 uy | AmplDecay -> 58 uy | AmplRelease -> 59 uy
503
+ | AmplDistortion -> 60 uy | AmplVolume -> 61 uy | AmplPan -> 62 uy | AmplPortamento -> 63 uy
504
+ | FilterBase -> 72 uy | FilterWidth -> 73 uy | FilterHighPassQ -> 74 uy | FilterLowPassQ -> 75 uy
505
+ | FilterAttack -> 76 uy | FilterDecay -> 77 uy | FilterBaseOffset -> 78 uy | FilterWidthOffset -> 79 uy
506
+ | EffectEqFrequency -> 80 uy | EffectEqGain -> 81 uy | EffectSampleRateReduction -> 82 uy | EffectDelayTime -> 83 uy
507
+ | EffectDelaySend -> 84 uy | EffectDelayFeedback -> 85 uy | EffectDelayFilterBase -> 86 uy | EffectDelayFilterWidth -> 87 uy
508
+ | LFOPage page -> getLFOCCPageBase page + 0 uy
509
+ | LFODest page -> getLFOCCPageBase page + 1 uy
510
+ | LFOTrig page -> getLFOCCPageBase page + 2 uy
511
+ | LFOWave page -> getLFOCCPageBase page + 3 uy
512
+ | LFOMultiplier page -> getLFOCCPageBase page + 4 uy
513
+ | LFOSpeed page -> getLFOCCPageBase page + 5 uy
514
+ | LFOInterlace page -> getLFOCCPageBase page + 6 uy
515
+ | LFODepth page -> getLFOCCPageBase page + 7 uy
516
+
517
+ let getFromCC cc =
518
+ match cc with
519
+ | 48 uy -> Some SynthParam1
520
+ | 49 uy -> Some SynthParam2
521
+ | 50 uy -> Some SynthParam3
522
+ | 51 uy -> Some SynthParam4
523
+ | 52 uy -> Some SynthParam5
524
+ | 53 uy -> Some SynthParam6
525
+ | 54 uy -> Some SynthParam7
526
+ | 55 uy -> Some SynthParam8
527
+ | 56 uy -> Some AmplAttack
528
+ | 57 uy -> Some AmplHold
529
+ | 58 uy -> Some AmplDecay
530
+ | 59 uy -> Some AmplRelease
531
+ | 60 uy -> Some AmplDistortion
532
+ | 61 uy -> Some AmplVolume
533
+ | 62 uy -> Some AmplPan
534
+ | 63 uy -> Some AmplPortamento
535
+ | 72 uy -> Some FilterBase
536
+ | 73 uy -> Some FilterWidth
537
+ | 74 uy -> Some FilterHighPassQ
538
+ | 75 uy -> Some FilterLowPassQ
539
+ | 76 uy -> Some FilterAttack
540
+ | 77 uy -> Some FilterDecay
541
+ | 78 uy -> Some FilterBaseOffset
542
+ | 79 uy -> Some FilterWidthOffset
543
+ | 80 uy -> Some EffectEqFrequency
544
+ | 81 uy -> Some EffectEqGain
545
+ | 82 uy -> Some EffectSampleRateReduction
546
+ | 83 uy -> Some EffectDelayTime
547
+ | 84 uy -> Some EffectDelaySend
548
+ | 85 uy -> Some EffectDelayFeedback
549
+ | 86 uy -> Some EffectDelayFilterBase
550
+ | 87 uy -> Some EffectDelayFilterWidth
551
+ | cc ->
552
+ getLfoParameter cc
553
+
554
+ type LFOEvent =
555
+ | AssignDest of Track * MonoMachineParameter
556
+
557
+
558
+ type MonoMachineEvent =
559
+ | TrackLevel of Track * value : byte
560
+ | TrackParameter of Track * MonoMachineParameter * value : byte
561
+ | TrackTrigger of Track * note : byte * velocity : byte
562
+ | TrackRelease of Track * note : byte * velocity : byte
563
+ | PatternChanged of PatternLocator
564
+ | LFOSetting of Track * LFOEvent
565
+ | Unknown of MidiMessage
566
+ | MonoMachineSysex of MonoMachineSysexResponse
567
+ | Sysex of byte array
568
+ | KitChanged of byte
569
+ | SequencerStarted
570
+ | SequencerStopped
571
+ | PatternSelected of PatternLocator
572
+ //| Note of Track * noteNumber: byte * velocity: byte
573
+
574
+
575
+
576
+
577
+ type TimestampedMessage < 't > = {
578
+ Timestamp : int
579
+ Message: 't
580
+ }
581
+
582
+
583
+ type MonoMachineEventListener ( getNow : unit -> int , mm : MonoMachine ) =
584
+ let settings = mm.CurrentGlobalSettings |> Option.map GlobalSettings.FromSysex
585
+ //let settings = { GlobalSettings.midiBaseChannel = 0uy }
586
+ let midiIn = mm.MidiOutPort
587
+ let midiRealtimeState = Midi.Registers.MidiRealtimeState()
588
+ let event = new Event<_>()
589
+
590
+ let makeMessage timestamp m = { Timestamp = timestamp; Message = m}
591
+
592
+ let onChannelMessage ( midiEvent : MidiEvent < _ >) =
593
+ match settings with
594
+ | None -> Unknown midiEvent.Message
595
+ | Some settings ->
596
+ let message = midiEvent.Message
597
+ let messageChannel = message.Channel.Value
598
+ let midiChannelIsTrack = messageChannel >= settings.midiChannel && messageChannel < ( settings.midiChannel + 6 uy)
599
+ if midiChannelIsTrack then
600
+ let track = Track.FromByte ( byte ( messageChannel - settings.midiChannel))
601
+ match message with
602
+ | Midi.MessageMatching.NoteOn (_, note, velocity) -> TrackTrigger( track, note, velocity)
603
+ | Midi.MessageMatching.NoteOff (_, note, velocity) -> TrackRelease( track, note, velocity)
604
+ | Midi.MessageMatching.ProgramChange { program = program} ->
605
+
606
+ let locator = PatternLocator.FromByte program
607
+ PatternSelected( locator)
608
+ | _ -> Unknown message
609
+
610
+
611
+ else
612
+ Unknown message
613
+
614
+ let onSysexMessage sysex =
615
+ Sysex sysex
616
+
617
+ let realtimeListener = midiIn.RealtimeMessageReceived.Subscribe( fun m ->
618
+ let oldStarted = midiRealtimeState.started
619
+ midiRealtimeState.UpdateWithEvent m.Message
620
+ if oldStarted <> midiRealtimeState.started then
621
+ { Timestamp = m.Timestamp; Message = ( if midiRealtimeState.started then SequencerStarted else SequencerStopped)} |> event.Trigger
622
+ )
623
+ let channelMessageListener = midiIn.ChannelMessageReceived.Subscribe( fun m ->
624
+ //midiBaseChannel
625
+ let message = onChannelMessage m
626
+ { Timestamp = m.Timestamp; Message = message } |> event.Trigger
627
+ )
628
+ let sysexListener = midiIn.SysexReceived.Subscribe( fun m ->
629
+ let timestamp = getNow()
630
+ let message = onSysexMessage m
631
+ { Timestamp = timestamp; Message = message } |> event.Trigger
632
+ )
633
+ interface System.IDisposable with
634
+ member x.Dispose () =
635
+ realtimeListener.Dispose()
636
+ sysexListener.Dispose()
637
+ channelMessageListener.Dispose()
638
+
639
+ [<CLIEvent>] member x.Event = event.Publish
640
+
641
+
642
+ (*
643
+ type MonoMachineEventListener(mnm: MonoMachine, getNow : unit -> int) =
644
+ let mutable mnmGlobals = mnm.CurrentGlobalSettings
645
+ let midiIn = mnm.MidiOutPort
646
+ let event = new Event<_>()
647
+
648
+ let onChannelMessage (midiEvent: MidiEvent<_>) =
649
+ let message = midiEvent.Message
650
+ let messageChannel = midiEvent.Message.Channel.Value
651
+ match mnmGlobals with
652
+ | None ->
653
+ Unknown message
654
+ | Some globals ->
655
+
656
+ let midiBaseChannel = globals.MidiBaseChannel
657
+ let track =
658
+ if messageChannel >= midiBaseChannel && messageChannel < midiBaseChannel + 6 then
659
+ Some (Track.FromByte (channel - midiBaseChannel))
660
+ else
661
+ None
662
+
663
+ match message with
664
+ | ProgramChange {_;program;other} -> PatternChanged (PatternLocator.FromByte program)
665
+ | CC {_;control;value} ->
666
+ match track with
667
+ | Some track ->
668
+ match MonoMachineControlChangeLogic.getFromCC control with
669
+ | Some mnmParam -> TrackParameter(track,mnmParam,value)
670
+ | None -> Unknown message
671
+ | None -> Unknown message
672
+ | None -> Unknown message
673
+
674
+ let channelMessageListener = midiIn.ChannelMessageReceived.Subscribe(fun m ->
675
+ let message = onChannelMessage m
676
+ { Timestamp = (m.Timestamp); Message = message } |> event.Trigger
677
+ )
678
+ let onSysexMessage (sysex: byte array) =
679
+ Sysex sysex
680
+
681
+ let sysexListener = midiIn.SysexReceived.Subscribe(fun m ->
682
+ // TODO TODO
683
+ let timestamp = getNow()
684
+ let message = onSysexMessage m
685
+ { Timestamp = timestamp; Message = message } |> event.Trigger
686
+ )
687
+ interface IDisposable with
688
+ member x.Dispose() =
689
+ sysexListener.Dispose()
690
+ channelMessageListener.Dispose()
691
+ *)
0 commit comments