1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127
|
let src = ref ""
let dst = ref ""
let buflen = ref 1024
let flush_outchan = flush
let input_string chan len =
let ans = Bytes.create len in
really_input chan ans 0 len;
Bytes.to_string ans
let input_int chan =
let buf = input_string chan 4 in
int_of_char buf.[0]
+ (int_of_char buf.[1] lsl 8)
+ (int_of_char buf.[2] lsl 16)
+ (int_of_char buf.[3] lsl 24)
let input_short chan =
let buf = input_string chan 2 in
int_of_char buf.[0] + (int_of_char buf.[1] lsl 8)
let compression = ref 5
let ogg = ref false
let usage = "usage: encode [options] source destination"
let _ =
Arg.parse
[
( "--compression",
Arg.Int (fun b -> compression := b),
"Compression level." );
("--ogg", Arg.Bool (fun b -> ogg := b), "Encoder in ogg format.");
]
(let pnum = ref (-1) in
fun s ->
incr pnum;
match !pnum with
| 0 -> src := s
| 1 -> dst := s
| _ ->
Printf.eprintf "Error: too many arguments\n";
exit 1)
usage;
if !src = "" || !dst = "" then (
Printf.printf "%s\n" usage;
exit 1);
let ic = open_in_bin !src in
(* TODO: improve! *)
if input_string ic 4 <> "RIFF" then invalid_arg "No RIFF tag";
ignore (input_string ic 4);
if input_string ic 4 <> "WAVE" then invalid_arg "No WAVE tag";
if input_string ic 4 <> "fmt " then invalid_arg "No fmt tag";
let _ = input_int ic in
let _ = input_short ic in
(* TODO: should be 1 *)
let channels = input_short ic in
let infreq = input_int ic in
let _ = input_int ic in
(* bytes / s *)
let _ = input_short ic in
(* block align *)
let bits = input_short ic in
if bits <> 16 then failwith "only s16le is supported for now..";
let params =
{
Flac.Encoder.channels;
sample_rate = infreq;
bits_per_sample = bits;
compression_level = Some !compression;
total_samples = None;
}
in
let comments = [("TITLE", "Encoding example")] in
let encode, finish =
if not !ogg then (
let enc = Flac.Encoder.File.create ~comments params !dst in
let encode buf = Flac.Encoder.process enc.Flac.Encoder.File.enc buf in
let finish () =
Flac.Encoder.finish enc.Flac.Encoder.File.enc;
Unix.close enc.Flac.Encoder.File.fd
in
(encode, finish))
else (
let oc = open_out !dst in
let write_page (header, body) =
output_string oc header;
output_string oc body
in
let serialno = Random.nativeint Nativeint.max_int in
let { Flac_ogg.Encoder.encoder; first_pages } =
Flac_ogg.Encoder.create ~comments ~serialno ~write:write_page params
in
List.iter write_page first_pages;
let encode = Flac.Encoder.process encoder in
let finish () = Flac.Encoder.finish encoder in
(encode, finish))
in
let start = Unix.time () in
Printf.printf "Input detected: PCM WAVE %d channels, %d Hz, %d bits\n%!"
channels infreq bits;
Printf.printf
"Encoding to: %s %d channels, %d Hz, compression level: %d\n\
Please wait...\n\
%!"
(if !ogg then "OGG/FLAC" else "FLAC")
channels infreq !compression;
while input_string ic 4 <> "data" do
let len = input_int ic in
really_input ic (Bytes.create len) 0 len
done;
(* This ensures the actual audio data will start on a new page, as per
* spec. *)
let buflen = channels * bits / 8 * !buflen in
let buf = Bytes.create buflen in
begin
try
while true do
really_input ic buf 0 (Bytes.length buf);
encode (Flac.Encoder.from_s16le (Bytes.to_string buf) channels)
done
with End_of_file -> ()
end;
finish ();
close_in ic;
Printf.printf "Finished in %.0f seconds.\n" (Unix.time () -. start);
Gc.full_major ();
Gc.full_major ()
|