Skip to content

Commit df8483b

Browse files
fix track parser, apparently the track length is in bytes, not in message count, which makes sense to allow to skip tracks, or chunks.
defined a repeatTillPosition parser primitive Files with sysex are still broken (infinite loop?)
1 parent dd753e3 commit df8483b

File tree

3 files changed

+95
-18
lines changed

3 files changed

+95
-18
lines changed

demo/scratch.fsx

Lines changed: 66 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,39 +1,52 @@
1+
2+
13
//#load "../src/zmidi/datatypes.fs"
24
//#load "../src/zmidi/extratypes.fs"
35
//#load "../src/zmidi/internal/utils.fs"
46
//#load "../src/zmidi/internal/parsermonad.fs"
57
//#load "../src/zmidi/read.fs"
68
#r "../build/Debug/AnyCPU/net45/zmidi-fs-core.dll"
7-
8-
99
open System.IO
1010
open ZMidi.Internal.ParserMonad
1111
open ZMidi
12+
//ZMidi.Internal.ParserMonad.debug <- true
13+
(*
14+
15+
16+
17+
let pp = parseMidi {
18+
return boundRepeat 10 readByte
19+
}
20+
21+
22+
let d = Seq.initInfinite (fun i -> byte (i % 255)) |> Seq.truncate 10 |> Seq.toArray
23+
let s = State.initial
24+
25+
let (Ok(ParserMonad f)) = (ZMidi.Internal.ParserMonad.runParser pp d s)
26+
f d s
27+
*)
1228

1329
let folder =
1430
Path.Combine(__SOURCE_DIRECTORY__ , ".." , "data", "midifiles")
1531
|> DirectoryInfo
1632

1733
for file in folder.EnumerateFiles() do
1834
let buffer = File.ReadAllBytes file.FullName
35+
printfn "======================= %s" file.FullName
1936

2037
let parseResult =
2138
ZMidi.Internal.ParserMonad.runParser
2239
ZMidi.ReadFile.midiFile
2340
buffer
2441
State.initial
2542

26-
27-
printfn "%s" file.FullName
28-
2943
match parseResult with
3044
| Ok result ->
3145

3246
printfn "%i tracks" result.tracks.Length
3347
for t in result.tracks do
34-
t.Length
35-
printfn "track: %A" t
36-
()
48+
printfn "track: %A events" t.Length
49+
3750
| Error something -> printfn "ERR: %s %A" file.FullName something
3851

3952

@@ -65,6 +78,39 @@ do
6578

6679
//do printfn "hello"; let a = 1; printfn "world %i" a;
6780

81+
82+
83+
84+
85+
86+
87+
88+
let d = [| 0xffuy
89+
0x08uy
90+
0x0euy
91+
0x41uy
92+
0x6Duy
93+
0x61uy
94+
0x7Auy
95+
0x69uy
96+
0x6euy
97+
0x67uy
98+
0x20uy
99+
0x47uy
100+
0x72uy
101+
0x61uy
102+
0x63uy
103+
0x65uy
104+
0x00uy
105+
|]
106+
107+
let p = ZMidi.ReadFile.event
108+
let s = State.initial
109+
110+
let (Ok(ParserMonad f)) = (ZMidi.Internal.ParserMonad.runParser p d s)
111+
f d s
112+
113+
68114
open ZMidi.ReadFile
69115
open ZMidi.DataTypes
70116
let p = parseMidi {
@@ -78,14 +124,8 @@ let p = parseMidi {
78124
timeDivision = timeDiv
79125
format = format }
80126

81-
let! _ = assertString "MTrk"
82-
let! l = readUInt32be
83-
let! t = deltaTime
84-
let! e = event
85-
return (l,t,e)
86-
//let! track1 = track
87-
//return track1
88-
}
127+
return! track
128+
}
89129

90130

91131

@@ -105,3 +145,13 @@ for file in folder.EnumerateFiles() do
105145
| Ok result ->
106146
printfn "%A" result
107147
| Error something -> printfn "ERR: %s %A" file.FullName something
148+
149+
150+
151+
let pp = parseMidi {
152+
return boundRepeat 5 readByte
153+
}
154+
155+
let (Ok(ParserMonad f)) = (ZMidi.Internal.ParserMonad.runParser pp [|1uy..5uy|] State.initial)
156+
157+
f [|1uy..5uy|] State.initial

src/ZMidi/Internal/ParserMonad.fs

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -290,6 +290,29 @@ module ParserMonad =
290290

291291

292292
/// Run a parser within a bounded section of the input stream.
293+
let repeatTillPosition (maxPosition: Pos) (p: ParserMonad<'a>) : ParserMonad<'a array> =
294+
ParserMonad(fun data state ->
295+
let results = ResizeArray()
296+
let mutable firstError = Ok (Array.empty, state)
297+
let mutable lastState = state
298+
let rec loop () =
299+
if lastState.Position < int maxPosition then
300+
match apply1 p data lastState with
301+
| Ok (result, state) ->
302+
lastState <- state
303+
results.Add result
304+
loop ()
305+
| Error e ->
306+
firstError <- Error e
307+
308+
loop ()
309+
match firstError with
310+
| Ok _ ->
311+
Ok(results.ToArray(), lastState)
312+
| Error _ ->
313+
firstError
314+
)
315+
293316
let inline boundRepeat (n: ^T) (p: ParserMonad<'a>) : ParserMonad<'a array> =
294317
ParserMonad(fun data state ->
295318
let result = Array.zeroCreate (int n)
@@ -299,6 +322,7 @@ module ParserMonad =
299322
let mutable i = LanguagePrimitives.GenericZero
300323
let mutable errorOccured = false
301324
logf "bound repeat %i" n
325+
302326
while i < n && not errorOccured do
303327
logf "bound repeat %i/%i" i n
304328

@@ -321,7 +345,7 @@ module ParserMonad =
321345
let inline gencount (plen: ParserMonad<'T>) (p: ParserMonad<'a>) (constr: ^T -> 'a array -> 'answer) : ParserMonad<'answer> =
322346
parseMidi {
323347
let! l = plen
324-
printfn "gen count: l: %i" l
348+
logf "gen count: l: %i" l
325349
let! items = boundRepeat l p
326350
return constr l items
327351
}

src/ZMidi/Read.fs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -428,7 +428,10 @@ event = peek >>= step
428428
}
429429
let messages i =
430430
parseMidi {
431-
return! boundRepeat (int i) message
431+
432+
let! lastPos = getPos
433+
let maxPos = lastPos + int i
434+
return! repeatTillPosition maxPos message
432435
}
433436
let track : ParserMonad<MidiTrack> =
434437
parseMidi {

0 commit comments

Comments
 (0)