Skip to content

Commit

Permalink
Add back examples.
Browse files Browse the repository at this point in the history
  • Loading branch information
toots committed Dec 29, 2024
1 parent 5b1b10b commit 8be1b49
Show file tree
Hide file tree
Showing 16 changed files with 1,851 additions and 0 deletions.
190 changes: 190 additions & 0 deletions flac/examples/decode.ml
Original file line number Diff line number Diff line change
@@ -0,0 +1,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 ()
38 changes: 38 additions & 0 deletions flac/examples/dune
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
(executable
(name decode)
(modules decode)
(optional)
(libraries flac.ogg))

(executable
(name encode)
(modules encode)
(optional)
(libraries flac.ogg))

(rule
(alias citest)
(target src.wav)
(action
(run
ffmpeg
-hide_banner
-loglevel
error
-f
lavfi
-i
"sine=frequency=220:duration=5"
-ac
2
%{target})))

(rule
(alias citest)
(deps ./src.wav)
(action
(progn
(run ./encode.exe ./src.wav ./src.flac)
(run ./decode.exe -i ./src.flac -o ./dst.wav)
(run ./encode.exe --ogg true ./src.wav ./dst.ogg)
(run ./decode.exe -ogg true -i ./dst.ogg -o ./ogg-dst.wav))))
127 changes: 127 additions & 0 deletions flac/examples/encode.ml
Original file line number Diff line number Diff line change
@@ -0,0 +1,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 ()
9 changes: 9 additions & 0 deletions opus/examples/dune
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
(executable
(name opus2wav)
(modules opus2wav)
(libraries opus))

(executable
(name wav2opus)
(modules wav2opus)
(libraries opus))
Loading

0 comments on commit 8be1b49

Please sign in to comment.