 PRIVATE>
 
 : mp3>id3 ( path -- id3/f )
-    dup file-info size>> 0 <= [ drop f ] [ (mp3>id3) ] if ; inline
+    dup file-info size>> 0 <= [ drop f ] [ (mp3>id3) ] if ;
 
 : find-id3-frame ( id3 name -- obj/f )
-    swap frames>> at* [ data>> ] when ; inline
-
-: title ( id3 -- string/f ) "TIT2" find-id3-frame ; inline
-
-: artist ( id3 -- string/f ) "TPE1" find-id3-frame ; inline
-
-: album ( id3 -- string/f ) "TALB" find-id3-frame ; inline
-
-: year ( id3 -- string/f ) "TYER" find-id3-frame ; inline
-
-: comment ( id3 -- string/f ) "COMM" find-id3-frame ; inline
+    swap frames>> at* [ data>> ] when ;
+
+: title ( id3 -- string/f ) "TIT2" find-id3-frame ;
+
+: artist ( id3 -- string/f ) "TPE1" find-id3-frame ;
+
+: album ( id3 -- string/f ) "TALB" find-id3-frame ;
+
+: year ( id3 -- string/f ) "TYER" find-id3-frame ;
+
+: comment ( id3 -- string/f ) "COMM" find-id3-frame ;
 
 : genre ( id3 -- string/f )
-    "TCON" find-id3-frame parse-genre ; inline
+    "TCON" find-id3-frame parse-genre ;
 
 : find-mp3s ( path -- seq )
-    [ >lower ".mp3" tail? ] find-all-files ; inline
+    [ >lower ".mp3" tail? ] find-all-files ;
 
 : mp3-paths>id3s ( seq -- seq' )
-    [ dup mp3>id3 ] { } map>assoc ; inline
+    [ dup mp3>id3 ] { } map>assoc ;
 
 : parse-mp3-directory ( path -- seq )
     find-mp3s mp3-paths>id3s ;

        [ [ 181 211 ] dip subseq decode-text >>genre-name ]
        [ [ 211 217 ] dip subseq decode-text >>start-time ]
        [ [ 217 223 ] dip subseq decode-text >>end-time ]
    } cleave ; inline

: read-v1+-tags ( id3 seq -- id3 )
    id3v1+-offset tail-slice* 4 tail-slice
    extract-v1+-tags ; inline

: parse-genre ( string -- n/f )
    dup "(" ?head-slice drop ")" ?tail-slice drop

    ] output>array sift ;

: seq>synchsafe ( seq -- n )
    0 [ [ 7 shift ] dip bitor ] reduce ;

: synchsafe>seq ( n -- seq )
    dup 1+ log2 1+ 7 / ceiling
    [ [ -7 shift ] keep HEX: 7f bitand  ] replicate nip reverse ;

: filter-text-data ( data -- filtered )
    [ printable? ] filter ;

: valid-tag? ( id -- ? )
    [ { [ digit? ] [ LETTER? ] } 1|| ] all? ;

: read-frame-data ( frame seq -- frame data )
    [ 10 over size>> 10 + ] dip <slice> filter-text-data ;

: decode-text ( string -- string' )
    dup 2 short head
    { { HEX: ff HEX: fe } { HEX: fe HEX: ff } } member?
    utf16 ascii ? decode ;

: (read-frame) ( seq -- frame )
    [ <frame> ] dip
