@@ -53,7 +53,13 @@ module ReadFile =
53
53
return ( uint32 result) }
54
54
55
55
let getVarlenText = gencount getVarlen readChar ( fun _ b -> System.String b)
56
-
56
+ let getVarlenBytes = gencount getVarlen readByte ( fun _ b -> b)
57
+ let deltaTime =
58
+ parseMidi {
59
+ let! v = getVarlen
60
+ return DeltaTime( v)
61
+ } <??> ( fun p -> " delta time" )
62
+
57
63
let fileFormat =
58
64
parseMidi {
59
65
match ! readUInt16be with
@@ -103,23 +109,18 @@ module ReadFile =
103
109
let metaEvent i =
104
110
parseMidi {
105
111
match i with
106
- | 0x00 -> return ! metaEventSequenceNumber
107
- | 0x01 -> return ! textEvent GenericText
108
- | 0x02 -> return ! textEvent CopyrightNotice
109
- | 0x03 -> return ! textEvent SequenceName
110
- | 0x04 -> return ! textEvent InstrumentName
111
- | 0x05 -> return ! textEvent Lyrics
112
- | 0x06 -> return ! textEvent Marker
113
- | 0x07 -> return ! textEvent CuePoint
112
+ | 0x00 uy -> return ! metaEventSequenceNumber
113
+ | 0x01 uy -> return ! textEvent GenericText
114
+ | 0x02 uy -> return ! textEvent CopyrightNotice
115
+ | 0x03 uy -> return ! textEvent SequenceName
116
+ | 0x04 uy -> return ! textEvent InstrumentName
117
+ | 0x05 uy -> return ! textEvent Lyrics
118
+ | 0x06 uy -> return ! textEvent Marker
119
+ | 0x07 uy -> return ! textEvent CuePoint
114
120
}
115
121
// let (<*>) af ma =
116
122
117
123
118
- let runningStatus : ParserMonad < MidiRunningStatus > =
119
- parseMidi {
120
-
121
- return MidiRunningStatus.ON
122
- }
123
124
//let metaEvent n = //: ParserMonad<MetaEvent> =
124
125
// match n with
125
126
// ///| 0x00uy -> ( SequenceNumber <~> (assertWord8 2uy *> word16be)) <??> (sprintf "sequence number: failed at %i" )
@@ -136,34 +137,223 @@ module ReadFile =
136
137
//parseMidi {
137
138
//
138
139
//}
140
+
141
+ //sysExContPackets =
142
+ // deltaTime >>= \dt -> getVarlenBytes (,) >>= \(n,xs) ->
143
+ // let ans1 = MidiSysExContPacket dt n xs
144
+ // in if isTerminated xs then return [ans1]
145
+ // else sysExContPackets >>= \ks ->
146
+ // return $ ans1:ks
147
+
148
+ let isTerminated bytes =
149
+ bytes
150
+ |> Array.tryFind ((=) 0xf7 uy)
151
+ |> function | Some i -> true
152
+ | None -> false
153
+
154
+ let rec sysExContPackets =
155
+ parseMidi {
156
+ let! d = deltaTime
157
+ let! b = getVarlenBytes
158
+ let answer = MidiSysExContPacket ( d, b)
159
+ if isTerminated b then return List.singleton answer
160
+ else
161
+ let! answer2 = sysExContPackets
162
+ return ( answer :: answer2)
163
+ }
164
+ let sysExEvent =
165
+ parseMidi {
166
+ let! b = getVarlenBytes
167
+ if isTerminated b then
168
+ return SysExSingle b
169
+ else
170
+ let! cont = sysExContPackets
171
+ return SysExCont( b, cont)
172
+ } <??> ( fun _ -> " sysExEvent" )
173
+ let sysExEscape =
174
+ parseMidi {
175
+ let! bytes = getVarlenBytes
176
+ return SysExEscape bytes
177
+ } <??> ( fun _ -> " sysExEscape" )
178
+ let impossibleMatch text =
179
+ fatalError ( ErrMsg.Other ( sprintf " impossible match: %s " text))
180
+
181
+ let sysCommonEvent n =
182
+ match n with
183
+ | 0xf1 uy -> readByte >>= ( QuarterFrame >> mreturn) <??> ( fun p -> " quarter frame" )
184
+ | 0xf2 uy ->
185
+ parseMidi {
186
+ let! a = readByte
187
+ let! b = readByte
188
+ return SongPosPointer( a, b)
189
+ } <??> ( fun p -> " song pos. pointer" )
190
+ | 0xf3 uy -> readByte >>= ( QuarterFrame >> mreturn) <??> ( fun p -> " song select" )
191
+ | 0xf4 uy -> mreturn UndefinedF4
192
+ | 0xf5 uy -> mreturn UndefinedF5
193
+ | 0xf6 uy -> mreturn TuneRequest
194
+ | 0xf7 uy -> mreturn EOX
195
+ | tag -> impossibleMatch ( sprintf " sysCommonEvent %x " tag)
196
+
197
+ let sysRealtimeEvent n =
198
+ match n with
199
+ | 0xf8 uy -> mreturn TimingClock
200
+ | 0xf9 uy -> mreturn TimingClock
201
+ | 0xfa uy -> mreturn TimingClock
202
+ | 0xfb uy -> mreturn TimingClock
203
+ | 0xfc uy -> mreturn TimingClock
204
+ | 0xfd uy -> mreturn TimingClock
205
+ | 0xfe uy -> mreturn TimingClock
206
+ | 0xff uy -> mreturn TimingClock
207
+ | tag -> impossibleMatch ( sprintf " sysRealtimeEvent %x " tag)
208
+
209
+ let inline (| SB |) b =
210
+ b &&& 0xf0 uy, b &&& 0x0f uy
211
+
212
+ let noteOff ch =
213
+ parseMidi {
214
+ let! a = readByte
215
+ let! b = readByte
216
+ return MidiVoiceEvent.NoteOff( ch, a, b)
217
+ } <??> ( fun p -> " note-off" )
218
+
219
+ let noteOn ch =
220
+ parseMidi {
221
+ let! a = readByte
222
+ let! b = readByte
223
+ return MidiVoiceEvent.NoteOn( ch, a, b)
224
+ } <??> ( fun p -> " note-on" )
225
+
226
+ let noteAftertouch ch =
227
+ parseMidi {
228
+ let! a = readByte
229
+ let! b = readByte
230
+ return MidiVoiceEvent.NoteAfterTouch( ch, a, b)
231
+ } <??> ( fun p -> " noteAftertouch" )
232
+
233
+ let controller ch =
234
+ parseMidi {
235
+ let! a = readByte
236
+ let! b = readByte
237
+ return MidiVoiceEvent.Controller( ch, a, b)
238
+ } <??> ( fun p -> " controller" )
239
+
240
+ let programChange ch =
241
+ parseMidi {
242
+ let! a = readByte
243
+ return MidiVoiceEvent.ProgramChange( ch, a)
244
+ } <??> ( fun p -> " controller" )
245
+
246
+ let channelAftertouch ch =
247
+ parseMidi {
248
+ let! a = readByte
249
+ return MidiVoiceEvent.ChannelAftertouch( ch, a)
250
+ } <??> ( fun p -> " channelAftertouch" )
251
+ let pitchBend ch =
252
+ parseMidi {
253
+ let! a = readWord14be
254
+ return MidiVoiceEvent.PitchBend( ch, a)
255
+ } <??> ( fun p -> " pitchBend" )
256
+
257
+
258
+ let voiceEvent n =
259
+ match n with
260
+ | SB( 0x80 uy, ch) -> parseMidi { do ! setRunningEvent ( NoteOff ch)
261
+ return ! noteOff ch }
262
+ | SB( 0x90 uy, ch) -> parseMidi { do ! setRunningEvent ( NoteOn ch)
263
+ return ! noteOn ch }
264
+ | SB( 0xa0 uy, ch) -> parseMidi { do ! setRunningEvent ( NoteAftertoucuh ch)
265
+ return ! noteAftertouch ch }
266
+ | SB( 0xb0 uy, ch) -> parseMidi { do ! setRunningEvent ( Control ch)
267
+ return ! controller ch }
268
+ | SB( 0xc0 uy, ch) -> parseMidi { do ! setRunningEvent ( Program ch)
269
+ return ! programChange ch }
270
+ | SB( 0xd0 uy, ch) -> parseMidi { do ! setRunningEvent ( ChannelAftertouch ch)
271
+ return ! channelAftertouch ch }
272
+ | SB( 0xe0 uy, ch) -> parseMidi { do ! setRunningEvent ( PitchBend ch)
273
+ return ! pitchBend ch }
274
+ | otherwise -> impossibleMatch ( sprintf " voiceEvent: %x " otherwise)
275
+ let runningStatus ( event : VoiceEvent ) : ParserMonad < MidiEvent > =
276
+ let mVoiceEvent e = mreturn ( VoiceEvent( MidiRunningStatus.ON, e))
277
+ match event with
278
+ | NoteOff ch -> ( noteOff ch) >>= mVoiceEvent
279
+ | NoteOn ch -> ( noteOn ch) >>= mVoiceEvent
280
+ | NoteAftertoucuh ch -> ( noteAftertouch ch) >>= mVoiceEvent
281
+ | Control ch -> ( controller ch) >>= mVoiceEvent
282
+ | Program ch -> ( programChange ch) >>= mVoiceEvent
283
+ | ChannelAftertouch ch -> ( channelAftertouch ch) >>= mVoiceEvent
284
+ | PitchBend ch -> ( pitchBend ch) >>= mVoiceEvent
285
+ | StatusOff -> readByte >>= ( MidiEventOther >> mreturn)
286
+ //parseMidi {
287
+ //
288
+ // //return MidiRunningStatus.ON
289
+ //}
290
+
291
+ (*
292
+ event :: ParserM MidiEvent
293
+ event = peek >>= step
294
+ where
295
+ -- 00..7f -- /data/
296
+ step n
297
+ | n == 0xFF = MetaEvent <$> (dropW8 *> (word8 >>= metaEvent))
298
+ | n >= 0xF8 = SysRealTimeEvent <$> (dropW8 *> sysRealTimeEvent n)
299
+ | n == 0xF7 = SysExEvent <$> (dropW8 *> sysExEscape)
300
+ | n >= 0xF1 = SysCommonEvent <$> (dropW8 *> sysCommonEvent n)
301
+ | n == 0xF0 = SysExEvent <$> (dropW8 *> sysExEvent)
302
+ | n >= 0x80 = VoiceEvent RS_OFF <$> (dropW8 *> voiceEvent (splitByte n))
303
+ | otherwise = getRunningEvent >>= runningStatus
304
+ *)
305
+
306
+ /// Parse an event - for valid input this function should parse
307
+ /// without error (i.e all cases of event types are fully
308
+ /// enumerated).
309
+ ///
310
+ /// Malformed input (syntactically bad events, or truncated data)
311
+ /// can cause fatal parse errors.
312
+
139
313
let event : ParserMonad < MidiEvent > =
140
- let step n : ParserMonad < MidiMetaEvent >=
141
- //parseMidi {
314
+ //let foo = (readByte >>= metaEvent)
315
+ let step n : ParserMonad < MidiEvent >=
316
+ parseMidi {
142
317
match n with
143
- | 0xff uy -> failwithf " " //MetaEvent <~> (dropByte *> (readByte >>= metaEvent))
144
- //| 0xf7uy -> ()//SysexEvent
145
- //| 0xf0uy -> ()//SysexEvent
146
- //| 0x80uy -> ()//VoiceEvent
147
- //| n when n >= 0xf8uy -> ()//SysRealtimeEvent
148
- //| n when n >= 0xf1uy -> ()//SysCommonEvent
149
- //| n when n >= 0x80uy -> ()//VoiceEvent
150
- //| _ -> getRunningEvent >>= runningStatus
151
- //}
152
- parseMidi {
153
- let! p = peek
154
- step p
155
- return ! fatalError ( Other " event: not implemented" ) }
318
+ | 0xff uy ->
319
+ do ! dropByte
320
+ let! event = readByte >>= metaEvent
321
+ return MetaEvent event
322
+ //MetaEvent <~> (dropByte *> (fun _ -> (readByte >>= metaEvent))) // failwithf "event ff"
323
+ | 0xf7 uy ->
324
+ do ! dropByte
325
+ let! sysexEvent = sysExEscape
326
+ return SysExEvent sysexEvent
327
+ | 0xf0 uy ->
328
+ do ! dropByte
329
+ let! sysexEvent = sysExEvent
330
+ return SysExEvent sysexEvent
331
+ | x when x >= 0xf8 uy ->
332
+ do ! dropByte
333
+ let! event = sysRealtimeEvent x
334
+ return SysRealtimeEvent event
335
+ | x when x >= 0xf1 uy ->
336
+ do ! dropByte
337
+ let! event = sysCommonEvent x
338
+ return SysCommonEvent event
339
+ | x when x >= 0x80 uy ->
340
+ do ! dropByte
341
+ let! voiceEvent = voiceEvent x
342
+ return VoiceEvent( MidiRunningStatus.OFF, voiceEvent)
343
+ | otherwise ->
344
+ return ! ( getRunningEvent >>= runningStatus)
156
345
157
- let deltaTime =
346
+ }
158
347
parseMidi {
159
- return ! getVarlen
160
- } <??> ( fun p -> " delta time" )
348
+ let! p = peek
349
+ return ! step p
350
+ }
161
351
162
352
let message =
163
353
parseMidi {
164
354
let! deltaTime = deltaTime
165
355
let! event = event
166
- return { timestamp = DeltaTime ( deltaTime) ; event = event }
356
+ return { timestamp = deltaTime; event = event }
167
357
}
168
358
let messages i =
169
359
parseMidi {
0 commit comments