Skip to content

Commit 7bc5177

Browse files
MTS stuff
1 parent 674c0eb commit 7bc5177

File tree

1 file changed

+71
-24
lines changed

1 file changed

+71
-24
lines changed

src/Midinette/Midi.Tuning.fs

Lines changed: 71 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,44 @@
11
module Midi.Tuning
22
open Midi
3-
3+
// based on specs from midi.org
4+
// additional spec: http://www.somascape.org/midi/tech/spec.html#usx7E0800
45
type MessageId =
56
| DumpRequestId = 0uy
67
| DumpResponseId = 1uy
78
| SingleNoteTuningChangeId = 2uy
89

910
let makeSysex deviceId (messageId: MessageId) data =
11+
let requiresCheckSum =
12+
if messageId = MessageId.DumpResponseId then true
13+
else false
14+
15+
let bytesForChecksum =
16+
[|
17+
[|
18+
0x7euy
19+
deviceId
20+
0x08uy
21+
byte messageId
22+
|]
23+
data
24+
|]
25+
|> Array.concat
26+
27+
let checkSum =
28+
if requiresCheckSum then
29+
let mutable sum = 0uy
30+
for b in bytesForChecksum do
31+
sum <- sum ^^^ b
32+
[|sum|]
33+
else
34+
[||]
35+
1036
[|
1137
[|
1238
0xf0uy
13-
0x7euy
14-
deviceId
15-
0x08uy
16-
byte messageId
1739
|]
18-
data
40+
bytesForChecksum
41+
checkSum
1942
[|
2043
0xf7uy
2144
|]
@@ -28,17 +51,22 @@ type NoteTuning =
2851
cents : decimal
2952
}
3053

54+
type NoteTuningChange =
55+
| NoFrequency
56+
//| Hertz of hertz: decimal
57+
| NoteAndCents of NoteTuning
58+
3159
type BulkTuningDumpResponse =
3260
{
3361
name : string
3462
programNumber: byte
35-
tunings : NoteTuning array
63+
tunings : NoteTuningChange array
3664
}
3765

3866
type TuningMessage =
3967
| BulkTuningDumpRequest of tuningProgramNumber: byte
4068
| BulkTuningDump of BulkTuningDumpResponse
41-
| SingleNoteTuningChange of noteIndexAndTunings: (byte * NoteTuning) array
69+
| SingleNoteTuningChange of noteIndexAndTunings: (byte * NoteTuningChange) array
4270
| TuningProgramSelect of program: byte * channel: byte // + do RPNs inc/dec
4371
with
4472
member x.IsRealTime =
@@ -56,30 +84,52 @@ with
5684
| TuningProgramSelect _ -> None
5785

5886
member x.SysexData =
87+
let centIncrement = 0.0061m
88+
let centsAsShorts cents = int16 (cents / centIncrement)
89+
let centFirstByte centsAsShort = byte ((centsAsShort >>> 7) &&& 0b01111111s)
90+
let centSecondByte centsAsShort = byte (centsAsShort &&& 0b01111111s)
5991
match x with
6092
| BulkTuningDumpRequest programNumber -> Some [|programNumber|]
61-
| BulkTuningDump _ -> Some [||]
93+
| BulkTuningDump {name=name; programNumber=programNumber; tunings=tunings} ->
94+
Some
95+
[|
96+
yield programNumber
97+
yield! (System.Text.Encoding.ASCII.GetBytes (name.PadLeft 16))
98+
for tuning in tunings do
99+
match tuning with
100+
| NoFrequency -> yield! [|0x7fuy; 0x7fuy; 0x7fuy |]
101+
| NoteAndCents(tuning) ->
102+
let centsAsShort = centsAsShorts tuning.cents
103+
let centFirstByte = centFirstByte centsAsShort
104+
let centSecondByte = centSecondByte centsAsShort
105+
yield! [|tuning.semiTone; centFirstByte; centSecondByte|]
106+
|]
62107
| SingleNoteTuningChange tunings ->
63108
Some(
64109
[|
65110
for (noteIndex, tuning) in tunings do
66-
let centIncrement = 0.0061m
67-
let centsAsShort = int16 (tuning.cents / centIncrement)
68-
let centFirstByte = byte ((centsAsShort >>> 7) &&& 0b01111111s)
69-
let centSecondByte = byte (centsAsShort &&& 0b01111111s)
70-
yield! [|noteIndex; tuning.semiTone; centFirstByte; centSecondByte|]
111+
match tuning with
112+
| NoFrequency -> yield! [|noteIndex; 0x7fuy; 0x7fuy; 0x7fuy |]
113+
| NoteAndCents(tuning) ->
114+
let centsAsShort = centsAsShorts tuning.cents
115+
let centFirstByte = centFirstByte centsAsShort
116+
let centSecondByte = centSecondByte centsAsShort
117+
yield! [|noteIndex; tuning.semiTone; centFirstByte; centSecondByte|]
71118
|]
72119
)
73120
| TuningProgramSelect _ -> None
74121

75-
76-
77-
member x.Send (deviceId: byte, midiOutput: IMidiOutput<_>, nowTimestamp) =
122+
member x.MakeMTSSysex deviceId =
78123
let sysex, messageId = x.SysexData, x.MessageId
79124
match sysex, messageId with
80-
| Some (data), Some (messageId) ->
81-
midiOutput.WriteSysex (nowTimestamp()) (makeSysex deviceId messageId data)
82-
| _ -> ()
125+
| Some data, Some messageId ->
126+
Some (makeSysex deviceId messageId data)
127+
| _ -> None
128+
129+
member x.Send (deviceId: byte, midiOutput: IMidiOutput<_>, nowTimestamp) =
130+
match x.MakeMTSSysex deviceId with
131+
| Some sysex -> midiOutput.WriteSysex (nowTimestamp()) sysex
132+
| None -> ()
83133

84134
match x with
85135
| BulkTuningDumpRequest _ | BulkTuningDump _ | SingleNoteTuningChange _ -> ()
@@ -89,8 +139,5 @@ with
89139
//midiOutput.WriteMessages (nowTimestamp()) messages
90140
()
91141
(*
92-
type NoteTuningChange =
93-
| NoFrequency
94-
| Hertz of hertz: decimal
95-
| NoteAndCents of NoteTuning
142+
96143
*)

0 commit comments

Comments
 (0)