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
|
let src = ref ""
let dst = ref ""
let buflen = ref 1024
let input_string chan len =
let ans = Buffer.create len in
let buf = Bytes.create len in
let rec f rem =
if 0 < rem then (
let ret = input chan buf 0 rem in
Buffer.add_subbytes ans buf 0 ret;
f (rem - ret))
in
f len;
Buffer.contents 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 bitrate = ref 128
let usage = "usage: encode [options] source destination"
let _ =
Arg.parse
[("--bitrate", Arg.Int (fun b -> bitrate := b), "Encoding bitrate.")]
(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 oc = open_out !dst in
let params = { Shine.channels; samplerate = infreq; bitrate = !bitrate } in
let enc = Shine.create params 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: MP3 %d channels, %d Hz, bitrate: %d\nPlease wait...\n%!"
channels infreq !bitrate;
let rec f () =
let tag = input_string ic 4 in
let len = input_int ic in
if tag <> "data" then (
ignore (input_string ic len);
f ())
in
f ();
(* This ensures the actual audio data will start on a new page, as per
* spec. *)
let buflen = 2 * channels * Shine.samples_per_pass enc in
let buf = Bytes.create buflen in
begin
try
while true do
really_input ic buf 0 (Bytes.length buf);
output_string oc (Shine.encode_s16le enc (Bytes.to_string buf) channels)
done
with End_of_file -> ()
end;
output_string oc (Shine.flush enc);
close_in ic;
Printf.printf "Finished in %.0f seconds.\n" (Unix.time () -. start);
Gc.full_major ()
|