1
+ module Midi.Tuning
2
+ open Midi
3
+
4
+ type MessageId =
5
+ | DumpRequestId = 0 uy
6
+ | DumpResponseId = 1 uy
7
+ | SingleNoteTuningChangeId = 2 uy
8
+
9
+ let makeSysex deviceId ( messageId : MessageId ) data =
10
+ [|
11
+ [|
12
+ 0xf0 uy
13
+ 0x7e uy
14
+ deviceId
15
+ 0x08 uy
16
+ byte messageId
17
+ |]
18
+ data
19
+ [|
20
+ 0xf7 uy
21
+ |]
22
+ |]
23
+ |> Array.concat
24
+
25
+ type NoteTuning =
26
+ {
27
+ semiTone: byte
28
+ cents : decimal
29
+ }
30
+
31
+ type BulkTuningDumpResponse =
32
+ {
33
+ name : string
34
+ programNumber: byte
35
+ tunings : NoteTuning array
36
+ }
37
+
38
+ type TuningMessage =
39
+ | BulkTuningDumpRequest of tuningProgramNumber : byte
40
+ | BulkTuningDump of BulkTuningDumpResponse
41
+ | SingleNoteTuningChange of noteIndexAndTunings : ( byte * NoteTuning ) array
42
+ | TuningProgramSelect of program : byte * channel : byte // + do RPNs inc/dec
43
+ with
44
+ member x.IsRealTime =
45
+ match x with
46
+ | TuningProgramSelect _ | SingleNoteTuningChange _ -> true
47
+ | BulkTuningDumpRequest _
48
+ | BulkTuningDump _
49
+ -> false
50
+
51
+ member x.MessageId =
52
+ match x with
53
+ | BulkTuningDumpRequest _ -> Some MessageId.DumpRequestId
54
+ | BulkTuningDump _ -> Some MessageId.DumpResponseId
55
+ | SingleNoteTuningChange _ -> Some MessageId.SingleNoteTuningChangeId
56
+ | TuningProgramSelect _ -> None
57
+
58
+ member x.SysexData =
59
+ match x with
60
+ | BulkTuningDumpRequest programNumber -> Some [| programNumber|]
61
+ | BulkTuningDump _ -> Some [||]
62
+ | SingleNoteTuningChange tunings ->
63
+ Some(
64
+ [|
65
+ for ( noteIndex, tuning) in tunings do
66
+ let centIncrement = 0.0061 m
67
+ let centsAsShort = int16 ( tuning.cents / centIncrement)
68
+ let centFirstByte = byte (( centsAsShort >>> 7 ) &&& 0b01111111 s)
69
+ let centSecondByte = byte ( centsAsShort &&& 0b01111111 s)
70
+ yield ! [| noteIndex; tuning.semiTone; centFirstByte; centSecondByte|]
71
+ |]
72
+ )
73
+ | TuningProgramSelect _ -> None
74
+
75
+
76
+
77
+ member x.Send ( deviceId : byte , midiOutput : IMidiOutput < _ >, nowTimestamp ) =
78
+ let sysex , messageId = x.SysexData, x.MessageId
79
+ match sysex, messageId with
80
+ | Some ( data), Some ( messageId) ->
81
+ midiOutput.WriteSysex ( nowTimestamp()) ( makeSysex deviceId messageId data)
82
+ | _ -> ()
83
+
84
+ match x with
85
+ | BulkTuningDumpRequest _ | BulkTuningDump _ | SingleNoteTuningChange _ -> ()
86
+ | TuningProgramSelect _ ->
87
+ //let rpn = 3
88
+ //let messages = Midi.Nrpn.makeNRPN2 1uy 1uy 1uy
89
+ //midiOutput.WriteMessages (nowTimestamp()) messages
90
+ ()
91
+ (*
92
+ type NoteTuningChange =
93
+ | NoFrequency
94
+ | Hertz of hertz: decimal
95
+ | NoteAndCents of NoteTuning
96
+ *)
0 commit comments