Skip to content

Commit

Permalink
RIFF support.
Browse files Browse the repository at this point in the history
  • Loading branch information
smimram committed Jan 30, 2024
1 parent 8d974cc commit 296dbbe
Show file tree
Hide file tree
Showing 9 changed files with 82 additions and 68 deletions.
1 change: 1 addition & 0 deletions CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
- Add optional custom parser argument to override the default parsing mechanism.
- Update default metadata mappings to follow musicbrainz's picard mapping.
- Add `MIME` module to guess MIME type of files (#4).
- Generic RIFF format parser, adds support for wave files.

0.2.0 (2023-07-01)
=====
Expand Down
4 changes: 1 addition & 3 deletions examples/dune
Original file line number Diff line number Diff line change
Expand Up @@ -73,9 +73,7 @@
-i
"sine=frequency=440:sample_rate=44100:duration=10"
-f
mp3
-write_id3v1
true
wav
-metadata
"title=The title"
-metadata
Expand Down
6 changes: 4 additions & 2 deletions src/metadata.ml
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ module Make (E : CharEncoding.T) = struct
module PNG = MetadataPNG
module AVI = MetadataAVI
module MP4 = MetadataMP4
module WAV = MetadataWAV
module RIFF = MetadataRIFF

(** Charset conversion function. *)
let recode = E.convert
Expand Down Expand Up @@ -43,7 +45,7 @@ module Make (E : CharEncoding.T) = struct
| [] -> raise Invalid

module Audio = struct
let parsers = [ID3.parse; OGG.parse; FLAC.parse]
let parsers = [ID3.parse; OGG.parse; FLAC.parse; WAV.parse]
let parse = first_valid parsers

let parse_file ?custom_parser file =
Expand All @@ -67,7 +69,7 @@ module Make (E : CharEncoding.T) = struct
end

module Any = struct
let parsers = Audio.parsers @ Image.parsers @ Video.parsers
let parsers = Audio.parsers @ Image.parsers @ Video.parsers @ [RIFF.parse]

(** Genering parsing of metadata. *)
let parse = first_valid parsers
Expand Down
6 changes: 6 additions & 0 deletions src/metadata.mli
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,12 @@ module Make : functor (_ : CharEncoding.T) -> sig
(** MP4 metadata. *)
module MP4 = MetadataMP4

(** WAV metadata. *)
module WAV = MetadataWAV

(** RIFF metdata. *)
module RIFF = MetadataRIFF

(** Convert the charset encoding of a string. *)
val recode :
?source:[ `ISO_8859_1 | `UTF_16 | `UTF_16BE | `UTF_16LE | `UTF_8 ] ->
Expand Down
62 changes: 2 additions & 60 deletions src/metadataAVI.ml
Original file line number Diff line number Diff line change
@@ -1,61 +1,3 @@
open MetadataBase
module R = Reader
let parse = MetadataRIFF.parse ~format:"AVI "

(* Tag normalization. *)
let tagn =
[
("IART", "artist");
("ICMT", "comment");
("ICOP", "copyright");
("ICRD", "date");
("ICRD", "date");
("IGNR", "genre");
("INAM", "title");
("IPRD", "album");
("IPRT", "track");
("ISFT", "encoder");
]

let parse f : metadata =
if R.read f 4 <> "RIFF" then raise Invalid;
let _ (* file size *) = R.int32_le f in
if R.read f 4 <> "AVI " then raise Invalid;
let ans = ref [] in
let chunk () =
let tag = R.read f 4 in
let size = R.int32_le f in
if tag <> "LIST" then R.drop f size
else (
let subtag = R.read f 4 in
match subtag with
| "INFO" ->
let remaining = ref (size - 4) in
while !remaining > 0 do
let tag = R.read f 4 in
let size = R.int32_le f in
match R.read_tag ~length:(size - 1) ~label:tag f with
| None -> ()
| Some s ->
R.drop f 1;
(* null-terminated *)
let padding = size mod 2 in
R.drop f padding;
remaining := !remaining - (8 + size + padding);
let tag =
match List.assoc_opt tag tagn with
| Some tag -> tag
| None -> tag
in
ans := (tag, s) :: !ans
done
| "movi" -> raise Exit (* stop parsing there *)
| _ -> R.drop f (size - 4))
in
try
while true do
chunk ()
done;
assert false
with _ -> List.rev !ans

let parse_file ?custom_parser file = R.with_file ?custom_parser parse file
let parse_file = MetadataRIFF.parse_file ~format:"AVI "
3 changes: 0 additions & 3 deletions src/metadataAVI.mli

This file was deleted.

62 changes: 62 additions & 0 deletions src/metadataRIFF.ml
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
open MetadataBase
module R = Reader

(* Tag normalization. *)
let tagn =
[
("IART", "artist");
("ICMT", "comment");
("ICOP", "copyright");
("ICRD", "date");
("ICRD", "date");
("IGNR", "genre");
("INAM", "title");
("IPRD", "album");
("IPRT", "track");
("ISFT", "encoder");
("ITRK", "track");
]

let parse ?format f : metadata =
if R.read f 4 <> "RIFF" then raise Invalid;
let _ (* file size *) = R.int32_le f in
if format <> None && Some (R.read f 4) <> format then raise Invalid;
let ans = ref [] in
let chunk () =
let tag = R.read f 4 in
let size = R.int32_le f in
if tag <> "LIST" then R.drop f size
else (
let subtag = R.read f 4 in
match subtag with
| "INFO" ->
let remaining = ref (size - 4) in
while !remaining > 0 do
let tag = R.read f 4 in
let size = R.int32_le f in
match R.read_tag ~length:(size - 1) ~label:tag f with
| None -> ()
| Some s ->
R.drop f 1;
(* null-terminated *)
let padding = size mod 2 in
R.drop f padding;
remaining := !remaining - (8 + size + padding);
let tag =
match List.assoc_opt tag tagn with
| Some tag -> tag
| None -> tag
in
ans := (tag, s) :: !ans
done
| "movi" -> raise Exit (* stop parsing there *)
| _ -> R.drop f (size - 4))
in
try
while true do
chunk ()
done;
assert false
with _ -> List.rev !ans

let parse_file ?format ?custom_parser file = R.with_file ?custom_parser (parse ?format) file
3 changes: 3 additions & 0 deletions src/metadataRIFF.mli
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
val parse : ?format:string -> MetadataBase.Reader.t -> MetadataBase.metadata

val parse_file : ?format:string -> ?custom_parser:MetadataBase.custom_parser -> string -> MetadataBase.metadata
3 changes: 3 additions & 0 deletions src/metadataWAV.ml
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
let parse = MetadataRIFF.parse ~format:"WAVE"

let parse_file = MetadataRIFF.parse_file ~format:"WAVE"

0 comments on commit 296dbbe

Please sign in to comment.