Skip to content

Commit 86814e9

Browse files
experimentation with F# units of measure, not expecting this to remain as is or to be gone soon.
1 parent 7ff5349 commit 86814e9

16 files changed

+454
-671
lines changed

paket.dependencies

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ source https://nuget.org/api/v2
55
storage: none
66
redirects: force
77
clitool dotnet-fable
8+
github fsprojects/FSharp.UMX src/FSharp.UMX.fs
89
nuget Fable.Core
910
nuget Fable.Promise
1011
nuget Fable.Import.Browser

paket.lock

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -566,6 +566,8 @@ NUGET
566566
RtMidi.Core (1.0.59-alpha-3)
567567
Serilog (>= 2.8) - restriction: || (>= net45) (>= netstandard2.0)
568568
System.ValueTuple (>= 4.5) - restriction: || (>= net45) (>= netstandard2.0)
569-
569+
GITHUB
570+
remote: fsprojects/FSharp.UMX
571+
src/FSharp.UMX.fs (3d887477c075ad498faa9f5c24844d2a2c6e5c12)
570572
GROUP Build
571573
RESTRICTION: >= net461

src/Midinette.Elektron/Elektron.MachineDrum.fs

Lines changed: 254 additions & 532 deletions
Large diffs are not rendered by default.

src/Midinette.Elektron/Elektron.MonoMachine.fs

Lines changed: 64 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
module Elektron.MonoMachine
2-
2+
open FSharp.UMX
33
open System
44
open Midi
5+
56
open Midinette.Platform
67
open Elektron.Platform
78
open Elektron.Platform.SilverMachines
@@ -19,21 +20,22 @@ type LFOShape =
1920
match value with
2021
| _ -> failwithf "%i not defined" value
2122

22-
2323
type LFOMultiplier = Times1 | Times2 | Times4 | Times8 | Times16 | Times32 | Times64
2424

2525
module internal Helpers =
26-
let monoMachineHeader = [|
26+
let monoMachineHeader =
27+
[|
2728
0xf0uy
2829
0x00uy
2930
0x20uy
3031
0x3cuy
3132
0x03uy
3233
0x00uy
3334
|]
35+
|> UMX.tag_sysex_data
3436

3537
let makeSysexMessage message =
36-
let sysexEnd = [|0xf7uy|]
38+
let sysexEnd = [|UMX.tag_sysex_data 0xf7uy|]
3739
Array.concat [|monoMachineHeader;message;sysexEnd|]
3840

3941
open Helpers
@@ -58,8 +60,8 @@ with
5860
| SequencerMode -> 0x10uy
5961
| AudioMode -> 0x20uy
6062
| SequencerModeMode -> 0x21uy
61-
static member FromByte v =
62-
match v with
63+
static member FromByte (v: byte<_>) =
64+
match UMX.untag v with
6365
| 0x01uy -> GlobalSlot
6466
| 0x02uy -> KitNumber
6567
| 0x04uy -> PatternNumber
@@ -73,7 +75,7 @@ with
7375
type Track = Track1 | Track2 | Track3 | Track4 | Track5 | Track6
7476
with
7577
static member FromByte b =
76-
match b with
78+
match UMX.untag_byte_7bits b with
7779
| 0x0uy -> Track1
7880
| 0x1uy -> Track2
7981
| 0x2uy -> Track3
@@ -173,7 +175,7 @@ type MachineParameters(bytes: byte array) =
173175
member x.MIDI = getBytes midiBase
174176
member x.ADSR = getBytes adsrBase
175177

176-
type MonoMachineKit (data: byte array) =
178+
type MonoMachineKit (data: sysex_data) =
177179
member x.Version = data.[0x07]
178180
member x.Revision = data.[0x08]
179181
member x.OriginalPosition = data.[0x09]
@@ -186,17 +188,17 @@ type MonoMachineKit (data: byte array) =
186188
|> dataToByte
187189
//else [||]
188190
member x.Name =
189-
x.unpacked |> getSlice 0 11 |> ASCIIEncoding.ASCII.GetString
191+
x.unpacked |> SysexBufferEdit.getSlice 0 11 |> unbox |> ASCIIEncoding.ASCII.GetString
190192
member x.Levels =
191-
x.unpacked |> getSlice 0xb 6
193+
x.unpacked |> SysexBufferEdit.getSlice 0xb 6
192194
member x.Parameters =
193195
x.unpacked
194-
|> getSlice 0x11 (72 * 6)
196+
|> SysexBufferEdit.getSlice 0x11 (72 * 6)
195197
|> Array.chunkBySize 72
196198
|> Array.map MachineParameters
197199
member x.Machines =
198200
x.unpacked
199-
|> getSlice 0x1c1 6
201+
|> SysexBufferEdit.getSlice 0x1c1 6
200202
|> Array.map ((&&&) 0b01111111uy)
201203
|> Array.map MonoMachineType.FromValue
202204

@@ -214,57 +216,58 @@ with
214216
| Fixed v -> v
215217

216218
type GlobalSettings = {
217-
midiChannelAutoTrack : byte
218-
midiChannel : byte
219-
midiChannelMultiTrig : byte
220-
midiChannelMultiMap : byte
221-
midiMachineChannels : byte array
222-
ccDestinationsPerChannel: byte array array
219+
midiChannelAutoTrack : byte_7bits
220+
midiChannel : byte_7bits
221+
midiChannelMultiTrig : byte_7bits
222+
midiChannelMultiMap : byte_7bits
223+
midiMachineChannels : byte_7bits array
224+
ccDestinationsPerChannel: byte_7bits array array
223225
programChangeIn : bool
224226
velocityCurve : VelocityCurve
225-
fixedVelocity : byte
226-
knobSpeed : byte
227+
fixedVelocity : byte_7bits
228+
knobSpeed : byte_7bits
227229
baseFrequency : int
228230
}
229231
with
230232
static member Default =
231233
{
232-
midiChannelAutoTrack= 8uy
233-
midiChannel = 0uy
234-
midiChannelMultiTrig = 7uy
235-
midiChannelMultiMap = 08uy
236-
midiMachineChannels = [|0uy .. 05uy|]
234+
midiChannelAutoTrack = UMX.tag_byte_7bits 8uy
235+
midiChannel = UMX.tag_byte_7bits 0uy
236+
midiChannelMultiTrig = UMX.tag_byte_7bits 7uy
237+
midiChannelMultiMap = UMX.tag_byte_7bits 08uy
238+
midiMachineChannels = UMX.tag_byte_7bits [|0uy .. 05uy|]
237239
ccDestinationsPerChannel= [||]
238240
programChangeIn = true
239241
velocityCurve = VelocityCurve.Linear
240-
fixedVelocity = 0uy
241-
knobSpeed = 0uy
242+
fixedVelocity = UMX.tag_byte_7bits 0uy
243+
knobSpeed = UMX.tag_byte_7bits 0uy
242244
baseFrequency = 440
243245

244246
}
245-
static member FromSysex (sysexData: byte array) =
247+
static member FromSysex (sysexData: sysex_data) =
246248
// note: this is just plain broken on hardware side
247249
if areMonoMachineCheckSumAndLengthValid sysexData then
248250
let globalData =
249251
(getMonoMachineDataSliceFromSysexMessage sysexData)
250252
|> Seq.toArray
251-
|> Elektron.Platform.dataToByte
253+
|> dataToByte
254+
252255
//if globalData.Length < 0x101 then None
253256
//else
254257
Some
255258
{
256-
midiChannelAutoTrack = globalData.[0x00]
257-
midiChannel = globalData.[0x01]
258-
midiChannelMultiTrig = globalData.[0x02]
259-
midiChannelMultiMap = globalData.[0x03]
259+
midiChannelAutoTrack = UMX.tag_byte_7bits globalData.[0x00]
260+
midiChannel = UMX.tag_byte_7bits globalData.[0x01]
261+
midiChannelMultiTrig = UMX.tag_byte_7bits globalData.[0x02]
262+
midiChannelMultiMap = UMX.tag_byte_7bits globalData.[0x03]
260263
midiMachineChannels = [||]//globalData.[0x12..0x1]
261264

262265
// external sync
263266
ccDestinationsPerChannel = [||]//[|globalData.[0x18..0x1]|]
264267
programChangeIn = true //globalData.[0xfd] = 1uy
265268
velocityCurve = VelocityCurve.Fixed 1uy //globalData.[0xff] |> VelocityCurve.FromByte
266-
fixedVelocity = 0uy //globalData.[0x100]
267-
knobSpeed = 0uy//globalData.[0x101]
269+
fixedVelocity = UMX.tag_byte_7bits 0uy //globalData.[0x100]
270+
knobSpeed = UMX.tag_byte_7bits 0uy//globalData.[0x101]
268271
baseFrequency = 0 //globalData.[0x104..] |> Elektron.fourBytesToBigEndianInt
269272
}
270273
else
@@ -274,26 +277,26 @@ with
274277
type MonoMachineSysexResponse =
275278
| GlobalSettings of GlobalSettings
276279
| Kit of MonoMachineKit
277-
| Pattern of byte array
278-
| Song of byte array
279-
| StatusResponse of statusType: MonoMachineStatusType * value: byte
280+
| Pattern of sysex_data
281+
| Song of sysex_data
282+
| StatusResponse of statusType: MonoMachineStatusType * value: byte_7bits
280283
with
281-
static member BuildResponse (bytes: byte array) =
282-
match bytes.[6] with
283-
| 72uy -> StatusResponse(MonoMachineStatusType.FromByte bytes.[7], bytes.[8])
284+
static member BuildResponse (bytes: sysex_data) =
285+
match UMX.untag_sysex bytes.[6] with
286+
| 72uy -> StatusResponse(MonoMachineStatusType.FromByte bytes.[7], UMX.to_byte_7bits bytes.[8])
284287
| 0x50uy -> GlobalSettings (GlobalSettings.FromSysex(bytes).Value)
285288
| 0x52uy -> Kit (MonoMachineKit(bytes))
286289
| 0x67uy -> Pattern bytes
287290
| _ -> failwithf "h:%x response not understood" bytes.[6]
288291

289292

290293
type MonoMachineSysexRequests =
291-
| DumpGlobalSettings of globalSettingsIndex: byte
292-
| DumpKit of kit: byte
293-
| DumpPattern of pattern: byte
294-
| DumpSong of song: byte
294+
| DumpGlobalSettings of globalSettingsIndex: byte_7bits
295+
| DumpKit of kit: byte_7bits
296+
| DumpPattern of pattern: byte_7bits
297+
| DumpSong of song: byte_7bits
295298
| QueryStatus of statusType: MonoMachineStatusType
296-
| AssignMachine of track: byte * machine: MonoMachineType * parametersMode: AssignMachineParameterMode
299+
| AssignMachine of track: byte_7bits * machine: MonoMachineType * parametersMode: AssignMachineParameterMode
297300
with
298301
member x.MessageId =
299302
match x with
@@ -306,13 +309,14 @@ with
306309
member x.Sysex =
307310
let data =
308311
match x with
309-
| DumpGlobalSettings id -> id |> Array.singleton
310-
| DumpKit kit -> kit |> Array.singleton
311-
| DumpPattern pattern -> pattern |> Array.singleton
312-
| DumpSong song -> song |> Array.singleton
312+
| DumpGlobalSettings id -> id |> UMX.untag |> Array.singleton
313+
| DumpKit kit -> kit |> UMX.untag |> Array.singleton
314+
| DumpPattern pattern -> pattern |> UMX.untag |> Array.singleton
315+
| DumpSong song -> song |> UMX.untag |> Array.singleton
313316
| QueryStatus status -> status.Id |> Array.singleton
314-
| AssignMachine (t,m,p) -> [|t;m.Value;p.Value|]
315-
makeSysexMessage (Array.concat ([|x.MessageId |> Array.singleton; data|]))
317+
| AssignMachine (t,m,p) -> [|UMX.untag t;UMX.untag m.Value;UMX.untag p.Value|]
318+
let data = UMX.tag_sysex_data data
319+
makeSysexMessage (Array.concat ([|x.MessageId |> UMX.tag_sysex_data |> Array.singleton; data|]))
316320
member x.ResponseMessageId =
317321
match x with
318322
| DumpGlobalSettings _
@@ -327,7 +331,7 @@ with
327331
| DumpKit _ -> Some <| Kit(MonoMachineKit data)
328332
| DumpPattern _ -> Some <| Pattern data
329333
| DumpSong _ -> Some <| Song data
330-
| QueryStatus _ -> Some <| StatusResponse((MonoMachineStatusType.FromByte data.[monoMachineHeader.Length + 1]), data.[monoMachineHeader.Length + 2])
334+
| QueryStatus _ -> Some <| StatusResponse((MonoMachineStatusType.FromByte data.[monoMachineHeader.Length + 1]), UMX.to_byte_7bits data.[monoMachineHeader.Length + 2])
331335
| AssignMachine(_) -> failwithf "not implemented"
332336
//| _ -> None
333337

@@ -347,8 +351,8 @@ type MonoMachine<'timestamp>(inPort: IMidiInput<'timestamp>, outPort: IMidiOutpu
347351
maxMessage
348352
timeout
349353
(fun sysex ->
350-
sysex.[0..5] = Helpers.monoMachineHeader
351-
&& Some sysex.[6] = request.ResponseMessageId
354+
sysex.[0..5] = monoMachineHeader
355+
&& Some (UMX.untag_sysex sysex.[6]) = request.ResponseMessageId
352356
)
353357
request.BuildResponse
354358
inPort
@@ -647,7 +651,7 @@ type MonoMachineEvent =
647651
| Unknown of MidiMessage
648652
| UnknownNRPN of Midi.Nrpn.NRPNEvent
649653
| MonoMachineSysex of MonoMachineSysexResponse
650-
| Sysex of byte array
654+
| Sysex of sysex_data
651655
| KitChanged of byte
652656
| SequencerStarted
653657
| SequencerStopped
@@ -706,12 +710,12 @@ type MonoMachineEventListener<'timestamp>
706710
let settings = GlobalSettings.Default //settings |> Option.defaultValue
707711
let message = midiEvent.Message
708712
let messageChannel = message.Channel.Value
709-
let midiChannelIsTrack = messageChannel >= settings.midiChannel && messageChannel < (settings.midiChannel + 6uy)
713+
let midiChannelIsTrack = messageChannel >= settings.midiChannel && messageChannel < (settings.midiChannel + (UMX.tag_byte_7bits 6uy))
710714
if midiChannelIsTrack then
711-
let track = Track.FromByte (byte (messageChannel - settings.midiChannel))
715+
let track = Track.FromByte (messageChannel - settings.midiChannel)
712716
match message with
713-
| NoteOn (_, note, velocity) -> TrackTrigger(track, note, velocity)
714-
| NoteOff (_, note, velocity) -> TrackRelease(track, note, velocity)
717+
| NoteOn (_, note, velocity) -> TrackTrigger(track, UMX.tag note, velocity)
718+
| NoteOff (_, note, velocity) -> TrackRelease(track, UMX.tag note, velocity)
715719
| ProgramChange {program = program} ->
716720
let locator = PatternLocator.FromByte program
717721
PatternSelected(locator)

0 commit comments

Comments
 (0)