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 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190
|
let () = Printexc.record_backtrace true
let output_int chan n =
output_char chan (char_of_int ((n lsr 0) land 0xff));
output_char chan (char_of_int ((n lsr 8) land 0xff));
output_char chan (char_of_int ((n lsr 16) land 0xff));
output_char chan (char_of_int ((n lsr 24) land 0xff))
let output_short chan n =
output_char chan (char_of_int ((n lsr 0) land 0xff));
output_char chan (char_of_int ((n lsr 8) land 0xff))
let progress_bar =
let spin = ref 0 in
fun title pos tot ->
let nbeq = 40 in
let n = min (100. *. float_of_int pos /. float_of_int tot) 100. in
Printf.printf "\r%s " title;
if tot > 0 then begin
Printf.printf "%6.2f%% [" n;
let e = int_of_float (n /. 100. *. float_of_int nbeq) in
for _ = 1 to e do
Printf.printf "="
done;
if e != nbeq then Printf.printf ">";
for _ = e + 2 to nbeq do
Printf.printf " "
done;
Printf.printf "] "
end;
incr spin;
if !spin > 4 then spin := 1;
Printf.printf "%c%!"
(if tot > 0 && n = 100. then ' '
else (
match !spin with
| 1 -> '|'
| 2 -> '/'
| 3 -> '-'
| 4 -> '\\'
| _ -> failwith "this did not happen"))
let infile = ref "input.flac"
let outfile = ref "output.raw"
let ogg = ref false
let () =
Arg.parse
[
("-o", Arg.Set_string outfile, "Output file");
("-i", Arg.Set_string infile, "Input file");
("-ogg", Arg.Bool (fun x -> ogg := x), "Ogg/flac file");
]
ignore "decode [options]"
let process () =
let fd =
Printf.printf "Opening input file %S\n%!" !infile;
Unix.openfile !infile [Unix.O_RDONLY] 0o640
in
let oc =
Printf.printf "Opening output file %S\n%!" !outfile;
open_out !outfile
in
let ret = Buffer.create 1024 in
let write x = Buffer.add_string ret (Flac.Decoder.to_s16le x) in
let get () =
let ans = Buffer.contents ret in
Buffer.reset ret;
ans
in
let process, info, comments =
if not !ogg then (
let h = Flac.Decoder.File.create_from_fd ~write fd in
let process () =
Flac.Decoder.process h.Flac.Decoder.File.dec;
Flac.Decoder.state h.Flac.Decoder.File.dec
in
(process, h.Flac.Decoder.File.info, h.Flac.Decoder.File.comments))
else (
let sync = Ogg.Sync.create (Unix.read fd) in
let test_flac () =
(* Get First page *)
let page = Ogg.Sync.read sync in
(* Check wether this is a b_o_s *)
if not (Ogg.Page.bos page) then raise Flac.Decoder.Not_flac;
(* Create a stream with this ID *)
let serial = Ogg.Page.serialno page in
Printf.printf "Testing stream %nx\n" serial;
let os = Ogg.Stream.create ~serial () in
Ogg.Stream.put_page os page;
let packet = Ogg.Stream.peek_packet os in
(* Test header. Do not catch anything, first page should be sufficient *)
if not (Flac_ogg.Decoder.check_packet packet) then raise Not_found;
Printf.printf "Got a flac stream !\n";
let fill () =
let page = Ogg.Sync.read sync in
if Ogg.Page.serialno page = serial then Ogg.Stream.put_page os page
in
let dec, info, meta = Flac_ogg.Decoder.create ~fill ~write os in
let rec process () =
try
Flac.Decoder.process dec;
Flac.Decoder.state dec
with
| Ogg.End_of_stream -> `End_of_stream
| Ogg.Not_enough_data -> (
try
fill ();
process ()
with Ogg.End_of_stream | Ogg.Not_enough_data -> `End_of_stream)
in
(process, info, meta)
in
(* Now find a flac stream *)
let rec init () =
try test_flac () with
| Not_found ->
Printf.printf "This stream was not flac..\n";
init ()
| Flac.Decoder.Not_flac ->
Printf.printf "No flac stream was found..\n%!";
raise Flac.Decoder.Not_flac
in
init ())
in
Printf.printf "Stream info:\n";
Printf.printf "sample rate: %i\n" info.Flac.Decoder.sample_rate;
Printf.printf "bits per sample: %i\n" info.Flac.Decoder.bits_per_sample;
Printf.printf "channels: %i\n" info.Flac.Decoder.channels;
Printf.printf "total samples: %s\n"
(Int64.to_string info.Flac.Decoder.total_samples);
Printf.printf "md5sum: ";
String.iter
(fun c -> Printf.printf "%x" (int_of_char c))
info.Flac.Decoder.md5sum;
Printf.printf "\n";
if info.Flac.Decoder.bits_per_sample <> 16 then
failwith "Unsupported bits per sample.";
let srate = info.Flac.Decoder.sample_rate in
let chans = info.Flac.Decoder.channels in
let datalen = Int64.to_int info.Flac.Decoder.total_samples * chans * 2 in
let () =
match comments with
| None -> Printf.printf "No comment found..\n"
| Some (vendor, comments) ->
Printf.printf "Metadata:\n";
List.iter (fun (x, y) -> Printf.printf "%s: %s\n" x y) comments;
Printf.printf "VENDOR: %s\n" vendor
in
output_string oc "RIFF";
output_int oc (4 + 24 + 8 + datalen);
output_string oc "WAVE";
output_string oc "fmt ";
output_int oc 16;
output_short oc 1;
(* WAVE_FORMAT_PCM *)
output_short oc chans;
(* channels *)
output_int oc srate;
(* freq *)
output_int oc (srate * chans * 2);
(* bytes / s *)
output_short oc (chans * 2);
(* block alignment *)
output_short oc 16;
(* bits per sample *)
output_string oc "data";
output_int oc datalen;
let pos = ref 0 in
let rec decode () =
let state = process () in
let ret = get () in
pos := !pos + String.length ret;
progress_bar "Decoding FLAC file:" !pos datalen;
output_string oc ret;
flush oc;
match state with `End_of_stream -> Printf.printf "\n" | _ -> decode ()
in
decode ();
Printf.printf "\n";
close_out oc;
Unix.close fd
let () =
process ();
(* We have global root values
* so we need to do two full major.. *)
Gc.full_major ();
Gc.full_major ()
|