Skip to content

Commit d88a744

Browse files
Read: a bit of midievent parsing
1 parent 3ae3016 commit d88a744

File tree

3 files changed

+45
-21
lines changed

3 files changed

+45
-21
lines changed

src/ZMidi/DataTypes.fs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ type word16 = uint16
66
type word32 = uint32
77
type bits7 = byte
88
type midichannel = byte
9-
type [<Struct>] DeltaTime(value: int32) =
9+
type [<Struct>] DeltaTime(value: word32) =
1010
member x.Value = value
1111

1212
type [<Struct>] word14(value: word16) =

src/ZMidi/Internal/ParserMonad.fs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -175,7 +175,13 @@ module ParserMonad =
175175
sk st2 (a1 :: ac))
176176
work length state (fun msg -> Error msg) (fun st ac -> Ok (ac, st))
177177
|> Result.map (fun (ans, st) -> (List.toArray ans, st))
178+
179+
/// Apply the parser for /count/ times, derive the final answer
180+
/// from the intermediate list with the supplied function.
181+
let inline gencount (plen: ParserMonad<'T>) (p: ParserMonad<'a>) (constr: ^T -> 'a array -> 'answer) : ParserMonad<'answer> =
182+
failwith "gencount: not implemented"
178183

184+
/// Run a parser within a bounded section of the input stream.
179185
let inline boundRepeat (n: ^T) (p: ParserMonad<'a>) : ParserMonad<'a array> =
180186
parseMidi {
181187
let l = Array.zeroCreate (int n) // can't use array expression inside a CE (at least as is)

src/ZMidi/Read.fs

Lines changed: 38 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,16 @@ module ReadFile =
3434
let assertWord32 i =
3535
postCheck readUInt32be ((=) i) (Other (sprintf "assertWord32: expected '%i'" i))
3636

37+
let assertWord8 i =
38+
postCheck readByte ((=) i) (Other (sprintf "assertWord8: expected '%i'" i))
39+
40+
let getVarlen : ParserMonad<word32> =
41+
parseMidi {
42+
failwith "getVarlen: not imple"
43+
}
44+
45+
let getVarlenText = gencount getVarlen readChar (fun _ b -> System.String b)
46+
3747
let fileFormat =
3848
parseMidi {
3949
match! readUInt16be with
@@ -64,46 +74,54 @@ module ReadFile =
6474
let! _ = assertString "MTrk"
6575
return! readUInt32be
6676
}
67-
let event : ParserMonad<MidiMessage> =
77+
let textEvent textType =
6878
parseMidi {
69-
return! fatalError (Other "not implemented") }
70-
let getVarLen : ParserMonad<uint32> =
79+
let! text = getVarlenText
80+
return TextEvent(textType, text)
81+
}
82+
let metaEventSequenceNumber =
7183
parseMidi {
72-
return! fatalError (Other "not implemented")
73-
//getVarlen :: ParserM Word32
74-
//getVarlen = liftM fromVarlen step1
75-
// where
76-
// step1 = word8 >>= \a -> if msbHigh a then step2 a else return (V1 a)
77-
// step2 a = word8 >>= \b -> if msbHigh b then step3 a b else return (V2 a b)
78-
// step3 a b = word8 >>= \c -> if msbHigh c then do { d <- word8
79-
// ; return (V4 a b c d) }
80-
// else return (V3 a b c)
81-
82-
84+
let! a = assertWord8 2uy
85+
let! b = peek
86+
return SequenceNumber(word16be a b)
8387
}
88+
89+
let metaEventGenericText =
90+
parseMidi {
91+
let! a = assertWord8 2uy
92+
let! b = peek
93+
return! textEvent GenericText
94+
}
95+
let metaEvent i =
96+
parseMidi {
97+
match i with
98+
| 0x00 -> return metaEventSequenceNumber
99+
| 0x01 -> return metaEventGenericText
100+
}
101+
let event : ParserMonad<MidiEvent> =
102+
parseMidi {
103+
return! fatalError (Other "event: not implemented") }
84104

85105

86106
let deltaTime =
87107
parseMidi {
88-
return! getVarLen
108+
return! getVarlen
89109
} <??> (fun p -> "delta time")
90110

91111
let message =
92112
parseMidi {
93113
let! deltaTime = deltaTime
94114
let! event = event
95-
return deltaTime, event
115+
return { timestamp = DeltaTime(deltaTime); event = event }
96116
}
97117
let messages i =
98118
parseMidi {
99-
return! boundRepeat i message
119+
return! boundRepeat (int i) message
100120
}
101121
let track : ParserMonad<MidiTrack> =
102122
parseMidi {
103123
let! length = trackHeader
104-
let! messages = messages length
105-
return! fatalError (Other "not implemented")
106-
124+
return! messages length
107125
}
108126
//let midiFile =
109127
// parseMidi {

0 commit comments

Comments
 (0)