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 128 129 130 131 132
|
open Unix
let src = ref ""
let dst = ref ""
let buflen = ref 1024
let input_string chan len =
let ans = String.create len in
(* TODO: check length *)
ignore (input chan ans 0 len) ;
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 = 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
enc.Flac.Encoder.File.callbacks
buf
in
let finish () =
Flac.Encoder.finish enc.Flac.Encoder.File.enc
enc.Flac.Encoder.File.callbacks ;
Unix.close enc.Flac.Encoder.File.fd;
in
encode,finish
else
let os = Ogg.Stream.create () in
let oc = open_out !dst in
let enc,p,l = Ogg_flac.Encoder.create ~comments params os in
Ogg.Stream.put_packet os p;
output_string oc (Ogg.Stream.flush os) ;
List.iter (Ogg.Stream.put_packet os) l;
output_string oc (Ogg.Stream.flush os) ;
flush oc ;
let encode buf =
Flac.Encoder.process enc Ogg_flac.Encoder.callbacks
buf;
output_string oc (Ogg.Stream.pagesout os);
in
let finish () =
Flac.Encoder.finish enc Ogg_flac.Encoder.callbacks;
output_string oc (Ogg.Stream.flush os) ;
close_out oc
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\nPlease wait...\n%!"
(if !ogg then "OGG/FLAC" else "FLAC") channels infreq !compression;
if input_string ic 4 <> "data" then invalid_arg "No data tag";
(* This ensures the actual audio data will start on a new page, as per
* spec. *)
let buflen = channels*bits/8*(!buflen) in
let buf = String.create buflen in
begin try while true do
really_input ic buf 0 (String.length buf);
encode (Flac.Encoder.from_s16le 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 ()
|