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
|
(*
* Copyright 2003 Savonet team
*
* This file is part of OCaml-Opus.
*
* OCaml-Opus is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* OCaml-Opus is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with OCaml-Opus; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*)
(**
* An opus to wav converter using OCaml-Opus.
*
* @author Samuel Mimram
*)
open Unix
let src = ref ""
let dst = ref ""
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 usage = "usage: opus2wav [options] source destination"
let () =
Arg.parse
[]
(
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 sync, fd = Ogg.Sync.create_from_file !src in
Printf.printf "Checking file.\n%!";
let os, p1 =
let page = Ogg.Sync.read sync in
assert (Ogg.Page.bos page);
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.get_packet os in
assert (Opus.Decoder.check_packet packet);
Printf.printf "Found an opus stream!\n%!";
os, packet
in
let page = Ogg.Sync.read sync in
Ogg.Stream.put_page os page;
let p2 = Ogg.Stream.get_packet os in
let samplerate = 48000 in
Printf.printf "Creating decoder...\n%!";
let dec = Opus.Decoder.create ~samplerate p1 p2 in
let chans = Opus.Decoder.channels dec in
Printf.printf "Channels: %d\n%!" chans;
let vendor, comments = Opus.Decoder.comments dec in
Printf.printf "Vendor: %s\nComments:\n%!" vendor;
List.iter (fun (l,v) -> Printf.printf "- %s = %s\n%!" l v) comments;
Printf.printf "done.\n%!";
Printf.printf "Decoding...%!";
let max_frame_size = 960*6 in
let buflen = max_frame_size in
let buf = Array.init chans (fun _ -> Array.create buflen 0.) in
let outbuf = Array.create chans ([||] : float array) in
(
try
while true do
try
let len =
Opus.Decoder.decode_float dec os buf 0 buflen
in
for c = 0 to chans - 1 do
outbuf.(c) <- Array.append outbuf.(c) (Array.sub buf.(c) 0 len)
done
with
| Ogg.Not_enough_data ->
let page = Ogg.Sync.read sync in
if Ogg.Page.serialno page = Ogg.Stream.serialno os then Ogg.Stream.put_page os page
done
with
| Ogg.End_of_stream -> ()
);
Printf.printf "done.\n%!";
Unix.close fd;
let len = Array.length outbuf.(0) in
let datalen = 2 * len in
let oc = open_out_bin !dst 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 2; (* channels *)
output_int oc samplerate; (* freq *)
output_int oc (samplerate * 2 * 2); (* bytes / s *)
output_short oc (2 * 2); (* block alignment *)
output_short oc 16; (* bits per sample *)
output_string oc "data";
output_int oc datalen;
for i = 0 to len - 1 do
for c = 0 to chans - 1 do
let x = outbuf.(c).(i) in
let x = int_of_float (x *. 32767.) in
output_short oc x;
done
done;
close_out oc;
Gc.full_major ()
|