initial flac metadata read
parent
2235eadf04
commit
1dfba430a8
|
@ -0,0 +1 @@
|
||||||
|
Steve Ayerhart
|
|
@ -0,0 +1,82 @@
|
||||||
|
! Copyright (C) 2020 .
|
||||||
|
! See http://factorcode.org/license.txt for BSD license.
|
||||||
|
USING: alien.syntax math io.encodings.binary kernel io io.files locals endian bit-arrays ;
|
||||||
|
USING: prettyprint ;
|
||||||
|
USING: flac.metadata.private flac.metadata ;
|
||||||
|
|
||||||
|
QUALIFIED: bitstreams
|
||||||
|
|
||||||
|
|
||||||
|
IN: flac.decoder
|
||||||
|
|
||||||
|
ALIAS: read-bit bitstreams:read
|
||||||
|
CONSTANT: sync-code 16382
|
||||||
|
ERROR: sync-code-error ;
|
||||||
|
|
||||||
|
ENUM: flac-channel-assignment
|
||||||
|
channel-assignment-independent
|
||||||
|
channel-assignment-left-side
|
||||||
|
channel-assignment-right-side
|
||||||
|
channel-assignment-mid-side ;
|
||||||
|
ENUM: flac-frame-number-type
|
||||||
|
frame-number-type-frame
|
||||||
|
frame-number-type-sample ;
|
||||||
|
|
||||||
|
ENUM: flac-subframe-type
|
||||||
|
subframe-type-constant
|
||||||
|
subframe-type-verbatim
|
||||||
|
subframe-type-fixed
|
||||||
|
subframe-type-lpc ;
|
||||||
|
|
||||||
|
ENUM: flac-entropy-coding-method
|
||||||
|
entropy-coding-partioned-rice
|
||||||
|
entropy-coding-partioned-rice2 ;
|
||||||
|
|
||||||
|
TUPLE: subframe
|
||||||
|
{ type maybe{ subframe-type-constant
|
||||||
|
subframe-type-verbatim
|
||||||
|
subframe-type-fixed
|
||||||
|
subframe-type-lpc } } ;
|
||||||
|
|
||||||
|
TUPLE: frame-header
|
||||||
|
{ blocksize integer }
|
||||||
|
{ sample-rate integer }
|
||||||
|
{ channels integer }
|
||||||
|
{ channel-assignment maybe{ channel-assignment-independent
|
||||||
|
channel-assignment-left-side
|
||||||
|
channel-assignment-right-side
|
||||||
|
channel-assignment-mid-side } }
|
||||||
|
{ bits-per-sample integer }
|
||||||
|
{ number-type maybe{ frame-number-type-frame frame-number-type-sample } }
|
||||||
|
{ number integer }
|
||||||
|
{ crc integer } ;
|
||||||
|
|
||||||
|
TUPLE: frame-footer
|
||||||
|
{ crc integer } ;
|
||||||
|
|
||||||
|
:: read-sync-code ( bitstream -- ? )
|
||||||
|
14 bitstream read-bit sync-code = ;
|
||||||
|
|
||||||
|
:: (decode-frame-header) ( bitstream -- )
|
||||||
|
[
|
||||||
|
bitstream read-sync-code [ sync-code-error ] unless
|
||||||
|
1 bitstream read-bit drop
|
||||||
|
1 bitstream read-bit drop
|
||||||
|
4 bitstream read-bit integer>bit-array .
|
||||||
|
4 bitstream read-bit integer>bit-array .
|
||||||
|
|
||||||
|
] with-big-endian ;
|
||||||
|
|
||||||
|
: decode-frame-header ( -- )
|
||||||
|
[
|
||||||
|
3 read bitstreams:<msb0-bit-reader> (decode-frame-header)
|
||||||
|
] with-big-endian ;
|
||||||
|
|
||||||
|
: decode-file ( filename -- )
|
||||||
|
binary
|
||||||
|
[
|
||||||
|
read-flac-magic [ not-a-flac-file ] unless
|
||||||
|
read-stream-info drop
|
||||||
|
skip-metadata
|
||||||
|
decode-frame-header
|
||||||
|
] with-file-reader ;
|
|
@ -0,0 +1,10 @@
|
||||||
|
! Copyright (C) 2020 .
|
||||||
|
! See http://factorcode.org/license.txt for BSD license.
|
||||||
|
USING: help.markup help.syntax ;
|
||||||
|
IN: flac
|
||||||
|
|
||||||
|
ARTICLE: "flac" "flac"
|
||||||
|
{ $vocab-link "flac" }
|
||||||
|
;
|
||||||
|
|
||||||
|
ABOUT: "flac"
|
|
@ -0,0 +1,4 @@
|
||||||
|
! Copyright (C) 2020 .
|
||||||
|
! See http://factorcode.org/license.txt for BSD license.
|
||||||
|
USING: tools.test flac ;
|
||||||
|
IN: flac.tests
|
|
@ -0,0 +1,5 @@
|
||||||
|
! Copyright (C) 2020 .
|
||||||
|
! See http://factorcode.org/license.txt for BSD license.
|
||||||
|
USING: ;
|
||||||
|
|
||||||
|
IN: flac
|
|
@ -0,0 +1,267 @@
|
||||||
|
! Copyright (C) 2020 .
|
||||||
|
! See http://factorcode.org/license.txt for BSD license.
|
||||||
|
USING: endian sequences kernel classes.struct io io.binary io.files io.encodings io.encodings.string io.encodings.utf8 io.encodings.binary alien.c-types alien.endian math locals accessors prettyprint combinators pack math.parser strings arrays io.streams.byte-array sequences.generalizations assocs splitting byte-arrays alien.syntax alien.enums io.encodings.ascii ;
|
||||||
|
QUALIFIED: bitstreams
|
||||||
|
|
||||||
|
IN: flac.metadata
|
||||||
|
|
||||||
|
ALIAS: read-bit bitstreams:read
|
||||||
|
|
||||||
|
CONSTANT: FLAC-MAGIC "fLaC"
|
||||||
|
|
||||||
|
ENUM: metadata-type
|
||||||
|
metadata-stream-info
|
||||||
|
metadata-padding
|
||||||
|
metadata-application
|
||||||
|
metadata-seek-table
|
||||||
|
metadata-vorbis-comment
|
||||||
|
metadata-cuesheet
|
||||||
|
metadata-picture
|
||||||
|
{ metadata-invalid 127 } ;
|
||||||
|
|
||||||
|
ERROR: not-a-flac-file ;
|
||||||
|
ERROR: cuesheet-index-reserved-must-be-zero ;
|
||||||
|
|
||||||
|
TUPLE: metadata-block-header
|
||||||
|
{ last? boolean }
|
||||||
|
{ type maybe{ metadata-stream-info
|
||||||
|
metadata-padding
|
||||||
|
metadata-application
|
||||||
|
metadata-seek-table
|
||||||
|
metadata-vorbis-comment
|
||||||
|
metadata-cuesheet
|
||||||
|
metadata-picture
|
||||||
|
metadata-invalid } }
|
||||||
|
{ length integer } ;
|
||||||
|
|
||||||
|
TUPLE: stream-info
|
||||||
|
{ min-block-size integer }
|
||||||
|
{ max-block-size integer }
|
||||||
|
{ min-frame-size integer }
|
||||||
|
{ max-frame-size integer }
|
||||||
|
{ sample-rate integer }
|
||||||
|
{ channels integer }
|
||||||
|
{ bits-per-sample integer }
|
||||||
|
{ samples integer }
|
||||||
|
{ md5 string } ;
|
||||||
|
|
||||||
|
TUPLE: seek-table
|
||||||
|
{ seek-points array } ;
|
||||||
|
TUPLE: seek-point
|
||||||
|
{ sample-number integer }
|
||||||
|
{ offset integer }
|
||||||
|
{ total-samples } ;
|
||||||
|
|
||||||
|
TUPLE: vorbis-comment
|
||||||
|
{ vendor-string string }
|
||||||
|
{ comments assoc } ;
|
||||||
|
|
||||||
|
TUPLE: padding
|
||||||
|
{ length integer } ;
|
||||||
|
|
||||||
|
TUPLE: application
|
||||||
|
{ id string }
|
||||||
|
{ data byte-array } ;
|
||||||
|
|
||||||
|
ENUM: cuesheet-track-type audio non-audio ;
|
||||||
|
|
||||||
|
TUPLE: cuesheet-track
|
||||||
|
{ offset integer }
|
||||||
|
{ number number }
|
||||||
|
{ isrc string }
|
||||||
|
{ type integer }
|
||||||
|
{ pre-emphasis boolean }
|
||||||
|
{ indices array } ;
|
||||||
|
TUPLE: cuesheet-index
|
||||||
|
{ offset integer }
|
||||||
|
{ number integer } ;
|
||||||
|
TUPLE: cuesheet
|
||||||
|
{ catalog-number integer }
|
||||||
|
{ lead-in integer }
|
||||||
|
{ cd? boolean }
|
||||||
|
{ tracks array } ;
|
||||||
|
|
||||||
|
ENUM: picture-type
|
||||||
|
other
|
||||||
|
file-icon
|
||||||
|
other-file-icon
|
||||||
|
front-cover
|
||||||
|
back-cover
|
||||||
|
leaflet-page
|
||||||
|
media
|
||||||
|
lead-artist/performer/soloist
|
||||||
|
artist/performer
|
||||||
|
conductor
|
||||||
|
band/orchestra
|
||||||
|
composer
|
||||||
|
lyricist/text-writer
|
||||||
|
recording-location
|
||||||
|
during-recording
|
||||||
|
during-performance
|
||||||
|
movie/video-screen-capture
|
||||||
|
bright-coloured-fish
|
||||||
|
illustration
|
||||||
|
badn/artist-logotype
|
||||||
|
publisher/studio-logotype ;
|
||||||
|
|
||||||
|
TUPLE: picture
|
||||||
|
type
|
||||||
|
{ mime-type string }
|
||||||
|
{ description string }
|
||||||
|
{ width integer }
|
||||||
|
{ height integer }
|
||||||
|
{ depth integer }
|
||||||
|
{ colors integer }
|
||||||
|
{ data byte-array } ;
|
||||||
|
|
||||||
|
TUPLE: metadata
|
||||||
|
{ stream-info stream-info }
|
||||||
|
{ padding maybe{ padding } }
|
||||||
|
{ application maybe{ application } }
|
||||||
|
{ seek-table maybe{ seek-table } }
|
||||||
|
{ vorbis-comment maybe{ vorbis-comment } }
|
||||||
|
{ cuesheet maybe{ cuesheet } }
|
||||||
|
{ picture maybe{ picture } } ;
|
||||||
|
|
||||||
|
<PRIVATE
|
||||||
|
|
||||||
|
: read-flac-magic ( -- magic )
|
||||||
|
4 read utf8 decode FLAC-MAGIC = ;
|
||||||
|
|
||||||
|
:: (parse-metadata-block-header) ( bitstream -- header )
|
||||||
|
[
|
||||||
|
1 bitstream read-bit 1 =
|
||||||
|
7 bitstream read-bit <metadata-type>
|
||||||
|
24 bitstream read-bit
|
||||||
|
] with-big-endian
|
||||||
|
metadata-block-header boa ;
|
||||||
|
|
||||||
|
: parse-metadata-block-header ( byte-array -- header )
|
||||||
|
bitstreams:<msb0-bit-reader> (parse-metadata-block-header) ;
|
||||||
|
|
||||||
|
: read-metadata-block-header ( -- header )
|
||||||
|
4 read parse-metadata-block-header dup . ;
|
||||||
|
|
||||||
|
:: (parse-stream-info) ( bitstream -- stream-info )
|
||||||
|
[
|
||||||
|
16 bitstream read-bit
|
||||||
|
16 bitstream read-bit
|
||||||
|
24 bitstream read-bit
|
||||||
|
24 bitstream read-bit
|
||||||
|
20 bitstream read-bit
|
||||||
|
3 bitstream read-bit 1 +
|
||||||
|
5 bitstream read-bit 1 +
|
||||||
|
36 bitstream read-bit
|
||||||
|
128 bitstream read-bit u128>byte-array bytes>hex-string
|
||||||
|
] with-big-endian
|
||||||
|
stream-info boa ;
|
||||||
|
|
||||||
|
: parse-stream-info ( byte-array -- stream-info )
|
||||||
|
bitstreams:<msb0-bit-reader> (parse-stream-info) ;
|
||||||
|
|
||||||
|
: parse-seek-table ( byte-array -- seek-table )
|
||||||
|
dup
|
||||||
|
binary
|
||||||
|
[
|
||||||
|
length 18 / <iota>
|
||||||
|
[ drop 8 read be> 8 read be> 2 read be> seek-point boa ] map
|
||||||
|
] with-byte-reader
|
||||||
|
seek-table boa ;
|
||||||
|
|
||||||
|
: parse-vorbis-comment ( byte-array -- comments )
|
||||||
|
binary
|
||||||
|
[
|
||||||
|
4 read le> read utf8 decode
|
||||||
|
4 read le> <iota> [
|
||||||
|
drop
|
||||||
|
4 read le> read utf8 decode
|
||||||
|
"=" split
|
||||||
|
] map
|
||||||
|
] with-byte-reader >alist vorbis-comment boa ;
|
||||||
|
|
||||||
|
: parse-padding ( byte-array -- padding )
|
||||||
|
length padding boa ;
|
||||||
|
|
||||||
|
: parse-application ( byte-array -- application )
|
||||||
|
drop application new ;
|
||||||
|
|
||||||
|
: parse-cuesheet ( byte-array -- cuesheet )
|
||||||
|
binary
|
||||||
|
[
|
||||||
|
128 read ascii decode
|
||||||
|
8 read be>
|
||||||
|
259 read drop f
|
||||||
|
1 read be> <iota> [
|
||||||
|
drop
|
||||||
|
8 read be>
|
||||||
|
1 read be>
|
||||||
|
12 read ascii decode
|
||||||
|
21 read drop 0 <cuesheet-track-type> t
|
||||||
|
1 read <iota> [
|
||||||
|
drop
|
||||||
|
8 read be>
|
||||||
|
1 read be>
|
||||||
|
3 read be> = 0 [ cuesheet-index-reserved-must-be-zero ] unless
|
||||||
|
cuesheet-index boa
|
||||||
|
] map
|
||||||
|
cuesheet-track boa
|
||||||
|
] map
|
||||||
|
] with-byte-reader cuesheet boa ;
|
||||||
|
|
||||||
|
: parse-picture ( byte-array -- picture )
|
||||||
|
binary
|
||||||
|
[
|
||||||
|
4 read be> <picture-type>
|
||||||
|
4 read be> read utf8 decode
|
||||||
|
4 read be> read utf8 decode
|
||||||
|
4 read be>
|
||||||
|
4 read be>
|
||||||
|
4 read be>
|
||||||
|
4 read be>
|
||||||
|
4 read be> read
|
||||||
|
] with-byte-reader picture boa ;
|
||||||
|
|
||||||
|
: read-metadata-block ( metadata byte-array type -- metadata )
|
||||||
|
{
|
||||||
|
{ metadata-stream-info [ parse-stream-info >>stream-info ] }
|
||||||
|
{ metadata-padding [ parse-padding >>padding ] }
|
||||||
|
{ metadata-application [ parse-application >>application ] }
|
||||||
|
{ metadata-seek-table [ parse-seek-table >>seek-table ] }
|
||||||
|
{ metadata-vorbis-comment [ parse-vorbis-comment >>vorbis-comment ] }
|
||||||
|
{ metadata-cuesheet [ parse-cuesheet >>cuesheet ] }
|
||||||
|
{ metadata-picture [ parse-picture >>picture ] }
|
||||||
|
} case ;
|
||||||
|
|
||||||
|
PRIVATE>
|
||||||
|
|
||||||
|
: read-stream-info ( -- stream-info )
|
||||||
|
read-metadata-block-header
|
||||||
|
length>> read bitstreams:<msb0-bit-reader> parse-stream-info ;
|
||||||
|
|
||||||
|
: skip-metadata ( -- )
|
||||||
|
[
|
||||||
|
read-metadata-block-header
|
||||||
|
[ length>> read drop ] [ last?>> not ] bi
|
||||||
|
] loop ;
|
||||||
|
|
||||||
|
! TODO: handle other formats gracefully such as ID3
|
||||||
|
: read-metadata ( filename -- metadata )
|
||||||
|
binary
|
||||||
|
[
|
||||||
|
read-flac-magic [ not-a-flac-file ] unless
|
||||||
|
metadata new
|
||||||
|
[
|
||||||
|
read-metadata-block-header
|
||||||
|
[ length>> read ] [ type>> ] [ last?>> not ] tri
|
||||||
|
[ read-metadata-block ] dip
|
||||||
|
] loop
|
||||||
|
] with-file-reader ;
|
||||||
|
|
||||||
|
: <flac-metadata> ( filename -- metadata )
|
||||||
|
read-metadata ;
|
||||||
|
|
||||||
|
:: write-something ( bitstream -- header )
|
||||||
|
1 1 bitstream bitstreams:poke
|
||||||
|
1 7 bitstream bitstreams:poke
|
||||||
|
34 24 bitstream bitstreams:poke
|
||||||
|
bitstream bitstreams:bit-writer-bytes ;
|
|
@ -0,0 +1 @@
|
||||||
|
flac
|
|
@ -0,0 +1 @@
|
||||||
|
flac audio
|
Loading…
Reference in New Issue